1 /*
   2  * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.scenario.animation.shared;
  27 
  28 import com.sun.javafx.animation.TickCalculation;
  29 import static org.junit.Assert.assertEquals;
  30 import static org.junit.Assert.assertNotSame;
  31 import static org.junit.Assert.assertSame;
  32 import static org.junit.Assert.assertTrue;
  33 import javafx.animation.KeyFrame;
  34 import javafx.animation.KeyValue;
  35 import javafx.beans.property.IntegerProperty;
  36 import javafx.beans.property.SimpleIntegerProperty;
  37 import javafx.util.Duration;
  38 
  39 import org.junit.Test;
  40 
  41 public class GeneralClipInterpolatorTest {
  42         
  43         @Test
  44         public void testSetKeyFrame() {
  45         final KeyFrame kf1 = new KeyFrame(Duration.ZERO);
  46         final KeyFrame kf2 = new KeyFrame(Duration.millis(1000));
  47         final KeyFrame kf3 = new KeyFrame(Duration.millis(2000));
  48         final GeneralClipInterpolator gci = new GeneralClipInterpolator(new KeyFrame[] {kf1, kf2, kf3}, new long[] {0, 6000, 6000});
  49         
  50         assertSame   (gci, gci.setKeyFrames(new KeyFrame[]{kf1, kf2, kf3}, new long[] {0, 6000, 6000}));
  51         assertNotSame(gci, gci.setKeyFrames(new KeyFrame[]{kf1, kf2     }, new long[] {0, 6000      }));
  52         assertNotSame(gci, gci.setKeyFrames(new KeyFrame[]{kf1,      kf3}, new long[] {0,       6000}));
  53         assertSame   (gci, gci.setKeyFrames(new KeyFrame[]{kf1          }, new long[] {0            }));
  54         assertSame   (gci, gci.setKeyFrames(new KeyFrame[]{     kf2, kf3}, new long[] {   6000, 6000}));
  55         assertNotSame(gci, gci.setKeyFrames(new KeyFrame[]{     kf2     }, new long[] {   6000      }));
  56         assertNotSame(gci, gci.setKeyFrames(new KeyFrame[]{          kf3}, new long[] {         6000}));
  57         assertSame   (gci, gci.setKeyFrames(new KeyFrame[]{             }, new long[] {             }));
  58         }
  59         
  60         @Test
  61         public void test_OneKeyFrameOnly() {
  62                 // main purpose of this test is to ensure we do not throw exceptions
  63                 final KeyFrame kf1 = new KeyFrame(Duration.ZERO);
  64                 final KeyFrame kf2 = new KeyFrame(Duration.ZERO);
  65                 
  66         // one key frame
  67         final GeneralClipInterpolator gci1 = new GeneralClipInterpolator (new KeyFrame[] {kf1}, new long[] {0});
  68         gci1.validate(true);
  69         gci1.validate(true);
  70         gci1.setKeyFrames(new KeyFrame[]{kf2}, new long[] {6000});
  71         gci1.validate(true);
  72         gci1.setKeyFrames(new KeyFrame[]{}, new long[] {});
  73         gci1.validate(true);
  74         
  75         // no key frames
  76         final GeneralClipInterpolator gci2 = new GeneralClipInterpolator (new KeyFrame[] {}, new long[] {});
  77         gci2.validate(true);
  78         gci2.validate(true);
  79         gci2.setKeyFrames(new KeyFrame[]{kf1}, new long[] {0});
  80         gci2.validate(true);
  81     }
  82 
  83     @Test
  84     public void test_NoKeyValues() {
  85         final KeyFrame start1 = new KeyFrame(Duration.ZERO);
  86         final KeyFrame start2 = new KeyFrame(Duration.ZERO);
  87         final KeyFrame end1 = new KeyFrame(Duration.millis(1000));
  88         final KeyFrame end2a = new KeyFrame(Duration.millis(2000));
  89         final KeyFrame end2b = new KeyFrame(Duration.millis(3000));
  90         
  91         // four key frames
  92         final GeneralClipInterpolator gci1 = new GeneralClipInterpolator (new KeyFrame[] {start1, start2, end1, end2a}, new long[] {0, 0, 6000, 12000});
  93         gci1.validate(true);
  94         gci1.interpolate(TickCalculation.fromMillis(300));
  95         gci1.interpolate(TickCalculation.fromMillis(1300));
  96         
  97         gci1.validate(true);
  98         gci1.interpolate(TickCalculation.fromMillis(800));
  99         gci1.interpolate(TickCalculation.fromMillis(1800));
 100         
 101         gci1.setKeyFrames(new KeyFrame[]{start1, start2, end1, end2b}, new long[] {0, 0, 6000, 18000});
 102         gci1.interpolate(TickCalculation.fromMillis(400));
 103         gci1.interpolate(TickCalculation.fromMillis(1400));
 104         
 105         gci1.validate(true);
 106         gci1.interpolate(TickCalculation.fromMillis(600));
 107         gci1.interpolate(TickCalculation.fromMillis(1600));
 108         
 109         // two key frames
 110         final GeneralClipInterpolator gci2 = new GeneralClipInterpolator (new KeyFrame[] {end1, end2a}, new long[] {6000, 12000});
 111         gci2.validate(true);
 112         gci2.interpolate(TickCalculation.fromMillis(300));
 113         gci2.interpolate(TickCalculation.fromMillis(1300));
 114         
 115         gci2.validate(true);
 116         gci2.interpolate(TickCalculation.fromMillis(800));
 117         gci2.interpolate(TickCalculation.fromMillis(1800));
 118         
 119         gci2.setKeyFrames(new KeyFrame[]{end1, end2b}, new long[] {6000, 18000});
 120         gci2.interpolate(TickCalculation.fromMillis(400));
 121         gci2.interpolate(TickCalculation.fromMillis(1400));
 122         
 123         gci2.validate(true);
 124         gci2.interpolate(TickCalculation.fromMillis(600));
 125         gci2.interpolate(TickCalculation.fromMillis(1600));
 126     }
 127 
 128     @Test
 129     public void test_ThreeKeyFrames_OneKeyValue() {
 130         final IntegerProperty v = new SimpleIntegerProperty();
 131         final KeyFrame start1 = new KeyFrame(Duration.ZERO);
 132         final KeyFrame start2 = new KeyFrame(Duration.ZERO, new KeyValue(v, 30));
 133         final KeyFrame mid1 = new KeyFrame(Duration.millis(1000), new KeyValue(v, 40));
 134         final KeyFrame end1 = new KeyFrame(Duration.millis(2000), new KeyValue(v, 60));
 135         final KeyFrame end2 = new KeyFrame(Duration.millis(4000), new KeyValue(v, 70));
 136         
 137         final GeneralClipInterpolator gci1 = new GeneralClipInterpolator (new KeyFrame[] {start1, start2, mid1, end1}, new long[] {0, 0, 6000, 12000});
 138         v.set(0);
 139         gci1.validate(true);
 140         gci1.interpolate(TickCalculation.fromMillis(0));
 141         assertEquals(30, v.get());
 142         gci1.interpolate(TickCalculation.fromMillis(300));
 143         assertEquals(33, v.get());
 144         gci1.interpolate(TickCalculation.fromMillis(1000));
 145         assertEquals(40, v.get());
 146         gci1.interpolate(TickCalculation.fromMillis(1600));
 147         assertEquals(52, v.get());
 148         gci1.interpolate(TickCalculation.fromMillis(2000));
 149         assertEquals(60, v.get());
 150         
 151         // re-validate
 152         v.set(20);
 153         gci1.validate(true);
 154         gci1.interpolate(TickCalculation.fromMillis(0));
 155         assertEquals(30, v.get());
 156         gci1.interpolate(TickCalculation.fromMillis(800));
 157         assertEquals(38, v.get());
 158         gci1.interpolate(TickCalculation.fromMillis(1000));
 159         assertEquals(40, v.get());
 160         gci1.interpolate(TickCalculation.fromMillis(1200));
 161         assertEquals(44, v.get());
 162         gci1.interpolate(TickCalculation.fromMillis(2000));
 163         assertEquals(60, v.get());
 164         
 165         // set new key frames
 166         gci1.setKeyFrames(new KeyFrame[]{start1, start2, mid1, end2}, new long[] {0, 0, 6000, 24000});
 167         v.set(0);
 168         gci1.interpolate(TickCalculation.fromMillis(0));
 169         assertEquals(30, v.get());
 170         gci1.interpolate(TickCalculation.fromMillis(600));
 171         assertEquals(36, v.get());
 172         gci1.interpolate(TickCalculation.fromMillis(1000));
 173         assertEquals(40, v.get());
 174         gci1.interpolate(TickCalculation.fromMillis(1300));
 175         assertEquals(46, v.get());
 176         gci1.interpolate(TickCalculation.fromMillis(2000));
 177         assertEquals(60, v.get());
 178         
 179         // validate new key frames
 180         v.set(0);
 181         gci1.validate(true);
 182         gci1.interpolate(TickCalculation.fromMillis(0));
 183         assertEquals(30, v.get());
 184         gci1.interpolate(TickCalculation.fromMillis(700));
 185         assertEquals(37, v.get());
 186         gci1.interpolate(TickCalculation.fromMillis(1000));
 187         assertEquals(40, v.get());
 188         gci1.interpolate(TickCalculation.fromMillis(1300));
 189         assertEquals(43, v.get());
 190         gci1.interpolate(TickCalculation.fromMillis(4000));
 191         assertEquals(70, v.get());
 192     }
 193 
 194     @Test
 195     public void test_TwoKeyFrames_OneKeyValue() {
 196         final IntegerProperty v = new SimpleIntegerProperty();
 197         final KeyFrame mid1 = new KeyFrame(Duration.millis(1000), new KeyValue(v, 40));
 198         final KeyFrame end1 = new KeyFrame(Duration.millis(2000), new KeyValue(v, 60));
 199         final KeyFrame end2 = new KeyFrame(Duration.millis(4000), new KeyValue(v, 70));
 200 
 201         final GeneralClipInterpolator gci1 = new GeneralClipInterpolator (new KeyFrame[] {mid1, end1}, new long[] {6000, 12000});
 202         v.set(0);
 203         gci1.validate(true);
 204         gci1.interpolate(TickCalculation.fromMillis(0));
 205         assertEquals( 0, v.get());
 206         gci1.interpolate(TickCalculation.fromMillis(300));
 207         assertEquals(12, v.get());
 208         gci1.interpolate(TickCalculation.fromMillis(1000));
 209         assertEquals(40, v.get());
 210         gci1.interpolate(TickCalculation.fromMillis(1600));
 211         assertEquals(52, v.get());
 212         gci1.interpolate(TickCalculation.fromMillis(2000));
 213         assertEquals(60, v.get());
 214         
 215         // re-validate
 216         v.set(20);
 217         gci1.validate(true);
 218         gci1.interpolate(TickCalculation.fromMillis(0));
 219         assertEquals(20, v.get());
 220         gci1.interpolate(TickCalculation.fromMillis(800));
 221         assertEquals(36, v.get());
 222         gci1.interpolate(TickCalculation.fromMillis(1000));
 223         assertEquals(40, v.get());
 224         gci1.interpolate(TickCalculation.fromMillis(1200));
 225         assertEquals(44, v.get());
 226         gci1.interpolate(TickCalculation.fromMillis(2000));
 227         assertEquals(60, v.get());
 228         
 229         // set new key frames
 230         gci1.setKeyFrames(new KeyFrame[]{mid1, end2}, new long[] {6000, 24000});
 231         v.set(0);
 232         gci1.interpolate(TickCalculation.fromMillis(0));
 233         assertEquals(20, v.get());
 234         gci1.interpolate(TickCalculation.fromMillis(600));
 235         assertEquals(32, v.get());
 236         gci1.interpolate(TickCalculation.fromMillis(1000));
 237         assertEquals(40, v.get());
 238         gci1.interpolate(TickCalculation.fromMillis(1300));
 239         assertEquals(46, v.get());
 240         gci1.interpolate(TickCalculation.fromMillis(2000));
 241         assertEquals(60, v.get());
 242         
 243         // validate new key frames
 244         v.set(0);
 245         gci1.validate(true);
 246         gci1.interpolate(TickCalculation.fromMillis(0));
 247         assertEquals( 0, v.get());
 248         gci1.interpolate(TickCalculation.fromMillis(700));
 249         assertEquals(28, v.get());
 250         gci1.interpolate(TickCalculation.fromMillis(1000));
 251         assertEquals(40, v.get());
 252         gci1.interpolate(TickCalculation.fromMillis(1300));
 253         assertEquals(43, v.get());
 254         gci1.interpolate(TickCalculation.fromMillis(4000));
 255         assertEquals(70, v.get());
 256     }
 257 
 258     @Test
 259     public void test_ThreeKeyFrames_ThreeKeyValues() {
 260         final IntegerProperty v1 = new SimpleIntegerProperty();
 261         final IntegerProperty v2 = new SimpleIntegerProperty();
 262         final IntegerProperty v3 = new SimpleIntegerProperty();
 263         final IntegerProperty v4 = new SimpleIntegerProperty();
 264         final KeyFrame start1 = new KeyFrame(Duration.ZERO, new KeyValue(v3, 230), new KeyValue(v4, 330));
 265         final KeyFrame start2 = new KeyFrame(Duration.ZERO, new KeyValue(v2, 130));
 266         final KeyFrame mid1 = new KeyFrame(Duration.millis(1000), new KeyValue(v1, 40), new KeyValue(v2, 140), new KeyValue(v3, 240));
 267         final KeyFrame end1 = new KeyFrame(Duration.millis(2000), new KeyValue(v1, 60), new KeyValue(v2, 160));
 268         final KeyFrame end2 = new KeyFrame(Duration.millis(4000), new KeyValue(v1, 70), new KeyValue(v2, 170));
 269         
 270         final GeneralClipInterpolator gci1 = new GeneralClipInterpolator (new KeyFrame[] {start1, start2, mid1, end1}, new long[] {0, 0, 6000, 12000});
 271         v1.set(  0);
 272         v2.set(100);
 273         v3.set(200);
 274         v4.set(300);
 275         gci1.validate(true);
 276         gci1.interpolate(TickCalculation.fromMillis(0));
 277         assertEquals(  0, v1.get());
 278         assertEquals(130, v2.get());
 279         assertEquals(230, v3.get());
 280         assertEquals(300, v4.get());
 281         gci1.interpolate(TickCalculation.fromMillis(300));
 282         assertEquals( 12, v1.get());
 283         assertEquals(133, v2.get());
 284         assertEquals(233, v3.get());
 285         assertEquals(300, v4.get());
 286         gci1.interpolate(TickCalculation.fromMillis(1000));
 287         assertEquals( 40, v1.get());
 288         assertEquals(140, v2.get());
 289         assertEquals(240, v3.get());
 290         assertEquals(300, v4.get());
 291         gci1.interpolate(TickCalculation.fromMillis(1600));
 292         assertEquals( 52, v1.get());
 293         assertEquals(152, v2.get());
 294         assertEquals(240, v3.get());
 295         assertEquals(300, v4.get());
 296         gci1.interpolate(TickCalculation.fromMillis(2000));
 297         assertEquals( 60, v1.get());
 298         assertEquals(160, v2.get());
 299         assertEquals(240, v3.get());
 300         assertEquals(300, v4.get());
 301         
 302         // re-validate
 303         v1.set( 20);
 304         v2.set(120);
 305         v3.set(220);
 306         v4.set(320);
 307         gci1.validate(true);
 308         gci1.interpolate(TickCalculation.fromMillis(0));
 309         assertEquals( 20, v1.get());
 310         assertEquals(130, v2.get());
 311         assertEquals(230, v3.get());
 312         assertEquals(320, v4.get());
 313         gci1.interpolate(TickCalculation.fromMillis(800));
 314         assertEquals( 36, v1.get());
 315         assertEquals(138, v2.get());
 316         assertEquals(238, v3.get());
 317         assertEquals(320, v4.get());
 318         gci1.interpolate(TickCalculation.fromMillis(1000));
 319         assertEquals( 40, v1.get());
 320         assertEquals(140, v2.get());
 321         assertEquals(240, v3.get());
 322         assertEquals(320, v4.get());
 323         gci1.interpolate(TickCalculation.fromMillis(1200));
 324         assertEquals( 44, v1.get());
 325         assertEquals(144, v2.get());
 326         assertEquals(240, v3.get());
 327         assertEquals(320, v4.get());
 328         gci1.interpolate(TickCalculation.fromMillis(2000));
 329         assertEquals( 60, v1.get());
 330         assertEquals(160, v2.get());
 331         assertEquals(240, v3.get());
 332         assertEquals(320, v4.get());
 333         
 334         // change key frames
 335         gci1.setKeyFrames(new KeyFrame[]{start1, start2, mid1, end2}, new long[] {0, 0, 6000, 24000});
 336         v1.set(  0);
 337         v2.set(100);
 338         v3.set(200);
 339         v4.set(300);
 340         gci1.interpolate(TickCalculation.fromMillis(0));
 341         assertEquals( 20, v1.get());
 342         assertEquals(130, v2.get());
 343         assertEquals(230, v3.get());
 344         assertEquals(300, v4.get());
 345         gci1.interpolate(TickCalculation.fromMillis(300));
 346         assertEquals( 26, v1.get());
 347         assertEquals(133, v2.get());
 348         assertEquals(233, v3.get());
 349         assertEquals(300, v4.get());
 350         gci1.interpolate(TickCalculation.fromMillis(1000));
 351         assertEquals( 40, v1.get());
 352         assertEquals(140, v2.get());
 353         assertEquals(240, v3.get());
 354         assertEquals(300, v4.get());
 355         gci1.interpolate(TickCalculation.fromMillis(1300));
 356         assertEquals( 46, v1.get());
 357         assertEquals(146, v2.get());
 358         assertEquals(240, v3.get());
 359         assertEquals(300, v4.get());
 360         gci1.interpolate(TickCalculation.fromMillis(2000));
 361         assertEquals( 60, v1.get());
 362         assertEquals(160, v2.get());
 363         assertEquals(240, v3.get());
 364         assertEquals(300, v4.get());
 365         
 366         // validate new key frames
 367         v1.set( 20);
 368         v2.set(120);
 369         v3.set(220);
 370         v4.set(320);
 371         gci1.validate(true);
 372         gci1.interpolate(TickCalculation.fromMillis(0));
 373         assertEquals( 20, v1.get());
 374         assertEquals(130, v2.get());
 375         assertEquals(230, v3.get());
 376         assertEquals(320, v4.get());
 377         gci1.interpolate(TickCalculation.fromMillis(600));
 378         assertEquals( 32, v1.get());
 379         assertEquals(136, v2.get());
 380         assertEquals(236, v3.get());
 381         assertEquals(320, v4.get());
 382         gci1.interpolate(TickCalculation.fromMillis(1000));
 383         assertEquals( 40, v1.get());
 384         assertEquals(140, v2.get());
 385         assertEquals(240, v3.get());
 386         assertEquals(320, v4.get());
 387         gci1.interpolate(TickCalculation.fromMillis(1300));
 388         assertEquals( 43, v1.get());
 389         assertEquals(143, v2.get());
 390         assertEquals(240, v3.get());
 391         assertEquals(320, v4.get());
 392         gci1.interpolate(TickCalculation.fromMillis(4000));
 393         assertEquals( 70, v1.get());
 394         assertEquals(170, v2.get());
 395         assertEquals(240, v3.get());
 396         assertEquals(320, v4.get());
 397     }
 398 
 399     @Test
 400     public void test_TwoKeyFrames_ThreeKeyValues() {
 401         final IntegerProperty v1 = new SimpleIntegerProperty();
 402         final IntegerProperty v2 = new SimpleIntegerProperty();
 403         final IntegerProperty v3 = new SimpleIntegerProperty();
 404         final KeyFrame mid1 = new KeyFrame(Duration.millis(1000), new KeyValue(v1, 40), new KeyValue(v2, 140), new KeyValue(v3, 240));
 405         final KeyFrame end1 = new KeyFrame(Duration.millis(2000), new KeyValue(v1, 60), new KeyValue(v2, 160), new KeyValue(v3, 260));
 406         final KeyFrame end2 = new KeyFrame(Duration.millis(4000), new KeyValue(v1, 70), new KeyValue(v2, 170), new KeyValue(v3, 270));
 407 
 408         final GeneralClipInterpolator gci1 = new GeneralClipInterpolator (new KeyFrame[] {mid1, end1}, new long[] {6000, 12000});
 409         v1.set(  0);
 410         v2.set(100);
 411         v3.set(200);
 412         gci1.validate(true);
 413         gci1.interpolate(TickCalculation.fromMillis(0));
 414         assertEquals(  0, v1.get());
 415         assertEquals(100, v2.get());
 416         assertEquals(200, v3.get());
 417         gci1.interpolate(TickCalculation.fromMillis(300));
 418         assertEquals( 12, v1.get());
 419         assertEquals(112, v2.get());
 420         assertEquals(212, v3.get());
 421         gci1.interpolate(TickCalculation.fromMillis(1000));
 422         assertEquals( 40, v1.get());
 423         assertEquals(140, v2.get());
 424         assertEquals(240, v3.get());
 425         gci1.interpolate(TickCalculation.fromMillis(1600));
 426         assertEquals( 52, v1.get());
 427         assertEquals(152, v2.get());
 428         assertEquals(252, v3.get());
 429         gci1.interpolate(TickCalculation.fromMillis(2000));
 430         assertEquals( 60, v1.get());
 431         assertEquals(160, v2.get());
 432         assertEquals(260, v3.get());
 433         
 434         // re-validate
 435         v1.set( 20);
 436         v2.set(120);
 437         v3.set(220);
 438         gci1.validate(true);
 439         gci1.interpolate(TickCalculation.fromMillis(0));
 440         assertEquals( 20, v1.get());
 441         assertEquals(120, v2.get());
 442         assertEquals(220, v3.get());
 443         gci1.interpolate(TickCalculation.fromMillis(800));
 444         assertEquals( 36, v1.get());
 445         assertEquals(136, v2.get());
 446         assertEquals(236, v3.get());
 447         gci1.interpolate(TickCalculation.fromMillis(1000));
 448         assertEquals( 40, v1.get());
 449         assertEquals(140, v2.get());
 450         assertEquals(240, v3.get());
 451         gci1.interpolate(TickCalculation.fromMillis(1200));
 452         assertEquals( 44, v1.get());
 453         assertEquals(144, v2.get());
 454         assertEquals(244, v3.get());
 455         gci1.interpolate(TickCalculation.fromMillis(2000));
 456         assertEquals( 60, v1.get());
 457         assertEquals(160, v2.get());
 458         assertEquals(260, v3.get());
 459         
 460         // change key frames
 461         gci1.setKeyFrames(new KeyFrame[]{mid1, end2}, new long[] {6000, 24000});
 462         v1.set(  0);
 463         v2.set(100);
 464         v3.set(200);
 465         gci1.interpolate(TickCalculation.fromMillis(0));
 466         assertEquals( 20, v1.get());
 467         assertEquals(120, v2.get());
 468         assertEquals(220, v3.get());
 469         gci1.interpolate(TickCalculation.fromMillis(300));
 470         assertEquals( 26, v1.get());
 471         assertEquals(126, v2.get());
 472         assertEquals(226, v3.get());
 473         gci1.interpolate(TickCalculation.fromMillis(1000));
 474         assertEquals( 40, v1.get());
 475         assertEquals(140, v2.get());
 476         assertEquals(240, v3.get());
 477         gci1.interpolate(TickCalculation.fromMillis(1300));
 478         assertEquals( 46, v1.get());
 479         assertEquals(146, v2.get());
 480         assertEquals(246, v3.get());
 481         gci1.interpolate(TickCalculation.fromMillis(2000));
 482         assertEquals( 60, v1.get());
 483         assertEquals(160, v2.get());
 484         assertEquals(260, v3.get());
 485         
 486         // validate new key frames
 487         v1.set( 20);
 488         v2.set(120);
 489         v3.set(220);
 490         gci1.validate(true);
 491         gci1.interpolate(TickCalculation.fromMillis(0));
 492         assertEquals( 20, v1.get());
 493         assertEquals(120, v2.get());
 494         assertEquals(220, v3.get());
 495         gci1.interpolate(TickCalculation.fromMillis(600));
 496         assertEquals( 32, v1.get());
 497         assertEquals(132, v2.get());
 498         assertEquals(232, v3.get());
 499         gci1.interpolate(TickCalculation.fromMillis(1000));
 500         assertEquals( 40, v1.get());
 501         assertEquals(140, v2.get());
 502         assertEquals(240, v3.get());
 503         gci1.interpolate(TickCalculation.fromMillis(1300));
 504         assertEquals( 43, v1.get());
 505         assertEquals(143, v2.get());
 506         assertEquals(243, v3.get());
 507         gci1.interpolate(TickCalculation.fromMillis(4000));
 508         assertEquals( 70, v1.get());
 509         assertEquals(170, v2.get());
 510         assertEquals(270, v3.get());
 511     }
 512 
 513 
 514     @Test
 515     public void test_DuplicateKeyValue() {
 516         final IntegerProperty v1 = new SimpleIntegerProperty();
 517         final IntegerProperty v2 = new SimpleIntegerProperty();
 518         final KeyFrame start1 = new KeyFrame(Duration.ZERO, new KeyValue(v1, 30), new KeyValue(v2, 0));
 519         final KeyFrame start2 = new KeyFrame(Duration.ZERO, new KeyValue(v1, 30), new KeyValue(v1, -30), new KeyValue(v2, 0));
 520         final KeyFrame mid1 = new KeyFrame(Duration.millis(1000), new KeyValue(v1, 40), new KeyValue(v2, 100));
 521         final KeyFrame mid2 = new KeyFrame(Duration.millis(1000), new KeyValue(v1, 40), new KeyValue(v1, -40), new KeyValue(v2, 100));
 522         final KeyFrame end1 = new KeyFrame(Duration.millis(2000), new KeyValue(v1, 60), new KeyValue(v2, 0));
 523         final KeyFrame end2 = new KeyFrame(Duration.millis(2000), new KeyValue(v1, 60), new KeyValue(v1, -60), new KeyValue(v2, 0));
 524 
 525         // single value in start, single value in mid, duplicate value in end
 526         final GeneralClipInterpolator gci1 = new GeneralClipInterpolator (new KeyFrame[] {start1, mid1, end2}, new long[] {0, 6000, 12000});
 527         v1.set(0);
 528         v2.set(0);
 529         gci1.validate(true);
 530         gci1.interpolate(TickCalculation.fromMillis(0));
 531         assertEquals(30, v1.get());
 532         assertEquals(0, v2.get());
 533         gci1.interpolate(TickCalculation.fromMillis(300));
 534         assertEquals(33, v1.get());
 535         assertEquals(30, v2.get());
 536         gci1.interpolate(TickCalculation.fromMillis(1000));
 537         assertEquals(40, v1.get());
 538         assertEquals(100, v2.get());
 539         gci1.interpolate(TickCalculation.fromMillis(1600));
 540         assertTrue("v1.get(): " + v1.get(), (52 == v1.get()) || (-20 == v1.get()));
 541         assertEquals(40, v2.get());
 542         gci1.interpolate(TickCalculation.fromMillis(2000));
 543         assertTrue("v1.get(): " + v1.get(), (60 == v1.get()) || (-60 == v1.get()));
 544         assertEquals(0, v2.get());
 545 
 546         // single value in start, duplicate value in mid, single value in end
 547         final GeneralClipInterpolator gci2 = new GeneralClipInterpolator (new KeyFrame[] {start1, mid2, end1}, new long[] {0, 6000, 12000});
 548         v1.set(0);
 549         v2.set(0);
 550         gci2.validate(true);
 551         gci2.interpolate(TickCalculation.fromMillis(0));
 552         assertEquals(30, v1.get());
 553         assertEquals(0, v2.get());
 554         gci2.interpolate(TickCalculation.fromMillis(300));
 555         assertTrue("v1.get(): " + v1.get(), (33 == v1.get()) || (9 == v1.get()));
 556         assertEquals(30, v2.get());
 557         gci2.interpolate(TickCalculation.fromMillis(1000));
 558         assertTrue("v1.get(): " + v1.get(), (40 == v1.get()) || (-40 == v1.get()));
 559         assertEquals(100, v2.get());
 560         gci2.interpolate(TickCalculation.fromMillis(1600));
 561         assertTrue("v1.get(): " + v1.get(), (52 == v1.get()) || (20 == v1.get()));
 562         assertEquals(40, v2.get());
 563         gci2.interpolate(TickCalculation.fromMillis(2000));
 564         assertEquals(60, v1.get());
 565         assertEquals(0, v2.get());
 566 
 567         // duplicate value in start, single value in mid, single value in end
 568         final GeneralClipInterpolator gci3 = new GeneralClipInterpolator (new KeyFrame[] {start2, mid1, end1}, new long[] {0, 6000, 12000});
 569         v1.set(0);
 570         v2.set(0);
 571         gci3.validate(true);
 572         gci3.interpolate(TickCalculation.fromMillis(0));
 573         assertTrue("v1.get(): " + v1.get(), (30 == v1.get()) || (-30 == v1.get()));
 574         assertEquals(0, v2.get());
 575         gci3.interpolate(TickCalculation.fromMillis(300));
 576         assertTrue("v1.get(): " + v1.get(), (33 == v1.get()) || (-9 == v1.get()));
 577         assertEquals(30, v2.get());
 578         gci3.interpolate(TickCalculation.fromMillis(1000));
 579         assertEquals(40, v1.get());
 580         assertEquals(100, v2.get());
 581         gci3.interpolate(TickCalculation.fromMillis(1600));
 582         assertEquals(52, v1.get());
 583         assertEquals(40, v2.get());
 584         gci3.interpolate(TickCalculation.fromMillis(2000));
 585         assertEquals(60, v1.get());
 586         assertEquals(0, v2.get());
 587 
 588         // duplicate value in start, duplicate value in mid, single value in end
 589         final GeneralClipInterpolator gci4 = new GeneralClipInterpolator (new KeyFrame[] {start2, mid2, end1}, new long[] {0, 6000, 12000});
 590         v1.set(0);
 591         v2.set(0);
 592         gci4.validate(true);
 593         gci4.interpolate(TickCalculation.fromMillis(0));
 594         assertTrue("v1.get(): " + v1.get(), (30 == v1.get()) || (-30 == v1.get()));
 595         assertEquals(0, v2.get());
 596         gci4.interpolate(TickCalculation.fromMillis(300));
 597         assertTrue("v1.get(): " + v1.get(), (33 == v1.get()) || (9 == v1.get()) || (-9 == v1.get()) || (-33 == v1.get()));
 598         assertEquals(30, v2.get());
 599         gci4.interpolate(TickCalculation.fromMillis(1000));
 600         assertTrue("v1.get(): " + v1.get(), (40 == v1.get()) || (-40 == v1.get()));
 601         assertEquals(100, v2.get());
 602         gci4.interpolate(TickCalculation.fromMillis(1600));
 603         assertTrue("v1.get(): " + v1.get(), (52 == v1.get()) || (20 == v1.get()));
 604         assertEquals(40, v2.get());
 605         gci4.interpolate(TickCalculation.fromMillis(2000));
 606         assertEquals(60, v1.get());
 607         assertEquals(0, v2.get());
 608 
 609         // duplicate value in start, single value in mid, duplicate value in end
 610         final GeneralClipInterpolator gci5 = new GeneralClipInterpolator (new KeyFrame[] {start2, mid1, end2}, new long[] {0, 6000, 12000});
 611         v1.set(0);
 612         v2.set(0);
 613         gci5.validate(true);
 614         gci5.interpolate(TickCalculation.fromMillis(0));
 615         assertTrue("v1.get(): " + v1.get(), (30 == v1.get()) || (-30 == v1.get()));
 616         assertEquals(0, v2.get());
 617         gci5.interpolate(TickCalculation.fromMillis(300));
 618         assertTrue("v1.get(): " + v1.get(), (33 == v1.get()) || (-9 == v1.get()));
 619         assertEquals(30, v2.get());
 620         gci5.interpolate(TickCalculation.fromMillis(1000));
 621         assertEquals(40, v1.get());
 622         assertEquals(100, v2.get());
 623         gci5.interpolate(TickCalculation.fromMillis(1600));
 624         assertTrue("v1.get(): " + v1.get(), (52 == v1.get()) || (-20 == v1.get()));
 625         assertEquals(40, v2.get());
 626         gci5.interpolate(TickCalculation.fromMillis(2000));
 627         assertTrue("v1.get(): " + v1.get(), (60 == v1.get()) || (-60 == v1.get()));
 628         assertEquals(0, v2.get());
 629 
 630         // single value in start, duplicate value in mid, duplicate value in end
 631         final GeneralClipInterpolator gci6 = new GeneralClipInterpolator (new KeyFrame[] {start1, mid2, end2}, new long[] {0, 6000, 12000});
 632         v1.set(0);
 633         v2.set(0);
 634         gci6.validate(true);
 635         gci6.interpolate(TickCalculation.fromMillis(0));
 636         assertEquals(30, v1.get());
 637         assertEquals(0, v2.get());
 638         gci6.interpolate(TickCalculation.fromMillis(300));
 639         assertTrue("v1.get(): " + v1.get(), (33 == v1.get()) || (9 == v1.get()));
 640         assertEquals(30, v2.get());
 641         gci6.interpolate(TickCalculation.fromMillis(1000));
 642         assertTrue("v1.get(): " + v1.get(), (40 == v1.get()) || (-40 == v1.get()));
 643         assertEquals(100, v2.get());
 644         gci6.interpolate(TickCalculation.fromMillis(1600));
 645         assertTrue("v1.get(): " + v1.get(), (52 == v1.get()) || (-20 == v1.get()) || (20 == v1.get()) || (-52 == v1.get()));
 646         assertEquals(40, v2.get());
 647         gci6.interpolate(TickCalculation.fromMillis(2000));
 648         assertTrue("v1.get(): " + v1.get(), (60 == v1.get()) || (-60 == v1.get()));
 649         assertEquals(0, v2.get());
 650 
 651         // duplicate value in start, duplicate value in mid, duplicate value in end
 652         final GeneralClipInterpolator gci7 = new GeneralClipInterpolator (new KeyFrame[] {start2, mid2, end2}, new long[] {0, 6000, 12000});
 653         v1.set(0);
 654         v2.set(0);
 655         gci7.validate(true);
 656         gci7.interpolate(TickCalculation.fromMillis(0));
 657         assertTrue("v1.get(): " + v1.get(), (30 == v1.get()) || (-30 == v1.get()));
 658         assertEquals(0, v2.get());
 659         gci7.interpolate(TickCalculation.fromMillis(300));
 660         assertTrue("v1.get(): " + v1.get(), (33 == v1.get()) || (9 == v1.get()) || (-9 == v1.get()) || (-33 == v1.get()));
 661         assertEquals(30, v2.get());
 662         gci7.interpolate(TickCalculation.fromMillis(1000));
 663         assertTrue("v1.get(): " + v1.get(), (40 == v1.get()) || (-40 == v1.get()));
 664         assertEquals(100, v2.get());
 665         gci7.interpolate(TickCalculation.fromMillis(1600));
 666         assertTrue("v1.get(): " + v1.get(), (52 == v1.get()) || (-20 == v1.get()) || (20 == v1.get()) || (-52 == v1.get()));
 667         assertEquals(40, v2.get());
 668         gci7.interpolate(TickCalculation.fromMillis(2000));
 669         assertTrue("v1.get(): " + v1.get(), (60 == v1.get()) || (-60 == v1.get()));
 670         assertEquals(0, v2.get());
 671 
 672         // no value in start, single value in mid, duplicate value in end
 673         final GeneralClipInterpolator gci8 = new GeneralClipInterpolator (new KeyFrame[] {mid1, end2}, new long[] {6000, 12000});
 674         v1.set(0);
 675         v2.set(0);
 676         gci8.validate(true);
 677         gci8.interpolate(TickCalculation.fromMillis(0));
 678         assertEquals(0, v1.get());
 679         assertEquals(0, v2.get());
 680         gci8.interpolate(TickCalculation.fromMillis(400));
 681         assertEquals(16, v1.get());
 682         assertEquals(40, v2.get());
 683         gci8.interpolate(TickCalculation.fromMillis(1000));
 684         assertEquals(40, v1.get());
 685         assertEquals(100, v2.get());
 686         gci8.interpolate(TickCalculation.fromMillis(1600));
 687         assertTrue("v1.get(): " + v1.get(), (52 == v1.get()) || (-20 == v1.get()));
 688         assertEquals(40, v2.get());
 689         gci8.interpolate(TickCalculation.fromMillis(2000));
 690         assertTrue("v1.get(): " + v1.get(), (60 == v1.get()) || (-60 == v1.get()));
 691         assertEquals(0, v2.get());
 692 
 693         // no value in start, duplicate value in mid, single value in end
 694         final GeneralClipInterpolator gci9 = new GeneralClipInterpolator (new KeyFrame[] {mid2, end1}, new long[] {6000, 12000});
 695         v1.set(0);
 696         v2.set(0);
 697         gci9.validate(true);
 698         gci9.interpolate(TickCalculation.fromMillis(0));
 699         assertEquals(0, v1.get());
 700         assertEquals(0, v2.get());
 701         gci9.interpolate(TickCalculation.fromMillis(400));
 702         assertTrue("v1.get(): " + v1.get(), (16 == v1.get()) || (-16 == v1.get()));
 703         assertEquals(40, v2.get());
 704         gci9.interpolate(TickCalculation.fromMillis(1000));
 705         assertTrue("v1.get(): " + v1.get(), (40 == v1.get()) || (-40 == v1.get()));
 706         assertEquals(100, v2.get());
 707         gci9.interpolate(TickCalculation.fromMillis(1600));
 708         assertTrue("v1.get(): " + v1.get(), (52 == v1.get()) || (20 == v1.get()));
 709         assertEquals(40, v2.get());
 710         gci9.interpolate(TickCalculation.fromMillis(2000));
 711         assertEquals(60, v1.get());
 712         assertEquals(0, v2.get());
 713 
 714         // no value in start, duplicate value in mid, duplicate value in end
 715         final GeneralClipInterpolator gci10 = new GeneralClipInterpolator (new KeyFrame[] {mid2, end2}, new long[] {6000, 12000});
 716         v1.set(0);
 717         v2.set(0);
 718         gci10.validate(true);
 719         gci10.interpolate(TickCalculation.fromMillis(0));
 720         assertEquals(0, v1.get());
 721         assertEquals(0, v2.get());
 722         gci10.interpolate(TickCalculation.fromMillis(400));
 723         assertTrue("v1.get(): " + v1.get(), (16 == v1.get()) || (-16 == v1.get()));
 724         assertEquals(40, v2.get());
 725         gci10.interpolate(TickCalculation.fromMillis(1000));
 726         assertTrue("v1.get(): " + v1.get(), (40 == v1.get()) || (-40 == v1.get()));
 727         assertEquals(100, v2.get());
 728         gci10.interpolate(TickCalculation.fromMillis(1600));
 729         assertTrue("v1.get(): " + v1.get(), (52 == v1.get()) || (-20 == v1.get()) || (20 == v1.get()) || (-52 == v1.get()));
 730         assertEquals(40, v2.get());
 731         gci10.interpolate(TickCalculation.fromMillis(2000));
 732         assertTrue("v1.get(): " + v1.get(), (60 == v1.get()) || (-60 == v1.get()));
 733         assertEquals(0, v2.get());
 734     }
 735 }