Merge "use modern construct '= default' for special functions." into devel/master
authorDavid Steele <david.steele@samsung.com>
Fri, 23 Oct 2020 10:32:46 +0000 (10:32 +0000)
committerGerrit Code Review <gerrit@review>
Fri, 23 Oct 2020 10:32:46 +0000 (10:32 +0000)
30 files changed:
automated-tests/README.md
automated-tests/patch-coverage.pl
automated-tests/src/dali/utc-Dali-Actor.cpp [changed mode: 0644->0755]
automated-tests/src/dali/utc-Dali-TouchProcessing.cpp [changed mode: 0644->0755]
dali/devel-api/actors/actor-devel.cpp [changed mode: 0644->0755]
dali/devel-api/actors/actor-devel.h [changed mode: 0644->0755]
dali/internal/event/actors/actor-impl.cpp [changed mode: 0644->0755]
dali/internal/event/actors/actor-impl.h [changed mode: 0644->0755]
dali/internal/event/actors/actor-property-handler.cpp [changed mode: 0644->0755]
dali/internal/event/animation/animation-impl.cpp
dali/internal/event/animation/animation-impl.h
dali/internal/event/events/ray-test.cpp [changed mode: 0644->0755]
dali/internal/event/events/touch-event-processor.cpp [changed mode: 0644->0755]
dali/internal/update/animation/scene-graph-animation.cpp
dali/internal/update/animation/scene-graph-animation.h
dali/internal/update/manager/transform-manager.cpp
dali/internal/update/manager/transform-manager.h
dali/internal/update/manager/update-manager.cpp
dali/internal/update/manager/update-manager.h
dali/internal/update/rendering/scene-graph-renderer.cpp
dali/internal/update/rendering/scene-graph-renderer.h
dali/public-api/actors/custom-actor-impl.h
dali/public-api/actors/custom-actor.h
dali/public-api/animation/alpha-function.h
dali/public-api/animation/animation.h
dali/public-api/dali-core-version.cpp
dali/public-api/object/handle.h
dali/public-api/object/property-map.cpp
dali/public-api/object/property-map.h
packaging/dali.spec

index b2fc212..7d363fb 100644 (file)
@@ -105,16 +105,35 @@ To execute a subset of tests, you can run individual test sets, e.g.
 
     ./execute.sh dali
 
-To get coverage output (you need to first build dali libraries with
+To get full coverage output (you need to first build dali libraries with
 --coverage), run
 
     ./coverage.sh
 
+To check the coverage of your patch, (the build server uses its own copy
+of these scripts), you can use
+
+    ./patch-coverage.pl -q [diff-spec]
+
+to get a summary, or
+
+    ./patch-coverage.pl [diff-spec]
+
+to get textual output, or
+
+    ./patch-coverage.pl -o out.html [diff-spec]
+
+to get HTML output (used by build server).
+
+diff-spec is any refspec accepted by git-diff. If it's left out, it creates
+a refspec to the latest commit, or uses the index/working tree.
+
+
 
 Testing on target
 =================
 
-To build for target, first build and install dali-core, dali-adaptor and dali-toolkit, then build dali-capi without --keep-packs option.
+To build for target, first build and install dali-core, dali-adaptor and dali-toolkit.
 
 You will need to install libconfig-tiny-perl:
 
@@ -226,14 +245,14 @@ Debugging
 On desktop, you can debug the tests by running gdb on the test program:
 
     $ cd automated-tests
-    $ gdb build/src/dali/tct-dali-core
+    $ ./execute.sh -d <TestCase>
     gdb> r <TestCase>
 
 replace `<TestCase>` with the name of the failing testcase.
 
 For example, using testcase UtcDaliActorAddP from the dali-core test suite:
 
-    $ gdb build/src/dali/tct-dali-core
+    $ ./execute.sh -d UtcDaliActorAddP
     gdb> r UtcDaliActorAddP
 
 
index c5d9083..702dc0b 100755 (executable)
@@ -19,33 +19,59 @@ use strict;
 use Git;
 use Getopt::Long;
 use Error qw(:try);
-use HTML::Element;
 use Pod::Usage;
 use File::Basename;
-#use Data::Dumper;
 use File::stat;
 use Scalar::Util qw /looks_like_number/;
 use Cwd qw /getcwd/;
 use Term::ANSIColor qw(:constants);
+use Data::Dumper;
 
-# Program to run gcov on files in patch (that are in source dirs - needs to be dali-aware).
+# Dali specific program to run lcov and parse output for files in patch
 
-# A) Get patch
-# B) Remove uninteresting files
-# C) Find matching gcno/gcda files
-# D) Copy and rename them to match source prefix (i.e. strip library name off front)
-# E) Generate patch output with covered/uncovered lines marked in green/red
-# F) Generate coverage data for changed lines
-# G) Exit status should be 0 for high coverage (90% line coverage for all new/changed lines)
+# A) Generate lcov output from lib & test cases
+# B) Get patch using git diff
+# C) Generate patch output with covered/uncovered lines marked in green/red
+# D) Generate coverage data for changed lines
+# E) Exit status should be 0 for high coverage (90% line coverage for all new/changed lines)
 #    or 1 for low coverage
 
 # Sources for conversion of gcno/gcda files:
-# ~/bin/lcov
+# /usr/bin/lcov & genhtml
 # Python git-coverage (From http://stef.thewalter.net/git-coverage-useful-code-coverage.html)
 
+# From genhtml:
+sub read_info_file($);
+sub get_info_entry($);
+sub set_info_entry($$$$$$$$$;$$$$$$);
+sub combine_info_entries($$$);
+sub combine_info_files($$);
+sub compress_brcount($);
+sub brcount_to_db($);
+sub db_to_brcount($;$);
+sub brcount_db_combine($$$);
+sub add_counts($$);
+sub info(@);
+
 our $repo = Git->repository();
-our $debug=0;
+our $debug=1;
 our $pd_debug=0;
+our $root;
+our %info_data; # Hash containing all data from .info files
+
+# Settings from genhtml:
+our $func_coverage;     # If set, generate function coverage statistics
+our $no_func_coverage;  # Disable func_coverage
+our $br_coverage;       # If set, generate branch coverage statistics
+our $no_br_coverage;    # Disable br_coverage
+our $sort = 1;          # If set, provide directory listings with sorted entries
+our $no_sort;           # Disable sort
+
+# Branch data combination types
+our $BR_SUB = 0;
+our $BR_ADD = 1;
+
+# Command line options
 our $opt_cached;
 our $opt_help;
 our $opt_output;
@@ -64,6 +90,793 @@ GetOptions( %longOptions ) or pod2usage(2);
 pod2usage(1) if $opt_help;
 
 
+# From genhtml:
+#
+# read_info_file(info_filename)
+#
+# Read in the contents of the .info file specified by INFO_FILENAME. Data will
+# be returned as a reference to a hash containing the following mappings:
+#
+# %result: for each filename found in file -> \%data
+#
+# %data: "test"    -> \%testdata
+#        "sum"     -> \%sumcount
+#        "func"    -> \%funcdata
+#        "found"   -> $lines_found (number of instrumented lines found in file)
+#        "hit"     -> $lines_hit (number of executed lines in file)
+#        "f_found" -> $fn_found (number of instrumented functions found in file)
+#        "f_hit"   -> $fn_hit (number of executed functions in file)
+#        "b_found" -> $br_found (number of instrumented branches found in file)
+#        "b_hit"   -> $br_hit (number of executed branches in file)
+#        "check"   -> \%checkdata
+#        "testfnc" -> \%testfncdata
+#        "sumfnc"  -> \%sumfnccount
+#        "testbr"  -> \%testbrdata
+#        "sumbr"   -> \%sumbrcount
+#
+# %testdata   : name of test affecting this file -> \%testcount
+# %testfncdata: name of test affecting this file -> \%testfnccount
+# %testbrdata:  name of test affecting this file -> \%testbrcount
+#
+# %testcount   : line number   -> execution count for a single test
+# %testfnccount: function name -> execution count for a single test
+# %testbrcount : line number   -> branch coverage data for a single test
+# %sumcount    : line number   -> execution count for all tests
+# %sumfnccount : function name -> execution count for all tests
+# %sumbrcount  : line number   -> branch coverage data for all tests
+# %funcdata    : function name -> line number
+# %checkdata   : line number   -> checksum of source code line
+# $brdata      : vector of items: block, branch, taken
+#
+# Note that .info file sections referring to the same file and test name
+# will automatically be combined by adding all execution counts.
+#
+# Note that if INFO_FILENAME ends with ".gz", it is assumed that the file
+# is compressed using GZIP. If available, GUNZIP will be used to decompress
+# this file.
+#
+# Die on error.
+#
+sub read_info_file($)
+{
+    my $tracefile = $_[0];      # Name of tracefile
+    my %result;             # Resulting hash: file -> data
+    my $data;           # Data handle for current entry
+    my $testdata;           #       "             "
+    my $testcount;          #       "             "
+    my $sumcount;           #       "             "
+    my $funcdata;           #       "             "
+    my $checkdata;          #       "             "
+    my $testfncdata;
+    my $testfnccount;
+    my $sumfnccount;
+    my $testbrdata;
+    my $testbrcount;
+    my $sumbrcount;
+    my $line;           # Current line read from .info file
+    my $testname;           # Current test name
+    my $filename;           # Current filename
+    my $hitcount;           # Count for lines hit
+    my $count;          # Execution count of current line
+    my $negative;           # If set, warn about negative counts
+    my $changed_testname;       # If set, warn about changed testname
+    my $line_checksum;      # Checksum of current line
+    my $notified_about_relative_paths;
+    local *INFO_HANDLE;         # Filehandle for .info file
+
+    info("Reading data file $tracefile\n");
+
+    # Check if file exists and is readable
+    stat($tracefile);
+    if (!(-r _))
+    {
+        die("ERROR: cannot read file $tracefile!\n");
+    }
+
+    # Check if this is really a plain file
+    if (!(-f _))
+    {
+        die("ERROR: not a plain file: $tracefile!\n");
+    }
+
+    # Check for .gz extension
+    if ($tracefile =~ /\.gz$/)
+    {
+        # Check for availability of GZIP tool
+        system_no_output(1, "gunzip" ,"-h")
+            and die("ERROR: gunzip command not available!\n");
+
+        # Check integrity of compressed file
+        system_no_output(1, "gunzip", "-t", $tracefile)
+            and die("ERROR: integrity check failed for ".
+                    "compressed file $tracefile!\n");
+
+        # Open compressed file
+        open(INFO_HANDLE, "-|", "gunzip -c '$tracefile'")
+            or die("ERROR: cannot start gunzip to decompress ".
+                   "file $tracefile!\n");
+    }
+    else
+    {
+        # Open decompressed file
+        open(INFO_HANDLE, "<", $tracefile)
+            or die("ERROR: cannot read file $tracefile!\n");
+    }
+
+    $testname = "";
+    while (<INFO_HANDLE>)
+    {
+        chomp($_);
+        $line = $_;
+
+        # Switch statement
+        foreach ($line)
+        {
+            /^TN:([^,]*)(,diff)?/ && do
+            {
+                # Test name information found
+                $testname = defined($1) ? $1 : "";
+                if ($testname =~ s/\W/_/g)
+                {
+                    $changed_testname = 1;
+                }
+                $testname .= $2 if (defined($2));
+                last;
+            };
+
+            /^[SK]F:(.*)/ && do
+            {
+                # Filename information found
+                # Retrieve data for new entry
+                $filename = File::Spec->rel2abs($1, $root);
+
+                if (!File::Spec->file_name_is_absolute($1) &&
+                    !$notified_about_relative_paths)
+                {
+                    info("Resolved relative source file ".
+                         "path \"$1\" with CWD to ".
+                         "\"$filename\".\n");
+                    $notified_about_relative_paths = 1;
+                }
+
+                $data = $result{$filename};
+                ($testdata, $sumcount, $funcdata, $checkdata,
+                 $testfncdata, $sumfnccount, $testbrdata,
+                 $sumbrcount) =
+                    get_info_entry($data);
+
+                if (defined($testname))
+                {
+                    $testcount = $testdata->{$testname};
+                    $testfnccount = $testfncdata->{$testname};
+                    $testbrcount = $testbrdata->{$testname};
+                }
+                else
+                {
+                    $testcount = {};
+                    $testfnccount = {};
+                    $testbrcount = {};
+                }
+                last;
+            };
+
+            /^DA:(\d+),(-?\d+)(,[^,\s]+)?/ && do
+            {
+                # Fix negative counts
+                $count = $2 < 0 ? 0 : $2;
+                if ($2 < 0)
+                {
+                    $negative = 1;
+                }
+                # Execution count found, add to structure
+                # Add summary counts
+                $sumcount->{$1} += $count;
+
+                # Add test-specific counts
+                if (defined($testname))
+                {
+                    $testcount->{$1} += $count;
+                }
+
+                # Store line checksum if available
+                if (defined($3))
+                {
+                    $line_checksum = substr($3, 1);
+
+                    # Does it match a previous definition
+                    if (defined($checkdata->{$1}) &&
+                        ($checkdata->{$1} ne
+                         $line_checksum))
+                    {
+                        die("ERROR: checksum mismatch ".
+                            "at $filename:$1\n");
+                    }
+
+                    $checkdata->{$1} = $line_checksum;
+                }
+                last;
+            };
+
+            /^FN:(\d+),([^,]+)/ && do
+            {
+                last if (!$func_coverage);
+
+                # Function data found, add to structure
+                $funcdata->{$2} = $1;
+
+                # Also initialize function call data
+                if (!defined($sumfnccount->{$2})) {
+                    $sumfnccount->{$2} = 0;
+                }
+                if (defined($testname))
+                {
+                    if (!defined($testfnccount->{$2})) {
+                        $testfnccount->{$2} = 0;
+                    }
+                }
+                last;
+            };
+
+            /^FNDA:(\d+),([^,]+)/ && do
+            {
+                last if (!$func_coverage);
+                # Function call count found, add to structure
+                # Add summary counts
+                $sumfnccount->{$2} += $1;
+
+                # Add test-specific counts
+                if (defined($testname))
+                {
+                    $testfnccount->{$2} += $1;
+                }
+                last;
+            };
+
+            /^BRDA:(\d+),(\d+),(\d+),(\d+|-)/ && do {
+                # Branch coverage data found
+                my ($line, $block, $branch, $taken) =
+                    ($1, $2, $3, $4);
+
+                last if (!$br_coverage);
+                $sumbrcount->{$line} .=
+                    "$block,$branch,$taken:";
+
+                # Add test-specific counts
+                if (defined($testname)) {
+                    $testbrcount->{$line} .=
+                        "$block,$branch,$taken:";
+                }
+                last;
+            };
+
+            /^end_of_record/ && do
+            {
+                # Found end of section marker
+                if ($filename)
+                {
+                    # Store current section data
+                    if (defined($testname))
+                    {
+                        $testdata->{$testname} =
+                            $testcount;
+                        $testfncdata->{$testname} =
+                            $testfnccount;
+                        $testbrdata->{$testname} =
+                            $testbrcount;
+                    }
+
+                    set_info_entry($data, $testdata,
+                                   $sumcount, $funcdata,
+                                   $checkdata, $testfncdata,
+                                   $sumfnccount,
+                                   $testbrdata,
+                                   $sumbrcount);
+                    $result{$filename} = $data;
+                    last;
+                }
+            };
+
+            # default
+            last;
+        }
+    }
+    close(INFO_HANDLE);
+
+    # Calculate lines_found and lines_hit for each file
+    foreach $filename (keys(%result))
+    {
+        $data = $result{$filename};
+
+        ($testdata, $sumcount, undef, undef, $testfncdata,
+         $sumfnccount, $testbrdata, $sumbrcount) =
+            get_info_entry($data);
+
+        # Filter out empty files
+        if (scalar(keys(%{$sumcount})) == 0)
+        {
+            delete($result{$filename});
+            next;
+        }
+        # Filter out empty test cases
+        foreach $testname (keys(%{$testdata}))
+        {
+            if (!defined($testdata->{$testname}) ||
+                scalar(keys(%{$testdata->{$testname}})) == 0)
+            {
+                delete($testdata->{$testname});
+                delete($testfncdata->{$testname});
+            }
+        }
+
+        $data->{"found"} = scalar(keys(%{$sumcount}));
+        $hitcount = 0;
+
+        foreach (keys(%{$sumcount}))
+        {
+            if ($sumcount->{$_} > 0) { $hitcount++; }
+        }
+
+        $data->{"hit"} = $hitcount;
+
+        # Get found/hit values for function call data
+        $data->{"f_found"} = scalar(keys(%{$sumfnccount}));
+        $hitcount = 0;
+
+        foreach (keys(%{$sumfnccount})) {
+            if ($sumfnccount->{$_} > 0) {
+                $hitcount++;
+            }
+        }
+        $data->{"f_hit"} = $hitcount;
+
+        # Combine branch data for the same branches
+        (undef, $data->{"b_found"}, $data->{"b_hit"}) = compress_brcount($sumbrcount);
+        foreach $testname (keys(%{$testbrdata})) {
+            compress_brcount($testbrdata->{$testname});
+        }
+    }
+
+    if (scalar(keys(%result)) == 0)
+    {
+        die("ERROR: no valid records found in tracefile $tracefile\n");
+    }
+    if ($negative)
+    {
+        warn("WARNING: negative counts found in tracefile ".
+             "$tracefile\n");
+    }
+    if ($changed_testname)
+    {
+        warn("WARNING: invalid characters removed from testname in ".
+             "tracefile $tracefile\n");
+    }
+
+    return(\%result);
+}
+
+sub print_simplified_info
+{
+    for my $key (keys(%info_data))
+    {
+        print "K $key: \n";
+        my $sumcountref = $info_data{$key}->{"sum"};
+        for my $line (sort{$a<=>$b}(keys(%$sumcountref)))
+        {
+            print "L  $line: $sumcountref->{$line}\n";
+        }
+    }
+}
+
+# From genhtml:
+#
+# get_info_entry(hash_ref)
+#
+# Retrieve data from an entry of the structure generated by read_info_file().
+# Return a list of references to hashes:
+# (test data hash ref, sum count hash ref, funcdata hash ref, checkdata hash
+#  ref, testfncdata hash ref, sumfnccount hash ref, lines found, lines hit,
+#  functions found, functions hit)
+#
+
+sub get_info_entry($)
+{
+    my $testdata_ref = $_[0]->{"test"};
+    my $sumcount_ref = $_[0]->{"sum"};
+    my $funcdata_ref = $_[0]->{"func"};
+    my $checkdata_ref = $_[0]->{"check"};
+    my $testfncdata = $_[0]->{"testfnc"};
+    my $sumfnccount = $_[0]->{"sumfnc"};
+    my $testbrdata = $_[0]->{"testbr"};
+    my $sumbrcount = $_[0]->{"sumbr"};
+    my $lines_found = $_[0]->{"found"};
+    my $lines_hit = $_[0]->{"hit"};
+    my $fn_found = $_[0]->{"f_found"};
+    my $fn_hit = $_[0]->{"f_hit"};
+    my $br_found = $_[0]->{"b_found"};
+    my $br_hit = $_[0]->{"b_hit"};
+
+    return ($testdata_ref, $sumcount_ref, $funcdata_ref, $checkdata_ref,
+            $testfncdata, $sumfnccount, $testbrdata, $sumbrcount,
+            $lines_found, $lines_hit, $fn_found, $fn_hit,
+            $br_found, $br_hit);
+}
+
+
+# From genhtml:
+#
+# set_info_entry(hash_ref, testdata_ref, sumcount_ref, funcdata_ref,
+#                checkdata_ref, testfncdata_ref, sumfcncount_ref,
+#                testbrdata_ref, sumbrcount_ref[,lines_found,
+#                lines_hit, f_found, f_hit, $b_found, $b_hit])
+#
+# Update the hash referenced by HASH_REF with the provided data references.
+#
+
+sub set_info_entry($$$$$$$$$;$$$$$$)
+{
+    my $data_ref = $_[0];
+
+    $data_ref->{"test"} = $_[1];
+    $data_ref->{"sum"} = $_[2];
+    $data_ref->{"func"} = $_[3];
+    $data_ref->{"check"} = $_[4];
+    $data_ref->{"testfnc"} = $_[5];
+    $data_ref->{"sumfnc"} = $_[6];
+    $data_ref->{"testbr"} = $_[7];
+    $data_ref->{"sumbr"} = $_[8];
+
+    if (defined($_[9])) { $data_ref->{"found"} = $_[9]; }
+    if (defined($_[10])) { $data_ref->{"hit"} = $_[10]; }
+    if (defined($_[11])) { $data_ref->{"f_found"} = $_[11]; }
+    if (defined($_[12])) { $data_ref->{"f_hit"} = $_[12]; }
+    if (defined($_[13])) { $data_ref->{"b_found"} = $_[13]; }
+    if (defined($_[14])) { $data_ref->{"b_hit"} = $_[14]; }
+}
+
+# From genhtml:
+#
+# combine_info_entries(entry_ref1, entry_ref2, filename)
+#
+# Combine .info data entry hashes referenced by ENTRY_REF1 and ENTRY_REF2.
+# Return reference to resulting hash.
+#
+sub combine_info_entries($$$)
+{
+    my $entry1 = $_[0];     # Reference to hash containing first entry
+    my $testdata1;
+    my $sumcount1;
+    my $funcdata1;
+    my $checkdata1;
+    my $testfncdata1;
+    my $sumfnccount1;
+    my $testbrdata1;
+    my $sumbrcount1;
+
+    my $entry2 = $_[1];     # Reference to hash containing second entry
+    my $testdata2;
+    my $sumcount2;
+    my $funcdata2;
+    my $checkdata2;
+    my $testfncdata2;
+    my $sumfnccount2;
+    my $testbrdata2;
+    my $sumbrcount2;
+
+    my %result;         # Hash containing combined entry
+    my %result_testdata;
+    my $result_sumcount = {};
+    my $result_funcdata;
+    my $result_testfncdata;
+    my $result_sumfnccount;
+    my $result_testbrdata;
+    my $result_sumbrcount;
+    my $lines_found;
+    my $lines_hit;
+    my $fn_found;
+    my $fn_hit;
+    my $br_found;
+    my $br_hit;
+
+    my $testname;
+    my $filename = $_[2];
+
+    # Retrieve data
+    ($testdata1, $sumcount1, $funcdata1, $checkdata1, $testfncdata1,
+     $sumfnccount1, $testbrdata1, $sumbrcount1) = get_info_entry($entry1);
+    ($testdata2, $sumcount2, $funcdata2, $checkdata2, $testfncdata2,
+     $sumfnccount2, $testbrdata2, $sumbrcount2) = get_info_entry($entry2);
+
+#    # Merge checksums
+#    $checkdata1 = merge_checksums($checkdata1, $checkdata2, $filename);
+#
+#    # Combine funcdata
+#    $result_funcdata = merge_func_data($funcdata1, $funcdata2, $filename);
+#
+#    # Combine function call count data
+#    $result_testfncdata = add_testfncdata($testfncdata1, $testfncdata2);
+#    ($result_sumfnccount, $fn_found, $fn_hit) =
+#        add_fnccount($sumfnccount1, $sumfnccount2);
+#
+#    # Combine branch coverage data
+#    $result_testbrdata = add_testbrdata($testbrdata1, $testbrdata2);
+#    ($result_sumbrcount, $br_found, $br_hit) =
+#        combine_brcount($sumbrcount1, $sumbrcount2, $BR_ADD);
+#
+    # Combine testdata
+    foreach $testname (keys(%{$testdata1}))
+    {
+        if (defined($testdata2->{$testname}))
+        {
+            # testname is present in both entries, requires
+            # combination
+            ($result_testdata{$testname}) =
+                add_counts($testdata1->{$testname},
+                           $testdata2->{$testname});
+        }
+        else
+        {
+            # testname only present in entry1, add to result
+            $result_testdata{$testname} = $testdata1->{$testname};
+        }
+
+        # update sum count hash
+        ($result_sumcount, $lines_found, $lines_hit) =
+            add_counts($result_sumcount,
+                       $result_testdata{$testname});
+    }
+
+    foreach $testname (keys(%{$testdata2}))
+    {
+        # Skip testnames already covered by previous iteration
+        if (defined($testdata1->{$testname})) { next; }
+
+        # testname only present in entry2, add to result hash
+        $result_testdata{$testname} = $testdata2->{$testname};
+
+        # update sum count hash
+        ($result_sumcount, $lines_found, $lines_hit) =
+            add_counts($result_sumcount,
+                       $result_testdata{$testname});
+    }
+
+    # Calculate resulting sumcount
+
+    # Store result
+    set_info_entry(\%result, \%result_testdata, $result_sumcount,
+                   $result_funcdata, $checkdata1, $result_testfncdata,
+                   $result_sumfnccount, $result_testbrdata,
+                   $result_sumbrcount, $lines_found, $lines_hit,
+                   $fn_found, $fn_hit, $br_found, $br_hit);
+
+    return(\%result);
+}
+
+# From genhtml:
+#
+# combine_info_files(info_ref1, info_ref2)
+#
+# Combine .info data in hashes referenced by INFO_REF1 and INFO_REF2. Return
+# reference to resulting hash.
+#
+sub combine_info_files($$)
+{
+    my %hash1 = %{$_[0]};
+    my %hash2 = %{$_[1]};
+    my $filename;
+
+    foreach $filename (keys(%hash2))
+    {
+        if ($hash1{$filename})
+        {
+            # Entry already exists in hash1, combine them
+            $hash1{$filename} =
+                combine_info_entries($hash1{$filename},
+                                     $hash2{$filename},
+                                     $filename);
+        }
+        else
+        {
+            # Entry is unique in both hashes, simply add to
+            # resulting hash
+            $hash1{$filename} = $hash2{$filename};
+        }
+    }
+
+    return(\%hash1);
+}
+
+# From genhtml:
+#
+# add_counts(data1_ref, data2_ref)
+#
+# DATA1_REF and DATA2_REF are references to hashes containing a mapping
+#
+#   line number -> execution count
+#
+# Return a list (RESULT_REF, LINES_FOUND, LINES_HIT) where RESULT_REF
+# is a reference to a hash containing the combined mapping in which
+# execution counts are added.
+#
+sub add_counts($$)
+{
+    my $data1_ref = $_[0];  # Hash 1
+    my $data2_ref = $_[1];  # Hash 2
+    my %result;             # Resulting hash
+    my $line;               # Current line iteration scalar
+    my $data1_count;        # Count of line in hash1
+    my $data2_count;        # Count of line in hash2
+    my $found = 0;          # Total number of lines found
+    my $hit = 0;            # Number of lines with a count > 0
+
+    foreach $line (keys(%$data1_ref))
+    {
+        $data1_count = $data1_ref->{$line};
+        $data2_count = $data2_ref->{$line};
+
+        # Add counts if present in both hashes
+        if (defined($data2_count)) { $data1_count += $data2_count; }
+
+        # Store sum in %result
+        $result{$line} = $data1_count;
+
+        $found++;
+        if ($data1_count > 0) { $hit++; }
+    }
+
+    # Add lines unique to data2_ref
+    foreach $line (keys(%$data2_ref))
+    {
+        # Skip lines already in data1_ref
+        if (defined($data1_ref->{$line})) { next; }
+
+        # Copy count from data2_ref
+        $result{$line} = $data2_ref->{$line};
+
+        $found++;
+        if ($result{$line} > 0) { $hit++; }
+    }
+
+    return (\%result, $found, $hit);
+}
+
+
+# From genhtml:
+sub compress_brcount($)
+{
+    my ($brcount) = @_;
+    my $db;
+
+    $db = brcount_to_db($brcount);
+    return db_to_brcount($db, $brcount);
+}
+
+#
+# brcount_to_db(brcount)
+#
+# Convert brcount data to the following format:
+#
+# db:          line number    -> block hash
+# block hash:  block number   -> branch hash
+# branch hash: branch number  -> taken value
+#
+
+sub brcount_to_db($)
+{
+    my ($brcount) = @_;
+    my $line;
+    my $db;
+
+    # Add branches to database
+    foreach $line (keys(%{$brcount})) {
+        my $brdata = $brcount->{$line};
+
+        foreach my $entry (split(/:/, $brdata)) {
+            my ($block, $branch, $taken) = split(/,/, $entry);
+            my $old = $db->{$line}->{$block}->{$branch};
+
+            if (!defined($old) || $old eq "-") {
+                $old = $taken;
+            } elsif ($taken ne "-") {
+                $old += $taken;
+            }
+
+            $db->{$line}->{$block}->{$branch} = $old;
+        }
+    }
+
+    return $db;
+}
+
+
+#
+# db_to_brcount(db[, brcount])
+#
+# Convert branch coverage data back to brcount format. If brcount is specified,
+# the converted data is directly inserted in brcount.
+#
+
+sub db_to_brcount($;$)
+{
+    my ($db, $brcount) = @_;
+    my $line;
+    my $br_found = 0;
+    my $br_hit = 0;
+
+    # Convert database back to brcount format
+    foreach $line (sort({$a <=> $b} keys(%{$db}))) {
+        my $ldata = $db->{$line};
+        my $brdata;
+        my $block;
+
+        foreach $block (sort({$a <=> $b} keys(%{$ldata}))) {
+            my $bdata = $ldata->{$block};
+            my $branch;
+
+            foreach $branch (sort({$a <=> $b} keys(%{$bdata}))) {
+                my $taken = $bdata->{$branch};
+
+                $br_found++;
+                $br_hit++ if ($taken ne "-" && $taken > 0);
+                $brdata .= "$block,$branch,$taken:";
+            }
+        }
+        $brcount->{$line} = $brdata;
+    }
+
+    return ($brcount, $br_found, $br_hit);
+}
+
+
+#
+# brcount_db_combine(db1, db2, op)
+#
+# db1 := db1 op db2, where
+#   db1, db2: brcount data as returned by brcount_to_db
+#   op:       one of $BR_ADD and BR_SUB
+#
+sub brcount_db_combine($$$)
+{
+    my ($db1, $db2, $op) = @_;
+
+    foreach my $line (keys(%{$db2})) {
+        my $ldata = $db2->{$line};
+
+        foreach my $block (keys(%{$ldata})) {
+            my $bdata = $ldata->{$block};
+
+            foreach my $branch (keys(%{$bdata})) {
+                my $taken = $bdata->{$branch};
+                my $new = $db1->{$line}->{$block}->{$branch};
+
+                if (!defined($new) || $new eq "-") {
+                    $new = $taken;
+                } elsif ($taken ne "-") {
+                    if ($op == $BR_ADD) {
+                        $new += $taken;
+                    } elsif ($op == $BR_SUB) {
+                        $new -= $taken;
+                        $new = 0 if ($new < 0);
+                    }
+                }
+
+                $db1->{$line}->{$block}->{$branch} = $new;
+            }
+        }
+    }
+}
+
+# From genhtml
+sub info(@)
+{
+    if($debug)
+    {
+        # Print info string
+        printf(@_);
+    }
+}
+
+# NEW STUFF
+
 ## Format per file, repeated, no linebreak
 # <diffcmd>
 # index c1..c2 c3
@@ -78,6 +891,12 @@ pod2usage(1) if $opt_help;
 # 3 lines of context
 #
 # output:
+# <dali-source-file>: source / header files in dali/dali-toolkit
+# \%filter: <dali-source-file> -> \%filedata
+# %filedata: "patch"   -> \@checklines
+#            "b_lines" -> \%b_lines
+# @checklines: vector of \[start, length] # line numbers of new/modified lines
+# %b_lines: <line-number> -> patch line in b-file.
 sub parse_diff
 {
     my $patchref = shift;
@@ -184,7 +1003,7 @@ sub parse_diff
         }
     }
 
-    return {%filter};
+    return {%filter};#copy? - test and fixme
 }
 
 sub show_patch_lines
@@ -203,133 +1022,11 @@ sub show_patch_lines
     }
 }
 
-sub get_gcno_file
-{
-    # Assumes test cases have been run, and "make rename_cov_data" has been executed
-
-    my $file = shift;
-    my ($name, $path, $suffix) = fileparse($file, (".c", ".cpp", ".h"));
-    my $gcno_file = $repo->wc_path() . "/build/tizen/.cov/$name.gcno";
-
-    # Note, will translate headers to their source's object, which
-    # may miss execution code in the headers (e.g. inlines are usually
-    # not all used in the implementation, and require getting coverage
-    # from test cases.
-
-    if( -f $gcno_file )
-    {
-        my $gcno_st = stat($gcno_file);
-        my $fq_file = $repo->wc_path() . $file;
-        my $src_st = stat($fq_file);
-        if($gcno_st->ctime < $src_st->mtime)
-        {
-            print "WARNING: GCNO $gcno_file older than SRC $fq_file\n";
-            $gcno_file="";
-        }
-
-    }
-    else
-    {
-        print("WARNING: No equivalent gcno file for $file\n");
-    }
-    return $gcno_file;
-}
-
-our %gcovfiles=();
-sub get_coverage
-{
-    my $file = shift;
-    my $filesref = shift;
-    print("get_coverage($file)\n") if $debug;
-
-    my $gcno_file = get_gcno_file($file);
-    my @gcov_files = ();
-    my $gcovfile;
-    if( $gcno_file )
-    {
-        print "Running gcov on $gcno_file:\n" if $debug;
-        open( my $fh,  "gcov --preserve-paths $gcno_file |") || die "Can't run gcov:$!\n";
-        while( <$fh> )
-        {
-            print $_ if $debug>=3;
-            chomp;
-            if( m!'(.*\.gcov)'$! )
-            {
-                my $coverage_file = $1; # File has / replaced with # and .. replaced with ^
-                my $source_file = $coverage_file;
-                $source_file =~ s!\^!..!g;  # Change ^ to ..
-                $source_file =~ s!\#!/!g;   # change #'s to /s
-                $source_file =~ s!.gcov$!!; # Strip off .gcov suffix
-
-                print "Matching $file against $source_file\n" if $debug >= 3;
-                # Only want the coverage files matching source file:
-                if(index( $source_file, $file ) > 0 )
-                {
-                    $gcovfile = $coverage_file;
-                    # Some header files do not produce an equivalent gcov file so we shouldn't parse them
-                    if(($source_file =~ /\.h$/) && (! -e $gcovfile))
-                    {
-                        print "Omitting Header: $source_file\n" if $debug;
-                        $gcovfile = ""
-                    }
-                    last;
-                }
-            }
-        }
-        close($fh);
-
-        if($gcovfile)
-        {
-            if($gcovfiles{$gcovfile} == undef)
-            {
-                # Only parse a gcov file once
-                $gcovfiles{$gcovfile}->{"seen"}=1;
-
-                print "Getting coverage data from $gcovfile\n" if $debug;
 
-                open( FH, "< $gcovfile" ) || die "Can't open $gcovfile for reading:$!\n";
-                while(<FH>)
-                {
-                    my ($cov, $line, @code ) = split( /:/, $_ );
-                    $cov =~ s/^\s+//; # Strip leading space
-                    $line =~ s/^\s+//;
-                    my $code=join(":", @code);
-                    if($cov =~ /\#/)
-                    {
-                        # There is no coverage data for these executable lines
-                        $gcovfiles{$gcovfile}->{"uncovered"}->{$line}++;
-                        $gcovfiles{$gcovfile}->{"src"}->{$line}=$code;
-                    }
-                    elsif( $cov ne "-" && looks_like_number($cov) && $cov > 0 )
-                    {
-                        $gcovfiles{$gcovfile}->{"covered"}->{$line}=$cov;
-                        $gcovfiles{$gcovfile}->{"src"}->{$line}=$code;
-                    }
-                    else
-                    {
-                        # All other lines are not executable.
-                        $gcovfiles{$gcovfile}->{"src"}->{$line}=$code;
-                    }
-                }
-                close( FH );
-            }
-            $filesref->{$file}->{"coverage"} = $gcovfiles{$gcovfile}; # store hashref
-        }
-        else
-        {
-            # No gcov output - the gcno file produced no coverage of the source/header
-            # Probably means that there is no coverage for the file (with the given
-            # test case - there may be some somewhere, but for the sake of speed, don't
-            # check (yet).
-        }
-    }
-}
-
-# Run the git diff command to get the patch, then check the coverage
-# output for the patch.
+# Run the git diff command to get the patch
+# Output - see parse_diff
 sub run_diff
 {
-    #print "run_diff(" . join(" ", @_) . ")\n";
     my ($fh, $c) = $repo->command_output_pipe(@_);
     our @patch=();
     while(<$fh>)
@@ -343,23 +1040,8 @@ sub run_diff
 
     # @patch has slurped diff for all files...
     my $filesref = parse_diff ( \@patch );
-    show_patch_lines($filesref) if $debug;
-
-    print "Checking coverage:\n" if $debug;
+    show_patch_lines($filesref) if $debug>1;
 
-    my $cwd=getcwd();
-    chdir ".cov" || die "Can't find $cwd/.cov:$!\n";
-
-    for my $file (keys(%$filesref))
-    {
-        my ($name, $path, $suffix) = fileparse($file, qr{\.[^.]*$});
-        next if($path !~ /^dali/);
-        if($suffix eq ".cpp" || $suffix eq ".c" || $suffix eq ".h")
-        {
-            get_coverage($file, $filesref);
-        }
-    }
-    chdir $cwd;
     return $filesref;
 }
 
@@ -378,35 +1060,45 @@ sub calc_patch_coverage_percentage
         my $uncovered_lines = 0;
 
         my $patchref = $filesref->{$file}->{"patch"};
-        my $coverage_ref = $filesref->{$file}->{"coverage"};
-        if( $coverage_ref )
+
+        my $abs_filename = File::Spec->rel2abs($file, $root);
+        my $sumcountref = $info_data{$abs_filename}->{"sum"};
+
+        if( $sumcountref )
         {
             for my $patch (@$patchref)
             {
                 for(my $i = 0; $i < $patch->[1]; $i++ )
                 {
                     my $line = $i + $patch->[0];
-                    if($coverage_ref->{"covered"}->{$line})
-                    {
-                        $covered_lines++;
-                        $total_covered_lines++;
-                    }
-                    if($coverage_ref->{"uncovered"}->{$line})
+                    if(exists($sumcountref->{$line}))
                     {
-                        $uncovered_lines++;
-                        $total_uncovered_lines++;
+                        if( $sumcountref->{$line} > 0 )
+                        {
+                            $covered_lines++;
+                            $total_covered_lines++;
+                        }
+                        else
+                        {
+                            $uncovered_lines++;
+                            $total_uncovered_lines++;
+                        }
                     }
                 }
             }
-            $coverage_ref->{"covered_lines"} = $covered_lines;
-            $coverage_ref->{"uncovered_lines"} = $uncovered_lines;
+            $filesref->{$file}->{"covered_lines"} = $covered_lines;
+            $filesref->{$file}->{"uncovered_lines"} = $uncovered_lines;
             my $total = $covered_lines + $uncovered_lines;
             my $percent = 0;
             if($total > 0)
             {
                 $percent = $covered_lines / $total;
             }
-            $coverage_ref->{"percent_covered"} = 100 * $percent;
+            $filesref->{$file}->{"percent_covered"} = 100 * $percent;
+        }
+        else
+        {
+            print "Can't find coverage data for $abs_filename\n";
         }
     }
     my $total_exec = $total_covered_lines + $total_uncovered_lines;
