From: Jinho, Lee Date: Thu, 28 Sep 2017 05:31:39 +0000 (+0900) Subject: Merge branch 'devel/master' into tizen_4.0 X-Git-Tag: accepted/tizen/4.0/unified/20171010.163001~13 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4dd49a6baa87885f9115e303601dab034e793b24;hp=b4cef6c179ee60f0e829bc8a1e6c25a56773637d;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git Merge branch 'devel/master' into tizen_4.0 Change-Id: I057de451aab6a93a76e3b6204b9148f6d1d9feec --- diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp index 2d06a44..24c5c5d 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include #include using namespace Dali::Toolkit::Internal; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualUrl.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualUrl.cpp index 476a023..962ad8e 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualUrl.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualUrl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,22 +26,22 @@ using namespace Dali::Toolkit::Internal; int UtcDaliVisualUrlConstructor(void) { - const char* url="http://bar.org/foobar.gif"; + const char* url="file://bar.org/foobar.gif"; VisualUrl visualUrl(url); DALI_TEST_EQUALS( true, visualUrl.IsValid(), TEST_LOCATION ); DALI_TEST_EQUALS( visualUrl.GetType(), VisualUrl::GIF, TEST_LOCATION ); - DALI_TEST_EQUALS( visualUrl.GetLocation(), VisualUrl::REMOTE, TEST_LOCATION ); + DALI_TEST_EQUALS( visualUrl.GetProtocolType(), VisualUrl::LOCAL, TEST_LOCATION ); VisualUrl visualUrl2("foobar.jpeg"); visualUrl2 = visualUrl; DALI_TEST_EQUALS( true, visualUrl2.IsValid(), TEST_LOCATION ); DALI_TEST_EQUALS( visualUrl2.GetType(), VisualUrl::GIF, TEST_LOCATION ); - DALI_TEST_EQUALS( visualUrl2.GetLocation(), VisualUrl::REMOTE, TEST_LOCATION ); + DALI_TEST_EQUALS( visualUrl2.GetProtocolType(), VisualUrl::LOCAL, TEST_LOCATION ); VisualUrl visualUrl3( visualUrl ); DALI_TEST_EQUALS( true, visualUrl3.IsValid(), TEST_LOCATION ); DALI_TEST_EQUALS( visualUrl3.GetType(), VisualUrl::GIF, TEST_LOCATION ); - DALI_TEST_EQUALS( visualUrl3.GetLocation(), VisualUrl::REMOTE, TEST_LOCATION ); + DALI_TEST_EQUALS( visualUrl3.GetProtocolType(), VisualUrl::LOCAL, TEST_LOCATION ); END_TEST; } @@ -66,6 +66,8 @@ int UtcDaliVisualUrlRegularImage(void) DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl("9").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl("dali://bar.org/foobar.gif").GetType(), TEST_LOCATION ); + END_TEST; } @@ -132,6 +134,7 @@ int UtcDaliVisualUrlGif(void) DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl("gif.png").GetType(), TEST_LOCATION ); DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl("gif.gif1").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl("dali://.gif").GetType(), TEST_LOCATION ); END_TEST; } @@ -141,65 +144,82 @@ int UtcDaliVisualUrlLocationP(void) { tet_infoline( "UtcDaliVisualUrl Location" ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("foobar.gif").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("foobar.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("foobar.svg").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("foobar.GIF").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("foobar.9.png").GetLocation(), TEST_LOCATION ); - - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("file://bar.org/foobar.gif").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("file://bar.org/foobar.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("file://bar.org/foobar.svg").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("file://bar.org/foobar.jpeg").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("file://bar.org/foobar.9.png").GetLocation(), TEST_LOCATION ); - - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ftp://bar.org/foobar.gif").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ftp://bar.org/foobar.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ftp://bar.org/foobar.svg").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ftp://bar.org/foobar.GIF").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ftp://bar.org/foobar.9.png").GetLocation(), TEST_LOCATION ); - - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ssh://bar.org/foobar.gif").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ssh://bar.org/foobar.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ssh://bar.org/foobar.svg").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ssh://bar.org/foobar.GIF").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ssh://bar.org/foobar.9.png").GetLocation(), TEST_LOCATION ); - - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("http://bar.org/foobar.gif").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("http://bar.org/foobar.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("http://bar.org/foobar.svg").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("http://bar.org/foobar.GIF").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("http://bar.org/foobar.9.png").GetLocation(), TEST_LOCATION ); - - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("https://bar.org/foobar.gif").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("https://bar.org/foobar.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("https://bar.org/foobar.svg").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("https://bar.org/foobar.GIF").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("https://bar.org/foobar.9.png").GetLocation(), TEST_LOCATION ); - - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("FTP://bar.org/foobar.gif").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("FTP://bar.org/foobar.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("FTP://bar.org/foobar.svg").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("FTP://bar.org/foobar.GIF").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("FTP://BAR.ORG/foobar.9.png").GetLocation(), TEST_LOCATION ); - - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("SSH://bar.org/foobar.gif").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("SSH://bar.org/foobar.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("SSH://bar.org/foobar.svg").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("SSH://bar.org/foobar.GIF").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("SSH://BAR.ORG/foobar.9.png").GetLocation(), TEST_LOCATION ); - - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTP://bar.org/foobar.gif").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTP://bar.org/foobar.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTP://bar.org/foobar.svg").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTP://bar.org/foobar.GIF").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTP://bar.org/foobar.9.png").GetLocation(), TEST_LOCATION ); - - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTPS://bar.org/foobar.gif").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTPS://bar.org/foobar.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTPS://bar.org/foobar.svg").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTPS://bar.org/foobar.GIF").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTPS://bar.org/foobar.9.png").GetLocation(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("foobar.svg").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("foobar.GIF").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("foobar.9.png").GetProtocolType(), TEST_LOCATION ); + + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("file://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("file://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("file://bar.org/foobar.svg").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("file://bar.org/foobar.jpeg").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("file://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ftp://").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ftp://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ftp://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ftp://bar.org/foobar.svg").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ftp://bar.org/foobar.GIF").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ftp://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ssh://").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ssh://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ssh://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ssh://bar.org/foobar.svg").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ssh://bar.org/foobar.GIF").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("ssh://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("http://").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("http://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("http://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("http://bar.org/foobar.svg").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("http://bar.org/foobar.GIF").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("http://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("https://").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("https://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("https://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("https://bar.org/foobar.svg").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("https://bar.org/foobar.GIF").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("https://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("FTP://").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("FTP://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("FTP://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("FTP://bar.org/foobar.svg").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("FTP://bar.org/foobar.GIF").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("FTP://BAR.ORG/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("SSH://").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("SSH://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("SSH://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("SSH://bar.org/foobar.svg").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("SSH://bar.org/foobar.GIF").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("SSH://BAR.ORG/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTP://").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTP://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTP://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTP://bar.org/foobar.svg").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTP://bar.org/foobar.GIF").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTP://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTPS://").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTPS://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTPS://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTPS://bar.org/foobar.svg").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTPS://bar.org/foobar.GIF").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::REMOTE, VisualUrl("HTTPS://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + + DALI_TEST_EQUALS( VisualUrl::TEXTURE, VisualUrl("dali://").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::TEXTURE, VisualUrl("dali://1234").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::TEXTURE, VisualUrl("DALI://1234").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::TEXTURE, VisualUrl("dali://.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::TEXTURE, VisualUrl("dali://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::TEXTURE, VisualUrl("dali://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::TEXTURE, VisualUrl("dali://bar.org/foobar.svg").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::TEXTURE, VisualUrl("dali://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); END_TEST; } @@ -209,63 +229,48 @@ int UtcDaliVisualUrlLocationN(void) { tet_infoline( "UtcDaliVisualUrl Location negative tests" ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("htp://bar.org/foobar.gif").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("htpp://bar.org/foobar.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("sshttp://bar.org/foobar.svg").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("htth://bar.org/foobar.GIF").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("http:https://bar.org/foobar.9.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("https:http://bar.org/foobar.9.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("HPPT://bar.org/foobar.gif").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("ftp:/bar.org/foobar.9.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("ssh;//bar.org/foobar.9.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("ssh:/bar.org/foobar.9.png").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("http:/bar.org/foobar.gif").GetLocation(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("https:/bar.org/foobar.gif").GetLocation(), TEST_LOCATION ); - - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("file://bar.org/foobar.png").GetLocation(), TEST_LOCATION ); - - END_TEST; -} - - -int UtcDaliVisualUrlIsLocal(void) -{ - tet_infoline( "UtcDaliVisualUrl IsLocal" ); - - DALI_TEST_EQUALS( true, VisualUrl("foobar.gif").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("foobar.png").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("foobar.svg").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("foobar.GIF").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("foobar.9.png").IsLocal(), TEST_LOCATION ); - - DALI_TEST_EQUALS( false, VisualUrl("http://bar.org/foobar.gif").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("http://bar.org/foobar.png").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("http://bar.org/foobar.svg").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("http://bar.org/foobar.GIF").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("http://bar.org/foobar.9.png").IsLocal(), TEST_LOCATION ); - - DALI_TEST_EQUALS( false, VisualUrl("https://bar.org/foobar.gif").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("https://bar.org/foobar.png").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("https://bar.org/foobar.svg").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("https://bar.org/foobar.GIF").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("https://bar.org/foobar.9.png").IsLocal(), TEST_LOCATION ); - - DALI_TEST_EQUALS( false, VisualUrl("HTTP://bar.org/foobar.gif").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("HTTP://bar.org/foobar.png").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("HTTP://bar.org/foobar.svg").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("HTTP://bar.org/foobar.GIF").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("HTTP://bar.org/foobar.9.png").IsLocal(), TEST_LOCATION ); - - DALI_TEST_EQUALS( false, VisualUrl("HTTPS://bar.org/foobar.gif").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("HTTPS://bar.org/foobar.png").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("HTTPS://bar.org/foobar.svg").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("HTTPS://bar.org/foobar.GIF").IsLocal(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("HTTPS://bar.org/foobar.9.png").IsLocal(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("h://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("ht://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("htp://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("htpp://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("httt://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("http;//bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("http:x/bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("http:/xbar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("sshttp://bar.org/foobar.svg").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("http:https://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("https:http://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("HPPT://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("ftp:/bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("ftp:a/bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("fpp://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("ftt://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("ssh;//bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("ssh:/bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("ssh:a/bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("shh://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("sss://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("http:/bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("h1tps://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("ht2ps://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("htt3s://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("http4://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("https5/bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("https:6/bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("https:/7bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); + + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("file://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("dal://1").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("d1li://1").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("da2i://1").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("dal3://1").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("dali4//1").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("dali:5/1").GetProtocolType(), TEST_LOCATION ); + DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("dali:/61").GetProtocolType(), TEST_LOCATION ); END_TEST; } - int UtcDaliVisualUrlIsValid(void) { tet_infoline( "UtcDaliVisualUrl IsValid" ); @@ -305,3 +310,77 @@ int UtcDaliVisualUrlIsValid(void) END_TEST; } + + +int UtcDaliVisualUrlIsLocalResource(void) +{ + tet_infoline( "UtcDaliVisualUrl IsLocalResource" ); + + DALI_TEST_EQUALS( true, VisualUrl("foobar.gif").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, VisualUrl("foobar.png").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, VisualUrl("foobar.svg").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, VisualUrl("foobar.GIF").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, VisualUrl("foobar.9.png").IsLocalResource(), TEST_LOCATION ); + + DALI_TEST_EQUALS( false, VisualUrl("http://bar.org/foobar.gif").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("http://bar.org/foobar.png").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("http://bar.org/foobar.svg").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("http://bar.org/foobar.GIF").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("http://bar.org/foobar.9.png").IsLocalResource(), TEST_LOCATION ); + + DALI_TEST_EQUALS( false, VisualUrl("https://bar.org/foobar.gif").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("https://bar.org/foobar.png").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("https://bar.org/foobar.svg").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("https://bar.org/foobar.GIF").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("https://bar.org/foobar.9.png").IsLocalResource(), TEST_LOCATION ); + + DALI_TEST_EQUALS( false, VisualUrl("HTTP://bar.org/foobar.gif").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("HTTP://bar.org/foobar.png").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("HTTP://bar.org/foobar.svg").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("HTTP://bar.org/foobar.GIF").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("HTTP://bar.org/foobar.9.png").IsLocalResource(), TEST_LOCATION ); + + DALI_TEST_EQUALS( false, VisualUrl("HTTPS://bar.org/foobar.gif").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("HTTPS://bar.org/foobar.png").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("HTTPS://bar.org/foobar.svg").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("HTTPS://bar.org/foobar.GIF").IsLocalResource(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, VisualUrl("HTTPS://bar.org/foobar.9.png").IsLocalResource(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliVisualUrlGetLocationP(void) +{ + tet_infoline( "UtcDaliVisualUrl GetLocation Positive" ); + + DALI_TEST_EQUAL( "a", VisualUrl("http://a").GetLocation() ); + DALI_TEST_EQUAL( "1", VisualUrl("dali://1").GetLocation() ); + DALI_TEST_EQUAL( "", VisualUrl("ftp://").GetLocation() ); + DALI_TEST_EQUAL( "http://", VisualUrl("http://http://").GetLocation() ); + + END_TEST; +} + +int UtcDaliVisualUrlGetLocationN(void) +{ + tet_infoline( "UtcDaliVisualUrl GetLocation Negative" ); + + DALI_TEST_EQUAL( "", VisualUrl("").GetLocation() ); + DALI_TEST_EQUAL( "a", VisualUrl("a").GetLocation() ); + DALI_TEST_EQUAL( "dali:/1", VisualUrl("dali:/1").GetLocation() ); + DALI_TEST_EQUAL( "dali//1", VisualUrl("dali//1").GetLocation() ); + DALI_TEST_EQUAL( "", VisualUrl("http:/http://").GetLocation() ); + + END_TEST; +} + +int UtcDaliVisualUrlCreateTextureUrl(void) +{ + tet_infoline( "UtcDaliVisualUrl CreateTextureUrl" ); + + DALI_TEST_EQUAL( "dali://a", VisualUrl::CreateTextureUrl( "a" ) ); + DALI_TEST_EQUAL( "dali://1234", VisualUrl::CreateTextureUrl( "1234" ) ); + DALI_TEST_EQUAL( "dali://", VisualUrl::CreateTextureUrl( "" ) ); + + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit/CMakeLists.txt b/automated-tests/src/dali-toolkit/CMakeLists.txt index d3b5bba..4def66d 100755 --- a/automated-tests/src/dali-toolkit/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit/CMakeLists.txt @@ -36,6 +36,7 @@ SET(TC_SOURCES utc-Dali-TextSelectionPopup.cpp utc-Dali-TextSelectionPopupMirroringLTR.cpp utc-Dali-TextSelectionPopupMirroringRTL.cpp + utc-Dali-TextureManager.cpp utc-Dali-ToolBar.cpp utc-Dali-Tooltip.cpp utc-Dali-TransitionData.cpp diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.cpp index 8877a50..b38428b 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.cpp @@ -117,6 +117,7 @@ void DALI_TEST_EQUALS( const Matrix3& matrix1, const Matrix3& matrix2, const cha m1[6], m1[7], m1[8], m2[6], m2[7], m2[8]); tet_result(TET_FAIL); + throw("TET_FAIL"); } else { @@ -147,6 +148,7 @@ void DALI_TEST_EQUALS( const Matrix3& matrix1, const Matrix3& matrix2, float eps m1[6], m1[7], m1[8], m2[6], m2[7], m2[8]); tet_result(TET_FAIL); + throw("TET_FAIL"); } else { @@ -183,6 +185,7 @@ void DALI_TEST_EQUALS( const Matrix& matrix1, const Matrix& matrix2, const char* m1[12], m1[13], m1[14], m1[15], m2[12], m2[13], m2[14], m2[15]); tet_result(TET_FAIL); + throw("TET_FAIL"); } else { @@ -214,6 +217,7 @@ void DALI_TEST_EQUALS( const Matrix& matrix1, const Matrix& matrix2, float epsil m1[12], m1[13], m1[14], m1[15], m2[12], m2[13], m2[14], m2[15]); tet_result(TET_FAIL); + throw("TET_FAIL"); } else { @@ -251,6 +255,7 @@ void DALI_TEST_EQUALS( Property::Value& str1, const char* str2, const char* loca else { tet_result(TET_FAIL); + throw("TET_FAIL"); } } @@ -265,6 +270,7 @@ void DALI_TEST_ASSERT( DaliException& e, std::string conditionSubString, const c { fprintf(stderr, "Expected substring '%s' : actual exception string '%s' : location %s\n", conditionSubString.c_str(), e.condition, location ); tet_result(TET_FAIL); + throw("TET_FAIL"); } else { @@ -294,6 +300,7 @@ void ConstraintAppliedCheck::CheckSignalReceived() { fprintf(stderr, "Expected Applied signal was not received\n" ); tet_result( TET_FAIL ); + throw("TET_FAIL"); } else { @@ -307,6 +314,7 @@ void ConstraintAppliedCheck::CheckSignalNotReceived() { fprintf(stderr, "Unexpected Applied signal was received\n" ); tet_result( TET_FAIL ); + throw("TET_FAIL"); } else { diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.h index 2b84d39..4f71920 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.h @@ -40,11 +40,24 @@ using namespace Dali; #define STRINGIZE_I(text) #text #define STRINGIZE(text) STRINGIZE_I(text) -// the following is the other compilers way of token pasting, gcc seems to just concatenate strings automatically -//#define TOKENPASTE(x,y) x ## y -#define TOKENPASTE(x,y) x y -#define TOKENPASTE2(x,y) TOKENPASTE( x, y ) -#define TEST_LOCATION TOKENPASTE2( "Test failed in ", TOKENPASTE2( __FILE__, TOKENPASTE2( ", line ", STRINGIZE(__LINE__) ) ) ) +/** + * Inspired by https://stackoverflow.com/questions/1706346/file-macro-manipulation-handling-at-compile-time + * answer by Chetan Reddy + */ +constexpr int32_t basenameIndex( const char * const path, const int32_t index = 0, const int32_t slashIndex = -1 ) +{ + return path[ index ] + ? ( path[ index ] == '/' + ? basenameIndex( path, index + 1, index ) + : basenameIndex( path, index + 1, slashIndex ) ) + : ( slashIndex + 1 ); +} + +#define __FILELINE__ ( { static const int32_t basenameIdx = basenameIndex( __FILE__ ); \ + static_assert (basenameIdx >= 0, "compile-time basename" ); \ + __FILE__ ":" STRINGIZE(__LINE__) + basenameIdx ; } ) + +#define TEST_LOCATION __FILELINE__ #define TEST_INNER_LOCATION(x) ( std::string(x) + " (" + STRINGIZE(__LINE__) + ")" ).c_str() #define TET_UNDEF 2 @@ -73,7 +86,7 @@ if ( (condition) ) } \ else \ { \ - fprintf(stderr, "%s Failed in %s at line %d\n", __PRETTY_FUNCTION__, __FILE__, __LINE__); \ + fprintf(stderr, "Test failed in %s, condition: %s\n", __FILELINE__, #condition ); \ tet_result(TET_FAIL); \ throw("TET_FAIL"); \ } @@ -97,8 +110,9 @@ inline void DALI_TEST_EQUALS(Type value1, Type value2, const char* location) { std::ostringstream o; o << value1 << " == " << value2 << std::endl; - fprintf(stderr, "%s, checking %s", location, o.str().c_str()); + fprintf(stderr, "Test failed in %s, checking %s", location, o.str().c_str()); tet_result(TET_FAIL); + throw("TET_FAIL"); \ } else { @@ -106,6 +120,13 @@ inline void DALI_TEST_EQUALS(Type value1, Type value2, const char* location) } } +/** + * Test whether two values are equal. + * @param[in] value1 The first value + * @param[in] value2 The second value + */ +#define DALI_TEST_EQUAL( v1, v2 ) DALI_TEST_EQUALS( v1, v2, __FILELINE__ ) + template inline void DALI_TEST_EQUALS(Type value1, Type value2, float epsilon, const char* location) { @@ -113,8 +134,9 @@ inline void DALI_TEST_EQUALS(Type value1, Type value2, float epsilon, const char { std::ostringstream o; o << value1 << " == " << value2 << std::endl; - fprintf(stderr, "%s, checking %s", location, o.str().c_str()); + fprintf(stderr, "Test failed in %s, checking %s", location, o.str().c_str()); tet_result(TET_FAIL); + throw("TET_FAIL"); \ } else { @@ -129,8 +151,9 @@ inline void DALI_TEST_NOT_EQUALS(Type value1, Type value2, float epsilon, const { std::ostringstream o; o << value1 << " != " << value2 << std::endl; - fprintf(stderr, "%s, checking %s", location, o.str().c_str()); + fprintf(stderr, "Test failed in %s, checking %s", location, o.str().c_str()); tet_result(TET_FAIL); + throw("TET_FAIL"); \ } else { @@ -151,13 +174,15 @@ inline void DALI_TEST_EQUALS( TimePeriod value1, TimePeriod value2, { if ((fabs(value1.durationSeconds - value2.durationSeconds) > epsilon)) { - fprintf(stderr, "%s, checking durations %f == %f, epsilon %f\n", location, value1.durationSeconds, value2.durationSeconds, epsilon); + fprintf(stderr, "Test failed in %s, checking durations %f == %f, epsilon %f\n", location, value1.durationSeconds, value2.durationSeconds, epsilon); tet_result(TET_FAIL); + throw("TET_FAIL"); \ } else if ((fabs(value1.delaySeconds - value2.delaySeconds) > epsilon)) { - fprintf(stderr, "%s, checking delays %f == %f, epsilon %f\n", location, value1.delaySeconds, value2.delaySeconds, epsilon); + fprintf(stderr, "Test failed in %s, checking delays %f == %f, epsilon %f\n", location, value1.delaySeconds, value2.delaySeconds, epsilon); tet_result(TET_FAIL); + throw("TET_FAIL"); \ } else { @@ -232,8 +257,9 @@ inline void DALI_TEST_EQUALS( const char* str1, const char* str2, c { if (strcmp(str1, str2)) { - fprintf(stderr, "%s, checking '%s' == '%s'\n", location, str1, str2); + fprintf(stderr, "Test failed in %s, checking '%s' == '%s'\n", location, str1, str2); tet_result(TET_FAIL); + throw("TET_FAIL"); \ } else { @@ -289,8 +315,9 @@ void DALI_TEST_GREATER( T value1, T value2, const char* location) { if (!(value1 > value2)) { - std::cerr << location << ", checking " << value1 <<" > " << value2 << "\n"; + std::cerr << "Test failed in " << location << ", checking " << value1 <<" > " << value2 << "\n"; tet_result(TET_FAIL); + throw("TET_FAIL"); \ } else { diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-harness.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-harness.cpp index 840ef0d..645d74b 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-harness.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-harness.cpp @@ -52,7 +52,14 @@ int RunTestCase( struct ::testcase_s& testCase ) { testCase.startup(); } - result = testCase.function(); + try + { + result = testCase.function(); + } + catch( const char* ) + { + // just catch test fail exception, return is already set to EXIT_STATUS_TESTCASE_FAILED + } if( testCase.cleanup ) { testCase.cleanup(); diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-abstraction.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-abstraction.cpp old mode 100644 new mode 100755 index df25aaa..5cc9401 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-abstraction.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-abstraction.cpp @@ -152,8 +152,8 @@ public: void GetFontMetrics( FontId fontId, FontMetrics& metrics ){} GlyphIndex GetGlyphIndex( FontId fontId, Character charcode ){return 0;} bool GetGlyphMetrics( GlyphInfo* array, uint32_t size, bool horizontal ){return true;} - void CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data ){} - PixelData CreateBitmap( FontId fontId, GlyphIndex glyphIndex ){return PixelData();} + void CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth ){} + PixelData CreateBitmap( FontId fontId, GlyphIndex glyphIndex, int outlineWidth ){return PixelData();} void CreateVectorBlob( FontId fontId, GlyphIndex glyphIndex, VectorBlob*& blob, unsigned int& blobLength, unsigned int& nominalWidth, unsigned int& nominalHeight ) { @@ -472,14 +472,14 @@ bool FontClient::GetGlyphMetrics( GlyphInfo* array, uint32_t size, GlyphType typ return GetImplementation(*this).GetGlyphMetrics( array, size, horizontal ); } -void FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data ) +void FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth ) { - GetImplementation(*this).CreateBitmap( fontId, glyphIndex, data ); + GetImplementation(*this).CreateBitmap( fontId, glyphIndex, data, outlineWidth ); } -PixelData FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex ) +PixelData FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, int outlineWidth ) { - return GetImplementation(*this).CreateBitmap( fontId, glyphIndex ); + return GetImplementation(*this).CreateBitmap( fontId, glyphIndex, outlineWidth ); } void FontClient::CreateVectorBlob( FontId fontId, diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp index 3fd4bd6..59925df 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp @@ -732,8 +732,19 @@ int UtcDaliTextEditorSetPropertyP(void) DALI_TEST_EQUALS( editor.GetProperty( TextEditor::Property::INPUT_EMBOSS ), std::string("Emboss input properties"), TEST_LOCATION ); // Check the outline property - editor.SetProperty( TextEditor::Property::OUTLINE, "Outline properties" ); - DALI_TEST_EQUALS( editor.GetProperty( TextEditor::Property::OUTLINE ), std::string("Outline properties"), TEST_LOCATION ); + Property::Map outlineMapSet; + Property::Map outlineMapGet; + + outlineMapSet["color"] = Color::RED; + outlineMapSet["width"] = 2.0f; + + editor.SetProperty( TextEditor::Property::OUTLINE, outlineMapSet ); + + outlineMapSet["color"] = "red"; + outlineMapSet["width"] = "2"; + outlineMapGet = editor.GetProperty( TextEditor::Property::OUTLINE ); + DALI_TEST_EQUALS( outlineMapGet.Count(), outlineMapSet.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( DaliTestCheckMaps( outlineMapGet, outlineMapSet ), true, TEST_LOCATION ); // Check the input outline property editor.SetProperty( TextEditor::Property::INPUT_OUTLINE, "Outline input properties" ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp index 08b194f..df0a150 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp @@ -100,6 +100,7 @@ const char* const PROPERTY_NAME_HIDDEN_INPUT_SETTINGS = "hiddenIn const char* const PROPERTY_NAME_PIXEL_SIZE = "pixelSize"; const char* const PROPERTY_NAME_ENABLE_SELECTION = "enableSelection"; const char* const PROPERTY_NAME_PLACEHOLDER = "placeholder"; +const char* const PROPERTY_NAME_ELLIPSIS = "ellipsis"; const int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND; @@ -513,6 +514,7 @@ int UtcDaliTextFieldGetPropertyP(void) DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_PIXEL_SIZE ) == DevelTextField::Property::PIXEL_SIZE ); DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_ENABLE_SELECTION ) == DevelTextField::Property::ENABLE_SELECTION ); DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_PLACEHOLDER ) == DevelTextField::Property::PLACEHOLDER ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_ELLIPSIS ) == DevelTextField::Property::ELLIPSIS ); END_TEST; } @@ -827,8 +829,19 @@ int UtcDaliTextFieldSetPropertyP(void) DALI_TEST_EQUALS( field.GetProperty( TextField::Property::INPUT_EMBOSS ), std::string("Emboss input properties"), TEST_LOCATION ); // Check the outline property - field.SetProperty( TextField::Property::OUTLINE, "Outline properties" ); - DALI_TEST_EQUALS( field.GetProperty( TextField::Property::OUTLINE ), std::string("Outline properties"), TEST_LOCATION ); + Property::Map outlineMapSet; + Property::Map outlineMapGet; + + outlineMapSet["color"] = Color::RED; + outlineMapSet["width"] = 2.0f; + + field.SetProperty( TextField::Property::OUTLINE, outlineMapSet ); + + outlineMapSet["color"] = "red"; + outlineMapSet["width"] = "2"; + outlineMapGet = field.GetProperty( TextField::Property::OUTLINE ); + DALI_TEST_EQUALS( outlineMapGet.Count(), outlineMapSet.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( DaliTestCheckMaps( outlineMapGet, outlineMapSet ), true, TEST_LOCATION ); // Check the input outline property field.SetProperty( TextField::Property::INPUT_OUTLINE, "Outline input properties" ); @@ -864,6 +877,7 @@ int UtcDaliTextFieldSetPropertyP(void) placeholderPixelSizeMapSet["placeholderColor"] = Color::BLUE; placeholderPixelSizeMapSet["placeholderFontFamily"] = "Arial"; placeholderPixelSizeMapSet["placeholderPixelSize"] = 15.0f; + placeholderPixelSizeMapSet["placeholderEllipsis"] = true; placeholderFontstyleMap.Insert( "weight", "bold" ); placeholderPixelSizeMapSet["placeholderFontStyle"] = placeholderFontstyleMap; @@ -881,6 +895,7 @@ int UtcDaliTextFieldSetPropertyP(void) placeholderMapSet["placeholderColor"] = Color::RED; placeholderMapSet["placeholderFontFamily"] = "Arial"; placeholderMapSet["placeholderPointSize"] = 12.0f; + placeholderMapSet["placeholderEllipsis"] = false; // Check the placeholder font style property placeholderFontstyleMap.Clear(); @@ -921,6 +936,11 @@ int UtcDaliTextFieldSetPropertyP(void) DALI_TEST_EQUALS( placeholderMapGet.Count(), placeholderMapSet.Count(), TEST_LOCATION ); DALI_TEST_EQUALS( DaliTestCheckMaps( placeholderMapGet, placeholderMapSet ), true, TEST_LOCATION ); + // Check the ellipsis property + DALI_TEST_CHECK( !field.GetProperty( DevelTextField::Property::ELLIPSIS ) ); + field.SetProperty( DevelTextField::Property::ELLIPSIS, true ); + DALI_TEST_CHECK( field.GetProperty( DevelTextField::Property::ELLIPSIS ) ); + END_TEST; } diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp index 1a642dd..2f2e692 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -434,8 +434,18 @@ int UtcDaliToolkitTextLabelSetPropertyP(void) DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::EMBOSS ), std::string("Emboss properties"), TEST_LOCATION ); // Check the outline property - label.SetProperty( TextLabel::Property::OUTLINE, "Outline properties" ); - DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::OUTLINE ), std::string("Outline properties"), TEST_LOCATION ); + Property::Map outlineMapSet; + Property::Map outlineMapGet; + + outlineMapSet["color"] = Color::RED; + outlineMapSet["width"] = 2.0f; + label.SetProperty( TextLabel::Property::OUTLINE, outlineMapSet ); + + outlineMapSet["color"] = "red"; + outlineMapSet["width"] = "2"; + outlineMapGet = label.GetProperty( TextLabel::Property::OUTLINE ); + DALI_TEST_EQUALS( outlineMapGet.Count(), outlineMapSet.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( DaliTestCheckMaps( outlineMapGet, outlineMapSet ), true, TEST_LOCATION ); // Check the pixel size of font label.SetProperty( DevelTextLabel::Property::PIXEL_SIZE, 20.f ); @@ -986,6 +996,75 @@ int UtcDaliToolkitTextLabelColorComponents(void) label.SetProperty( DevelTextLabel::Property::TEXT_COLOR_ALPHA, 0.6f ); DALI_TEST_EQUALS( label.GetProperty< float >( DevelTextLabel::Property::TEXT_COLOR_ALPHA ), 0.6f, TEST_LOCATION ); DALI_TEST_EQUALS( label.GetProperty< Vector4 >( DevelTextLabel::Property::TEXT_COLOR_ANIMATABLE ), Vector4( 0.0f, 0.0f, 1.0f, 0.6f ), TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty< Vector4 >( TextLabel::Property::TEXT_COLOR ), Vector4( 0.0f, 0.0f, 1.0f, 0.6f ), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliToolkitTextlabelTextStyle01(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliToolkitTextlabelTextStyle Setting Outline after Shadow"); + + TextLabel label = TextLabel::New(); + label.SetSize( 300.0f, 300.f ); + label.SetProperty( TextLabel::Property::TEXT, "Hello world Hello world" ); + label.SetProperty( TextLabel::Property::POINT_SIZE, 12 ); + Stage::GetCurrent().Add( label ); + + Property::Map outlineMapSet; + Property::Map outlineMapGet; + + outlineMapSet["color"] = Color::BLUE; + outlineMapSet["width"] = 2.0f; + label.SetProperty( TextLabel::Property::OUTLINE, outlineMapSet ); + + application.SendNotification(); + application.Render(); + + Property::Map shadowMapSet; + shadowMapSet.Insert( "color", "green" ); + shadowMapSet.Insert( "offset", "2 2" ); + label.SetProperty( TextLabel::Property::SHADOW, shadowMapSet ); + + outlineMapSet["color"] = Color::RED; + outlineMapSet["width"] = 0.0f; + label.SetProperty( TextLabel::Property::OUTLINE, outlineMapSet ); + + application.SendNotification(); + application.Render(); + + outlineMapGet = label.GetProperty( TextLabel::Property::OUTLINE ); + + Property::Value* colorValue = outlineMapGet.Find("color"); + + bool colorMatched( false ); + + if ( colorValue ) + { + Property::Type valueType = colorValue->GetType(); + + if ( Property::STRING == valueType ) + { + std::string stringValue; + colorValue->Get( stringValue ); + if ( stringValue == "red" ) + { + colorMatched = true; + } + } + else if ( Property::VECTOR4 == valueType ) + { + Vector4 colorVector4; + colorValue->Get( colorVector4 ); + if ( colorVector4 == Color::RED ) + { + colorMatched = true; + } + } + } + + DALI_TEST_EQUALS( colorMatched, true, TEST_LOCATION ); END_TEST; } diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextureManager.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextureManager.cpp new file mode 100644 index 0000000..89a95ba --- /dev/null +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextureManager.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +using namespace Dali; +using namespace Dali::Toolkit; + +namespace +{ + +} // namespace + + +void dali_texture_manager_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void dali_texture_manager_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliTextureManagerAddRemoveP(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliTextureManager" ); + + std::string url; + std::string url2; + std::string url3; + std::string url4; + // scope to ensure texturesets are kept alive by texture manager + { + auto texture = Texture::New( Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, 88, 99 ); + url = TextureManager::AddTexture( texture ); + DALI_TEST_CHECK( url.size() > 0u ); + + auto textureSet = TextureSet::New(); + textureSet.SetTexture( 0u, texture ); + url2 = TextureManager::AddTexture( textureSet ); + DALI_TEST_CHECK( url2.size() > 0u ); + DALI_TEST_CHECK( url2 != url ); + + // add same texture again, should give new Url + url3 = TextureManager::AddTexture( texture ); + DALI_TEST_CHECK( url3.size() > 0u ); + DALI_TEST_CHECK( url3 != url ); + DALI_TEST_CHECK( url3 != url2 ); + + textureSet = TextureSet::New(); + url4 = TextureManager::AddTexture( textureSet ); + DALI_TEST_CHECK( url4.size() > 0u ); + DALI_TEST_CHECK( url4 != url ); + DALI_TEST_CHECK( url4 != url2 ); + DALI_TEST_CHECK( url4 != url3 ); + } + + auto textureSet = TextureManager::RemoveTexture( url ); + DALI_TEST_CHECK( textureSet && "Texture needs to be non empty handle" ); + auto texture = textureSet.GetTexture( 0u ); + DALI_TEST_EQUAL( texture.GetWidth(), 88u ); + DALI_TEST_EQUAL( texture.GetHeight(), 99u ); + textureSet = TextureManager::RemoveTexture( url ); + DALI_TEST_CHECK( !textureSet && "Texture needs to be removed from texture manager" ); + + textureSet = TextureManager::RemoveTexture( url2 ); + DALI_TEST_CHECK( textureSet && "Texture needs to be non empty handle" ); + texture = textureSet.GetTexture( 0u ); + DALI_TEST_EQUAL( texture.GetWidth(), 88u ); + DALI_TEST_EQUAL( texture.GetHeight(), 99u ); + textureSet = TextureManager::RemoveTexture( url2 ); + DALI_TEST_CHECK( !textureSet && "Texture needs to be removed from texture manager" ); + + textureSet = TextureManager::RemoveTexture( url3 ); + DALI_TEST_CHECK( textureSet && "Texture needs to be non empty handle" ); + texture = textureSet.GetTexture( 0u ); + DALI_TEST_EQUAL( texture.GetWidth(), 88u ); + DALI_TEST_EQUAL( texture.GetHeight(), 99u ); + textureSet = TextureManager::RemoveTexture( url3 ); + DALI_TEST_CHECK( !textureSet && "Texture needs to be removed from texture manager" ); + + textureSet = TextureManager::RemoveTexture( url4 ); + DALI_TEST_CHECK( textureSet && "Texture needs to be non empty handle" ); + textureSet = TextureManager::RemoveTexture( url4 ); + DALI_TEST_CHECK( !textureSet && "Texture needs to be removed from texture manager" ); + + END_TEST; +} + +int UtcDaliTextureManagerAddN(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliTextureManager" ); + + // empty texture is ok, though pointless from app point of view + TextureSet empty; + std::string url = TextureManager::AddTexture( empty ); + DALI_TEST_CHECK( url.size() > 0u ); + + END_TEST; +} + +int UtcDaliTextureManagerRemoveN(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliTextureManager" ); + + // removing empty texture returns empty handle + auto texture = TextureManager::RemoveTexture( "" ); + DALI_TEST_CHECK( !texture && "Texture should not be found" ); + + // removing empty texture returns empty handle + texture = TextureManager::RemoveTexture( "dali://" ); + DALI_TEST_CHECK( !texture && "Texture should not be found" ); + + // empty texture is ok, though pointless from app point of view + TextureSet empty; + std::string url = TextureManager::AddTexture( empty ); + DALI_TEST_CHECK( url.size() > 0u ); + // removing texture with wrong URL returns empty handle + texture = TextureManager::RemoveTexture( "dali://" ); + DALI_TEST_CHECK( !texture && "Texture should not be found" ); + + // removing ftp texture returns empty handle + texture = TextureManager::RemoveTexture( "ftp://foobar" ); + DALI_TEST_CHECK( !texture && "Texture should not be found" ); + + // add a texture + url = TextureManager::AddTexture( texture ); + texture = TextureManager::RemoveTexture( url + "foo" ); + DALI_TEST_CHECK( !texture && "Texture should not be found" ); + + END_TEST; +} + + + diff --git a/build/tizen/Makefile.am b/build/tizen/Makefile.am index 3df2c08..1649112 100755 --- a/build/tizen/Makefile.am +++ b/build/tizen/Makefile.am @@ -58,7 +58,7 @@ rename_cov_data: @rm -f $(COVERAGE_DIR)/* @cp dali-toolkit/.libs/*.gcda dali-toolkit/.libs/*.gcno $(COVERAGE_DIR) @for i in `find $(COVERAGE_DIR) -name "libdali_toolkit*_la-*.gcda" -o -name "libdali_toolkit*_la-*.gcno"` ;\ - do mv $$i `echo $$i | sed s/libdali_toolkit*_la-//` ; echo $$i ; done + do dest=`echo $$i | sed s/libdali_.*_la-//` ; mv $$i $$dest ; echo $$i ; done cov_data: rename_cov_data @cd $(COVERAGE_DIR) ; lcov $(LCOV_OPTS) --base-directory . --directory . -c -o dali.info diff --git a/dali-toolkit/devel-api/controls/text-controls/text-field-devel.h b/dali-toolkit/devel-api/controls/text-controls/text-field-devel.h index bc199ad..4369126 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-field-devel.h +++ b/dali-toolkit/devel-api/controls/text-controls/text-field-devel.h @@ -116,6 +116,7 @@ namespace Property * propertyMap["placeholderColor"] = Color::RED; * propertyMap["placeholderFontFamily"] = "Arial"; * propertyMap["placeholderPointSize"] = 12.0f; + * propertyMap["placeholderEllipsis"] = true; * * Property::Map fontStyleMap; * fontStyleMap.Insert( "weight", "bold" ); @@ -128,7 +129,14 @@ namespace Property * * @details name "placeholder", type MAP */ - PLACEHOLDER = INPUT_OUTLINE + 4 + PLACEHOLDER = INPUT_OUTLINE + 4, + + /** + * @brief Enable or disable the ellipsis. + * @details name "ellipsis", type Property::BOOLEAN. + * @note PLACEHOLDER map is used to add ellipsis to placeholder text. + */ + ELLIPSIS = INPUT_OUTLINE + 5 }; } // namespace Property diff --git a/dali-toolkit/devel-api/file.list b/dali-toolkit/devel-api/file.list index 7f4308b..5cf6797 100644 --- a/dali-toolkit/devel-api/file.list +++ b/dali-toolkit/devel-api/file.list @@ -30,6 +30,7 @@ devel_api_src_files = \ $(devel_api_src_dir)/image-loader/async-image-loader-devel.cpp \ $(devel_api_src_dir)/image-loader/atlas-upload-observer.cpp \ $(devel_api_src_dir)/image-loader/image-atlas.cpp \ + $(devel_api_src_dir)/image-loader/texture-manager.cpp \ $(devel_api_src_dir)/scripting/script.cpp \ $(devel_api_src_dir)/styling/style-manager-devel.cpp \ $(devel_api_src_dir)/transition-effects/cube-transition-cross-effect.cpp \ diff --git a/dali-toolkit/devel-api/image-loader/texture-manager.cpp b/dali-toolkit/devel-api/image-loader/texture-manager.cpp new file mode 100644 index 0000000..d46d2b4 --- /dev/null +++ b/dali-toolkit/devel-api/image-loader/texture-manager.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace TextureManager +{ + +std::string AddTexture( Texture& texture ) +{ + TextureSet set = TextureSet::New(); + set.SetTexture( 0u, texture ); + return AddTexture( set ); +} + +std::string AddTexture( TextureSet& textureSet ) +{ + auto visualFactory = Toolkit::VisualFactory::Get(); + auto& textureMgr = GetImplementation( visualFactory ).GetTextureManager(); + return textureMgr.AddExternalTexture( textureSet ); +} + +TextureSet RemoveTexture( const std::string& textureUrl ) +{ + auto visualFactory = Toolkit::VisualFactory::Get(); + auto& textureMgr = GetImplementation( visualFactory ).GetTextureManager(); + return textureMgr.RemoveExternalTexture( textureUrl ); +} + +} // TextureManager + +} // Toolkit + +} // Dali diff --git a/dali-toolkit/devel-api/image-loader/texture-manager.h b/dali-toolkit/devel-api/image-loader/texture-manager.h new file mode 100644 index 0000000..b88eab9 --- /dev/null +++ b/dali-toolkit/devel-api/image-loader/texture-manager.h @@ -0,0 +1,70 @@ +#ifndef DALI_TOOLKIT_DEVEL_API_TEXTURE_MANAGER_H +#define DALI_TOOLKIT_DEVEL_API_TEXTURE_MANAGER_H + +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +/** + * API to interface with the toolkit texture manager + * Allows developers to add Textures through TextureSets to toolkit so that visuals can use them to render + */ +namespace TextureManager +{ + +/** + * @brief Add a Texture to texture manager + * Toolkit keeps the Texture handle until RemoveTexture is called. + * @note this method does not check for duplicates, + * if same Texture is added multiple times, a different URL is returned each time + * @param[in] texture the Texture to add + * @return the Url string representing this texture + */ +DALI_IMPORT_API std::string AddTexture( Texture& texture ); + +/** + * @brief Add a TextureSet to texture manager + * Toolkit keeps the TextureSet handle until RemoveTexture is called. + * @note this method does not check for duplicates, + * if same TextureSet is added multiple times, a different URL is returned each time + * @param[in] textureSet the TextureSet to add + * @return the Url string representing this texture + */ +DALI_IMPORT_API std::string AddTexture( TextureSet& textureSet ); + +/** + * @brief Removes a TextureSet from toolkit + * @note TextureSet may still be used by visuals and kept alive by them + * @param[in] textureUrl to remove + * @return the handle to the TextureSet or empty handle in case TextureSet is not found + */ +DALI_IMPORT_API TextureSet RemoveTexture( const std::string& textureUrl ); + +} + +} // Toolkit + +} // Dali + +#endif // DALI_TOOLKIT_DEVEL_API_TEXTURE_MANAGER_H diff --git a/dali-toolkit/devel-api/visuals/text-visual-properties.h b/dali-toolkit/devel-api/visuals/text-visual-properties.h index 10adcbc..4286c38 100644 --- a/dali-toolkit/devel-api/visuals/text-visual-properties.h +++ b/dali-toolkit/devel-api/visuals/text-visual-properties.h @@ -88,6 +88,18 @@ enum * @details name "enableMarkup", type BOOLEAN */ ENABLE_MARKUP, + + /** + * @brief The shadow parameters. + * @details name "shadow", type MAP. + */ + SHADOW, + + /** + * @brief The default underline parameters. + * @details name "underline", type MAP. + */ + UNDERLINE, }; } // namespace Property diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp index d5ea993..25273f1 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -142,6 +142,7 @@ DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "hiddenInputSettings", DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "pixelSize", FLOAT, PIXEL_SIZE ) DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "enableSelection", BOOLEAN, ENABLE_SELECTION ) DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "placeholder", MAP, PLACEHOLDER ) +DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "ellipsis", BOOLEAN, ELLIPSIS ) DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "textChanged", SIGNAL_TEXT_CHANGED ) DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "maxLengthReached", SIGNAL_MAX_LENGTH_REACHED ) @@ -772,6 +773,17 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr } break; } + case Toolkit::DevelTextField::Property::ELLIPSIS: + { + if( impl.mController ) + { + const bool ellipsis = value.Get(); + DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p ELLIPSIS %d\n", impl.mController.Get(), ellipsis ); + + impl.mController->SetTextElideEnabled( ellipsis ); + } + break; + } } // switch } // textfield } @@ -1165,6 +1177,14 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde value = map; break; } + case Toolkit::DevelTextField::Property::ELLIPSIS: + { + if( impl.mController ) + { + value = impl.mController->IsTextElideEnabled(); + } + break; + } } //switch } diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp index db99cc4..e871db3 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -35,6 +35,13 @@ #include #include +#include +#include +#include +#include +#include +#include + using namespace Dali::Toolkit::Text; namespace Dali @@ -97,7 +104,7 @@ BaseHandle Create() // Setup properties, signals and actions using the type-registry. DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextLabel, Toolkit::Control, Create ); -DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "renderingBackend", INTEGER, RENDERING_BACKEND ) +DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "renderingBackend", INTEGER, RENDERING_BACKEND ) // Deprecated property DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "text", STRING, TEXT ) DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "fontFamily", STRING, FONT_FAMILY ) DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "fontStyle", MAP, FONT_STYLE ) @@ -127,7 +134,7 @@ DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextLabel, "autoScrollLoopDelay", FLO DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextLabel, "autoScrollStopMode", STRING, AUTO_SCROLL_STOP_MODE ) DALI_DEVEL_PROPERTY_REGISTRATION_READ_ONLY( Toolkit, TextLabel, "lineCount", INTEGER, LINE_COUNT ) DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextLabel, "lineWrapMode", STRING, LINE_WRAP_MODE ) -DALI_DEVEL_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT( Toolkit, TextLabel, "textColorAnimatable", Color::WHITE, TEXT_COLOR_ANIMATABLE ) +DALI_DEVEL_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT( Toolkit, TextLabel, "textColorAnimatable", Color::BLACK, TEXT_COLOR_ANIMATABLE ) DALI_DEVEL_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, TextLabel, "textColorRed", TEXT_COLOR_RED, TEXT_COLOR_ANIMATABLE, 0) DALI_DEVEL_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, TextLabel, "textColorGreen", TEXT_COLOR_GREEN, TEXT_COLOR_ANIMATABLE, 1) DALI_DEVEL_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, TextLabel, "textColorBlue", TEXT_COLOR_BLUE, TEXT_COLOR_ANIMATABLE, 2) @@ -162,6 +169,8 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr { case Toolkit::TextLabel::Property::RENDERING_BACKEND: { + DALI_LOG_WARNING("[%s] Using deprecated Property TextLabel::Property::RENDERING_BACKEND which is no longer supported and will be ignored\n", __FUNCTION__); + int backend = value.Get< int >(); #ifndef ENABLE_VECTOR_BASED_TEXT_RENDERING @@ -173,7 +182,7 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr if( impl.mRenderingBackend != backend ) { impl.mRenderingBackend = backend; - impl.mRenderer.Reset(); + impl.mTextUpdateNeeded = true; if( impl.mController ) { @@ -262,7 +271,8 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr case Toolkit::TextLabel::Property::TEXT_COLOR: { - SetProperty( object, DevelTextLabel::Property::TEXT_COLOR_ANIMATABLE, value ); + label.SetProperty( DevelTextLabel::Property::TEXT_COLOR_ANIMATABLE, value ); + impl.mTextUpdateNeeded = true; break; } @@ -274,7 +284,7 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr if ( impl.mController->GetShadowOffset() != shadowOffset ) { impl.mController->SetShadowOffset( shadowOffset ); - impl.mRenderer.Reset(); + impl.mTextUpdateNeeded = true; } } break; @@ -287,7 +297,7 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr if ( impl.mController->GetShadowColor() != shadowColor ) { impl.mController->SetShadowColor( shadowColor ); - impl.mRenderer.Reset(); + impl.mTextUpdateNeeded = true; } } break; @@ -300,7 +310,7 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr if ( impl.mController->GetUnderlineColor() != color ) { impl.mController->SetUnderlineColor( color ); - impl.mRenderer.Reset(); + impl.mTextUpdateNeeded = true; } } break; @@ -313,7 +323,7 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr if ( impl.mController->IsUnderlineEnabled() != enabled ) { impl.mController->SetUnderlineEnabled( enabled ); - impl.mRenderer.Reset(); + impl.mTextUpdateNeeded = true; } } break; @@ -327,7 +337,7 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr if( fabsf( impl.mController->GetUnderlineHeight() - height ) > Math::MACHINE_EPSILON_1000 ) { impl.mController->SetUnderlineHeight( height ); - impl.mRenderer.Reset(); + impl.mTextUpdateNeeded = true; } } break; @@ -425,7 +435,7 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr { const float lineSpacing = value.Get(); impl.mController->SetDefaultLineSpacing( lineSpacing ); - impl.mRenderer.Reset(); + impl.mTextUpdateNeeded = true; } break; } @@ -434,7 +444,7 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); if( update ) { - impl.mRenderer.Reset(); + impl.mTextUpdateNeeded = true; } break; } @@ -443,7 +453,7 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); if( update ) { - impl.mRenderer.Reset(); + impl.mTextUpdateNeeded = true; } break; } @@ -452,7 +462,7 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); if( update ) { - impl.mRenderer.Reset(); + impl.mTextUpdateNeeded = true; } break; } @@ -461,7 +471,7 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); if( update ) { - impl.mRenderer.Reset(); + impl.mTextUpdateNeeded = true; } break; } @@ -522,6 +532,8 @@ Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index inde { case Toolkit::TextLabel::Property::RENDERING_BACKEND: { + DALI_LOG_WARNING("[%s] Using deprecated Property TextLabel::Property::RENDERING_BACKEND which is no longer supported and will be ignored\n", __FUNCTION__); + value = impl.mRenderingBackend; break; } @@ -594,10 +606,7 @@ Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index inde } case Toolkit::TextLabel::Property::TEXT_COLOR: { - if( impl.mController ) - { - value = impl.mController->GetDefaultColor(); - } + value = label.GetProperty( Toolkit::DevelTextLabel::Property::TEXT_COLOR_ANIMATABLE ); break; } case Toolkit::TextLabel::Property::SHADOW_OFFSET: @@ -783,11 +792,19 @@ void TextLabel::OnInitialize() { Actor self = Self(); - mController = Text::Controller::New( this ); + Property::Map propertyMap; + propertyMap.Add( Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::TEXT ); - // When using the vector-based rendering, the size of the GLyphs are different - TextAbstraction::GlyphType glyphType = (Text::RENDERING_VECTOR_BASED == mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH; - mController->SetGlyphType( glyphType ); + mVisual = Toolkit::VisualFactory::Get().CreateVisual( propertyMap ); + DevelControl::RegisterVisual( *this, Toolkit::TextLabel::Property::TEXT, mVisual ); + + TextVisual::SetAnimatableTextColorProperty( mVisual, Toolkit::DevelTextLabel::Property::TEXT_COLOR_ANIMATABLE ); + + mController = TextVisual::GetController(mVisual); + if( mController ) + { + mController->SetControlInterface(this); + } // Use height-for-width negotiation by default self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); @@ -798,8 +815,6 @@ void TextLabel::OnInitialize() Layout::Engine& engine = mController->GetLayoutEngine(); engine.SetCursorWidth( 0u ); // Do not layout space for the cursor. - - self.OnStageSignal().Connect( this, &TextLabel::OnStageConnect ); } void TextLabel::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change ) @@ -852,14 +867,13 @@ void TextLabel::OnPropertySet( Property::Index index, Property::Value propertyVa switch ( index ) { - case Toolkit::TextLabel::Property::TEXT_COLOR: case Toolkit::DevelTextLabel::Property::TEXT_COLOR_ANIMATABLE: { const Vector4& textColor = propertyValue.Get< Vector4 >(); if( mController->GetDefaultColor() != textColor ) { mController->SetDefaultColor( textColor ); - mRenderer.Reset(); + mTextUpdateNeeded = true; } break; } @@ -879,76 +893,50 @@ void TextLabel::OnRelayout( const Vector2& size, RelayoutContainer& container ) Self().GetPadding( padding ); Vector2 contentSize( size.x - ( padding.left + padding.right ), size.y - ( padding.top + padding.bottom ) ); - const Text::Controller::UpdateTextType updateTextType = mController->Relayout( contentSize ); - if( ( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType ) ) || - !mRenderer ) + if( ( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType ) ) + || mTextUpdateNeeded ) { - if( !mRenderer ) - { - mRenderer = Text::Backend::Get().NewRenderer( mRenderingBackend ); - } - RenderText(); - } -} - -void TextLabel::RequestTextRelayout() -{ - RelayoutRequest(); -} + DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::OnRelayout IsAutoScrollEnabled[%s] [%p]\n", ( mController->IsAutoScrollEnabled())?"true":"false", this ); -void TextLabel::RenderText() -{ - DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::RenderText IsAutoScrollEnabled[%s] [%p]\n", ( mController->IsAutoScrollEnabled())?"true":"false", this ); + // Update the visual + TextVisual::EnableRendererUpdate( mVisual ); - Actor self = Self(); - Actor renderableActor; + Padding padding; + Self().GetPadding( padding ); - float alignmentOffset = 0.f; - if( mRenderer ) - { - - Dali::Toolkit::TextLabel handle = Dali::Toolkit::TextLabel( GetOwner() ); - - renderableActor = mRenderer->Render( mController->GetView(), - handle, - Toolkit::DevelTextLabel::Property::TEXT_COLOR_ANIMATABLE, - alignmentOffset, - DepthIndex::CONTENT ); - } - - if( renderableActor != mRenderableActor ) - { - UnparentAndReset( mRenderableActor ); - - if( renderableActor ) - { - const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition(); - Padding padding; - self.GetPadding( padding ); - renderableActor.SetPosition( scrollOffset.x + alignmentOffset + padding.left, scrollOffset.y + padding.top ); - - self.Add( renderableActor ); - } - mRenderableActor = renderableActor; + Property::Map visualTransform; + visualTransform.Add( Toolkit::DevelVisual::Transform::Property::SIZE, contentSize ) + .Add( Toolkit::DevelVisual::Transform::Property::SIZE_POLICY, Vector2( DevelVisual::Transform::Policy::ABSOLUTE, DevelVisual::Transform::Policy::ABSOLUTE ) ) + .Add( Toolkit::DevelVisual::Transform::Property::OFFSET, Vector2(padding.left, padding.top) ) + .Add( Toolkit::DevelVisual::Transform::Property::OFFSET_POLICY, Vector2( Toolkit::DevelVisual::Transform::Policy::ABSOLUTE, Toolkit::DevelVisual::Transform::Policy::ABSOLUTE ) ) + .Add( Toolkit::DevelVisual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN ) + .Add( Toolkit::DevelVisual::Transform::Property::ANCHOR_POINT, Toolkit::Align::TOP_BEGIN ); + mVisual.SetTransformAndSize( visualTransform, size ); if ( mController->IsAutoScrollEnabled() ) { SetUpAutoScrolling(); } + + mTextUpdateNeeded = false; } } +void TextLabel::RequestTextRelayout() +{ + RelayoutRequest(); +} + void TextLabel::SetUpAutoScrolling() { const Size& controlSize = mController->GetView().GetControlSize(); - const Size offScreenSize = GetNaturalSize().GetVectorXY(); // As relayout of text may not be done at this point natural size is used to get size. Single line scrolling only. - const float alignmentOffset = mController->GetAutoScrollLineAlignment(); + const Size textNaturalSize = GetNaturalSize().GetVectorXY(); // As relayout of text may not be done at this point natural size is used to get size. Single line scrolling only. const Text::CharacterDirection direction = mController->GetAutoScrollDirection(); - DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetUpAutoScrolling alignmentOffset[%f] offScreenSize[%f,%f] controlSize[%f,%f]\n", - alignmentOffset, offScreenSize.x,offScreenSize.y , controlSize.x,controlSize.y ); + DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetUpAutoScrolling textNaturalSize[%f,%f] controlSize[%f,%f]\n", + textNaturalSize.x,textNaturalSize.y , controlSize.x,controlSize.y ); if ( !mTextScroller ) { @@ -957,23 +945,27 @@ void TextLabel::SetUpAutoScrolling() // If speed, loopCount or gap not set via property system then will need to create a TextScroller with defaults mTextScroller = Text::TextScroller::New( *this ); } - mTextScroller->SetParameters( mRenderableActor, controlSize, offScreenSize, direction, alignmentOffset, mController->GetHorizontalAlignment() ); - - Actor self = Self(); - self.Add( mTextScroller->GetScrollingText() ); - self.Add( mTextScroller->GetSourceCamera() ); -} -void TextLabel::OnStageConnect( Dali::Actor actor ) -{ - if ( mHasBeenStaged ) - { - RenderText(); - } - else - { - mHasBeenStaged = true; - } + // Create a texture of the text for scrolling + Text::TypesetterPtr typesetter = Text::Typesetter::New( mController->GetTextModel() ); + PixelData data = typesetter->Render( textNaturalSize, Text::Typesetter::RENDER_TEXT_AND_STYLES, true, Pixel::RGBA8888 ); // ignore the horizontal alignment + Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, + data.GetPixelFormat(), + data.GetWidth(), + data.GetHeight() ); + texture.Upload( data ); + + TextureSet textureSet = TextureSet::New(); + textureSet.SetTexture( 0u, texture ); + + // Filter mode needs to be set to linear to produce better quality while scaling. + Sampler sampler = Sampler::New(); + sampler.SetFilterMode( FilterMode::LINEAR, FilterMode::LINEAR ); + textureSet.SetSampler( 0u, sampler ); + + // Set parameters for scrolling + Renderer renderer = static_cast( GetImplementation( mVisual ) ).GetRenderer(); + mTextScroller->SetParameters( Self(), renderer, textureSet, controlSize, textNaturalSize, direction, mController->GetHorizontalAlignment(), mController->GetVerticalAlignment() ); } void TextLabel::ScrollingFinished() @@ -988,7 +980,7 @@ void TextLabel::ScrollingFinished() TextLabel::TextLabel() : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ), mRenderingBackend( DEFAULT_RENDERING_BACKEND ), - mHasBeenStaged( false ) + mTextUpdateNeeded( false ) { } diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.h b/dali-toolkit/internal/controls/text-controls/text-label-impl.h index f15acbf..85e94ab 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.h @@ -18,6 +18,9 @@ * */ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include #include @@ -26,6 +29,8 @@ #include #include #include +#include + namespace Dali { @@ -132,14 +137,6 @@ private: TextLabel(const TextLabel&); TextLabel& operator=(const TextLabel& rhs); - // Connection needed to re-render text, when a Text Label returns to the stage - void OnStageConnect( Dali::Actor actor ); - - /** - * @brief Render view, create and attach actor(s) to this Text Label - */ - void RenderText(); - /** * @brief Set up Autoscrolling */ @@ -148,11 +145,12 @@ private: private: // Data Text::ControllerPtr mController; - Text::RendererPtr mRenderer; Text::TextScrollerPtr mTextScroller; - Actor mRenderableActor; + + Toolkit::Visual::Base mVisual; + int mRenderingBackend; - bool mHasBeenStaged:1; + bool mTextUpdateNeeded:1; }; } // namespace Internal diff --git a/dali-toolkit/internal/controls/video-view/video-view-impl.cpp b/dali-toolkit/internal/controls/video-view/video-view-impl.cpp index b09de6b..2fdb70b 100644 --- a/dali-toolkit/internal/controls/video-view/video-view-impl.cpp +++ b/dali-toolkit/internal/controls/video-view/video-view-impl.cpp @@ -620,7 +620,11 @@ void VideoView::SetWindowSurfaceTarget() mVideoPlayer.Play(); mVideoPlayer.Pause(); } - mVideoPlayer.SetPlayPosition( curPos ); + + if( curPos > 0 ) + { + mVideoPlayer.SetPlayPosition( curPos ); + } // For underlay rendering mode, video display area have to be transparent. Geometry geometry = VisualFactoryCache::CreateQuadGeometry(); @@ -660,7 +664,10 @@ void VideoView::SetNativeImageTarget() mVideoPlayer.Play(); mVideoPlayer.Pause(); } - mVideoPlayer.SetPlayPosition( curPos ); + if( curPos > 0 ) + { + mVideoPlayer.SetPlayPosition( curPos ); + } } void VideoView::UpdateDisplayArea() diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 9b6809f..77df72f 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -31,7 +31,7 @@ toolkit_src_files = \ $(toolkit_src_dir)/visuals/svg/svg-visual.cpp \ $(toolkit_src_dir)/visuals/text/text-visual.cpp \ $(toolkit_src_dir)/visuals/transition-data-impl.cpp \ - $(toolkit_src_dir)/visuals/texture-manager.cpp \ + $(toolkit_src_dir)/visuals/texture-manager-impl.cpp \ $(toolkit_src_dir)/visuals/texture-upload-observer.cpp \ $(toolkit_src_dir)/visuals/visual-base-data-impl.cpp \ $(toolkit_src_dir)/visuals/visual-base-impl.cpp \ diff --git a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp index c3ebe62..3f398c5 100644 --- a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp +++ b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp @@ -122,6 +122,7 @@ KeyboardFocusManager::KeyboardFocusManager() mIsFocusIndicatorEnabled( -1 ), mFocusGroupLoopEnabled( false ), mIsWaitingKeyboardFocusChangeCommit( false ), + mClearFocusOnTouch( true ), mFocusHistory(), mSlotDelegate( this ), mCustomAlgorithmInterface(NULL) @@ -142,6 +143,7 @@ void KeyboardFocusManager::GetConfigurationFromStyleManger() { Property::Map config = Toolkit::DevelStyleManager::GetConfigurations( styleManager ); mIsFocusIndicatorEnabled = static_cast(config["alwaysShowFocus"].Get()); + mClearFocusOnTouch = mIsFocusIndicatorEnabled ? false : true; } } @@ -863,9 +865,17 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) void KeyboardFocusManager::OnTouch(const TouchData& touch) { + // if mIsFocusIndicatorEnabled is -1, it means Configuration is not loaded. + // Try to load configuration. + if( mIsFocusIndicatorEnabled == -1 ) + { + GetConfigurationFromStyleManger(); + } + // Clear the focus when user touch the screen. // We only do this on a Down event, otherwise the clear action may override a manually focused actor. - if( ( touch.GetPointCount() < 1 ) || ( touch.GetState( 0 ) == PointState::DOWN ) ) + // If mClearFocusOnTouch is false, do not clear the focus even if user touch the screen. + if( (( touch.GetPointCount() < 1 ) || ( touch.GetState( 0 ) == PointState::DOWN )) && mClearFocusOnTouch ) { ClearFocus(); } diff --git a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h index 049ce1f..32a0390 100644 --- a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h +++ b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h @@ -265,6 +265,8 @@ private: bool mIsWaitingKeyboardFocusChangeCommit:1; /// A flag to indicate PreFocusChangeSignal emitted but the proposed focus actor is not commited by the application yet. + bool mClearFocusOnTouch:1; ///< Whether clear focus on touch. + FocusStack mFocusHistory; ///< Stack to contain pre-focused actor's BaseObject* SlotDelegate< KeyboardFocusManager > mSlotDelegate; diff --git a/dali-toolkit/internal/image-loader/image-load-thread.cpp b/dali-toolkit/internal/image-loader/image-load-thread.cpp index c1b4a91..7e0a181 100644 --- a/dali-toolkit/internal/image-loader/image-load-thread.cpp +++ b/dali-toolkit/internal/image-loader/image-load-thread.cpp @@ -44,7 +44,7 @@ LoadingTask::LoadingTask( uint32_t id, const VisualUrl& url, ImageDimensions dim void LoadingTask::Load() { - if( url.IsLocal() ) + if( url.IsLocalResource() ) { pixelBuffer = Dali::LoadImageFromFile( url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection ); } diff --git a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp index 13eeae6..62865d6 100644 --- a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp @@ -94,6 +94,7 @@ const float HALF( 0.5f ); const float ONE( 1.0f ); const uint32_t DEFAULT_ATLAS_WIDTH = 512u; const uint32_t DEFAULT_ATLAS_HEIGHT = 512u; +const int NO_OUTLINE( 0 ); } struct AtlasRenderer::Impl @@ -354,7 +355,8 @@ struct AtlasRenderer::Impl mFontClient.CreateBitmap( glyph.fontId, glyph.index, - glyphBufferData ); + glyphBufferData, + NO_OUTLINE ); // Create the pixel data. bitmap = PixelData::New( glyphBufferData.buffer, diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.cpp b/dali-toolkit/internal/text/rendering/text-typesetter.cpp old mode 100644 new mode 100755 index 78aba49..b524710 --- a/dali-toolkit/internal/text/rendering/text-typesetter.cpp +++ b/dali-toolkit/internal/text/rendering/text-typesetter.cpp @@ -21,6 +21,7 @@ // EXTERNAL INCLUDES #include #include +#include // INTERNAL INCLUDES #include @@ -42,7 +43,7 @@ namespace */ struct GlyphData { - uint32_t* bitmapBuffer; ///< The buffer of the whole bitmap. The format is RGBA8888. + Devel::PixelBuffer bitmapBuffer; ///< The buffer of the whole bitmap. The format is RGBA8888. Vector2* position; ///< The position of the glyph. TextAbstraction::FontClient::GlyphBufferData glyphBitmap; ///< The glyph's bitmap. unsigned int width; ///< The bitmap's width. @@ -57,10 +58,14 @@ struct GlyphData * @param[in] data Struct which contains the glyph's data and the bitmap's data. * @param[in] position The position of the glyph. * @param[in] color The color of the glyph. + * @param[in] style The style of the text. + * @param[in] pixelFormat The format of the pixel in the image that the text is rendered as (i.e. either Pixel::BGRA8888 or Pixel::L8). */ -void TypesetGlyph( const GlyphData& data, +void TypesetGlyph( GlyphData& data, const Vector2* const position, - const Vector4* const color ) + const Vector4* const color, + Typesetter::Style style, + Pixel::Format pixelFormat ) { if( ( 0u == data.glyphBitmap.width ) || ( 0u == data.glyphBitmap.height ) ) { @@ -71,71 +76,178 @@ void TypesetGlyph( const GlyphData& data, const int widthMinusOne = static_cast( data.width - 1u ); const int heightMinusOne = static_cast( data.height - 1u ); - // Whether the given glyph is a color one. - const bool isColorGlyph = Pixel::BGRA8888 == data.glyphBitmap.format; + if ( Pixel::RGBA8888 == pixelFormat ) + { + // Whether the given glyph is a color one. + const bool isColorGlyph = Pixel::BGRA8888 == data.glyphBitmap.format; - // Pointer to the color glyph if there is one. - const uint32_t* const colorGlyphBuffer = isColorGlyph ? reinterpret_cast( data.glyphBitmap.buffer ) : NULL; + // Pointer to the color glyph if there is one. + const uint32_t* const colorGlyphBuffer = isColorGlyph ? reinterpret_cast( data.glyphBitmap.buffer ) : NULL; - // Pack the given color into a 32bit buffer. The alpha channel will be updated later for each pixel. - // The format is RGBA8888. - uint32_t packedColor = 0u; - uint8_t* packedColorBuffer = reinterpret_cast( &packedColor ); - *( packedColorBuffer + 2 ) = static_cast( color->b * 255.f ); - *( packedColorBuffer + 1 ) = static_cast( color->g * 255.f ); - *packedColorBuffer = static_cast( color->r * 255.f ); + // Pack the given color into a 32bit buffer. The alpha channel will be updated later for each pixel. + // The format is RGBA8888. + uint32_t packedColor = 0u; + uint8_t* packedColorBuffer = reinterpret_cast( &packedColor ); + *( packedColorBuffer + 2 ) = static_cast( color->b * 255.f ); + *( packedColorBuffer + 1 ) = static_cast( color->g * 255.f ); + *packedColorBuffer = static_cast( color->r * 255.f ); - // Initial vertical offset. - const int yOffset = data.verticalOffset + position->y; + // Initial vertical offset. + const int yOffset = data.verticalOffset + position->y; - // Traverse the pixels of the glyph line per line. - for( int lineIndex = 0, glyphHeight = static_cast( data.glyphBitmap.height ); lineIndex < glyphHeight; ++lineIndex ) - { - const int yOffsetIndex = yOffset + lineIndex; - if( ( 0 > yOffsetIndex ) || ( yOffsetIndex > heightMinusOne ) ) + // Traverse the pixels of the glyph line per line. + for( int lineIndex = 0, glyphHeight = static_cast( data.glyphBitmap.height ); lineIndex < glyphHeight; ++lineIndex ) { - // Do not write out of bounds. - break; + const int yOffsetIndex = yOffset + lineIndex; + if( ( 0 > yOffsetIndex ) || ( yOffsetIndex > heightMinusOne ) ) + { + // Do not write out of bounds. + continue; + } + + const int verticalOffset = yOffsetIndex * data.width; + const int xOffset = data.horizontalOffset + position->x; + const int glyphBufferOffset = lineIndex * static_cast( data.glyphBitmap.width ); + for( int index = 0, glyphWidth = static_cast( data.glyphBitmap.width ); index < glyphWidth; ++index ) + { + const int xOffsetIndex = xOffset + index; + if( ( 0 > xOffsetIndex ) || ( xOffsetIndex > widthMinusOne ) ) + { + // Don't write out of bounds. + continue; + } + + uint32_t* bitmapBuffer = reinterpret_cast< uint32_t* >( data.bitmapBuffer.GetBuffer() ); + + if( isColorGlyph ) + { + // Retrieves the color from the color glyph. The format is BGRA8888. + uint32_t packedColorGlyph = *( colorGlyphBuffer + glyphBufferOffset + index ); + uint8_t* packedColorGlyphBuffer = reinterpret_cast( &packedColorGlyph ); + + if( Typesetter::STYLE_SHADOW == style ) + { + // The shadow of color glyph needs to have the shadow color. + *( packedColorGlyphBuffer + 2 ) = static_cast( color->b * 255.f ); + *( packedColorGlyphBuffer + 1 ) = static_cast( color->g * 255.f ); + *packedColorGlyphBuffer = static_cast( color->r * 255.f ); + } + else + { + std::swap( *packedColorGlyphBuffer, *( packedColorGlyphBuffer + 2u ) ); // Swap B and R. + } + + // Update the alpha channel. + if( Typesetter::STYLE_MASK == style || Typesetter::STYLE_OUTLINE == style ) // Outline not shown for color glyph + { + // Create an alpha mask for color glyph. + *( packedColorGlyphBuffer + 3u ) = 0u; + } + else + { + *( packedColorGlyphBuffer + 3u ) = static_cast( color->a * static_cast( *( packedColorGlyphBuffer + 3u ) ) ); + } + + // Set the color into the final pixel buffer. + *( bitmapBuffer + verticalOffset + xOffsetIndex ) = packedColorGlyph; + } + else + { + // Update the alpha channel. + const uint8_t alpha = *( data.glyphBitmap.buffer + glyphBufferOffset + index ); + + // Copy non-transparent pixels only + if ( alpha > 0u ) + { + // Check alpha of overlapped pixels + uint32_t& currentColor = *( bitmapBuffer + verticalOffset + xOffsetIndex ); + uint8_t* packedCurrentColorBuffer = reinterpret_cast( ¤tColor ); + + uint8_t currentAlpha = *( packedCurrentColorBuffer + 3u ); + uint8_t newAlpha = static_cast( color->a * static_cast( alpha ) ); + + // For any pixel overlapped with the pixel in previous glyphs, make sure we don't + // overwrite a previous bigger alpha with a smaller alpha (in order to avoid + // semi-transparent gaps between joint glyphs with overlapped pixels, which could + // happen, for example, in the RTL text when we copy glyphs from right to left). + *( packedColorBuffer + 3u ) = std::max( currentAlpha, newAlpha ); + + // Set the color into the final pixel buffer. + currentColor = packedColor; + } + } + } } + } + else + { + // Initial vertical offset. + const int yOffset = data.verticalOffset + position->y; - const int verticalOffset = yOffsetIndex * data.width; - const int xOffset = data.horizontalOffset + position->x; - const int glyphBufferOffset = lineIndex * static_cast( data.glyphBitmap.width ); - for( int index = 0, glyphWidth = static_cast( data.glyphBitmap.width ); index < glyphWidth; ++index ) + // Traverse the pixels of the glyph line per line. + for( int lineIndex = 0, glyphHeight = static_cast( data.glyphBitmap.height ); lineIndex < glyphHeight; ++lineIndex ) { - const int xOffsetIndex = xOffset + index; - if( ( 0 > xOffsetIndex ) || ( xOffsetIndex > widthMinusOne ) ) + const int yOffsetIndex = yOffset + lineIndex; + if( ( 0 > yOffsetIndex ) || ( yOffsetIndex > heightMinusOne ) ) { - // Don't write out of bounds. - break; + // Do not write out of bounds. + continue; } - if( isColorGlyph ) + const int verticalOffset = yOffsetIndex * data.width; + const int xOffset = data.horizontalOffset + position->x; + const int glyphBufferOffset = lineIndex * static_cast( data.glyphBitmap.width ); + for( int index = 0, glyphWidth = static_cast( data.glyphBitmap.width ); index < glyphWidth; ++index ) { - // Retrieves the color from the glyph. The format is BGRA8888. - uint32_t packedColorGlyph = *( colorGlyphBuffer + glyphBufferOffset + index ); + const int xOffsetIndex = xOffset + index; + if( ( 0 > xOffsetIndex ) || ( xOffsetIndex > widthMinusOne ) ) + { + // Don't write out of bounds. + continue; + } - // Update the alpha channel. - uint8_t* packedColorGlyphBuffer = reinterpret_cast( &packedColorGlyph ); - std::swap( *packedColorGlyphBuffer, *( packedColorGlyphBuffer + 2u ) ); // Swap B and R. - *( packedColorGlyphBuffer + 3u ) = static_cast( color->a * static_cast( *( packedColorGlyphBuffer + 3u ) ) ); + uint8_t* bitmapBuffer = reinterpret_cast< uint8_t* >( data.bitmapBuffer.GetBuffer() ); - // Set the color into the final pixel buffer. - *( data.bitmapBuffer + verticalOffset + xOffsetIndex ) = packedColorGlyph; - } - else - { // Update the alpha channel. const uint8_t alpha = *( data.glyphBitmap.buffer + glyphBufferOffset + index ); - *( packedColorBuffer + 3u ) = static_cast( color->a * static_cast( alpha ) ); - // Set the color into the final pixel buffer. - *( data.bitmapBuffer + verticalOffset + xOffsetIndex ) = packedColor; + // Copy non-transparent pixels only + if ( alpha > 0u ) + { + // Check alpha of overlapped pixels + uint8_t& currentAlpha = *( bitmapBuffer + verticalOffset + xOffsetIndex ); + uint8_t newAlpha = static_cast( color->a * static_cast( alpha ) ); + + // For any pixel overlapped with the pixel in previous glyphs, make sure we don't + // overwrite a previous bigger alpha with a smaller alpha (in order to avoid + // semi-transparent gaps between joint glyphs with overlapped pixels, which could + // happen, for example, in the RTL text when we copy glyphs from right to left). + *( bitmapBuffer + verticalOffset + xOffsetIndex ) = std::max( currentAlpha, newAlpha ); + } } } } } +bool IsGlyphUnderlined( GlyphIndex index, + const Vector& underlineRuns ) +{ + for( Vector::ConstIterator it = underlineRuns.Begin(), + endIt = underlineRuns.End(); + it != endIt; + ++it ) + { + const GlyphRun& run = *it; + + if( ( run.glyphIndex <= index ) && ( index < run.glyphIndex + run.numberOfGlyphs ) ) + { + return true; + } + } + + return false; +} + } // namespace TypesetterPtr Typesetter::New( const ModelInterface* const model ) @@ -148,7 +260,7 @@ ViewModel* Typesetter::GetViewModel() return mModel; } -PixelData Typesetter::Render( const Vector2& size ) +PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat ) { // @todo. This initial implementation for a TextLabel has only one visible page. @@ -180,6 +292,85 @@ PixelData Typesetter::Render( const Vector2& size ) } } + // Generate the image buffers of the text for each different style first, + // then combine all of them together as one final image buffer. We try to + // do all of these in CPU only, so that once the final texture is generated, + // no calculation is needed in GPU during each frame. + + const unsigned int bufferWidth = static_cast( size.width ); + const unsigned int bufferHeight = static_cast( size.height ); + + const unsigned int bufferSizeInt = bufferWidth * bufferHeight; + const unsigned int bufferSizeChar = 4u * bufferSizeInt; + + Length numberOfGlyphs = mModel->GetNumberOfGlyphs(); + + Devel::PixelBuffer imageBuffer; + + if( RENDER_MASK == behaviour ) + { + // Generate the image buffer as an alpha mask for color glyphs. + imageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_MASK, ignoreHorizontalAlignment, pixelFormat, penY, 0u, numberOfGlyphs - 1 ); + } + else if( RENDER_NO_TEXT == behaviour ) + { + // Generate an empty image buffer so that it can been combined with the image buffers for styles + imageBuffer = Devel::PixelBuffer::New( bufferWidth, bufferHeight, Pixel::RGBA8888 ); + memset( imageBuffer.GetBuffer(), 0u, bufferSizeChar ); + } + else + { + // Generate the image buffer for the text with no style. + imageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_NONE, ignoreHorizontalAlignment, pixelFormat, penY, 0u, numberOfGlyphs -1 ); + } + + if ( ( RENDER_NO_STYLES != behaviour ) && ( RENDER_MASK != behaviour ) ) + { + + // Generate the outline if enabled + const float outlineWidth = mModel->GetOutlineWidth(); + if ( outlineWidth > Math::MACHINE_EPSILON_1 ) + { + // Create the image buffer for outline + Devel::PixelBuffer outlineImageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_OUTLINE, ignoreHorizontalAlignment, pixelFormat, penY, 0u, numberOfGlyphs -1 ); + + // Combine the two buffers + imageBuffer = CombineImageBuffer( imageBuffer, outlineImageBuffer, bufferWidth, bufferHeight ); + } + + // @todo. Support shadow and underline for partial text later on. + + // Generate the shadow if enabled + const Vector2& shadowOffset = mModel->GetShadowOffset(); + if ( fabsf( shadowOffset.x ) > Math::MACHINE_EPSILON_1 || fabsf( shadowOffset.y ) > Math::MACHINE_EPSILON_1 ) + { + // Create the image buffer for shadow + Devel::PixelBuffer shadowImageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_SHADOW, ignoreHorizontalAlignment, pixelFormat, penY, 0u, numberOfGlyphs - 1 ); + + // Combine the two buffers + imageBuffer = CombineImageBuffer( imageBuffer, shadowImageBuffer, bufferWidth, bufferHeight ); + } + + // Generate the underline if enabled + const bool underlineEnabled = mModel->IsUnderlineEnabled(); + if ( underlineEnabled ) + { + // Create the image buffer for underline + Devel::PixelBuffer underlineImageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_UNDERLINE, ignoreHorizontalAlignment, pixelFormat, penY, 0u, numberOfGlyphs - 1 ); + + // Combine the two buffers + imageBuffer = CombineImageBuffer( imageBuffer, underlineImageBuffer, bufferWidth, bufferHeight ); + } + } + + // Create the final PixelData for the combined image buffer + PixelData pixelData = Devel::PixelBuffer::Convert( imageBuffer ); + + return pixelData; +} + +Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth, const unsigned int bufferHeight, Typesetter::Style style, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int verticalOffset, GlyphIndex fromGlyphIndex, GlyphIndex toGlyphIndex ) +{ // Retrieve lines, glyphs, positions and colors from the view model. const Length modelNumberOfLines = mModel->GetNumberOfLines(); const LineRun* const modelLinesBuffer = mModel->GetLines(); @@ -190,26 +381,27 @@ PixelData Typesetter::Render( const Vector2& size ) const ColorIndex* const colorIndexBuffer = mModel->GetColorIndices(); // Whether to use the default color. - const bool useDefaultColor = NULL == colorsBuffer; + const bool useDefaultColor = ( NULL == colorsBuffer ); const Vector4& defaultColor = mModel->GetDefaultColor(); // Create and initialize the pixel buffer. GlyphData glyphData; - glyphData.verticalOffset = penY; + glyphData.verticalOffset = verticalOffset; + glyphData.width = bufferWidth; + glyphData.height = bufferHeight; + glyphData.bitmapBuffer = Devel::PixelBuffer::New( bufferWidth, bufferHeight, pixelFormat ); + glyphData.horizontalOffset = 0; - glyphData.width = static_cast( size.width ); - glyphData.height = static_cast( size.height ); - const unsigned int bufferSizeInt = glyphData.width * glyphData.height; - const unsigned int bufferSizeChar = 4u * bufferSizeInt; - glyphData.bitmapBuffer = new uint32_t[ bufferSizeInt ]; // This array will get deleted by PixelData because of the DELETE_ARRAY parameter. - memset( glyphData.bitmapBuffer, 0u, bufferSizeChar ); - - PixelData pixelData = PixelData::New( reinterpret_cast( glyphData.bitmapBuffer ), - bufferSizeChar, - glyphData.width, - glyphData.height, - Pixel::RGBA8888, // The format is RGBA8888 because is the format accepted by the image atlas manager. - PixelData::DELETE_ARRAY ); + if ( Pixel::RGBA8888 == pixelFormat ) + { + const unsigned int bufferSizeInt = bufferWidth * bufferHeight; + const unsigned int bufferSizeChar = 4u * bufferSizeInt; + memset( glyphData.bitmapBuffer.GetBuffer(), 0u, bufferSizeChar ); + } + else + { + memset( glyphData.bitmapBuffer.GetBuffer(), 0, bufferWidth * bufferHeight ); + } // Get a handle of the font client. Used to retrieve the bitmaps of the glyphs. TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); @@ -220,15 +412,67 @@ PixelData Typesetter::Render( const Vector2& size ) const LineRun& line = *( modelLinesBuffer + lineIndex ); // Sets the horizontal offset of the line. - glyphData.horizontalOffset = static_cast( line.alignmentOffset ); + glyphData.horizontalOffset = ignoreHorizontalAlignment ? 0 : static_cast( line.alignmentOffset ); // Increases the vertical offset with the line's ascender. glyphData.verticalOffset += static_cast( line.ascender ); + // Retrieves the glyph's outline width + float outlineWidth = mModel->GetOutlineWidth(); + + if( style == Typesetter::STYLE_OUTLINE ) + { + glyphData.horizontalOffset -= outlineWidth; + if( lineIndex == 0u ) + { + // Only need to add the vertical outline offset for the first line + glyphData.verticalOffset -= outlineWidth; + } + } + else if ( style == Typesetter::STYLE_SHADOW ) + { + const Vector2& shadowOffset = mModel->GetShadowOffset(); + glyphData.horizontalOffset += shadowOffset.x - outlineWidth; // if outline enabled then shadow should offset from outline + + if ( lineIndex == 0u ) + { + // Only need to add the vertical shadow offset for first line + glyphData.verticalOffset += shadowOffset.y - outlineWidth; + } + } + + const bool underlineEnabled = mModel->IsUnderlineEnabled(); + const Vector4& underlineColor = mModel->GetUnderlineColor(); + const float underlineHeight = mModel->GetUnderlineHeight(); + + // Get the underline runs. + const Length numberOfUnderlineRuns = mModel->GetNumberOfUnderlineRuns(); + Vector underlineRuns; + underlineRuns.Resize( numberOfUnderlineRuns ); + mModel->GetUnderlineRuns( underlineRuns.Begin(), 0u, numberOfUnderlineRuns ); + + bool thereAreUnderlinedGlyphs = false; + + float currentUnderlinePosition = 0.0f; + float currentUnderlineThickness = underlineHeight; + float maxUnderlineThickness = currentUnderlineThickness; + + FontId lastUnderlinedFontId = 0; + + float lineExtentLeft = bufferWidth; + float lineExtentRight = 0.0f; + float baseline = 0.0f; + // Traverses the glyphs of the line. const GlyphIndex endGlyphIndex = std::min( numberOfGlyphs, line.glyphRun.glyphIndex + line.glyphRun.numberOfGlyphs ); for( GlyphIndex glyphIndex = line.glyphRun.glyphIndex; glyphIndex < endGlyphIndex; ++glyphIndex ) { + if ( glyphIndex < fromGlyphIndex || glyphIndex > toGlyphIndex ) + { + // Ignore any glyph that out of the specified range + continue; + } + // Retrieve the glyph's info. const GlyphInfo* const glyphInfo = glyphsBuffer + glyphIndex; @@ -239,31 +483,153 @@ PixelData Typesetter::Render( const Vector2& size ) continue; } + const bool underlineGlyph = underlineEnabled || IsGlyphUnderlined( glyphIndex, underlineRuns ); + thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || underlineGlyph; + + // Are we still using the same fontId as previous + if( underlineGlyph && ( glyphInfo->fontId != lastUnderlinedFontId ) ) + { + // We need to fetch fresh font underline metrics + FontMetrics fontMetrics; + fontClient.GetFontMetrics( glyphInfo->fontId, fontMetrics ); + currentUnderlinePosition = ceil( fabsf( fontMetrics.underlinePosition ) ); + const float descender = ceil( fabsf( fontMetrics.descender ) ); + + if( fabsf( underlineHeight ) < Math::MACHINE_EPSILON_1000 ) + { + currentUnderlineThickness = fontMetrics.underlineThickness; + + // Ensure underline will be at least a pixel high + if ( currentUnderlineThickness < 1.0f ) + { + currentUnderlineThickness = 1.0f; + } + else + { + currentUnderlineThickness = ceil( currentUnderlineThickness ); + } + } + + // The underline thickness should be the max underline thickness of all glyphs of the line. + if ( currentUnderlineThickness > maxUnderlineThickness ) + { + maxUnderlineThickness = currentUnderlineThickness; + } + + // Clamp the underline position at the font descender and check for ( as EFL describes it ) a broken font + if( currentUnderlinePosition > descender ) + { + currentUnderlinePosition = descender; + } + + if( fabsf( currentUnderlinePosition ) < Math::MACHINE_EPSILON_1000 ) + { + // Move offset down by one ( EFL behavior ) + currentUnderlinePosition = 1.0f; + } + + lastUnderlinedFontId = glyphInfo->fontId; + } // underline + // Retrieves the glyph's position. const Vector2* const position = positionBuffer + glyphIndex; + if ( baseline < position->y + glyphInfo->yBearing ) + { + baseline = position->y + glyphInfo->yBearing; + } + + // Calculate the positions of leftmost and rightmost glyphs in the current line + if ( position->x < lineExtentLeft) + { + lineExtentLeft = position->x; + } + + if ( position->x + glyphInfo->width > lineExtentRight) + { + lineExtentRight = position->x + glyphInfo->width; + } // Retrieves the glyph's color. const ColorIndex colorIndex = *( colorIndexBuffer + glyphIndex ); - const Vector4* const color = ( useDefaultColor || ( 0u == colorIndex ) ) ? &defaultColor : colorsBuffer + ( colorIndex - 1u ); + + const Vector4* color; + if ( style == Typesetter::STYLE_SHADOW ) + { + color = &( mModel->GetShadowColor() ); + } + else if ( style == Typesetter::STYLE_OUTLINE ) + { + color = &( mModel->GetOutlineColor() ); + } + else + { + color = ( useDefaultColor || ( 0u == colorIndex ) ) ? &defaultColor : colorsBuffer + ( colorIndex - 1u ); + } // Retrieves the glyph's bitmap. glyphData.glyphBitmap.buffer = NULL; glyphData.glyphBitmap.width = glyphInfo->width; // Desired width and height. glyphData.glyphBitmap.height = glyphInfo->height; + + if( style != Typesetter::STYLE_OUTLINE && style != Typesetter::STYLE_SHADOW ) + { + // Don't render outline for other styles + outlineWidth = 0.0f; + } + fontClient.CreateBitmap( glyphInfo->fontId, glyphInfo->index, - glyphData.glyphBitmap ); + glyphData.glyphBitmap, + outlineWidth ); // Sets the glyph's bitmap into the bitmap of the whole text. if( NULL != glyphData.glyphBitmap.buffer ) { TypesetGlyph( glyphData, position, - color ); + color, + style, + pixelFormat); // delete the glyphBitmap.buffer as it is now copied into glyphData.bitmapBuffer delete []glyphData.glyphBitmap.buffer; glyphData.glyphBitmap.buffer = NULL; + } + } + // Draw the underline from the leftmost glyph to the rightmost glyph + if ( thereAreUnderlinedGlyphs && style == Typesetter::STYLE_UNDERLINE ) + { + int underlineYOffset = glyphData.verticalOffset + baseline + currentUnderlinePosition; + + for( unsigned int y = underlineYOffset; y < underlineYOffset + maxUnderlineThickness; y++ ) + { + if( ( y < 0 ) || ( y > bufferHeight - 1 ) ) + { + // Do not write out of bounds. + break; + } + + for( unsigned int x = glyphData.horizontalOffset + lineExtentLeft; x <= glyphData.horizontalOffset + lineExtentRight; x++ ) + { + if( ( x < 0 ) || ( x > bufferWidth - 1 ) ) + { + // Do not write out of bounds. + break; + } + + // Always RGBA image for text with styles + uint32_t* bitmapBuffer = reinterpret_cast< uint32_t* >( glyphData.bitmapBuffer.GetBuffer() ); + uint32_t underlinePixel = *( bitmapBuffer + y * glyphData.width + x ); + uint8_t* underlinePixelBuffer = reinterpret_cast( &underlinePixel ); + + // Write the underline color to the pixel buffer + *( underlinePixelBuffer ) = static_cast( underlineColor.r * 255.f ); + *( underlinePixelBuffer + 1u ) = static_cast( underlineColor.g * 255.f ); + *( underlinePixelBuffer + 2u ) = static_cast( underlineColor.b * 255.f ); + *( underlinePixelBuffer + 3u ) = static_cast( underlineColor.a * 255.f ); + + *( bitmapBuffer + y * glyphData.width + x ) = underlinePixel; + } } } @@ -271,7 +637,70 @@ PixelData Typesetter::Render( const Vector2& size ) glyphData.verticalOffset += static_cast( -line.descender ); } - return pixelData; + return glyphData.bitmapBuffer; +} + +Devel::PixelBuffer Typesetter::CombineImageBuffer( Devel::PixelBuffer topPixelBuffer, Devel::PixelBuffer bottomPixelBuffer, const unsigned int bufferWidth, const unsigned int bufferHeight ) +{ + unsigned char* topBuffer = topPixelBuffer.GetBuffer(); + unsigned char* bottomBuffer = bottomPixelBuffer.GetBuffer(); + + Devel::PixelBuffer combinedPixelBuffer; + + if ( topBuffer == NULL && bottomBuffer == NULL ) + { + // Nothing to do if both buffers are empty. + return combinedPixelBuffer; + } + + if ( topBuffer == NULL ) + { + // Nothing to do if topBuffer is empty. + return bottomPixelBuffer; + } + + if ( bottomBuffer == NULL ) + { + // Nothing to do if bottomBuffer is empty. + return topPixelBuffer; + } + + // Always combine two RGBA images + const unsigned int bufferSizeInt = bufferWidth * bufferHeight; + const unsigned int bufferSizeChar = 4u * bufferSizeInt; + + combinedPixelBuffer = Devel::PixelBuffer::New( bufferWidth, bufferHeight, Pixel::RGBA8888 ); + uint8_t* combinedBuffer = reinterpret_cast< uint8_t* >( combinedPixelBuffer.GetBuffer() ); + memset( combinedBuffer, 0u, bufferSizeChar ); + + for (unsigned int pixelIndex = 0; pixelIndex < bufferSizeInt; pixelIndex++) + { + // If the alpha of the pixel in either buffer is not fully opaque, blend the two pixels. + // Otherwise, copy pixel from topBuffer to combinedBuffer. + + unsigned int alphaBuffer1 = topBuffer[pixelIndex*4+3]; + unsigned int alphaBuffer2 = bottomBuffer[pixelIndex*4+3]; + + if ( alphaBuffer1 != 255 || alphaBuffer2 != 255 ) + { + // At least one pixel is not fully opaque + // "Over" blend the the pixel from topBuffer with the pixel in bottomBuffer + combinedBuffer[pixelIndex*4] = ( topBuffer[pixelIndex*4] * topBuffer[pixelIndex*4+3] / 255 ) + ( bottomBuffer[pixelIndex*4] * bottomBuffer[pixelIndex*4+3] * ( 255 - topBuffer[pixelIndex*4+3] ) / ( 255*255 ) ); + combinedBuffer[pixelIndex*4+1] = ( topBuffer[pixelIndex*4+1] * topBuffer[pixelIndex*4+3] / 255 ) + ( bottomBuffer[pixelIndex*4+1] * bottomBuffer[pixelIndex*4+3] * ( 255 - topBuffer[pixelIndex*4+3] ) / ( 255*255 ) ); + combinedBuffer[pixelIndex*4+2] = ( topBuffer[pixelIndex*4+2] * topBuffer[pixelIndex*4+3] / 255 ) + ( bottomBuffer[pixelIndex*4+2] * bottomBuffer[pixelIndex*4+3] * ( 255 - topBuffer[pixelIndex*4+3] ) / ( 255*255 ) ); + combinedBuffer[pixelIndex*4+3] = topBuffer[pixelIndex*4+3] + ( bottomBuffer[pixelIndex*4+3] * ( 255 - topBuffer[pixelIndex*4+3] ) / 255 ); + } + else + { + // Copy the pixel from topBuffer to combinedBuffer + combinedBuffer[pixelIndex*4] = topBuffer[pixelIndex*4]; + combinedBuffer[pixelIndex*4+1] = topBuffer[pixelIndex*4+1]; + combinedBuffer[pixelIndex*4+2] = topBuffer[pixelIndex*4+2]; + combinedBuffer[pixelIndex*4+3] = topBuffer[pixelIndex*4+3]; + } + } + + return combinedPixelBuffer; } Typesetter::Typesetter( const ModelInterface* const model ) diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.h b/dali-toolkit/internal/text/rendering/text-typesetter.h index a5aab65..285348e 100644 --- a/dali-toolkit/internal/text/rendering/text-typesetter.h +++ b/dali-toolkit/internal/text/rendering/text-typesetter.h @@ -21,7 +21,10 @@ // EXTERNAL INCLUDES #include #include +#include #include +#include +#include namespace Dali { @@ -43,6 +46,33 @@ typedef IntrusivePtr TypesetterPtr; */ class Typesetter : public RefObject { +public: + + /** + * @brief Behaviours of how to render the text. + */ + enum RenderBehaviour + { + RENDER_TEXT_AND_STYLES, ///< Render both the text and its styles + RENDER_NO_TEXT, ///< Do not render the text itself + RENDER_NO_STYLES, ///< Do not render any styles + RENDER_MASK ///< Render an alpha mask (for color glyphs with no color animation, e.g. emoji) + }; + + /** + * @brief Styles of the text. + */ + enum Style + { + STYLE_NONE, ///< No style + STYLE_MASK, ///< Alpha mask + STYLE_SHADOW, ///< Hard shadow + STYLE_SOFT_SHADOW, ///< Soft shadow + STYLE_UNDERLINE, ///< Underline + STYLE_OUTLINE, ///< Outline + STYLE_BACKGROUND ///< Text background + }; + public: // Constructor. /** * @brief Creates a Typesetter instance. @@ -68,15 +98,17 @@ public: * Does the following operations: * - Finds the visible pages needed to be rendered. * - Elide glyphs if needed. - * - Retrieves the data buffers from the text model. - * - Creates the pixel data used to generate the final image with the given size. - * - Traverse the visible glyphs, retrieve their bitmaps and compose the final pixel data. + * - Creates image buffers for diffrent text styles with the given size. + * - Combines different image buffers to create the pixel data used to generate the final image * * @param[in] size The renderer size. + * @param[in] behaviour The behaviour of how to render the text (i.e. whether to render the text only or the styles only or both). + * @param[in] ignoreHorizontalAlignment Whether to ignore the horizontal alignment (i.e. always render as if HORIZONTAL_ALIGN_BEGIN). + * @param[in] pixelFormat The format of the pixel in the image that the text is rendered as (i.e. either Pixel::BGRA8888 or Pixel::L8). * * @return A pixel data with the text rendered. */ - PixelData Render( const Vector2& size ); + PixelData Render( const Vector2& size, RenderBehaviour behaviour = RENDER_TEXT_AND_STYLES, bool ignoreHorizontalAlignment = false, Pixel::Format pixelFormat = Pixel::RGBA8888 ); private: /** @@ -92,6 +124,46 @@ private: // Declared private and left undefined to avoid copies. Typesetter& operator=( const Typesetter& handle ); + /** + * @brief Create the image buffer for the given range of the glyphs in the given style. + * + * Does the following operations: + * - Retrieves the data buffers from the text model. + * - Creates the pixel data used to generate the final image with the given size. + * - Traverse the visible glyphs, retrieve their bitmaps and compose the final pixel data. + * + * @param[in] bufferWidth The width of the image buffer. + * @param[in] bufferHeight The height of the image buffer. + * @param[in] style The style of the text. + * @param[in] ignoreHorizontalAlignment Whether to ignore the horizontal alignment, not ignored by default. + * @param[in] pixelFormat The format of the pixel in the image that the text is rendered as (i.e. either Pixel::BGRA8888 or Pixel::L8). + * @param[in] verticalOffset The vertical offset to be added to the glyph's position. + * @param[in] fromGlyphIndex The index of the first glyph within the text to be drawn + * @param[in] toGlyphIndex The index of the last glyph within the text to be drawn + * + * @return An image buffer with the text. + */ + Devel::PixelBuffer CreateImageBuffer( const unsigned int bufferWidth, const unsigned int bufferHeight, Typesetter::Style style, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int verticalOffset, TextAbstraction::GlyphIndex fromGlyphIndex, TextAbstraction::GlyphIndex toGlyphIndex ); + + /** + * @brief Combine the two RGBA image buffers together. + * + * The top layer buffer will blend over the bottom layer buffer: + * - If the pixel is not fully opaque from either buffer, it will be blended with + * the pixel from the other buffer and copied to the combined buffer. + * - If the pixels from both buffers are fully opaque, the pixels from the top layer + * buffer will be copied to the combined buffer. + * + * @param[in] topPixelBuffer The top layer buffer. + * @param[in] bottomPixelBuffer The bottom layer buffer. + * @param[in] bufferWidth The width of the image buffer. + * @param[in] bufferHeight The height of the image buffer. + * + * @return The combined image buffer with the text. + * + */ + Devel::PixelBuffer CombineImageBuffer( Devel::PixelBuffer topPixelBuffer, Devel::PixelBuffer bottomPixelBuffer, const unsigned int bufferWidth, const unsigned int bufferHeightbool ); + protected: /** @@ -102,6 +174,7 @@ protected: virtual ~Typesetter(); private: + ViewModel* mModel; }; diff --git a/dali-toolkit/internal/text/rendering/view-model.cpp b/dali-toolkit/internal/text/rendering/view-model.cpp old mode 100644 new mode 100755 index eb49465..fe3c451 --- a/dali-toolkit/internal/text/rendering/view-model.cpp +++ b/dali-toolkit/internal/text/rendering/view-model.cpp @@ -86,6 +86,16 @@ const LineRun* const ViewModel::GetLines() const return mModel->GetLines(); } +Length ViewModel::GetNumberOfScripts() const +{ + return mModel->GetNumberOfScripts(); +} + +const ScriptRun* const ViewModel::GetScriptRuns() const +{ + return mModel->GetScriptRuns(); +} + Length ViewModel::GetNumberOfGlyphs() const { if( mIsTextElided && mModel->IsTextElideEnabled() ) @@ -143,6 +153,51 @@ const Vector4& ViewModel::GetDefaultColor() const return mModel->GetDefaultColor(); } +const Vector2& ViewModel::GetShadowOffset() const +{ + return mModel->GetShadowOffset(); +} + +const Vector4& ViewModel::GetShadowColor() const +{ + return mModel->GetShadowColor(); +} + +const Vector4& ViewModel::GetUnderlineColor() const +{ + return mModel->GetUnderlineColor(); +} + +bool ViewModel::IsUnderlineEnabled() const +{ + return mModel->IsUnderlineEnabled(); +} + +float ViewModel::GetUnderlineHeight() const +{ + return mModel->GetUnderlineHeight(); +} + +Length ViewModel::GetNumberOfUnderlineRuns() const +{ + return mModel->GetNumberOfUnderlineRuns(); +} + +void ViewModel::GetUnderlineRuns( GlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns ) const +{ + mModel->GetUnderlineRuns( underlineRuns, index, numberOfRuns ); +} + +const Vector4& ViewModel::GetOutlineColor() const +{ + return mModel->GetOutlineColor(); +} + +float ViewModel::GetOutlineWidth() const +{ + return mModel->GetOutlineWidth(); +} + void ViewModel::ElideGlyphs() { mIsTextElided = false; diff --git a/dali-toolkit/internal/text/rendering/view-model.h b/dali-toolkit/internal/text/rendering/view-model.h old mode 100644 new mode 100755 index d178577..827ecf0 --- a/dali-toolkit/internal/text/rendering/view-model.h +++ b/dali-toolkit/internal/text/rendering/view-model.h @@ -97,6 +97,16 @@ public: virtual const LineRun* const GetLines() const; /** + * @copydoc ModelInterface::GetNumberOfScripts() + */ + virtual Length GetNumberOfScripts() const; + + /** + * @copydoc ModelInterface::GetScriptRuns() + */ + virtual const ScriptRun* const GetScriptRuns() const; + + /** * @copydoc ModelInterface::GetNumberOfGlyphs() */ virtual Length GetNumberOfGlyphs() const; @@ -127,6 +137,51 @@ public: virtual const Vector4& GetDefaultColor() const; /** + * @copydoc ModelInterface::GetShadowOffset() + */ + virtual const Vector2& GetShadowOffset() const; + + /** + * @copydoc ModelInterface::GetShadowColor() + */ + virtual const Vector4& GetShadowColor() const; + + /** + * @copydoc ModelInterface::GetUnderlineColor() + */ + virtual const Vector4& GetUnderlineColor() const; + + /** + * @copydoc ModelInterface::IsUnderlineEnabled() + */ + virtual bool IsUnderlineEnabled() const; + + /** + * @copydoc ModelInterface::GetUnderlineHeight() + */ + virtual float GetUnderlineHeight() const; + + /** + * @copydoc ModelInterface::GetNumberOfUnderlineRuns() + */ + virtual Length GetNumberOfUnderlineRuns() const; + + /** + * @copydoc ModelInterface::GetUnderlineRuns() + */ + virtual void GetUnderlineRuns( GlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns ) const; + + /** + * @copydoc ModelInterface::GetOutlineColor() + */ + virtual const Vector4& GetOutlineColor() const; + + /** + * @copydoc ModelInterface::GetOutlineWidth() + */ + virtual float GetOutlineWidth() const; + + /** * @brief Does the text elide. * * It stores a copy of the visible glyphs and removes as many glyphs as needed diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index fef0f70..0101616 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -106,7 +106,9 @@ EventData::EventData( DecoratorPtr decorator ) mAllTextSelected( false ), mUpdateInputStyle( false ), mPasswordInput( false ), - mIsPlaceholderPixelSize( false ) + mIsPlaceholderPixelSize( false ), + mIsPlaceholderElideEnabled( false ), + mPlaceholderEllipsisFlag( false ) { mImfManager = ImfManager::Get(); } diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index 898e2c6..23188f5 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -159,6 +159,8 @@ struct EventData bool mPasswordInput : 1; ///< True if password input is enabled. bool mCheckScrollAmount : 1; ///< Whether to check scrolled amount after updating the position bool mIsPlaceholderPixelSize : 1; ///< True if the placeholder font size is set as pixel size. + bool mIsPlaceholderElideEnabled : 1; ///< True if the placeholder text's elide is enabled. + bool mPlaceholderEllipsisFlag : 1; ///< True if the text controller sets the placeholder ellipsis. }; struct ModifyEvent diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp old mode 100644 new mode 100755 index 7875e5c..4cc9d90 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -54,6 +54,7 @@ const char * const PLACEHOLDER_FONT_FAMILY = "placeholderFontFamily"; const char * const PLACEHOLDER_FONT_STYLE = "placeholderFontStyle"; const char * const PLACEHOLDER_POINT_SIZE = "placeholderPointSize"; const char * const PLACEHOLDER_PIXEL_SIZE = "placeholderPixelSize"; +const char * const PLACEHOLDER_ELLIPSIS = "placeholderEllipsis"; float ConvertToEven( float value ) { @@ -430,6 +431,24 @@ bool Controller::IsTextElideEnabled() const return mImpl->mModel->mElideEnabled; } +void Controller::SetPlaceholderTextElideEnabled( bool enabled ) +{ + mImpl->mEventData->mIsPlaceholderElideEnabled = enabled; + mImpl->mEventData->mPlaceholderEllipsisFlag = true; + + // Update placeholder if there is no text + if( mImpl->IsShowingPlaceholderText() || + ( 0u == mImpl->mModel->mLogicalModel->mText.Count() ) ) + { + ShowPlaceholderText(); + } +} + +bool Controller::IsPlaceholderTextElideEnabled() const +{ + return mImpl->mEventData->mIsPlaceholderElideEnabled; +} + void Controller::SetSelectionEnabled( bool enabled ) { mImpl->mEventData->mSelectionEnabled = enabled; @@ -1129,6 +1148,30 @@ float Controller::GetUnderlineHeight() const return mImpl->mModel->mVisualModel->GetUnderlineHeight(); } +void Controller::SetOutlineColor( const Vector4& color ) +{ + mImpl->mModel->mVisualModel->SetOutlineColor( color ); + + mImpl->RequestRelayout(); +} + +const Vector4& Controller::GetOutlineColor() const +{ + return mImpl->mModel->mVisualModel->GetOutlineColor(); +} + +void Controller::SetOutlineWidth( float width ) +{ + mImpl->mModel->mVisualModel->SetOutlineWidth( width ); + + mImpl->RequestRelayout(); +} + +float Controller::GetOutlineWidth() const +{ + return mImpl->mModel->mVisualModel->GetOutlineWidth(); +} + void Controller::SetDefaultEmbossProperties( const std::string& embossProperties ) { if( NULL == mImpl->mEmbossDefaults ) @@ -1757,14 +1800,14 @@ Vector3 Controller::GetNaturalSize() mImpl->UpdateModel( onlyOnceOperations ); // Layout the text for the new width. - mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | LAYOUT ); + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | LAYOUT | REORDER ); // Store the actual control's size to restore later. const Size actualControlSize = mImpl->mModel->mVisualModel->mControlSize; DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ), static_cast( onlyOnceOperations | - LAYOUT ), + LAYOUT | REORDER ), naturalSize.GetVectorXY() ); // Do not do again the only once operations. @@ -1982,6 +2025,12 @@ void Controller::SetPlaceholderProperty( const Property::Map& map ) SetPlaceholderTextFontSize( pixelSize, Text::Controller::PIXEL_SIZE ); } } + else if( key == PLACEHOLDER_ELLIPSIS ) + { + bool ellipsis; + value.Get( ellipsis ); + SetPlaceholderTextElideEnabled( ellipsis ); + } } } @@ -2014,6 +2063,11 @@ void Controller::GetPlaceholderProperty( Property::Map& map ) { map[ PLACEHOLDER_PIXEL_SIZE ] = GetPlaceholderTextFontSize( Text::Controller::PIXEL_SIZE ); } + + if( mImpl->mEventData->mPlaceholderEllipsisFlag ) + { + map[ PLACEHOLDER_ELLIPSIS ] = IsPlaceholderTextElideEnabled(); + } } } @@ -2071,6 +2125,20 @@ Controller::UpdateTextType Controller::Relayout( const Size& size ) COLOR ); } + // Set the update info to elide the text. + if( mImpl->mModel->mElideEnabled || + ( ( NULL != mImpl->mEventData ) && mImpl->mEventData->mIsPlaceholderElideEnabled ) ) + { + // Update Text layout for applying elided + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | + ALIGN | + LAYOUT | + UPDATE_LAYOUT_SIZE | + REORDER ); + mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true; + mImpl->mTextUpdateInfo.mCharacterIndex = 0u; + } + // Make sure the model is up-to-date before layouting. ProcessModifyEvents(); bool updated = mImpl->UpdateModel( mImpl->mOperationsPending ); @@ -3255,13 +3323,35 @@ bool Controller::DoRelayout( const Size& size, layoutParameters.startLineIndex = mImpl->mTextUpdateInfo.mStartLineIndex; layoutParameters.estimatedNumberOfLines = mImpl->mTextUpdateInfo.mEstimatedNumberOfLines; + // Update the ellipsis + bool elideTextEnabled = mImpl->mModel->mElideEnabled; + + if( NULL != mImpl->mEventData ) + { + if( mImpl->mEventData->mPlaceholderEllipsisFlag && mImpl->IsShowingPlaceholderText() ) + { + elideTextEnabled = mImpl->mEventData->mIsPlaceholderElideEnabled; + } + else if( EventData::INACTIVE != mImpl->mEventData->mState ) + { + // Disable ellipsis when editing + elideTextEnabled = false; + } + + // Reset the scroll position in inactive state + if( elideTextEnabled && ( mImpl->mEventData->mState == EventData::INACTIVE ) ) + { + ResetScrollPosition(); + } + } + // Update the visual model. Size newLayoutSize; viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters, glyphPositions, mImpl->mModel->mVisualModel->mLines, newLayoutSize, - mImpl->mModel->mElideEnabled ); + elideTextEnabled ); viewUpdated = viewUpdated || ( newLayoutSize != layoutSize ); @@ -3694,6 +3784,11 @@ void Controller::ResetScrollPosition() } } +void Controller::SetControlInterface( ControlInterface* controlInterface ) +{ + mImpl->mControlInterface = controlInterface; +} + bool Controller::ShouldClearFocusOnEscape() const { return mImpl->mShouldClearFocusOnEscape; diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h old mode 100644 new mode 100755 index 1f64c24..b02bb68 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -369,6 +369,18 @@ public: // Configure the text controller. bool IsTextElideEnabled() const; /** + * @brief Enable or disable the placeholder text elide. + * @param enabled Whether to enable the placeholder text elide. + */ + void SetPlaceholderTextElideEnabled( bool enabled ); + + /** + * @brief Whether the placeholder text elide property is enabled. + * @return True if the placeholder text elide property is enabled, false otherwise. + */ + bool IsPlaceholderTextElideEnabled() const; + + /** * @brief Enable or disable the text selection. * @param[in] enabled Whether to enable the text selection. */ @@ -777,6 +789,34 @@ public: // Default style & Input style float GetUnderlineHeight() const; /** + * @brief Set the outline color. + * + * @param[in] color color of outline. + */ + void SetOutlineColor( const Vector4& color ); + + /** + * @brief Retrieve the outline color. + * + * @return The outline color. + */ + const Vector4& GetOutlineColor() const; + + /** + * @brief Set the outline width + * + * @param[in] width The width in pixels of the outline, 0 indicates no outline + */ + void SetOutlineWidth( float width ); + + /** + * @brief Retrieves the width of an outline + * + * @return The width of the outline. + */ + float GetOutlineWidth() const; + + /** * @brief Sets the emboss's properties string. * * @note The string is stored to be recovered. @@ -999,6 +1039,13 @@ public: // Default style & Input style */ const std::string& GetInputOutlineProperties() const; + /** + * @brief Set the control's interface. + * + * @param[in] controlInterface The control's interface. + */ + void SetControlInterface( ControlInterface* controlInterface ); + public: // Queries & retrieves. /** diff --git a/dali-toolkit/internal/text/text-effects-style.cpp b/dali-toolkit/internal/text/text-effects-style.cpp old mode 100644 new mode 100755 index 75fabd7..8b71d30 --- a/dali-toolkit/internal/text/text-effects-style.cpp +++ b/dali-toolkit/internal/text/text-effects-style.cpp @@ -35,6 +35,7 @@ namespace { const std::string COLOR_KEY( "color" ); const std::string OFFSET_KEY( "offset" ); +const std::string WIDTH_KEY( "width" ); const std::string HEIGHT_KEY( "height" ); const std::string ENABLE_KEY( "enable" ); const std::string TRUE_TOKEN( "true" ); @@ -120,6 +121,36 @@ bool ParseUnderlineProperties( const Property::Map& underlinePropertiesMap, return 0u == numberOfItems; } +bool ParseOutlineProperties( const Property::Map& underlinePropertiesMap, + bool& colorDefined, + Vector4& color, + bool& widthDefined, + float& width ) +{ + const unsigned int numberOfItems = underlinePropertiesMap.Count(); + + // Parses and applies the style. + for( unsigned int index = 0u; index < numberOfItems; ++index ) + { + const KeyValuePair& valueGet = underlinePropertiesMap.GetKeyValue( index ); + + if( COLOR_KEY == valueGet.first.stringKey ) + { + /// Color key. + colorDefined = true; + color = valueGet.second.Get(); + } + else if( WIDTH_KEY == valueGet.first.stringKey ) + { + /// Width key. + widthDefined = true; + width = valueGet.second.Get(); + } + } + + return 0u == numberOfItems; +} + bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type ) { bool update = false; @@ -463,24 +494,63 @@ bool SetOutlineProperties( ControllerPtr controller, const Property::Value& valu if( controller ) { - const std::string properties = value.Get< std::string >(); - switch( type ) { case EffectStyle::DEFAULT: { - // Stores the default outline's properties string to be recovered by the GetOutlineProperties() function. - controller->SetDefaultOutlineProperties( properties ); + const Property::Map& propertiesMap = value.Get(); + + bool colorDefined = false; + Vector4 color; + bool widthDefined = false; + float width = 0.f; + + bool empty = true; + + if ( !propertiesMap.Empty() ) + { + empty = ParseOutlineProperties( propertiesMap, + colorDefined, + color, + widthDefined, + width ); + } + + if( !empty ) + { + // Sets the default outline values. + if( colorDefined && ( controller->GetOutlineColor() != color ) ) + { + controller->SetOutlineColor( color ); + update = true; + } + + if( widthDefined && ( fabsf( controller->GetOutlineWidth() - width ) > Math::MACHINE_EPSILON_1000 ) ) + { + controller->SetOutlineWidth( width ); + update = true; + } + } + else + { + // Disable outline + if( fabsf( controller->GetOutlineWidth() ) > Math::MACHINE_EPSILON_1000 ) + { + controller->SetOutlineWidth( 0.0f ); + update = true; + } + } break; } case EffectStyle::INPUT: { - // Stores the input outline's properties string to be recovered by the GetOutlineProperties() function. - controller->SetInputOutlineProperties( properties ); + const std::string& outlineProperties = value.Get(); + + controller->SetInputOutlineProperties( outlineProperties ); break; } - } - } + } // switch + } // if( controller ) return update; } @@ -493,7 +563,21 @@ void GetOutlineProperties( ControllerPtr controller, Property::Value& value, Eff { case EffectStyle::DEFAULT: { - value = controller->GetDefaultOutlineProperties(); + const Vector4& color = controller->GetOutlineColor(); + const float width = controller->GetOutlineWidth(); + + Property::Map map; + + std::string colorStr; + Vector4ToColorString( color, colorStr ); + map.Insert( COLOR_KEY, colorStr ); + + std::string widthStr; + FloatToString( width, widthStr ); + map.Insert( WIDTH_KEY, widthStr ); + + value = map; + break; } case EffectStyle::INPUT: diff --git a/dali-toolkit/internal/text/text-effects-style.h b/dali-toolkit/internal/text/text-effects-style.h old mode 100644 new mode 100755 index 4ab61a3..521f52c --- a/dali-toolkit/internal/text/text-effects-style.h +++ b/dali-toolkit/internal/text/text-effects-style.h @@ -72,6 +72,21 @@ bool ParseUnderlineProperties( const Property::Map& underlineProperties, float& height ); /** + * @brief Parses the outline properties. + * + * @param[in] outlineProperties The map with the outline properties. + * @param[out] colorDefined Whether the outline's color is defined. + * @param[out] color The outline's color. + * @param[out] widthDefined Whether the outline's width is defined. + * @param[out] width The outline's width. + */ +bool ParseOutlineProperties( const Property::Map& outlineProperties, + bool& colorDefined, + Vector4& color, + bool& widthDefined, + float& width ); + +/** * @brief Sets the underline properties. * * @param[in] controller The text's controller. diff --git a/dali-toolkit/internal/text/text-font-style.cpp b/dali-toolkit/internal/text/text-font-style.cpp index 8978beb..927f277 100644 --- a/dali-toolkit/internal/text/text-font-style.cpp +++ b/dali-toolkit/internal/text/text-font-style.cpp @@ -45,10 +45,6 @@ const std::string TYPE_KEY( "type" ); const std::string SYSTEM_TOKEN( "system" ); -#if defined(DEBUG_ENABLED) -Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS"); -#endif - } // namespace void SetFontFamilyProperty( ControllerPtr controller, const Property::Value& value ) diff --git a/dali-toolkit/internal/text/text-model-interface.h b/dali-toolkit/internal/text/text-model-interface.h old mode 100644 new mode 100755 index b3eb694..18cb7cc --- a/dali-toolkit/internal/text/text-model-interface.h +++ b/dali-toolkit/internal/text/text-model-interface.h @@ -24,6 +24,7 @@ // INTERNAL INCLUDES #include #include +#include #include namespace Dali @@ -104,6 +105,20 @@ public: virtual const LineRun* const GetLines() const = 0; /** + * @brief Retrieves the number of script runs. + * + * @return The number of script runs. + */ + virtual Length GetNumberOfScripts() const = 0; + + /** + * @brief Retrieves the script runs. + * + * @return A pointer to the vector with the runs of characters with the same script.. + */ + virtual const ScriptRun* const GetScriptRuns() const = 0; + + /** * @brief Retrieves the number of laid-out glyphs. * * @return The number of laid-out glyphs. @@ -144,6 +159,72 @@ public: * @return The default color. */ virtual const Vector4& GetDefaultColor() const = 0; + + /** + * @brief Retrieves the shadow offset, 0 indicates no shadow. + * + * @return The shadow offset. + */ + virtual const Vector2& GetShadowOffset() const = 0; + + /** + * @brief Retrieves the shadow color. + * + * @return The shadow color. + */ + virtual const Vector4& GetShadowColor() const = 0; + + /** + * @brief Retrieves the underline color. + * + * @return The underline color. + */ + virtual const Vector4& GetUnderlineColor() const = 0; + + /** + * @brief Returns whether underline is enabled or not. + * + * @return The underline state. + */ + virtual bool IsUnderlineEnabled() const = 0; + + /** + * @brief Retrieves the underline height override + * + * @return Returns the override height for an underline, 0 indicates that adaptor will determine the height + */ + virtual float GetUnderlineHeight() const = 0; + + /** + * @brief Retrieves the number of underline runs. + * + * @return The number of underline runs. + */ + virtual Length GetNumberOfUnderlineRuns() const = 0; + + /** + * @brief Retrieves the underline runs. + * + * @param[out] underlineRuns Pointer to a buffer where the underline runs are copied. + * @param[in] index Index of the first underline run to be copied. + * @param[in] numberOfRuns Number of underline runs to be copied. + */ + virtual void GetUnderlineRuns( GlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns ) const = 0; + + /** + * @brief Retrieve the outline color. + * + * @return The outline color. + */ + virtual const Vector4& GetOutlineColor() const = 0; + + /** + * @brief Retrieves the width of an outline + * + * @return The width of the outline. + */ + virtual float GetOutlineWidth() const = 0; + }; } // namespace Text diff --git a/dali-toolkit/internal/text/text-model.cpp b/dali-toolkit/internal/text/text-model.cpp old mode 100644 new mode 100755 index 95f9514..cf6f35c --- a/dali-toolkit/internal/text/text-model.cpp +++ b/dali-toolkit/internal/text/text-model.cpp @@ -72,6 +72,16 @@ const LineRun* const Model::GetLines() const return mVisualModel->mLines.Begin(); } +Length Model::GetNumberOfScripts() const +{ + return mLogicalModel->mScriptRuns.Count(); +} + +const ScriptRun* const Model::GetScriptRuns() const +{ + return mLogicalModel->mScriptRuns.Begin(); +} + Length Model::GetNumberOfGlyphs() const { return mVisualModel->mGlyphs.Count(); @@ -102,6 +112,51 @@ const Vector4& Model::GetDefaultColor() const return mVisualModel->mTextColor; } +const Vector2& Model::GetShadowOffset() const +{ + return mVisualModel->mShadowOffset; +} + +const Vector4& Model::GetShadowColor() const +{ + return mVisualModel->mShadowColor; +} + +const Vector4& Model::GetUnderlineColor() const +{ + return mVisualModel->GetUnderlineColor(); +} + +bool Model::IsUnderlineEnabled() const +{ + return mVisualModel->IsUnderlineEnabled(); +} + +float Model::GetUnderlineHeight() const +{ + return mVisualModel->GetUnderlineHeight(); +} + +Length Model::GetNumberOfUnderlineRuns() const +{ + return mVisualModel->GetNumberOfUnderlineRuns(); +} + +void Model::GetUnderlineRuns( GlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns ) const +{ + mVisualModel->GetUnderlineRuns( underlineRuns, index, numberOfRuns ); +} + +const Vector4& Model::GetOutlineColor() const +{ + return mVisualModel->GetOutlineColor(); +} + +float Model::GetOutlineWidth() const +{ + return mVisualModel->GetOutlineWidth(); +} + Model::Model() : mLogicalModel(), mVisualModel(), diff --git a/dali-toolkit/internal/text/text-model.h b/dali-toolkit/internal/text/text-model.h old mode 100644 new mode 100755 index 4256421..cd49581 --- a/dali-toolkit/internal/text/text-model.h +++ b/dali-toolkit/internal/text/text-model.h @@ -100,6 +100,16 @@ public: virtual const LineRun* const GetLines() const; /** + * @copydoc ModelInterface::GetNumberOfScripts() + */ + virtual Length GetNumberOfScripts() const; + + /** + * @copydoc ModelInterface::GetScriptRuns() + */ + virtual const ScriptRun* const GetScriptRuns() const; + + /** * @copydoc ModelInterface::GetNumberOfGlyphs() */ virtual Length GetNumberOfGlyphs() const; @@ -129,6 +139,51 @@ public: */ virtual const Vector4& GetDefaultColor() const; + /** + * @copydoc ModelInterface::GetShadowOffset() + */ + virtual const Vector2& GetShadowOffset() const; + + /** + * @copydoc ModelInterface::GetShadowColor() + */ + virtual const Vector4& GetShadowColor() const; + + /** + * @copydoc ModelInterface::GetUnderlineColor() + */ + virtual const Vector4& GetUnderlineColor() const; + + /** + * @copydoc ModelInterface::IsUnderlineEnabled() + */ + virtual bool IsUnderlineEnabled() const; + + /** + * @copydoc ModelInterface::GetUnderlineHeight() + */ + virtual float GetUnderlineHeight() const; + + /** + * @copydoc ModelInterface::GetNumberOfUnderlineRuns() + */ + virtual Length GetNumberOfUnderlineRuns() const; + + /** + * @copydoc ModelInterface::GetUnderlineRuns() + */ + virtual void GetUnderlineRuns( GlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns ) const; + + /** + * @copydoc ModelInterface::GetOutlineColor() + */ + virtual const Vector4& GetOutlineColor() const; + + /** + * @copydoc ModelInterface::GetOutlineWidth() + */ + virtual float GetOutlineWidth() const; + private: // Private contructors & copy operator. /** diff --git a/dali-toolkit/internal/text/text-scroller.cpp b/dali-toolkit/internal/text/text-scroller.cpp index 590f919..b109661 100644 --- a/dali-toolkit/internal/text/text-scroller.cpp +++ b/dali-toolkit/internal/text/text-scroller.cpp @@ -20,13 +20,6 @@ // EXTERNAL INCLUDES #include -#include -#include -#include -#include -#include -#include -#include #include // INTERNAL INCLUDES @@ -51,30 +44,41 @@ const char* VERTEX_SHADER_SCROLL = DALI_COMPOSE_SHADER( attribute mediump vec2 aPosition;\n varying highp vec2 vTexCoord;\n varying highp float vRatio;\n - uniform mediump mat4 uModelMatrix;\n - uniform mediump mat4 uViewMatrix;\n - uniform mediump mat4 uProjection;\n uniform mediump vec3 uSize;\n uniform mediump float uDelta;\n - uniform mediump vec2 uTextureSize; + uniform mediump vec2 uTextureSize;\n uniform mediump float uGap;\n - uniform mediump float uAlign;\n + uniform mediump float uHorizontalAlign;\n + uniform mediump float uVerticalAlign;\n + \n + uniform mediump mat4 uModelMatrix;\n + uniform mediump mat4 uViewMatrix;\n + uniform mediump mat4 uProjection;\n \n + //Visual size and offset + uniform mediump vec2 offset;\n + uniform mediump vec2 size;\n + uniform mediump vec4 offsetSizeMode;\n + uniform mediump vec2 origin;\n + uniform mediump vec2 anchorPoint;\n + void main()\n {\n - {\n - highp vec4 vertexPosition = vec4(aPosition*uSize.xy, 0.0, 1.0);\n - vertexPosition = uViewMatrix * uModelMatrix * vertexPosition ;\n - vertexPosition.x = floor( vertexPosition.x ) + 0.5; - vertexPosition.y = floor( vertexPosition.y ) + 0.5; - float smallTextPadding = max(uSize.x - uTextureSize.x, 0. );\n - float gap = max( uGap, smallTextPadding );\n - float delta = floor ( uDelta ) + 0.5; - vTexCoord.x = ( delta + ( uAlign * ( uTextureSize.x - uSize.x ) ) + ( aPosition.x * uSize.x ) )/ ( uTextureSize.x + gap );\n - vTexCoord.y = ( 0.5 + floor( aPosition.y * uSize.y ) )/ ( uTextureSize.y ) ;\n - vRatio = uTextureSize.x / ( uTextureSize.x + gap );\n - gl_Position = uProjection * vertexPosition; - }\n + mediump vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy );\n + mediump vec2 visualSize = mix( uSize.xy * size, size, offsetSizeMode.zw );\n + \n + mediump float smallTextPadding = max( visualSize.x - uTextureSize.x, 0. );\n + mediump float gap = max( uGap, smallTextPadding );\n + mediump float delta = floor ( uDelta ) + 0.5;\n + vTexCoord.x = ( delta + uHorizontalAlign * ( uTextureSize.x - visualSize.x ) + floor( aPosition.x * visualSize.x ) + 0.5 - gap * 0.5 ) / ( uTextureSize.x + gap ) + 0.5;\n + vTexCoord.y = ( uVerticalAlign * ( uTextureSize.y - visualSize.y ) + floor( aPosition.y * visualSize.y ) + 0.5 ) / ( uTextureSize.y ) + 0.5;\n + vRatio = uTextureSize.x / ( uTextureSize.x + gap );\n + \n + mediump vec4 vertexPosition = vec4( floor( ( aPosition + anchorPoint ) * visualSize + ( visualOffset + origin ) * uSize.xy ), 0.0, 1.0 );\n + mediump vec4 nonAlignedVertex = uViewMatrix * uModelMatrix * vertexPosition;\n + mediump vec4 pixelAlignedVertex = vec4 ( floor( nonAlignedVertex.xyz ), 1.0 );\n + \n + gl_Position = uProjection * pixelAlignedVertex;\n }\n ); @@ -88,7 +92,7 @@ const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( highp vec2 texCoord;\n texCoord.y = vTexCoord.y;\n texCoord.x = fract( vTexCoord.x ) / vRatio;\n - if ( texCoord.x > 1.0 )\n + if ( texCoord.x > 1.0 || texCoord.y > 1.0 )\n discard;\n \n gl_FragColor = texture2D( sTexture, texCoord );\n @@ -96,146 +100,46 @@ const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( ); /** - * @brief How the text should be aligned when scrolling the text. + * @brief How the text should be aligned horizontally when scrolling the text. * - * 0.0f aligns the text to the left, 1.0f aligns the text to the right. - * The final alignment depends on three factors: + * -0.5f aligns the text to the left, 0.0f aligns the text to the center, 0.5f aligns the text to the right. + * The final alignment depends on two factors: * 1) The alignment value of the text label (Use Text::Layout::HorizontalAlignment enumerations). * 2) The text direction, i.e. whether it's LTR or RTL (0 = LTR, 1 = RTL). - * 3) Whether the text is greater than the size of the control ( 0 = Text width <= Control width, 1 = Text width > Control width ). */ -const float ALIGNMENT_TABLE[ Text::Layout::HORIZONTAL_ALIGN_COUNT ][ 2 ][ 2 ] = +const float HORIZONTAL_ALIGNMENT_TABLE[ Text::Layout::HORIZONTAL_ALIGN_COUNT ][ 2 ] = { // HORIZONTAL_ALIGN_BEGIN { - { // LTR - 0.0f, // Text width <= Control width - 0.0f // Text width > Control width - }, - { // RTL - 1.0f, // Text width <= Control width - 1.0f // Text width > Control width - } + -0.5f, // LTR + 0.5f // RTL }, // HORIZONTAL_ALIGN_CENTER { - { // LTR - 0.5f, // Text width <= Control width - 0.0f // Text width > Control width - }, - { // RTL - 0.5f, // Text width <= Control width - 1.0f // Text width > Control width - } + 0.0f, // LTR + 0.0f // RTL }, // HORIZONTAL_ALIGN_END { - { // LTR - 1.0f, // Text width <= Control width - 0.0f // Text width > Control width - }, - { // RTL - 0.0f, // Text width <= Control width - 1.0f // Text width > Control width - } + 0.5f, // LTR + -0.5f // RTL } }; /** - * @brief Create and set up a camera for the render task to use - * - * @param[in] sizeOfTarget size of the source camera to look at - * @param[out] offscreenCamera custom camera - */ -void CreateCameraActor( const Size& sizeOfTarget, CameraActor& offscreenCamera ) -{ - offscreenCamera = CameraActor::New(); - offscreenCamera.SetOrthographicProjection( sizeOfTarget ); - offscreenCamera.SetInvertYAxis( true ); -} - -/** - * @brief Create a render task + * @brief How the text should be aligned vertically when scrolling the text. * - * @param[in] sourceActor actor to be used as source - * @param[in] cameraActor camera looking at source - * @param[in] offscreenTarget resulting image from render task - * @param[out] renderTask render task that has been setup + * -0.5f aligns the text to the top, 0.0f aligns the text to the center, 0.5f aligns the text to the bottom. + * The alignment depends on the alignment value of the text label (Use Text::Layout::VerticalAlignment enumerations). */ -void CreateRenderTask( Actor sourceActor, CameraActor cameraActor , FrameBufferImage offscreenTarget, RenderTask& renderTask ) +const float VERTICAL_ALIGNMENT_TABLE[ Text::Layout::VERTICAL_ALIGN_COUNT ] = { - Stage stage = Stage::GetCurrent(); - RenderTaskList taskList = stage.GetRenderTaskList(); - renderTask = taskList.CreateTask(); - renderTask.SetSourceActor( sourceActor ); - renderTask.SetExclusive( true ); - renderTask.SetInputEnabled( false ); - renderTask.SetClearEnabled( true ); - renderTask.SetCameraActor( cameraActor ); - renderTask.SetTargetFrameBuffer( offscreenTarget ); - renderTask.SetClearColor( Color::TRANSPARENT ); - renderTask.SetCullMode( false ); -} - -/** - * @brief Create quad geometry for the mesh - * - * @param[out] geometry quad geometry that can be used for a mesh - */ -void CreateGeometry( Geometry& geometry ) -{ - struct QuadVertex { Vector2 position; }; - - QuadVertex quadVertexData[4] = - { - { Vector2( 0.0f, 0.0f) }, - { Vector2( 1.0f, 0.0f) }, - { Vector2( 0.0f, 1.0f) }, - { Vector2( 1.0f, 1.0f) }, - }; - - const unsigned short indices[6] = - { - 3,1,0,0,2,3 - }; - - Property::Map quadVertexFormat; - quadVertexFormat["aPosition"] = Property::VECTOR2; - PropertyBuffer quadVertices = PropertyBuffer::New( quadVertexFormat ); - quadVertices.SetData(quadVertexData, 4 ); - - geometry = Geometry::New(); - geometry.AddVertexBuffer( quadVertices ); - geometry.SetIndexBuffer( indices, sizeof(indices)/sizeof(indices[0]) ); -} - - -/** - * @brief Create a renderer - * - * @param[in] frameBufferImage texture to be used - * @param[out] renderer mesh renderer using the supplied texture - */ -void CreateRenderer( FrameBufferImage frameBufferImage, Dali::Renderer& renderer ) -{ - Shader shader = Shader::New( VERTEX_SHADER_SCROLL , FRAGMENT_SHADER, Shader::Hint::NONE ); - - Sampler sampler = Sampler::New(); - sampler.SetFilterMode(FilterMode::LINEAR, FilterMode::LINEAR ); - - TextureSet textureSet = TextureSet::New(); - TextureSetImage( textureSet, 0u, frameBufferImage ); - textureSet.SetSampler( 0u, sampler ); - - Geometry meshGeometry; - CreateGeometry( meshGeometry ); - - renderer = Renderer::New( meshGeometry, shader ); - renderer.SetProperty( Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true ); - renderer.SetTextures( textureSet ); -} + -0.5f, // VERTICAL_ALIGN_TOP + 0.0f, // VERTICAL_ALIGN_CENTER + 0.5f // VERTICAL_ALIGN_BOTTOM +}; } // namespace @@ -311,7 +215,6 @@ void TextScroller::StopScrolling() case DevelTextLabel::AutoScrollStopMode::IMMEDIATE: { mScrollAnimation.Stop(); - CleanUp(); mScrollerInterface.ScrollingFinished(); break; } @@ -333,38 +236,28 @@ DevelTextLabel::AutoScrollStopMode::Type TextScroller::GetStopMode() const return mStopMode; } -Actor TextScroller::GetSourceCamera() const -{ - return mOffscreenCameraActor; -} - -Actor TextScroller::GetScrollingText() const -{ - return mScrollingTextActor; -} - -TextScroller::TextScroller( ScrollerInterface& scrollerInterface ) : mScrollerInterface( scrollerInterface ), - mScrollDeltaIndex( Property::INVALID_INDEX ), - mScrollSpeed( MINIMUM_SCROLL_SPEED ), - mLoopCount( 1 ), - mLoopDelay( 0.0f ), - mWrapGap( 0.0f ), - mStopMode( DevelTextLabel::AutoScrollStopMode::FINISH_LOOP ) +TextScroller::TextScroller( ScrollerInterface& scrollerInterface ) +: mScrollerInterface( scrollerInterface ), + mScrollDeltaIndex( Property::INVALID_INDEX ), + mScrollSpeed( MINIMUM_SCROLL_SPEED ), + mLoopCount( 1 ), + mLoopDelay( 0.0f ), + mWrapGap( 0.0f ), + mStopMode( DevelTextLabel::AutoScrollStopMode::FINISH_LOOP ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller Default Constructor\n" ); } TextScroller::~TextScroller() { - CleanUp(); } -void TextScroller::SetParameters( Actor sourceActor, const Size& controlSize, const Size& offScreenSize, CharacterDirection direction, float alignmentOffset, Layout::HorizontalAlignment horizontalAlignment ) +void TextScroller::SetParameters( Actor scrollingTextActor, Renderer renderer, TextureSet textureSet, const Size& controlSize, const Size& textNaturalSize, CharacterDirection direction, Layout::HorizontalAlignment horizontalAlignment, Layout::VerticalAlignment verticalAlignment ) { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters controlSize[%f,%f] offscreenSize[%f,%f] direction[%d] alignmentOffset[%f]\n", - controlSize.x, controlSize.y, offScreenSize.x, offScreenSize.y, direction, alignmentOffset ); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters controlSize[%f,%f] offscreenSize[%f,%f] direction[%d]\n", + controlSize.x, controlSize.y, textNaturalSize.x, textNaturalSize.y, direction ); - CleanUp(); // If already scrolling then restart with new parameters + mRenderer = renderer; float animationProgress = 0.0f; int remainedLoop = mLoopCount; @@ -381,114 +274,69 @@ void TextScroller::SetParameters( Actor sourceActor, const Size& controlSize, co } } mScrollAnimation.Clear(); - } - - FrameBufferImage offscreenRenderTargetForText = FrameBufferImage::New( offScreenSize.width, offScreenSize.height, Pixel::RGBA8888 ); - Renderer renderer; - CreateCameraActor( offScreenSize, mOffscreenCameraActor ); - CreateRenderer( offscreenRenderTargetForText, renderer ); - CreateRenderTask( sourceActor, mOffscreenCameraActor, offscreenRenderTargetForText, mRenderTask ); - - float xPosition = 0.0f; - switch( horizontalAlignment ) - { - case Layout::HORIZONTAL_ALIGN_BEGIN: - { - // Reposition camera to match alignment of target, RTL text has direction=true - if ( direction ) - { - xPosition = alignmentOffset + offScreenSize.width * 0.5f; - } - else - { - xPosition = offScreenSize.width * 0.5f; - } - break; - } - - case Layout::HORIZONTAL_ALIGN_CENTER: - { - xPosition = controlSize.width * 0.5f; - break; - } - - case Layout::HORIZONTAL_ALIGN_END: - { - // Reposition camera to match alignment of target, RTL text has direction=true - if ( direction ) - { - xPosition = offScreenSize.width * 0.5f; - } - else - { - xPosition = alignmentOffset + offScreenSize.width * 0.5f; - } - break; - } + // Reset to the original shader and texture before scrolling + mRenderer.SetShader(mShader); + mRenderer.SetTextures( mTextureSet ); } - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters xPosition[%f]\n", xPosition ); + mShader = mRenderer.GetShader(); + mTextureSet = mRenderer.GetTextures(); - mOffscreenCameraActor.SetX( xPosition ); - mOffscreenCameraActor.SetY( offScreenSize.height * 0.5f ); + // Set the shader and texture for scrolling + Shader shader = Shader::New( VERTEX_SHADER_SCROLL, FRAGMENT_SHADER, Shader::Hint::NONE ); + mRenderer.SetShader( shader ); + mRenderer.SetTextures( textureSet ); DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters mWrapGap[%f]\n", mWrapGap ); - const float align = ALIGNMENT_TABLE[ horizontalAlignment ][ direction ][ offScreenSize.width > controlSize.width ]; - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters align[%f]\n", align ); + const float horizontalAlign = HORIZONTAL_ALIGNMENT_TABLE[ horizontalAlignment ][ direction ]; + const float verticalAlign = VERTICAL_ALIGNMENT_TABLE[ verticalAlignment ]; + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters horizontalAlign[%f], verticalAlign[%f]\n", horizontalAlign, verticalAlign ); - mScrollingTextActor = Actor::New(); - mScrollingTextActor.AddRenderer( renderer ); - mScrollingTextActor.RegisterProperty( "uTextureSize", offScreenSize ); - mScrollingTextActor.RegisterProperty( "uAlign", align ); - mScrollingTextActor.RegisterProperty( "uGap", mWrapGap ); - mScrollingTextActor.SetSize( controlSize.width, std::min( offScreenSize.height, controlSize.height ) ); - mScrollDeltaIndex = mScrollingTextActor.RegisterProperty( "uDelta", 0.0f ); + scrollingTextActor.RegisterProperty( "uTextureSize", textNaturalSize ); + scrollingTextActor.RegisterProperty( "uHorizontalAlign", horizontalAlign ); + scrollingTextActor.RegisterProperty( "uVerticalAlign", verticalAlign ); + scrollingTextActor.RegisterProperty( "uGap", mWrapGap ); + mScrollDeltaIndex = scrollingTextActor.RegisterProperty( "uDelta", 0.0f ); - float scrollAmount = std::max( offScreenSize.width + mWrapGap, controlSize.width ); + float scrollAmount = std::max( textNaturalSize.width + mWrapGap, controlSize.width ); float scrollDuration = scrollAmount / mScrollSpeed; if ( direction ) { - scrollAmount = -scrollAmount; // reverse direction of scrollung + scrollAmount = -scrollAmount; // reverse direction of scrolling } - StartScrolling( scrollAmount, scrollDuration, remainedLoop ); + StartScrolling( scrollingTextActor, scrollAmount, scrollDuration, remainedLoop ); mScrollAnimation.SetCurrentProgress(animationProgress); } void TextScroller::AutoScrollAnimationFinished( Dali::Animation& animation ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::AutoScrollAnimationFinished\n" ); - CleanUp(); mScrollerInterface.ScrollingFinished(); + + // Revert to the original shader and texture after scrolling + mRenderer.SetShader(mShader); + if ( mTextureSet ) + { + mRenderer.SetTextures( mTextureSet ); + } } -void TextScroller::StartScrolling( float scrollAmount, float scrollDuration, int loopCount ) +void TextScroller::StartScrolling( Actor scrollingTextActor, float scrollAmount, float scrollDuration, int loopCount ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::StartScrolling scrollAmount[%f] scrollDuration[%f], loop[%d] speed[%d]\n", scrollAmount, scrollDuration, loopCount, mScrollSpeed ); mScrollAnimation = Animation::New( scrollDuration ); - mScrollAnimation.AnimateTo( Property( mScrollingTextActor, mScrollDeltaIndex ), scrollAmount, TimePeriod( mLoopDelay, scrollDuration ) ); + mScrollAnimation.AnimateTo( Property( scrollingTextActor, mScrollDeltaIndex ), scrollAmount, TimePeriod( mLoopDelay, scrollDuration ) ); mScrollAnimation.SetEndAction( Animation::Discard ); mScrollAnimation.SetLoopCount( loopCount ); mScrollAnimation.FinishedSignal().Connect( this, &TextScroller::AutoScrollAnimationFinished ); mScrollAnimation.Play(); } -void TextScroller::CleanUp() -{ - if ( Stage::IsInstalled() ) - { - Stage stage = Stage::GetCurrent(); - RenderTaskList taskList = stage.GetRenderTaskList(); - UnparentAndReset( mScrollingTextActor ); - UnparentAndReset( mOffscreenCameraActor ); - taskList.RemoveTask( mRenderTask ); - } -} - } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/text-scroller.h b/dali-toolkit/internal/text/text-scroller.h index 2d611bb..b8dc10f 100644 --- a/dali-toolkit/internal/text/text-scroller.h +++ b/dali-toolkit/internal/text/text-scroller.h @@ -22,6 +22,7 @@ #include #include #include +#include // INTERNAL INCLUDES #include @@ -60,14 +61,16 @@ public: /** * @brief Set parameters relating to source required for scrolling * - * @param[in] sourceActor source actor to be scrolled + * @param[in] scrollingTextActor actor containing the text to be scrolled + * @param[in] renderer renderer to render the text + * @param[in] textureSet texture of the text to be scrolled * @param[in] controlSize size of the control to scroll within - * @param[in] offScreenSize size of the sourceActor + * @param[in] textNaturalSize natural size of the text * @param[in] direction text direction true for right to left text - * @param[in] alignmentOffset alignment of source text - * + * @param[in] horizontalAlignment horizontal alignment of the text + * @param[in] verticalAlignment vertical alignment of the text */ - void SetParameters( Actor sourceActor, const Size& controlSize, const Size& offScreenSize, CharacterDirection direction, float alignmentOffset, Layout::HorizontalAlignment horizontalAlignment ); + void SetParameters( Actor scrollingTextActor, Dali::Renderer renderer, TextureSet textureSet, const Size& controlSize, const Size& offScreenSize, CharacterDirection direction, Layout::HorizontalAlignment horizontalAlignment, Layout::VerticalAlignment verticalAlignment ); /** * @brief Set the gap distance to elapse before the text wraps around @@ -134,18 +137,6 @@ public: */ DevelTextLabel::AutoScrollStopMode::Type GetStopMode() const; - /** - * @brief Get the camera used to look at source, should be added to the parent of target actor. - * @return camera Actor - */ - Actor GetSourceCamera() const; - - /** - * @brief Get the resulting scrolling text actor, add to target actor which will show scrolling text - * @return mesh Actor - */ - Actor GetScrollingText() const; - private: // Implementation /** @@ -172,25 +163,21 @@ private: // Implementation /** * @brief variables required to set up scrolling animation + * @param[in] scrollingTextActor actor that shows scrolling text * @param[in] scrollAmount distance to animate text for the given duration * @param[in] scrollDuration duration of aninmation * @param[in] loopCount number of times to loop the scrolling text */ - void StartScrolling( float scrollAmount, float scrollDuration, int loopCount ); - - /** - * @brief When scrolling ended, the actors are cleaned up so no longer staged. - */ - void CleanUp(); + void StartScrolling( Actor scrollingTextActor, float scrollAmount, float scrollDuration, int loopCount ); private: - RenderTask mRenderTask; // Renders full text to a FrameBuffer which is then scrolled. - CameraActor mOffscreenCameraActor; // Camera used by render task - Actor mScrollingTextActor; // Actor used to show scrolling text ScrollerInterface& mScrollerInterface; // Interface implemented by control that requires scrolling Property::Index mScrollDeltaIndex; // Property used by shader to represent distance to scroll Animation mScrollAnimation; // Animation used to update the mScrollDeltaIndex + Dali::Renderer mRenderer; // Renderer used to render the text + Shader mShader; // Shader originally used by the renderer while not scrolling + TextureSet mTextureSet; // Texture originally used by the renderer while not scrolling int mScrollSpeed; ///< Speed which text should automatically scroll at int mLoopCount; ///< Number of time the text should scroll diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index 754b06d..9e8d0be 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -384,7 +384,7 @@ Length View::GetNumberOfUnderlineRuns() const { if( mImpl->mVisualModel ) { - return mImpl->mVisualModel->mUnderlineRuns.Count(); + return mImpl->mVisualModel->GetNumberOfUnderlineRuns(); } return 0u; diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp old mode 100644 new mode 100755 index 2ee0bab..3e3f2d6 --- a/dali-toolkit/internal/text/visual-model-impl.cpp +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -350,6 +350,11 @@ void VisualModel::SetUnderlineColor( const Vector4& color ) mUnderlineColorSet = true; } +void VisualModel::SetOutlineColor( const Vector4& color ) +{ + mOutlineColor = color; +} + void VisualModel::SetUnderlineEnabled( bool enabled ) { mUnderlineEnabled = enabled; @@ -360,6 +365,11 @@ void VisualModel::SetUnderlineHeight( float height ) mUnderlineHeight = height; } +void VisualModel::SetOutlineWidth( float width ) +{ + mOutlineWidth = width; +} + const Vector4& VisualModel::GetTextColor() const { return mTextColor; @@ -380,6 +390,11 @@ const Vector4& VisualModel::GetUnderlineColor() const return mUnderlineColor; } +const Vector4& VisualModel::GetOutlineColor() const +{ + return mOutlineColor; +} + bool VisualModel::IsUnderlineEnabled() const { return mUnderlineEnabled; @@ -390,6 +405,16 @@ float VisualModel::GetUnderlineHeight() const return mUnderlineHeight; } +float VisualModel::GetOutlineWidth() const +{ + return mOutlineWidth; +} + +Length VisualModel::GetNumberOfUnderlineRuns() const +{ + return mUnderlineRuns.Count(); +} + void VisualModel::ClearCaches() { mCachedLineIndex = 0u; @@ -410,9 +435,11 @@ VisualModel::VisualModel() mTextColor( Color::BLACK ), mShadowColor( Color::BLACK ), mUnderlineColor( Color::BLACK ), + mOutlineColor( Color::WHITE ), mControlSize(), mShadowOffset(), mUnderlineHeight( 0.0f ), + mOutlineWidth( 0.0f ), mNaturalSize(), mLayoutSize(), mCachedLineIndex( 0u ), diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h old mode 100644 new mode 100755 index 0874c05..ea888cd --- a/dali-toolkit/internal/text/visual-model-impl.h +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -280,6 +280,41 @@ public: */ float GetUnderlineHeight() const; + /** + * @brief Retrieves the number of underline runs. + * + * @return The number of underline runs. + */ + Length GetNumberOfUnderlineRuns() const; + + /** + * @brief Set the outline color. + * + * @param[in] color color of outline. + */ + void SetOutlineColor( const Vector4& color ); + + /** + * @brief Retrieve the outline color. + * + * @return The outline color. + */ + const Vector4& GetOutlineColor() const; + + /** + * @brief Set the outline width + * + * @param[in] width The width in pixels of the outline, 0 indicates no outline + */ + void SetOutlineWidth( float width ); + + /** + * @brief Retrieves the width of an outline + * + * @return The width of the outline. + */ + float GetOutlineWidth() const; + protected: /** @@ -316,9 +351,11 @@ public: Vector4 mTextColor; ///< The text color Vector4 mShadowColor; ///< Color of drop shadow Vector4 mUnderlineColor; ///< Color of underline + Vector4 mOutlineColor; ///< Color of outline Size mControlSize; ///< The size of the UI control. Vector2 mShadowOffset; ///< Offset for drop shadow, 0 indicates no shadow float mUnderlineHeight; ///< Fixed height for underline to override font metrics. + float mOutlineWidth; ///< Width of outline. private: diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp index 7c933ce..acaede8 100644 --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp @@ -274,6 +274,7 @@ void AnimatedImageVisual::DoSetProperty( Property::Index index, { mWrapModeU = Dali::WrapMode::Type::DEFAULT; } + break; } case Toolkit::ImageVisual::Property::WRAP_MODE_V: { @@ -477,7 +478,7 @@ TextureSet AnimatedImageVisual::PrepareAnimatedGifImage() // load from image file std::vector pixelDataList; - if( mImageUrl.IsLocal() ) + if( mImageUrl.IsLocalResource() ) { if( Dali::LoadAnimatedGifFromFile( mImageUrl.GetUrl().c_str() , pixelDataList, mFrameDelayContainer ) ) { diff --git a/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h b/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h index b30a11a..4c59447 100644 --- a/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h +++ b/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h @@ -19,7 +19,7 @@ // EXTERNAL INCLUDES #include -#include +#include namespace Dali { diff --git a/dali-toolkit/internal/visuals/animated-image/image-cache.h b/dali-toolkit/internal/visuals/animated-image/image-cache.h index 5061d76..12e89e9 100644 --- a/dali-toolkit/internal/visuals/animated-image/image-cache.h +++ b/dali-toolkit/internal/visuals/animated-image/image-cache.h @@ -19,7 +19,7 @@ // EXTERNAL INCLUDES #include -#include +#include namespace Dali { diff --git a/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.h b/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.h index 6f5607c..1aed961 100644 --- a/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.h +++ b/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.h @@ -21,7 +21,7 @@ #include #include -#include +#include namespace Dali { diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index dcb222d..ee0042a 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #include @@ -554,7 +554,7 @@ void ImageVisual::GetNaturalSize( Vector2& naturalSize ) } else if( mImageUrl.IsValid() ) { - if( mImageUrl.GetLocation() == VisualUrl::LOCAL ) + if( mImageUrl.GetProtocolType() == VisualUrl::LOCAL ) { ImageDimensions dimensions = Dali::GetClosestImageSize( mImageUrl.GetUrl() ); @@ -787,7 +787,7 @@ void ImageVisual::InitializeRenderer() { mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED; - if( ! mImpl->mCustomShader && mImageUrl.GetLocation() == VisualUrl::LOCAL ) + if( ! mImpl->mCustomShader && mImageUrl.GetProtocolType() == VisualUrl::LOCAL ) { bool defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE; diff --git a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp index 9235545..7be7301 100755 --- a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp +++ b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp @@ -264,7 +264,7 @@ void NPatchVisual::GetNaturalSize( Vector2& naturalSize ) naturalSize.y = 0u; // load now if not already loaded - if( NPatchLoader::UNINITIALIZED_ID == mId && mImageUrl.IsLocal() ) + if( NPatchLoader::UNINITIALIZED_ID == mId && mImageUrl.IsLocalResource() ) { mId = mLoader.Load( mImageUrl.GetUrl(), mBorder ); } @@ -304,7 +304,7 @@ void NPatchVisual::DoSetProperties( const Property::Map& propertyMap ) void NPatchVisual::DoSetOnStage( Actor& actor ) { // load when first go on stage - if( NPatchLoader::UNINITIALIZED_ID == mId && mImageUrl.IsLocal() ) + if( NPatchLoader::UNINITIALIZED_ID == mId && mImageUrl.IsLocalResource() ) { mId = mLoader.Load( mImageUrl.GetUrl(), mBorder ); } diff --git a/dali-toolkit/internal/visuals/svg/svg-visual.cpp b/dali-toolkit/internal/visuals/svg/svg-visual.cpp index 1e95223..ef2fdae 100644 --- a/dali-toolkit/internal/visuals/svg/svg-visual.cpp +++ b/dali-toolkit/internal/visuals/svg/svg-visual.cpp @@ -155,7 +155,7 @@ void SvgVisual::DoCreateInstancePropertyMap( Property::Map& map ) const void SvgVisual::ParseFromUrl( const VisualUrl& imageUrl ) { mImageUrl = imageUrl; - if( mImageUrl.IsLocal() ) + if( mImageUrl.IsLocalResource() ) { Vector2 dpi = Stage::GetCurrent().GetDpi(); float meanDpi = (dpi.height + dpi.width) * 0.5f; diff --git a/dali-toolkit/internal/visuals/text/text-visual.cpp b/dali-toolkit/internal/visuals/text/text-visual.cpp old mode 100644 new mode 100755 index 7ce455e..4031f94 --- a/dali-toolkit/internal/visuals/text/text-visual.cpp +++ b/dali-toolkit/internal/visuals/text/text-visual.cpp @@ -18,6 +18,10 @@ // CLASS HEADER #include +// EXTERNAL INCLUDES +#include +#include + // INTERNAL HEADER #include #include @@ -27,6 +31,8 @@ #include #include #include +#include +#include namespace Dali { @@ -49,6 +55,8 @@ const char * const HORIZONTAL_ALIGNMENT_PROPERTY( "horizontalAlignment" ); const char * const VERTICAL_ALIGNMENT_PROPERTY( "verticalAlignment" ); const char * const TEXT_COLOR_PROPERTY( "textColor" ); const char * const ENABLE_MARKUP_PROPERTY( "enableMarkup" ); +const char * const SHADOW_PROPERTY( "shadow" ); +const char * const UNDERLINE_PROPERTY( "underline" ); const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] = { @@ -74,7 +82,11 @@ std::string GetHorizontalAlignment( Toolkit::Text::Layout::HorizontalAlignment a HORIZONTAL_ALIGNMENT_STRING_TABLE, HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ); - return std::string( name ); + if( name ) + { + return std::string( name ); + } + return std::string(); } std::string GetVerticalAlignment( Toolkit::Text::Layout::VerticalAlignment alignment ) @@ -83,21 +95,25 @@ std::string GetVerticalAlignment( Toolkit::Text::Layout::VerticalAlignment align VERTICAL_ALIGNMENT_STRING_TABLE, VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ); - return std::string( name ); + if( name ) + { + return std::string( name ); + } + return std::string(); } const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( attribute mediump vec2 aPosition;\n uniform mediump mat4 uMvpMatrix;\n uniform mediump vec3 uSize;\n - uniform mediump vec4 pixelArea; + uniform mediump vec4 pixelArea;\n uniform mediump mat4 uModelMatrix;\n uniform mediump mat4 uViewMatrix;\n uniform mediump mat4 uProjection;\n varying mediump vec2 vTexCoord;\n - \n + //Visual size and offset uniform mediump vec2 offset;\n uniform mediump vec2 size;\n @@ -123,19 +139,54 @@ const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( }\n ); -const char* FRAGMENT_SHADER_ATLAS_CLAMP = DALI_COMPOSE_SHADER( - varying mediump vec2 vTexCoord;\n - uniform sampler2D sTexture;\n - uniform mediump vec4 uAtlasRect;\n - uniform lowp vec4 uColor;\n - uniform lowp vec3 mixColor;\n - uniform lowp float opacity;\n - \n - void main()\n - {\n - mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );\n - gl_FragColor = texture2D( sTexture, texCoord ) * uColor * vec4( mixColor, opacity );\n - }\n +const char* FRAGMENT_SHADER_ATLAS_CLAMP_RGBA = DALI_COMPOSE_SHADER( + varying mediump vec2 vTexCoord;\n + uniform sampler2D sTexture;\n + uniform sampler2D sStyle;\n + uniform sampler2D sMask;\n + uniform lowp float uHasMultipleTextColors;\n + uniform lowp vec4 uTextColorAnimatable;\n + uniform mediump vec4 uAtlasRect;\n + uniform lowp vec4 uColor;\n + uniform lowp vec3 mixColor;\n + uniform lowp float opacity;\n + \n + void main()\n + {\n + mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );\n + mediump vec4 textTexture = texture2D( sTexture, texCoord );\n + mediump vec4 styleTexture = texture2D( sStyle, texCoord );\n + mediump vec4 maskTexture = texture2D( sMask, texCoord );\n + + // Set the color of non-transparent pixel in text to what it is animated to. + // Markup text with multiple text colors are not animated (but can be supported later on if required). + // Emoji color are not animated. + mediump vec4 textColor = textTexture * textTexture.a;\n + mediump float vstep = step( 0.0001, textColor.a );\n + textColor.rgb = mix( textColor.rgb, uTextColorAnimatable.rgb, vstep * maskTexture.a * ( 1.0 - uHasMultipleTextColors ) );\n + + // Draw the text as overlay above the style + gl_FragColor = ( textColor + styleTexture * ( 1.0 - textTexture.a ) ) * uColor * vec4( mixColor, opacity );\n + }\n +); + +const char* FRAGMENT_SHADER_ATLAS_CLAMP_L8 = DALI_COMPOSE_SHADER( + varying mediump vec2 vTexCoord;\n + uniform sampler2D sTexture;\n + uniform lowp vec4 uTextColorAnimatable;\n + uniform mediump vec4 uAtlasRect;\n + uniform lowp vec4 uColor;\n + uniform lowp vec3 mixColor;\n + uniform lowp float opacity;\n + \n + void main()\n + {\n + mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );\n + mediump float textTexture = texture2D( sTexture, texCoord ).r;\n + + // Set the color of the text to what it is animated to. + gl_FragColor = uTextColorAnimatable * textTexture * uColor * vec4( mixColor, opacity );\n + }\n ); /** @@ -188,6 +239,14 @@ Dali::Property::Index StringKeyToIndexKey( const std::string& stringKey ) { result = Toolkit::TextVisual::Property::ENABLE_MARKUP; } + else if( stringKey == SHADOW_PROPERTY ) + { + result = Toolkit::TextVisual::Property::SHADOW; + } + else if( stringKey == UNDERLINE_PROPERTY ) + { + result = Toolkit::TextVisual::Property::UNDERLINE; + } return result; } @@ -259,6 +318,12 @@ void TextVisual::DoCreatePropertyMap( Property::Map& map ) const map.Insert( Toolkit::TextVisual::Property::TEXT_COLOR, mController->GetDefaultColor() ); map.Insert( Toolkit::TextVisual::Property::ENABLE_MARKUP, mController->IsMarkupProcessorEnabled() ); + + GetShadowProperties( mController, value, Text::EffectStyle::DEFAULT ); + map.Insert( Toolkit::TextVisual::Property::SHADOW, value ); + + GetUnderlineProperties( mController, value, Text::EffectStyle::DEFAULT ); + map.Insert( Toolkit::TextVisual::Property::UNDERLINE, value ); } void TextVisual::DoCreateInstancePropertyMap( Property::Map& map ) const @@ -274,7 +339,9 @@ void TextVisual::DoCreateInstancePropertyMap( Property::Map& map ) const TextVisual::TextVisual( VisualFactoryCache& factoryCache ) : Visual::Base( factoryCache ), mController( Text::Controller::New() ), - mTypesetter( Text::Typesetter::New( mController->GetTextModel() ) ) + mTypesetter( Text::Typesetter::New( mController->GetTextModel() ) ), + mAnimatableTextColorPropertyIndex( Property::INVALID_INDEX ), + mRendererUpdateNeeded( false ) { } @@ -313,20 +380,29 @@ void TextVisual::DoSetOnStage( Actor& actor ) mControl = actor; Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); + Shader shader = GetTextShader(mFactoryCache, true); - Shader shader = mFactoryCache.GetShader( VisualFactoryCache::TEXT_SHADER ); - if( ! shader ) - { - shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP ); - shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT ); + mImpl->mRenderer = Renderer::New( geometry, shader ); + mImpl->mRenderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, Toolkit::DepthIndex::CONTENT ); + + const Vector4& defaultColor = mController->GetTextModel()->GetDefaultColor(); + Dali::Property::Index shaderTextColorIndex = mImpl->mRenderer.RegisterProperty( "uTextColorAnimatable", defaultColor ); - mFactoryCache.SaveShader( VisualFactoryCache::TEXT_SHADER, shader ); + if ( mAnimatableTextColorPropertyIndex != Property::INVALID_INDEX ) + { + // Create constraint for the animatable text's color Property with uTextColorAnimatable in the renderer. + if( shaderTextColorIndex != Property::INVALID_INDEX ) + { + Constraint constraint = Constraint::New( mImpl->mRenderer, shaderTextColorIndex, EqualToConstraint() ); + constraint.AddSource( Source( actor, mAnimatableTextColorPropertyIndex ) ); + constraint.Apply(); + } } - mImpl->mRenderer = Renderer::New( geometry, shader ); - mImpl->mRenderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, Toolkit::DepthIndex::CONTENT ); + // Renderer needs textures and to be added to control + mRendererUpdateNeeded = true; - UpdateRenderer( true ); // Renderer needs textures and to be added to control + UpdateRenderer(); } void TextVisual::DoSetOffStage( Actor& actor ) @@ -348,7 +424,7 @@ void TextVisual::DoSetOffStage( Actor& actor ) void TextVisual::OnSetTransform() { - UpdateRenderer( false ); + UpdateRenderer(); } void TextVisual::DoSetProperty( Dali::Property::Index index, const Dali::Property::Value& propertyValue ) @@ -423,10 +499,20 @@ void TextVisual::DoSetProperty( Dali::Property::Index index, const Dali::Propert } break; } + case Toolkit::TextVisual::Property::SHADOW: + { + SetShadowProperties( mController, propertyValue, Text::EffectStyle::DEFAULT ); + break; + } + case Toolkit::TextVisual::Property::UNDERLINE: + { + SetUnderlineProperties( mController, propertyValue, Text::EffectStyle::DEFAULT ); + break; + } } } -void TextVisual::UpdateRenderer( bool initializeRendererAndTexture ) +void TextVisual::UpdateRenderer() { Actor control = mControl.GetHandle(); if( !control ) @@ -463,8 +549,11 @@ void TextVisual::UpdateRenderer( bool initializeRendererAndTexture ) const Text::Controller::UpdateTextType updateTextType = mController->Relayout( relayoutSize ); - if( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType ) || initializeRendererAndTexture ) + if( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType ) + || mRendererUpdateNeeded ) { + mRendererUpdateNeeded = false; + // Removes the texture set. RemoveTextureSet(); @@ -477,39 +566,141 @@ void TextVisual::UpdateRenderer( bool initializeRendererAndTexture ) if( ( relayoutSize.width > Math::MACHINE_EPSILON_1000 ) && ( relayoutSize.height > Math::MACHINE_EPSILON_1000 ) ) { - PixelData data = mTypesetter->Render( relayoutSize ); + // Check whether it is a markup text with multiple text colors + const Vector4* const colorsBuffer = mController->GetTextModel()->GetColors(); + bool hasMultipleTextColors = ( NULL != colorsBuffer ); - Vector4 atlasRect = FULL_TEXTURE_RECT; + // Check whether the text contains any emoji + bool containsEmoji = false; + + Text::ScriptRunIndex numberOfScripts = mController->GetTextModel()->GetNumberOfScripts(); + const Text::ScriptRun* scripts = mController->GetTextModel()->GetScriptRuns(); + for ( Text::ScriptRunIndex scriptIndex = 0u; scriptIndex < numberOfScripts; scriptIndex++ ) + { + const Text::ScriptRun& scriptRun = *( scripts + scriptIndex ); + if( TextAbstraction::EMOJI == scriptRun.script ) + { + containsEmoji = true; + break; + } + } + + // Check whether the text contains any style colors (e.g. underline color, shadow color, etc.) - // Texture set not retrieved from Atlas Manager whilst pixel offset visible. + bool shadowEnabled = false; + const Vector2& shadowOffset = mController->GetTextModel()->GetShadowOffset(); + if ( fabsf( shadowOffset.x ) > Math::MACHINE_EPSILON_1 || fabsf( shadowOffset.y ) > Math::MACHINE_EPSILON_1 ) + { + shadowEnabled = true; + } + + bool outlineWidthEnabled = false; + float outlineWidth = mController->GetTextModel()->GetOutlineWidth(); + if ( outlineWidth > Math::MACHINE_EPSILON_1 ) + { + outlineWidthEnabled = true; + } + + const bool underlineEnabled = mController->GetTextModel()->IsUnderlineEnabled(); + + if ( hasMultipleTextColors || containsEmoji || shadowEnabled || underlineEnabled || outlineWidthEnabled ) + { + // Create RGBA textures if the text contains emojis or styles or multiple text colors + + // Create a texture for the text without any styles + PixelData data = mTypesetter->Render( relayoutSize, Text::Typesetter::RENDER_NO_STYLES ); + + // It may happen the image atlas can't handle a pixel data it exceeds the maximum size. + // In that case, create a texture. TODO: should tile the text. + + Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, + data.GetPixelFormat(), + data.GetWidth(), + data.GetHeight() ); + + texture.Upload( data ); - // It may happen the image atlas can't handle a pixel data it exceeds the maximum size. - // In that case, create a texture. TODO: should tile the text. + TextureSet textureSet = TextureSet::New(); + textureSet.SetTexture( 0u, texture ); - Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, - data.GetPixelFormat(), - data.GetWidth(), - data.GetHeight() ); + // Create a texture for all the text styles (without the text itself) + PixelData styleData = mTypesetter->Render( relayoutSize, Text::Typesetter::RENDER_NO_TEXT ); + + Texture styleTexture = Texture::New( Dali::TextureType::TEXTURE_2D, + styleData.GetPixelFormat(), + styleData.GetWidth(), + styleData.GetHeight() ); + + styleTexture.Upload( styleData ); + + textureSet.SetTexture( 1u, styleTexture ); + + // Create a texture as a mask to avoid color glyphs (e.g. emojis) to be affected by text color animation + PixelData maskData = mTypesetter->Render( relayoutSize, Text::Typesetter::RENDER_MASK ); + + Texture maskTexture = Texture::New( Dali::TextureType::TEXTURE_2D, + styleData.GetPixelFormat(), + styleData.GetWidth(), + styleData.GetHeight() ); + + maskTexture.Upload( maskData ); + + textureSet.SetTexture( 2u, maskTexture ); + + // Filter mode needs to be set to nearest to produce better quality while static. + Sampler sampler = Sampler::New(); + sampler.SetFilterMode( FilterMode::LINEAR, FilterMode::LINEAR ); + textureSet.SetSampler( 0u, sampler ); + textureSet.SetSampler( 1u, sampler ); + textureSet.SetSampler( 2u, sampler ); + + mImpl->mRenderer.SetTextures( textureSet ); + + Shader shader = GetTextShader(mFactoryCache, true); // RGBA shader + mImpl->mRenderer.SetShader(shader); + } + else + { + // Create L8 texture if the text contains only single text color with no emoji and no style - texture.Upload( data ); + // Create a texture for the text without any styles + PixelData data = mTypesetter->Render( relayoutSize, Text::Typesetter::RENDER_NO_STYLES, false, Pixel::L8 ); - TextureSet textureSet = TextureSet::New(); - textureSet.SetTexture( 0u, texture ); + // It may happen the image atlas can't handle a pixel data it exceeds the maximum size. + // In that case, create a texture. TODO: should tile the text. + + Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, + data.GetPixelFormat(), + data.GetWidth(), + data.GetHeight() ); + + texture.Upload( data ); + + TextureSet textureSet = TextureSet::New(); + textureSet.SetTexture( 0u, texture ); + + // Filter mode needs to be set to nearest to produce better quality while static. + Sampler sampler = Sampler::New(); + sampler.SetFilterMode( FilterMode::NEAREST, FilterMode::NEAREST ); + textureSet.SetSampler( 0u, sampler ); + + mImpl->mRenderer.SetTextures( textureSet ); + + Shader shader = GetTextShader(mFactoryCache, false); // L8 shader + mImpl->mRenderer.SetShader(shader); + } mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED; + Vector4 atlasRect = FULL_TEXTURE_RECT; mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, atlasRect ); + mImpl->mRenderer.RegisterProperty( "uHasMultipleTextColors", static_cast( hasMultipleTextColors ) ); + + mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON); //Register transform properties mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT ); - // Filter mode needs to be set to nearest to avoid blurry text. - Sampler sampler = Sampler::New(); - sampler.SetFilterMode( FilterMode::NEAREST, FilterMode::NEAREST ); - textureSet.SetSampler( 0u, sampler ); - - mImpl->mRenderer.SetTextures( textureSet ); - control.AddRenderer( mImpl->mRenderer ); // Text rendered and ready to display @@ -537,6 +728,33 @@ void TextVisual::RemoveTextureSet() } } +Shader TextVisual::GetTextShader( VisualFactoryCache& factoryCache, bool isRgbaTexture ) +{ + Shader shader; + if( isRgbaTexture ) + { + shader = factoryCache.GetShader( VisualFactoryCache::TEXT_SHADER_RGBA ); + if( !shader ) + { + shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP_RGBA ); + shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT ); + factoryCache.SaveShader( VisualFactoryCache::TEXT_SHADER_RGBA, shader ); + } + } + else + { + shader = factoryCache.GetShader( VisualFactoryCache::TEXT_SHADER_L8 ); + if( !shader ) + { + shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP_L8 ); + shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT ); + factoryCache.SaveShader( VisualFactoryCache::TEXT_SHADER_L8, shader ); + } + } + + return shader; +} + } // namespace Internal } // namespace Toolkit diff --git a/dali-toolkit/internal/visuals/text/text-visual.h b/dali-toolkit/internal/visuals/text/text-visual.h index 8222276..31353b9 100644 --- a/dali-toolkit/internal/visuals/text/text-visual.h +++ b/dali-toolkit/internal/visuals/text/text-visual.h @@ -18,6 +18,9 @@ * */ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include #include @@ -81,6 +84,35 @@ public: */ static void ConvertStringKeysToIndexKeys( Property::Map& propertyMap ); + /** + * @brief Retrieve the text's controller. + * @param[in] visual The text visual. + * @return The text controller + */ + static Text::ControllerPtr GetController( Toolkit::Visual::Base visual ) + { + return GetVisualObject( visual ).mController; + }; + + /** + * @brief Set the index of the animatable text color property. + * @param[in] visual The text visual. + * @param[in] animatablePropertyIndex The index of the animatable property + */ + static void SetAnimatableTextColorProperty( Toolkit::Visual::Base visual, Property::Index animatablePropertyIndex ) + { + GetVisualObject( visual ).mAnimatableTextColorPropertyIndex = animatablePropertyIndex; + }; + + /** + * @brief Set the flag to trigger the textures to be initialized and renderer to be added to the control. + * @param[in] visual The text visual. + */ + static void EnableRendererUpdate( Toolkit::Visual::Base visual ) + { + GetVisualObject( visual ).mRendererUpdateNeeded = true; + }; + public: // from Visual::Base /** @@ -151,19 +183,37 @@ private: /** * @brief Updates the text's renderer. - * @param[in] initializeRendererAndTexture Set flag to true to initialize textures and add renderer to control. */ - void UpdateRenderer( bool initializeRendererAndTexture ); + void UpdateRenderer(); /** * @brief Removes the texture set from the renderer. */ void RemoveTextureSet(); + /** + * Get the text rendering shader. + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @param[in] isRgbaTexture Whether the texture is in RGBA format. + */ + Shader GetTextShader( VisualFactoryCache& factoryCache, bool isRgbaTexture ); + + /** + * @brief Retrieve the text's controller. + * @param[in] visual The text visual. + * @return The text controller + */ + static TextVisual& GetVisualObject( Toolkit::Visual::Base visual ) + { + return static_cast( visual.GetBaseObject() ); + }; + private: - Text::ControllerPtr mController; ///< The text's controller. - Text::TypesetterPtr mTypesetter; ///< The text's typesetter. - WeakHandle mControl; ///< The control where the renderer is added. + Text::ControllerPtr mController; ///< The text's controller. + Text::TypesetterPtr mTypesetter; ///< The text's typesetter. + WeakHandle mControl; ///< The control where the renderer is added. + Property::Index mAnimatableTextColorPropertyIndex; ///< The index of animatable text color property registered by the control. + bool mRendererUpdateNeeded:1; ///< The flag to indicate whether the renderer needs to be updated. }; } // namespace Internal diff --git a/dali-toolkit/internal/visuals/texture-manager.cpp b/dali-toolkit/internal/visuals/texture-manager-impl.cpp similarity index 95% rename from dali-toolkit/internal/visuals/texture-manager.cpp rename to dali-toolkit/internal/visuals/texture-manager-impl.cpp index 9468935..f074087 100644 --- a/dali-toolkit/internal/visuals/texture-manager.cpp +++ b/dali-toolkit/internal/visuals/texture-manager-impl.cpp @@ -16,10 +16,11 @@ */ // CLASS HEADER -#include "texture-manager.h" +#include // EXTERNAL HEADERS #include +#include #include #include #include @@ -85,9 +86,9 @@ const int INVALID_CACHE_INDEX( -1 ); ///< Invalid Cache index TextureManager::TextureManager() -: mCurrentTextureId( 0 ), - mAsyncLocalLoaders( GetNumberOfLocalLoaderThreads(), [&]() { return AsyncLoadingHelper(*this); } ), - mAsyncRemoteLoaders( GetNumberOfRemoteLoaderThreads(), [&]() { return AsyncLoadingHelper(*this); } ) +: mAsyncLocalLoaders( GetNumberOfLocalLoaderThreads(), [&]() { return AsyncLoadingHelper(*this); } ), + mAsyncRemoteLoaders( GetNumberOfRemoteLoaderThreads(), [&]() { return AsyncLoadingHelper(*this); } ), + mCurrentTextureId( 0 ) { } @@ -309,6 +310,43 @@ TextureSet TextureManager::GetTextureSet( TextureId textureId ) return textureSet; } +std::string TextureManager::AddExternalTexture( TextureSet& textureSet ) +{ + TextureManager::ExternalTextureInfo info; + info.textureId = GenerateUniqueTextureId(); + info.textureSet = textureSet; + mExternalTextures.emplace_back( info ); + return VisualUrl::CreateTextureUrl( std::to_string( info.textureId ) ); +} + +TextureSet TextureManager::RemoveExternalTexture( const std::string& url ) +{ + if( url.size() > 0u ) + { + // get the location from the Url + VisualUrl parseUrl( url ); + if( VisualUrl::TEXTURE == parseUrl.GetProtocolType() ) + { + std::string location = parseUrl.GetLocation(); + if( location.size() > 0u ) + { + TextureId id = std::stoi( location ); + const auto end = mExternalTextures.end(); + for( auto iter = mExternalTextures.begin(); iter != end; ++iter ) + { + if( iter->textureId == id ) + { + auto textureSet = iter->textureSet; + mExternalTextures.erase( iter ); + return textureSet; + } + } + } + } + } + return TextureSet(); +} + bool TextureManager::LoadTexture( TextureInfo& textureInfo ) { bool success = true; @@ -319,7 +357,7 @@ bool TextureManager::LoadTexture( TextureInfo& textureInfo ) if( !textureInfo.loadSynchronously ) { - auto& loadersContainer = textureInfo.url.IsLocal() ? mAsyncLocalLoaders : mAsyncRemoteLoaders; + auto& loadersContainer = textureInfo.url.IsLocalResource() ? mAsyncLocalLoaders : mAsyncRemoteLoaders; auto loadingHelperIt = loadersContainer.GetNext(); DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End()); loadingHelperIt->Load(textureInfo.textureId, textureInfo.url, diff --git a/dali-toolkit/internal/visuals/texture-manager.h b/dali-toolkit/internal/visuals/texture-manager-impl.h similarity index 94% rename from dali-toolkit/internal/visuals/texture-manager.h rename to dali-toolkit/internal/visuals/texture-manager-impl.h index 090846e..117bd1f 100644 --- a/dali-toolkit/internal/visuals/texture-manager.h +++ b/dali-toolkit/internal/visuals/texture-manager-impl.h @@ -1,5 +1,5 @@ -#ifndef DALI_TOOLKIT_TEXTURE_MANAGER_H -#define DALI_TOOLKIT_TEXTURE_MANAGER_H +#ifndef DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H +#define DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H /* * Copyright (c) 2017 Samsung Electronics Co., Ltd. @@ -46,8 +46,6 @@ namespace Toolkit namespace Internal { -class MaskTextureObserver; - /** * The TextureManager provides a common Image loading API for Visuals. * @@ -212,6 +210,20 @@ public: */ TextureSet GetTextureSet( TextureId textureId ); + /** + * Adds an external texture to the texture manager + * @param[in] texture The texture to add + * @return string containing the URL for the texture + */ + std::string AddExternalTexture( TextureSet& texture ); + + /** + * Removes an external texture from texture manager + * @param[in] url The string containing the texture to remove + * @return handle to the texture + */ + TextureSet RemoveExternalTexture( const std::string& url ); + private: /** @@ -547,6 +559,12 @@ private: AsyncLoadingInfoContainerType mLoadingInfoContainer; }; + struct ExternalTextureInfo + { + TextureId textureId; + TextureSet textureSet; + }; + private: /** @@ -568,12 +586,13 @@ private: private: // Member Variables: - AtlasInfoContainerType mAtlasContainer; ///< Used to manage Atlas creation and destruction - TextureInfoContainerType mTextureInfoContainer; ///< Used to manage the life-cycle and caching of Textures - TextureId mCurrentTextureId; ///< The current value used for the unique Texture Id generation + AtlasInfoContainerType mAtlasContainer; ///< Used to manage Atlas creation and destruction + TextureInfoContainerType mTextureInfoContainer; ///< Used to manage the life-cycle and caching of Textures + RoundRobinContainerView< AsyncLoadingHelper > mAsyncLocalLoaders; ///< The Asynchronous image loaders used to provide all local async loads + RoundRobinContainerView< AsyncLoadingHelper > mAsyncRemoteLoaders; ///< The Asynchronous image loaders used to provide all remote async loads + std::vector< ExternalTextureInfo > mExternalTextures; ///< Externally provided textures + TextureId mCurrentTextureId; ///< The current value used for the unique Texture Id generation - RoundRobinContainerView mAsyncLocalLoaders; ///< The Asynchronous image loaders used to provide all local async loads - RoundRobinContainerView mAsyncRemoteLoaders; ///< The Asynchronous image loaders used to provide all remote async loads }; @@ -583,4 +602,4 @@ private: // Member Variables: } // namespace Dali -#endif // DALI_TOOLKIT_TEXTURE_MANAGER_H +#endif // DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H diff --git a/dali-toolkit/internal/visuals/visual-factory-cache.h b/dali-toolkit/internal/visuals/visual-factory-cache.h index cc68e0f..aac15c7 100644 --- a/dali-toolkit/internal/visuals/visual-factory-cache.h +++ b/dali-toolkit/internal/visuals/visual-factory-cache.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_VISUAL_FACTORY_CACHE_H /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,7 @@ // INTERNAL INCLUDES #include #include -#include +#include namespace Dali { @@ -69,7 +69,8 @@ public: IMAGE_SHADER_ATLAS_CUSTOM_WRAP, NINE_PATCH_SHADER, SVG_SHADER, - TEXT_SHADER, + TEXT_SHADER_RGBA, + TEXT_SHADER_L8, WIREFRAME_SHADER, SHADER_TYPE_MAX = WIREFRAME_SHADER }; diff --git a/dali-toolkit/internal/visuals/visual-factory-impl.cpp b/dali-toolkit/internal/visuals/visual-factory-impl.cpp index 469ead5..3aef5bc 100644 --- a/dali-toolkit/internal/visuals/visual-factory-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-factory-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -316,6 +316,15 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const std::string& url, Image return Toolkit::Visual::Base( visualPtr.Get() ); } +Internal::TextureManager& VisualFactory::GetTextureManager() +{ + if( !mFactoryCache ) + { + mFactoryCache = new VisualFactoryCache(); + } + return mFactoryCache->GetTextureManager(); +} + } // namespace Internal } // namespace Toolkit diff --git a/dali-toolkit/internal/visuals/visual-factory-impl.h b/dali-toolkit/internal/visuals/visual-factory-impl.h index 030512e..257b03c 100644 --- a/dali-toolkit/internal/visuals/visual-factory-impl.h +++ b/dali-toolkit/internal/visuals/visual-factory-impl.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_VISUAL_FACTORY_IMPL_H /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -66,6 +66,11 @@ public: */ Toolkit::Visual::Base CreateVisual( const std::string& image, ImageDimensions size ); + /** + * @return the reference to texture manager + */ + Internal::TextureManager& GetTextureManager(); + protected: /** diff --git a/dali-toolkit/internal/visuals/visual-url.cpp b/dali-toolkit/internal/visuals/visual-url.cpp index c3c675d..907b428 100644 --- a/dali-toolkit/internal/visuals/visual-url.cpp +++ b/dali-toolkit/internal/visuals/visual-url.cpp @@ -30,54 +30,59 @@ namespace Internal namespace { -VisualUrl::Location ResolveLocation( const std::string& url) +VisualUrl::ProtocolType ResolveLocation( const std::string& url ) { - const char FTP[] = { 'f', 't', 'p', ':', '/', '/' }; - const char SSH[] = { 's', 's', 'h', ':', '/', '/' }; - const char HTTP[] = { 'h', 't', 't', 'p', ':', '/', '/' }; - const char HTTPS[] = { 'h', 't', 't', 'p', 's', ':', '/', '/' }; - - const int MATCH_FTP = 0x01; - const int MATCH_SSH = 0x02; - const int MATCH_HTTP = 0x04; - const int MATCH_HTTPS = 0x08; - const char* urlCStr = url.c_str(); - if( url.size() > 6 ) + const uint32_t length = url.size(); + if( ( length > 7 ) && urlCStr[5] == ':' && urlCStr[6] == '/' && urlCStr[7] == '/' ) + { + // https:// + if( ( 'h' == tolower( urlCStr[0] ) )&& + ( 't' == tolower( urlCStr[1] ) )&& + ( 't' == tolower( urlCStr[2] ) )&& + ( 'p' == tolower( urlCStr[3] ) )&& + ( 's' == tolower( urlCStr[4] ) ) ) + { + return VisualUrl::REMOTE; + } + } + else if( ( length > 6 ) && urlCStr[4] == ':' && urlCStr[5] == '/' && urlCStr[6] == '/' ) + { + // http:// or dali:// + const char hOrd = tolower( urlCStr[0] ); + const char tOra = tolower( urlCStr[1] ); + const char tOrl = tolower( urlCStr[2] ); + const char pOri = tolower( urlCStr[3] ); + if( ( 'h' == hOrd )&& + ( 't' == tOra )&& + ( 't' == tOrl )&& + ( 'p' == pOri ) ) + { + return VisualUrl::REMOTE; + } + if( ( 'd' == hOrd )&& + ( 'a' == tOra )&& + ( 'l' == tOrl )&& + ( 'i' == pOri ) ) + { + return VisualUrl::TEXTURE; + } + } + else if( ( length > 5 ) && urlCStr[3] == ':' && urlCStr[4] == '/' && urlCStr[5] == '/' ) { - if( urlCStr[3] == ':' || urlCStr[4] == ':' || urlCStr[5] == ':' ) + // ftp:// or ssh:// + const char fOrS = tolower( urlCStr[0] ); + if( ( 'f' == fOrS )||( 's' == fOrS ) ) { - int flags = 0x0F; - for( unsigned int i=0; i < sizeof(HTTPS); ++i ) + const char tOrs = tolower( urlCStr[1] ); + if( ( 't' == tOrs )||( 's' == tOrs ) ) { - char c = tolower( urlCStr[i] ); - if( i < sizeof(FTP) && (flags & MATCH_FTP) && c != FTP[i] ) - { - flags &= ~MATCH_FTP; - } - if( i < sizeof(SSH) && (flags & MATCH_SSH) && c != SSH[i] ) - { - flags &= ~MATCH_SSH; - } - if( i < sizeof(HTTP) && (flags & MATCH_HTTP) && c != HTTP[i] ) - { - flags &= ~MATCH_HTTP; - } - if( i < sizeof(HTTPS) && (flags & MATCH_HTTPS) && c != HTTPS[i] ) + const char pOrh = tolower( urlCStr[2] ); + if( ( 'p' == pOrh )||( 'h' == pOrh ) ) { - flags &= ~MATCH_HTTPS; - } - - if( (flags & (MATCH_FTP | MATCH_SSH | MATCH_HTTP | MATCH_HTTPS )) == 0 ) - { - break; + return VisualUrl::REMOTE; } } - - if( flags ) - { - return VisualUrl::REMOTE; - } } } return VisualUrl::LOCAL; @@ -99,9 +104,9 @@ VisualUrl::Type ResolveType( const std::string& url ) int index = count; while( --index >= 0 ) { - const char currentChar = url[ index ]; + const char currentChar = tolower( url[ index ] ); const std::size_t offsetFromEnd = count - index - 1u; - if( ( offsetFromEnd < sizeof(SVG) )&&( tolower( currentChar ) == SVG[ offsetFromEnd ] ) ) + if( ( offsetFromEnd < sizeof(SVG) )&&( currentChar == SVG[ offsetFromEnd ] ) ) { // early out if SVG as can't be used in N patch for now if( ++svgScore == sizeof(SVG) ) @@ -109,9 +114,9 @@ VisualUrl::Type ResolveType( const std::string& url ) return VisualUrl::SVG; } } - if( ( offsetFromEnd < sizeof(GIF) )&&( tolower( currentChar ) == GIF[ offsetFromEnd ] ) ) + if( ( offsetFromEnd < sizeof(GIF) )&&( currentChar == GIF[ offsetFromEnd ] ) ) { - // early out if GIF + // early out if GIF as can't be used in N patch for now if( ++gifScore == sizeof(GIF) ) { return VisualUrl::GIF; @@ -178,7 +183,11 @@ VisualUrl::VisualUrl( const std::string& url ) if( ! url.empty() ) { mLocation = ResolveLocation( url ); - mType = ResolveType( url ); + if( VisualUrl::TEXTURE != mLocation ) + { + // TEXTURE location url doesn't need type resolving, REGULAR_IMAGE is fine + mType = ResolveType( url ); + } } } @@ -210,7 +219,7 @@ VisualUrl::Type VisualUrl::GetType() const return mType; } -VisualUrl::Location VisualUrl::GetLocation() const +VisualUrl::ProtocolType VisualUrl::GetProtocolType() const { return mLocation; } @@ -220,13 +229,28 @@ bool VisualUrl::IsValid() const return mUrl.size() > 0u; } -bool VisualUrl::IsLocal() const +bool VisualUrl::IsLocalResource() const { return mLocation == VisualUrl::LOCAL; } +std::string VisualUrl::GetLocation() +{ + const auto location = mUrl.find( "://" ); + if( std::string::npos != location ) + { + return mUrl.substr( location + 3u ); // 3 characters forwards from the start of :// + } + return mUrl; +} +std::string VisualUrl::CreateTextureUrl( const std::string& location ) +{ + return "dali://" + location; +} } // Internal + } // Toolkit + } // Dali diff --git a/dali-toolkit/internal/visuals/visual-url.h b/dali-toolkit/internal/visuals/visual-url.h index d9ed48a..b261813 100644 --- a/dali-toolkit/internal/visuals/visual-url.h +++ b/dali-toolkit/internal/visuals/visual-url.h @@ -43,10 +43,11 @@ public: GIF }; - enum Location + enum ProtocolType { - LOCAL, - REMOTE + LOCAL, ///< file in local file system + TEXTURE, ///< texture uploaded to texture manager + REMOTE ///< remote image }; /** @@ -90,7 +91,7 @@ public: * Is the URL is local to the device, or remote? * @return the location of the resource */ - Location GetLocation() const; + ProtocolType GetProtocolType() const; /** * Is the URL valid? @@ -99,14 +100,26 @@ public: bool IsValid() const; /** - * @return true if the location is LOCAL + * @return true if the location is LOCAL, i.e. is loadable from local file system */ - bool IsLocal() const; + bool IsLocalResource() const; + + /** + * @return the location part of the url + */ + std::string GetLocation(); + + /** + * Helper to create a URL of type TEXTURE + * @param location the location of the texture + * @return the Url + */ + static std::string CreateTextureUrl( const std::string& location ); private: std::string mUrl; Type mType; - Location mLocation; + ProtocolType mLocation; }; diff --git a/dali-toolkit/public-api/controls/text-controls/text-label.h b/dali-toolkit/public-api/controls/text-controls/text-label.h index 5674716..df0abce 100644 --- a/dali-toolkit/public-api/controls/text-controls/text-label.h +++ b/dali-toolkit/public-api/controls/text-controls/text-label.h @@ -90,6 +90,7 @@ public: enum { /** + * DEPRECATED_1_2.53 No longer be supported and will be ignored. * @brief The type of rendering e.g. bitmap-based. * @details name "renderingBackend", type INT, default RENDERING_SHARED_ATLAS. * @SINCE_1_0.0 diff --git a/dali-toolkit/public-api/dali-toolkit-version.cpp b/dali-toolkit/public-api/dali-toolkit-version.cpp index 8417ead..1edcdb5 100644 --- a/dali-toolkit/public-api/dali-toolkit-version.cpp +++ b/dali-toolkit/public-api/dali-toolkit-version.cpp @@ -31,7 +31,7 @@ namespace Toolkit const unsigned int TOOLKIT_MAJOR_VERSION = 1; const unsigned int TOOLKIT_MINOR_VERSION = 2; -const unsigned int TOOLKIT_MICRO_VERSION = 56; +const unsigned int TOOLKIT_MICRO_VERSION = 58; const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index b46e4ff..006c501 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -1,6 +1,6 @@ Name: dali-toolkit Summary: Dali 3D engine Toolkit -Version: 1.2.56 +Version: 1.2.58 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT @@ -295,22 +295,37 @@ popd ############################## %preun resources_480x800 -pushd %{dali_toolkit_style_files} -mv images ./480x800 -mv dali-toolkit-default-theme.json ./480x800 -popd +case "$1" in + 0) + %preun resources_480x800 + pushd %{dali_toolkit_style_files} + mv images ./480x800 + mv dali-toolkit-default-theme.json ./480x800 + popd + ;; +esac %preun resources_720x1280 -pushd %{dali_toolkit_style_files} -mv images ./720x1280 -mv dali-toolkit-default-theme.json ./720x1280 -popd +case "$1" in + 0) + %preun resources_720x1280 + pushd %{dali_toolkit_style_files} + mv images ./720x1280 + mv dali-toolkit-default-theme.json ./720x1280 + popd + ;; +esac %preun resources_1920x1080 -pushd %{dali_toolkit_style_files} -mv images ./1920x1080 -mv dali-toolkit-default-theme.json ./1920x1080 -popd +case "$1" in + 0) + %preun resources_1920x1080 + pushd %{dali_toolkit_style_files} + mv images ./1920x1080 + mv dali-toolkit-default-theme.json ./1920x1080 + popd + ;; +esac ############################## # Post Uninstall