-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathDocumentTransform.java
More file actions
130 lines (118 loc) · 4.66 KB
/
Copy pathDocumentTransform.java
File metadata and controls
130 lines (118 loc) · 4.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package com.demcha.compose.document.style;
/**
* Canonical-surface value object that carries a 2-D affine transformation
* (rotation around the placement centre plus uniform or non-uniform
* scaling) for a node. The transform is a render-time concern: the
* canonical layout compiler still measures and places nodes against
* their natural bbox, and backends apply the transform when drawing.
*
* <p>Mirrors {@code com.demcha.compose.engine.components.layout.Transform}
* one-to-one but lives on the canonical side so the public DSL never
* leaks engine.* types (see {@code PublicApiNoEngineLeakTest}).</p>
*
* <p>Conventions:</p>
* <ul>
* <li>{@link #rotationDegrees()} — clockwise rotation in degrees,
* {@code 0.0} means no rotation. Backends rotate around the
* placement centre, not the page origin.</li>
* <li>{@link #scaleX()} / {@link #scaleY()} — multiplicative scaling
* factors, {@code 1.0} means no scaling, {@code 0.5} halves,
* {@code 2.0} doubles. Negative values are allowed (mirror).</li>
* </ul>
*
* @param rotationDegrees clockwise rotation in degrees
* @param scaleX horizontal scale factor (must be finite, non-zero)
* @param scaleY vertical scale factor (must be finite, non-zero)
*
* @author Artem Demchyshyn
*/
public record DocumentTransform(double rotationDegrees, double scaleX, double scaleY) {
/** Identity transform — no rotation, no scaling. */
public static final DocumentTransform NONE = new DocumentTransform(0.0, 1.0, 1.0);
/**
* Validates that the rotation is finite and the scale factors are
* finite and non-zero. Zero scale would collapse the geometry to a
* point and is almost always a caller mistake.
*/
public DocumentTransform {
requireFinite("rotationDegrees", rotationDegrees);
requireFiniteNonZero("scaleX", scaleX);
requireFiniteNonZero("scaleY", scaleY);
}
/**
* Returns the identity transform.
*
* @return the identity transform (alias for {@link #NONE})
*/
public static DocumentTransform none() {
return NONE;
}
/**
* Creates a rotation-only transform with identity scaling.
*
* @param degrees clockwise rotation in degrees
* @return a transform that only rotates, with identity scaling
*/
public static DocumentTransform rotate(double degrees) {
return new DocumentTransform(degrees, 1.0, 1.0);
}
/**
* Uniform scaling — both axes share the same factor.
*
* @param uniformFactor scale factor for both axes
* @return a transform that only scales, with no rotation
*/
public static DocumentTransform scale(double uniformFactor) {
return new DocumentTransform(0.0, uniformFactor, uniformFactor);
}
/**
* Non-uniform scaling.
*
* @param scaleX horizontal scale factor
* @param scaleY vertical scale factor
* @return a transform that only scales, with no rotation
*/
public static DocumentTransform scale(double scaleX, double scaleY) {
return new DocumentTransform(0.0, scaleX, scaleY);
}
/**
* Returns a copy of this transform with the rotation replaced.
*
* @param degrees clockwise rotation in degrees
* @return a copy of this transform with the rotation replaced
*/
public DocumentTransform withRotation(double degrees) {
return new DocumentTransform(degrees, scaleX, scaleY);
}
/**
* Returns a copy of this transform with the scale factors replaced.
*
* @param scaleX horizontal scale factor
* @param scaleY vertical scale factor
* @return a copy of this transform with the scale factors replaced
*/
public DocumentTransform withScale(double scaleX, double scaleY) {
return new DocumentTransform(rotationDegrees, scaleX, scaleY);
}
/**
* Reports whether this transform is the identity.
*
* @return {@code true} when the transform is the identity (no
* rotation, no scaling); backends may skip CTM push/pop
* when this is the case
*/
public boolean isIdentity() {
return rotationDegrees == 0.0 && scaleX == 1.0 && scaleY == 1.0;
}
private static void requireFinite(String label, double value) {
if (Double.isNaN(value) || Double.isInfinite(value)) {
throw new IllegalArgumentException(label + " must be finite: " + value);
}
}
private static void requireFiniteNonZero(String label, double value) {
requireFinite(label, value);
if (value == 0.0) {
throw new IllegalArgumentException(label + " must be non-zero (a zero scale collapses the geometry)");
}
}
}