From: Bowon Ryu Date: Mon, 23 May 2022 05:11:56 +0000 (+0000) Subject: Merge "Add text selection popup style" into devel/master X-Git-Tag: dali_2.1.24~5 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=ff6ce970724ccc8bee65f7c93411b274907c09d7;hp=6ae6cb59fdc507c422db80110606c4125c19466b Merge "Add text selection popup style" into devel/master --- diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp index 8364147..9a79f34 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp @@ -537,41 +537,45 @@ int UtcDaliAccessibilityRelation(void) Dali::Accessibility::TestEnableSC( true ); auto rel = Accessibility::RelationType::FLOWS_TO; - auto number = static_cast< size_t >( rel ); auto control = Control::New(); auto destination1 = Control::New(); auto destination2 = Control::New(); DevelControl::AppendAccessibilityRelation( control, destination1, rel ); auto relations = DevelControl::GetAccessibilityRelations(control); - DALI_TEST_CHECK( relations[ number ].size() == 1 ); + DALI_TEST_EQUALS(relations.size(), 1u, TEST_LOCATION); + DALI_TEST_EQUALS(relations[0].mRelationType, rel, TEST_LOCATION); + DALI_TEST_EQUALS(relations[0].mTargets.size(), 1u, TEST_LOCATION); DevelControl::AppendAccessibilityRelation( control, destination2, rel ); relations = DevelControl::GetAccessibilityRelations(control); - DALI_TEST_CHECK( relations[ number ].size() == 2 ); + DALI_TEST_EQUALS(relations.size(), 1u, TEST_LOCATION); + DALI_TEST_EQUALS(relations[0].mRelationType, rel, TEST_LOCATION); + DALI_TEST_EQUALS(relations[0].mTargets.size(), 2u, TEST_LOCATION); auto accessible = Dali::Accessibility::Accessible::Get( control ); auto accessible_destination1 = Dali::Accessibility::Accessible::Get( destination1 ); auto accessible_destination2 = Dali::Accessibility::Accessible::Get( destination2 ); auto relationset = accessible->GetRelationSet(); - DALI_TEST_CHECK( relationset[0].relationType == rel ); - DALI_TEST_CHECK( relationset[0].targets[0] == accessible_destination1->GetAddress() || relationset[0].targets[1] == accessible_destination1->GetAddress() ); - DALI_TEST_CHECK( relationset[0].targets[0] == accessible_destination2->GetAddress() || relationset[0].targets[1] == accessible_destination2->GetAddress() ); + DALI_TEST_CHECK( relationset[0].mRelationType == rel ); + DALI_TEST_CHECK( relationset[0].mTargets[0] == accessible_destination1 || relationset[0].mTargets[1] == accessible_destination1 ); + DALI_TEST_CHECK( relationset[0].mTargets[0] == accessible_destination2 || relationset[0].mTargets[1] == accessible_destination2 ); auto relationset_bridge = TestGetRelationSet( accessible -> GetAddress() ); - DALI_TEST_CHECK( static_cast< uint32_t >( relationset[0].relationType ) == std::get<0>( relationset_bridge[0] ) ); + DALI_TEST_CHECK( static_cast< uint32_t >( relationset[0].mRelationType ) == std::get<0>( relationset_bridge[0] ) ); - DALI_TEST_CHECK( relationset[0].targets[0] == std::get<1>( relationset_bridge[0] )[0] || relationset[0].targets[1] == std::get<1>( relationset_bridge[0] )[0] ); - DALI_TEST_CHECK( relationset[0].targets[0] == std::get<1>( relationset_bridge[0] )[1] || relationset[0].targets[1] == std::get<1>( relationset_bridge[0] )[1] ); + DALI_TEST_CHECK( relationset[0].mTargets[0]->GetAddress() == std::get<1>( relationset_bridge[0] )[0] || relationset[0].mTargets[1]->GetAddress() == std::get<1>( relationset_bridge[0] )[0] ); + DALI_TEST_CHECK( relationset[0].mTargets[0]->GetAddress() == std::get<1>( relationset_bridge[0] )[1] || relationset[0].mTargets[1]->GetAddress() == std::get<1>( relationset_bridge[0] )[1] ); - DevelControl::RemoveAccessibilityRelation(control,destination2,rel); + DevelControl::RemoveAccessibilityRelation(control, destination2, rel); relations = DevelControl::GetAccessibilityRelations(control); - DALI_TEST_CHECK( relations[ number ].size() == 1 ); + DALI_TEST_EQUALS(relations.size(), 1u, TEST_LOCATION); + DALI_TEST_EQUALS(relations[0].mTargets.size(), 1u, TEST_LOCATION); DevelControl::ClearAccessibilityRelations(control); relations = DevelControl::GetAccessibilityRelations(control); - DALI_TEST_CHECK( relations[ number ].size() == 0 ); + DALI_TEST_EQUALS(relations.size(), 0u, TEST_LOCATION); Dali::Accessibility::TestEnableSC( false ); 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 af42955..bd5ab62 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) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -19,6 +19,8 @@ #include +#include + #include #include @@ -26,420 +28,445 @@ using namespace Dali::Toolkit::Internal; int UtcDaliVisualUrlConstructor(void) { - 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.GetProtocolType(), VisualUrl::LOCAL, TEST_LOCATION ); + 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.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.GetProtocolType(), VisualUrl::LOCAL, TEST_LOCATION ); + DALI_TEST_EQUALS(true, visualUrl2.IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(visualUrl2.GetType(), VisualUrl::GIF, 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.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.GetProtocolType(), VisualUrl::LOCAL, TEST_LOCATION); VisualUrl visualUrl4("dali://0"); visualUrl4 = visualUrl; - DALI_TEST_EQUALS( true, visualUrl4.IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( visualUrl4.GetType(), VisualUrl::GIF, TEST_LOCATION ); - DALI_TEST_EQUALS( visualUrl4.GetProtocolType(), VisualUrl::LOCAL, TEST_LOCATION ); + DALI_TEST_EQUALS(true, visualUrl4.IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(visualUrl4.GetType(), VisualUrl::GIF, TEST_LOCATION); + DALI_TEST_EQUALS(visualUrl4.GetProtocolType(), VisualUrl::LOCAL, TEST_LOCATION); VisualUrl visualUrl5("dali://1"); visualUrl4 = visualUrl5; - DALI_TEST_EQUALS( true, visualUrl4.IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( visualUrl4.GetType(), VisualUrl::REGULAR_IMAGE, TEST_LOCATION ); - DALI_TEST_EQUALS( visualUrl4.GetProtocolType(), VisualUrl::TEXTURE, TEST_LOCATION ); + DALI_TEST_EQUALS(true, visualUrl4.IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(visualUrl4.GetType(), VisualUrl::REGULAR_IMAGE, TEST_LOCATION); + DALI_TEST_EQUALS(visualUrl4.GetProtocolType(), VisualUrl::TEXTURE, TEST_LOCATION); VisualUrl visualUrl6("enbuf://0"); visualUrl6 = visualUrl; - DALI_TEST_EQUALS( true, visualUrl6.IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( visualUrl6.GetType(), VisualUrl::GIF, TEST_LOCATION ); - DALI_TEST_EQUALS( visualUrl6.GetProtocolType(), VisualUrl::LOCAL, TEST_LOCATION ); + DALI_TEST_EQUALS(true, visualUrl6.IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(visualUrl6.GetType(), VisualUrl::GIF, TEST_LOCATION); + DALI_TEST_EQUALS(visualUrl6.GetProtocolType(), VisualUrl::LOCAL, TEST_LOCATION); VisualUrl visualUrl7("enbuf://1"); visualUrl6 = visualUrl7; - DALI_TEST_EQUALS( true, visualUrl6.IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( visualUrl6.GetType(), VisualUrl::REGULAR_IMAGE, TEST_LOCATION ); - DALI_TEST_EQUALS( visualUrl6.GetProtocolType(), VisualUrl::BUFFER, TEST_LOCATION ); + DALI_TEST_EQUALS(true, visualUrl6.IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(visualUrl6.GetType(), VisualUrl::REGULAR_IMAGE, TEST_LOCATION); + DALI_TEST_EQUALS(visualUrl6.GetProtocolType(), VisualUrl::BUFFER, TEST_LOCATION); END_TEST; } - int UtcDaliVisualUrlRegularImage(void) { - tet_infoline( "UtcDaliVisualUrl REGULAR_IMAGE" ); + tet_infoline("UtcDaliVisualUrl REGULAR_IMAGE"); - DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl("foobar.jpeg").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::REGULAR_IMAGE, VisualUrl("foobar.jpeg").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl("foobar.PNG").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::REGULAR_IMAGE, VisualUrl("foobar.PNG").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl("foobar.Png123").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::REGULAR_IMAGE, VisualUrl("foobar.Png123").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl("foobar.Png1.23").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::REGULAR_IMAGE, VisualUrl("foobar.Png1.23").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl("").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::REGULAR_IMAGE, VisualUrl("").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl(" ").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::REGULAR_IMAGE, VisualUrl(" ").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl(".").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::REGULAR_IMAGE, VisualUrl(".").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl("9").GetType(), TEST_LOCATION ); + 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 ); + DALI_TEST_EQUALS(VisualUrl::REGULAR_IMAGE, VisualUrl("dali://bar.org/foobar.gif").GetType(), TEST_LOCATION); END_TEST; } int UtcDaliVisualUrlSvg(void) { - tet_infoline( "UtcDaliVisualUrl SVG" ); + tet_infoline("UtcDaliVisualUrl SVG"); - DALI_TEST_EQUALS( VisualUrl::SVG, VisualUrl("foobar.svg").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::SVG, VisualUrl("foobar.svg").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::SVG, VisualUrl("foobar.svg.svg").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::SVG, VisualUrl("foobar.svg.svg").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::SVG, VisualUrl("foobar.svG").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::SVG, VisualUrl("foobar.svG").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::SVG, VisualUrl("foobar.SVG").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::SVG, VisualUrl("foobar.SVG").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::SVG, VisualUrl(".SvG").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::SVG, VisualUrl(".SvG").GetType(), TEST_LOCATION); // SVGs aren't N-patch - DALI_TEST_EQUALS( VisualUrl::SVG, VisualUrl("foobar.9.svg").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::SVG, VisualUrl("foobar.9.svg").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl("svg.png").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::REGULAR_IMAGE, VisualUrl("svg.png").GetType(), TEST_LOCATION); // maybe controversial, but for now we expect the suffix to be exactly .svg - DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl("svg.svg1").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::REGULAR_IMAGE, VisualUrl("svg.svg1").GetType(), TEST_LOCATION); END_TEST; } int UtcDaliVisualUrlNPatch(void) { - tet_infoline( "UtcDaliVisualUrl N_PATCH" ); + tet_infoline("UtcDaliVisualUrl N_PATCH"); - DALI_TEST_EQUALS( VisualUrl::N_PATCH, VisualUrl("foobar.#.png").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::N_PATCH, VisualUrl("foobar.#.png").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::N_PATCH, VisualUrl("foobar.9.9.bmp").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::N_PATCH, VisualUrl("foobar.9.9.bmp").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::N_PATCH, VisualUrl("foobar.9.9.jpg[]=$$").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::N_PATCH, VisualUrl("foobar.9.9.jpg[]=$$").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::N_PATCH, VisualUrl("foobar.9.#.#.9.wbpm123").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::N_PATCH, VisualUrl("foobar.9.#.#.9.wbpm123").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl("svg.##.png").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::REGULAR_IMAGE, VisualUrl("svg.##.png").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::REGULAR_IMAGE, VisualUrl("svg.99.jpeg").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::REGULAR_IMAGE, VisualUrl("svg.99.jpeg").GetType(), TEST_LOCATION); END_TEST; } int UtcDaliVisualUrlGif(void) { - tet_infoline( "UtcDaliVisualUrl GIF" ); + tet_infoline("UtcDaliVisualUrl GIF"); - DALI_TEST_EQUALS( VisualUrl::GIF, VisualUrl("foobar.gif").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::GIF, VisualUrl("foobar.gif").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::GIF, VisualUrl("foobar.gif.gif").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::GIF, VisualUrl("foobar.gif.gif").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::GIF, VisualUrl("foobar.giF").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::GIF, VisualUrl("foobar.giF").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::GIF, VisualUrl("foobar.GIF").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::GIF, VisualUrl("foobar.GIF").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::GIF, VisualUrl(".GiF").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::GIF, VisualUrl(".GiF").GetType(), TEST_LOCATION); - DALI_TEST_EQUALS( VisualUrl::N_PATCH, VisualUrl("foobar.9.gif").GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS(VisualUrl::N_PATCH, VisualUrl("foobar.9.gif").GetType(), TEST_LOCATION); - 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 ); + 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; } - int UtcDaliVisualUrlLocationP(void) { - tet_infoline( "UtcDaliVisualUrl 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 ); - - DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("enbuf://").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("enbuf://1234").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("ENBUF://1234").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("enbuf://.gif").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("enbuf://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("enbuf://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("enbuf://bar.org/foobar.svg").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::BUFFER, VisualUrl("enbuf://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); + tet_infoline("UtcDaliVisualUrl 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); + + DALI_TEST_EQUALS(VisualUrl::BUFFER, VisualUrl("enbuf://").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::BUFFER, VisualUrl("enbuf://1234").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::BUFFER, VisualUrl("ENBUF://1234").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::BUFFER, VisualUrl("enbuf://.gif").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::BUFFER, VisualUrl("enbuf://bar.org/foobar.gif").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::BUFFER, VisualUrl("enbuf://bar.org/foobar.png").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::BUFFER, VisualUrl("enbuf://bar.org/foobar.svg").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::BUFFER, VisualUrl("enbuf://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION); END_TEST; } - int UtcDaliVisualUrlLocationN(void) { - tet_infoline( "UtcDaliVisualUrl Location negative tests" ); - - 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("fsh://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("stp://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 ); - - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("eunki://1").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("enbu://1").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("eubnf://1").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("1nbuf://1").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("e2bun://1").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("en3uf://1").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("enb4f://1").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("enbu5://1").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("enbuf6//1").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("enbuf:7/1").GetProtocolType(), TEST_LOCATION ); - DALI_TEST_EQUALS( VisualUrl::LOCAL, VisualUrl("enbuf:/81").GetProtocolType(), TEST_LOCATION ); + tet_infoline("UtcDaliVisualUrl Location negative tests"); + + 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("fsh://bar.org/foobar.9.png").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::LOCAL, VisualUrl("stp://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); + + DALI_TEST_EQUALS(VisualUrl::LOCAL, VisualUrl("eunki://1").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::LOCAL, VisualUrl("enbu://1").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::LOCAL, VisualUrl("eubnf://1").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::LOCAL, VisualUrl("1nbuf://1").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::LOCAL, VisualUrl("e2bun://1").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::LOCAL, VisualUrl("en3uf://1").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::LOCAL, VisualUrl("enb4f://1").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::LOCAL, VisualUrl("enbu5://1").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::LOCAL, VisualUrl("enbuf6//1").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::LOCAL, VisualUrl("enbuf:7/1").GetProtocolType(), TEST_LOCATION); + DALI_TEST_EQUALS(VisualUrl::LOCAL, VisualUrl("enbuf:/81").GetProtocolType(), TEST_LOCATION); END_TEST; } int UtcDaliVisualUrlIsValid(void) { - tet_infoline( "UtcDaliVisualUrl IsValid" ); - - DALI_TEST_EQUALS( false, VisualUrl().IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( false, VisualUrl("").IsValid(), TEST_LOCATION ); - - DALI_TEST_EQUALS( true, VisualUrl("foobar.gif").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("foobar.png").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("foobar.svg").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("foobar.GIF").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("foobar.9.png").IsValid(), TEST_LOCATION ); - - DALI_TEST_EQUALS( true, VisualUrl("http://bar.org/foobar.gif").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("http://bar.org/foobar.png").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("http://bar.org/foobar.svg").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("http://bar.org/foobar.GIF").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("http://bar.org/foobar.9.png").IsValid(), TEST_LOCATION ); - - DALI_TEST_EQUALS( true, VisualUrl("https://bar.org/foobar.gif").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("https://bar.org/foobar.png").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("https://bar.org/foobar.svg").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("https://bar.org/foobar.GIF").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("https://bar.org/foobar.9.png").IsValid(), TEST_LOCATION ); - - DALI_TEST_EQUALS( true, VisualUrl("HTTP://bar.org/foobar.gif").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("HTTP://bar.org/foobar.png").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("HTTP://bar.org/foobar.svg").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("HTTP://bar.org/foobar.GIF").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("HTTP://bar.org/foobar.9.png").IsValid(), TEST_LOCATION ); - - DALI_TEST_EQUALS( true, VisualUrl("HTTPS://bar.org/foobar.gif").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("HTTPS://bar.org/foobar.png").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("HTTPS://bar.org/foobar.svg").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("HTTPS://bar.org/foobar.GIF").IsValid(), TEST_LOCATION ); - DALI_TEST_EQUALS( true, VisualUrl("HTTPS://bar.org/foobar.9.png").IsValid(), TEST_LOCATION ); + tet_infoline("UtcDaliVisualUrl IsValid"); + + DALI_TEST_EQUALS(false, VisualUrl().IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(false, VisualUrl("").IsValid(), TEST_LOCATION); + + DALI_TEST_EQUALS(true, VisualUrl("foobar.gif").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("foobar.png").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("foobar.svg").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("foobar.GIF").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("foobar.9.png").IsValid(), TEST_LOCATION); + + DALI_TEST_EQUALS(true, VisualUrl("http://bar.org/foobar.gif").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("http://bar.org/foobar.png").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("http://bar.org/foobar.svg").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("http://bar.org/foobar.GIF").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("http://bar.org/foobar.9.png").IsValid(), TEST_LOCATION); + + DALI_TEST_EQUALS(true, VisualUrl("https://bar.org/foobar.gif").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("https://bar.org/foobar.png").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("https://bar.org/foobar.svg").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("https://bar.org/foobar.GIF").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("https://bar.org/foobar.9.png").IsValid(), TEST_LOCATION); + + DALI_TEST_EQUALS(true, VisualUrl("HTTP://bar.org/foobar.gif").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("HTTP://bar.org/foobar.png").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("HTTP://bar.org/foobar.svg").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("HTTP://bar.org/foobar.GIF").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("HTTP://bar.org/foobar.9.png").IsValid(), TEST_LOCATION); + + DALI_TEST_EQUALS(true, VisualUrl("HTTPS://bar.org/foobar.gif").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("HTTPS://bar.org/foobar.png").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("HTTPS://bar.org/foobar.svg").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("HTTPS://bar.org/foobar.GIF").IsValid(), TEST_LOCATION); + DALI_TEST_EQUALS(true, VisualUrl("HTTPS://bar.org/foobar.9.png").IsValid(), TEST_LOCATION); 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 ); + 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" ); + tet_infoline("UtcDaliVisualUrl GetLocation Positive"); - DALI_TEST_EQUAL( "a", VisualUrl("http://a").GetLocation() ); - DALI_TEST_EQUAL( "1", VisualUrl("dali://1").GetLocation() ); - DALI_TEST_EQUAL( "4", VisualUrl("enbuf://4").GetLocation() ); - DALI_TEST_EQUAL( "", VisualUrl("ftp://").GetLocation() ); - DALI_TEST_EQUAL( "http://", VisualUrl("http://http://").GetLocation() ); + DALI_TEST_EQUAL("a", VisualUrl("http://a").GetLocation()); + DALI_TEST_EQUAL("1", VisualUrl("dali://1").GetLocation()); + DALI_TEST_EQUAL("4", VisualUrl("enbuf://4").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" ); + 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( "enbuf:/2", VisualUrl("enbuf:/2").GetLocation() ); - DALI_TEST_EQUAL( "", VisualUrl("http:/http://").GetLocation() ); + 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("enbuf:/2", VisualUrl("enbuf:/2").GetLocation()); + DALI_TEST_EQUAL("", VisualUrl("http:/http://").GetLocation()); END_TEST; } int UtcDaliVisualUrlCreateTextureUrl(void) { - tet_infoline( "UtcDaliVisualUrl CreateTextureUrl" ); + 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( "" ) ); + DALI_TEST_EQUAL("dali://a", VisualUrl::CreateTextureUrl("a")); + DALI_TEST_EQUAL("dali://1234", VisualUrl::CreateTextureUrl("1234")); + DALI_TEST_EQUAL("dali://", VisualUrl::CreateTextureUrl("")); END_TEST; } int UtcDaliVisualUrlCreateBufferUrl(void) { - tet_infoline( "UtcDaliVisualUrl CreateBufferUrl" ); + tet_infoline("UtcDaliVisualUrl CreateBufferUrl"); - DALI_TEST_EQUAL( "enbuf://a", VisualUrl::CreateBufferUrl( "a" ) ); - DALI_TEST_EQUAL( "enbuf://1234", VisualUrl::CreateBufferUrl( "1234" ) ); - DALI_TEST_EQUAL( "enbuf://", VisualUrl::CreateBufferUrl( "" ) ); + DALI_TEST_EQUAL("enbuf://a", VisualUrl::CreateBufferUrl("a")); + DALI_TEST_EQUAL("enbuf://1234", VisualUrl::CreateBufferUrl("1234")); + DALI_TEST_EQUAL("enbuf://", VisualUrl::CreateBufferUrl("")); END_TEST; } + +int UtcDaliVisualUrlGetUrlHash(void) +{ + tet_infoline("UtcDaliVisualUrl GetUrlHash"); + + std::vector testUrlLists = + { + "", // empty string. + "/opt/usr/home/owner/media/resources/test.png", + "hello.world", + "image.jpg", + "not_suffix", + "https://bar.org/foo/bar.gif", + "dali://0", + "enbuf://1", + }; + + for(auto& url : testUrlLists) + { + VisualUrl visualUrl(url); + + std::uint64_t exceptHash = Dali::CalculateHash(url); + std::uint64_t visualHash = visualUrl.GetUrlHash(); + + DALI_TEST_EQUAL(visualHash, exceptHash); + } + + END_TEST; +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp index c810939..dab40a2 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -644,6 +644,21 @@ int UtcDaliToolkitTextLabelSetPropertyP(void) DALI_TEST_EQUALS(strikethroughMapGet.Count(), strikethroughMapSet.Count(), TEST_LOCATION); DALI_TEST_EQUALS(DaliTestCheckMaps(strikethroughMapGet, strikethroughMapSet), true, TEST_LOCATION); + // Check the transparent strikethrough property for coverage. + strikethroughMapSet.Clear(); + strikethroughMapSet.Insert("enable", true); + strikethroughMapSet.Insert("color", Color::TRANSPARENT); + strikethroughMapSet.Insert("height", 2.0f); + + label.SetProperty(DevelTextLabel::Property::STRIKETHROUGH, strikethroughMapSet); + + application.SendNotification(); + application.Render(); + + strikethroughMapGet = label.GetProperty(DevelTextLabel::Property::STRIKETHROUGH); + DALI_TEST_EQUALS(strikethroughMapGet.Count(), strikethroughMapSet.Count(), TEST_LOCATION); + DALI_TEST_EQUALS(DaliTestCheckMaps(strikethroughMapGet, strikethroughMapSet), true, TEST_LOCATION); + strikethroughMapSet.Clear(); strikethroughMapSet.Insert(Toolkit::DevelText::Strikethrough::Property::ENABLE, true); strikethroughMapSet.Insert(Toolkit::DevelText::Strikethrough::Property::COLOR, Color::RED); @@ -803,6 +818,24 @@ int UtcDaliToolkitTextLabelSetPropertyP(void) DALI_TEST_EQUALS(underlineMapGet.Count(), underlineMapSet.Count(), TEST_LOCATION); DALI_TEST_EQUALS(DaliTestCheckMaps(underlineMapGet, underlineMapSet), true, TEST_LOCATION); + // Check the transparent double underline property for coverage. + underlineMapSet.Clear(); + underlineMapSet.Insert("enable", true); + underlineMapSet.Insert("color", Color::TRANSPARENT); + underlineMapSet.Insert("height", 1); + underlineMapSet.Insert("type", Text::Underline::DOUBLE); + underlineMapSet.Insert("dashWidth", 2); + underlineMapSet.Insert("dashGap", 1); + + label.SetProperty(TextLabel::Property::UNDERLINE, underlineMapSet); + + application.SendNotification(); + application.Render(); + + underlineMapGet = label.GetProperty(TextLabel::Property::UNDERLINE); + DALI_TEST_EQUALS(underlineMapGet.Count(), underlineMapSet.Count(), TEST_LOCATION); + DALI_TEST_EQUALS(DaliTestCheckMaps(underlineMapGet, underlineMapSet), true, TEST_LOCATION); + underlineMapSet.Clear(); underlineMapSet.Insert(Toolkit::DevelText::Underline::Property::ENABLE, true); underlineMapSet.Insert(Toolkit::DevelText::Underline::Property::COLOR, Color::GREEN); @@ -931,6 +964,19 @@ int UtcDaliToolkitTextLabelSetPropertyP(void) DALI_TEST_EQUALS(backgroundMapGet.Count(), backgroundMapSet.Count(), TEST_LOCATION); DALI_TEST_EQUALS(DaliTestCheckMaps(backgroundMapGet, backgroundMapSet), true, TEST_LOCATION); + // Check the transparent background property for coverage + backgroundMapSet.Clear(); + backgroundMapSet["enable"] = true; + backgroundMapSet["color"] = Color::TRANSPARENT; + label.SetProperty(DevelTextLabel::Property::BACKGROUND, backgroundMapSet); + + application.SendNotification(); + application.Render(); + + backgroundMapGet = label.GetProperty(DevelTextLabel::Property::BACKGROUND); + DALI_TEST_EQUALS(backgroundMapGet.Count(), backgroundMapSet.Count(), TEST_LOCATION); + DALI_TEST_EQUALS(DaliTestCheckMaps(backgroundMapGet, backgroundMapSet), true, TEST_LOCATION); + backgroundMapSet.Clear(); backgroundMapSet[Toolkit::DevelText::Background::Property::ENABLE] = true; backgroundMapSet[Toolkit::DevelText::Background::Property::COLOR] = Color::GREEN; diff --git a/dali-toolkit/devel-api/controls/control-accessible.cpp b/dali-toolkit/devel-api/controls/control-accessible.cpp index 9a3da6c..85b3c6a 100644 --- a/dali-toolkit/devel-api/controls/control-accessible.cpp +++ b/dali-toolkit/devel-api/controls/control-accessible.cpp @@ -457,24 +457,7 @@ std::vector ControlAccessible::GetRelationSet() { auto control = Dali::Toolkit::Control::DownCast(Self()); - Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control); - Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get(internalControl); - - std::vector ret; - - for(auto& relation : controlImpl.mAccessibilityRelations) - { - auto& targets = relation.second; - - ret.emplace_back(Accessibility::Relation{relation.first, {}}); - - // Map every Accessible* to its Address - std::transform(targets.begin(), targets.end(), std::back_inserter(ret.back().targets), [](auto* x) { - return x->GetAddress(); - }); - } - - return ret; + return DevelControl::GetAccessibilityRelations(control); } bool ControlAccessible::ScrollToChild(Actor child) diff --git a/dali-toolkit/devel-api/controls/control-devel.cpp b/dali-toolkit/devel-api/controls/control-devel.cpp index a604433..51e0564 100644 --- a/dali-toolkit/devel-api/controls/control-devel.cpp +++ b/dali-toolkit/devel-api/controls/control-devel.cpp @@ -201,19 +201,17 @@ void RemoveAccessibilityRelation(Toolkit::Control control, Dali::Actor destinati } } -std::vector> GetAccessibilityRelations(Toolkit::Control control) +std::vector GetAccessibilityRelations(Toolkit::Control control) { - std::vector> result(static_cast(Accessibility::RelationType::MAX_COUNT)); + const auto& relations = GetControlImplementation(control).mAccessibilityRelations; + std::vector result; - // Map every Accessible* to its Address - for(auto& relation : GetControlImplementation(control).mAccessibilityRelations) + for(auto& relation : relations) { - auto index = static_cast(relation.first); auto& targets = relation.second; - std::transform(targets.begin(), targets.end(), std::back_inserter(result[index]), [](auto* x) { - return x->GetAddress(); - }); + result.emplace_back(Accessibility::Relation{relation.first, {}}); + std::copy(targets.begin(), targets.end(), std::back_inserter(result.back().mTargets)); } return result; diff --git a/dali-toolkit/devel-api/controls/control-devel.h b/dali-toolkit/devel-api/controls/control-devel.h index 42384a1..34b733b 100644 --- a/dali-toolkit/devel-api/controls/control-devel.h +++ b/dali-toolkit/devel-api/controls/control-devel.h @@ -488,12 +488,14 @@ DALI_TOOLKIT_API void AppendAccessibilityRelation(Toolkit::Control control, Dali DALI_TOOLKIT_API void RemoveAccessibilityRelation(Toolkit::Control control, Dali::Actor destination, Dali::Accessibility::RelationType relation); /** - * @brief The method returns collection accessibility addresses representing objects connected with current object + * @brief Returns a collection of Accessible objects related to current object and grouped by relation type. * - * @param control object to append attribute to - * @return std::vector, where index is casted value of Accessibility::RelationType and value is std::vector of type Accessibility::Address + * @param control object to query + * @return collection of relations + * + * @see Dali::Accessibility::Accessible::GetRelationSet() */ -DALI_TOOLKIT_API std::vector> GetAccessibilityRelations(Toolkit::Control control); +DALI_TOOLKIT_API std::vector GetAccessibilityRelations(Toolkit::Control control); /** * @brief The method removes all previously appended relations diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.cpp b/dali-toolkit/internal/text/rendering/text-typesetter.cpp index 500a081..826e894 100644 --- a/dali-toolkit/internal/text/rendering/text-typesetter.cpp +++ b/dali-toolkit/internal/text/rendering/text-typesetter.cpp @@ -41,6 +41,20 @@ namespace { const float HALF(0.5f); const float ONE_AND_A_HALF(1.5f); + +/** + * @brief Fast multiply & divide by 255. It wiil be useful when we applying alpha value in color + * + * @param x The value between [0..255] + * @param y The value between [0..255] + * @return (x*y)/255 + */ +inline uint8_t MultiplyAndNormalizeColor(const uint8_t& x, const uint8_t& y) noexcept +{ + const uint32_t xy = static_cast(x) * y; + return ((xy << 15) + (xy << 7) + xy) >> 23; +} + /** * @brief Data struct used to set the buffer of the glyph's bitmap into the final bitmap's buffer. */ @@ -49,16 +63,16 @@ struct GlyphData 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. - unsigned int height; ///< The bitmap's height. - int horizontalOffset; ///< The horizontal offset to be added to the 'x' glyph's position. - int verticalOffset; ///< The vertical offset to be added to the 'y' glyph's position. + uint32_t width; ///< The bitmap's width. + uint32_t height; ///< The bitmap's height. + int32_t horizontalOffset; ///< The horizontal offset to be added to the 'x' glyph's position. + int32_t verticalOffset; ///< The vertical offset to be added to the 'y' glyph's position. }; /** * @brief Sets the glyph's buffer into the bitmap's buffer. * - * @param[in] data Struct which contains the glyph's data and the bitmap's data. + * @param[in, out] 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. @@ -76,46 +90,70 @@ void TypesetGlyph(GlyphData& data, return; } - const int widthMinusOne = static_cast(data.width - 1u); - const int heightMinusOne = static_cast(data.height - 1u); + // Initial vertical / horizontal offset. + const int32_t yOffset = data.verticalOffset + position->y; + const int32_t xOffset = data.horizontalOffset + position->x; + + // Whether the given glyph is a color one. + const bool isColorGlyph = data.glyphBitmap.isColorEmoji || data.glyphBitmap.isColorBitmap; + const uint32_t glyphPixelSize = Pixel::GetBytesPerPixel(data.glyphBitmap.format); + const uint32_t alphaIndex = glyphPixelSize - 1u; + + // Determinate iterator range. + const int32_t lineIndexRangeMin = std::max(0, -yOffset); + const int32_t lineIndexRangeMax = std::min(static_cast(data.glyphBitmap.height), static_cast(data.height) - yOffset); + const int32_t indexRangeMin = std::max(0, -xOffset); + const int32_t indexRangeMax = std::min(static_cast(data.glyphBitmap.width), static_cast(data.width) - xOffset); + + // If current glyph don't need to be rendered, just ignore. + if(lineIndexRangeMax <= lineIndexRangeMin || indexRangeMax <= indexRangeMin) + { + return; + } if(Pixel::RGBA8888 == pixelFormat) { - // Whether the given glyph is a color one. - const bool isColorGlyph = data.glyphBitmap.isColorEmoji || data.glyphBitmap.isColorBitmap; - const uint32_t glyphPixelSize = Pixel::GetBytesPerPixel(data.glyphBitmap.format); - const uint32_t alphaIndex = glyphPixelSize - 1u; - const bool swapChannelsBR = Pixel::BGRA8888 == data.glyphBitmap.format; + const bool swapChannelsBR = Pixel::BGRA8888 == data.glyphBitmap.format; + + uint32_t* bitmapBuffer = reinterpret_cast(data.bitmapBuffer.GetBuffer()); + + // Fast-cut if style is MASK or OUTLINE. Outline not shown for color glyph. + // Just overwrite transparent color and return. + if(isColorGlyph && (Typesetter::STYLE_MASK == style || Typesetter::STYLE_OUTLINE == style)) + { + for(int32_t lineIndex = lineIndexRangeMin; lineIndex < lineIndexRangeMax; ++lineIndex) + { + const int32_t yOffsetIndex = yOffset + lineIndex; + const int32_t verticalOffset = yOffsetIndex * data.width; + + // We can use memset here. + memset(bitmapBuffer + verticalOffset + xOffset + indexRangeMin, 0, (indexRangeMax - indexRangeMin) * sizeof(uint32_t)); + } + return; + } // Pointer to the color glyph if there is one. const uint32_t* const colorGlyphBuffer = isColorGlyph ? reinterpret_cast(data.glyphBitmap.buffer) : NULL; - // Initial vertical offset. - const int yOffset = data.verticalOffset + position->y; + // Precalculate input color's packed result. + uint32_t packedInputColor = 0u; + uint8_t* packedInputColorBuffer = reinterpret_cast(&packedInputColor); - uint32_t* bitmapBuffer = reinterpret_cast(data.bitmapBuffer.GetBuffer()); + *(packedInputColorBuffer + 3u) = static_cast(color->a * 255); + *(packedInputColorBuffer + 2u) = static_cast(color->b * 255); + *(packedInputColorBuffer + 1u) = static_cast(color->g * 255); + *(packedInputColorBuffer) = static_cast(color->r * 255); // Traverse the pixels of the glyph line per line. - for(int lineIndex = 0, glyphHeight = static_cast(data.glyphBitmap.height); lineIndex < glyphHeight; ++lineIndex) + for(int32_t lineIndex = lineIndexRangeMin; lineIndex < lineIndexRangeMax; ++lineIndex) { - const int yOffsetIndex = yOffset + lineIndex; - if((0 > yOffsetIndex) || (yOffsetIndex > heightMinusOne)) - { - // Do not write out of bounds. - continue; - } + const int32_t yOffsetIndex = yOffset + lineIndex; - 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 int32_t verticalOffset = yOffsetIndex * data.width; + const int32_t glyphBufferOffset = lineIndex * static_cast(data.glyphBitmap.width); + for(int32_t index = indexRangeMin; index < indexRangeMax; ++index) { - const int xOffsetIndex = xOffset + index; - if((0 > xOffsetIndex) || (xOffsetIndex > widthMinusOne)) - { - // Don't write out of bounds. - continue; - } + const int32_t xOffsetIndex = xOffset + index; if(isColorGlyph) { @@ -124,43 +162,32 @@ void TypesetGlyph(GlyphData& data, uint8_t* packedColorGlyphBuffer = reinterpret_cast(&packedColorGlyph); // Update the alpha channel. - if(Typesetter::STYLE_MASK == style || Typesetter::STYLE_OUTLINE == style) // Outline not shown for color glyph + const uint8_t colorAlpha = MultiplyAndNormalizeColor(*(packedInputColorBuffer + 3u), *(packedColorGlyphBuffer + 3u)); + *(packedColorGlyphBuffer + 3u) = colorAlpha; + + if(Typesetter::STYLE_SHADOW == style) { - // Create an alpha mask for color glyph. - *(packedColorGlyphBuffer + 3u) = 0u; - *(packedColorGlyphBuffer + 2u) = 0u; - *(packedColorGlyphBuffer + 1u) = 0u; - *packedColorGlyphBuffer = 0u; + // The shadow of color glyph needs to have the shadow color. + *(packedColorGlyphBuffer + 2u) = MultiplyAndNormalizeColor(*(packedInputColorBuffer + 2u), colorAlpha); + *(packedColorGlyphBuffer + 1u) = MultiplyAndNormalizeColor(*(packedInputColorBuffer + 1u), colorAlpha); + *packedColorGlyphBuffer = MultiplyAndNormalizeColor(*packedInputColorBuffer, colorAlpha); } else { - const uint8_t colorAlpha = static_cast(color->a * static_cast(*(packedColorGlyphBuffer + 3u))); - *(packedColorGlyphBuffer + 3u) = colorAlpha; - - if(Typesetter::STYLE_SHADOW == style) + if(swapChannelsBR) { - // The shadow of color glyph needs to have the shadow color. - *(packedColorGlyphBuffer + 2u) = static_cast(color->b * colorAlpha); - *(packedColorGlyphBuffer + 1u) = static_cast(color->g * colorAlpha); - *packedColorGlyphBuffer = static_cast(color->r * colorAlpha); + std::swap(*packedColorGlyphBuffer, *(packedColorGlyphBuffer + 2u)); // Swap B and R. } - else + + *(packedColorGlyphBuffer + 2u) = MultiplyAndNormalizeColor(*(packedColorGlyphBuffer + 2u), colorAlpha); + *(packedColorGlyphBuffer + 1u) = MultiplyAndNormalizeColor(*(packedColorGlyphBuffer + 1u), colorAlpha); + *packedColorGlyphBuffer = MultiplyAndNormalizeColor(*packedColorGlyphBuffer, colorAlpha); + + if(data.glyphBitmap.isColorBitmap) { - if(swapChannelsBR) - { - std::swap(*packedColorGlyphBuffer, *(packedColorGlyphBuffer + 2u)); // Swap B and R. - } - - *(packedColorGlyphBuffer + 2u) = (*(packedColorGlyphBuffer + 2u) * colorAlpha / 255); - *(packedColorGlyphBuffer + 1u) = (*(packedColorGlyphBuffer + 1u) * colorAlpha / 255); - *packedColorGlyphBuffer = (*(packedColorGlyphBuffer)*colorAlpha / 255); - - if(data.glyphBitmap.isColorBitmap) - { - *(packedColorGlyphBuffer + 2u) = static_cast(*(packedColorGlyphBuffer + 2u) * color->b); - *(packedColorGlyphBuffer + 1u) = static_cast(*(packedColorGlyphBuffer + 1u) * color->g); - *packedColorGlyphBuffer = static_cast(*packedColorGlyphBuffer * color->r); - } + *(packedColorGlyphBuffer + 2u) = MultiplyAndNormalizeColor(*(packedInputColorBuffer + 2u), *(packedColorGlyphBuffer + 2u)); + *(packedColorGlyphBuffer + 1u) = MultiplyAndNormalizeColor(*(packedInputColorBuffer + 1u), *(packedColorGlyphBuffer + 1u)); + *packedColorGlyphBuffer = MultiplyAndNormalizeColor(*packedInputColorBuffer, *packedColorGlyphBuffer); } } @@ -190,15 +217,22 @@ void TypesetGlyph(GlyphData& data, // happen, for example, in the RTL text when we copy glyphs from right to left). uint8_t currentAlpha = *(packedCurrentColorBuffer + 3u); currentAlpha = std::max(currentAlpha, alpha); - - // Color is pre-muliplied with its alpha. - *(packedColorBuffer + 3u) = static_cast(color->a * currentAlpha); - *(packedColorBuffer + 2u) = static_cast(color->b * currentAlpha); - *(packedColorBuffer + 1u) = static_cast(color->g * currentAlpha); - *(packedColorBuffer) = static_cast(color->r * currentAlpha); - - // Set the color into the final pixel buffer. - currentColor = packedColor; + if(currentAlpha == 255) + { + // Fast-cut to avoid float type operation. + currentColor = packedInputColor; + } + else + { + // Color is pre-muliplied with its alpha. + *(packedColorBuffer + 3u) = MultiplyAndNormalizeColor(*(packedInputColorBuffer + 3u), currentAlpha); + *(packedColorBuffer + 2u) = MultiplyAndNormalizeColor(*(packedInputColorBuffer + 2u), currentAlpha); + *(packedColorBuffer + 1u) = MultiplyAndNormalizeColor(*(packedInputColorBuffer + 1u), currentAlpha); + *(packedColorBuffer) = MultiplyAndNormalizeColor(*packedInputColorBuffer, currentAlpha); + + // Set the color into the final pixel buffer. + currentColor = packedColor; + } } } } @@ -206,40 +240,22 @@ void TypesetGlyph(GlyphData& data, } else { - // Whether the given glyph is a color one. - const bool isColorGlyph = data.glyphBitmap.isColorEmoji || data.glyphBitmap.isColorBitmap; - const uint32_t glyphPixelSize = Pixel::GetBytesPerPixel(data.glyphBitmap.format); - const uint32_t alphaIndex = glyphPixelSize - 1u; - - // Initial vertical offset. - const int yOffset = data.verticalOffset + position->y; - - uint8_t* bitmapBuffer = reinterpret_cast(data.bitmapBuffer.GetBuffer()); - - // Traverse the pixels of the glyph line per line. - for(int lineIndex = 0, glyphHeight = static_cast(data.glyphBitmap.height); lineIndex < glyphHeight; ++lineIndex) + // Below codes required only if not color glyph. + if(!isColorGlyph) { - const int yOffsetIndex = yOffset + lineIndex; - if((0 > yOffsetIndex) || (yOffsetIndex > heightMinusOne)) - { - // Do not write out of bounds. - continue; - } + uint8_t* bitmapBuffer = reinterpret_cast(data.bitmapBuffer.GetBuffer()); - 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(int32_t lineIndex = lineIndexRangeMin; lineIndex < lineIndexRangeMax; ++lineIndex) { - const int xOffsetIndex = xOffset + index; - if((0 > xOffsetIndex) || (xOffsetIndex > widthMinusOne)) - { - // Don't write out of bounds. - continue; - } + const int32_t yOffsetIndex = yOffset + lineIndex; - if(!isColorGlyph) + const int32_t verticalOffset = yOffsetIndex * data.width; + const int32_t glyphBufferOffset = lineIndex * static_cast(data.glyphBitmap.width); + for(int32_t index = indexRangeMin; index < indexRangeMax; ++index) { + const int32_t xOffsetIndex = xOffset + index; + // Update the alpha channel. const uint8_t alpha = *(data.glyphBitmap.buffer + glyphPixelSize * (glyphBufferOffset + index) + alphaIndex); @@ -261,38 +277,16 @@ void TypesetGlyph(GlyphData& data, } } -/// Draws the specified color to the pixel buffer -void WriteColorToPixelBuffer( - GlyphData& glyphData, - uint32_t* bitmapBuffer, - const Vector4& color, - const unsigned int x, - const unsigned int y) -{ - // Always RGBA image for text with styles - uint32_t pixel = *(bitmapBuffer + y * glyphData.width + x); - uint8_t* pixelBuffer = reinterpret_cast(&pixel); - - // Write the color to the pixel buffer - uint8_t colorAlpha = static_cast(color.a * 255.f); - *(pixelBuffer + 3u) = colorAlpha; - *(pixelBuffer + 2u) = static_cast(color.b * colorAlpha); - *(pixelBuffer + 1u) = static_cast(color.g * colorAlpha); - *(pixelBuffer) = static_cast(color.r * colorAlpha); - - *(bitmapBuffer + y * glyphData.width + x) = pixel; -} - /// Draws the specified underline color to the buffer void DrawUnderline( - const unsigned int bufferWidth, - const unsigned int bufferHeight, + const uint32_t& bufferWidth, + const uint32_t& bufferHeight, GlyphData& glyphData, - const float baseline, - const float currentUnderlinePosition, - const float maxUnderlineHeight, - const float lineExtentLeft, - const float lineExtentRight, + const float& baseline, + const float& currentUnderlinePosition, + const float& maxUnderlineHeight, + const float& lineExtentLeft, + const float& lineExtentRight, const UnderlineStyleProperties& commonUnderlineProperties, const UnderlineStyleProperties& currentUnderlineProperties, const LineRun& line) @@ -302,76 +296,118 @@ void DrawUnderline( const float dashedUnderlineWidth = currentUnderlineProperties.dashWidthDefined ? currentUnderlineProperties.dashWidth : commonUnderlineProperties.dashWidth; const float dashedUnderlineGap = currentUnderlineProperties.dashGapDefined ? currentUnderlineProperties.dashGap : commonUnderlineProperties.dashGap; - int underlineYOffset = glyphData.verticalOffset + baseline + currentUnderlinePosition; - uint32_t* bitmapBuffer = reinterpret_cast(glyphData.bitmapBuffer.GetBuffer()); + int32_t underlineYOffset = glyphData.verticalOffset + baseline + currentUnderlinePosition; + + const uint32_t yRangeMin = underlineYOffset; + const uint32_t yRangeMax = std::min(bufferHeight, underlineYOffset + static_cast(maxUnderlineHeight)); + const uint32_t xRangeMin = static_cast(glyphData.horizontalOffset + lineExtentLeft); + const uint32_t xRangeMax = std::min(bufferWidth, static_cast(glyphData.horizontalOffset + lineExtentRight + 1)); // Due to include last point, we add 1 here + + // If current glyph don't need to be rendered, just ignore. + if((underlineType != Text::Underline::DOUBLE && yRangeMax <= yRangeMin) || xRangeMax <= xRangeMin) + { + return; + } + + // We can optimize by memset when underlineColor.a is near zero + uint8_t underlineColorAlpha = static_cast(underlineColor.a * 255.f); - for(unsigned int y = underlineYOffset; y < underlineYOffset + maxUnderlineHeight; y++) + uint32_t* bitmapBuffer = reinterpret_cast(glyphData.bitmapBuffer.GetBuffer()); + + // Skip yRangeMin line. + bitmapBuffer += yRangeMin * glyphData.width; + + // Note if underlineType is DASHED, we cannot setup color by memset. + if(underlineType != Text::Underline::DASHED && underlineColorAlpha == 0) { - if(y > bufferHeight - 1) + for(uint32_t y = yRangeMin; y < yRangeMax; y++) { - // Do not write out of bounds. - break; + // We can use memset. + memset(bitmapBuffer + xRangeMin, 0, (xRangeMax - xRangeMin) * sizeof(uint32_t)); + bitmapBuffer += glyphData.width; } - if(underlineType == Text::Underline::DASHED) + if(underlineType == Text::Underline::DOUBLE) { - float dashWidth = dashedUnderlineWidth; - float dashGap = 0; + int32_t secondUnderlineYOffset = underlineYOffset - ONE_AND_A_HALF * maxUnderlineHeight; + const uint32_t secondYRangeMin = static_cast(std::max(0, secondUnderlineYOffset)); + const uint32_t secondYRangeMax = static_cast(std::max(0, std::min(static_cast(bufferHeight), secondUnderlineYOffset + static_cast(maxUnderlineHeight)))); - for(unsigned int x = glyphData.horizontalOffset + lineExtentLeft; x <= glyphData.horizontalOffset + lineExtentRight; x++) + // Rewind bitmapBuffer pointer, and skip secondYRangeMin line. + bitmapBuffer = reinterpret_cast(glyphData.bitmapBuffer.GetBuffer()) + yRangeMin * glyphData.width; + + for(uint32_t y = secondYRangeMin; y < secondYRangeMax; y++) { - if(x > bufferWidth - 1) - { - // Do not write out of bounds. - break; - } - if(dashGap == 0 && dashWidth > 0) - { - WriteColorToPixelBuffer(glyphData, bitmapBuffer, underlineColor, x, y); - dashWidth--; - } - else if(dashGap < dashedUnderlineGap) - { - dashGap++; - } - else - { - //reset - dashWidth = dashedUnderlineWidth; - dashGap = 0; - } + // We can use memset. + memset(bitmapBuffer + xRangeMin, 0, (xRangeMax - xRangeMin) * sizeof(uint32_t)); + bitmapBuffer += glyphData.width; } } - else + } + else + { + uint32_t packedUnderlineColor = 0u; + uint8_t* packedUnderlineColorBuffer = reinterpret_cast(&packedUnderlineColor); + + // Write the color to the pixel buffer + *(packedUnderlineColorBuffer + 3u) = underlineColorAlpha; + *(packedUnderlineColorBuffer + 2u) = static_cast(underlineColor.b * underlineColorAlpha); + *(packedUnderlineColorBuffer + 1u) = static_cast(underlineColor.g * underlineColorAlpha); + *(packedUnderlineColorBuffer) = static_cast(underlineColor.r * underlineColorAlpha); + + for(uint32_t y = yRangeMin; y < yRangeMax; y++) { - for(unsigned int x = glyphData.horizontalOffset + lineExtentLeft; x <= glyphData.horizontalOffset + lineExtentRight; x++) + if(underlineType == Text::Underline::DASHED) { - if(x > bufferWidth - 1) + float dashWidth = dashedUnderlineWidth; + float dashGap = 0; + + for(uint32_t x = xRangeMin; x < xRangeMax; x++) { - // Do not write out of bounds. - break; + if(dashGap == 0 && dashWidth > 0) + { + // Note : this is same logic as bitmap[y][x] = underlineColor; + *(bitmapBuffer + x) = packedUnderlineColor; + dashWidth--; + } + else if(dashGap < dashedUnderlineGap) + { + dashGap++; + } + else + { + //reset + dashWidth = dashedUnderlineWidth; + dashGap = 0; + } } - WriteColorToPixelBuffer(glyphData, bitmapBuffer, underlineColor, x, y); } - } - } - if(underlineType == Text::Underline::DOUBLE) - { - int secondUnderlineYOffset = underlineYOffset - ONE_AND_A_HALF * maxUnderlineHeight; - for(unsigned int y = secondUnderlineYOffset; y < secondUnderlineYOffset + maxUnderlineHeight; y++) - { - if(y > bufferHeight - 1) + else { - // Do not write out of bounds. - break; + for(uint32_t x = xRangeMin; x < xRangeMax; x++) + { + // Note : this is same logic as bitmap[y][x] = underlineColor; + *(bitmapBuffer + x) = packedUnderlineColor; + } } - for(unsigned int x = glyphData.horizontalOffset + lineExtentLeft; x <= glyphData.horizontalOffset + lineExtentRight; x++) + bitmapBuffer += glyphData.width; + } + if(underlineType == Text::Underline::DOUBLE) + { + int32_t secondUnderlineYOffset = underlineYOffset - ONE_AND_A_HALF * maxUnderlineHeight; + const uint32_t secondYRangeMin = static_cast(std::max(0, secondUnderlineYOffset)); + const uint32_t secondYRangeMax = static_cast(std::max(0, std::min(static_cast(bufferHeight), secondUnderlineYOffset + static_cast(maxUnderlineHeight)))); + + // Rewind bitmapBuffer pointer, and skip secondYRangeMin line. + bitmapBuffer = reinterpret_cast(glyphData.bitmapBuffer.GetBuffer()) + yRangeMin * glyphData.width; + + for(uint32_t y = secondYRangeMin; y < secondYRangeMax; y++) { - if(x > bufferWidth - 1) + for(uint32_t x = xRangeMin; x < xRangeMax; x++) { - // Do not write out of bounds. - break; + // Note : this is same logic as bitmap[y][x] = underlineColor; + *(bitmapBuffer + x) = packedUnderlineColor; } - WriteColorToPixelBuffer(glyphData, bitmapBuffer, underlineColor, x, y); + bitmapBuffer += glyphData.width; } } } @@ -379,39 +415,67 @@ void DrawUnderline( /// Draws the background color to the buffer void DrawBackgroundColor( - Vector4 backgroundColor, - const unsigned int bufferWidth, - const unsigned int bufferHeight, - GlyphData& glyphData, - const float baseline, - const LineRun& line, - const float lineExtentLeft, - const float lineExtentRight) + Vector4 backgroundColor, + const uint32_t& bufferWidth, + const uint32_t& bufferHeight, + GlyphData& glyphData, + const float& baseline, + const LineRun& line, + const float& lineExtentLeft, + const float& lineExtentRight) { + const int32_t yRangeMin = std::max(0, static_cast(glyphData.verticalOffset + baseline - line.ascender)); + const int32_t yRangeMax = std::min(static_cast(bufferHeight), static_cast(glyphData.verticalOffset + baseline - line.descender)); + const int32_t xRangeMin = std::max(0, static_cast(glyphData.horizontalOffset + lineExtentLeft)); + const int32_t xRangeMax = std::min(static_cast(bufferWidth), static_cast(glyphData.horizontalOffset + lineExtentRight + 1)); // Due to include last point, we add 1 here + + // If current glyph don't need to be rendered, just ignore. + if(yRangeMax <= yRangeMin || xRangeMax <= xRangeMin) + { + return; + } + + // We can optimize by memset when backgroundColor.a is near zero + uint8_t backgroundColorAlpha = static_cast(backgroundColor.a * 255.f); + uint32_t* bitmapBuffer = reinterpret_cast(glyphData.bitmapBuffer.GetBuffer()); - for(int y = glyphData.verticalOffset + baseline - line.ascender; y < glyphData.verticalOffset + baseline - line.descender; y++) + // Skip yRangeMin line. + bitmapBuffer += yRangeMin * glyphData.width; + + if(backgroundColorAlpha == 0) { - if((y < 0) || (y > static_cast(bufferHeight - 1))) + for(int32_t y = yRangeMin; y < yRangeMax; y++) { - // Do not write out of bounds. - continue; + // We can use memset. + memset(bitmapBuffer + xRangeMin, 0, (xRangeMax - xRangeMin) * sizeof(uint32_t)); + bitmapBuffer += glyphData.width; } + } + else + { + uint32_t packedBackgroundColor = 0u; + uint8_t* packedBackgroundColorBuffer = reinterpret_cast(&packedBackgroundColor); + + // Write the color to the pixel buffer + *(packedBackgroundColorBuffer + 3u) = backgroundColorAlpha; + *(packedBackgroundColorBuffer + 2u) = static_cast(backgroundColor.b * backgroundColorAlpha); + *(packedBackgroundColorBuffer + 1u) = static_cast(backgroundColor.g * backgroundColorAlpha); + *(packedBackgroundColorBuffer) = static_cast(backgroundColor.r * backgroundColorAlpha); - for(int x = glyphData.horizontalOffset + lineExtentLeft; x <= glyphData.horizontalOffset + lineExtentRight; x++) + for(int32_t y = yRangeMin; y < yRangeMax; y++) { - if((x < 0) || (x > static_cast(bufferWidth - 1))) + for(int32_t x = xRangeMin; x < xRangeMax; x++) { - // Do not write out of bounds. - continue; + // Note : this is same logic as bitmap[y][x] = backgroundColor; + *(bitmapBuffer + x) = packedBackgroundColor; } - - WriteColorToPixelBuffer(glyphData, bitmapBuffer, backgroundColor, x, y); + bitmapBuffer += glyphData.width; } } } -Devel::PixelBuffer DrawGlyphsBackground(const ViewModel* model, Devel::PixelBuffer& buffer, const unsigned int bufferWidth, const unsigned int bufferHeight, bool ignoreHorizontalAlignment, int horizontalOffset, int verticalOffset) +Devel::PixelBuffer DrawGlyphsBackground(const ViewModel* model, Devel::PixelBuffer& buffer, const uint32_t& bufferWidth, const uint32_t& bufferHeight, bool ignoreHorizontalAlignment, int32_t horizontalOffset, int32_t verticalOffset) { // Retrieve lines, glyphs, positions and colors from the view model. const Length modelNumberOfLines = model->GetNumberOfLines(); @@ -439,16 +503,16 @@ Devel::PixelBuffer DrawGlyphsBackground(const ViewModel* model, Devel::PixelBuff const LineRun& line = *(modelLinesBuffer + lineIndex); // Sets the horizontal offset of the line. - glyphData.horizontalOffset = ignoreHorizontalAlignment ? 0 : static_cast(line.alignmentOffset); + glyphData.horizontalOffset = ignoreHorizontalAlignment ? 0 : static_cast(line.alignmentOffset); glyphData.horizontalOffset += horizontalOffset; // Increases the vertical offset with the line's ascender. - glyphData.verticalOffset += static_cast(line.ascender); + glyphData.verticalOffset += static_cast(line.ascender); // Include line spacing after first line if(lineIndex > 0u) { - glyphData.verticalOffset += static_cast(line.lineSpacing); + glyphData.verticalOffset += static_cast(line.lineSpacing); } float left = bufferWidth; @@ -515,71 +579,98 @@ Devel::PixelBuffer DrawGlyphsBackground(const ViewModel* model, Devel::PixelBuff } // Increases the vertical offset with the line's descender. - glyphData.verticalOffset += static_cast(-line.descender); + glyphData.verticalOffset += static_cast(-line.descender); } return glyphData.bitmapBuffer; } /// Draws the specified strikethrough color to the buffer -void DrawStrikethrough(const unsigned int bufferWidth, - const unsigned int bufferHeight, +void DrawStrikethrough(const uint32_t& bufferWidth, + const uint32_t& bufferHeight, GlyphData& glyphData, - const float baseline, - const float strikethroughStartingYPosition, - const float maxStrikethroughHeight, - const float lineExtentLeft, - const float lineExtentRight, + const float& baseline, + const float& strikethroughStartingYPosition, + const float& maxStrikethroughHeight, + const float& lineExtentLeft, + const float& lineExtentRight, const StrikethroughStyleProperties& commonStrikethroughProperties, const StrikethroughStyleProperties& currentStrikethroughProperties, const LineRun& line) { const Vector4& strikethroughColor = currentStrikethroughProperties.colorDefined ? currentStrikethroughProperties.color : commonStrikethroughProperties.color; + const uint32_t yRangeMin = static_cast(strikethroughStartingYPosition); + const uint32_t yRangeMax = std::min(bufferHeight, static_cast(strikethroughStartingYPosition + maxStrikethroughHeight)); + const uint32_t xRangeMin = static_cast(glyphData.horizontalOffset + lineExtentLeft); + const uint32_t xRangeMax = std::min(bufferWidth, static_cast(glyphData.horizontalOffset + lineExtentRight + 1)); // Due to include last point, we add 1 here + + // If current glyph don't need to be rendered, just ignore. + if(yRangeMax <= yRangeMin || xRangeMax <= xRangeMin) + { + return; + } + + // We can optimize by memset when strikethroughColor.a is near zero + uint8_t strikethroughColorAlpha = static_cast(strikethroughColor.a * 255.f); + uint32_t* bitmapBuffer = reinterpret_cast(glyphData.bitmapBuffer.GetBuffer()); - for(unsigned int y = strikethroughStartingYPosition; y < strikethroughStartingYPosition + maxStrikethroughHeight; y++) + // Skip yRangeMin line. + bitmapBuffer += yRangeMin * glyphData.width; + + if(strikethroughColorAlpha == 0) { - if(y > bufferHeight - 1) + for(uint32_t y = yRangeMin; y < yRangeMax; y++) { - // Do not write out of bounds. - break; + // We can use memset. + memset(bitmapBuffer + xRangeMin, 0, (xRangeMax - xRangeMin) * sizeof(uint32_t)); + bitmapBuffer += glyphData.width; } + } + else + { + uint32_t packedStrikethroughColor = 0u; + uint8_t* packedStrikethroughColorBuffer = reinterpret_cast(&packedStrikethroughColor); + + // Write the color to the pixel buffer + *(packedStrikethroughColorBuffer + 3u) = strikethroughColorAlpha; + *(packedStrikethroughColorBuffer + 2u) = static_cast(strikethroughColor.b * strikethroughColorAlpha); + *(packedStrikethroughColorBuffer + 1u) = static_cast(strikethroughColor.g * strikethroughColorAlpha); + *(packedStrikethroughColorBuffer) = static_cast(strikethroughColor.r * strikethroughColorAlpha); - for(unsigned int x = glyphData.horizontalOffset + lineExtentLeft; x <= glyphData.horizontalOffset + lineExtentRight; x++) + for(uint32_t y = yRangeMin; y < yRangeMax; y++) { - if(x > bufferWidth - 1) + for(uint32_t x = xRangeMin; x < xRangeMax; x++) { - // Do not write out of bounds. - break; + // Note : this is same logic as bitmap[y][x] = strikethroughColor; + *(bitmapBuffer + x) = packedStrikethroughColor; } - - WriteColorToPixelBuffer(glyphData, bitmapBuffer, strikethroughColor, x, y); + bitmapBuffer += glyphData.width; } } } -} // namespace - -TypesetterPtr Typesetter::New(const ModelInterface* const model) -{ - return TypesetterPtr(new Typesetter(model)); -} - -ViewModel* Typesetter::GetViewModel() -{ - return mModel; -} - -Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, const unsigned int bufferHeight, Pixel::Format pixelFormat) +/** + * @brief Create an initialized image buffer filled with transparent color. + * + * Creates the pixel data used to generate the final image with the given size. + * + * @param[in] bufferWidth The width of the image buffer. + * @param[in] bufferHeight The height of the image buffer. + * @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 An image buffer. + */ +inline Devel::PixelBuffer CreateTransparentImageBuffer(const uint32_t& bufferWidth, const uint32_t& bufferHeight, const Pixel::Format& pixelFormat) { Devel::PixelBuffer imageBuffer = Devel::PixelBuffer::New(bufferWidth, bufferHeight, pixelFormat); if(Pixel::RGBA8888 == pixelFormat) { - const unsigned int bufferSizeInt = bufferWidth * bufferHeight; - const unsigned int bufferSizeChar = 4u * bufferSizeInt; - memset(imageBuffer.GetBuffer(), 0u, bufferSizeChar); + const uint32_t bufferSizeInt = bufferWidth * bufferHeight; + const uint32_t bufferSizeChar = sizeof(uint32_t) * bufferSizeInt; + memset(imageBuffer.GetBuffer(), 0, bufferSizeChar); } else { @@ -589,6 +680,125 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, return imageBuffer; } +/** + * @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. + * + * Due to the performance issue, We need to re-use input'ed pixelBuffer memory. + * We can determine which pixelBuffer's memory is destination + * + * @param[in, out] topPixelBuffer The top layer buffer. + * @param[in, out] bottomPixelBuffer The bottom layer buffer. + * @param[in] bufferWidth The width of the image buffer. + * @param[in] bufferHeight The height of the image buffer. + * @param[in] storeResultIntoTop True if we store the combined image buffer result into topPixelBuffer. + * False if we store the combined image buffer result into bottomPixelBuffer. + * + */ +void CombineImageBuffer(Devel::PixelBuffer& topPixelBuffer, Devel::PixelBuffer& bottomPixelBuffer, const uint32_t& bufferWidth, const uint32_t& bufferHeight, bool storeResultIntoTop) +{ + // Assume that we always combine two RGBA images + // Jump with 4bytes for optimize runtime. + uint32_t* topBuffer = reinterpret_cast(topPixelBuffer.GetBuffer()); + uint32_t* bottomBuffer = reinterpret_cast(bottomPixelBuffer.GetBuffer()); + + if(topBuffer == NULL && bottomBuffer == NULL) + { + // Nothing to do if both buffers are empty. + return; + } + + if(topBuffer == NULL) + { + // Nothing to do if topBuffer is empty. + // If we need to store the result into top, change topPixelBuffer as bottomPixelBuffer. + if(storeResultIntoTop) + { + topPixelBuffer = bottomPixelBuffer; + } + return; + } + + if(bottomBuffer == NULL) + { + // Nothing to do if bottomBuffer is empty. + // If we need to store the result into bottom, change bottomPixelBuffer as topPixelBuffer. + if(!storeResultIntoTop) + { + bottomPixelBuffer = topPixelBuffer; + } + return; + } + + const uint32_t bufferSizeInt = bufferWidth * bufferHeight; + + uint32_t* combinedBuffer = storeResultIntoTop ? topBuffer : bottomBuffer; + uint8_t* topAlphaBufferPointer = reinterpret_cast(topBuffer) + 3; + + for(uint32_t 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. + // Note : Be careful when we read & write into combinedBuffer. It can be write into same pointer. + + uint8_t topAlpha = *topAlphaBufferPointer; + + if(topAlpha == 0) + { + // Copy the pixel from bottomBuffer to combinedBuffer + if(storeResultIntoTop) + { + *(combinedBuffer) = *(bottomBuffer); + } + } + else if(topAlpha == 255) + { + // Copy the pixel from topBuffer to combinedBuffer + if(!storeResultIntoTop) + { + *(combinedBuffer) = *(topBuffer); + } + } + else + { + // At least one pixel is not fully opaque + // "Over" blend the the pixel from topBuffer with the pixel in bottomBuffer + uint32_t blendedBottomBufferColor = *(bottomBuffer); + uint8_t* blendedBottomBufferColorBuffer = reinterpret_cast(&blendedBottomBufferColor); + + blendedBottomBufferColorBuffer[0] = MultiplyAndNormalizeColor(blendedBottomBufferColorBuffer[0], 255 - topAlpha); + blendedBottomBufferColorBuffer[1] = MultiplyAndNormalizeColor(blendedBottomBufferColorBuffer[1], 255 - topAlpha); + blendedBottomBufferColorBuffer[2] = MultiplyAndNormalizeColor(blendedBottomBufferColorBuffer[2], 255 - topAlpha); + blendedBottomBufferColorBuffer[3] = MultiplyAndNormalizeColor(blendedBottomBufferColorBuffer[3], 255 - topAlpha); + + *(combinedBuffer) = *(topBuffer) + blendedBottomBufferColor; + } + + // Increase each buffer's pointer. + ++combinedBuffer; + ++topBuffer; + ++bottomBuffer; + topAlphaBufferPointer += sizeof(uint32_t) / sizeof(uint8_t); + } +} + +} // namespace + +TypesetterPtr Typesetter::New(const ModelInterface* const model) +{ + return TypesetterPtr(new Typesetter(model)); +} + +ViewModel* Typesetter::GetViewModel() +{ + return mModel; +} + PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirection::Type textDirection, RenderBehaviour behaviour, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat) { // @todo. This initial implementation for a TextLabel has only one visible page. @@ -599,10 +809,10 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect // Retrieves the layout size. const Size& layoutSize = mModel->GetLayoutSize(); - const int outlineWidth = static_cast(mModel->GetOutlineWidth()); + const int32_t outlineWidth = static_cast(mModel->GetOutlineWidth()); // Set the offset for the horizontal alignment according to the text direction and outline width. - int penX = 0; + int32_t penX = 0; switch(mModel->GetHorizontalAlignment()) { @@ -624,7 +834,7 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect } // Set the offset for the vertical alignment. - int penY = 0u; + int32_t penY = 0u; switch(mModel->GetVerticalAlignment()) { @@ -635,13 +845,13 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect } case VerticalAlignment::CENTER: { - penY = static_cast(0.5f * (size.height - layoutSize.height)); + penY = static_cast(0.5f * (size.height - layoutSize.height)); penY = penY < 0.f ? 0.f : penY; break; } case VerticalAlignment::BOTTOM: { - penY = static_cast(size.height - layoutSize.height); + penY = static_cast(size.height - layoutSize.height); break; } } @@ -657,14 +867,14 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect { const auto& line = *mModel->GetLines(); penY -= line.descender; - penY += static_cast(line.lineSpacing * 0.5f + line.descender); + penY += static_cast(line.lineSpacing * 0.5f + line.descender); break; } case DevelText::VerticalLineAlignment::BOTTOM: { const auto& line = *mModel->GetLines(); const auto lineHeight = line.ascender + (-line.descender) + line.lineSpacing; - penY += static_cast(lineHeight - (line.ascender - line.descender)); + penY += static_cast(lineHeight - (line.ascender - line.descender)); break; } } @@ -674,11 +884,11 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect // 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 uint32_t bufferWidth = static_cast(size.width); + const uint32_t bufferHeight = static_cast(size.height); - const unsigned int bufferSizeInt = bufferWidth * bufferHeight; - const unsigned int bufferSizeChar = 4u * bufferSizeInt; + const uint32_t bufferSizeInt = bufferWidth * bufferHeight; + const uint32_t bufferSizeChar = sizeof(uint32_t) * bufferSizeInt; //Elided text in ellipsis at START could start on index greater than 0 auto startIndexOfGlyphs = mModel->GetStartIndexOfElidedGlyphs(); @@ -713,7 +923,7 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect Devel::PixelBuffer outlineImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_OUTLINE, ignoreHorizontalAlignment, pixelFormat, penX, penY, startIndexOfGlyphs, endIndexOfGlyphs); // Combine the two buffers - imageBuffer = CombineImageBuffer(imageBuffer, outlineImageBuffer, bufferWidth, bufferHeight); + CombineImageBuffer(imageBuffer, outlineImageBuffer, bufferWidth, bufferHeight, true); } // @todo. Support shadow and underline for partial text later on. @@ -734,7 +944,7 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect } // Combine the two buffers - imageBuffer = CombineImageBuffer(imageBuffer, shadowImageBuffer, bufferWidth, bufferHeight); + CombineImageBuffer(imageBuffer, shadowImageBuffer, bufferWidth, bufferHeight, true); } // Generate the underline if enabled @@ -745,7 +955,7 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect Devel::PixelBuffer underlineImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_UNDERLINE, ignoreHorizontalAlignment, pixelFormat, penX, penY, startIndexOfGlyphs, endIndexOfGlyphs); // Combine the two buffers - imageBuffer = CombineImageBuffer(imageBuffer, underlineImageBuffer, bufferWidth, bufferHeight); + CombineImageBuffer(imageBuffer, underlineImageBuffer, bufferWidth, bufferHeight, true); } // Generate the background if enabled @@ -761,7 +971,7 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect } else { - backgroundImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, pixelFormat); + backgroundImageBuffer = CreateTransparentImageBuffer(bufferWidth, bufferHeight, pixelFormat); } if(backgroundMarkupSet) @@ -770,7 +980,7 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect } // Combine the two buffers - imageBuffer = CombineImageBuffer(imageBuffer, backgroundImageBuffer, bufferWidth, bufferHeight); + CombineImageBuffer(imageBuffer, backgroundImageBuffer, bufferWidth, bufferHeight, true); } // Generate the strikethrough if enabled @@ -781,7 +991,7 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect Devel::PixelBuffer strikethroughImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_STRIKETHROUGH, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, endIndexOfGlyphs); // Combine the two buffers - imageBuffer = CombineImageBuffer(imageBuffer, strikethroughImageBuffer, bufferWidth, bufferHeight); + CombineImageBuffer(imageBuffer, strikethroughImageBuffer, bufferWidth, bufferHeight, true); } // Markup-Processor @@ -795,7 +1005,7 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect return pixelData; } -Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, const unsigned int bufferHeight, Typesetter::Style style, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int horizontalOffset, int verticalOffset, GlyphIndex fromGlyphIndex, GlyphIndex toGlyphIndex) +Devel::PixelBuffer Typesetter::CreateImageBuffer(const uint32_t& bufferWidth, const uint32_t& bufferHeight, Typesetter::Style style, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, const int32_t& horizontalOffset, const int32_t& verticalOffset, GlyphIndex fromGlyphIndex, GlyphIndex toGlyphIndex) { // Retrieve lines, glyphs, positions and colors from the view model. const Length modelNumberOfLines = mModel->GetNumberOfLines(); @@ -824,7 +1034,7 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, glyphData.verticalOffset = verticalOffset; glyphData.width = bufferWidth; glyphData.height = bufferHeight; - glyphData.bitmapBuffer = CreateImageBuffer(bufferWidth, bufferHeight, pixelFormat); + glyphData.bitmapBuffer = CreateTransparentImageBuffer(bufferWidth, bufferHeight, pixelFormat); glyphData.horizontalOffset = 0; // Get a handle of the font client. Used to retrieve the bitmaps of the glyphs. @@ -842,11 +1052,11 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, const LineRun& line = *(modelLinesBuffer + lineIndex); // Sets the horizontal offset of the line. - glyphData.horizontalOffset = ignoreHorizontalAlignment ? 0 : static_cast(line.alignmentOffset); + glyphData.horizontalOffset = ignoreHorizontalAlignment ? 0 : static_cast(line.alignmentOffset); glyphData.horizontalOffset += horizontalOffset; // Increases the vertical offset with the line's ascender. - glyphData.verticalOffset += static_cast(line.ascender); + glyphData.verticalOffset += static_cast(line.ascender); // Retrieves the glyph's outline width float outlineWidth = static_cast(mModel->GetOutlineWidth()); @@ -930,18 +1140,12 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, bool addHyphen = false; // Traverses the glyphs of the line. - const GlyphIndex startGlyphIndex = std::max(line.glyphRun.glyphIndex, startIndexOfGlyphs); + const GlyphIndex startGlyphIndex = std::max(std::max(line.glyphRun.glyphIndex, startIndexOfGlyphs), fromGlyphIndex); GlyphIndex endGlyphIndex = (line.isSplitToTwoHalves ? line.glyphRunSecondHalf.glyphIndex + line.glyphRunSecondHalf.numberOfGlyphs : line.glyphRun.glyphIndex + line.glyphRun.numberOfGlyphs) - 1u; - endGlyphIndex = std::min(endGlyphIndex, endIndexOfGlyphs); + endGlyphIndex = std::min(std::min(endGlyphIndex, endIndexOfGlyphs), toGlyphIndex); for(GlyphIndex glyphIndex = startGlyphIndex; glyphIndex <= endGlyphIndex; ++glyphIndex) { - if(glyphIndex < fromGlyphIndex || glyphIndex > toGlyphIndex) - { - // Ignore any glyph that out of the specified range - continue; - } - //To handle START case of ellipsis, the first glyph has been shifted //glyphIndex represent indices in whole glyphs but elidedGlyphIndex represents indices in elided Glyphs GlyphIndex elidedGlyphIndex = glyphIndex - startIndexOfGlyphs; @@ -1085,7 +1289,7 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, glyphInfo->isItalicRequired, glyphInfo->isBoldRequired, glyphData.glyphBitmap, - static_cast(outlineWidth)); + static_cast(outlineWidth)); } // Sets the glyph's bitmap into the bitmap of the whole text. @@ -1153,75 +1357,13 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, } // Increases the vertical offset with the line's descender & line spacing. - glyphData.verticalOffset += static_cast(-line.descender+line.lineSpacing); + glyphData.verticalOffset += static_cast(-line.descender + line.lineSpacing); } 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(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]; - - if(alphaBuffer1 != 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] + (bottomBuffer[pixelIndex * 4] * (255 - topBuffer[pixelIndex * 4 + 3]) / 255); - combinedBuffer[pixelIndex * 4 + 1] = topBuffer[pixelIndex * 4 + 1] + (bottomBuffer[pixelIndex * 4 + 1] * (255 - topBuffer[pixelIndex * 4 + 3]) / 255); - combinedBuffer[pixelIndex * 4 + 2] = topBuffer[pixelIndex * 4 + 2] + (bottomBuffer[pixelIndex * 4 + 2] * (255 - topBuffer[pixelIndex * 4 + 3]) / 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; -} - -Devel::PixelBuffer Typesetter::ApplyUnderlineMarkupImageBuffer(Devel::PixelBuffer topPixelBuffer, const unsigned int bufferWidth, const unsigned int bufferHeight, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int horizontalOffset, int verticalOffset) +Devel::PixelBuffer Typesetter::ApplyUnderlineMarkupImageBuffer(Devel::PixelBuffer topPixelBuffer, const uint32_t& bufferWidth, const uint32_t& bufferHeight, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, const int32_t& horizontalOffset, const int32_t& verticalOffset) { // Underline-tags (this is for Markup case) // Get the underline runs. @@ -1244,7 +1386,8 @@ Devel::PixelBuffer Typesetter::ApplyUnderlineMarkupImageBuffer(Devel::PixelBuffe // Create the image buffer for underline Devel::PixelBuffer underlineImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_UNDERLINE, ignoreHorizontalAlignment, pixelFormat, horizontalOffset, verticalOffset, startGlyphIndex, endGlyphIndex); // Combine the two buffers - topPixelBuffer = CombineImageBuffer(underlineImageBuffer, topPixelBuffer, bufferWidth, bufferHeight); + // Result pixel buffer will be stored into topPixelBuffer. + CombineImageBuffer(underlineImageBuffer, topPixelBuffer, bufferWidth, bufferHeight, false); itGlyphRun++; } @@ -1252,7 +1395,7 @@ Devel::PixelBuffer Typesetter::ApplyUnderlineMarkupImageBuffer(Devel::PixelBuffe return topPixelBuffer; } -Devel::PixelBuffer Typesetter::ApplyStrikethroughMarkupImageBuffer(Devel::PixelBuffer topPixelBuffer, const unsigned int bufferWidth, const unsigned int bufferHeight, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int horizontalOffset, int verticalOffset) +Devel::PixelBuffer Typesetter::ApplyStrikethroughMarkupImageBuffer(Devel::PixelBuffer topPixelBuffer, const uint32_t& bufferWidth, const uint32_t& bufferHeight, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, const int32_t& horizontalOffset, const int32_t& verticalOffset) { // strikethrough-tags (this is for Markup case) // Get the strikethrough runs. @@ -1275,7 +1418,8 @@ Devel::PixelBuffer Typesetter::ApplyStrikethroughMarkupImageBuffer(Devel::PixelB // Create the image buffer for strikethrough Devel::PixelBuffer strikethroughImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_STRIKETHROUGH, ignoreHorizontalAlignment, pixelFormat, horizontalOffset, verticalOffset, startGlyphIndex, endGlyphIndex); // Combine the two buffers - topPixelBuffer = CombineImageBuffer(strikethroughImageBuffer, topPixelBuffer, bufferWidth, bufferHeight); + // Result pixel buffer will be stored into topPixelBuffer. + CombineImageBuffer(strikethroughImageBuffer, topPixelBuffer, bufferWidth, bufferHeight, false); itGlyphRun++; } @@ -1283,7 +1427,7 @@ Devel::PixelBuffer Typesetter::ApplyStrikethroughMarkupImageBuffer(Devel::PixelB return topPixelBuffer; } -Devel::PixelBuffer Typesetter::ApplyMarkupProcessorOnPixelBuffer(Devel::PixelBuffer topPixelBuffer, const unsigned int bufferWidth, const unsigned int bufferHeight, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int horizontalOffset, int verticalOffset) +Devel::PixelBuffer Typesetter::ApplyMarkupProcessorOnPixelBuffer(Devel::PixelBuffer topPixelBuffer, const uint32_t& bufferWidth, const uint32_t& bufferHeight, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, const int32_t& horizontalOffset, const int32_t& verticalOffset) { // Apply the markup-Processor if enabled const bool markupProcessorEnabled = mModel->IsMarkupProcessorEnabled(); diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.h b/dali-toolkit/internal/text/rendering/text-typesetter.h index bf46b90..3f9dd66 100644 --- a/dali-toolkit/internal/text/rendering/text-typesetter.h +++ b/dali-toolkit/internal/text/rendering/text-typesetter.h @@ -144,39 +144,7 @@ private: * * @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 horizontalOffset, int verticalOffset, TextAbstraction::GlyphIndex fromGlyphIndex, TextAbstraction::GlyphIndex toGlyphIndex); - - /** - * @brief Create an initialized image buffer. - * - * Creates the pixel data used to generate the final image with the given size. - * - * @param[in] bufferWidth The width of the image buffer. - * @param[in] bufferHeight The height of the image buffer. - * @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 An image buffer. - */ - Devel::PixelBuffer CreateImageBuffer(const unsigned int bufferWidth, const unsigned int bufferHeight, Pixel::Format pixelFormat); - - /** - * @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); + Devel::PixelBuffer CreateImageBuffer(const uint32_t& bufferWidth, const uint32_t& bufferHeight, Typesetter::Style style, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, const int32_t& horizontalOffset, const int32_t& verticalOffset, TextAbstraction::GlyphIndex fromGlyphIndex, TextAbstraction::GlyphIndex toGlyphIndex); /** * @brief Apply behaviour of tags if the markup-processor is enabled. @@ -191,7 +159,7 @@ private: * * @return The image buffer with the markup. */ - Devel::PixelBuffer ApplyMarkupProcessorOnPixelBuffer(Devel::PixelBuffer topPixelBuffer, const unsigned int bufferWidth, const unsigned int bufferHeight, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int horizontalOffset, int verticalOffset); + Devel::PixelBuffer ApplyMarkupProcessorOnPixelBuffer(Devel::PixelBuffer topPixelBuffer, const uint32_t& bufferWidth, const uint32_t& bufferHeight, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, const int32_t& horizontalOffset, const int32_t& verticalOffset); /** * @brief Apply markup underline tags. @@ -212,7 +180,7 @@ private: * * @return The image buffer with the markup. */ - Devel::PixelBuffer ApplyUnderlineMarkupImageBuffer(Devel::PixelBuffer topPixelBuffer, const unsigned int bufferWidth, const unsigned int bufferHeight, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int horizontalOffset, int verticalOffset); + Devel::PixelBuffer ApplyUnderlineMarkupImageBuffer(Devel::PixelBuffer topPixelBuffer, const uint32_t& bufferWidth, const uint32_t& bufferHeight, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, const int32_t& horizontalOffset, const int32_t& verticalOffset); /** * @brief Apply markup strikethrough tags. @@ -233,7 +201,7 @@ private: * * @return The image buffer with the markup. */ - Devel::PixelBuffer ApplyStrikethroughMarkupImageBuffer(Devel::PixelBuffer topPixelBuffer, const unsigned int bufferWidth, const unsigned int bufferHeight, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int horizontalOffset, int verticalOffset); + Devel::PixelBuffer ApplyStrikethroughMarkupImageBuffer(Devel::PixelBuffer topPixelBuffer, const uint32_t& bufferWidth, const uint32_t& bufferHeight, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, const int32_t& horizontalOffset, const int32_t& verticalOffset); protected: /** diff --git a/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp b/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp index 01e43a4..85d2e87 100644 --- a/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp +++ b/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp @@ -484,17 +484,16 @@ TextureCacheManager::TextureHash TextureCacheManager::GenerateHash( const bool& cropToMask, const std::uint32_t& frameIndex) { - std::vector hashTarget(url.GetUrl().begin(), url.GetUrl().end()); - const size_t urlLength = hashTarget.size(); - const uint16_t width = size.GetWidth(); - const uint16_t height = size.GetWidth(); + std::vector hashTarget; + const uint16_t width = size.GetWidth(); + const uint16_t height = size.GetWidth(); // If either the width or height has been specified, include the resizing options in the hash if(width != 0 || height != 0) { // We are appending 5 bytes to the URL to form the hash input. - hashTarget.resize(urlLength + 5u); - std::uint8_t* hashTargetPtr = &(hashTarget[urlLength]); + hashTarget.resize(5u); + std::uint8_t* hashTargetPtr = &(hashTarget[0u]); // Pack the width and height (4 bytes total). *hashTargetPtr++ = size.GetWidth() & 0xff; @@ -509,19 +508,19 @@ TextureCacheManager::TextureHash TextureCacheManager::GenerateHash( else { // We are not including sizing information, but we still need an extra byte for atlasing. - hashTarget.resize(urlLength + 1u); + hashTarget.resize(1u); // Add the atlasing to the hash input. switch(useAtlas) { case UseAtlas::NO_ATLAS: { - hashTarget[urlLength] = 'f'; + hashTarget[0u] = 'f'; break; } case UseAtlas::USE_ATLAS: { - hashTarget[urlLength] = 't'; + hashTarget[0u] = 't'; break; } } @@ -560,7 +559,7 @@ TextureCacheManager::TextureHash TextureCacheManager::GenerateHash( } } - return Dali::CalculateHash(hashTarget); + return url.GetUrlHash() ^ Dali::CalculateHash(hashTarget); } TextureCacheManager::TextureCacheIndex TextureCacheManager::FindCachedTexture( diff --git a/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp b/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp index 5b7597e..81a73db 100644 --- a/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp +++ b/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp @@ -139,6 +139,7 @@ TextureManager::~TextureManager() } TextureSet TextureManager::LoadAnimatedImageTexture( + const VisualUrl& url, Dali::AnimatedImageLoading animatedImageLoading, const uint32_t& frameIndex, TextureManager::TextureId& textureId, @@ -200,7 +201,7 @@ TextureSet TextureManager::LoadAnimatedImageTexture( } auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY; - textureId = RequestLoadInternal(animatedImageLoading.GetUrl(), alphaMaskId, contentScaleFactor, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, UseAtlas::NO_ATLAS, cropToMask, StorageType::UPLOAD_TO_TEXTURE, textureObserver, true, TextureManager::ReloadPolicy::CACHED, preMultiply, animatedImageLoading, frameIndex, false); + textureId = RequestLoadInternal(url, alphaMaskId, contentScaleFactor, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, UseAtlas::NO_ATLAS, cropToMask, StorageType::UPLOAD_TO_TEXTURE, textureObserver, true, TextureManager::ReloadPolicy::CACHED, preMultiply, animatedImageLoading, frameIndex, false); TextureManager::LoadState loadState = mTextureCacheManager.GetTextureStateInternal(textureId); if(loadState == TextureManager::LoadState::UPLOADED) diff --git a/dali-toolkit/internal/texture-manager/texture-manager-impl.h b/dali-toolkit/internal/texture-manager/texture-manager-impl.h index 5800e54..91f7778 100644 --- a/dali-toolkit/internal/texture-manager/texture-manager-impl.h +++ b/dali-toolkit/internal/texture-manager/texture-manager-impl.h @@ -112,6 +112,7 @@ public: * The parameters are used to specify how the animated image is loaded. * The observer has the LoadComplete method called when the load is ready. * + * @param[in] url The URL of the image to load * @param[in] animatedImageLoading The AnimatedImageLoading that contain the animated image information * @param[in] frameIndex The frame index to load. * @param[out] textureId The textureId of the frame @@ -125,7 +126,8 @@ public: * * @return The texture set containing the frame of animated image, or empty if still loading. */ - TextureSet LoadAnimatedImageTexture(Dali::AnimatedImageLoading animatedImageLoading, + TextureSet LoadAnimatedImageTexture(const VisualUrl& url, + Dali::AnimatedImageLoading animatedImageLoading, const uint32_t& frameIndex, TextureManager::TextureId& textureId, MaskingDataPointer& maskInfo, 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 b704d34..719329d 100644 --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp @@ -163,7 +163,7 @@ AnimatedImageVisualPtr AnimatedImageVisual::New(VisualFactoryCache& factoryCache void AnimatedImageVisual::InitializeAnimatedImage(const VisualUrl& imageUrl) { - mImageUrl = imageUrl; + mImageUrl = imageUrl; mAnimatedImageLoading = AnimatedImageLoading::New(imageUrl.GetUrl(), imageUrl.IsLocalResource()); } @@ -253,7 +253,7 @@ void AnimatedImageVisual::GetNaturalSize(Vector2& naturalSize) ImageDimensions dimensions = Dali::GetClosestImageSize(mMaskingData->mAlphaMaskUrl.GetUrl()); if(dimensions != ImageDimensions(0, 0)) { - mImageSize = dimensions; + mImageSize = dimensions; naturalSize.x = dimensions.GetWidth(); naturalSize.y = dimensions.GetHeight(); return; @@ -266,7 +266,7 @@ void AnimatedImageVisual::GetNaturalSize(Vector2& naturalSize) } else if(mImageUrls && mImageUrls->size() > 0) { - mImageSize = Dali::GetClosestImageSize((*mImageUrls)[0].mUrl); + mImageSize = Dali::GetClosestImageSize((*mImageUrls)[0].mUrl.GetUrl()); } } @@ -292,7 +292,7 @@ void AnimatedImageVisual::DoCreatePropertyMap(Property::Map& map) const Property::Array urls; for(unsigned int i = 0; i < mImageUrls->size(); ++i) { - urls.Add((*mImageUrls)[i].mUrl); + urls.Add((*mImageUrls)[i].mUrl.GetUrl()); } Property::Value value(const_cast(urls)); map.Insert(Toolkit::ImageVisual::Property::URL, value); @@ -307,8 +307,7 @@ void AnimatedImageVisual::DoCreatePropertyMap(Property::Map& map) const map.Insert(Toolkit::ImageVisual::Property::FRAME_DELAY, static_cast(mFrameDelay)); map.Insert(Toolkit::DevelImageVisual::Property::LOOP_COUNT, static_cast(mLoopCount)); map.Insert(Toolkit::DevelImageVisual::Property::CURRENT_FRAME_NUMBER, (mImageCache) ? static_cast(mImageCache->GetCurrentFrameIndex()) : -1); - map.Insert(Toolkit::DevelImageVisual::Property::TOTAL_FRAME_NUMBER, (mImageCache) ? static_cast((mAnimatedImageLoading) ? mAnimatedImageLoading.GetImageCount() : - mImageCache->GetTotalFrameCount()) : -1); + map.Insert(Toolkit::DevelImageVisual::Property::TOTAL_FRAME_NUMBER, (mImageCache) ? static_cast((mAnimatedImageLoading) ? mAnimatedImageLoading.GetImageCount() : mImageCache->GetTotalFrameCount()) : -1); map.Insert(Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR, mStopBehavior); @@ -358,7 +357,7 @@ void AnimatedImageVisual::OnDoAction(const Dali::Property::Index actionId, const { // STOP reset functionality will actually be done in a future change // Stop will be executed on next timer tick - mActionStatus = DevelAnimatedImageVisual::Action::STOP; + mActionStatus = DevelAnimatedImageVisual::Action::STOP; mCurrentLoopIndex = FIRST_LOOP; if(IsOnScene()) { @@ -578,11 +577,11 @@ void AnimatedImageVisual::DoSetProperty(Property::Index index, value.Get(sync); if(sync) { - mImpl->mFlags |= Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; + mImpl->mFlags |= Visual::Base::Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; } else { - mImpl->mFlags &= ~Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; + mImpl->mFlags &= ~Visual::Base::Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; } break; } @@ -640,8 +639,8 @@ void AnimatedImageVisual::DoSetProperty(Property::Index index, void AnimatedImageVisual::DoSetOnScene(Actor& actor) { - mStartFirstFrame = true; - mPlacementActor = actor; + mStartFirstFrame = true; + mPlacementActor = actor; PrepareTextureSet(); } @@ -666,9 +665,9 @@ void AnimatedImageVisual::DoSetOffScene(Actor& actor) } mPlacementActor.Reset(); - mStartFirstFrame = false; + mStartFirstFrame = false; mCurrentFrameIndex = FIRST_FRAME_INDEX; - mCurrentLoopIndex = FIRST_LOOP; + mCurrentLoopIndex = FIRST_LOOP; } void AnimatedImageVisual::OnSetTransform() diff --git a/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp b/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp index 8cc69ff..97b8d35 100644 --- a/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp +++ b/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -31,7 +31,7 @@ namespace Internal { namespace { -constexpr bool ENABLE_ORIENTATION_CORRECTION(true); +constexpr bool ENABLE_ORIENTATION_CORRECTION(true); constexpr uint32_t FIRST_FRAME_INDEX = 0u; } // namespace @@ -112,8 +112,8 @@ void FixedImageCache::LoadBatch() // Once the cache is filled, no more images are loaded. for(unsigned int i = 0; i < mBatchSize && mReadyFlags.size() < mImageUrls.size(); ++i) { - uint32_t frameIndex = mReadyFlags.size(); - std::string& url = mImageUrls[frameIndex].mUrl; + uint32_t frameIndex = mReadyFlags.size(); + VisualUrl& url = mImageUrls[frameIndex].mUrl; mReadyFlags.push_back(false); @@ -121,16 +121,16 @@ void FixedImageCache::LoadBatch() // from within this method. This means it won't yet have a texture id, so we // need to account for this inside the LoadComplete method using mRequestingLoad. mRequestingLoad = true; - mLoadState = TextureManager::LoadState::LOADING; + mLoadState = TextureManager::LoadState::LOADING; - bool synchronousLoading = false; - bool atlasingStatus = false; - bool loadingStatus = false; - AtlasUploadObserver* atlasObserver = nullptr; - ImageAtlasManagerPtr imageAtlasManager = nullptr; - Vector4 textureRect; - Dali::ImageDimensions textureRectSize; - auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY; + bool synchronousLoading = false; + bool atlasingStatus = false; + bool loadingStatus = false; + AtlasUploadObserver* atlasObserver = nullptr; + ImageAtlasManagerPtr imageAtlasManager = nullptr; + Vector4 textureRect; + Dali::ImageDimensions textureRectSize; + auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY; mTextureManager.LoadTexture( url, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, mMaskingData, synchronousLoading, mImageUrls[frameIndex].mTextureId, textureRect, textureRectSize, atlasingStatus, loadingStatus, Dali::WrapMode::Type::DEFAULT, Dali::WrapMode::Type::DEFAULT, this, atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiply); @@ -181,7 +181,7 @@ void FixedImageCache::LoadComplete(bool loadSuccess, TextureInformation textureI { if(loadSuccess) { - mLoadState = TextureManager::LoadState::LOAD_FINISHED; + mLoadState = TextureManager::LoadState::LOAD_FINISHED; bool frontFrameReady = IsFrontReady(); if(!mRequestingLoad) { diff --git a/dali-toolkit/internal/visuals/animated-image/image-cache.h b/dali-toolkit/internal/visuals/animated-image/image-cache.h index 65f39df..d3b6b0a 100644 --- a/dali-toolkit/internal/visuals/animated-image/image-cache.h +++ b/dali-toolkit/internal/visuals/animated-image/image-cache.h @@ -47,7 +47,7 @@ public: struct UrlStore { TextureManager::TextureId mTextureId = TextureManager::INVALID_TEXTURE_ID; - std::string mUrl; + VisualUrl mUrl; }; /** diff --git a/dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.cpp b/dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.cpp index 33df7b8..2929d89 100644 --- a/dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.cpp +++ b/dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.cpp @@ -27,16 +27,16 @@ namespace #if defined(DEBUG_ENABLED) Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_ANIMATED_IMAGE"); -#define LOG_CACHE \ - { \ - std::ostringstream oss; \ - oss << "Size:" << mQueue.Count() << " [ "; \ - for(std::size_t _i = 0; _i < mQueue.Count(); ++_i) \ - { \ - oss << _i << "={ frm#: " << mQueue[_i].mFrameNumber << " tex: " << mImageUrls[mQueue[_i].mFrameNumber].mTextureId << "}, "; \ - } \ - oss << " ]" << std::endl; \ - DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "%s", oss.str().c_str()); \ +#define LOG_CACHE \ + { \ + std::ostringstream oss; \ + oss << "Size:" << mQueue.Count() << " [ "; \ + for(std::size_t _i = 0; _i < mQueue.Count(); ++_i) \ + { \ + oss << _i << "={ frm#: " << mQueue[_i].mFrameNumber << " tex: " << mTextureIds[mQueue[_i].mFrameNumber] << "}, "; \ + } \ + oss << " ]" << std::endl; \ + DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "%s", oss.str().c_str()); \ } #else @@ -67,6 +67,7 @@ RollingAnimatedImageCache::RollingAnimatedImageCache(TextureManager& uint16_t batchSize, bool isSynchronousLoading) : ImageCache(textureManager, maskingData, observer, batchSize, 0u), + mImageUrl(animatedImageLoading.GetUrl()), mAnimatedImageLoading(animatedImageLoading), mFrameCount(SINGLE_IMAGE_COUNT), mFrameIndex(FIRST_FRAME_INDEX), @@ -74,7 +75,7 @@ RollingAnimatedImageCache::RollingAnimatedImageCache(TextureManager& mQueue(cacheSize), mIsSynchronousLoading(isSynchronousLoading) { - mImageUrls.resize(mFrameCount); + mTextureIds.resize(mFrameCount); mIntervals.assign(mFrameCount, 0); } @@ -191,7 +192,8 @@ TextureSet RollingAnimatedImageCache::RequestFrameLoading(uint32_t frameIndex, b mLoadState = TextureManager::LoadState::LOADING; TextureManager::TextureId loadTextureId = TextureManager::INVALID_TEXTURE_ID; - TextureSet textureSet = mTextureManager.LoadAnimatedImageTexture(mAnimatedImageLoading, + TextureSet textureSet = mTextureManager.LoadAnimatedImageTexture(mImageUrl, + mAnimatedImageLoading, frameIndex, loadTextureId, mMaskingData, @@ -201,7 +203,7 @@ TextureSet RollingAnimatedImageCache::RequestFrameLoading(uint32_t frameIndex, b synchronousLoading, this); - mImageUrls[frameIndex].mTextureId = loadTextureId; + mTextureIds[frameIndex] = loadTextureId; return textureSet; } @@ -252,14 +254,14 @@ TextureSet RollingAnimatedImageCache::GetFrontTextureSet() const TextureManager::TextureId RollingAnimatedImageCache::GetCachedTextureId(int index) const { - return mImageUrls[mQueue[index].mFrameNumber].mTextureId; + return mTextureIds[mQueue[index].mFrameNumber]; } void RollingAnimatedImageCache::PopFrontCache() { ImageFrame imageFrame = mQueue.PopFront(); - mTextureManager.Remove(mImageUrls[imageFrame.mFrameNumber].mTextureId, this); - mImageUrls[imageFrame.mFrameNumber].mTextureId = TextureManager::INVALID_TEXTURE_ID; + mTextureManager.Remove(mTextureIds[imageFrame.mFrameNumber], this); + mTextureIds[imageFrame.mFrameNumber] = TextureManager::INVALID_TEXTURE_ID; if(mMaskingData && mMaskingData->mAlphaMaskId != TextureManager::INVALID_TEXTURE_ID) { @@ -296,7 +298,7 @@ void RollingAnimatedImageCache::MakeFrameReady(bool loadSuccess, TextureSet text if(mFrameCount != mAnimatedImageLoading.GetImageCount()) { mFrameCount = mAnimatedImageLoading.GetImageCount(); - mImageUrls.resize(mFrameCount); + mTextureIds.resize(mFrameCount); mIntervals.assign(mFrameCount, 0u); } diff --git a/dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.h b/dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.h index 1a772ce..f520907 100644 --- a/dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.h +++ b/dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.h @@ -170,12 +170,13 @@ private: uint32_t mFrameNumber = 0u; bool mReady = false; }; + std::vector mTextureIds; + VisualUrl mImageUrl; Dali::AnimatedImageLoading mAnimatedImageLoading; uint32_t mFrameCount; uint32_t mFrameIndex; uint32_t mCacheSize; - std::vector mImageUrls; std::vector mIntervals; std::vector mLoadWaitingQueue; CircularQueue mQueue; diff --git a/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp b/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp index c0c598a..f78d74a 100644 --- a/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp +++ b/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -81,7 +81,7 @@ TextureSet RollingImageCache::Frame(uint32_t frameIndex) while(!mQueue.IsEmpty() && mQueue.Front().mUrlIndex != frameIndex) { PopFrontCache(); - popExist = true; + popExist = true; } // TODO: synchronous loading of first frame. @@ -144,7 +144,7 @@ void RollingImageCache::LoadBatch(uint32_t frameIndex) { ImageFrame imageFrame; - std::string& url = mImageUrls[frameIndex].mUrl; + VisualUrl& url = mImageUrls[frameIndex].mUrl; imageFrame.mUrlIndex = frameIndex; imageFrame.mReady = false; @@ -154,16 +154,16 @@ void RollingImageCache::LoadBatch(uint32_t frameIndex) // from within this method. This means it won't yet have a texture id, so we // need to account for this inside the LoadComplete method using mRequestingLoad. mRequestingLoad = true; - mLoadState = TextureManager::LoadState::LOADING; + mLoadState = TextureManager::LoadState::LOADING; - bool synchronousLoading = false; - bool atlasingStatus = false; - bool loadingStatus = false; - AtlasUploadObserver* atlasObserver = nullptr; - ImageAtlasManagerPtr imageAtlasManager = nullptr; - Vector4 textureRect; - Dali::ImageDimensions textureRectSize; - auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY; + bool synchronousLoading = false; + bool atlasingStatus = false; + bool loadingStatus = false; + AtlasUploadObserver* atlasObserver = nullptr; + ImageAtlasManagerPtr imageAtlasManager = nullptr; + Vector4 textureRect; + Dali::ImageDimensions textureRectSize; + auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY; TextureManager::TextureId loadTextureId = TextureManager::INVALID_TEXTURE_ID; TextureSet textureSet = mTextureManager.LoadTexture( @@ -220,7 +220,7 @@ void RollingImageCache::LoadComplete(bool loadSuccess, TextureInformation textur if(loadSuccess) { - mLoadState = TextureManager::LoadState::LOAD_FINISHED; + mLoadState = TextureManager::LoadState::LOAD_FINISHED; bool frontFrameReady = IsFrontReady(); if(!mRequestingLoad) { diff --git a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp index a7d1f76..f4e3059 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp @@ -99,7 +99,7 @@ AnimatedVectorImageVisual::AnimatedVectorImageVisual(VisualFactoryCache& factory mRedrawInScalingDown(true) { // the rasterized image is with pre-multiplied alpha format - mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA; + mImpl->mFlags |= Visual::Base::Impl::IS_PREMULTIPLIED_ALPHA; if(!mVectorAnimationTask->Load(mUrl.GetUrl())) { diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index a2e9096..e3aa797 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -307,11 +307,11 @@ void ImageVisual::DoSetProperty(Property::Index index, const Property::Value& va { if(sync) { - mImpl->mFlags |= Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; + mImpl->mFlags |= Visual::Base::Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; } else { - mImpl->mFlags &= ~Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; + mImpl->mFlags &= ~Visual::Base::Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; } } else @@ -471,7 +471,7 @@ void ImageVisual::GetNaturalSize(Vector2& naturalSize) } else if(mImpl->mRenderer) // Check if we have a loaded image { - if(mImpl->mFlags & Impl::IS_ATLASING_APPLIED) + if(mImpl->mFlags & Visual::Base::Impl::IS_ATLASING_APPLIED) { naturalSize.x = mAtlasRectSize.GetWidth(); naturalSize.y = mAtlasRectSize.GetHeight(); @@ -620,11 +620,11 @@ void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& te if(atlasing) // Flag needs to be set before creating renderer { - mImpl->mFlags |= Impl::IS_ATLASING_APPLIED; + mImpl->mFlags |= Visual::Base::Impl::IS_ATLASING_APPLIED; } else { - mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED; + mImpl->mFlags &= ~Visual::Base::Impl::IS_ATLASING_APPLIED; } } @@ -981,7 +981,7 @@ Shader ImageVisual::GenerateShader() const shader = mImageVisualShaderFactory.GetShader( mFactoryCache, ImageVisualShaderFeature::FeatureBuilder() - .EnableTextureAtlas(mImpl->mFlags & Impl::IS_ATLASING_APPLIED && !useNativeImage) + .EnableTextureAtlas(mImpl->mFlags & Visual::Base::Impl::IS_ATLASING_APPLIED && !useNativeImage) .ApplyDefaultTextureWrapMode(mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE) .EnableRoundedCorner(IsRoundedCornerRequired()) .EnableBorderline(IsBorderlineRequired()) diff --git a/dali-toolkit/internal/visuals/text/text-visual.cpp b/dali-toolkit/internal/visuals/text/text-visual.cpp index 9b0e811..777e48f 100644 --- a/dali-toolkit/internal/visuals/text/text-visual.cpp +++ b/dali-toolkit/internal/visuals/text/text-visual.cpp @@ -342,8 +342,6 @@ void TextVisual::DoSetOnScene(Actor& actor) // Renderer needs textures and to be added to control mRendererUpdateNeeded = true; - mRendererList.push_back(mImpl->mRenderer); - UpdateRenderer(); } @@ -620,16 +618,16 @@ void TextVisual::CreateTextureSet(TilingInfo& info, VisualRenderer& renderer, Sa ++textureSetIndex; } - if(styleEnabled && info.styleBuffer) + if(styleEnabled && info.styleBuffer && info.overlayStyleBuffer) { PixelData styleData = ConvertToPixelData(info.styleBuffer, info.width, info.height, info.offsetPosition, Pixel::RGBA8888); AddTexture(textureSet, styleData, sampler, textureSetIndex); ++textureSetIndex; - } - if(styleEnabled && isOverlayStyle && info.styleBuffer) - { - PixelData overlayStyleData = ConvertToPixelData(info.styleBuffer, info.width, info.height, info.offsetPosition, Pixel::RGBA8888); + // TODO : We need to seperate whether use overlayStyle or not. + // Current text visual shader required both of them. + + PixelData overlayStyleData = ConvertToPixelData(info.overlayStyleBuffer, info.width, info.height, info.offsetPosition, Pixel::RGBA8888); AddTexture(textureSet, overlayStyleData, sampler, textureSetIndex); ++textureSetIndex; } @@ -711,6 +709,14 @@ void TextVisual::AddRenderer(Actor& actor, const Vector2& size, bool hasMultiple PixelData styleData = mTypesetter->Render(size, textDirection, Text::Typesetter::RENDER_NO_TEXT, false, Pixel::RGBA8888); Dali::DevelPixelData::PixelDataBuffer stylePixelData = Dali::DevelPixelData::ReleasePixelDataBuffer(styleData); info.styleBuffer = stylePixelData.buffer; + + // TODO : We need to seperate whether use overlayStyle or not. + // Current text visual shader required both of them. + + // Create RGBA texture for all the overlay styles + PixelData overlayStyleData = mTypesetter->Render(size, textDirection, Text::Typesetter::RENDER_OVERLAY_STYLE, false, Pixel::RGBA8888); + Dali::DevelPixelData::PixelDataBuffer overlayStylePixelData = Dali::DevelPixelData::ReleasePixelDataBuffer(overlayStyleData); + info.overlayStyleBuffer = overlayStylePixelData.buffer; } if(containsColorGlyph && !hasMultipleTextColors) @@ -758,12 +764,38 @@ void TextVisual::AddRenderer(Actor& actor, const Vector2& size, bool hasMultiple mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED; + const Vector4& defaultColor = mController->GetTextModel()->GetDefaultColor(); + for(RendererContainer::iterator iter = mRendererList.begin(); iter != mRendererList.end(); ++iter) { Renderer renderer = (*iter); if(renderer) { actor.AddRenderer(renderer); + + if(renderer != mImpl->mRenderer) + { + // Set constraint for text label's color for non-default renderers. + if(mAnimatableTextColorPropertyIndex != Property::INVALID_INDEX) + { + // Register unique property, or get property for default renderer. + Property::Index index = renderer.RegisterUniqueProperty("uTextColorAnimatable", defaultColor); + + // Create constraint for the animatable text's color Property with uTextColorAnimatable in the renderer. + if(index != Property::INVALID_INDEX) + { + Constraint colorConstraint = Constraint::New(renderer, index, TextColorConstraint); + colorConstraint.AddSource(Source(actor, mAnimatableTextColorPropertyIndex)); + colorConstraint.Apply(); + } + + // Make zero if the alpha value of text color is zero to skip rendering text + // VisualRenderer::Property::OPACITY uses same animatable property internally. + Constraint opacityConstraint = Constraint::New(renderer, Dali::DevelRenderer::Property::OPACITY, OpacityConstraint); + opacityConstraint.AddSource(Source(actor, mAnimatableTextColorPropertyIndex)); + opacityConstraint.Apply(); + } + } } } } @@ -797,6 +829,10 @@ TextureSet TextVisual::GetTextTexture(const Vector2& size, bool hasMultipleTextC PixelData styleData = mTypesetter->Render(size, textDirection, Text::Typesetter::RENDER_NO_TEXT, false, Pixel::RGBA8888); AddTexture(textureSet, styleData, sampler, textureSetIndex); ++textureSetIndex; + + // TODO : We need to seperate whether use overlayStyle or not. + // Current text visual shader required both of them. + // Create RGBA texture for overlay styles such as underline and strikethrough (without the text itself) PixelData overlayStyleData = mTypesetter->Render(size, textDirection, Text::Typesetter::RENDER_OVERLAY_STYLE, false, Pixel::RGBA8888); AddTexture(textureSet, overlayStyleData, sampler, textureSetIndex); diff --git a/dali-toolkit/internal/visuals/text/text-visual.h b/dali-toolkit/internal/visuals/text/text-visual.h index fa7ca4e..c79c254 100644 --- a/dali-toolkit/internal/visuals/text/text-visual.h +++ b/dali-toolkit/internal/visuals/text/text-visual.h @@ -193,6 +193,7 @@ private: { unsigned char* textBuffer; unsigned char* styleBuffer; + unsigned char* overlayStyleBuffer; unsigned char* maskBuffer; int width; int height; @@ -203,6 +204,7 @@ private: TilingInfo(int width, int height, Pixel::Format textPixelFormat) : textBuffer(NULL), styleBuffer(NULL), + overlayStyleBuffer(NULL), maskBuffer(NULL), width(width), height(height), @@ -222,6 +224,10 @@ private: { free(styleBuffer); } + if(overlayStyleBuffer) + { + free(overlayStyleBuffer); + } if(maskBuffer) { free(maskBuffer); diff --git a/dali-toolkit/internal/visuals/visual-url.cpp b/dali-toolkit/internal/visuals/visual-url.cpp index af3b04c..c43af6d 100644 --- a/dali-toolkit/internal/visuals/visual-url.cpp +++ b/dali-toolkit/internal/visuals/visual-url.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -18,6 +18,7 @@ #include // EXTERNAL HEADERS +#include #include // for toupper() namespace Dali @@ -104,8 +105,8 @@ VisualUrl::ProtocolType ResolveLocation(const std::string& url) VisualUrl::Type ResolveType(const std::string& url) { // if only one char in string, can only be regular image - const std::size_t count = url.size(); - VisualUrl::Type returnType = VisualUrl::REGULAR_IMAGE; + const std::size_t count = url.size(); + VisualUrl::Type returnType = VisualUrl::REGULAR_IMAGE; if(count > 0) { // parsing from the end for better chance of early outs @@ -218,14 +219,16 @@ VisualUrl::Type ResolveType(const std::string& url) VisualUrl::VisualUrl() : mUrl(), mType(VisualUrl::REGULAR_IMAGE), - mLocation(VisualUrl::LOCAL) + mLocation(VisualUrl::LOCAL), + mUrlHash(0ull) { } VisualUrl::VisualUrl(const std::string& url) : mUrl(url), mType(VisualUrl::REGULAR_IMAGE), - mLocation(VisualUrl::LOCAL) + mLocation(VisualUrl::LOCAL), + mUrlHash(0ull) { if(!url.empty()) { @@ -241,7 +244,8 @@ VisualUrl::VisualUrl(const std::string& url) VisualUrl::VisualUrl(const VisualUrl& url) : mUrl(url.mUrl), mType(url.mType), - mLocation(url.mLocation) + mLocation(url.mLocation), + mUrlHash(url.mUrlHash) { } @@ -256,6 +260,7 @@ VisualUrl& VisualUrl::operator=(const VisualUrl& url) mUrl = url.mUrl; mType = url.mType; mLocation = url.mLocation; + mUrlHash = url.mUrlHash; } return *this; } @@ -265,6 +270,11 @@ const std::string& VisualUrl::GetUrl() const return mUrl; } +const std::uint64_t& VisualUrl::GetUrlHash() const +{ + return DALI_UNLIKELY(mUrlHash == 0) ? (mUrlHash = Dali::CalculateHash(mUrl)) : mUrlHash; +} + VisualUrl::Type VisualUrl::GetType() const { return mType; diff --git a/dali-toolkit/internal/visuals/visual-url.h b/dali-toolkit/internal/visuals/visual-url.h index 08a276a..941d0b8 100644 --- a/dali-toolkit/internal/visuals/visual-url.h +++ b/dali-toolkit/internal/visuals/visual-url.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_INTERNAL_VISUAL_URL_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -90,6 +90,12 @@ public: const std::string& GetUrl() const; /** + * Get the hash value of full URL + * @return The hash value of url + */ + const std::uint64_t& GetUrlHash() const; + + /** * Get the visual type of the URL * @return The visual type of the URL */ @@ -154,6 +160,8 @@ private: std::string mUrl; Type mType; ProtocolType mLocation; + + mutable std::uint64_t mUrlHash; }; } // namespace Internal diff --git a/dali-toolkit/public-api/dali-toolkit-version.cpp b/dali-toolkit/public-api/dali-toolkit-version.cpp index 9a460c0..de50efc 100644 --- a/dali-toolkit/public-api/dali-toolkit-version.cpp +++ b/dali-toolkit/public-api/dali-toolkit-version.cpp @@ -29,7 +29,7 @@ namespace Toolkit { const unsigned int TOOLKIT_MAJOR_VERSION = 2; const unsigned int TOOLKIT_MINOR_VERSION = 1; -const unsigned int TOOLKIT_MICRO_VERSION = 22; +const unsigned int TOOLKIT_MICRO_VERSION = 23; const char* const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index ceeba38..eb88f6b 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -1,6 +1,6 @@ Name: dali2-toolkit Summary: Dali 3D engine Toolkit -Version: 2.1.22 +Version: 2.1.23 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT