/**
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License
* at:
*
* http://opensource.org/licenses/ecl2.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
*/
package org.opencastproject.composer.layout;
import static org.junit.Assert.assertEquals;
import static org.opencastproject.composer.layout.AnchorOffset.anchorOffset;
import static org.opencastproject.composer.layout.Dimension.dimension;
import static org.opencastproject.composer.layout.LayoutManager.aspectRatio;
import static org.opencastproject.composer.layout.LayoutManager.scaleToFit;
import static org.opencastproject.composer.layout.Offset.offset;
import static org.opencastproject.util.data.Collections.list;
import static org.opencastproject.util.data.Tuple.tuple;
import org.opencastproject.util.JsonObj;
import org.opencastproject.util.data.Tuple;
import org.junit.Test;
import java.util.List;
public class LayoutManagerTest {
private static final double TOLERANCE = 0.01;
private static final double ASPECT_RATIO_16_9 = 16.0 / 9.0;
private static final double ASPECT_RATIO_4_3 = 4.0 / 3.0;
@Test
public void testTwoShapeLayout0() throws Exception {
TwoShapeLayout layout = LayoutManager.twoShapeLayout(
dimension(4000, 2000), // 2:1 canvas
dimension(1000, 500), // 2:1 upper
dimension(1000, 500), // 2:1 lower
new TwoShapeLayouts.TwoShapeLayoutSpec(new HorizontalCoverageLayoutSpec(anchorOffset(Anchors.TOP_LEFT,
Anchors.TOP_LEFT, 0, 0), 0.5), new HorizontalCoverageLayoutSpec(anchorOffset(Anchors.BOTTOM_RIGHT,
Anchors.BOTTOM_RIGHT, 0, 0), 0.5)));
assertEquals(dimension(2000, 1000), layout.getUpper().getDimension());
assertEquals(offset(0, 0), layout.getUpper().getOffset());
assertEquals(dimension(2000, 1000), layout.getLower().getDimension());
assertEquals(offset(2000, 1000), layout.getLower().getOffset());
}
@Test
public void testTwoShapeLayout1() throws Exception {
TwoShapeLayout layout = LayoutManager.twoShapeLayout(
dimension(4000, 2000), // 2:1 canvas
dimension(1000, 500), // 2:1 upper
dimension(1000, 500), // 2:1 lower
new TwoShapeLayouts.TwoShapeLayoutSpec(new HorizontalCoverageLayoutSpec(anchorOffset(Anchors.TOP_LEFT,
Anchors.TOP_LEFT, 0, 0), 0.2), new HorizontalCoverageLayoutSpec(anchorOffset(Anchors.BOTTOM_RIGHT,
Anchors.BOTTOM_RIGHT, 0, 0), 0.5)));
assertEquals(dimension(800, 400), layout.getUpper().getDimension());
assertEquals(offset(0, 0), layout.getUpper().getOffset());
assertEquals(dimension(2000, 1000), layout.getLower().getDimension());
assertEquals(offset(2000, 1000), layout.getLower().getOffset());
}
@Test
public void testTwoShapeLayout2() throws Exception {
TwoShapeLayout layout = LayoutManager.twoShapeLayout(
dimension(4000, 1000), // canvas
dimension(1000, 500), // upper
dimension(1000, 500), // lower
new TwoShapeLayouts.TwoShapeLayoutSpec(
new HorizontalCoverageLayoutSpec(
anchorOffset(Anchors.TOP_LEFT, Anchors.TOP_LEFT, 0, 0), 0.2),
new HorizontalCoverageLayoutSpec(
anchorOffset(Anchors.BOTTOM_RIGHT, Anchors.BOTTOM_RIGHT, 0, 0), 0.5)));
assertEquals(dimension(800, 400), layout.getUpper().getDimension());
assertEquals(offset(0, 0), layout.getUpper().getOffset());
assertEquals(dimension(2000, 1000), layout.getLower().getDimension());
assertEquals(offset(2000, 0), layout.getLower().getOffset());
}
/** This tests ensures that a media is not scaled to exceed the canvas. */
@Test
public void testTwoShapeLayout3() throws Exception {
TwoShapeLayout layout = LayoutManager.twoShapeLayout(
dimension(1920, 1080), // 1.77:1 canvas
dimension(640, 480), // 4:3 upper (1.33:1)
dimension(640, 480), // 4:3 lower
new TwoShapeLayouts.TwoShapeLayoutSpec(
new HorizontalCoverageLayoutSpec(
anchorOffset(Anchors.TOP_LEFT, Anchors.TOP_LEFT, -20, -20), 0.2),
new HorizontalCoverageLayoutSpec(
anchorOffset(Anchors.BOTTOM_RIGHT, Anchors.BOTTOM_RIGHT, -20, -20), 0.8)));
assertEquals("Media must not exceed canvas", dimension(384, 288), layout.getUpper().getDimension());
assertEquals("Media must not exceed canvas", offset(0, 0), layout.getUpper().getOffset());
assertEquals("Media must not exceed canvas", dimension(1440, 1080), layout.getLower().getDimension());
assertEquals("Media must not exceed canvas", offset(460, 0), layout.getLower().getOffset());
}
@Test
public void testTwoShapeLayoutDifferentAspectRatios() throws Exception {
TwoShapeLayout layout = LayoutManager.twoShapeLayout(
dimension(4000, 4000),
dimension(400, 300),
dimension(1000, 500),
new TwoShapeLayouts.TwoShapeLayoutSpec(new HorizontalCoverageLayoutSpec(anchorOffset(Anchors.TOP_LEFT,
Anchors.TOP_LEFT, 50, 50), 0.25), new HorizontalCoverageLayoutSpec(anchorOffset(
Anchors.BOTTOM_RIGHT, Anchors.BOTTOM_RIGHT, -20, -20), 0.8)));
assertEquals(dimension(1000, 750), layout.getUpper().getDimension());
assertEquals(offset(50, 50), layout.getUpper().getOffset());
assertEquals(dimension(3200, 1600), layout.getLower().getDimension());
assertEquals(offset(780, 2380), layout.getLower().getOffset());
}
@Test
public void testTwoShapeLayoutSmallerCanvas() throws Exception {
TwoShapeLayout layout = LayoutManager.twoShapeLayout(
dimension(200, 200),
dimension(400, 600),
dimension(1000, 500),
new TwoShapeLayouts.TwoShapeLayoutSpec(
new HorizontalCoverageLayoutSpec(
anchorOffset(Anchors.TOP_LEFT, Anchors.TOP_LEFT, 5, 5), 1.0),
new HorizontalCoverageLayoutSpec(
anchorOffset(Anchors.BOTTOM_RIGHT, Anchors.BOTTOM_RIGHT, -2, -2), 0.8)));
assertEquals(200, layout.getUpper().getDimension().getHeight());
assertEquals(400.0 / 600.0, aspectRatio(layout.getUpper().getDimension()), TOLERANCE);
assertEquals(offset(5, 5), layout.getUpper().getOffset());
assertEquals(dimension(160, 80), layout.getLower().getDimension());
assertEquals(offset(38, 118), layout.getLower().getOffset());
}
@Test
public void testTwoShapeLayoutCompose4to3And16to9() {
final Dimension canvas16To9 = dimension(1600, 900);
final Dimension upper4To3 = dimension(400, 300);
final Dimension lower16To9 = dimension(960, 540);
final double upperCoverage = 0.3;
final double lowerCoverage = 0.7;
final TwoShapeLayout layout = LayoutManager.twoShapeLayout(
canvas16To9,
upper4To3,
lower16To9,
new TwoShapeLayouts.TwoShapeLayoutSpec(new HorizontalCoverageLayoutSpec(anchorOffset(Anchors.TOP_LEFT,
Anchors.TOP_LEFT, 0, 0), upperCoverage), new HorizontalCoverageLayoutSpec(anchorOffset(
Anchors.BOTTOM_RIGHT, Anchors.BOTTOM_RIGHT, 0, 0), lowerCoverage)));
assertEquals(dimension(1120, 630), layout.getLower().getDimension());
assertEquals(ASPECT_RATIO_16_9, aspectRatio(lower16To9), TOLERANCE);
assertEquals(ASPECT_RATIO_16_9, aspectRatio(layout.getLower().getDimension()), TOLERANCE);
assertEquals(dimension(480, 360), layout.getUpper().getDimension());
assertEquals(ASPECT_RATIO_4_3, aspectRatio(upper4To3), TOLERANCE);
assertEquals(ASPECT_RATIO_4_3, aspectRatio(layout.getUpper().getDimension()), TOLERANCE);
}
@Test
public void testTwoShapeLayoutPreserveAspectRatio() {
final Dimension canvas = dimension(1900, 1080);
final Dimension upper = dimension(1024, 768);
final Dimension lower = dimension(1280, 720);
final double upperCoverage = 0.3;
final double lowerCoverage = 0.7;
final TwoShapeLayout layout = LayoutManager.twoShapeLayout(
canvas,
upper,
lower,
new TwoShapeLayouts.TwoShapeLayoutSpec(new HorizontalCoverageLayoutSpec(anchorOffset(Anchors.TOP_LEFT,
Anchors.TOP_LEFT, 0, 0), upperCoverage), new HorizontalCoverageLayoutSpec(anchorOffset(
Anchors.BOTTOM_RIGHT, Anchors.BOTTOM_RIGHT, 0, 0), lowerCoverage)));
assertEquals(aspectRatio(upper), aspectRatio(layout.getUpper().getDimension()), TOLERANCE);
assertEquals(aspectRatio(lower), aspectRatio(layout.getLower().getDimension()), TOLERANCE);
}
@Test
public void testTwoShapeLayoutPictureInPicture() {
final Dimension canvas = dimension(1900, 1080);
final Dimension upper = dimension(1024, 768);
final Dimension lower = dimension(1280, 720);
final double upperCoverage = 0.2;
final double lowerCoverage = 1.0;
final TwoShapeLayout layout = LayoutManager.twoShapeLayout(
canvas,
upper,
lower,
new TwoShapeLayouts.TwoShapeLayoutSpec(new HorizontalCoverageLayoutSpec(anchorOffset(Anchors.TOP_LEFT,
Anchors.TOP_LEFT, 10, 10), upperCoverage), new HorizontalCoverageLayoutSpec(anchorOffset(
Anchors.BOTTOM_RIGHT, Anchors.BOTTOM_RIGHT, 0, 0), lowerCoverage)));
assertEquals(dimension(1900, 1069), layout.getLower().getDimension());
assertEquals(offset(0, 11), layout.getLower().getOffset());
assertEquals(dimension(380, 285), layout.getUpper().getDimension());
assertEquals(offset(10, 10), layout.getUpper().getOffset());
}
@Test
public void testMultiShapeLayoutTwoVideoAndWatermark() {
final Dimension canvas = dimension(1900, 1080);
final Dimension upper = dimension(1024, 768);
final Dimension lower = dimension(1280, 720);
final Dimension watermark = dimension(80, 80);
final double upperCoverage = 0.3;
final double lowerCoverage = 0.7;
final double watermarkCoverage = 0.05;
LayoutManager.multiShapeLayout(
canvas,
list(tuple(lower,
new HorizontalCoverageLayoutSpec(anchorOffset(Anchors.BOTTOM_RIGHT, Anchors.BOTTOM_RIGHT, 0, 0),
lowerCoverage)),
tuple(upper, new HorizontalCoverageLayoutSpec(
anchorOffset(Anchors.TOP_LEFT, Anchors.TOP_LEFT, 0, 0), upperCoverage)),
tuple(watermark,
new HorizontalCoverageLayoutSpec(
anchorOffset(Anchors.TOP_RIGHT, Anchors.TOP_RIGHT, 20, 20), watermarkCoverage))));
// todo
}
@Test
public void testScaleToFit() {
assertEquals(dimension(100, 100), scaleToFit(dimension(100, 100), dimension(10, 10)));
assertEquals(dimension(50, 100), scaleToFit(dimension(100, 100), dimension(10, 20)));
assertEquals(dimension(100, 50), scaleToFit(dimension(100, 100), dimension(20, 10)));
assertEquals(dimension(100, 1), scaleToFit(dimension(100, 500), dimension(1000, 10)));
}
/** SWITCHP-337 */
@Test
public void testWatermarkLayout() {
final List<Tuple<Offset, String>> fixtures = list(
// top left
tuple(offset(20, 20), "{\"anchorOffset\":{\"referring\":{\"left\":0.0,\"top\":0.0},\"offset\":{\"y\":20,\"x\":20},\"reference\":{\"left\":0.0,\"top\":0.0}}}"),
// top right
tuple(offset(1340, 20), "{\"anchorOffset\":{\"referring\":{\"left\":1.0,\"top\":0.0},\"offset\":{\"y\":20,\"x\":-20},\"reference\":{\"left\":1.0,\"top\":0.0}}}"),
// bottom left
tuple(offset(20, 340), "{\"anchorOffset\":{\"referring\":{\"left\":0.0,\"top\":1.0},\"offset\":{\"y\":-20,\"x\":20},\"reference\":{\"left\":0.0,\"top\":1.0}}}"),
// bottom right
tuple(offset(1340, 340), "{\"anchorOffset\":{\"referring\":{\"left\":1.0,\"top\":1.0},\"offset\":{\"y\":-20,\"x\":-20},\"reference\":{\"left\":1.0,\"top\":1.0}}}"));
for (final Tuple<Offset, String> fixture : fixtures) {
final AbsolutePositionLayoutSpec spec = Serializer.absolutePositionLayoutSpec(JsonObj.jsonObj(fixture.getB()));
final MultiShapeLayout layout = LayoutManager.absoluteMultiShapeLayout(
Dimension.dimension(1900, 1080),
list(tuple(Dimension.dimension(540, 720), spec)));
assertEquals(1, layout.getShapes().size());
assertEquals(fixture.getA(), layout.getShapes().get(0).getOffset());
}
}
}