@@ -416,6 +1108,8 @@ sub calc_patch_coverage_percentage
     return [ $total_exec, $percent ];
 }
 
+#
+#
 sub patch_output
 {
     my $filesref = shift;
@@ -424,18 +1118,22 @@ sub patch_output
         my ($name, $path, $suffix) = fileparse($file, qr{\.[^.]*$});
         next if($path !~ /^dali/);
 
-        my $patchref = $filesref->{$file}->{"patch"};
-        my $b_lines_ref = $filesref->{$file}->{"b_lines"};
-        my $coverage_ref = $filesref->{$file}->{"coverage"};
+        my $fileref = $filesref->{$file};
+        my $patchref = $fileref->{"patch"};
+        my $b_lines_ref = $fileref->{"b_lines"};
+
+        my $abs_filename = File::Spec->rel2abs($file, $root);
+        my $sumcountref = $info_data{$abs_filename}->{"sum"};
+
         print BOLD, "$file  ";
 
-        if($coverage_ref)
+        if($fileref)
         {
-            if( $coverage_ref->{"covered_lines"} > 0
+            if( $fileref->{"covered_lines"} > 0
                 ||
-                $coverage_ref->{"uncovered_lines"} > 0 )
+                $fileref->{"uncovered_lines"} > 0 )
             {
-                print GREEN, "Covered: " . $coverage_ref->{"covered_lines"}, RED, " Uncovered: " . $coverage_ref->{"uncovered_lines"}, RESET;
+                print GREEN, "Covered: " . $fileref->{"covered_lines"}, RED, " Uncovered: " . $fileref->{"uncovered_lines"}, RESET;
             }
         }
         else
@@ -461,28 +1159,29 @@ sub patch_output
                 my $line = $i + $patch->[0];
                 printf "%-6s  ", $line;
 
-                if($coverage_ref)
+                if($sumcountref)
                 {
                     my $color;
-                    if($coverage_ref->{"covered"}->{$line})
-                    {
-                        $color=GREEN;
-                    }
-                    elsif($coverage_ref->{"uncovered"}->{$line})
+                    if(exists($sumcountref->{$line}))
                     {
-                        $color=BOLD . RED;
+                        if($sumcountref->{$line} > 0)
+                        {
+                            $color=GREEN;
+                        }
+                        else
+                        {
+                            $color=BOLD . RED;
+                        }
                     }
                     else
                     {
-                        $color=BLACK;
+                        $color=CYAN;
                     }
-                    my $src=$coverage_ref->{"src"}->{$line};
-                    chomp($src);
+                    my $src = $b_lines_ref->{$line};
                     print $color, "$src\n", RESET;
                 }
                 else
                 {
-                    # We don't have coverage data, so print it from the patch instead.
                     my $src = $b_lines_ref->{$line};
                     print "$src\n";
                 }
@@ -491,70 +1190,65 @@ sub patch_output
     }
 }
 
-
+#
+#
 sub patch_html_output
 {
     my $filesref = shift;
 
-    my $html = HTML::Element->new('html');
-    my $head = HTML::Element->new('head');
-    my $title = HTML::Element->new('title');
-    $title->push_content("Patch Coverage");
-    $head->push_content($title, "\n");
-    $html->push_content($head, "\n");
+    open( my $filehandle, ">", $opt_output ) || die "Can't open $opt_output for writing:$!\n";
 
-    my $body = HTML::Element->new('body');
-    $body->attr('bgcolor', "white");
+    my $OUTPUT_FH = select;
+    select $filehandle;
+    print <<EOH;
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
+"http://www.w3.org/TR/REC-html40/loose.dtd">
+<html>
+<head>
+<title>Patch Coverage</title>
+</head>
+<body bgcolor="white">
+EOH
 
-    foreach my $file (sort(keys(%$filesref)))
+    foreach my $file (keys(%$filesref))
     {
         my ($name, $path, $suffix) = fileparse($file, qr{\.[^.]*$});
         next if($path !~ /^dali/);
 
-        my $patchref = $filesref->{$file}->{"patch"};
-        my $b_lines_ref = $filesref->{$file}->{"b_lines"};
-        my $coverage_ref = $filesref->{$file}->{"coverage"};
-
-        my $header = HTML::Element->new('h2');
-        $header->push_content($file);
-        $body->push_content($header);
-        $body->push_content("\n");
-        if($coverage_ref)
+        my $fileref = $filesref->{$file};
+        my $patchref = $fileref->{"patch"};
+        my $b_lines_ref = $fileref->{"b_lines"};
+
+        my $abs_filename = File::Spec->rel2abs($file, $root);
+        my $sumcountref = $info_data{$abs_filename}->{"sum"};
+
+        print "<h2>$file</h2>\n";
+
+        if($fileref)
         {
-            if( $coverage_ref->{"covered_lines"} > 0
+            if( $fileref->{"covered_lines"} > 0
                 ||
-                $coverage_ref->{"uncovered_lines"} > 0 )
+                $fileref->{"uncovered_lines"} > 0 )
             {
-                my $para = HTML::Element->new('p');
-                my $covered = HTML::Element->new('span');
-                $covered->attr('style', "color:green;");
-                $covered->push_content("Covered: " . $coverage_ref->{"covered_lines"} );
-                $para->push_content($covered);
-
-                my $para2 = HTML::Element->new('p');
-                my $uncovered = HTML::Element->new('span');
-                $uncovered->attr('style', "color:red;");
-                $uncovered->push_content("Uncovered: " . $coverage_ref->{"uncovered_lines"} );
-                $para2->push_content($uncovered);
-                $body->push_content($para, $para2);
-            }
-            else
-            {
-                #print "coverage ref exists for $file:\n" . Data::Dumper::Dumper($coverage_ref) . "\n";
+                print "<p style=\"color:green;\">Covered: " .
+                    $fileref->{"covered_lines"} . "<p>" .
+                    "<p style=\"color:red;\">Uncovered: " .
+                    $fileref->{"uncovered_lines"} . "</span></p>";
             }
         }
         else
         {
-            my $para = HTML::Element->new('p');
-            my $span = HTML::Element->new('span');
+            print "<p>";
+            my $span=0;
             if($suffix eq ".cpp" || $suffix eq ".c" || $suffix eq ".h")
             {
-                $span->attr('style', "color:red;");
+                print "<span style=\"color:red;\">";
+                $span=1;
             }
-            $span->push_content("No coverage found");
-            $para->push_content($span);
-            $body->push_content($para);
+            print "No coverage found";
+            print "</span>" if $span;
         }
+        print "</p>";
 
         for my $patch (@$patchref)
         {
@@ -563,71 +1257,54 @@ sub patch_html_output
             {
                 $hunkstr .= " - " . ($patch->[0]+$patch->[1]-1);
             }
+            print "<p style=\"font-weight:bold;\">" . $hunkstr . "</p>";
 
-            my $para = HTML::Element->new('p');
-            my $span = HTML::Element->new('span');
-            $span->attr('style', "font-weight:bold;");
-            $span->push_content($hunkstr);
-            $para->push_content($span);
-            $body->push_content($para);
-
-            my $codeHunk = HTML::Element->new('pre');
+            print "<pre>";
             for(my $i = 0; $i < $patch->[1]; $i++ )
             {
                 my $line = $i + $patch->[0];
                 my $num_line_digits=log($line)/log(10);
                 for $i (0..(6-$num_line_digits-1))
                 {
-                    $codeHunk->push_content(" ");
+                    print " ";
                 }
+                print "$line  ";
 
-                $codeHunk->push_content("$line  ");
-
-                my $srcLine = HTML::Element->new('span');
-                if($coverage_ref)
+                if($sumcountref)
                 {
                     my $color;
-
-                    if($coverage_ref->{"covered"}->{$line})
-                    {
-                        $srcLine->attr('style', "color:green;");
-                    }
-                    elsif($coverage_ref->{"uncovered"}->{$line})
+                    if(exists($sumcountref->{$line}))
                     {
-                        $srcLine->attr('style', "color:red;font-weight:bold;");
+                        if($sumcountref->{$line} > 0)
+                        {
+                            print("<span style=\"color:green;\">");
+                        }
+                        else
+                        {
+                            print("<span style=\"color:red;font-weight:bold;\">");
+                        }
                     }
                     else
                     {
-                        $srcLine->attr('style', "color:black;font-weight:normal;");
+                        print("<span style=\"color:black;font-weight:normal;\">");
                     }
-                    my $src=$coverage_ref->{"src"}->{$line};
+                    my $src=$b_lines_ref->{$line};
                     chomp($src);
-                    $srcLine->push_content($src);
+                    print "$src</span>\n";
                 }
                 else
                 {
-                    # We don't have coverage data, so print it from the patch instead.
                     my $src = $b_lines_ref->{$line};
-                    $srcLine->attr('style', "color:black;font-weight:normal;");
-                    $srcLine->push_content($src);
+                    print "$src\n";
                 }
-                $codeHunk->push_content($srcLine, "\n");
             }
-            $body->push_content($codeHunk, "\n");
+            print "<\pre>\n";
         }
     }
-    $body->push_content(HTML::Element->new('hr'));
-    $html->push_content($body, "\n");
-
-    open( my $filehandle, ">", $opt_output ) || die "Can't open $opt_output for writing:$!\n";
 
-    print $filehandle <<EOH;
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
-"http://www.w3.org/TR/REC-html40/loose.dtd">
-EOH
-;
-    print $filehandle $html->as_HTML();
+    print $filehandle "<hr>\n</body>\n</html>\n";
     close $filehandle;
+    select $OUTPUT_FH;
 }
 
 
@@ -635,15 +1312,38 @@ EOH
 ##                                    MAIN                                    ##
 ################################################################################
 
-my $cwd = getcwd();
-chdir $repo->wc_path();
-chdir "build/tizen";
-`make rename_cov_data`;
+my $cwd = getcwd(); # expect this to be automated-tests folder
 
-my @cmd=('--no-pager','diff','--no-ext-diff','-U0','--no-color');
+# execute coverage.sh, generating build/tizen/dali.info from lib, and
+# *.dir/dali.info. Don't generate html
+`coverage.sh -n`;
+chdir "..";
+$root = getcwd();
+
+our %info_data; # Hash of all data from .info files
+my @info_files = split(/\n/, `find . -name dali.info`);
+my %new_info;
 
+# Read in all specified .info files
+foreach (@info_files)
+{
+    %new_info = %{read_info_file($_)};
+
+    # Combine %new_info with %info_data
+    %info_data = %{combine_info_files(\%info_data, \%new_info)};
+}
+
+
+# Generate git diff command
+my @cmd=('--no-pager','diff','--no-ext-diff','-U0','--no-color');
 my $status = $repo->command("status", "-s");
-if( $status eq "" && !scalar(@ARGV))
+
+if(scalar(@ARGV)) # REMOVE ME
+{
+    # REMOVE ME - temp to get past modifying this script in place.
+    push @cmd, @ARGV;
+}
+elsif( $status eq "" && !scalar(@ARGV))
 {
     # There are no changes in the index or working tree, and
     # no diff arguments to append. Use the last patch instead.
@@ -674,6 +1374,8 @@ else
 }
 
 push @cmd, @ARGV;
