@lexmata/micropdf 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +191 -0
- package/README.md +985 -0
- package/binding.gyp +73 -0
- package/dist/annot.d.ts +458 -0
- package/dist/annot.d.ts.map +1 -0
- package/dist/annot.js +697 -0
- package/dist/annot.js.map +1 -0
- package/dist/archive.d.ts +128 -0
- package/dist/archive.d.ts.map +1 -0
- package/dist/archive.js +268 -0
- package/dist/archive.js.map +1 -0
- package/dist/buffer.d.ts +572 -0
- package/dist/buffer.d.ts.map +1 -0
- package/dist/buffer.js +971 -0
- package/dist/buffer.js.map +1 -0
- package/dist/colorspace.d.ts +287 -0
- package/dist/colorspace.d.ts.map +1 -0
- package/dist/colorspace.js +542 -0
- package/dist/colorspace.js.map +1 -0
- package/dist/context.d.ts +184 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +320 -0
- package/dist/context.js.map +1 -0
- package/dist/cookie.d.ts +164 -0
- package/dist/cookie.d.ts.map +1 -0
- package/dist/cookie.js +306 -0
- package/dist/cookie.js.map +1 -0
- package/dist/device.d.ts +169 -0
- package/dist/device.d.ts.map +1 -0
- package/dist/device.js +350 -0
- package/dist/device.js.map +1 -0
- package/dist/display-list.d.ts +202 -0
- package/dist/display-list.d.ts.map +1 -0
- package/dist/display-list.js +410 -0
- package/dist/display-list.js.map +1 -0
- package/dist/document.d.ts +637 -0
- package/dist/document.d.ts.map +1 -0
- package/dist/document.js +902 -0
- package/dist/document.js.map +1 -0
- package/dist/easy.d.ts +423 -0
- package/dist/easy.d.ts.map +1 -0
- package/dist/easy.js +644 -0
- package/dist/easy.js.map +1 -0
- package/dist/enhanced.d.ts +226 -0
- package/dist/enhanced.d.ts.map +1 -0
- package/dist/enhanced.js +368 -0
- package/dist/enhanced.js.map +1 -0
- package/dist/filter.d.ts +51 -0
- package/dist/filter.d.ts.map +1 -0
- package/dist/filter.js +381 -0
- package/dist/filter.js.map +1 -0
- package/dist/font.d.ts +222 -0
- package/dist/font.d.ts.map +1 -0
- package/dist/font.js +381 -0
- package/dist/font.js.map +1 -0
- package/dist/form.d.ts +214 -0
- package/dist/form.d.ts.map +1 -0
- package/dist/form.js +497 -0
- package/dist/form.js.map +1 -0
- package/dist/geometry.d.ts +469 -0
- package/dist/geometry.d.ts.map +1 -0
- package/dist/geometry.js +780 -0
- package/dist/geometry.js.map +1 -0
- package/dist/image.d.ts +172 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +348 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +171 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +339 -0
- package/dist/index.js.map +1 -0
- package/dist/link.d.ts +168 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +343 -0
- package/dist/link.js.map +1 -0
- package/dist/micropdf.d.ts +40 -0
- package/dist/micropdf.d.ts.map +1 -0
- package/dist/micropdf.js +45 -0
- package/dist/micropdf.js.map +1 -0
- package/dist/nanopdf.d.ts +40 -0
- package/dist/nanopdf.d.ts.map +1 -0
- package/dist/nanopdf.js +45 -0
- package/dist/nanopdf.js.map +1 -0
- package/dist/native.d.ts +242 -0
- package/dist/native.d.ts.map +1 -0
- package/dist/native.js +509 -0
- package/dist/native.js.map +1 -0
- package/dist/output.d.ts +166 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +365 -0
- package/dist/output.js.map +1 -0
- package/dist/path.d.ts +420 -0
- package/dist/path.d.ts.map +1 -0
- package/dist/path.js +687 -0
- package/dist/path.js.map +1 -0
- package/dist/pdf/object.d.ts +489 -0
- package/dist/pdf/object.d.ts.map +1 -0
- package/dist/pdf/object.js +1045 -0
- package/dist/pdf/object.js.map +1 -0
- package/dist/pixmap.d.ts +315 -0
- package/dist/pixmap.d.ts.map +1 -0
- package/dist/pixmap.js +590 -0
- package/dist/pixmap.js.map +1 -0
- package/dist/profiler.d.ts +159 -0
- package/dist/profiler.d.ts.map +1 -0
- package/dist/profiler.js +380 -0
- package/dist/profiler.js.map +1 -0
- package/dist/render-options.d.ts +227 -0
- package/dist/render-options.d.ts.map +1 -0
- package/dist/render-options.js +130 -0
- package/dist/render-options.js.map +1 -0
- package/dist/resource-tracking.d.ts +332 -0
- package/dist/resource-tracking.d.ts.map +1 -0
- package/dist/resource-tracking.js +653 -0
- package/dist/resource-tracking.js.map +1 -0
- package/dist/simple.d.ts +276 -0
- package/dist/simple.d.ts.map +1 -0
- package/dist/simple.js +343 -0
- package/dist/simple.js.map +1 -0
- package/dist/stext.d.ts +290 -0
- package/dist/stext.d.ts.map +1 -0
- package/dist/stext.js +312 -0
- package/dist/stext.js.map +1 -0
- package/dist/stream.d.ts +174 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +476 -0
- package/dist/stream.js.map +1 -0
- package/dist/text.d.ts +337 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +454 -0
- package/dist/text.js.map +1 -0
- package/dist/typed-arrays.d.ts +127 -0
- package/dist/typed-arrays.d.ts.map +1 -0
- package/dist/typed-arrays.js +410 -0
- package/dist/typed-arrays.js.map +1 -0
- package/dist/types.d.ts +358 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +216 -0
- package/dist/types.js.map +1 -0
- package/native/annot.cc +557 -0
- package/native/buffer.cc +204 -0
- package/native/colorspace.cc +166 -0
- package/native/context.cc +84 -0
- package/native/cookie.cc +179 -0
- package/native/device.cc +179 -0
- package/native/display_list.cc +179 -0
- package/native/document.cc +268 -0
- package/native/enhanced.cc +70 -0
- package/native/font.cc +282 -0
- package/native/form.cc +523 -0
- package/native/geometry.cc +255 -0
- package/native/image.cc +216 -0
- package/native/include/micropdf/enhanced.h +38 -0
- package/native/include/micropdf/types.h +36 -0
- package/native/include/micropdf.h +106 -0
- package/native/include/mupdf-ffi.h +39 -0
- package/native/include/mupdf.h +11 -0
- package/native/include/mupdf_minimal.h +381 -0
- package/native/lib/linux-x64/libmicropdf.a +0 -0
- package/native/link.cc +234 -0
- package/native/micropdf.cc +71 -0
- package/native/output.cc +229 -0
- package/native/page.cc +572 -0
- package/native/path.cc +259 -0
- package/native/pixmap.cc +240 -0
- package/native/stext.cc +610 -0
- package/native/stream.cc +239 -0
- package/package.json +120 -0
- package/scripts/build-from-rust.js +97 -0
- package/scripts/install.js +184 -0
package/dist/geometry.js
ADDED
|
@@ -0,0 +1,780 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Geometry primitives - Point, Rect, IRect, Matrix, Quad
|
|
3
|
+
*
|
|
4
|
+
* This module provides fundamental 2D geometry types used throughout the MicroPDF library.
|
|
5
|
+
* All types are immutable and follow functional programming principles.
|
|
6
|
+
*
|
|
7
|
+
* This implementation mirrors the Rust `fitz::geometry` module for 100% API compatibility.
|
|
8
|
+
*
|
|
9
|
+
* @module geometry
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { Point, Rect, Matrix } from 'micropdf';
|
|
13
|
+
*
|
|
14
|
+
* // Create a point
|
|
15
|
+
* const p = new Point(100, 200);
|
|
16
|
+
*
|
|
17
|
+
* // Create a rectangle
|
|
18
|
+
* const rect = new Rect(0, 0, 100, 100);
|
|
19
|
+
*
|
|
20
|
+
* // Transform with a matrix
|
|
21
|
+
* const matrix = Matrix.scale(2, 2);
|
|
22
|
+
* const transformed = p.transform(matrix);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* A 2D point with floating-point coordinates.
|
|
27
|
+
*
|
|
28
|
+
* Points are immutable - all operations return new Point instances rather than
|
|
29
|
+
* modifying the existing point. This makes them safe to use in functional programming
|
|
30
|
+
* contexts and prevents accidental mutations.
|
|
31
|
+
*
|
|
32
|
+
* @class Point
|
|
33
|
+
* @implements {PointLike}
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* // Create a point
|
|
37
|
+
* const p1 = new Point(10, 20);
|
|
38
|
+
*
|
|
39
|
+
* // Transform it
|
|
40
|
+
* const p2 = p1.scale(2); // Point(20, 40)
|
|
41
|
+
*
|
|
42
|
+
* // Calculate distance
|
|
43
|
+
* const distance = p1.distanceTo(p2); // 22.36...
|
|
44
|
+
*
|
|
45
|
+
* // Points are immutable
|
|
46
|
+
* const p3 = p1.add(new Point(5, 5)); // p1 is unchanged
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export class Point {
|
|
50
|
+
/**
|
|
51
|
+
* The x-coordinate of the point.
|
|
52
|
+
* @readonly
|
|
53
|
+
* @type {number}
|
|
54
|
+
*/
|
|
55
|
+
x;
|
|
56
|
+
/**
|
|
57
|
+
* The y-coordinate of the point.
|
|
58
|
+
* @readonly
|
|
59
|
+
* @type {number}
|
|
60
|
+
*/
|
|
61
|
+
y;
|
|
62
|
+
/**
|
|
63
|
+
* Creates a new Point with the specified coordinates.
|
|
64
|
+
*
|
|
65
|
+
* @param {number} x - The x-coordinate
|
|
66
|
+
* @param {number} y - The y-coordinate
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const point = new Point(100, 200);
|
|
70
|
+
* console.log(point.x); // 100
|
|
71
|
+
* console.log(point.y); // 200
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
constructor(x, y) {
|
|
75
|
+
this.x = x;
|
|
76
|
+
this.y = y;
|
|
77
|
+
}
|
|
78
|
+
// ============================================================================
|
|
79
|
+
// Static Constants
|
|
80
|
+
// ============================================================================
|
|
81
|
+
/**
|
|
82
|
+
* The origin point at coordinates (0, 0).
|
|
83
|
+
*
|
|
84
|
+
* This is a convenience constant for the most commonly used point.
|
|
85
|
+
*
|
|
86
|
+
* @static
|
|
87
|
+
* @readonly
|
|
88
|
+
* @type {Point}
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* const origin = Point.ORIGIN;
|
|
92
|
+
* console.log(origin.x, origin.y); // 0, 0
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
static ORIGIN = new Point(0, 0);
|
|
96
|
+
// ============================================================================
|
|
97
|
+
// Static Constructors
|
|
98
|
+
// ============================================================================
|
|
99
|
+
/**
|
|
100
|
+
* Creates a Point from a point-like object.
|
|
101
|
+
*
|
|
102
|
+
* This method accepts any object with `x` and `y` properties and converts it
|
|
103
|
+
* to a proper Point instance. If the input is already a Point, it returns it unchanged.
|
|
104
|
+
*
|
|
105
|
+
* @static
|
|
106
|
+
* @param {PointLike} p - A point-like object with x and y properties
|
|
107
|
+
* @returns {Point} A Point instance
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* // From a plain object
|
|
111
|
+
* const p1 = Point.from({ x: 10, y: 20 });
|
|
112
|
+
*
|
|
113
|
+
* // From an existing Point (returns the same instance)
|
|
114
|
+
* const p2 = new Point(10, 20);
|
|
115
|
+
* const p3 = Point.from(p2); // p2 === p3
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
static from(p) {
|
|
119
|
+
if (p instanceof Point) {
|
|
120
|
+
return p;
|
|
121
|
+
}
|
|
122
|
+
return new Point(p.x, p.y);
|
|
123
|
+
}
|
|
124
|
+
// ============================================================================
|
|
125
|
+
// Methods
|
|
126
|
+
// ============================================================================
|
|
127
|
+
/**
|
|
128
|
+
* Transforms this point by a transformation matrix.
|
|
129
|
+
*
|
|
130
|
+
* Applies a 2D affine transformation to the point. This is commonly used for
|
|
131
|
+
* scaling, rotation, translation, and skewing operations.
|
|
132
|
+
*
|
|
133
|
+
* @param {MatrixLike} m - The transformation matrix to apply
|
|
134
|
+
* @returns {Point} A new transformed point
|
|
135
|
+
* @example
|
|
136
|
+
* ```typescript
|
|
137
|
+
* const p = new Point(10, 20);
|
|
138
|
+
*
|
|
139
|
+
* // Scale by 2x
|
|
140
|
+
* const scaled = p.transform(Matrix.scale(2, 2));
|
|
141
|
+
* console.log(scaled); // Point(20, 40)
|
|
142
|
+
*
|
|
143
|
+
* // Rotate 90 degrees
|
|
144
|
+
* const rotated = p.transform(Matrix.rotate(90));
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
transform(m) {
|
|
148
|
+
return new Point(this.x * m.a + this.y * m.c + m.e, this.x * m.b + this.y * m.d + m.f);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Calculates the Euclidean distance to another point.
|
|
152
|
+
*
|
|
153
|
+
* Uses the Pythagorean theorem to compute the straight-line distance
|
|
154
|
+
* between this point and another point in 2D space.
|
|
155
|
+
*
|
|
156
|
+
* @param {PointLike} other - The point to measure distance to
|
|
157
|
+
* @returns {number} The distance in the same units as the coordinates
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* const p1 = new Point(0, 0);
|
|
161
|
+
* const p2 = new Point(3, 4);
|
|
162
|
+
* const distance = p1.distanceTo(p2); // 5.0
|
|
163
|
+
*
|
|
164
|
+
* // Distance is symmetric
|
|
165
|
+
* p2.distanceTo(p1) === p1.distanceTo(p2); // true
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
distanceTo(other) {
|
|
169
|
+
const dx = this.x - other.x;
|
|
170
|
+
const dy = this.y - other.y;
|
|
171
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Adds another point to this point (vector addition).
|
|
175
|
+
*
|
|
176
|
+
* Returns a new point whose coordinates are the sum of this point's
|
|
177
|
+
* coordinates and the other point's coordinates.
|
|
178
|
+
*
|
|
179
|
+
* @param {PointLike} other - The point to add
|
|
180
|
+
* @returns {Point} A new point with summed coordinates
|
|
181
|
+
* @example
|
|
182
|
+
* ```typescript
|
|
183
|
+
* const p1 = new Point(10, 20);
|
|
184
|
+
* const p2 = new Point(5, 10);
|
|
185
|
+
* const sum = p1.add(p2);
|
|
186
|
+
* console.log(sum); // Point(15, 30)
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
add(other) {
|
|
190
|
+
return new Point(this.x + other.x, this.y + other.y);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Subtracts another point from this point (vector subtraction).
|
|
194
|
+
*
|
|
195
|
+
* Returns a new point whose coordinates are the difference between
|
|
196
|
+
* this point's coordinates and the other point's coordinates.
|
|
197
|
+
*
|
|
198
|
+
* @param {PointLike} other - The point to subtract
|
|
199
|
+
* @returns {Point} A new point with the difference
|
|
200
|
+
* @example
|
|
201
|
+
* ```typescript
|
|
202
|
+
* const p1 = new Point(10, 20);
|
|
203
|
+
* const p2 = new Point(5, 10);
|
|
204
|
+
* const diff = p1.subtract(p2);
|
|
205
|
+
* console.log(diff); // Point(5, 10)
|
|
206
|
+
* ```
|
|
207
|
+
*/
|
|
208
|
+
subtract(other) {
|
|
209
|
+
return new Point(this.x - other.x, this.y - other.y);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Scales this point by a factor (scalar multiplication).
|
|
213
|
+
*
|
|
214
|
+
* Multiplies both x and y coordinates by the given factor.
|
|
215
|
+
*
|
|
216
|
+
* @param {number} factor - The scaling factor
|
|
217
|
+
* @returns {Point} A new scaled point
|
|
218
|
+
* @example
|
|
219
|
+
* ```typescript
|
|
220
|
+
* const p = new Point(10, 20);
|
|
221
|
+
* const doubled = p.scale(2); // Point(20, 40)
|
|
222
|
+
* const halved = p.scale(0.5); // Point(5, 10)
|
|
223
|
+
* const negated = p.scale(-1); // Point(-10, -20)
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
scale(factor) {
|
|
227
|
+
return new Point(this.x * factor, this.y * factor);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Normalizes this point to unit length.
|
|
231
|
+
*
|
|
232
|
+
* Returns a point in the same direction but with length 1.0.
|
|
233
|
+
* If the point is at the origin (length 0), returns the origin.
|
|
234
|
+
*
|
|
235
|
+
* @returns {Point} A normalized point with length 1.0 (or origin if length is 0)
|
|
236
|
+
* @example
|
|
237
|
+
* ```typescript
|
|
238
|
+
* const p = new Point(3, 4);
|
|
239
|
+
* const normalized = p.normalize();
|
|
240
|
+
* console.log(normalized); // Point(0.6, 0.8)
|
|
241
|
+
* console.log(normalized.length); // 1.0
|
|
242
|
+
*
|
|
243
|
+
* // Origin stays at origin
|
|
244
|
+
* Point.ORIGIN.normalize(); // Point(0, 0)
|
|
245
|
+
* ```
|
|
246
|
+
*/
|
|
247
|
+
normalize() {
|
|
248
|
+
const len = Math.sqrt(this.x * this.x + this.y * this.y);
|
|
249
|
+
if (len === 0) {
|
|
250
|
+
return new Point(0, 0);
|
|
251
|
+
}
|
|
252
|
+
return new Point(this.x / len, this.y / len);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Gets the length (magnitude) of this point when treated as a vector.
|
|
256
|
+
*
|
|
257
|
+
* Computes the Euclidean distance from the origin to this point.
|
|
258
|
+
*
|
|
259
|
+
* @readonly
|
|
260
|
+
* @type {number}
|
|
261
|
+
* @example
|
|
262
|
+
* ```typescript
|
|
263
|
+
* const p = new Point(3, 4);
|
|
264
|
+
* console.log(p.length); // 5.0
|
|
265
|
+
*
|
|
266
|
+
* // Right triangle: 3² + 4² = 5²
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
get length() {
|
|
270
|
+
return Math.sqrt(this.x * this.x + this.y * this.y);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Checks if this point is equal to another point.
|
|
274
|
+
*
|
|
275
|
+
* Two points are considered equal if both their x and y coordinates are exactly equal.
|
|
276
|
+
* Note: This uses strict equality, so floating point precision issues may affect the result.
|
|
277
|
+
*
|
|
278
|
+
* @param {PointLike} other - The point to compare with
|
|
279
|
+
* @returns {boolean} True if the points have identical coordinates
|
|
280
|
+
* @example
|
|
281
|
+
* ```typescript
|
|
282
|
+
* const p1 = new Point(10, 20);
|
|
283
|
+
* const p2 = new Point(10, 20);
|
|
284
|
+
* const p3 = new Point(10, 21);
|
|
285
|
+
*
|
|
286
|
+
* p1.equals(p2); // true
|
|
287
|
+
* p1.equals(p3); // false
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
290
|
+
equals(other) {
|
|
291
|
+
return this.x === other.x && this.y === other.y;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Returns a string representation of the point.
|
|
295
|
+
*
|
|
296
|
+
* @returns {string} A string in the format "Point(x, y)"
|
|
297
|
+
* @example
|
|
298
|
+
* ```typescript
|
|
299
|
+
* const p = new Point(10.5, 20.3);
|
|
300
|
+
* console.log(p.toString()); // "Point(10.5, 20.3)"
|
|
301
|
+
* console.log(String(p)); // "Point(10.5, 20.3)"
|
|
302
|
+
* ```
|
|
303
|
+
*/
|
|
304
|
+
toString() {
|
|
305
|
+
return `Point(${this.x}, ${this.y})`;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* A rectangle defined by two corner points (floating point)
|
|
310
|
+
*/
|
|
311
|
+
export class Rect {
|
|
312
|
+
x0;
|
|
313
|
+
y0;
|
|
314
|
+
x1;
|
|
315
|
+
y1;
|
|
316
|
+
constructor(x0, y0, x1, y1) {
|
|
317
|
+
this.x0 = x0;
|
|
318
|
+
this.y0 = y0;
|
|
319
|
+
this.x1 = x1;
|
|
320
|
+
this.y1 = y1;
|
|
321
|
+
}
|
|
322
|
+
// ============================================================================
|
|
323
|
+
// Static Constants
|
|
324
|
+
// ============================================================================
|
|
325
|
+
/** Empty rectangle */
|
|
326
|
+
static EMPTY = new Rect(Infinity, Infinity, -Infinity, -Infinity);
|
|
327
|
+
/** Infinite rectangle */
|
|
328
|
+
static INFINITE = new Rect(-Infinity, -Infinity, Infinity, Infinity);
|
|
329
|
+
/** Unit rectangle (0,0) to (1,1) */
|
|
330
|
+
static UNIT = new Rect(0, 0, 1, 1);
|
|
331
|
+
// ============================================================================
|
|
332
|
+
// Static Constructors
|
|
333
|
+
// ============================================================================
|
|
334
|
+
/** Create a rect from a rect-like object */
|
|
335
|
+
static from(r) {
|
|
336
|
+
if (r instanceof Rect) {
|
|
337
|
+
return r;
|
|
338
|
+
}
|
|
339
|
+
if (r == null) {
|
|
340
|
+
return new Rect(0, 0, 0, 0);
|
|
341
|
+
}
|
|
342
|
+
return new Rect(r.x0, r.y0, r.x1, r.y1);
|
|
343
|
+
}
|
|
344
|
+
/** Create a rect from position and size */
|
|
345
|
+
static fromXYWH(x, y, width, height) {
|
|
346
|
+
return new Rect(x, y, x + width, y + height);
|
|
347
|
+
}
|
|
348
|
+
/** Create a rect from an IRect */
|
|
349
|
+
static fromIRect(r) {
|
|
350
|
+
return new Rect(r.x0, r.y0, r.x1, r.y1);
|
|
351
|
+
}
|
|
352
|
+
// ============================================================================
|
|
353
|
+
// Properties
|
|
354
|
+
// ============================================================================
|
|
355
|
+
/** Width of the rectangle */
|
|
356
|
+
get width() {
|
|
357
|
+
return this.x1 - this.x0;
|
|
358
|
+
}
|
|
359
|
+
/** Height of the rectangle */
|
|
360
|
+
get height() {
|
|
361
|
+
return this.y1 - this.y0;
|
|
362
|
+
}
|
|
363
|
+
/** Check if the rectangle is empty */
|
|
364
|
+
get isEmpty() {
|
|
365
|
+
return this.x0 >= this.x1 || this.y0 >= this.y1;
|
|
366
|
+
}
|
|
367
|
+
/** Check if the rectangle is infinite */
|
|
368
|
+
get isInfinite() {
|
|
369
|
+
return this.x0 === -Infinity;
|
|
370
|
+
}
|
|
371
|
+
containsPoint(xOrPoint, y) {
|
|
372
|
+
const px = typeof xOrPoint === 'number' ? xOrPoint : xOrPoint.x;
|
|
373
|
+
const py = typeof xOrPoint === 'number' ? y : xOrPoint.y;
|
|
374
|
+
return px >= this.x0 && px < this.x1 && py >= this.y0 && py < this.y1;
|
|
375
|
+
}
|
|
376
|
+
/** Check if this rectangle contains another rectangle */
|
|
377
|
+
containsRect(other) {
|
|
378
|
+
return this.x0 <= other.x0 && this.y0 <= other.y0 && this.x1 >= other.x1 && this.y1 >= other.y1;
|
|
379
|
+
}
|
|
380
|
+
/** Union with another rectangle */
|
|
381
|
+
union(other) {
|
|
382
|
+
if (this.isEmpty)
|
|
383
|
+
return Rect.from(other);
|
|
384
|
+
if (other.x0 >= other.x1 || other.y0 >= other.y1)
|
|
385
|
+
return this;
|
|
386
|
+
return new Rect(Math.min(this.x0, other.x0), Math.min(this.y0, other.y0), Math.max(this.x1, other.x1), Math.max(this.y1, other.y1));
|
|
387
|
+
}
|
|
388
|
+
/** Intersection with another rectangle */
|
|
389
|
+
intersect(other) {
|
|
390
|
+
const result = new Rect(Math.max(this.x0, other.x0), Math.max(this.y0, other.y0), Math.min(this.x1, other.x1), Math.min(this.y1, other.y1));
|
|
391
|
+
if (result.isEmpty) {
|
|
392
|
+
return Rect.EMPTY;
|
|
393
|
+
}
|
|
394
|
+
return result;
|
|
395
|
+
}
|
|
396
|
+
/** Expand by including a point */
|
|
397
|
+
includePoint(p) {
|
|
398
|
+
return new Rect(Math.min(this.x0, p.x), Math.min(this.y0, p.y), Math.max(this.x1, p.x), Math.max(this.y1, p.y));
|
|
399
|
+
}
|
|
400
|
+
/** Translate by offset */
|
|
401
|
+
translate(dx, dy) {
|
|
402
|
+
return new Rect(this.x0 + dx, this.y0 + dy, this.x1 + dx, this.y1 + dy);
|
|
403
|
+
}
|
|
404
|
+
/** Scale by factor */
|
|
405
|
+
scale(sx, sy = sx) {
|
|
406
|
+
return new Rect(this.x0 * sx, this.y0 * sy, this.x1 * sx, this.y1 * sy);
|
|
407
|
+
}
|
|
408
|
+
/** Transform by a matrix */
|
|
409
|
+
transform(m) {
|
|
410
|
+
if (this.isEmpty || this.isInfinite) {
|
|
411
|
+
return this;
|
|
412
|
+
}
|
|
413
|
+
const p1 = new Point(this.x0, this.y0).transform(m);
|
|
414
|
+
const p2 = new Point(this.x1, this.y0).transform(m);
|
|
415
|
+
const p3 = new Point(this.x0, this.y1).transform(m);
|
|
416
|
+
const p4 = new Point(this.x1, this.y1).transform(m);
|
|
417
|
+
return new Rect(Math.min(p1.x, p2.x, p3.x, p4.x), Math.min(p1.y, p2.y, p3.y, p4.y), Math.max(p1.x, p2.x, p3.x, p4.x), Math.max(p1.y, p2.y, p3.y, p4.y));
|
|
418
|
+
}
|
|
419
|
+
/** Normalize (ensure x0 <= x1 and y0 <= y1) */
|
|
420
|
+
normalize() {
|
|
421
|
+
return new Rect(Math.min(this.x0, this.x1), Math.min(this.y0, this.y1), Math.max(this.x0, this.x1), Math.max(this.y0, this.y1));
|
|
422
|
+
}
|
|
423
|
+
/** Round to integer rectangle */
|
|
424
|
+
round() {
|
|
425
|
+
return new IRect(Math.floor(this.x0), Math.floor(this.y0), Math.ceil(this.x1), Math.ceil(this.y1));
|
|
426
|
+
}
|
|
427
|
+
/** Check equality */
|
|
428
|
+
equals(other) {
|
|
429
|
+
return (this.x0 === other.x0 && this.y0 === other.y0 && this.x1 === other.x1 && this.y1 === other.y1);
|
|
430
|
+
}
|
|
431
|
+
toString() {
|
|
432
|
+
return `Rect(${this.x0}, ${this.y0}, ${this.x1}, ${this.y1})`;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* An integer rectangle defined by two corner points
|
|
437
|
+
*/
|
|
438
|
+
export class IRect {
|
|
439
|
+
x0;
|
|
440
|
+
y0;
|
|
441
|
+
x1;
|
|
442
|
+
y1;
|
|
443
|
+
constructor(x0, y0, x1, y1) {
|
|
444
|
+
this.x0 = Math.floor(x0);
|
|
445
|
+
this.y0 = Math.floor(y0);
|
|
446
|
+
this.x1 = Math.floor(x1);
|
|
447
|
+
this.y1 = Math.floor(y1);
|
|
448
|
+
}
|
|
449
|
+
// ============================================================================
|
|
450
|
+
// Static Constants
|
|
451
|
+
// ============================================================================
|
|
452
|
+
/** Empty integer rectangle */
|
|
453
|
+
static EMPTY = new IRect(0x7fffffff, 0x7fffffff, -0x80000000, -0x80000000);
|
|
454
|
+
/** Infinite integer rectangle */
|
|
455
|
+
static INFINITE = new IRect(-0x80000000, -0x80000000, 0x7fffffff, 0x7fffffff);
|
|
456
|
+
// ============================================================================
|
|
457
|
+
// Static Constructors
|
|
458
|
+
// ============================================================================
|
|
459
|
+
/** Create from a rect-like object */
|
|
460
|
+
static from(r) {
|
|
461
|
+
if (r instanceof IRect) {
|
|
462
|
+
return r;
|
|
463
|
+
}
|
|
464
|
+
return new IRect(r.x0, r.y0, r.x1, r.y1);
|
|
465
|
+
}
|
|
466
|
+
/** Create from a Rect by rounding */
|
|
467
|
+
static fromRect(r) {
|
|
468
|
+
return new IRect(Math.floor(r.x0), Math.floor(r.y0), Math.ceil(r.x1), Math.ceil(r.y1));
|
|
469
|
+
}
|
|
470
|
+
// ============================================================================
|
|
471
|
+
// Properties
|
|
472
|
+
// ============================================================================
|
|
473
|
+
/** Width */
|
|
474
|
+
get width() {
|
|
475
|
+
return this.x1 - this.x0;
|
|
476
|
+
}
|
|
477
|
+
/** Height */
|
|
478
|
+
get height() {
|
|
479
|
+
return this.y1 - this.y0;
|
|
480
|
+
}
|
|
481
|
+
/** Check if empty */
|
|
482
|
+
get isEmpty() {
|
|
483
|
+
return this.x0 >= this.x1 || this.y0 >= this.y1;
|
|
484
|
+
}
|
|
485
|
+
// ============================================================================
|
|
486
|
+
// Methods
|
|
487
|
+
// ============================================================================
|
|
488
|
+
/** Union with another integer rectangle */
|
|
489
|
+
union(other) {
|
|
490
|
+
if (this.isEmpty)
|
|
491
|
+
return IRect.from(other);
|
|
492
|
+
if (other.x0 >= other.x1 || other.y0 >= other.y1)
|
|
493
|
+
return this;
|
|
494
|
+
return new IRect(Math.min(this.x0, other.x0), Math.min(this.y0, other.y0), Math.max(this.x1, other.x1), Math.max(this.y1, other.y1));
|
|
495
|
+
}
|
|
496
|
+
/** Intersection with another integer rectangle */
|
|
497
|
+
intersect(other) {
|
|
498
|
+
const result = new IRect(Math.max(this.x0, other.x0), Math.max(this.y0, other.y0), Math.min(this.x1, other.x1), Math.min(this.y1, other.y1));
|
|
499
|
+
if (result.isEmpty) {
|
|
500
|
+
return IRect.EMPTY;
|
|
501
|
+
}
|
|
502
|
+
return result;
|
|
503
|
+
}
|
|
504
|
+
/** Translate by offset */
|
|
505
|
+
translate(dx, dy) {
|
|
506
|
+
return new IRect(this.x0 + dx, this.y0 + dy, this.x1 + dx, this.y1 + dy);
|
|
507
|
+
}
|
|
508
|
+
/** Convert to Rect */
|
|
509
|
+
toRect() {
|
|
510
|
+
return new Rect(this.x0, this.y0, this.x1, this.y1);
|
|
511
|
+
}
|
|
512
|
+
/** Check equality */
|
|
513
|
+
equals(other) {
|
|
514
|
+
return (this.x0 === other.x0 && this.y0 === other.y0 && this.x1 === other.x1 && this.y1 === other.y1);
|
|
515
|
+
}
|
|
516
|
+
toString() {
|
|
517
|
+
return `IRect(${this.x0}, ${this.y0}, ${this.x1}, ${this.y1})`;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* A 2D transformation matrix (affine transform)
|
|
522
|
+
*/
|
|
523
|
+
export class Matrix {
|
|
524
|
+
a;
|
|
525
|
+
b;
|
|
526
|
+
c;
|
|
527
|
+
d;
|
|
528
|
+
e;
|
|
529
|
+
f;
|
|
530
|
+
constructor(a, b, c, d, e, f) {
|
|
531
|
+
this.a = a;
|
|
532
|
+
this.b = b;
|
|
533
|
+
this.c = c;
|
|
534
|
+
this.d = d;
|
|
535
|
+
this.e = e;
|
|
536
|
+
this.f = f;
|
|
537
|
+
}
|
|
538
|
+
// ============================================================================
|
|
539
|
+
// Static Constants
|
|
540
|
+
// ============================================================================
|
|
541
|
+
/** Identity matrix */
|
|
542
|
+
static IDENTITY = new Matrix(1, 0, 0, 1, 0, 0);
|
|
543
|
+
// ============================================================================
|
|
544
|
+
// Static Constructors
|
|
545
|
+
// ============================================================================
|
|
546
|
+
/** Create a matrix from a matrix-like object */
|
|
547
|
+
static from(m) {
|
|
548
|
+
if (m instanceof Matrix) {
|
|
549
|
+
return m;
|
|
550
|
+
}
|
|
551
|
+
return new Matrix(m.a, m.b, m.c, m.d, m.e, m.f);
|
|
552
|
+
}
|
|
553
|
+
/** Create a translation matrix */
|
|
554
|
+
static translate(tx, ty) {
|
|
555
|
+
return new Matrix(1, 0, 0, 1, tx, ty);
|
|
556
|
+
}
|
|
557
|
+
/** Create a scaling matrix */
|
|
558
|
+
static scale(sx, sy = sx) {
|
|
559
|
+
return new Matrix(sx, 0, 0, sy, 0, 0);
|
|
560
|
+
}
|
|
561
|
+
/** Create a rotation matrix (degrees) */
|
|
562
|
+
static rotate(degrees) {
|
|
563
|
+
const rad = (degrees * Math.PI) / 180;
|
|
564
|
+
const cos = Math.cos(rad);
|
|
565
|
+
const sin = Math.sin(rad);
|
|
566
|
+
return new Matrix(cos, sin, -sin, cos, 0, 0);
|
|
567
|
+
}
|
|
568
|
+
/** Create a shear matrix */
|
|
569
|
+
static shear(sx, sy) {
|
|
570
|
+
return new Matrix(1, sy, sx, 1, 0, 0);
|
|
571
|
+
}
|
|
572
|
+
// ============================================================================
|
|
573
|
+
// Properties
|
|
574
|
+
// ============================================================================
|
|
575
|
+
/** Check if this is the identity matrix */
|
|
576
|
+
get isIdentity() {
|
|
577
|
+
return (this.a === 1 && this.b === 0 && this.c === 0 && this.d === 1 && this.e === 0 && this.f === 0);
|
|
578
|
+
}
|
|
579
|
+
/** Check if this is a rectilinear matrix (no rotation/shear) */
|
|
580
|
+
get isRectilinear() {
|
|
581
|
+
return (this.b === 0 && this.c === 0) || (this.a === 0 && this.d === 0);
|
|
582
|
+
}
|
|
583
|
+
// ============================================================================
|
|
584
|
+
// Methods
|
|
585
|
+
// ============================================================================
|
|
586
|
+
/** Concatenate with another matrix */
|
|
587
|
+
concat(other) {
|
|
588
|
+
return new Matrix(this.a * other.a + this.b * other.c, this.a * other.b + this.b * other.d, this.c * other.a + this.d * other.c, this.c * other.b + this.d * other.d, this.e * other.a + this.f * other.c + other.e, this.e * other.b + this.f * other.d + other.f);
|
|
589
|
+
}
|
|
590
|
+
/** Invert the matrix */
|
|
591
|
+
invert() {
|
|
592
|
+
const det = this.a * this.d - this.b * this.c;
|
|
593
|
+
if (Math.abs(det) < 1e-14) {
|
|
594
|
+
return null;
|
|
595
|
+
}
|
|
596
|
+
const invDet = 1 / det;
|
|
597
|
+
return new Matrix(this.d * invDet, -this.b * invDet, -this.c * invDet, this.a * invDet, (this.c * this.f - this.d * this.e) * invDet, (this.b * this.e - this.a * this.f) * invDet);
|
|
598
|
+
}
|
|
599
|
+
/** Pre-translate this matrix */
|
|
600
|
+
preTranslate(tx, ty) {
|
|
601
|
+
return Matrix.translate(tx, ty).concat(this);
|
|
602
|
+
}
|
|
603
|
+
/** Post-translate this matrix */
|
|
604
|
+
postTranslate(tx, ty) {
|
|
605
|
+
return this.concat(Matrix.translate(tx, ty));
|
|
606
|
+
}
|
|
607
|
+
/** Pre-scale this matrix */
|
|
608
|
+
preScale(sx, sy = sx) {
|
|
609
|
+
return Matrix.scale(sx, sy).concat(this);
|
|
610
|
+
}
|
|
611
|
+
/** Post-scale this matrix */
|
|
612
|
+
postScale(sx, sy = sx) {
|
|
613
|
+
return this.concat(Matrix.scale(sx, sy));
|
|
614
|
+
}
|
|
615
|
+
/** Pre-rotate this matrix */
|
|
616
|
+
preRotate(degrees) {
|
|
617
|
+
return Matrix.rotate(degrees).concat(this);
|
|
618
|
+
}
|
|
619
|
+
/** Post-rotate this matrix */
|
|
620
|
+
postRotate(degrees) {
|
|
621
|
+
return this.concat(Matrix.rotate(degrees));
|
|
622
|
+
}
|
|
623
|
+
/** Pre-shear this matrix */
|
|
624
|
+
preShear(sx, sy) {
|
|
625
|
+
return Matrix.shear(sx, sy).concat(this);
|
|
626
|
+
}
|
|
627
|
+
/** Post-shear this matrix */
|
|
628
|
+
postShear(sx, sy) {
|
|
629
|
+
return this.concat(Matrix.shear(sx, sy));
|
|
630
|
+
}
|
|
631
|
+
/** Transform a point */
|
|
632
|
+
transformPoint(p) {
|
|
633
|
+
return new Point(p.x * this.a + p.y * this.c + this.e, p.x * this.b + p.y * this.d + this.f);
|
|
634
|
+
}
|
|
635
|
+
/** Check equality */
|
|
636
|
+
equals(other) {
|
|
637
|
+
return (this.a === other.a &&
|
|
638
|
+
this.b === other.b &&
|
|
639
|
+
this.c === other.c &&
|
|
640
|
+
this.d === other.d &&
|
|
641
|
+
this.e === other.e &&
|
|
642
|
+
this.f === other.f);
|
|
643
|
+
}
|
|
644
|
+
toString() {
|
|
645
|
+
return `Matrix(${this.a}, ${this.b}, ${this.c}, ${this.d}, ${this.e}, ${this.f})`;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* A quadrilateral defined by four corner points
|
|
650
|
+
*/
|
|
651
|
+
export class Quad {
|
|
652
|
+
ul;
|
|
653
|
+
ur;
|
|
654
|
+
ll;
|
|
655
|
+
lr;
|
|
656
|
+
constructor(ul, ur, ll, lr) {
|
|
657
|
+
this.ul = Point.from(ul);
|
|
658
|
+
this.ur = Point.from(ur);
|
|
659
|
+
this.ll = Point.from(ll);
|
|
660
|
+
this.lr = Point.from(lr);
|
|
661
|
+
}
|
|
662
|
+
// ============================================================================
|
|
663
|
+
// Static Constructors
|
|
664
|
+
// ============================================================================
|
|
665
|
+
/** Create a quad from a rectangle */
|
|
666
|
+
static fromRect(r) {
|
|
667
|
+
return new Quad(new Point(r.x0, r.y0), new Point(r.x1, r.y0), new Point(r.x0, r.y1), new Point(r.x1, r.y1));
|
|
668
|
+
}
|
|
669
|
+
// ============================================================================
|
|
670
|
+
// Methods
|
|
671
|
+
// ============================================================================
|
|
672
|
+
/** Transform this quad by a matrix */
|
|
673
|
+
transform(m) {
|
|
674
|
+
const matrix = Matrix.from(m);
|
|
675
|
+
return new Quad(this.ul.transform(matrix), this.ur.transform(matrix), this.ll.transform(matrix), this.lr.transform(matrix));
|
|
676
|
+
}
|
|
677
|
+
/** Get the bounding rectangle */
|
|
678
|
+
get bounds() {
|
|
679
|
+
return new Rect(Math.min(this.ul.x, this.ur.x, this.ll.x, this.lr.x), Math.min(this.ul.y, this.ur.y, this.ll.y, this.lr.y), Math.max(this.ul.x, this.ur.x, this.ll.x, this.lr.x), Math.max(this.ul.y, this.ur.y, this.ll.y, this.lr.y));
|
|
680
|
+
}
|
|
681
|
+
/** Check if a point is inside the quad */
|
|
682
|
+
containsPoint(p) {
|
|
683
|
+
const px = p.x;
|
|
684
|
+
const py = p.y;
|
|
685
|
+
// Fast bounding box early-exit (avoids expensive cross products for ~90% of cases)
|
|
686
|
+
const minX = Math.min(this.ul.x, this.ur.x, this.ll.x, this.lr.x);
|
|
687
|
+
const maxX = Math.max(this.ul.x, this.ur.x, this.ll.x, this.lr.x);
|
|
688
|
+
const minY = Math.min(this.ul.y, this.ur.y, this.ll.y, this.lr.y);
|
|
689
|
+
const maxY = Math.max(this.ul.y, this.ur.y, this.ll.y, this.lr.y);
|
|
690
|
+
if (px < minX || px > maxX || py < minY || py > maxY) {
|
|
691
|
+
return false;
|
|
692
|
+
}
|
|
693
|
+
// For axis-aligned rectangles, the bounding box IS the quad
|
|
694
|
+
if (this.ul.x === this.ll.x &&
|
|
695
|
+
this.ur.x === this.lr.x &&
|
|
696
|
+
this.ul.y === this.ur.y &&
|
|
697
|
+
this.ll.y === this.lr.y) {
|
|
698
|
+
return true; // Already passed bounding box check
|
|
699
|
+
}
|
|
700
|
+
// Full cross product check for non-rectangular quads
|
|
701
|
+
// Inline cross product for performance (avoids function call overhead)
|
|
702
|
+
const ulx = this.ul.x, uly = this.ul.y;
|
|
703
|
+
const urx = this.ur.x, ury = this.ur.y;
|
|
704
|
+
const lrx = this.lr.x, lry = this.lr.y;
|
|
705
|
+
const llx = this.ll.x, lly = this.ll.y;
|
|
706
|
+
// Check each edge: point must be on the "inside" (left) of all edges
|
|
707
|
+
const c1 = (urx - ulx) * (py - uly) - (ury - uly) * (px - ulx);
|
|
708
|
+
if (c1 < 0)
|
|
709
|
+
return false;
|
|
710
|
+
const c2 = (lrx - urx) * (py - ury) - (lry - ury) * (px - urx);
|
|
711
|
+
if (c2 < 0)
|
|
712
|
+
return false;
|
|
713
|
+
const c3 = (llx - lrx) * (py - lry) - (lly - lry) * (px - lrx);
|
|
714
|
+
if (c3 < 0)
|
|
715
|
+
return false;
|
|
716
|
+
const c4 = (ulx - llx) * (py - lly) - (uly - lly) * (px - llx);
|
|
717
|
+
if (c4 < 0)
|
|
718
|
+
return false;
|
|
719
|
+
return true;
|
|
720
|
+
}
|
|
721
|
+
/** Check if this is a valid quad (non-self-intersecting) */
|
|
722
|
+
get isValid() {
|
|
723
|
+
// A simple check: all cross products should have the same sign
|
|
724
|
+
const cross = (p1, p2, p3) => {
|
|
725
|
+
return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);
|
|
726
|
+
};
|
|
727
|
+
const c1 = cross(this.ul, this.ur, this.lr);
|
|
728
|
+
const c2 = cross(this.ur, this.lr, this.ll);
|
|
729
|
+
const c3 = cross(this.lr, this.ll, this.ul);
|
|
730
|
+
const c4 = cross(this.ll, this.ul, this.ur);
|
|
731
|
+
return (c1 >= 0 && c2 >= 0 && c3 >= 0 && c4 >= 0) || (c1 <= 0 && c2 <= 0 && c3 <= 0 && c4 <= 0);
|
|
732
|
+
}
|
|
733
|
+
toString() {
|
|
734
|
+
return `Quad(${this.ul}, ${this.ur}, ${this.ll}, ${this.lr})`;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* An RGBA color
|
|
739
|
+
*/
|
|
740
|
+
export class Color {
|
|
741
|
+
r;
|
|
742
|
+
g;
|
|
743
|
+
b;
|
|
744
|
+
a;
|
|
745
|
+
constructor(r, g, b, a = 1.0) {
|
|
746
|
+
this.r = Math.max(0, Math.min(1, r));
|
|
747
|
+
this.g = Math.max(0, Math.min(1, g));
|
|
748
|
+
this.b = Math.max(0, Math.min(1, b));
|
|
749
|
+
this.a = Math.max(0, Math.min(1, a));
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Create color from color-like object
|
|
753
|
+
*/
|
|
754
|
+
static from(c) {
|
|
755
|
+
if (c instanceof Color) {
|
|
756
|
+
return c;
|
|
757
|
+
}
|
|
758
|
+
if (Array.isArray(c)) {
|
|
759
|
+
return new Color(c[0], c[1], c[2], c[3]);
|
|
760
|
+
}
|
|
761
|
+
return new Color(c.r, c.g, c.b, c.a);
|
|
762
|
+
}
|
|
763
|
+
/** Black color */
|
|
764
|
+
static BLACK = new Color(0, 0, 0);
|
|
765
|
+
/** White color */
|
|
766
|
+
static WHITE = new Color(1, 1, 1);
|
|
767
|
+
/** Red color */
|
|
768
|
+
static RED = new Color(1, 0, 0);
|
|
769
|
+
/** Green color */
|
|
770
|
+
static GREEN = new Color(0, 1, 0);
|
|
771
|
+
/** Blue color */
|
|
772
|
+
static BLUE = new Color(0, 0, 1);
|
|
773
|
+
/**
|
|
774
|
+
* Get as array [r, g, b, a]
|
|
775
|
+
*/
|
|
776
|
+
toArray() {
|
|
777
|
+
return [this.r, this.g, this.b, this.a];
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
//# sourceMappingURL=geometry.js.map
|