1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.opencastproject.composer.layout;
23
24 import org.opencastproject.util.data.Tuple;
25
26 import java.util.List;
27
28 public final class LayoutManager {
29 private LayoutManager() {
30 }
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 public static TwoShapeLayout twoShapeLayout(Dimension canvas,
46 Dimension upper,
47 Dimension lower,
48 TwoShapeLayouts.TwoShapeLayoutSpec spec) {
49 return new TwoShapeLayout(canvas,
50 calcLayout(canvas, upper, spec.getUpper()),
51 calcLayout(canvas, lower, spec.getLower()));
52 }
53
54 private static Layout calcLayout(Dimension canvas,
55 Dimension shape,
56 HorizontalCoverageLayoutSpec posSpec) {
57 final Dimension slice = new Dimension(limitMin(canvas.getWidth() * posSpec.getHorizontalCoverage(), 0),
58 canvas.getHeight());
59 final Dimension scaled = scaleToFit(slice, shape);
60 final AnchorOffset dist = posSpec.getAnchorOffset();
61 final Offset anchorOfReference = offset(dist.getReferenceAnchor(), canvas);
62 final Offset anchorOfReferring = offset(dist.getReferringAnchor(), scaled);
63 return new Layout(
64 scaled,
65 new Offset(limitMin(anchorOfReference.getX() + dist.getOffset().getX() - anchorOfReferring.getX(), 0),
66 limitMin(anchorOfReference.getY() + dist.getOffset().getY() - anchorOfReferring.getY(), 0)));
67 }
68
69 private static Layout calcLayout(Dimension canvas,
70 Dimension shape,
71 AbsolutePositionLayoutSpec posSpec) {
72 final AnchorOffset dist = posSpec.getAnchorOffset();
73 final Offset anchorOfReference = offset(dist.getReferenceAnchor(), canvas);
74 final Offset anchorOfReferring = offset(dist.getReferringAnchor(), shape);
75 return new Layout(
76 shape,
77 new Offset(limitMin(anchorOfReference.getX() + dist.getOffset().getX() - anchorOfReferring.getX(), 0),
78 limitMin(anchorOfReference.getY() + dist.getOffset().getY() - anchorOfReferring.getY(), 0)));
79 }
80
81
82
83
84
85
86
87
88
89
90 public static MultiShapeLayout multiShapeLayout(final Dimension canvas,
91 final List<Tuple<Dimension, HorizontalCoverageLayoutSpec>> shapes) {
92 List<Layout> layouts = shapes.stream()
93 .map(a -> calcLayout(canvas, a.getA(), a.getB()))
94 .toList();
95
96 return new MultiShapeLayout(canvas, layouts);
97 }
98
99
100
101
102
103
104
105
106
107
108 public static MultiShapeLayout absoluteMultiShapeLayout(
109 final Dimension canvas,
110 final List<Tuple<Dimension, AbsolutePositionLayoutSpec>> shapes) {
111 List<Layout> layouts = shapes.stream()
112 .map(a -> calcLayout(canvas, a.getA(), a.getB()))
113 .toList();
114
115 return new MultiShapeLayout(canvas, layouts);
116 }
117
118 public static int limitMax(double v, int max) {
119 return (int) Math.min(Math.round(v), max);
120 }
121
122 public static int limitMin(double v, int min) {
123 return (int) Math.max(Math.round(v), min);
124 }
125
126
127 public static boolean fits(Dimension into, Dimension shape) {
128 return shape.getHeight() <= into.getHeight() && shape.getWidth() <= into.getHeight();
129 }
130
131
132 public static int area(Dimension a) {
133 return a.getWidth() * a.getHeight();
134 }
135
136
137 public static Dimension max(Dimension a, Dimension b) {
138 return area(a) > area(b) ? a : b;
139 }
140
141
142 public static double aspectRatio(Dimension a) {
143 return d(a.getWidth()) / d(a.getHeight());
144 }
145
146
147 public static boolean overlap(Layout a, Layout b) {
148 return (between(left(a), right(a), left(b)) || between(left(a), right(a), right(b)))
149 && (between(top(a), bottom(a), top(b)) || between(top(a), bottom(a), bottom(b)));
150 }
151
152
153 public static int left(Layout a) {
154 return a.getOffset().getX();
155 }
156
157
158 public static int right(Layout a) {
159 return a.getOffset().getX() + a.getDimension().getWidth();
160 }
161
162
163 public static int top(Layout a) {
164 return a.getOffset().getY();
165 }
166
167
168 public static int bottom(Layout a) {
169 return a.getOffset().getY() + a.getDimension().getHeight();
170 }
171
172
173 public static Offset offset(Anchor a, Dimension dim) {
174 return new Offset(limitMax(a.getLeft() * d(dim.getWidth()), dim.getWidth()),
175 limitMax(a.getTop() * d(dim.getHeight()), dim.getHeight()));
176 }
177
178
179
180
181
182 public static Dimension scale(Dimension limit, Dimension shape, double scale) {
183 return Dimension.dimension(
184 limitMax(d(shape.getWidth()) * scale, limit.getWidth()),
185 limitMax(d(shape.getHeight()) * scale, limit.getHeight()));
186 }
187
188
189 public static Dimension scaleToFit(Dimension canvas, Dimension d) {
190 final double scaleToWidth = d(canvas.getWidth()) / d(d.getWidth());
191 if (d.getHeight() * scaleToWidth > canvas.getHeight()) {
192 final double scaleToHeight = d(canvas.getHeight()) / d(d.getHeight());
193 return scale(canvas, d, scaleToHeight);
194 } else {
195 return scale(canvas, d, scaleToWidth);
196 }
197 }
198
199
200 public static boolean between(int a, int b, int x) {
201 return a <= x && x <= b;
202 }
203
204 private static double d(int v) {
205 return v;
206 }
207 }