+
+# Execute diff & coverage from root directory
 my $filesref = run_diff(@cmd);
 
 chdir $cwd;
@@ -693,6 +1395,9 @@ if( $filecount == 0 )
     exit 0;    # Exit with no error.
 }
 
+#print_simplified_info() if $debug;
+#exit 0;
+
 my $percentref = calc_patch_coverage_percentage($filesref);
 if($percentref->[0] == 0)
 {
old mode 100644 (file)
new mode 100755 (executable)
index 0b2a35b..d161892
@@ -7926,6 +7926,43 @@ int UtcDaliActorCaptureAllTouchAfterStartPropertyN(void)
   END_TEST;
 }
 
+int UtcDaliActorTouchDelegateAreaPropertyP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector2 touchDelegateArea = actor.GetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA).Get<Vector2>();
+  DALI_TEST_EQUALS(touchDelegateArea, Vector2::ZERO, TEST_LOCATION);
+  actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Vector2(10.f, 10.f));
+  touchDelegateArea = actor.GetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA).Get<Vector2>();
+  DALI_TEST_EQUALS(touchDelegateArea, Vector2(10.f, 10.f), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliActorTouchDelegateAreaPropertyN(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Make sure setting invalid types does not cause a crash
+  try
+  {
+    actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, 1.0f);
+    actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Vector2::ONE);
+    actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Vector3::ONE);
+    actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Vector4::ONE);
+    actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Property::Map());
+    actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Property::Array());
+    tet_result(TET_PASS);
+  }
+  catch(...)
+  {
+    tet_result(TET_FAIL);
+  }
+  END_TEST;
+}
+
 int UtcDaliActorLowerBelowNegative(void)
 {
   TestApplication application;
old mode 100644 (file)
new mode 100755 (executable)
index 2aaf3e2..e0c7b80
@@ -2068,3 +2068,119 @@ int UtcDaliTouchEventIntegNewTouchEvent(void)
 
   END_TEST;
 }
+
+
+int UtcDaliTouchEventIntercept(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  parent.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  application.GetScene().Add(parent);
+
+  Actor actor = Actor::New();
+  actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  parent.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData        data;
+  TouchEventFunctor functor(data, false /* Do not consume */);
+  actor.TouchedSignal().Connect(&application, functor);
+
+
+  // Connect to parent's touched signal
+  SignalData        parentData;
+  TouchEventFunctor parentFunctor(parentData, false /* Do not consume */);
+  parent.TouchedSignal().Connect(&application, parentFunctor);
+  // Connect to parent's intercept touched signal
+  SignalData        interceptData;
+  TouchEventFunctor interceptFunctor(interceptData, true /* Do intercept */);
+  Dali::DevelActor::InterceptTouchedSignal(parent).Connect(&application, interceptFunctor);
+
+  // Emit a down signal
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+  // The actor touched signal is not called because the touch is intercepted in the parent.
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, interceptData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(PointState::DOWN, interceptData.receivedTouch.points[0].state, TEST_LOCATION);
+  DALI_TEST_CHECK(actor == interceptData.receivedTouch.points[0].hitActor);
+  DALI_TEST_CHECK(parent == interceptData.touchedActor);
+  DALI_TEST_EQUALS(true, parentData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(PointState::DOWN, parentData.receivedTouch.points[0].state, TEST_LOCATION);
+  DALI_TEST_CHECK(actor == parentData.receivedTouch.points[0].hitActor);
+  DALI_TEST_CHECK(parent == parentData.touchedActor);
+  data.Reset();
+  parentData.Reset();
+
+  END_TEST;
+}
+
+int UtcDaliTouchDelegateArea(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+
+  application.GetScene().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData        data;
+  TouchEventFunctor functor(data, false /* Do not consume */);
+  actor.TouchedSignal().Connect(&application, functor);
+
+  // Emit a down signal
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(110.0f, 110.0f)));
+  // The actor touched signal is not called because the touch area is outside actor.
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // set a bigger touch delegate area
+  actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Vector2(200.0f, 200.0f));
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit a down signal
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(110.0f, 110.0f)));
+  // The actor touched signal is called because the touch area is inside touchDelegateArea.
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+  DALI_TEST_CHECK(actor == data.receivedTouch.points[0].hitActor);
+  data.Reset();
+
+  // set a smaller touch delegate area
+  actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Vector2(50.0f, 50.0f));
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit a down signal
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(80.0f, 80.0f)));
+  // The actor touched signal is not called because the touch area is outside touchDelegateArea.
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Emit a down signal
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(30.0f, 30.0f)));
+  // The actor touched signal is called because the touch area is inside touchDelegateArea.
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+  DALI_TEST_CHECK(actor == data.receivedTouch.points[0].hitActor);
+  data.Reset();
+
+  END_TEST;
+}
old mode 100644 (file)
new mode 100755 (executable)
index 68a5205..fd08434
@@ -48,6 +48,11 @@ ChildOrderChangedSignalType& ChildOrderChangedSignal(Actor actor)
   return GetImplementation(actor).ChildOrderChangedSignal();
 }
 
+Actor::TouchEventSignalType& InterceptTouchedSignal(Actor actor)
+{
+  return GetImplementation(actor).InterceptTouchedSignal();
+}
+
 } // namespace DevelActor
 
 } // namespace Dali
old mode 100644 (file)
new mode 100755 (executable)
index 43b44f7..7b1b7d1
@@ -117,7 +117,21 @@ enum Type
     * @details Name "captureAllTouchAfterStart", type Property::BOOLEAN
     * @note Default is false, i.e. actor under touch event will receive the touch even if touch started on this actor
     */
-  CAPTURE_ALL_TOUCH_AFTER_START
+  CAPTURE_ALL_TOUCH_AFTER_START,
+
+  /**
+    * @brief If you set the TOUCH_DELEGATE_AREA on an actor, when you touch the actor, the delegate area is used rather than the size of the actor
+    * @details Name "touchDelegateArea", type Property::Vector2
+    * @note Default is Vector2::ZERO.
+    * @note for example
+    *  Actor actor = Actor::New();
+    *  actor.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+    *  actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Vector2(200.0f, 200.0f));
+    *  actor.TouchedSignal().Connect(OnTouchCallback);
+    *
+    *  If you want to reset the touch area to an area different with the size of the actor, you can set this TOUCH_DELEGATE_AREA property.
+    */
+  TOUCH_DELEGATE_AREA
 };
 
 } // namespace Property
@@ -215,6 +229,40 @@ using ChildOrderChangedSignalType = Signal<void(Actor)>; ///< Used when the acto
  */
 DALI_CORE_API ChildOrderChangedSignalType& ChildOrderChangedSignal(Actor actor);
 
+/**
+ * @brief This signal is emitted when intercepting the actor's touch event.
+ *
+ * A callback of the following type may be connected:
+ * @code
+ *   void MyCallbackName( Actor actor );
+ * @endcode
+ * actor The actor to intercept
+ *
+ * @note TouchEvent callbacks are called from the last child in the order of the parent's actor.
+ * The InterceptTouchEvent callback is to intercept the touch event in the parent.
+ * So, if the parent interepts the touch event, the child cannot receive the touch event.
+ *
+ * @note example
+ *   Actor parent = Actor::New();
+ *   Actor child = Actor::New();
+ *   parent.Add(child);
+ *   child.TouchedSignal().Connect(&application, childFunctor);
+ *   parent.TouchedSignal().Connect(&application, parentFunctor);
+ * The touch event callbacks are called in the order childFunctor -> parentFunctor.
+ *
+ * If you connect interceptTouchSignal to parentActor.
+ *   Dali::DevelActor::InterceptTouchedSignal(parent).Connect(&application, interceptFunctor);
+ *
+ * When interceptFunctor returns false, the touch event callbacks are called in the same order childFunctor -> parentFunctor.
+ * If interceptFunctor returns true, it means that the TouchEvent was intercepted.
+ * So the child actor will not be able to receive touch events.
+ * Only the parentFunctor is called.
+ *
+ * @return The signal to connect to
+ * @pre The Actor has been initialized
+ */
+DALI_CORE_API Actor::TouchEventSignalType& InterceptTouchedSignal(Actor actor);
+
 } // namespace DevelActor
 
 } // namespace Dali
old mode 100644 (file)
new mode 100755 (executable)
index 321b111..75ca77c
@@ -143,6 +143,7 @@ DALI_PROPERTY( "keyboardFocusable",         BOOLEAN,  true,  false, false, Dali:
 DALI_PROPERTY( "siblingOrder",              INTEGER,  true,  false, false, Dali::DevelActor::Property::SIBLING_ORDER )
 DALI_PROPERTY( "updateSizeHint",            VECTOR2,  true,  false, false, Dali::DevelActor::Property::UPDATE_SIZE_HINT )
 DALI_PROPERTY( "captureAllTouchAfterStart", BOOLEAN,  true,  false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START )
+DALI_PROPERTY( "touchDelegateArea",         VECTOR2,  true,  false, false, Dali::DevelActor::Property::TOUCH_DELEGATE_AREA )
 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
 
 // Signals
@@ -836,6 +837,8 @@ void Actor::SetOpacity( float opacity )
 
   // node is being used in a separate thread; queue a message to set the value & base value
   SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
+
+  RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
 }
 
 float Actor::GetCurrentOpacity() const
@@ -855,6 +858,8 @@ void Actor::SetColor( const Vector4& color )
 
   // node is being used in a separate thread; queue a message to set the value & base value
   SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
+
+  RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
 }
 
 void Actor::SetColorRed( float red )
@@ -863,6 +868,8 @@ void Actor::SetColorRed( float red )
 
   // node is being used in a separate thread; queue a message to set the value & base value
   SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
+
+  RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
 }
 
 void Actor::SetColorGreen( float green )
@@ -871,6 +878,8 @@ void Actor::SetColorGreen( float green )
 
   // node is being used in a separate thread; queue a message to set the value & base value
   SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
+
+  RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
 }
 
 void Actor::SetColorBlue( float blue )
@@ -879,6 +888,8 @@ void Actor::SetColorBlue( float blue )
 
   // node is being used in a separate thread; queue a message to set the value & base value
   SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
+
+  RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
 }
 
 const Vector4& Actor::GetCurrentColor() const
@@ -1319,6 +1330,11 @@ bool Actor::IsGestureRequired( GestureType::Value type ) const
   return mGestureData && mGestureData->IsGestureRequired( type );
 }
 
+bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch )
+{
+  return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch );
+}
+
 bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch )
 {
   return EmitConsumingSignal( *this, mTouchedSignal, touch );
@@ -1418,6 +1434,7 @@ Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
   mAnchorPoint( nullptr ),
   mRelayoutData( nullptr ),
   mGestureData( nullptr ),
+  mInterceptTouchedSignal(),
   mTouchedSignal(),
   mHoveredSignal(),
   mWheelEventSignal(),
@@ -1435,6 +1452,7 @@ Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
   mTargetPosition( Vector3::ZERO ),
   mTargetScale( Vector3::ONE ),
   mAnimatedSize( Vector3::ZERO ),
+  mTouchDelegateArea( Vector2::ZERO ),
   mName(),
   mSortedDepth( 0u ),
   mDepth( 0u ),
@@ -2492,6 +2510,8 @@ void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
     {
       // node is being used in a separate thread; queue a message to set the value & base value
       SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
+
+      RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
     }
 
     mVisible = visible;
old mode 100644 (file)
new mode 100755 (executable)
index 5a11cd0..4404718
@@ -1326,6 +1326,16 @@ public:
     return mKeyboardFocusable;
   }
 
+
+  /**
+   * Query whether the application or derived actor type requires intercept touch events.
+   * @return True if intercept touch events are required.
+   */
+  bool GetInterceptTouchRequired() const
+  {
+    return !mInterceptTouchedSignal.Empty();
+  }
+
   /**
    * Query whether the application or derived actor type requires touch events.
    * @return True if touch events are required.
@@ -1372,6 +1382,25 @@ public:
     return mCaptureAllTouchAfterStart;
   }
 
+  /**
+   * Sets the touch delegate area of an actor.
+   * @param [in] area The new area.
+   */
+  void SetTouchDelegateArea(Vector2 area)
+  {
+    mTouchDelegateArea = area;
+  }
+
+  /**
+   * Retrieve the Actor's touch delegate area.
+   * @return The Actor's touch delegate area.
+   */
+  const Vector2& GetTouchDelegateArea() const
+  {
+    return mTouchDelegateArea;
+  }
+
+
   // Gestures
 
   /**
@@ -1394,6 +1423,13 @@ public:
   // Signals
 
   /**
+   * Used by the EventProcessor to emit intercept touch event signals.
+   * @param[in] touch The touch data.
+   * @return True if the event was intercepted.
+   */
+  bool EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch );
+
+  /**
    * Used by the EventProcessor to emit touch event signals.
    * @param[in] touch The touch data.
    * @return True if the event was consumed.
@@ -1440,6 +1476,14 @@ public:
   void EmitChildRemovedSignal( Actor& child );
 
   /**
+   * @copydoc DevelActor::InterceptTouchedSignal()
+   */
+  Dali::Actor::TouchEventSignalType& InterceptTouchedSignal()
+  {
+    return mInterceptTouchedSignal;
+  }
+
+  /**
    * @copydoc Dali::Actor::TouchedSignal()
    */
   Dali::Actor::TouchEventSignalType& TouchedSignal()
