@contrail/documents 1.20.0-alpha.5014a52 → 1.20.0-alpha.d5bd4fa
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/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,7 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
12
12
|
- `MaskDefinition` and `MaskShapeKey` on `DocumentElement` — `maskDefinition` records that an image is masked into one of nine preset shapes, with an optional clockwise `rotation`. Its presence changes how `cropDefinition`'s percents are read: element-space (the mask window within the element) instead of the source-image crop they otherwise mean. Anything deriving image geometry must check `hasShapeMask` before treating a crop as a source crop — reading one as the other samples the wrong region of the bitmap.
|
|
13
13
|
- `@contrail/documents/util/mask` — the shared mask model, exported from the package root: the nine shapes as renderer-agnostic cubic path segments (`getMaskShapeSegments`), `rotatedRectAABB` for the bounds a tilted shape actually occupies, `rotatePoint`, and the mask-rect/percent conversions, so exporters and the canvas cannot drift apart. Segments are cubic-only because cubics survive affine maps exactly, letting each consumer render them however it draws — `Path2D` in a browser, an SVG composite in a service.
|
|
14
14
|
- `getMaskBakeGeometry`, `getMaskBakeLayout` and `maskShapeSegmentsToSvgPath` — the bake inputs a consumer needs to flatten a mask into a bitmap, and an SVG serializer for renderers that go through SVG rather than a canvas path. The layout scales to the source bitmap's own resolution rather than the element's on-board size, so a shrunk image does not bake at reduced detail, and re-bases a rotated mask onto its own bounding box. Only the rasterizer stays per-consumer: `Path2D` in a browser, an SVG composite in a service.
|
|
15
|
+
- `hasShapeMask` is a type guard and the complete discriminator: it requires a shape key the renderer knows and all four crop percents, so an origin of `0` passes while a missing origin (previously multiplied into `NaN` by `cropDefinitionToMaskRect`) and an unknown shape (previously thrown on by `getMaskShapeSegments`) are rejected up front. The true branch narrows the percents to numbers.
|
|
15
16
|
|
|
16
17
|
## [1.18.0] - 2026-09-10
|
|
17
18
|
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import { CropDefinition, DocumentElement, SizeDefinition } from '../../types';
|
|
1
|
+
import { CropDefinition, DocumentElement, MaskDefinition, SizeDefinition } from '../../types';
|
|
2
2
|
import { MaskRect, MaskShapeKey } from './mask-shape-geometry';
|
|
3
|
-
export
|
|
3
|
+
export type MaskCropDefinition = CropDefinition & Required<Pick<CropDefinition, 'x1Percent' | 'y1Percent' | 'widthPercent' | 'heightPercent'>>;
|
|
4
|
+
export type ShapeMaskedElement = DocumentElement & {
|
|
5
|
+
maskDefinition: MaskDefinition & {
|
|
6
|
+
shape: MaskShapeKey;
|
|
7
|
+
};
|
|
8
|
+
cropDefinition: MaskCropDefinition;
|
|
9
|
+
};
|
|
10
|
+
export declare function hasShapeMask(element: DocumentElement): element is ShapeMaskedElement;
|
|
4
11
|
export declare function getShapeMaskKey(element: DocumentElement): MaskShapeKey | null;
|
|
5
12
|
export declare function getShapeMaskRotation(element: DocumentElement): number;
|
|
6
13
|
export declare function normalizeMaskRotation(rotation: number): number;
|
|
@@ -9,10 +9,19 @@ exports.isShapeMaskable = isShapeMaskable;
|
|
|
9
9
|
exports.getDefaultShapeMaskCrop = getDefaultShapeMaskCrop;
|
|
10
10
|
exports.cropDefinitionToMaskRect = cropDefinitionToMaskRect;
|
|
11
11
|
exports.maskRectToCropDefinition = maskRectToCropDefinition;
|
|
12
|
+
const mask_shape_geometry_1 = require("./mask-shape-geometry");
|
|
12
13
|
const DEFAULT_MASK_FRACTION = 0.72;
|
|
13
14
|
function hasShapeMask(element) {
|
|
14
|
-
var _a
|
|
15
|
-
|
|
15
|
+
var _a;
|
|
16
|
+
const shape = (_a = element === null || element === void 0 ? void 0 : element.maskDefinition) === null || _a === void 0 ? void 0 : _a.shape;
|
|
17
|
+
if (!shape || !mask_shape_geometry_1.MASK_SHAPE_KEYS.includes(shape)) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
const crop = element === null || element === void 0 ? void 0 : element.cropDefinition;
|
|
21
|
+
return (Number.isFinite(crop === null || crop === void 0 ? void 0 : crop.x1Percent) &&
|
|
22
|
+
Number.isFinite(crop === null || crop === void 0 ? void 0 : crop.y1Percent) &&
|
|
23
|
+
crop.widthPercent > 0 &&
|
|
24
|
+
crop.heightPercent > 0);
|
|
16
25
|
}
|
|
17
26
|
function getShapeMaskKey(element) {
|
|
18
27
|
var _a, _b;
|