@oim-media/spec 1.27.8 → 1.27.10

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.
Files changed (64) hide show
  1. package/BINARY_SPEC.md +190 -186
  2. package/CANONICAL_SPEC.md +409 -409
  3. package/LICENSE +55 -55
  4. package/NOTICE +6 -6
  5. package/README.md +458 -444
  6. package/action-cases.json +13 -13
  7. package/artistic-text-cases.json +690 -690
  8. package/canonical-cases.json +6 -0
  9. package/keyframe-cases.json +32 -32
  10. package/keys.json +22 -22
  11. package/marks-cases.json +34 -34
  12. package/package.json +2 -1
  13. package/pattern-cases.json +552 -552
  14. package/schema/oim.schema.json +2920 -2920
  15. package/schema/oim2.schema.json +2763 -0
  16. package/schema/ovm.schema.json +2701 -2701
  17. package/text-effect-cases.json +835 -835
  18. package/tools/parity-core.mjs +122 -122
  19. package/tools/parity.mjs +86 -86
  20. package/vectors/README.md +105 -103
  21. package/vectors/accessibility.expected.json +67 -67
  22. package/vectors/artistic-text.expected.json +84 -84
  23. package/vectors/asymmetric-borders.expected.json +29 -29
  24. package/vectors/background-pattern-order.expected.json +95 -95
  25. package/vectors/basic-text.expected.json +29 -29
  26. package/vectors/color-blending-opacity.expected.json +47 -47
  27. package/vectors/crop.expected.json +32 -32
  28. package/vectors/embedded-font-woff.expected.json +57 -57
  29. package/vectors/extreme-aspect-ratios.expected.json +29 -29
  30. package/vectors/filter-effects.expected.json +33 -33
  31. package/vectors/flip.expected.json +47 -47
  32. package/vectors/frame-shapes.expected.json +73 -73
  33. package/vectors/full-monty-composite.expected.json +96 -96
  34. package/vectors/golden/exceptions.json +3 -3
  35. package/vectors/golden/mask-window.web.png +0 -0
  36. package/vectors/golden/zone-group.web.png +0 -0
  37. package/vectors/groups-and-parallax.expected.json +90 -90
  38. package/vectors/image-fill.expected.json +54 -54
  39. package/vectors/interactive-chained-actions.expected.json +77 -77
  40. package/vectors/interactive-hover.expected.json +36 -36
  41. package/vectors/interactive.expected.json +121 -121
  42. package/vectors/layer-blur.expected.json +48 -48
  43. package/vectors/layer-grain.expected.json +52 -52
  44. package/vectors/layer-ordering-zindex.expected.json +62 -62
  45. package/vectors/legacy-text-chunk.expected.json +29 -29
  46. package/vectors/mask-window.expected.json +45 -0
  47. package/vectors/mask-window.oim.png +0 -0
  48. package/vectors/media-filters.expected.json +50 -50
  49. package/vectors/multi-container-layout.expected.json +45 -45
  50. package/vectors/multilang-cjk-rtl.expected.json +30 -30
  51. package/vectors/nested-groups.expected.json +68 -68
  52. package/vectors/palettes.expected.json +57 -57
  53. package/vectors/parallax-infinite.expected.json +39 -39
  54. package/vectors/pattern-color-roles.expected.json +68 -68
  55. package/vectors/reedit-english.expected.json +45 -45
  56. package/vectors/reveal-and-play.expected.json +107 -107
  57. package/vectors/shadow-effects.expected.json +34 -34
  58. package/vectors/shape-shadows.expected.json +62 -62
  59. package/vectors/strokes-and-borders.expected.json +31 -31
  60. package/vectors/text-runs-precalculated.expected.json +46 -46
  61. package/vectors/transparent-background.expected.json +30 -30
  62. package/vectors/typography-styling.expected.json +34 -34
  63. package/vectors/zone-group.expected.json +46 -0
  64. package/vectors/zone-group.oim.png +0 -0
package/vectors/README.md CHANGED
@@ -1,103 +1,105 @@
1
- # Conformance vectors
2
-
3
- Each vector is a real `.oim` with the result that a reader must produce when
4
- opening it. The JSON Schema in `../schema/` says what **shape** a `.oim` has;
5
- this says what **result** comes out of a specific one.
6
-
7
- ```
8
- <name>.oim.png the file, signed, exactly as the system produces it
9
- <name>.expected.json what a conforming reader must extract from it
10
- ```
11
-
12
- ## The Normative Vectors
13
-
14
- A reduced suite cannot tell apart an implementation that **reads the format**
15
- from one that **gets a simple case right by chance**. These 37 vectors cover the
16
- initial 20-vector matrix plus every capability added since contract 1.10.0:
17
-
18
- | # | Vector | What it covers |
19
- |---|---|---|
20
- | 1 | `basic-text` | The minimum: PNG container, `zTXt` chunk, zlib, two languages, geometry in `cqw` |
21
- | 2 | `groups-and-parallax` | Simple hierarchy (`childIds` / `groupId`) and depth (`parallax`) |
22
- | 3 | `interactive` | `isInteractive`, `states.active.actions`, per-side corners and `min_player` |
23
- | 4 | `multilang-cjk-rtl` | Complex multilingual coverage: Spanish, Japanese (CJK: `こんにちは世界`) and Arabic (RTL: `مرحبا بالعالم`) |
24
- | 5 | `typography-styling` | Advanced typography: `fontFamily`, `fontWeight`, `fontStyle: "italic"`, `textTransform`, `letterSpacing`, `lineHeight` |
25
- | 6 | `nested-groups` | Multi-level hierarchy: a root group containing a subgroup with child elements |
26
- | 7 | `asymmetric-borders` | Independent corner radii per corner (`borderRadius: "10px 25px 50px 0px"`) |
27
- | 8 | `shadow-effects` | Shadow system: `shadowEnabled`, `shadowColor`, `shadowBlur`, `shadowOffsetX`, `shadowOffsetY`, `shadowOpacity` |
28
- | 9 | `color-blending-opacity` | Visual composition: layer opacity (`opacity: 70`) and blend modes (`blendMode: "multiply"`) |
29
- | 10 | `strokes-and-borders` | Vector stroke and outlines: `borderWidth`, `borderColor`, `strokeStyle: "dashed"` |
30
- | 11 | `parallax-infinite` | Continuous horizontal looping parallax effect (`mode: "infinite_horizontal"`, `speed_px_sec`, `direction`) |
31
- | 12 | `interactive-hover` | Cursor interactive state: `states.hover` with `scale`, `rotation`, `opacity` |
32
- | 13 | `interactive-chained-actions` | Several interactive actions chained when a layer is activated (`toggle`, `hide`) |
33
- | 14 | `filter-effects` | CSS visual filters: `filterBlur`, `filterBrightness`, `filterContrast`, `filterSaturate`, `filterHueRotate` |
34
- | 15 | `text-runs-precalculated` | Precalculated layout for native non-web renderers (`textRuns` with `lines`, `width`, `yOffset`) |
35
- | 16 | `multi-container-layout` | Several `container` slots organising the spatial layout of the document |
36
- | 17 | `extreme-aspect-ratios` | Ultra-wide panoramic canvas (`1600x400`, 4:1 ratio) testing container consistency |
37
- | 18 | `transparent-background` | Strictly transparent background (`fillColor: "transparent"`) under the normative colour rule |
38
- | 19 | `layer-ordering-zindex` | Strict stacking sequence with slots overlapping at identical coordinates |
39
- | 20 | `full-monty-composite` | Comprehensive master document combining multilingual content, active/hover interactivity, groups, parallax and shadows |
40
- | 21 | `legacy-text-chunk` | The same document as `basic-text` in the legacy container: a `tEXt` chunk with base64 of raw deflate |
41
- | 22 | `layer-blur` | Layer blur (`layerBlur`) on the style of a text and of a shape |
42
- | 23 | `layer-grain` | Per-layer grain (contract 1.10.0): `grain`, `grainIntensity`, `grainSize` and `grainBlend` |
43
- | 24 | `flip` | Layer flip (contract 1.14.0): `flipX` and `flipY` on rotated shapes |
44
- | 25 | `crop` | Image crop (contract 1.15.0): `imageCrop` framing an image at x 20 %, y 70 % and zoom 2 |
45
- | 26 | `accessibility` | Accessibility (contract 1.16.0): document `description`, per-language `alt` and `decorative` |
46
- | 27 | `image-fill` | Image fill (contract 1.17.0): shapes filled with an embedded photo and `fillImageCrop` |
47
- | 28 | `media-filters` | Media filters (contract 1.18.0): `filterPreset` on a photo and on a circular frame with blur and stroke |
48
- | 29 | `frame-shapes` | Frame shapes (contract 1.19.0): a cloud, a custom SVG path (`svgViewBox`) and a star with a flipped photo |
49
- | 30 | `palettes` | Named palettes (contract 1.20.0): `dark` and `light`, `defaultPalette: "dark"`, and colour roles |
50
- | 31 | `pattern-color-roles` | Colour roles in patterns and shadows (contract 1.21.0) |
51
- | 32 | `reveal-and-play` | Per-layer reveal and the `play` action (contract 1.22.0) |
52
- | 33 | `reedit-english` | Re-edit permission in English (contract 1.23.0): `reedit: "public"`, signed by the production service |
53
- | 34 | `embedded-font-woff` | Embedded font (contract 1.27.0): Inter bold as a static WOFF subset (`fonts[].format: "woff"`) |
54
- | 35 | `background-pattern-order` | A pattern background listed last still paints under every layer; pattern tile size; unitless `letterSpacing` on centred text |
55
- | 36 | `shape-shadows` | Hard shadows on a circle and on a circular photo frame: the shadow follows the shape, not its box |
56
- | 37 | `artistic-text` | Artistic text (4.6): a curved 3D title with shaded extrusion, outer and inner strokes and a gradient, and a two-line word, drawn with the embedded Inter subset |
57
-
58
- ## How to use it from another language
59
-
60
- 1. Open the `.oim` as a PNG and look for the metadata chunk: `zTXt` (key `OIM_Data`; the one written since 29 Oct 2026), or `tEXt` / `iTXt` (keys `OIM_Data` or `OIM_JSON_DATA`).
61
- 2. Decompress the payload: if it comes in base64, decode it first; decompression is **raw deflate** (no zlib header, RFC 1951) or standard zlib.
62
- 3. Interpret the result as UTF-8 JSON: these are the document's metadata.
63
- 4. Compare with `<name>.expected.json`, ignoring its `description` field.
64
-
65
- What is compared is what two implementations can genuinely disagree on: the
66
- geometry **already normalised** to `cqw` or user units, the hierarchy, the depth,
67
- the typography and the declared interactivity. Not the whole metadata — a full
68
- dump breaks every time the compiler adds a field, and then it gets regenerated
69
- without a look, which is a vector that no longer checks anything.
70
-
71
- ## The signature
72
-
73
- All 37 vectors are signed with the public key published in `packages/spec/keys.json`.
74
- The signature covers the canonical serialisation
75
- of the metadata and the cryptographic hash of the pixels (`image_hash` over the `IDAT` chunks).
76
- A reader that verifies must rebuild that canonical form following the seven rules
77
- specified in the `README.md` at the root of `packages/spec`; one that only reads the format
78
- may ignore it, but then it must not claim to validate authorship.
79
-
80
- ## How they were generated
81
-
82
- The vectors are generated by Xue Studios' signing service, through the same
83
- production pipeline that signs every published `.oim`: the slots are normalised
84
- to `cqw`, the file is sanitised, signed and embedded. The generator is not part
85
- of this repository; the output is committed here as-is, so every implementation
86
- reads the same files.
87
-
88
- `interactive` is the exception: it comes from a real editor export, and that is
89
- why it carries things the normalisation pipeline alone does not produce.
90
-
91
- The base image weighs about 3 KB and is reused across vectors. A published
92
- `.oim` weighs megabytes because it carries its rasterised canvas inside; the
93
- image is not what these vectors check.
94
-
95
- ## Keeping them from rotting
96
-
97
- `packages/core/src/conformance-vectors.test.ts` runs them in every suite: if the
98
- reference implementation changes what it produces, the vectors fail. It is
99
- circular on purpose and in one direction — the reference defines the result, and
100
- the test prevents it from moving without the vectors moving with it.
101
-
102
- The day a second reader exists and disagrees, there is a concrete file to discuss
103
- instead of two opinions.
1
+ # Conformance vectors
2
+
3
+ Each vector is a real `.oim` with the result that a reader must produce when
4
+ opening it. The JSON Schema in `../schema/` says what **shape** a `.oim` has;
5
+ this says what **result** comes out of a specific one.
6
+
7
+ ```
8
+ <name>.oim.png the file, signed, exactly as the system produces it
9
+ <name>.expected.json what a conforming reader must extract from it
10
+ ```
11
+
12
+ ## The Normative Vectors
13
+
14
+ A reduced suite cannot tell apart an implementation that **reads the format**
15
+ from one that **gets a simple case right by chance**. These 39 vectors cover the
16
+ initial 20-vector matrix plus every capability added since contract 1.10.0:
17
+
18
+ | # | Vector | What it covers |
19
+ |---|---|---|
20
+ | 1 | `basic-text` | The minimum: PNG container, `zTXt` chunk, zlib, two languages, geometry in `cqw` |
21
+ | 2 | `groups-and-parallax` | Simple hierarchy (`childIds` / `groupId`) and depth (`parallax`) |
22
+ | 3 | `interactive` | `isInteractive`, `states.active.actions`, per-side corners and `min_player` |
23
+ | 4 | `multilang-cjk-rtl` | Complex multilingual coverage: Spanish, Japanese (CJK: `こんにちは世界`) and Arabic (RTL: `مرحبا بالعالم`) |
24
+ | 5 | `typography-styling` | Advanced typography: `fontFamily`, `fontWeight`, `fontStyle: "italic"`, `textTransform`, `letterSpacing`, `lineHeight` |
25
+ | 6 | `nested-groups` | Multi-level hierarchy: a root group containing a subgroup with child elements |
26
+ | 7 | `asymmetric-borders` | Independent corner radii per corner (`borderRadius: "10px 25px 50px 0px"`) |
27
+ | 8 | `shadow-effects` | Shadow system: `shadowEnabled`, `shadowColor`, `shadowBlur`, `shadowOffsetX`, `shadowOffsetY`, `shadowOpacity` |
28
+ | 9 | `color-blending-opacity` | Visual composition: layer opacity (`opacity: 70`) and blend modes (`blendMode: "multiply"`) |
29
+ | 10 | `strokes-and-borders` | Vector stroke and outlines: `borderWidth`, `borderColor`, `strokeStyle: "dashed"` |
30
+ | 11 | `parallax-infinite` | Continuous horizontal looping parallax effect (`mode: "infinite_horizontal"`, `speed_px_sec`, `direction`) |
31
+ | 12 | `interactive-hover` | Cursor interactive state: `states.hover` with `scale`, `rotation`, `opacity` |
32
+ | 13 | `interactive-chained-actions` | Several interactive actions chained when a layer is activated (`toggle`, `hide`) |
33
+ | 14 | `filter-effects` | CSS visual filters: `filterBlur`, `filterBrightness`, `filterContrast`, `filterSaturate`, `filterHueRotate` |
34
+ | 15 | `text-runs-precalculated` | Precalculated layout for native non-web renderers (`textRuns` with `lines`, `width`, `yOffset`) |
35
+ | 16 | `multi-container-layout` | Several `container` slots organising the spatial layout of the document |
36
+ | 17 | `extreme-aspect-ratios` | Ultra-wide panoramic canvas (`1600x400`, 4:1 ratio) testing container consistency |
37
+ | 18 | `transparent-background` | Strictly transparent background (`fillColor: "transparent"`) under the normative colour rule |
38
+ | 19 | `layer-ordering-zindex` | Strict stacking sequence with slots overlapping at identical coordinates |
39
+ | 20 | `full-monty-composite` | Comprehensive master document combining multilingual content, active/hover interactivity, groups, parallax and shadows |
40
+ | 21 | `legacy-text-chunk` | The same document as `basic-text` in the legacy container: a `tEXt` chunk with base64 of raw deflate |
41
+ | 22 | `layer-blur` | Layer blur (`layerBlur`) on the style of a text and of a shape |
42
+ | 23 | `layer-grain` | Per-layer grain (contract 1.10.0): `grain`, `grainIntensity`, `grainSize` and `grainBlend` |
43
+ | 24 | `flip` | Layer flip (contract 1.14.0): `flipX` and `flipY` on rotated shapes |
44
+ | 25 | `crop` | Image crop (contract 1.15.0): `imageCrop` framing an image at x 20 %, y 70 % and zoom 2 |
45
+ | 26 | `accessibility` | Accessibility (contract 1.16.0): document `description`, per-language `alt` and `decorative` |
46
+ | 27 | `image-fill` | Image fill (contract 1.17.0): shapes filled with an embedded photo and `fillImageCrop` |
47
+ | 28 | `media-filters` | Media filters (contract 1.18.0): `filterPreset` on a photo and on a circular frame with blur and stroke |
48
+ | 29 | `frame-shapes` | Frame shapes (contract 1.19.0): a cloud, a custom SVG path (`svgViewBox`) and a star with a flipped photo |
49
+ | 30 | `palettes` | Named palettes (contract 1.20.0): `dark` and `light`, `defaultPalette: "dark"`, and colour roles |
50
+ | 31 | `pattern-color-roles` | Colour roles in patterns and shadows (contract 1.21.0) |
51
+ | 32 | `reveal-and-play` | Per-layer reveal and the `play` action (contract 1.22.0) |
52
+ | 33 | `reedit-english` | Re-edit permission in English (contract 1.23.0): `reedit: "public"`, signed by the production service |
53
+ | 34 | `embedded-font-woff` | Embedded font (contract 1.27.0): Inter bold as a static WOFF subset (`fonts[].format: "woff"`) |
54
+ | 35 | `background-pattern-order` | A pattern background listed last still paints under every layer; pattern tile size; unitless `letterSpacing` on centred text |
55
+ | 36 | `shape-shadows` | Hard shadows on a circle and on a circular photo frame: the shadow follows the shape, not its box |
56
+ | 37 | `artistic-text` | Artistic text (4.6): a curved 3D title with shaded extrusion, outer and inner strokes and a gradient, and a two-line word, drawn with the embedded Inter subset |
57
+ | 38 | `zone-group` | A 1.x zone becomes a 2.0 group: background, corners and backdrop blur kept; its layers keep their own x/y, the flex flow is retired (Decision 14 Nov) |
58
+ | 39 | `mask-window` | A window mask: a circle cut out of a dark cover with a white outline |
59
+
60
+ ## How to use it from another language
61
+
62
+ 1. Open the `.oim` as a PNG and look for the metadata chunk: `zTXt` (key `OIM_Data`; the one written since 29 Oct 2026), or `tEXt` / `iTXt` (keys `OIM_Data` or `OIM_JSON_DATA`).
63
+ 2. Decompress the payload: if it comes in base64, decode it first; decompression is **raw deflate** (no zlib header, RFC 1951) or standard zlib.
64
+ 3. Interpret the result as UTF-8 JSON: these are the document's metadata.
65
+ 4. Compare with `<name>.expected.json`, ignoring its `description` field.
66
+
67
+ What is compared is what two implementations can genuinely disagree on: the
68
+ geometry **already normalised** to `cqw` or user units, the hierarchy, the depth,
69
+ the typography and the declared interactivity. Not the whole metadata — a full
70
+ dump breaks every time the compiler adds a field, and then it gets regenerated
71
+ without a look, which is a vector that no longer checks anything.
72
+
73
+ ## The signature
74
+
75
+ All 39 vectors are signed with the public key published in `packages/spec/keys.json`.
76
+ The signature covers the canonical serialisation
77
+ of the metadata and the cryptographic hash of the pixels (`image_hash` over the `IDAT` chunks).
78
+ A reader that verifies must rebuild that canonical form following the seven rules
79
+ specified in the `README.md` at the root of `packages/spec`; one that only reads the format
80
+ may ignore it, but then it must not claim to validate authorship.
81
+
82
+ ## How they were generated
83
+
84
+ The vectors are generated by Xue Studios' signing service, through the same
85
+ production pipeline that signs every published `.oim`: the slots are normalised
86
+ to `cqw`, the file is sanitised, signed and embedded. The generator is not part
87
+ of this repository; the output is committed here as-is, so every implementation
88
+ reads the same files.
89
+
90
+ `interactive` is the exception: it comes from a real editor export, and that is
91
+ why it carries things the normalisation pipeline alone does not produce.
92
+
93
+ The base image weighs about 3 KB and is reused across vectors. A published
94
+ `.oim` weighs megabytes because it carries its rasterised canvas inside; the
95
+ image is not what these vectors check.
96
+
97
+ ## Keeping them from rotting
98
+
99
+ `packages/core/src/conformance-vectors.test.ts` runs them in every suite: if the
100
+ reference implementation changes what it produces, the vectors fail. It is
101
+ circular on purpose and in one direction — the reference defines the result, and
102
+ the test prevents it from moving without the vectors moving with it.
103
+
104
+ The day a second reader exists and disagrees, there is a concrete file to discuss
105
+ instead of two opinions.
@@ -1,67 +1,67 @@
1
- {
2
- "description": "Accessibility (contract 1.16.0): the work's `description`, a per-language `alt` on an image and `decorative` on a shape.",
3
- "canvas": {
4
- "natural_height": 600,
5
- "natural_width": 800
6
- },
7
- "signed": true,
8
- "key_version": "v1",
9
- "slots": [
10
- {
11
- "id": "titulo",
12
- "type": "text",
13
- "position": [
14
- 10,
15
- 6.6667
16
- ],
17
- "name": "Titulo",
18
- "content": {
19
- "en": "Hello",
20
- "es": "Hola"
21
- },
22
- "style": {
23
- "width": "62.5cqw",
24
- "height": "10.0cqw",
25
- "fontSize": "5.0cqw"
26
- }
27
- },
28
- {
29
- "id": "foto",
30
- "type": "image",
31
- "position": [
32
- 12.5,
33
- 26.6667
34
- ],
35
- "name": "Foto",
36
- "content": {
37
- "*": "https://cdn.oim.media/demos/crop.png"
38
- },
39
- "style": {
40
- "width": "37.5cqw",
41
- "height": "25.0cqw",
42
- "alt": {
43
- "en": "A fjord between mountains",
44
- "es": "Un fiordo entre montañas"
45
- }
46
- }
47
- },
48
- {
49
- "id": "adorno",
50
- "type": "geo",
51
- "position": [
52
- 65,
53
- 26.6667
54
- ],
55
- "name": "Adorno",
56
- "content": {
57
- "es": ""
58
- },
59
- "style": {
60
- "width": "25.0cqw",
61
- "height": "25.0cqw",
62
- "fillColor": "#264653",
63
- "decorative": true
64
- }
65
- }
66
- ]
67
- }
1
+ {
2
+ "description": "Accessibility (contract 1.16.0): the work's `description`, a per-language `alt` on an image and `decorative` on a shape.",
3
+ "canvas": {
4
+ "natural_height": 600,
5
+ "natural_width": 800
6
+ },
7
+ "signed": true,
8
+ "key_version": "v1",
9
+ "slots": [
10
+ {
11
+ "id": "titulo",
12
+ "type": "text",
13
+ "position": [
14
+ 10,
15
+ 6.6667
16
+ ],
17
+ "name": "Titulo",
18
+ "content": {
19
+ "en": "Hello",
20
+ "es": "Hola"
21
+ },
22
+ "style": {
23
+ "width": "62.5cqw",
24
+ "height": "10.0cqw",
25
+ "fontSize": "5.0cqw"
26
+ }
27
+ },
28
+ {
29
+ "id": "foto",
30
+ "type": "image",
31
+ "position": [
32
+ 12.5,
33
+ 26.6667
34
+ ],
35
+ "name": "Foto",
36
+ "content": {
37
+ "*": "https://cdn.oim.media/demos/crop.png"
38
+ },
39
+ "style": {
40
+ "width": "37.5cqw",
41
+ "height": "25.0cqw",
42
+ "alt": {
43
+ "en": "A fjord between mountains",
44
+ "es": "Un fiordo entre montañas"
45
+ }
46
+ }
47
+ },
48
+ {
49
+ "id": "adorno",
50
+ "type": "geo",
51
+ "position": [
52
+ 65,
53
+ 26.6667
54
+ ],
55
+ "name": "Adorno",
56
+ "content": {
57
+ "es": ""
58
+ },
59
+ "style": {
60
+ "width": "25.0cqw",
61
+ "height": "25.0cqw",
62
+ "fillColor": "#264653",
63
+ "decorative": true
64
+ }
65
+ }
66
+ ]
67
+ }
@@ -1,84 +1,84 @@
1
- {
2
- "description": "Artistic text (4.6): a curved 3D title with shaded extrusion, outer and inner strokes and a built-in gradient, and a second two-line word with no curve. Inter bold embedded (the embedded-font-woff subset), so every reader draws the same glyphs.",
3
- "canvas": {
4
- "natural_height": 600,
5
- "natural_width": 800
6
- },
7
- "signed": true,
8
- "key_version": "v1",
9
- "reedit": "author_only",
10
- "fonts": [
11
- {
12
- "family": "Inter",
13
- "name": "oim-26dd479f-Inter",
14
- "weight": 700,
15
- "style": "normal",
16
- "format": "woff"
17
- }
18
- ],
19
- "slots": [
20
- {
21
- "id": "retro-title",
22
- "type": "artistic-text",
23
- "position": [
24
- 0,
25
- 10
26
- ],
27
- "name": "Retro title",
28
- "content": {
29
- "es": "Fuente"
30
- },
31
- "style": {
32
- "width": "100.0cqw",
33
- "height": "27.5cqw",
34
- "fontSize": "15.0cqw",
35
- "fillColor": "#f9a8d4",
36
- "fontFamily": "Inter",
37
- "fontWeight": "700",
38
- "lineHeight": 1.25,
39
- "artisticPreset": "retro-wave-3d",
40
- "extrusionDepth": 18,
41
- "extrusionAngle": 45,
42
- "extrusionColor": "#DB2777",
43
- "extrusionShading": true,
44
- "curveAmount": 60,
45
- "curveType": "arc",
46
- "outerStrokeColor": "#1e1b4b",
47
- "outerStrokeWidth": 4,
48
- "innerStrokeColor": "#ffffff",
49
- "innerStrokeWidth": 1,
50
- "textGradientType": "sunset-gold"
51
- }
52
- },
53
- {
54
- "id": "two-lines",
55
- "type": "artistic-text",
56
- "position": [
57
- 25,
58
- 56.6667
59
- ],
60
- "name": "Two lines",
61
- "content": {
62
- "es": "ciudad\nsur"
63
- },
64
- "style": {
65
- "width": "50.0cqw",
66
- "height": "25.0cqw",
67
- "fontSize": "8.0cqw",
68
- "fillColor": "#fde047",
69
- "fontFamily": "Inter",
70
- "fontWeight": "700",
71
- "lineHeight": 1.25,
72
- "artisticPreset": "custom",
73
- "extrusionDepth": 10,
74
- "extrusionAngle": 135,
75
- "extrusionColor": "#7c2d12",
76
- "extrusionShading": false,
77
- "curveAmount": 0,
78
- "curveType": "arc",
79
- "outerStrokeColor": "#000000",
80
- "outerStrokeWidth": 2
81
- }
82
- }
83
- ]
84
- }
1
+ {
2
+ "description": "Artistic text (4.6): a curved 3D title with shaded extrusion, outer and inner strokes and a built-in gradient, and a second two-line word with no curve. Inter bold embedded (the embedded-font-woff subset), so every reader draws the same glyphs.",
3
+ "canvas": {
4
+ "natural_height": 600,
5
+ "natural_width": 800
6
+ },
7
+ "signed": true,
8
+ "key_version": "v1",
9
+ "reedit": "author_only",
10
+ "fonts": [
11
+ {
12
+ "family": "Inter",
13
+ "name": "oim-26dd479f-Inter",
14
+ "weight": 700,
15
+ "style": "normal",
16
+ "format": "woff"
17
+ }
18
+ ],
19
+ "slots": [
20
+ {
21
+ "id": "retro-title",
22
+ "type": "artistic-text",
23
+ "position": [
24
+ 0,
25
+ 10
26
+ ],
27
+ "name": "Retro title",
28
+ "content": {
29
+ "es": "Fuente"
30
+ },
31
+ "style": {
32
+ "width": "100.0cqw",
33
+ "height": "27.5cqw",
34
+ "fontSize": "15.0cqw",
35
+ "fillColor": "#f9a8d4",
36
+ "fontFamily": "Inter",
37
+ "fontWeight": "700",
38
+ "lineHeight": 1.25,
39
+ "artisticPreset": "retro-wave-3d",
40
+ "extrusionDepth": 18,
41
+ "extrusionAngle": 45,
42
+ "extrusionColor": "#DB2777",
43
+ "extrusionShading": true,
44
+ "curveAmount": 60,
45
+ "curveType": "arc",
46
+ "outerStrokeColor": "#1e1b4b",
47
+ "outerStrokeWidth": 4,
48
+ "innerStrokeColor": "#ffffff",
49
+ "innerStrokeWidth": 1,
50
+ "textGradientType": "sunset-gold"
51
+ }
52
+ },
53
+ {
54
+ "id": "two-lines",
55
+ "type": "artistic-text",
56
+ "position": [
57
+ 25,
58
+ 56.6667
59
+ ],
60
+ "name": "Two lines",
61
+ "content": {
62
+ "es": "ciudad\nsur"
63
+ },
64
+ "style": {
65
+ "width": "50.0cqw",
66
+ "height": "25.0cqw",
67
+ "fontSize": "8.0cqw",
68
+ "fillColor": "#fde047",
69
+ "fontFamily": "Inter",
70
+ "fontWeight": "700",
71
+ "lineHeight": 1.25,
72
+ "artisticPreset": "custom",
73
+ "extrusionDepth": 10,
74
+ "extrusionAngle": 135,
75
+ "extrusionColor": "#7c2d12",
76
+ "extrusionShading": false,
77
+ "curveAmount": 0,
78
+ "curveType": "arc",
79
+ "outerStrokeColor": "#000000",
80
+ "outerStrokeWidth": 2
81
+ }
82
+ }
83
+ ]
84
+ }
@@ -1,29 +1,29 @@
1
- {
2
- "description": "Independent corner radii for each corner.",
3
- "canvas": {
4
- "natural_height": 600,
5
- "natural_width": 800
6
- },
7
- "signed": true,
8
- "key_version": "v1",
9
- "slots": [
10
- {
11
- "id": "caja_curva",
12
- "type": "geo",
13
- "position": [
14
- 12.5,
15
- 16.6667
16
- ],
17
- "name": "Caja Asimétrica",
18
- "content": {
19
- "es": ""
20
- },
21
- "style": {
22
- "width": "37.5cqw",
23
- "height": "18.75cqw",
24
- "borderRadius": "10px 25px 50px 0px",
25
- "fillColor": "#3b82f6"
26
- }
27
- }
28
- ]
29
- }
1
+ {
2
+ "description": "Independent corner radii for each corner.",
3
+ "canvas": {
4
+ "natural_height": 600,
5
+ "natural_width": 800
6
+ },
7
+ "signed": true,
8
+ "key_version": "v1",
9
+ "slots": [
10
+ {
11
+ "id": "caja_curva",
12
+ "type": "geo",
13
+ "position": [
14
+ 12.5,
15
+ 16.6667
16
+ ],
17
+ "name": "Caja Asimétrica",
18
+ "content": {
19
+ "es": ""
20
+ },
21
+ "style": {
22
+ "width": "37.5cqw",
23
+ "height": "18.75cqw",
24
+ "borderRadius": "10px 25px 50px 0px",
25
+ "fillColor": "#3b82f6"
26
+ }
27
+ }
28
+ ]
29
+ }