@@ -1982,6 +2026,7 @@ protected:
   ActorGestureData* mGestureData;   ///< Optional Gesture data. Only created when actor requires gestures
 
   // Signals
+  Dali::Actor::TouchEventSignalType         mInterceptTouchedSignal;
   Dali::Actor::TouchEventSignalType        mTouchedSignal;
   Dali::Actor::HoverSignalType             mHoveredSignal;
   Dali::Actor::WheelEventSignalType        mWheelEventSignal;
@@ -2000,6 +2045,7 @@ protected:
   Vector3         mTargetPosition;    ///< Event-side storage for position (not a pointer as most actors will have a position)
   Vector3         mTargetScale;       ///< Event-side storage for scale
   Vector3         mAnimatedSize;      ///< Event-side storage for size animation
+  Vector2         mTouchDelegateArea; ///< touch delegate area
 
   std::string     mName;              ///< Name of the actor
   uint32_t        mSortedDepth;       ///< The sorted depth index. A combination of tree traversal and sibling order.
old mode 100644 (file)
new mode 100755 (executable)
index 099466e..415f637
@@ -574,6 +574,17 @@ void Actor::PropertyHandler::SetDefaultProperty( Internal::Actor& actor, Propert
       break;
     }
 
+    case Dali::DevelActor::Property::TOUCH_DELEGATE_AREA:
+    {
+      Vector2 vec2Value;
+      if( property.Get( vec2Value ) )
+      {
+        actor.SetTouchDelegateArea( vec2Value );
+      }
+      break;
+    }
+
+
     default:
     {
       // this can happen in the case of a non-animatable default property so just do nothing
@@ -1603,6 +1614,12 @@ bool Actor::PropertyHandler::GetCachedPropertyValue(const Internal::Actor& actor
       break;
     }
 
+    case Dali::DevelActor::Property::TOUCH_DELEGATE_AREA:
+    {
+      value = actor.GetTouchDelegateArea();
+      break;
+    }
+
     default:
     {
       // Must be a scene-graph only property
index db41040..0a05d70 100644 (file)
@@ -137,7 +137,6 @@ void ValidateParameters( Property::Type propertyType, Property::Type destination
 
 } // anonymous namespace
 
-
 AnimationPtr Animation::New(float durationSeconds)
 {
   if( durationSeconds < 0.0f )
@@ -155,26 +154,13 @@ AnimationPtr Animation::New(float durationSeconds)
   return animation;
 }
 
-Animation::Animation( EventThreadServices& eventThreadServices, AnimationPlaylist& playlist, float durationSeconds, EndAction endAction, EndAction disconnectAction, AlphaFunction defaultAlpha )
-: mAnimation( nullptr ),
-  mEventThreadServices( eventThreadServices ),
-  mPlaylist( playlist ),
-  mFinishedSignal(),
-  mConnectors(),
-  mConnectorTargetValues(),
-  mPlayRange( Vector2(0.0f,1.0f)),
-  mDurationSeconds( durationSeconds ),
-  mSpeedFactor(1.0f),
-  mNotificationCount( 0 ),
-  mLoopCount(1),
-  mCurrentLoop(0),
-  mEndAction( endAction ),
-  mDisconnectAction( disconnectAction ),
-  mDefaultAlpha( defaultAlpha ),
-  mState(Dali::Animation::STOPPED),
-  mProgressReachedMarker( 0.0f ),
-  mDelaySeconds( 0.0f ),
-  mAutoReverseEnabled( false )
+Animation::Animation(EventThreadServices& eventThreadServices, AnimationPlaylist& playlist, float durationSeconds, EndAction endAction, EndAction disconnectAction, AlphaFunction defaultAlpha)
+: mEventThreadServices(eventThreadServices),
+  mPlaylist(playlist),
+  mDefaultAlpha(defaultAlpha),
+  mDurationSeconds(durationSeconds),
+  mEndAction(endAction),
+  mDisconnectAction(disconnectAction)
 {
 }
 
index 3820ade..6d715fe 100644 (file)
@@ -61,12 +61,11 @@ using AnimationConstIter = AnimationContainer::const_iterator;
 class Animation : public BaseObject
 {
 public:
-
-  enum Type
+  enum Type : uint8_t
   {
-    TO,      ///< Animating TO the given value
-    BY,      ///< Animating BY the given value
-    BETWEEN  ///< Animating BETWEEN key-frames
+    TO,     ///< Animating TO the given value
+    BY,     ///< Animating BY the given value
+    BETWEEN ///< Animating BETWEEN key-frames
   };
 
   using EndAction     = Dali::Animation::EndAction;
@@ -492,7 +491,7 @@ private:
     Animation::Type animatorType{TO};
   };
 
-  enum class Notify
+  enum class Notify : uint8_t
   {
     USE_CURRENT_VALUE,   ///< Set the current value for the property
     USE_TARGET_VALUE,    ///< Set the animator's target value for the property
@@ -521,36 +520,33 @@ private:
   void SendFinalProgressNotificationMessage();
 
 private:
+  using AnimatorConnectorContainer     = OwnerContainer<AnimatorConnectorBase*>;
+  using ConnectorTargetValuesContainer = std::vector<ConnectorTargetValues>;
 
-  const SceneGraph::Animation* mAnimation;
+  const SceneGraph::Animation* mAnimation{ nullptr };
 
   EventThreadServices& mEventThreadServices;
-  AnimationPlaylist& mPlaylist;
-
-  Dali::Animation::AnimationSignalType mFinishedSignal;
-
-  Dali::Animation::AnimationSignalType mProgressReachedSignal;
-
-  using AnimatorConnectorContainer = OwnerContainer<AnimatorConnectorBase*>;
-  AnimatorConnectorContainer mConnectors; ///< Owned by the Animation
-
-  using ConnectorTargetValuesContainer = std::vector<ConnectorTargetValues>;
-  ConnectorTargetValuesContainer mConnectorTargetValues; //< Used to store animating property target value information
-
-  Vector2 mPlayRange;
-
-  float mDurationSeconds;
-  float mSpeedFactor;
-  int32_t mNotificationCount; ///< Keep track of how many Finished signals have been emitted.
-  int32_t mLoopCount;
-  int32_t mCurrentLoop;
-  EndAction mEndAction;
-  EndAction mDisconnectAction;
-  AlphaFunction mDefaultAlpha;
-  Dali::Animation::State mState;
-  float mProgressReachedMarker;
-  float mDelaySeconds;
-  bool mAutoReverseEnabled;  ///< Flag to identify that the looping mode is auto reverse.
+  AnimationPlaylist&   mPlaylist;
+
+  Dali::Animation::AnimationSignalType mFinishedSignal{};
+  Dali::Animation::AnimationSignalType mProgressReachedSignal{};
+
+  AnimatorConnectorContainer     mConnectors{};            ///< Owned by the Animation
+  ConnectorTargetValuesContainer mConnectorTargetValues{}; //< Used to store animating property target value information
+
+  AlphaFunction          mDefaultAlpha;
+  Vector2                mPlayRange{0.0f, 1.0f};
+  float                  mDurationSeconds;
+  float                  mSpeedFactor{1.0f};
+  int32_t                mNotificationCount{0}; ///< Keep track of how many Finished signals have been emitted.
+  int32_t                mLoopCount{1};
+  int32_t                mCurrentLoop{0};
+  float                  mProgressReachedMarker{0.0f};
+  float                  mDelaySeconds{0.0f};
+  EndAction              mEndAction;
+  EndAction              mDisconnectAction;
+  Dali::Animation::State mState{Dali::Animation::STOPPED};
+  bool                   mAutoReverseEnabled{false}; ///< Flag to identify that the looping mode is auto reverse.
 };
 
 } // namespace Internal
old mode 100644 (file)
new mode 100755 (executable)
index cee959d..112c03a
@@ -156,7 +156,7 @@ bool RayTest::ActorTest(const Internal::Actor& actor, const Vector4& rayOrigin,
       // Ray travels distance * rayDirLocal to intersect with plane.
       distance = a / b;
 
-      const Vector3& size = node.GetSize(EventThreadServices::Get().GetEventBufferIndex());
+      const Vector2& size = actor.GetTouchDelegateArea() == Vector2::ZERO ? Vector2(node.GetSize(EventThreadServices::Get().GetEventBufferIndex())) : actor.GetTouchDelegateArea();
       hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
       hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
 
old mode 100644 (file)
new mode 100755 (executable)
index 864ce8c..146387c
@@ -60,6 +60,36 @@ const char * TOUCH_POINT_STATE[ 6 ] =
 
 #endif // defined(DEBUG_ENABLED)
 
+Dali::Actor EmitInterceptTouchSignals( Dali::Actor actor, const Dali::TouchEvent& touchEvent )
+{
+  Dali::Actor interceptedActor;
+
+  if( actor )
+  {
+     Dali::Actor parent = actor.GetParent();
+     if( parent )
+     {
+       // Recursively deliver events to the actor and its parents for intercept touch event.
+       interceptedActor = EmitInterceptTouchSignals( parent, touchEvent );
+     }
+
+     if( !interceptedActor )
+     {
+       bool intercepted = false;
+       Actor& actorImpl( GetImplementation(actor) );
+       if( actorImpl.GetInterceptTouchRequired() )
+       {
+          intercepted = actorImpl.EmitInterceptTouchEventSignal( touchEvent );
+          if( intercepted )
+          {
+            interceptedActor = Dali::Actor( &actorImpl );
+          }
+       }
+     }
+  }
+
+  return interceptedActor;
+}
 
 /**
  *  Recursively deliver events to the actor and its parents, until the event is consumed or the stage is reached.
@@ -315,7 +345,16 @@ bool TouchEventProcessor::ProcessTouchEvent( const Integration::TouchEvent& even
   Dali::Actor consumedActor;
   if ( currentRenderTask )
   {
-    consumedActor = EmitTouchSignals( touchEventImpl->GetPoint( 0 ).GetHitActor(), touchEventHandle );
+    // Emit the intercept touch signal
+    Dali::Actor interceptedActor = EmitInterceptTouchSignals( touchEventImpl->GetPoint( 0 ).GetHitActor(), touchEventHandle );
+    if( interceptedActor )
+    {
+      consumedActor = EmitTouchSignals( interceptedActor, touchEventHandle );
+    }
+    else
+    {
+      consumedActor = EmitTouchSignals( touchEventImpl->GetPoint( 0 ).GetHitActor(), touchEventHandle );
+    }
     consumed = consumedActor ? true : false;
   }
 
index 3a95d54..aa01b10 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
@@ -78,7 +78,8 @@ Animation::Animation( float durationSeconds, float speedFactor, const Vector2& p
   mDisconnectAction(disconnectAction),
   mState(Stopped),
   mProgressReachedSignalRequired( false ),
-  mAutoReverseEnabled( false )
+  mAutoReverseEnabled( false ),
+  mIsActive{ false }
 {
 }
 
@@ -424,6 +425,8 @@ void Animation::Update( BufferIndex bufferIndex, float elapsedSeconds, bool& loo
 
 void Animation::UpdateAnimators( BufferIndex bufferIndex, bool bake, bool animationFinished )
 {
+  mIsActive[bufferIndex] = false;
+
   const Vector2 playRange( mPlayRange * mDurationSeconds );
   float elapsedSecondsClamped = Clamp( mElapsedSeconds, playRange.x, playRange.y );
 
@@ -454,6 +457,11 @@ void Animation::UpdateAnimators( BufferIndex bufferIndex, bool bake, bool animat
             progress = Clamp((elapsedSecondsClamped - intervalDelay) / animatorDuration, 0.0f , 1.0f );
           }
           animator->Update(bufferIndex, progress, bake);
+
+          if (animatorDuration > 0.0f && (elapsedSecondsClamped - intervalDelay) <= animatorDuration)
+          {
+            mIsActive[bufferIndex] = true;
+          }
         }
         applied = true;
       }
index a4e309f..0617041 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_ANIMATION_H
 
 /*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
@@ -259,6 +259,16 @@ public:
   }
 
   /**
+   * Query whether the animation is currently active (i.e. at least one of the animators has been updated in either frame)
+   * @return True if the animation is currently active
+   */
+  bool IsActive() const
+  {
+    // As we have double buffering, if animator is updated in either frame, it needs to be rendered.
+    return mIsActive[0] || mIsActive[1];
+  }
+
+  /**
    * @brief Sets the looping mode.
    *
    * Animation plays forwards and then restarts from the beginning or runs backwards again.
@@ -349,6 +359,7 @@ protected:
 
   bool mProgressReachedSignalRequired;  // Flag to indicate the progress marker was hit
   bool mAutoReverseEnabled;             // Flag to identify that the looping mode is auto reverse.
+  bool mIsActive[2];                    // Flag to indicate whether the animation is active in the current frame (which is double buffered)
 };
 
 }; //namespace SceneGraph
index a51b0d7..277ccfb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
@@ -228,8 +228,10 @@ void TransformManager::ResetToBaseValue()
   }
 }
 
-void TransformManager::Update()
+bool TransformManager::Update()
 {
+  bool componentsChanged = false;
+
   if( mReorder )
   {
     //If some transform component has change its parent or has been removed since last update
@@ -321,8 +323,11 @@ void TransformManager::Update()
     mBoundingSpheres[i] = mWorld[i].GetTranslation();
     mBoundingSpheres[i].w = Length( centerToEdgeWorldSpace );
 
+    componentsChanged = componentsChanged || mComponentDirty[i];
     mComponentDirty[i] = false;
   }
+
+  return componentsChanged;
 }
 
 void TransformManager::SwapComponents( unsigned int i, unsigned int j )
@@ -381,31 +386,26 @@ Vector3& TransformManager::GetVector3PropertyValue( TransformId id, TransformMan
     case TRANSFORM_PROPERTY_POSITION:
     {
       TransformId index( mIds[id] );
-      mComponentDirty[ index ] = true;
       return mTxComponentAnimatable[ index ].mPosition;
     }
     case TRANSFORM_PROPERTY_SCALE:
     {
       TransformId index( mIds[id] );
-      mComponentDirty[ index ] = true;
       return mTxComponentAnimatable[ index ].mScale;
     }
     case TRANSFORM_PROPERTY_PARENT_ORIGIN:
     {
       TransformId index( mIds[id] );
-      mComponentDirty[ index ] = true;
       return mTxComponentStatic[ index ].mParentOrigin;
     }
     case TRANSFORM_PROPERTY_ANCHOR_POINT:
     {
       TransformId index( mIds[id] );
-      mComponentDirty[ index ] = true;
       return mTxComponentStatic[ index ].mAnchorPoint;
     }
     case TRANSFORM_PROPERTY_SIZE:
     {
       TransformId index( mIds[id] );
-      mComponentDirty[ index ] = true;
       return mSize[ index ];
     }
     default:
@@ -834,7 +834,6 @@ void TransformManager::BakeZVector3PropertyValue( TransformId id, TransformManag
 Quaternion& TransformManager::GetQuaternionPropertyValue( TransformId id )
 {
   TransformId index( mIds[id] );
-  mComponentDirty[ index ] = true;
   return mTxComponentAnimatable[ index ].mOrientation;
 }
 
index d003f57..068c39f 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_TRANSFORM_MANAGER_H
 
 /*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
@@ -192,8 +192,9 @@ public:
 
   /**
    * Recomputes all world transform matrices
+   * @return true if any component has been changed in this frame, false otherwise
    */
-  void Update();
+  bool Update();
 
   /**
    * Resets all the animatable properties to its base value
index 58fb0bc..a7ca327 100644 (file)
@@ -189,7 +189,8 @@ struct UpdateManager::Impl
     previousUpdateScene( false ),
     renderTaskWaiting( false ),
     renderersAdded( false ),
-    surfaceRectChanged( false )
+    surfaceRectChanged( false ),
+    renderingRequired( false )
   {
     sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
 
@@ -298,6 +299,7 @@ struct UpdateManager::Impl
   bool                                 renderTaskWaiting;             ///< A REFRESH_ONCE render task is waiting to be rendered
   bool                                 renderersAdded;                ///< Flag to keep track when renderers have been added to avoid unnecessary processing
   bool                                 surfaceRectChanged;            ///< True if the default surface rect is changed
+  bool                                 renderingRequired;             ///< True if required to render the current frame
 
 private:
 
@@ -734,8 +736,10 @@ bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, uint32_t lastVSync
   return gestureUpdated;
 }
 
-void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
+bool UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
 {
+  bool animationActive = false;
+
   auto&& iter = mImpl->animations.Begin();
   bool animationLooped = false;
 
@@ -747,6 +751,8 @@ void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
     bool progressMarkerReached = false;
     animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
 
+    animationActive = animationActive || animation->IsActive();
+
     if ( progressMarkerReached )
     {
       mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
@@ -772,6 +778,8 @@ void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
     // The application should be notified by NotificationManager, in another thread
     mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
   }
+
+  return animationActive;
 }
 
 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
@@ -852,7 +860,7 @@ void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
     //Apply constraints
     ConstrainPropertyOwner( *renderer, bufferIndex );
 
-    renderer->PrepareRender( bufferIndex );
+    mImpl->renderingRequired = renderer->PrepareRender( bufferIndex ) || mImpl->renderingRequired;
   }
 }
 
@@ -884,17 +892,20 @@ uint32_t UpdateManager::Update( float elapsedSeconds,
   //Clear nodes/resources which were previously discarded
   mImpl->discardQueue.Clear( bufferIndex );
 
+  bool isAnimationRunning = IsAnimationRunning();
+
   //Process Touches & Gestures
   const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
 
   bool updateScene = // The scene-graph requires an update if..
       (mImpl->nodeDirtyFlags & RenderableUpdateFlags) ||    // ..nodes were dirty in previous frame OR
-      IsAnimationRunning()                            ||    // ..at least one animation is running OR
+      isAnimationRunning                              ||    // ..at least one animation is running OR
       mImpl->messageQueue.IsSceneUpdateRequired()     ||    // ..a message that modifies the scene graph node tree is queued OR
       mImpl->frameCallbackProcessor                   ||    // ..a frame callback processor is existed OR
       gestureUpdated;                                       // ..a gesture property was updated
 
   bool keepRendererRendering = false;
+  mImpl->renderingRequired = false;
 
   // Although the scene-graph may not require an update, we still need to synchronize double-buffered
   // values if the scene was updated in the previous frame.
@@ -919,7 +930,7 @@ uint32_t UpdateManager::Update( float elapsedSeconds,
   if( updateScene || mImpl->previousUpdateScene )
   {
     //Animate
-    Animate( bufferIndex, elapsedSeconds );
+    bool animationActive = Animate( bufferIndex, elapsedSeconds );
 
     //Constraint custom objects
     ConstrainCustomObjects( bufferIndex );
@@ -957,7 +968,10 @@ uint32_t UpdateManager::Update( float elapsedSeconds,
     UpdateRenderers( bufferIndex );
 
     //Update the transformations of all the nodes
-    mImpl->transformManager.Update();
+    if ( mImpl->transformManager.Update() )
+    {
+      mImpl->nodeDirtyFlags |= NodePropertyFlags::TRANSFORM;
+    }
 
     //Process Property Notifications
     ProcessPropertyNotifications( bufferIndex );
@@ -982,7 +996,6 @@ uint32_t UpdateManager::Update( float elapsedSeconds,
         }
       }
 
-
       std::size_t numberOfRenderInstructions = 0;
       for ( auto&& scene : mImpl->scenes )
       {
@@ -991,13 +1004,19 @@ uint32_t UpdateManager::Update( float elapsedSeconds,
           scene->scene->GetRenderInstructions().ResetAndReserve( bufferIndex,
                                                      static_cast<uint32_t>( scene->taskList->GetTasks().Count() ) );
 
-          keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex,
-                                              *scene->taskList,
-                                              *scene->root,
-                                              scene->sortedLayerList,
-                                              scene->scene->GetRenderInstructions(),
-                                              renderToFboEnabled,
-                                              isRenderingToFbo );
+          // If there are animations running, only add render instruction if at least one animation is currently active (i.e. not delayed)
+          // or the nodes are dirty
+          if ( !isAnimationRunning || animationActive || mImpl->renderingRequired || (mImpl->nodeDirtyFlags & RenderableUpdateFlags) )
+          {
+            keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex,
+                                                *scene->taskList,
+                                                *scene->root,
+                                                scene->sortedLayerList,
+                                                scene->scene->GetRenderInstructions(),
+                                                renderToFboEnabled,
+                                                isRenderingToFbo );
+
+          }
 
           numberOfRenderInstructions += scene->scene->GetRenderInstructions().Count( bufferIndex );
         }
@@ -1139,6 +1158,11 @@ void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavio
   mImpl->renderingBehavior = renderingBehavior;
 }
 
+void UpdateManager::RequestRendering()
+{
+  mImpl->renderingRequired = true;
+}
+
 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer )
 {
   for ( auto&& scene : mImpl->scenes )
index 73e0f38..8f272d8 100644 (file)
@@ -644,6 +644,14 @@ public:
   void SetRenderingBehavior( DevelStage::Rendering renderingBehavior );
 
   /**
+   * Request to render the current frame
+   * @note This is a temporary workaround (to be removed in the future) to request the rendering of
+   *       the current frame if the color or visibility of any actor is updated. It MUST NOT be used
+   *       for any other purposes.
+   */
+  void RequestRendering();
+
+  /**
    * Sets the depths of all layers.
    * @param layers The layers in depth order.
    * @param[in] rootLayer The root layer of the sorted layers.
@@ -709,8 +717,9 @@ private:
    * Perform animation updates
    * @param[in] bufferIndex to use
    * @param[in] elapsedSeconds time since last frame
+   * @return true if at least one animations is currently active or false otherwise
    */
-  void Animate( BufferIndex bufferIndex, float elapsedSeconds );
+  bool Animate( BufferIndex bufferIndex, float elapsedSeconds );
 
   /**
    * Applies constraints to CustomObjects
@@ -1108,6 +1117,17 @@ inline void SetRenderingBehaviorMessage( UpdateManager& manager, DevelStage::Ren
   new (slot) LocalType( &manager, &UpdateManager::SetRenderingBehavior, renderingBehavior );
 }
 
+inline void RequestRenderingMessage( UpdateManager& manager )
+{
+  using LocalType = Message<UpdateManager>;
+
+  // Reserve some memory inside the message queue
+  uint32_t* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::RequestRendering );
+}
+
 /**
  * Create a message for setting the depth of a layer
  * @param[in] manager The update manager
index e821f6e..cce7464 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
@@ -181,7 +181,7 @@ void Renderer::operator delete( void* ptr )
 }
 
 
-void Renderer::PrepareRender( BufferIndex updateBufferIndex )
+bool Renderer::PrepareRender( BufferIndex updateBufferIndex )
 {
   if( mRegenerateUniformMap == UNIFORM_MAP_READY )
   {
@@ -221,6 +221,8 @@ void Renderer::PrepareRender( BufferIndex updateBufferIndex )
     mRegenerateUniformMap--;
   }
 
+  bool rendererUpdated = mUniformMapChanged[updateBufferIndex] || mResendFlag;
+
   if( mResendFlag != 0 )
   {
     if( mResendFlag & RESEND_GEOMETRY )
@@ -365,6 +367,8 @@ void Renderer::PrepareRender( BufferIndex updateBufferIndex )
 
     mResendFlag = 0;
   }
+
+  return rendererUpdated;
 }
 
 void Renderer::SetTextures( TextureSet* textureSet )
index b3ab63e..a06fa2a 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_RENDERER_H
 
 /*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
@@ -339,8 +339,9 @@ public:
    * Prepare the object for rendering.
    * This is called by the UpdateManager when an object is due to be rendered in the current frame.
    * @param[in] updateBufferIndex The current update buffer index.
+   * @return Whether this renderer has been updated in the current frame
    */
-  void PrepareRender( BufferIndex updateBufferIndex );
+  bool PrepareRender( BufferIndex updateBufferIndex );
 
   /**
    * Retrieve the Render thread renderer
index 3afaa88..120d5e1 100644 (file)
@@ -105,7 +105,6 @@ public:
    *   D   E   F
    *
    * @endcode
-   * @param[in] depth The depth in the hierarchy for the actor
    */
   virtual void OnSceneConnection(int32_t depth) = 0;
 
index 5a4a98a..d353d6c 100644 (file)
@@ -93,7 +93,6 @@ public:
    *
    * @SINCE_1_0.0
    * @param[in] implementation The implementation for this custom actor
-   * @return A handle to a newly allocated Dali resource
    */
   CustomActor(CustomActorImpl& implementation);
 
index 1ea2677..48c32b0 100644 (file)
@@ -83,7 +83,6 @@ public:
    * @brief Default constructor.
    * Creates an alpha function object with the default built-in alpha function.
    * @SINCE_1_0.0
-   * @return The alpha function
    */
   AlphaFunction();
 
@@ -93,7 +92,6 @@ public:
    * to the constructor.
    * @SINCE_1_0.0
    * @param[in] function One of the built-in alpha functions
-   * @return The alpha function
    */
   AlphaFunction(BuiltinFunction function);
 
@@ -103,7 +101,6 @@ public:
    * to the constructor.
    * @SINCE_1_0.0
    * @param[in] function A pointer to an alpha function
-   * @return The alpha function
    */
   AlphaFunction(AlphaFunctionPrototype function);
 
@@ -115,7 +112,6 @@ public:
    * @SINCE_1_0.0
    * @param[in] controlPoint0 A Vector2 which will be used as the first control point of the curve
    * @param[in] controlPoint1 A Vector2 which will be used as the second control point of the curve
-   * @return The alpha function
    * @note The x components of the control points will be clamped to the range [0,1] to prevent
    * non monotonic curves.
    */
index f7ba6bc..73599f4 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 // EXTERNAL INCLUDES
-#include <cstdint> // uint32_t
+#include <cstdint> // uint32_t, uint8_t
 
 // INTERNAL INCLUDES
 #include <dali/public-api/animation/alpha-function.h>
@@ -131,7 +131,7 @@ public:
    * @brief Enumeration for what to do when the animation ends, is stopped, or is destroyed.
    * @SINCE_1_0.0
    */
-  enum EndAction
+  enum EndAction : uint8_t
   {
     BAKE,      ///< When the animation ends, the animated property values are saved. @SINCE_1_0.0
     DISCARD,   ///< When the animation ends, the animated property values are forgotten. @SINCE_1_0.0
@@ -142,7 +142,7 @@ public:
    * @brief Enumeration for what interpolation method to use on key-frame animations.
    * @SINCE_1_0.0
    */
-  enum Interpolation
+  enum Interpolation : uint8_t
   {
     LINEAR, ///< Values in between key frames are interpolated using a linear polynomial. (Default) @SINCE_1_0.0
     CUBIC   ///< Values in between key frames are interpolated using a cubic polynomial. @SINCE_1_0.0
@@ -155,7 +155,7 @@ public:
    *
    * @SINCE_1_1.21
    */
-  enum State
+  enum State : uint8_t
   {
     STOPPED, ///< Animation has stopped @SINCE_1_1.21
     PLAYING, ///< The animation is playing @SINCE_1_1.21
@@ -167,7 +167,7 @@ public:
    *
    * @SINCE_1_2.60
    */
-  enum LoopingMode
+  enum LoopingMode : uint8_t
   {
     RESTART,     ///< When the animation arrives at the end in looping mode, the animation restarts from the beginning. @SINCE_1_2.60
     AUTO_REVERSE ///< When the animation arrives at the end in looping mode, the animation reverses direction and runs backwards again. @SINCE_1_2.60
index d245797..8ff52e1 100644 (file)
@@ -27,7 +27,7 @@ namespace Dali
 {
 const uint32_t    CORE_MAJOR_VERSION = 1;
 const uint32_t    CORE_MINOR_VERSION = 9;
-const uint32_t    CORE_MICRO_VERSION = 33;
+const uint32_t    CORE_MICRO_VERSION = 34;
 const char* const CORE_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index b98df2f..d7dc63f 100644 (file)
@@ -74,7 +74,7 @@ public:
   /**
    * @brief PropertySetSignal function prototype for signal handler. Called when a property is set on this object.
    */
-  using PropertySetSignalType = Signal<void(Handle& handle, Property::Index index, Property::Value value)>;
+  using PropertySetSignalType = Signal<void(Handle& handle, Property::Index index, const Property::Value& value)>;
 
 public:
   /**
index 4e9aaaa..7a500c6 100644 (file)
@@ -98,22 +98,16 @@ bool Property::Map::Empty() const
   return mImpl->mStringValueContainer.empty() && mImpl->mIndexValueContainer.empty();
 }
 
-void Property::Map::Insert(const char* key, const Value& value)
+void Property::Map::Insert(std::string key, Value value)
 {
   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
-  mImpl->mStringValueContainer.push_back(std::make_pair(key, value));
+  mImpl->mStringValueContainer.push_back(std::make_pair(std::move(key), std::move(value)));
 }
 
-void Property::Map::Insert(const std::string& key, const Value& value)
+void Property::Map::Insert(Property::Index key, Value value)
 {
   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
-  mImpl->mStringValueContainer.push_back(std::make_pair(key, value));
-}
-
-void Property::Map::Insert(Property::Index key, const Value& value)
-{
-  DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
-  mImpl->mIndexValueContainer.push_back(std::make_pair(key, value));
+  mImpl->mIndexValueContainer.push_back(std::make_pair(key, std::move(value)));
 }
 
 Property::Value& Property::Map::GetValue(SizeType position) const
@@ -194,19 +188,17 @@ KeyValuePair Property::Map::GetKeyValue(SizeType position) const
   }
   else
   {
-    Key          key(mImpl->mIndexValueContainer[position - numStringKeys].first);
-    KeyValuePair keyValue(key, mImpl->mIndexValueContainer[position - numStringKeys].second);
-    return keyValue;
+    return mImpl->mIndexValueContainer[position - numStringKeys];
   }
 }
 
-Property::Value* Property::Map::Find(const char* key) const
+Property::Value* Property::Map::Find(std::string_view key) const
 {
   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
 
   for(auto&& iter : mImpl->mStringValueContainer)
   {
-    if(iter.first == key)
+    if(key == iter.first)
     {
       return &iter.second;
     }
@@ -214,11 +206,6 @@ Property::Value* Property::Map::Find(const char* key) const
   return nullptr; // Not found
 }
 
-Property::Value* Property::Map::Find(const std::string& key) const
-{
-  return Find(key.c_str());
-}
-
 Property::Value* Property::Map::Find(Property::Index key) const
 {
   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
@@ -233,7 +220,7 @@ Property::Value* Property::Map::Find(Property::Index key) const
   return nullptr; // Not found
 }
 
-Property::Value* Property::Map::Find(Property::Index indexKey, const std::string& stringKey) const
+Property::Value* Property::Map::Find(Property::Index indexKey, std::string_view stringKey) const
 {
   Property::Value* valuePtr = Find(indexKey);
   if(!valuePtr)
@@ -243,13 +230,13 @@ Property::Value* Property::Map::Find(Property::Index indexKey, const std::string
   return valuePtr;
 }
 
-Property::Value* Property::Map::Find(const std::string& key, Property::Type type) const
+Property::Value* Property::Map::Find(std::string_view key, Property::Type type) const
 {
   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
 
   for(auto&& iter : mImpl->mStringValueContainer)
   {
-    if((iter.second.GetType() == type) && (iter.first == key))
+    if((iter.second.GetType() == type) && (key == iter.first))
     {
       return &iter.second;
     }
@@ -306,7 +293,7 @@ void Property::Map::Merge(const Property::Map& from)
   }
 }
 
-const Property::Value& Property::Map::operator[](const std::string& key) const
+const Property::Value& Property::Map::operator[](std::string_view key) const
 {
   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
 
@@ -321,7 +308,7 @@ const Property::Value& Property::Map::operator[](const std::string& key) const
   DALI_ASSERT_ALWAYS(!"Invalid Key");
 }
 
-Property::Value& Property::Map::operator[](const std::string& key)
+Property::Value& Property::Map::operator[](std::string_view key)
 {
   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
 
@@ -334,8 +321,8 @@ Property::Value& Property::Map::operator[](const std::string& key)
   }
 
   // Create and return reference to new value
-  mImpl->mStringValueContainer.push_back(std::make_pair(key, Property::Value()));
-  return (mImpl->mStringValueContainer.end() - 1)->second;
+  mImpl->mStringValueContainer.push_back(std::make_pair(std::string(key), Property::Value()));
+  return mImpl->mStringValueContainer.back().second;
 }
 
 const Property::Value& Property::Map::operator[](Property::Index key) const
@@ -367,7 +354,7 @@ Property::Value& Property::Map::operator[](Property::Index key)
 
   // Create and return reference to new value
   mImpl->mIndexValueContainer.push_back(std::make_pair(key, Property::Value()));
-  return (mImpl->mIndexValueContainer.end() - 1)->second;
+  return mImpl->mIndexValueContainer.back().second;
 }
 
 Property::Map& Property::Map::operator=(const Property::Map& other)
index 115a7fa..45431f5 100644 (file)
@@ -22,6 +22,7 @@
 #include <initializer_list>
 #include <sstream>
 #include <string>
+#include <string_view>
 
 // INTERNAL INCLUDES
 #include <dali/public-api/common/dali-common.h>
@@ -109,17 +110,7 @@ public:
    * @param[in] key The key to insert
    * @param[in] value The value to insert
    */
-  void Insert(const char* key, const Value& value);
-
-  /**
-   * @brief Inserts the key-value pair in the Map, with the key type as string.
-   *
-   * Does not check for duplicates.
-   * @SINCE_1_0.0
-   * @param[in] key The key to insert
-   * @param[in] value The value to insert
-   */
-  void Insert(const std::string& key, const Value& value);
+  void Insert(std::string key, Value value);
 
   /**
    * @brief Inserts the key-value pair in the Map, with the key type as index.
@@ -129,7 +120,7 @@ public:
    * @param[in] key The key to insert
    * @param[in] value The value to insert
    */
-  void Insert(Property::Index key, const Value& value);
+  void Insert(Property::Index key, Value value);
 
   /**
    * @brief Inserts the key-value pair in the Map, with the key type as string.
@@ -140,24 +131,9 @@ public:
    * @param value to insert
    * @return a reference to this object
    */
-  inline Property::Map& Add(const char* key, const Value& value)
+  Property::Map& Add(std::string key, Value value)
   {
-    Insert(key, value);
-    return *this;
-  }
-
-  /**
-   * @brief Inserts the key-value pair in the Map, with the key type as string.
-   *
-   * Does not check for duplicates
-   * @SINCE_1_2.5
-   * @param key to insert
-   * @param value to insert
-   * @return a reference to this object
-   */
-  inline Property::Map& Add(const std::string& key, const Value& value)
-  {
-    Insert(key, value);
+    Insert(std::move(key), std::move(value));
     return *this;
   }
 
@@ -170,9 +146,9 @@ public:
    * @param value to insert
    * @return a reference to this object
    */
-  inline Property::Map& Add(Property::Index key, const Value& value)
+  Property::Map& Add(Property::Index key, Value value)
   {
-    Insert(key, value);
+    Insert(key, std::move(value));
     return *this;
   }
 
@@ -243,17 +219,7 @@ public:
    *
    * @return A const pointer to the value if it exists, NULL otherwise
    */
-  Value* Find(const char* key) const;
-
-  /**
-   * @brief Finds the value for the specified key if it exists.
-   *
-   * @SINCE_1_0.0
-   * @param[in] key The key to find
-   *
-   * @return A const pointer to the value if it exists, NULL otherwise
-   */
-  Value* Find(const std::string& key) const;
+  Value* Find(std::string_view key) const;
 
   /**
    * @brief Finds the value for the specified key if it exists.
@@ -276,7 +242,7 @@ public:
    *
    * @return A const pointer to the value if it exists, NULL otherwise
    */
-  Value* Find(Property::Index indexKey, const std::string& stringKey) const;
+  Value* Find(Property::Index indexKey, std::string_view stringKey) const;
 
   /**
    * @brief Finds the value for the specified key if it exists and its type is type.
@@ -287,7 +253,7 @@ public:
    *
    * @return A const pointer to the value if it exists, NULL otherwise
    */
-  Value* Find(const std::string& key, Property::Type type) const;
+  Value* Find(std::string_view key, Property::Type type) const;
 
   /**
    * @brief Finds the value for the specified key if it exists and its type is type.
@@ -326,7 +292,7 @@ public:
    *
    * @note Will assert if invalid-key is given.
    */
-  const Value& operator[](const std::string& key) const;
+  const Value& operator[](std::string_view key) const;
 
   /**
    * @brief Operator to access the element with the specified string key.
@@ -338,7 +304,7 @@ public:
    *
    * @note If an element with the key does not exist, then it is created.
    */
-  Value& operator[](const std::string& key);
+  Value& operator[](std::string_view key);
 
   /**
    * @brief Const operator to access element with the specified index key.
index 18d3582..0e58a69 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2
 Summary:    DALi 3D Engine
-Version:    1.9.33
+Version:    1.9.34
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT