diff --git a/.github/workflows/check-generated-fbs.yml b/.github/workflows/check-generated-fbs.yml new file mode 100644 index 0000000000..348581ab8f --- /dev/null +++ b/.github/workflows/check-generated-fbs.yml @@ -0,0 +1,62 @@ +# ----------------------------------------------------------------- +# Freshness check for committed FlatBuffers bindings +# ----------------------------------------------------------------- +# +# Why this exists +# --------------- +# The Rust FlatBuffers bindings (`crates/grida-canvas/src/io/generated/grida.rs`) +# are committed to git so that `cargo build` works from a clean checkout without +# requiring `flatc`. However, because the file is generated from `format/grida.fbs`, +# it can become stale if someone edits the schema but forgets to regenerate. +# +# This workflow re-runs codegen and asserts that the committed file is identical +# to what `flatc` would produce. If it differs, the check fails with a clear +# error message telling the contributor how to fix it. +# +# When does it run +# ---------------- +# Only on PRs / pushes that touch the schema, the generated output, the codegen +# tooling, or the TS format package (which shares the same schema source). +# +# How to fix a failure +# -------------------- +# pnpm --filter @crates/grida-canvas generate +# git add crates/grida-canvas/src/io/generated/grida.rs +# git commit +# ----------------------------------------------------------------- + +name: check generated flatbuffers + +on: + push: + branches: + - main + pull_request: + paths: + - "format/grida.fbs" + - "crates/grida-canvas/src/io/generated/**" + - "packages/grida-format/src/**" + - "bin/activate-flatc" + +jobs: + rust-bindings: + name: rust fbs freshness + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Regenerate Rust FlatBuffers bindings + run: | + python3 bin/activate-flatc -- --rust \ + -o crates/grida-canvas/src/io/generated \ + format/grida.fbs + mv crates/grida-canvas/src/io/generated/grida_generated.rs \ + crates/grida-canvas/src/io/generated/grida.rs + + - name: Check for uncommitted changes + run: | + if ! git diff --exit-code crates/grida-canvas/src/io/generated/grida.rs; then + echo "::error::Generated Rust FlatBuffers bindings are stale. Run 'pnpm --filter @crates/grida-canvas generate' and commit the result." + exit 1 + fi diff --git a/Cargo.lock b/Cargo.lock index 6ba92a5f52..70e92a7cf6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -495,6 +495,7 @@ dependencies = [ "clap", "criterion", "figma-api", + "flatbuffers", "futures", "gl", "glutin", @@ -730,9 +731,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] @@ -1172,6 +1173,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "flatbuffers" +version = "25.12.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35f6839d7b3b98adde531effaf34f0c2badc6f4735d26fe74709d8e513a96ef3" +dependencies = [ + "bitflags 2.9.1", + "rustc_version", +] + [[package]] name = "flate2" version = "1.1.1" @@ -1574,6 +1585,7 @@ dependencies = [ "tokio", "toml 0.9.8", "winit", + "zip", ] [[package]] @@ -3653,6 +3665,15 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.38.44" @@ -3836,6 +3857,12 @@ dependencies = [ "to_shmem_derive", ] +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + [[package]] name = "serde" version = "1.0.226" @@ -4829,6 +4856,12 @@ dependencies = [ "core_maths", ] +[[package]] +name = "typed-path" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" + [[package]] name = "typenum" version = "1.18.0" @@ -5884,6 +5917,19 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "zip" +version = "8.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b680f2a0cd479b4cff6e1233c483fdead418106eae419dc60200ae9850f6d004" +dependencies = [ + "crc32fast", + "flate2", + "indexmap 2.11.4", + "memchr", + "typed-path", +] + [[package]] name = "zune-core" version = "0.4.12" diff --git a/bin/activate-flatc b/bin/activate-flatc index 74debc074b..4ee37f9fec 100644 --- a/bin/activate-flatc +++ b/bin/activate-flatc @@ -5,9 +5,10 @@ Grida: FlatBuffers compiler (flatc) bootstrapper Why this exists --------------- -We intentionally do NOT commit generated FlatBuffers bindings to git (see -`packages/grida-format/.gitignore`). The package build step runs `flatc` (see -`packages/grida-format/package.json`), so CI and Vercel builds must have a +Generated FlatBuffers bindings are committed for the Rust crate +(`crates/grida-canvas/src/io/generated/grida.rs`) so that `cargo build` works +from a clean checkout. The TypeScript package (`packages/grida-format`) +regenerates at build time. In both cases CI and Vercel builds need a deterministic way to obtain `flatc`. FlatBuffers does not ship `flatc` via npm, so this script installs a prebuilt diff --git a/crates/grida-canvas-wasm/example/demo.grida1 b/crates/grida-canvas-wasm/example/demo.grida1 index 9cc296743c..42877cfdf8 100644 --- a/crates/grida-canvas-wasm/example/demo.grida1 +++ b/crates/grida-canvas-wasm/example/demo.grida1 @@ -9889,5 +9889,5 @@ "main" ] }, - "version": "0.90.0-beta+20260108" + "version": "0.91.0-beta+20260311" } \ No newline at end of file diff --git a/crates/grida-canvas-wasm/example/gradient.grida1 b/crates/grida-canvas-wasm/example/gradient.grida1 index dd00e65a6c..f336470f86 100644 --- a/crates/grida-canvas-wasm/example/gradient.grida1 +++ b/crates/grida-canvas-wasm/example/gradient.grida1 @@ -1,5 +1,5 @@ { - "version": "0.90.0-beta+20260108", + "version": "0.91.0-beta+20260311", "document": { "nodes": { "gradient-rect": { diff --git a/crates/grida-canvas-wasm/example/rectangle.grida1 b/crates/grida-canvas-wasm/example/rectangle.grida1 index 2d4507033b..e084bb2848 100644 --- a/crates/grida-canvas-wasm/example/rectangle.grida1 +++ b/crates/grida-canvas-wasm/example/rectangle.grida1 @@ -1,5 +1,5 @@ { - "version": "0.90.0-beta+20260108", + "version": "0.91.0-beta+20260311", "document": { "nodes": { "rectangle": { diff --git a/crates/grida-canvas-wasm/lib/__test__/environment-node-raster-export.test.ts b/crates/grida-canvas-wasm/lib/__test__/environment-node-raster-export.test.ts index 051095d2ad..da5d34bb29 100644 --- a/crates/grida-canvas-wasm/lib/__test__/environment-node-raster-export.test.ts +++ b/crates/grida-canvas-wasm/lib/__test__/environment-node-raster-export.test.ts @@ -76,7 +76,7 @@ describe("raster export (node)", () => { const imageBytes = new Uint8Array(readFileSync(imagePath)); const doc = { - version: "0.90.0-beta+20260108", + version: "0.91.0-beta+20260311", document: { nodes: { "image-rect": { diff --git a/crates/grida-canvas/AGENTS.md b/crates/grida-canvas/AGENTS.md index f0116bd093..efc8bc1e22 100644 --- a/crates/grida-canvas/AGENTS.md +++ b/crates/grida-canvas/AGENTS.md @@ -75,6 +75,5 @@ See [examples/tool_io_grida.rs](./examples/tool_io_grida.rs) for full documentat ## Package Docs ```sh -# skia-safe -cargo doc --package skia-safe --open --no-deps +cargo doc --package cg --open --no-deps ``` diff --git a/crates/grida-canvas/Cargo.toml b/crates/grida-canvas/Cargo.toml index 190fbce774..7f73b2d34c 100644 --- a/crates/grida-canvas/Cargo.toml +++ b/crates/grida-canvas/Cargo.toml @@ -22,6 +22,7 @@ gl = "0.14.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" json-patch = "4.1.0" +flatbuffers = "25.12.19" # text editing grida-text-edit = { path = "../grida-text-edit" } diff --git a/crates/grida-canvas/README.md b/crates/grida-canvas/README.md index 03bcccea8f..ce4705d27a 100644 --- a/crates/grida-canvas/README.md +++ b/crates/grida-canvas/README.md @@ -2,52 +2,116 @@ Grida Canvas Rendering Backend Example -Grida Canvas core graphics implements High-level Node & Property based Graphics API that supports mordern design techniques. +Grida Canvas is a **safe, high-performance 2D real-time rendering engine** for the Grida design tool. It provides a node- and property-based graphics API with support for modern design techniques. -## Rendering +- **Rendering**: [`skia-safe`](https://rust-skia.github.io/doc/skia_safe/) for painting +- **Geometry & math**: [`math2`](../math2/README.md) for transforms, rects, and common operations -**2D Nodes** +## Capabilities -- [ ] TextSpan -- [ ] Text (Text with mixed styles) -- [ ] Image -- [ ] Bitmap (for bitmap drawing) -- [ ] Group -- [ ] Container (Frame) -- [ ] Rectangle -- [ ] Ellipse -- [ ] Polygon -- [ ] RegularPolygon -- [ ] RegularStarPolygon -- [ ] Path (SVG Path) -- [ ] Vector (Vector Network) -- [ ] Line +### 2D nodes -**Meta** +| Node | Status | +| ------------------------------------------- | ------ | +| Container (Frame) | ✅ | +| Group | ✅ | +| Rectangle | ✅ | +| Ellipse (incl. arc, ring, sector) | ✅ | +| Polygon, RegularPolygon, RegularStarPolygon | ✅ | +| Line | ✅ | +| Path (SVG path) | ✅ | +| Vector (vector network) | ✅ | +| BooleanOperation | ✅ | +| TextSpan | ✅ | +| Image | ✅ | +| InitialContainer, Error | ✅ | -- [ ] Mask -- [ ] Clip +### Paints & effects -**Styles & Effects** +- **Fills**: Solid, LinearGradient, RadialGradient, SweepGradient, Image (with fit and image filters) +- **Strokes**: Stroke width (uniform/variable), dash array, caps/joins, stroke alignment, rect-specific stroke widths, markers +- **Effects**: Layer blur, backdrop blur, drop/inner shadow, liquid glass, noise +- **Blend modes** on layers and paints -- [ ] SolidPaint -- [ ] LinearGradientPaint -- [ ] RadialGradientPaint -- [ ] DropShadow -- [ ] BoxShadow -- [ ] BlendMode +### Layout -## API +- **Taffy**-based layout: flex (direction, alignment, gap, padding), positioning (inset, width/height), transform -**Camera** +### Meta -- [ ] 2D Camera +- **Masks** (layer and vector masks) -**Pipeline & API** +### Pipeline & runtime -- [ ] load font -- [ ] load image +- **Camera**: 2D camera (pan, zoom, viewport) +- **Resources**: Font loading (`FontRepository`), image loading (`ImageRepository`), embedded fonts (e.g. Geist, Geist Mono) +- **Export**: PNG, JPEG, WEBP, BMP, PDF, SVG -## Interactivity +### Interactivity -- [ ] Hit testing +- **Hit testing**: `HitTester` for point-in-node and hit-test queries + +## I/O + +| Module | Description | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `io::io_grida_fbs` | Encode/decode `.grida` FlatBuffers binaries. Bindings are generated from `format/grida.fbs` via `flatc --rust` (see repo root and `format/README.md`). | +| `io::io_grida` | Decode Grida JSON documents into a `Scene`. | +| `io::io_grida_patch` | Apply JSON Patch to a decoded scene. | +| `io::io_figma` | Decode Figma API JSON into a `Scene` (feature-gated: `--features figma`). | +| `io::io_svg`, `io::io_css`, `io::io_markdown` | Additional import/parsing helpers. | + +### Test fixtures + +Raw FlatBuffers test fixtures live in [`fixtures/test-grida/`](../../fixtures/test-grida/) at the repo root. In-memory round-trip tests are in `cargo test --package cg --test fbs_roundtrip`. See the fixtures directory README for format and version details. + +## NodeID system + +The canvas uses a dual-ID system: + +- **NodeId** (`u64`): Internal counter-based IDs for high-performance operations. Ephemeral and not serialized. +- **UserNodeId** (`String`): External user-provided IDs for public APIs. Stable and serialized in `.grida` files. + +See [AGENTS.md](./AGENTS.md#nodeid-system) for details and migration notes. + +## Testing & development + +```sh +# run tests +cargo test + +# run fmt +cargo fmt + +# run check +cargo check +cargo check --all-targets --all-features + +# run clippy (no deps — skips re-checking skia etc.) +cargo clippy --no-deps --all-targets --all-features + +# run build +cargo build + +# run examples (many require window/GPU; headless_gpu requires native-gl-context) +cargo run --example +cargo run --example headless_gpu --features native-gl-context +``` + +## Tools + +### `tool_io_grida` — Grida file validator + +CLI for validating `.grida` files and debugging parsing. + +```sh +cargo run --example tool_io_grida +``` + +Validates file structure, reports node counts and types, and surfaces decode errors. See [examples/tool_io_grida.rs](./examples/tool_io_grida.rs) for full documentation. + +## Package docs + +```sh +cargo doc --package cg --open --no-deps +``` diff --git a/crates/grida-canvas/examples/fixtures/README.md b/crates/grida-canvas/examples/fixtures/README.md new file mode 100644 index 0000000000..5d9ae9ea97 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/README.md @@ -0,0 +1,382 @@ +# `.grida` Test Fixtures + +Generated by the fixture generator tool: + +```sh +cargo run --package cg --example tool_gen_fixtures +``` + +Each fixture is a self-contained `.grida` file focusing on a single feature area. +The naming convention is `L0-.grida` where `L0` indicates baseline coverage. + +--- + +## L0-shapes + +One of each basic shape type with a plain solid fill. No effects, no strokes (except line), no layout tricks. + +```text +scene "L0 Shapes" +├─ rectangle 200×100 red solid +├─ ellipse 100×80 blue solid +├─ regular_polygon 100×100 hexagon (6 sides), green solid, corner_radius=5 +├─ regular_star 120×120 5-point star, inner_radius=0.4, gold solid +├─ line 200px black stroke 2px +├─ text_span "Hello, Grida!" Inter 20px, black solid +└─ vector 100×100 closed bezier quad (4 segments), purple fill + black stroke 1px +``` + +**Exercises:** all 7 leaf node types that the encoder supports. + +--- + +## L0-shape-arc + +Ellipse arcs demonstrating inner_radius, start_angle, sweep angle, and corner_radius. + +```text +scene "L0 Shape Arc" +├─ ellipse full circle (defaults) +├─ ellipse semicircle (angle=180°) +├─ ellipse donut (inner_radius=0.5) +├─ ellipse pie wedge (start_angle=45°, angle=90°) +└─ ellipse rounded arc (inner_radius=0.6, angle=270°, corner_radius=8) +``` + +**Exercises:** EllipseNodeRec arc fields: inner_radius, start_angle, angle, corner_radius. + +--- + +## L0-shape-polygon + +Regular polygons and star polygons with varying point counts and parameters. + +```text +scene "L0 Shape Polygon" +├─ regular_polygon triangle (3 sides) +├─ regular_polygon pentagon (5, corner_radius=10) +├─ regular_polygon hexagon (6, corner_radius=5) +├─ regular_polygon octagon (8) +├─ regular_star 4-point star (inner_radius=0.3, sharp) +├─ regular_star 5-point star (inner_radius=0.4, corner_radius=3) +├─ regular_star 6-point star (inner_radius=0.5) +└─ regular_star 8-point star (inner_radius=0.7, corner_radius=6) +``` + +**Exercises:** RegularPolygonNodeRec (point_count, corner_radius), RegularStarPolygonNodeRec (inner_radius, corner_radius). + +--- + +## L0-vector + +Vector network nodes: closed shapes, open paths, region fills, variable-width strokes. + +```text +scene "L0 Vector" +├─ vector closed bezier quad (4 curved segments, EvenOdd region, blue fill) +├─ vector open path (3 vertices, 2 segments, no region, markers) +├─ vector triangle with explicit region fill + dashed stroke (NonZero) +└─ vector open path with variable-width stroke profile (3 stops) +``` + +**Exercises:** VectorNetwork (segments, loops, regions), FillRule (EvenOdd, NonZero), region fills, VarWidthProfile, markers on vectors. + +--- + +## L0-paints + +One rectangle per paint type. Each rectangle uses exactly one fill to isolate the paint variant. + +```text +scene "L0 Paints" +├─ rectangle solid (red, full opacity) +├─ rectangle linear gradient (red→blue, left→right) +├─ rectangle radial gradient (yellow center→green edge, 80% opacity) +├─ rectangle sweep gradient (cyan→magenta→yellow, 3 stops) +└─ rectangle image paint (HASH ref, BoxFit::Cover) +``` + +**Exercises:** Solid, LinearGradient, RadialGradient, SweepGradient, ImagePaint. + +--- + +## L0-paints-stack + +A single rectangle with multiple fills stacked bottom-to-top, demonstrating paint compositing. + +```text +scene "L0 Paints Stack" +└─ rectangle 200×200 + fill[0]: solid white (base) + fill[1]: linear gradient (red→transparent, left→right) + fill[2]: radial gradient (yellow center→transparent edge) + fill[3]: sweep gradient (cyan→magenta→transparent) + fill[4]: image paint (HASH ref, 50% opacity) +``` + +**Exercises:** multiple fills on one node, paint opacity, compositing order. + +--- + +## L0-strokes + +Stroke options on basic shapes: alignment, cap, join, dash array, markers. + +```text +scene "L0 Strokes" +├─ rectangle stroke_align=Center, cap=Butt, join=Miter, 2px black +├─ rectangle stroke_align=Inside, cap=Round, join=Round, 3px blue +├─ rectangle stroke_align=Outside, cap=Square, join=Bevel, 4px green +├─ rectangle dashed stroke [10, 5], cap=Round, 2px black +├─ line marker_start=Circle, marker_end=EquilateralTriangle, 2px +└─ line marker_start=Diamond, marker_end=VerticalBar, 2px +``` + +**Exercises:** StrokeAlign (3), StrokeCap (3), StrokeJoin (3), StrokeDashArray, StrokeMarkerPreset (5 of 7). + +--- + +## L0-strokes-rect + +Container-specific rectangular (per-side) stroke widths and per-side corner radii. + +```text +scene "L0 Strokes Rect" +├─ container 300×200 rectangular stroke (top=1, right=2, bottom=3, left=4), black +└─ container 300×200 uniform stroke 2px + per-side corner radii (tl=0, tr=8, bl=16, br=24) +``` + +**Exercises:** StrokeWidth::Rectangular, per-side RectangularCornerRadius with varying radii. + +--- + +## L0-image + +Image paint-specific properties: fit modes, resource references, quarter turns, alignment. + +```text +scene "L0 Image" +├─ rectangle ImagePaint, HASH ref, BoxFit::Cover, alignment=CENTER +├─ rectangle ImagePaint, RID ref, BoxFit::Contain, alignment=CENTER +├─ rectangle ImagePaint, Transform fit (scale=0.5, translate 10,20) +└─ rectangle ImagePaint, quarter_turns=2, alignment=BOTTOM_RIGHT, Screen blend +``` + +**Exercises:** ResourceRef (HASH, RID), ImagePaintFit (Fit/Cover, Fit/Contain, Transform), quarter_turns, Alignment, paint-level blend_mode. + +--- + +## L0-image-filters + +Image paint with non-default ImageFilters: exposure, contrast, saturation, temperature, tint, highlights, shadows. + +```text +scene "L0 Image Filters" +├─ rectangle bright + warm (exposure=0.5, temperature=0.4) +├─ rectangle high contrast + desaturated (contrast=0.25, saturation=-0.8) +├─ rectangle cool tint + shadow lift (temperature=-0.6, tint=-0.3, shadows=0.5) +└─ rectangle all 7 filter channels non-zero +``` + +**Exercises:** ImageFilters (exposure, contrast, saturation, temperature, tint, highlights, shadows). + +--- + +## L0-effects + +Each effect type on its own rectangle, one per node. Solid grey fill so the effect is visible. + +```text +scene "L0 Effects" +├─ rectangle blur: gaussian, radius=5 +├─ rectangle backdrop_blur: gaussian, radius=8 +├─ rectangle drop_shadow: dx=2, dy=2, blur=4, spread=0, black +├─ rectangle inner_shadow: dx=1, dy=1, blur=3, spread=0, grey +└─ rectangle noise: mono coloring, intensity=0.3 +``` + +**Exercises:** FeLayerBlur, FeBackdropBlur, FeShadow (DropShadow), FeShadow (InnerShadow), FeNoiseEffect. + +--- + +## L0-effects-glass + +Liquid glass effect centered over alternating black/white stripes with even +padding (matching the golden reference pattern). The 380×380 stripe background +is drawn first; the 300×300 glass panel sits centered with 40 px padding on +every side. + +```text +scene "L0 Effects Glass" +├─ rectangle 380×380 fill: white (background) +├─ 10× rectangle 20×380 fill: black (even stripes over white bg) +└─ rectangle 300×300 corner_radius=60 glass: refraction=1.0, depth=100, + dispersion=1.0, blur_radius=0, light_intensity=0.7 +``` + +**Exercises:** FeLiquidGlass with maximum refraction and chromatic aberration +over a stripe pattern (same approach as `golden_liquid_glass.rs`). + +--- + +## L0-type + +Core typography: font sizes, weights, alignment, decoration, spacing, transforms, stroke, effects. + +```text +scene "L0 Type" +├─ text_span "Regular 16px" Inter 16px, weight=400, Left/Top +├─ text_span "Bold 24px" Inter 24px, weight=700, Center/Center +├─ text_span "Right Aligned" Inter 16px, Right/Bottom +├─ text_span "Justified Text..." Inter 14px, Justify/Top, width=200 +├─ text_span "With Stroke" Inter 20px, red stroke 1px Outside +├─ text_span "Drop Shadow" Inter 20px, drop shadow +├─ text_span "Max 2 Lines..." Inter 14px, max_lines=2, ellipsis="…" +├─ text_span "Tracked + Tall..." Inter 16px, letter_spacing=4, line_height=2× +├─ text_span "Underlined Text" Inter 18px, underline red 2px, skip_ink +└─ text_span "uppercase transform" Inter 16px, TextTransform::Uppercase +``` + +**Exercises:** TextAlign (Left, Center, Right, Justify), TextAlignVertical (Top, Center, Bottom), text stroke + stroke_align, drop shadow, max_lines, ellipsis, letter_spacing, line_height, TextDecorationRec (underline, color, style, skip_ink, thickness), TextTransform. + +--- + +## L0-type-fvar + +Variable font axes: weight, width, optical sizing, custom fvar axes, italic. + +```text +scene "L0 Type fvar" +├─ text_span "Thin 100" Inter weight=100 +├─ text_span "Light 300" Inter weight=300 +├─ text_span "Regular 400" Inter weight=400 +├─ text_span "Bold 700" Inter weight=700 +├─ text_span "Black 900" Inter weight=900 +├─ text_span "Condensed (width=75)" Inter font_width=75 +├─ text_span "Optical Size Fixed(48)" Inter font_optical_sizing=Fixed(48) +├─ text_span "Custom Axes..." Roboto Flex, wght=600 wdth=80 GRAD=50 +└─ text_span "Italic Style" Inter italic=true +``` + +**Exercises:** FontWeight (100–900), font_width, FontOpticalSizing (Auto, Fixed), FontVariation (custom axes), font_style_italic. + +--- + +## L0-type-features + +OpenType font features: ligatures, small caps, stylistic sets, tabular numbers, kerning. + +```text +scene "L0 Type Features" +├─ text_span "ffi ffl — liga off" Inter, liga=false +├─ text_span "ffi ffl — liga on" Inter, liga=true +├─ text_span "Small Caps Text — smcp" Inter, smcp=true +├─ text_span "Stylistic Set 01 — ss01" Inter, ss01=true +├─ text_span "0123456789 — tnum + zero" Inter, tnum=true zero=true +└─ text_span "AVAW Typography — kern off" Inter, font_kerning=false +``` + +**Exercises:** FontFeature (liga, smcp, ss01, tnum, zero), font_kerning toggle. + +--- + +## L0-masks + +Mask composition with each mask type. Each mask + its target are inside a dedicated group to avoid masking unrelated siblings. + +```text +scene "L0 Masks" +├─ group (image mask demo) +│ ├─ rectangle 100×100 red solid (content) +│ └─ rectangle 100×100 white solid (mask: Image/Alpha) +└─ group (geometry mask demo) + ├─ rectangle 100×100 blue solid (content) + └─ ellipse 80×80 black solid (mask: Geometry) +``` + +**Exercises:** LayerMaskType::Image(Alpha), LayerMaskType::Geometry, mask scoping via group. + +--- + +## L0-boolean-operation + +All four boolean path operations, each with two overlapping child rectangles. + +```text +scene "L0 Boolean Operation" +├─ boolean_op Union (red, 2 overlapping rects) +├─ boolean_op Intersection (blue, 2 overlapping rects) +├─ boolean_op Difference (green, 2 overlapping rects) +└─ boolean_op Xor (yellow, 2 overlapping rects) +``` + +**Exercises:** BooleanPathOperation (Union, Intersection, Difference, Xor), BooleanPathOperationNodeRec with child shapes. + +--- + +## L0-layout-position + +Positioning modes for shapes within a container. No flex — uses Normal layout mode. + +```text +scene "L0 Layout Position" +└─ container 400×300 Normal layout, light grey fill + ├─ rectangle 80×60 Cartesian position (x=20, y=20) + ├─ rectangle 80×60 Inset position (top=50, left=150) + └─ rectangle 80×60 Absolute positioning (layout_child, inset top=150, left=20) +``` + +**Exercises:** LayoutPositioningBasis::Cartesian, LayoutPositioningBasis::Inset, LayoutPositioning::Absolute. + +--- + +## L0-layout-flex + +Flex layout demonstration with two containers showing different configurations. + +```text +scene "L0 Layout Flex" +├─ container 500×80 horizontal flex, gap=10, main=SpaceBetween, cross=Center +│ ├─ rectangle 100×50 (auto) +│ ├─ rectangle 100×50 (auto) +│ └─ rectangle fill×50 (flex_grow=1) +└─ container 200×300 vertical flex, main=Center, cross=Stretch, padding=16, gap=8 + ├─ rectangle auto×40 + └─ rectangle auto×40 +``` + +**Exercises:** LayoutMode::Flex, Axis (Horizontal, Vertical), MainAxisAlignment::SpaceBetween, MainAxisAlignment::Center, CrossAxisAlignment::Center, CrossAxisAlignment::Stretch, layout_grow, LayoutGap, padding. + +--- + +## L0-layout-transform + +Rotation and affine transforms on containers and shapes. + +```text +scene "L0 Layout Transform" +├─ container 200×150 rotated 90°, Cartesian at (300, 50), blue fill +├─ rectangle 120×80 rotated 45°, at (50, 50), red fill +└─ line 200px rotated 45°, at (400, 200), black stroke 2px +``` + +**Exercises:** Container rotation, shape rotation via AffineTransform, line rotation. + +--- + +## Not included (rationale) + +| Topic | Reason | +| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Blend modes | All 16 + PassThrough are exhaustively covered by the `gen_all_blend_modes` in-memory test. A fixture file would be 17 identical rectangles — low visual value. | +| Deep nesting | Covered by `gen_deep_nesting` (4 levels). Nesting is structural, not visual. | +| Inactive / edge cases | Covered by `gen_inactive_node`. An invisible node in a visual fixture adds nothing. | + +--- + +## Regenerating + +```sh +# regenerate L0.grida (all scenes) +cargo run --package cg --example tool_gen_fixtures +``` diff --git a/crates/grida-canvas/examples/fixtures/l0_boolean_operation.rs b/crates/grida-canvas/examples/fixtures/l0_boolean_operation.rs new file mode 100644 index 0000000000..09555fd66c --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_boolean_operation.rs @@ -0,0 +1,88 @@ +use super::*; +use cg::cg::stroke_width::SingularStrokeWidth; +use math2::transform::AffineTransform; +use std::collections::HashMap; + +/// All four boolean operations, each with two overlapping child rectangles. +pub fn build() -> Scene { + let ops = [ + (BooleanPathOperation::Union, solid(220, 59, 59, 255)), + (BooleanPathOperation::Intersection, solid(59, 100, 220, 255)), + (BooleanPathOperation::Difference, solid(59, 180, 75, 255)), + (BooleanPathOperation::Xor, solid(255, 200, 40, 255)), + ]; + + let gap = 160.0; + let mut nodes: Vec<(u64, Node)> = Vec::new(); + let mut links: HashMap> = HashMap::new(); + let mut roots: Vec = Vec::new(); + let mut next_id = 1u64; + + for (i, (op, fill)) in ops.iter().enumerate() { + let x = (i as f32) * gap; + let bool_id = next_id; + next_id += 1; + + let bool_node = Node::BooleanOperation(BooleanPathOperationNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: Some(AffineTransform::from_box_center(x, 0.0, 0.0, 0.0, 0.0)), + op: *op, + corner_radius: None, + fills: Paints::new(vec![fill.clone()]), + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(Some(1.0)), + }); + + // Two overlapping rectangles as children + let child_a_id = next_id; + next_id += 1; + let child_a = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 0.0, 80.0, 80.0, 0.0), + size: Size { width: 80.0, height: 80.0 }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: None, + }); + + let child_b_id = next_id; + next_id += 1; + let child_b = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(40.0, 40.0, 80.0, 80.0, 0.0), + size: Size { width: 80.0, height: 80.0 }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: None, + }); + + nodes.push((bool_id, bool_node)); + nodes.push((child_a_id, child_a)); + nodes.push((child_b_id, child_b)); + links.insert(bool_id, vec![child_a_id, child_b_id]); + roots.push(bool_id); + } + + build_scene("L0 Boolean Operation", None, nodes, links, roots) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_container.rs b/crates/grida-canvas/examples/fixtures/l0_container.rs new file mode 100644 index 0000000000..7836a533e5 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_container.rs @@ -0,0 +1,190 @@ +use super::*; +use std::collections::HashMap; + +/// Container-specific features: clip on/off, nesting, InitialContainer. +pub fn build() -> Scene { + // ── [1] Outer container (clip=true) ───────────────────────────────── + // Child rectangle intentionally overflows to demonstrate clipping. + let clip_on = Node::Container(ContainerNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + rotation: 0.0, + position: LayoutPositioningBasis::Inset(EdgeInsets { + top: 0.0, right: 0.0, bottom: 0.0, left: 0.0, + }), + layout_container: LayoutContainerStyle::default(), + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(200.0), + layout_target_height: Some(150.0), + layout_min_width: None, layout_max_width: None, + layout_min_height: None, layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: { + use cg::cg::types::Radius; + let r = Radius::circular(12.0); + RectangularCornerRadius { tl: r, tr: r, bl: r, br: r } + }, + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(235, 240, 255, 255)]), + strokes: Paints::new(vec![solid(100, 120, 200, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::Uniform(1.0), + effects: LayerEffects::default(), + clip: true, + }); + + // Overflowing child — should be clipped by parent + let overflow_rect = rect(60.0, 80.0, 200.0, 120.0, solid(220, 59, 59, 200)); + + // ── [3] Same container but clip=false ─────────────────────────────── + let clip_off = Node::Container(ContainerNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + rotation: 0.0, + position: LayoutPositioningBasis::Inset(EdgeInsets { + top: 0.0, right: 0.0, bottom: 0.0, left: 240.0, + }), + layout_container: LayoutContainerStyle::default(), + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(200.0), + layout_target_height: Some(150.0), + layout_min_width: None, layout_max_width: None, + layout_min_height: None, layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: { + use cg::cg::types::Radius; + let r = Radius::circular(12.0); + RectangularCornerRadius { tl: r, tr: r, bl: r, br: r } + }, + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(235, 255, 240, 255)]), + strokes: Paints::new(vec![solid(100, 200, 120, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::Uniform(1.0), + effects: LayerEffects::default(), + clip: false, + }); + + // Same overflowing child — should be visible beyond parent bounds + let overflow_rect2 = rect(60.0, 80.0, 200.0, 120.0, solid(59, 180, 75, 200)); + + // ── [5] Nested containers (3 levels deep) ────────────────────────── + let outer = Node::Container(ContainerNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + rotation: 0.0, + position: LayoutPositioningBasis::Inset(EdgeInsets { + top: 180.0, right: 0.0, bottom: 0.0, left: 0.0, + }), + layout_container: LayoutContainerStyle::default(), + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(400.0), + layout_target_height: Some(250.0), + layout_min_width: None, layout_max_width: None, + layout_min_height: None, layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(245, 245, 245, 255)]), + strokes: Paints::new(vec![solid(180, 180, 180, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::Uniform(1.0), + effects: LayerEffects::default(), + clip: false, + }); + + let middle = Node::Container(ContainerNodeRec { + active: true, + opacity: 0.9, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + rotation: 0.0, + position: LayoutPositioningBasis::Inset(EdgeInsets { + top: 20.0, right: 0.0, bottom: 0.0, left: 20.0, + }), + layout_container: LayoutContainerStyle::default(), + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(300.0), + layout_target_height: Some(180.0), + layout_min_width: None, layout_max_width: None, + layout_min_height: None, layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: { + use cg::cg::types::Radius; + let r = Radius::circular(8.0); + RectangularCornerRadius { tl: r, tr: r, bl: r, br: r } + }, + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(220, 230, 255, 255)]), + strokes: Paints::new(vec![solid(150, 170, 220, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::Uniform(1.0), + effects: LayerEffects::default(), + clip: true, + }); + + let inner = Node::Container(ContainerNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + rotation: 0.0, + position: LayoutPositioningBasis::Inset(EdgeInsets { + top: 15.0, right: 0.0, bottom: 0.0, left: 15.0, + }), + layout_container: LayoutContainerStyle::default(), + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(200.0), + layout_target_height: Some(120.0), + layout_min_width: None, layout_max_width: None, + layout_min_height: None, layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(255, 240, 230, 255)]), + strokes: Paints::new(vec![solid(220, 180, 150, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::Uniform(1.0), + effects: LayerEffects::default(), + clip: false, + }); + + // Leaf inside the innermost container + let leaf = rect(10.0, 10.0, 80.0, 60.0, solid(128, 60, 200, 255)); + + // ── Tree ──────────────────────────────────────────────────────────── + let mut links = HashMap::new(); + links.insert(1u64, vec![2u64]); // clip_on → overflow_rect + links.insert(3u64, vec![4u64]); // clip_off → overflow_rect2 + links.insert(5u64, vec![6u64]); // outer → middle + links.insert(6u64, vec![7u64]); // middle → inner + links.insert(7u64, vec![8u64]); // inner → leaf + + build_scene( + "L0 Container", + None, + vec![ + (1, clip_on), (2, overflow_rect), + (3, clip_off), (4, overflow_rect2), + (5, outer), (6, middle), (7, inner), (8, leaf), + ], + links, + vec![1, 3, 5], + ) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_effects.rs b/crates/grida-canvas/examples/fixtures/l0_effects.rs new file mode 100644 index 0000000000..0ca9c3c534 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_effects.rs @@ -0,0 +1,77 @@ +use super::*; +use cg::cg::color::CGColor; +use cg::cg::fe::*; + +fn effect_rect(x: f32, effects: LayerEffects) -> Node { + Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(x, 0.0, 150.0, 150.0, 0.0), + size: Size { width: 150.0, height: 150.0 }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(180, 180, 180, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects, + layout_child: None, + }) +} + +pub fn build() -> Scene { + let gap = 170.0; + + let blur = effect_rect(0.0, LayerEffects { + blur: Some(FeLayerBlur { + active: true, + blur: FeBlur::Gaussian(FeGaussianBlur { radius: 5.0 }), + }), + ..LayerEffects::default() + }); + + let backdrop = effect_rect(gap, LayerEffects { + backdrop_blur: Some(FeBackdropBlur { + active: true, + blur: FeBlur::Gaussian(FeGaussianBlur { radius: 8.0 }), + }), + ..LayerEffects::default() + }); + + let drop_shadow = effect_rect(gap * 2.0, LayerEffects { + shadows: vec![FilterShadowEffect::DropShadow(FeShadow { + dx: 2.0, dy: 2.0, blur: 4.0, spread: 0.0, + color: CGColor { r: 0, g: 0, b: 0, a: 255 }, + active: true, + })], + ..LayerEffects::default() + }); + + let inner_shadow = effect_rect(gap * 3.0, LayerEffects { + shadows: vec![FilterShadowEffect::InnerShadow(FeShadow { + dx: 1.0, dy: 1.0, blur: 3.0, spread: 0.0, + color: CGColor { r: 128, g: 128, b: 128, a: 200 }, + active: true, + })], + ..LayerEffects::default() + }); + + let noise = effect_rect(gap * 4.0, LayerEffects { + noises: vec![FeNoiseEffect { + active: true, + noise_size: 1.0, + density: 0.3, + num_octaves: 4, + seed: 42.0, + coloring: NoiseEffectColors::Mono { + color: CGColor { r: 0, g: 0, b: 0, a: 64 }, + }, + blend_mode: BlendMode::Normal, + }], + ..LayerEffects::default() + }); + + flat_scene("L0 Effects", vec![blur, backdrop, drop_shadow, inner_shadow, noise]) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_effects_glass.rs b/crates/grida-canvas/examples/fixtures/l0_effects_glass.rs new file mode 100644 index 0000000000..5a82b05e3a --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_effects_glass.rs @@ -0,0 +1,65 @@ +use super::*; +use cg::cg::fe::*; + +pub fn build() -> Scene { + // Note: rect(x, y, w, h, ..) uses from_box_center which, at 0° rotation, + // places the rect's top-left at (x, y). + + let glass_size = 300.0; + let padding = 40.0; + let total = glass_size + padding * 2.0; // 380 + + // ── Background ───────────────────────────────────────────────────── + // White base + black stripes → alternating black/white pattern. + // Top-left at (0, 0), spans [0 .. total] in both axes. + let bg = rect(0.0, 0.0, total, total, solid(255, 255, 255, 255)); + + let stripe_w = 10.0; + let n_stripes = (total / stripe_w).ceil() as i32; + let mut nodes: Vec = vec![bg]; + for i in 0..n_stripes { + if i % 2 != 0 { + continue; // white gap covered by bg + } + let x = i as f32 * stripe_w; // top-left x within [0 .. total] + nodes.push(rect(x, 0.0, stripe_w, total, solid(0, 0, 0, 255))); + } + + // ── Glass panel ──────────────────────────────────────────────────── + // Inset by `padding` on every side → top-left at (padding, padding), + // centered within the stripe background. + // Parameters match the golden reference (golden_liquid_glass.rs). + let glass_rect = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center( + padding, padding, glass_size, glass_size, 0.0, + ), + size: Size { width: glass_size, height: glass_size }, + corner_radius: RectangularCornerRadius::circular(60.0), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects { + glass: Some(FeLiquidGlass { + active: true, + light_intensity: 0.7, + light_angle: 45.0, + refraction: 1.0, + depth: 100.0, + blur_radius: 0.0, + dispersion: 1.0, + }), + ..LayerEffects::default() + }, + layout_child: None, + }); + + nodes.push(glass_rect); + + flat_scene("L0 Effects Glass", nodes) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_group.rs b/crates/grida-canvas/examples/fixtures/l0_group.rs new file mode 100644 index 0000000000..185150bc9c --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_group.rs @@ -0,0 +1,83 @@ +use super::*; +use math2::transform::AffineTransform; +use std::collections::HashMap; + +/// Group node features: grouping children, opacity inheritance, blend modes, nesting. +pub fn build() -> Scene { + // ── [1] Simple group with two children ────────────────────────────── + let g1 = Node::Group(GroupNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: Some(AffineTransform::from_box_center(0.0, 0.0, 0.0, 0.0, 0.0)), + }); + let g1_a = rect(0.0, 0.0, 80.0, 80.0, solid(220, 59, 59, 255)); + let g1_b = rect(40.0, 40.0, 80.0, 80.0, solid(59, 100, 220, 200)); + + // ── [4] Group with reduced opacity (children inherit) ─────────────── + let g2 = Node::Group(GroupNodeRec { + active: true, + opacity: 0.4, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: Some(AffineTransform::from_box_center(200.0, 0.0, 0.0, 0.0, 0.0)), + }); + let g2_a = rect(0.0, 0.0, 80.0, 80.0, solid(220, 59, 59, 255)); + let g2_b = rect(40.0, 40.0, 80.0, 80.0, solid(59, 100, 220, 255)); + + // ── [7] Group with blend mode ─────────────────────────────────────── + let g3 = Node::Group(GroupNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::Blend(BlendMode::Multiply), + mask: None, + transform: Some(AffineTransform::from_box_center(400.0, 0.0, 0.0, 0.0, 0.0)), + }); + let g3_a = rect(0.0, 0.0, 100.0, 100.0, solid(255, 200, 40, 255)); + let g3_b = rect(30.0, 30.0, 100.0, 100.0, solid(59, 100, 220, 255)); + + // ── [10] Nested groups ────────────────────────────────────────────── + let g_outer = Node::Group(GroupNodeRec { + active: true, + opacity: 0.8, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: Some(AffineTransform::from_box_center(0.0, 160.0, 0.0, 0.0, 0.0)), + }); + + let g_inner = Node::Group(GroupNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::Blend(BlendMode::Screen), + mask: None, + transform: Some(AffineTransform::from_box_center(20.0, 20.0, 0.0, 0.0, 0.0)), + }); + + let leaf1 = rect(0.0, 0.0, 60.0, 60.0, solid(59, 180, 75, 255)); + let leaf2 = rect(30.0, 30.0, 60.0, 60.0, solid(128, 60, 200, 255)); + + // Sibling of g_inner inside g_outer + let sibling = ellipse(150.0, 20.0, 80.0, 80.0, solid(220, 120, 60, 255)); + + // ── Tree ──────────────────────────────────────────────────────────── + let mut links = HashMap::new(); + links.insert(1u64, vec![2, 3]); // g1 → children + links.insert(4u64, vec![5, 6]); // g2 → children + links.insert(7u64, vec![8, 9]); // g3 → children + links.insert(10u64, vec![11, 14]); // g_outer → g_inner + sibling + links.insert(11u64, vec![12, 13]); // g_inner → leaves + + build_scene( + "L0 Group", + None, + vec![ + (1, g1), (2, g1_a), (3, g1_b), + (4, g2), (5, g2_a), (6, g2_b), + (7, g3), (8, g3_a), (9, g3_b), + (10, g_outer), (11, g_inner), (12, leaf1), (13, leaf2), (14, sibling), + ], + links, + vec![1, 4, 7, 10], + ) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_image.rs b/crates/grida-canvas/examples/fixtures/l0_image.rs new file mode 100644 index 0000000000..439cf6848f --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_image.rs @@ -0,0 +1,37 @@ +use super::*; +use cg::cg::alignment::Alignment; +use math2::box_fit::BoxFit; +use math2::transform::AffineTransform; + +pub fn build() -> Scene { + let s = 150.0; + let gap = 170.0; + let img = || ResourceRef::HASH(SYSTEM_IMAGE.to_owned()); + + // Cover fit + let r1 = rect(0.0, 0.0, s, s, + image_paint_with(img(), ImagePaintFit::Fit(BoxFit::Cover))); + + // Contain fit + let r2 = rect(gap, 0.0, s, s, + image_paint_with(img(), ImagePaintFit::Fit(BoxFit::Contain))); + + // Transform fit (scale + offset) + let r3 = rect(gap * 2.0, 0.0, s, s, + image_paint_with(img(), ImagePaintFit::Transform(AffineTransform::new(10.0, 20.0, 0.0)))); + + // Quarter turns + alignment + Screen blend + let r4 = rect(gap * 3.0, 0.0, s, s, + Paint::Image(ImagePaint { + active: true, + image: img(), + fit: ImagePaintFit::Fit(BoxFit::Cover), + filters: ImageFilters::default(), + opacity: 1.0, + blend_mode: BlendMode::Screen, + quarter_turns: 2, + alignement: Alignment::BOTTOM_RIGHT, + })); + + flat_scene("L0 Image", vec![r1, r2, r3, r4]) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_image_filters.rs b/crates/grida-canvas/examples/fixtures/l0_image_filters.rs new file mode 100644 index 0000000000..5912556953 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_image_filters.rs @@ -0,0 +1,80 @@ +use super::*; +use cg::cg::alignment::Alignment; +use math2::box_fit::BoxFit; + +/// Image paint with non-default filter values: exposure, contrast, saturation, etc. +pub fn build() -> Scene { + let s = 150.0; + let gap = 170.0; + + // Bright + warm + let bright_warm = rect(0.0, 0.0, s, s, Paint::Image(ImagePaint { + active: true, + image: ResourceRef::HASH(SYSTEM_IMAGE.to_owned()), + fit: ImagePaintFit::Fit(BoxFit::Cover), + filters: ImageFilters { + exposure: 0.5, + temperature: 0.4, + ..ImageFilters::default() + }, + opacity: 1.0, + blend_mode: BlendMode::Normal, + quarter_turns: 0, + alignement: Alignment::CENTER, + })); + + // High contrast + desaturated + let contrast_desat = rect(gap, 0.0, s, s, Paint::Image(ImagePaint { + active: true, + image: ResourceRef::HASH(SYSTEM_IMAGE.to_owned()), + fit: ImagePaintFit::Fit(BoxFit::Cover), + filters: ImageFilters { + contrast: 0.25, + saturation: -0.8, + ..ImageFilters::default() + }, + opacity: 1.0, + blend_mode: BlendMode::Normal, + quarter_turns: 0, + alignement: Alignment::CENTER, + })); + + // Cool tint + shadow lift + let cool_shadow = rect(gap * 2.0, 0.0, s, s, Paint::Image(ImagePaint { + active: true, + image: ResourceRef::HASH(SYSTEM_IMAGE.to_owned()), + fit: ImagePaintFit::Fit(BoxFit::Cover), + filters: ImageFilters { + temperature: -0.6, + tint: -0.3, + shadows: 0.5, + ..ImageFilters::default() + }, + opacity: 1.0, + blend_mode: BlendMode::Normal, + quarter_turns: 0, + alignement: Alignment::CENTER, + })); + + // All filters non-zero + let all_filters = rect(gap * 3.0, 0.0, s, s, Paint::Image(ImagePaint { + active: true, + image: ResourceRef::HASH(SYSTEM_IMAGE.to_owned()), + fit: ImagePaintFit::Fit(BoxFit::Cover), + filters: ImageFilters { + exposure: 0.2, + contrast: 0.1, + saturation: 0.3, + temperature: -0.2, + tint: 0.15, + highlights: -0.4, + shadows: 0.3, + }, + opacity: 1.0, + blend_mode: BlendMode::Normal, + quarter_turns: 0, + alignement: Alignment::CENTER, + })); + + flat_scene("L0 Image Filters", vec![bright_warm, contrast_desat, cool_shadow, all_filters]) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_layout_flex.rs b/crates/grida-canvas/examples/fixtures/l0_layout_flex.rs new file mode 100644 index 0000000000..185d531916 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_layout_flex.rs @@ -0,0 +1,121 @@ +use super::*; +use std::collections::HashMap; + +pub fn build() -> Scene { + // Horizontal flex container: SpaceBetween, Center + let h_container = Node::Container(ContainerNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + rotation: 0.0, + position: LayoutPositioningBasis::Inset(EdgeInsets { + top: 0.0, right: 0.0, bottom: 0.0, left: 0.0, + }), + layout_container: LayoutContainerStyle { + layout_mode: LayoutMode::Flex, + layout_direction: Axis::Horizontal, + layout_wrap: Some(LayoutWrap::NoWrap), + layout_main_axis_alignment: Some(MainAxisAlignment::SpaceBetween), + layout_cross_axis_alignment: Some(CrossAxisAlignment::Center), + layout_padding: None, + layout_gap: Some(LayoutGap { main_axis_gap: 10.0, cross_axis_gap: 0.0 }), + }, + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(500.0), + layout_target_height: Some(80.0), + layout_min_width: None, layout_max_width: None, + layout_min_height: None, layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(240, 240, 245, 255)]), + strokes: Paints::new(vec![solid(200, 200, 210, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::Uniform(1.0), + effects: LayerEffects::default(), + clip: false, + }); + + let h1 = rect(0.0, 0.0, 100.0, 50.0, solid(220, 59, 59, 255)); + let h2 = rect(0.0, 0.0, 100.0, 50.0, solid(59, 100, 220, 255)); + // flex_grow=1 + let h3 = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 0.0, 100.0, 50.0, 0.0), + size: Size { width: 100.0, height: 50.0 }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(59, 180, 75, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: Some(LayoutChildStyle { + layout_grow: 1.0, + layout_positioning: LayoutPositioning::Auto, + }), + }); + + // Vertical flex container: Center, Stretch + let v_container = Node::Container(ContainerNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + rotation: 0.0, + position: LayoutPositioningBasis::Inset(EdgeInsets { + top: 100.0, right: 0.0, bottom: 0.0, left: 0.0, + }), + layout_container: LayoutContainerStyle { + layout_mode: LayoutMode::Flex, + layout_direction: Axis::Vertical, + layout_wrap: Some(LayoutWrap::NoWrap), + layout_main_axis_alignment: Some(MainAxisAlignment::Center), + layout_cross_axis_alignment: Some(CrossAxisAlignment::Stretch), + layout_padding: Some(EdgeInsets { + top: 16.0, right: 16.0, bottom: 16.0, left: 16.0, + }), + layout_gap: Some(LayoutGap { main_axis_gap: 8.0, cross_axis_gap: 0.0 }), + }, + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(200.0), + layout_target_height: Some(200.0), + layout_min_width: None, layout_max_width: None, + layout_min_height: None, layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(245, 240, 240, 255)]), + strokes: Paints::new(vec![solid(210, 200, 200, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::Uniform(1.0), + effects: LayerEffects::default(), + clip: false, + }); + + let v1 = rect(0.0, 0.0, 80.0, 40.0, solid(255, 200, 40, 255)); + let v2 = rect(0.0, 0.0, 80.0, 40.0, solid(128, 60, 200, 255)); + + let mut links = HashMap::new(); + links.insert(1u64, vec![2u64, 3u64, 4u64]); + links.insert(5u64, vec![6u64, 7u64]); + + build_scene( + "L0 Layout Flex", + None, + vec![ + (1, h_container), (2, h1), (3, h2), (4, h3), + (5, v_container), (6, v1), (7, v2), + ], + links, + vec![1, 5], + ) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_layout_position.rs b/crates/grida-canvas/examples/fixtures/l0_layout_position.rs new file mode 100644 index 0000000000..121e2c10c0 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_layout_position.rs @@ -0,0 +1,70 @@ +use super::*; +use std::collections::HashMap; + +pub fn build() -> Scene { + let container = Node::Container(ContainerNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + rotation: 0.0, + position: LayoutPositioningBasis::Inset(EdgeInsets { + top: 0.0, right: 0.0, bottom: 0.0, left: 0.0, + }), + layout_container: LayoutContainerStyle::default(), // Normal mode + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(400.0), + layout_target_height: Some(300.0), + layout_min_width: None, layout_max_width: None, + layout_min_height: None, layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(245, 245, 245, 255)]), + strokes: Paints::new(vec![solid(200, 200, 200, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::Uniform(1.0), + effects: LayerEffects::default(), + clip: false, + }); + + // Child at Cartesian (20, 20) + let c1 = rect(20.0, 20.0, 80.0, 60.0, solid(220, 59, 59, 255)); + + // Child at Inset (top=50, left=150) — same x,y via inset + let c2 = rect(150.0, 50.0, 80.0, 60.0, solid(59, 100, 220, 255)); + + // Child with layout_child Absolute positioning + let c3 = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(20.0, 150.0, 80.0, 60.0, 0.0), + size: Size { width: 80.0, height: 60.0 }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(59, 180, 75, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: Some(LayoutChildStyle { + layout_grow: 0.0, + layout_positioning: LayoutPositioning::Absolute, + }), + }); + + let mut links = HashMap::new(); + links.insert(1u64, vec![2u64, 3u64, 4u64]); + + build_scene( + "L0 Layout Position", + None, + vec![(1, container), (2, c1), (3, c2), (4, c3)], + links, + vec![1], + ) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_layout_transform.rs b/crates/grida-canvas/examples/fixtures/l0_layout_transform.rs new file mode 100644 index 0000000000..8aee256c0a --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_layout_transform.rs @@ -0,0 +1,38 @@ +use super::*; + +pub fn build() -> Scene { + // Container rotated 90°, Cartesian position + let rotated_container = Node::Container(ContainerNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + rotation: 90.0, + position: LayoutPositioningBasis::Cartesian(CGPoint::new(300.0, 50.0)), + layout_container: LayoutContainerStyle::default(), + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(200.0), + layout_target_height: Some(150.0), + layout_min_width: None, layout_max_width: None, + layout_min_height: None, layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(59, 100, 220, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + clip: false, + }); + + // Rectangle rotated 45° + let rotated_rect = rect_rotated(50.0, 50.0, 120.0, 80.0, 45.0, solid(220, 59, 59, 255)); + + // Line rotated 45° + let rotated_line = line(400.0, 200.0, 200.0, 45.0, 2.0); + + flat_scene("L0 Layout Transform", vec![rotated_container, rotated_rect, rotated_line]) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_masks.rs b/crates/grida-canvas/examples/fixtures/l0_masks.rs new file mode 100644 index 0000000000..b4d64aa926 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_masks.rs @@ -0,0 +1,75 @@ +use super::*; +use cg::cg::stroke_width::SingularStrokeWidth; +use math2::transform::AffineTransform; +use std::collections::HashMap; + +pub fn build() -> Scene { + // Group 1: image mask (alpha) + let group_img = Node::Group(GroupNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: Some(AffineTransform::from_box_center(0.0, 0.0, 0.0, 0.0, 0.0)), + }); + let content_img = rect(0.0, 0.0, 100.0, 100.0, solid(220, 59, 59, 255)); + let mask_img = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: Some(LayerMaskType::Image(ImageMaskType::Alpha)), + transform: AffineTransform::from_box_center(0.0, 0.0, 100.0, 100.0, 0.0), + size: Size { width: 100.0, height: 100.0 }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(255, 255, 255, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: None, + }); + + // Group 2: geometry mask + let group_geo = Node::Group(GroupNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: Some(AffineTransform::from_box_center(150.0, 0.0, 0.0, 0.0, 0.0)), + }); + let content_geo = rect(0.0, 0.0, 100.0, 100.0, solid(59, 100, 220, 255)); + let mask_geo = Node::Ellipse(EllipseNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: Some(LayerMaskType::Geometry), + transform: AffineTransform::from_box_center(10.0, 10.0, 80.0, 80.0, 0.0), + size: Size { width: 80.0, height: 80.0 }, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + inner_radius: None, + start_angle: 0.0, + angle: None, + corner_radius: None, + effects: LayerEffects::default(), + layout_child: None, + }); + + let mut links = HashMap::new(); + links.insert(1u64, vec![2u64, 3u64]); + links.insert(4u64, vec![5u64, 6u64]); + + build_scene( + "L0 Masks", + None, + vec![ + (1, group_img), (2, content_img), (3, mask_img), + (4, group_geo), (5, content_geo), (6, mask_geo), + ], + links, + vec![1, 4], + ) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_paints.rs b/crates/grida-canvas/examples/fixtures/l0_paints.rs new file mode 100644 index 0000000000..4c54a0d563 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_paints.rs @@ -0,0 +1,14 @@ +use super::*; + +pub fn build() -> Scene { + let s = 150.0; + let gap = 170.0; + + let solid_rect = rect(0.0, 0.0, s, s, solid(220, 59, 59, 255)); + let linear_rect = rect(gap, 0.0, s, s, linear_gradient()); + let radial_rect = rect(gap * 2.0, 0.0, s, s, radial_gradient()); + let sweep_rect = rect(gap * 3.0, 0.0, s, s, sweep_gradient()); + let image_rect = rect(gap * 4.0, 0.0, s, s, image_paint()); + + flat_scene("L0 Paints", vec![solid_rect, linear_rect, radial_rect, sweep_rect, image_rect]) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_paints_stack.rs b/crates/grida-canvas/examples/fixtures/l0_paints_stack.rs new file mode 100644 index 0000000000..1929dea919 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_paints_stack.rs @@ -0,0 +1,70 @@ +use super::*; +use cg::cg::alignment::Alignment; +use cg::cg::color::CGColor; +use cg::cg::tilemode::TileMode; +use math2::box_fit::BoxFit; +use math2::transform::AffineTransform; + +pub fn build() -> Scene { + // Single rectangle with 5 stacked fills + let stacked = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 0.0, 200.0, 200.0, 0.0), + size: Size { width: 200.0, height: 200.0 }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![ + // [0] solid white base + solid(255, 255, 255, 255), + // [1] linear gradient red→transparent + Paint::LinearGradient(LinearGradientPaint { + active: true, + xy1: Alignment::CENTER_LEFT, + xy2: Alignment::CENTER_RIGHT, + tile_mode: TileMode::default(), + transform: AffineTransform::default(), + stops: vec![ + GradientStop { offset: 0.0, color: CGColor { r: 255, g: 0, b: 0, a: 255 } }, + GradientStop { offset: 1.0, color: CGColor { r: 255, g: 0, b: 0, a: 0 } }, + ], + opacity: 1.0, + blend_mode: BlendMode::Normal, + }), + // [2] radial gradient yellow center→transparent + Paint::RadialGradient(RadialGradientPaint { + active: true, + transform: AffineTransform::default(), + stops: vec![ + GradientStop { offset: 0.0, color: CGColor { r: 255, g: 255, b: 0, a: 255 } }, + GradientStop { offset: 1.0, color: CGColor { r: 255, g: 255, b: 0, a: 0 } }, + ], + opacity: 1.0, + blend_mode: BlendMode::Normal, + tile_mode: TileMode::default(), + }), + // [3] sweep gradient + sweep_gradient(), + // [4] image paint at 50% opacity + Paint::Image(ImagePaint { + active: true, + image: ResourceRef::HASH(SYSTEM_IMAGE.to_owned()), + fit: ImagePaintFit::Fit(BoxFit::Cover), + filters: ImageFilters::default(), + opacity: 0.5, + blend_mode: BlendMode::Normal, + quarter_turns: 0, + alignement: Alignment::CENTER, + }), + ]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: None, + }); + + flat_scene("L0 Paints Stack", vec![stacked]) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_shape_arc.rs b/crates/grida-canvas/examples/fixtures/l0_shape_arc.rs new file mode 100644 index 0000000000..b978e50d19 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_shape_arc.rs @@ -0,0 +1,111 @@ +use super::*; +use cg::cg::stroke_width::SingularStrokeWidth; +use math2::transform::AffineTransform; + +/// Ellipse arc variants: full, semicircle, donut, pie wedge, rounded arc. +pub fn build() -> Scene { + let s = 120.0; + let gap = 140.0; + + // Full ellipse (defaults — no arc) + let full = Node::Ellipse(EllipseNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 0.0, s, s, 0.0), + size: Size { width: s, height: s }, + fills: Paints::new(vec![solid(59, 100, 220, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + inner_radius: None, + start_angle: 0.0, + angle: None, + corner_radius: None, + effects: LayerEffects::default(), + layout_child: None, + }); + + // Semicircle (180° sweep) + let semi = Node::Ellipse(EllipseNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(gap, 0.0, s, s, 0.0), + size: Size { width: s, height: s }, + fills: Paints::new(vec![solid(220, 59, 59, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + inner_radius: None, + start_angle: 0.0, + angle: Some(180.0), + corner_radius: None, + effects: LayerEffects::default(), + layout_child: None, + }); + + // Donut (inner_radius = 0.5) + let donut = Node::Ellipse(EllipseNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(gap * 2.0, 0.0, s, s, 0.0), + size: Size { width: s, height: s }, + fills: Paints::new(vec![solid(59, 180, 75, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + inner_radius: Some(0.5), + start_angle: 0.0, + angle: None, + corner_radius: None, + effects: LayerEffects::default(), + layout_child: None, + }); + + // Pie wedge (90° sweep, start at 45°) + let pie = Node::Ellipse(EllipseNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(gap * 3.0, 0.0, s, s, 0.0), + size: Size { width: s, height: s }, + fills: Paints::new(vec![solid(255, 200, 40, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + inner_radius: None, + start_angle: 45.0, + angle: Some(90.0), + corner_radius: None, + effects: LayerEffects::default(), + layout_child: None, + }); + + // Rounded arc (270° sweep, inner_radius 0.6, corner_radius 8) + let rounded_arc = Node::Ellipse(EllipseNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(gap * 4.0, 0.0, s, s, 0.0), + size: Size { width: s, height: s }, + fills: Paints::new(vec![solid(128, 60, 200, 255)]), + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(Some(2.0)), + inner_radius: Some(0.6), + start_angle: 0.0, + angle: Some(270.0), + corner_radius: Some(8.0), + effects: LayerEffects::default(), + layout_child: None, + }); + + flat_scene("L0 Shape Arc", vec![full, semi, donut, pie, rounded_arc]) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_shape_polygon.rs b/crates/grida-canvas/examples/fixtures/l0_shape_polygon.rs new file mode 100644 index 0000000000..75f5fd30ed --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_shape_polygon.rs @@ -0,0 +1,162 @@ +use super::*; +use cg::cg::stroke_width::SingularStrokeWidth; +use math2::transform::AffineTransform; + +/// Regular polygons and star polygons with varying point counts and parameters. +pub fn build() -> Scene { + let s = 120.0; + let gap = 140.0; + + // Triangle (3 sides) + let tri = Node::RegularPolygon(RegularPolygonNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(0.0, 0.0, s, s, 0.0), + size: Size { width: s, height: s }, + point_count: 3, + corner_radius: 0.0, + fills: Paints::new(vec![solid(220, 59, 59, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + layout_child: None, + }); + + // Pentagon (5 sides, rounded corners) + let pent = Node::RegularPolygon(RegularPolygonNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(gap, 0.0, s, s, 0.0), + size: Size { width: s, height: s }, + point_count: 5, + corner_radius: 10.0, + fills: Paints::new(vec![solid(59, 100, 220, 255)]), + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(Some(1.5)), + layout_child: None, + }); + + // Hexagon (6 sides) + let hex = Node::RegularPolygon(RegularPolygonNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(gap * 2.0, 0.0, s, s, 0.0), + size: Size { width: s, height: s }, + point_count: 6, + corner_radius: 5.0, + fills: Paints::new(vec![solid(59, 180, 75, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + layout_child: None, + }); + + // Octagon (8 sides) + let oct = Node::RegularPolygon(RegularPolygonNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(gap * 3.0, 0.0, s, s, 0.0), + size: Size { width: s, height: s }, + point_count: 8, + corner_radius: 0.0, + fills: Paints::new(vec![solid(255, 200, 40, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + layout_child: None, + }); + + // 4-point star (sharp) + let star4 = Node::RegularStarPolygon(RegularStarPolygonNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(0.0, gap, s, s, 0.0), + size: Size { width: s, height: s }, + point_count: 4, + inner_radius: 0.3, + corner_radius: 0.0, + fills: Paints::new(vec![solid(128, 60, 200, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + layout_child: None, + }); + + // 5-point star (classic) + let star5 = Node::RegularStarPolygon(RegularStarPolygonNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(gap, gap, s, s, 0.0), + size: Size { width: s, height: s }, + point_count: 5, + inner_radius: 0.4, + corner_radius: 3.0, + fills: Paints::new(vec![solid(255, 215, 0, 255)]), + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(Some(1.0)), + layout_child: None, + }); + + // 6-point star (Star of David shape) + let star6 = Node::RegularStarPolygon(RegularStarPolygonNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(gap * 2.0, gap, s, s, 0.0), + size: Size { width: s, height: s }, + point_count: 6, + inner_radius: 0.5, + corner_radius: 0.0, + fills: Paints::new(vec![solid(59, 180, 180, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + layout_child: None, + }); + + // 8-point star (rounded) + let star8 = Node::RegularStarPolygon(RegularStarPolygonNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(gap * 3.0, gap, s, s, 0.0), + size: Size { width: s, height: s }, + point_count: 8, + inner_radius: 0.7, + corner_radius: 6.0, + fills: Paints::new(vec![solid(220, 120, 60, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + layout_child: None, + }); + + flat_scene( + "L0 Shape Polygon", + vec![tri, pent, hex, oct, star4, star5, star6, star8], + ) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_shapes.rs b/crates/grida-canvas/examples/fixtures/l0_shapes.rs new file mode 100644 index 0000000000..444289ca52 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_shapes.rs @@ -0,0 +1,86 @@ +use super::*; +use cg::vectornetwork::*; +use math2::transform::AffineTransform; + +pub fn build() -> Scene { + let rectangle = rect(0.0, 0.0, 200.0, 100.0, solid(220, 59, 59, 255)); + + let ell = ellipse(220.0, 10.0, 100.0, 80.0, solid(59, 100, 220, 255)); + + let polygon = Node::RegularPolygon(RegularPolygonNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(340.0, 0.0, 100.0, 100.0, 0.0), + size: Size { width: 100.0, height: 100.0 }, + point_count: 6, + corner_radius: 5.0, + fills: Paints::new(vec![solid(59, 180, 75, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + layout_child: None, + }); + + let star = Node::RegularStarPolygon(RegularStarPolygonNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(460.0, 0.0, 120.0, 120.0, 0.0), + size: Size { width: 120.0, height: 120.0 }, + point_count: 5, + inner_radius: 0.4, + corner_radius: 3.0, + fills: Paints::new(vec![solid(255, 200, 40, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + layout_child: None, + }); + + let ln = line(0.0, 140.0, 200.0, 0.0, 2.0); + + let txt = text(220.0, 130.0, "Hello, Grida!", 20.0, 400); + + let vector = Node::Vector(VectorNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(460.0, 130.0, 100.0, 100.0, 0.0), + network: VectorNetwork { + vertices: vec![(0.0, 0.0), (100.0, 0.0), (100.0, 100.0), (0.0, 100.0)], + segments: vec![ + VectorNetworkSegment { a: 0, b: 1, ta: (30.0, 0.0), tb: (-30.0, 0.0) }, + VectorNetworkSegment { a: 1, b: 2, ta: (0.0, 30.0), tb: (0.0, -30.0) }, + VectorNetworkSegment { a: 2, b: 3, ta: (-30.0, 0.0), tb: (30.0, 0.0) }, + VectorNetworkSegment { a: 3, b: 0, ta: (0.0, -30.0), tb: (0.0, 30.0) }, + ], + regions: vec![VectorNetworkRegion { + loops: vec![VectorNetworkLoop(vec![0, 1, 2, 3])], + fill_rule: FillRule::EvenOdd, + fills: None, + }], + }, + corner_radius: 0.0, + fills: Paints::new(vec![solid(128, 60, 200, 255)]), + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_width: 1.0, + stroke_width_profile: None, + stroke_align: StrokeAlign::Center, + stroke_cap: StrokeCap::Butt, + stroke_join: StrokeJoin::Miter, + stroke_miter_limit: StrokeMiterLimit(4.0), + stroke_dash_array: None, + marker_start_shape: StrokeMarkerPreset::None, + marker_end_shape: StrokeMarkerPreset::None, + layout_child: None, + }); + + flat_scene("L0 Shapes", vec![rectangle, ell, polygon, star, ln, txt, vector]) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_strokes.rs b/crates/grida-canvas/examples/fixtures/l0_strokes.rs new file mode 100644 index 0000000000..0e4853ece9 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_strokes.rs @@ -0,0 +1,81 @@ +use super::*; +use cg::cg::stroke_dasharray::StrokeDashArray; +use math2::transform::AffineTransform; + +fn stroked_rect( + x: f32, y: f32, + align: StrokeAlign, cap: StrokeCap, join: StrokeJoin, + width: f32, color: Paint, dash: Option, +) -> Node { + Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(x, y, 120.0, 80.0, 0.0), + size: Size { width: 120.0, height: 80.0 }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(240, 240, 240, 255)]), + strokes: Paints::new(vec![color]), + stroke_style: StrokeStyle { + stroke_align: align, + stroke_cap: cap, + stroke_join: join, + stroke_miter_limit: StrokeMiterLimit(4.0), + stroke_dash_array: dash, + }, + stroke_width: StrokeWidth::Uniform(width), + effects: LayerEffects::default(), + layout_child: None, + }) +} + +fn marker_line( + x: f32, y: f32, + start: StrokeMarkerPreset, end: StrokeMarkerPreset, +) -> Node { + Node::Line(LineNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::new(x, y, 0.0), + size: Size { width: 150.0, height: 0.0 }, + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_width: 2.0, + stroke_cap: StrokeCap::Round, + stroke_miter_limit: StrokeMiterLimit(4.0), + stroke_dash_array: None, + _data_stroke_align: StrokeAlign::Center, + marker_start_shape: start, + marker_end_shape: end, + layout_child: None, + }) +} + +pub fn build() -> Scene { + let gap = 140.0; + + let r1 = stroked_rect(0.0, 0.0, + StrokeAlign::Center, StrokeCap::Butt, StrokeJoin::Miter, + 2.0, solid(0, 0, 0, 255), None); + let r2 = stroked_rect(gap, 0.0, + StrokeAlign::Inside, StrokeCap::Round, StrokeJoin::Round, + 3.0, solid(59, 100, 220, 255), None); + let r3 = stroked_rect(gap * 2.0, 0.0, + StrokeAlign::Outside, StrokeCap::Square, StrokeJoin::Bevel, + 4.0, solid(59, 180, 75, 255), None); + let r4 = stroked_rect(gap * 3.0, 0.0, + StrokeAlign::Center, StrokeCap::Round, StrokeJoin::Miter, + 2.0, solid(0, 0, 0, 255), + Some(StrokeDashArray(vec![10.0, 5.0]))); + + let l1 = marker_line(0.0, 120.0, + StrokeMarkerPreset::Circle, StrokeMarkerPreset::EquilateralTriangle); + let l2 = marker_line(200.0, 120.0, + StrokeMarkerPreset::Diamond, StrokeMarkerPreset::VerticalBar); + + flat_scene("L0 Strokes", vec![r1, r2, r3, r4, l1, l2]) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_strokes_rect.rs b/crates/grida-canvas/examples/fixtures/l0_strokes_rect.rs new file mode 100644 index 0000000000..4af15eef9b --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_strokes_rect.rs @@ -0,0 +1,157 @@ +use super::*; +use cg::cg::stroke_width::RectangularStrokeWidth; + +pub fn build() -> Scene { + // Container with per-side stroke widths + let c1 = Node::Container(ContainerNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + rotation: 0.0, + position: LayoutPositioningBasis::Inset(EdgeInsets { + top: 0.0, right: 0.0, bottom: 0.0, left: 0.0, + }), + layout_container: LayoutContainerStyle::default(), + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(300.0), + layout_target_height: Some(200.0), + layout_min_width: None, layout_max_width: None, + layout_min_height: None, layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(250, 250, 250, 255)]), + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::Rectangular(RectangularStrokeWidth { + stroke_top_width: 1.0, stroke_right_width: 2.0, stroke_bottom_width: 3.0, stroke_left_width: 4.0, + }), + effects: LayerEffects::default(), + clip: false, + }); + + // Container with uniform stroke + per-side corner radii + let c2 = Node::Container(ContainerNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + rotation: 0.0, + position: LayoutPositioningBasis::Inset(EdgeInsets { + top: 0.0, right: 0.0, bottom: 0.0, left: 320.0, + }), + layout_container: LayoutContainerStyle::default(), + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(300.0), + layout_target_height: Some(200.0), + layout_min_width: None, layout_max_width: None, + layout_min_height: None, layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: { + use cg::cg::types::Radius; + RectangularCornerRadius { + tl: Radius::circular(0.0), + tr: Radius::circular(8.0), + bl: Radius::circular(16.0), + br: Radius::circular(24.0), + } + }, + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(250, 250, 250, 255)]), + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::Uniform(2.0), + effects: LayerEffects::default(), + clip: false, + }); + + // Container with varying per-side stroke widths + dashed pattern + let c3 = Node::Container(ContainerNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + rotation: 0.0, + position: LayoutPositioningBasis::Inset(EdgeInsets { + top: 220.0, right: 0.0, bottom: 0.0, left: 0.0, + }), + layout_container: LayoutContainerStyle::default(), + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(300.0), + layout_target_height: Some(200.0), + layout_min_width: None, layout_max_width: None, + layout_min_height: None, layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(250, 250, 250, 255)]), + strokes: Paints::new(vec![solid(220, 59, 59, 255)]), + stroke_style: StrokeStyle { + stroke_align: StrokeAlign::Inside, + stroke_cap: StrokeCap::Round, + stroke_join: StrokeJoin::Round, + stroke_miter_limit: StrokeMiterLimit(4.0), + stroke_dash_array: Some(cg::cg::stroke_dasharray::StrokeDashArray(vec![12.0, 6.0, 4.0, 6.0])), + }, + stroke_width: StrokeWidth::Rectangular(RectangularStrokeWidth { + stroke_top_width: 2.0, stroke_right_width: 4.0, stroke_bottom_width: 6.0, stroke_left_width: 8.0, + }), + effects: LayerEffects::default(), + clip: false, + }); + + // Container with per-side corners + per-side stroke widths + dashed pattern + let c4 = Node::Container(ContainerNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + rotation: 0.0, + position: LayoutPositioningBasis::Inset(EdgeInsets { + top: 220.0, right: 0.0, bottom: 0.0, left: 320.0, + }), + layout_container: LayoutContainerStyle::default(), + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(300.0), + layout_target_height: Some(200.0), + layout_min_width: None, layout_max_width: None, + layout_min_height: None, layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: { + use cg::cg::types::Radius; + RectangularCornerRadius { + tl: Radius::circular(12.0), + tr: Radius::circular(0.0), + bl: Radius::circular(0.0), + br: Radius::circular(12.0), + } + }, + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(250, 250, 250, 255)]), + strokes: Paints::new(vec![solid(59, 100, 220, 255)]), + stroke_style: StrokeStyle { + stroke_align: StrokeAlign::Center, + stroke_cap: StrokeCap::Butt, + stroke_join: StrokeJoin::Miter, + stroke_miter_limit: StrokeMiterLimit(4.0), + stroke_dash_array: Some(cg::cg::stroke_dasharray::StrokeDashArray(vec![8.0, 4.0])), + }, + stroke_width: StrokeWidth::Rectangular(RectangularStrokeWidth { + stroke_top_width: 1.0, stroke_right_width: 3.0, stroke_bottom_width: 5.0, stroke_left_width: 3.0, + }), + effects: LayerEffects::default(), + clip: false, + }); + + let pairs = vec![(1u64, c1), (2u64, c2), (3u64, c3), (4u64, c4)]; + build_scene("L0 Strokes Rect", None, pairs, HashMap::new(), vec![1, 2, 3, 4]) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_type.rs b/crates/grida-canvas/examples/fixtures/l0_type.rs new file mode 100644 index 0000000000..5d0a6609e0 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_type.rs @@ -0,0 +1,246 @@ +use super::*; +use cg::cg::color::CGColor; +use cg::cg::fe::*; + +fn tspan( + x: f32, y: f32, + content: &str, + font_size: f32, + font_weight: u32, + h_align: TextAlign, + v_align: TextAlignVertical, + width: Option, + height: Option, +) -> Node { + Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(x, y, 0.0), + width, + height, + layout_child: None, + text: content.to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", font_size); + ts.font_weight = FontWeight(font_weight); + ts + }, + text_align: h_align, + text_align_vertical: v_align, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + }) +} + +pub fn build() -> Scene { + let y_gap = 50.0; + + // Regular 16px, Left/Top + let t1 = tspan(0.0, 0.0, + "Regular 16px", 16.0, 400, + TextAlign::Left, TextAlignVertical::Top, None, None); + + // Bold 24px, Center/Center + let t2 = tspan(0.0, y_gap, + "Bold 24px", 24.0, 700, + TextAlign::Center, TextAlignVertical::Center, + Some(300.0), Some(40.0)); + + // Right aligned + let t3 = tspan(0.0, y_gap * 2.0, + "Right Aligned", 16.0, 400, + TextAlign::Right, TextAlignVertical::Bottom, + Some(300.0), Some(30.0)); + + // Justified text + let t4 = tspan(0.0, y_gap * 3.0, + "Justified Text with enough words to wrap across multiple lines for demonstration.", + 14.0, 400, + TextAlign::Justify, TextAlignVertical::Top, + Some(200.0), None); + + // Text with stroke + let t5 = Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, y_gap * 5.0, 0.0), + width: None, + height: None, + layout_child: None, + text: "With Stroke".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 20.0); + ts.font_weight = FontWeight(400); + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![solid(220, 59, 59, 255)]), + stroke_width: 1.0, + stroke_align: StrokeAlign::Outside, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + }); + + // Text with drop shadow + let t6 = Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, y_gap * 6.0, 0.0), + width: None, + height: None, + layout_child: None, + text: "Drop Shadow".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 20.0); + ts.font_weight = FontWeight(400); + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects { + shadows: vec![FilterShadowEffect::DropShadow(FeShadow { + dx: 2.0, dy: 2.0, blur: 4.0, spread: 0.0, + color: CGColor { r: 0, g: 0, b: 0, a: 153 }, + active: true, + })], + ..LayerEffects::default() + }, + }); + + // Max lines + ellipsis + let t7 = Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, y_gap * 7.0, 0.0), + width: Some(120.0), + height: None, + layout_child: None, + text: "Max 2 Lines with truncation and ellipsis at the end".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 14.0); + ts.font_weight = FontWeight(400); + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: Some(2), + ellipsis: Some("\u{2026}".to_owned()), + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + }); + + // Letter spacing + line height + let t8 = Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, y_gap * 8.5, 0.0), + width: Some(300.0), + height: None, + layout_child: None, + text: "Tracked + Tall Line Height".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 16.0); + ts.letter_spacing = TextLetterSpacing::Fixed(4.0); + ts.line_height = TextLineHeight::Factor(2.0); + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + }); + + // Underline decoration (red, 2px thick) + let t9 = Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, y_gap * 10.0, 0.0), + width: None, + height: None, + layout_child: None, + text: "Underlined Text".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 18.0); + ts.text_decoration = Some(TextDecorationRec { + text_decoration_line: TextDecorationLine::Underline, + text_decoration_color: Some(CGColor { r: 220, g: 59, b: 59, a: 255 }), + text_decoration_style: Some(TextDecorationStyle::Solid), + text_decoration_skip_ink: Some(true), + text_decoration_thickness: Some(2.0), + }); + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + }); + + // UPPERCASE transform + let t10 = Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, y_gap * 11.0, 0.0), + width: None, + height: None, + layout_child: None, + text: "uppercase transform".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 16.0); + ts.text_transform = TextTransform::Uppercase; + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + }); + + flat_scene("L0 Type", vec![t1, t2, t3, t4, t5, t6, t7, t8, t9, t10]) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_type_features.rs b/crates/grida-canvas/examples/fixtures/l0_type_features.rs new file mode 100644 index 0000000000..cc8cbde935 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_type_features.rs @@ -0,0 +1,181 @@ +use super::*; + +/// OpenType font features: ligatures, small caps, stylistic sets, etc. +pub fn build() -> Scene { + let y_gap = 50.0; + + // Ligatures disabled + let t1 = Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, 0.0, 0.0), + width: None, + height: None, + layout_child: None, + text: "ffi ffl — liga off".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 20.0); + ts.font_features = Some(vec![ + FontFeature { tag: "liga".to_owned(), value: false }, + ]); + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + }); + + // Ligatures enabled (default, explicit) + let t2 = Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, y_gap, 0.0), + width: None, + height: None, + layout_child: None, + text: "ffi ffl — liga on".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 20.0); + ts.font_features = Some(vec![ + FontFeature { tag: "liga".to_owned(), value: true }, + ]); + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + }); + + // Small caps + let t3 = Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, y_gap * 2.0, 0.0), + width: None, + height: None, + layout_child: None, + text: "Small Caps Text — smcp".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 20.0); + ts.font_features = Some(vec![ + FontFeature { tag: "smcp".to_owned(), value: true }, + ]); + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + }); + + // Stylistic set 01 + let t4 = Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, y_gap * 3.0, 0.0), + width: None, + height: None, + layout_child: None, + text: "Stylistic Set 01 — ss01".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 20.0); + ts.font_features = Some(vec![ + FontFeature { tag: "ss01".to_owned(), value: true }, + ]); + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + }); + + // Tabular numbers + slashed zero + let t5 = Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, y_gap * 4.0, 0.0), + width: None, + height: None, + layout_child: None, + text: "0123456789 — tnum + zero".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 20.0); + ts.font_features = Some(vec![ + FontFeature { tag: "tnum".to_owned(), value: true }, + FontFeature { tag: "zero".to_owned(), value: true }, + ]); + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + }); + + // Kerning off + let t6 = Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, y_gap * 5.0, 0.0), + width: None, + height: None, + layout_child: None, + text: "AVAW Typography — kern off".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 20.0); + ts.font_kerning = false; + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + }); + + flat_scene("L0 Type Features", vec![t1, t2, t3, t4, t5, t6]) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_type_fvar.rs b/crates/grida-canvas/examples/fixtures/l0_type_fvar.rs new file mode 100644 index 0000000000..0652f3b7d3 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_type_fvar.rs @@ -0,0 +1,161 @@ +use super::*; + +/// Variable font axes: weight, width, optical sizing, and custom fvar axes. +pub fn build() -> Scene { + let y_gap = 50.0; + + // Weight axis via font_weight (100..900) + let weights = [ + (100, "Thin 100"), + (300, "Light 300"), + (400, "Regular 400"), + (700, "Bold 700"), + (900, "Black 900"), + ]; + + let mut nodes: Vec = Vec::new(); + + for (i, (w, label)) in weights.iter().enumerate() { + nodes.push(Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, (i as f32) * y_gap, 0.0), + width: None, + height: None, + layout_child: None, + text: label.to_string(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 20.0); + ts.font_weight = FontWeight(*w); + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + })); + } + + let base_y = (weights.len() as f32) * y_gap; + + // Width axis (font_width field — high-level wdth exposure) + nodes.push(Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, base_y, 0.0), + width: None, + height: None, + layout_child: None, + text: "Condensed (width=75)".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 20.0); + ts.font_width = Some(75.0); + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + })); + + // Optical sizing + nodes.push(Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, base_y + y_gap, 0.0), + width: None, + height: None, + layout_child: None, + text: "Optical Size Fixed(48)".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 20.0); + ts.font_optical_sizing = FontOpticalSizing::Fixed(48.0); + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + })); + + // Custom fvar axes via font_variations + nodes.push(Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, base_y + y_gap * 2.0, 0.0), + width: None, + height: None, + layout_child: None, + text: "Custom Axes: wght=600 wdth=80 GRAD=50".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Roboto Flex", 20.0); + ts.font_variations = Some(vec![ + FontVariation { axis: "wght".to_owned(), value: 600.0 }, + FontVariation { axis: "wdth".to_owned(), value: 80.0 }, + FontVariation { axis: "GRAD".to_owned(), value: 50.0 }, + ]); + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + })); + + // Italic style + nodes.push(Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, base_y + y_gap * 3.0, 0.0), + width: None, + height: None, + layout_child: None, + text: "Italic Style".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", 20.0); + ts.font_style_italic = true; + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + })); + + flat_scene("L0 Type fvar", nodes) +} diff --git a/crates/grida-canvas/examples/fixtures/l0_vector.rs b/crates/grida-canvas/examples/fixtures/l0_vector.rs new file mode 100644 index 0000000000..a6e47ef10c --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/l0_vector.rs @@ -0,0 +1,152 @@ +use super::*; +use cg::cg::stroke_dasharray::StrokeDashArray; +use cg::vectornetwork::*; +use math2::transform::AffineTransform; + +/// Vector network nodes: closed shape, open path, multi-region, variable-width stroke. +pub fn build() -> Scene { + // Closed bezier quad (4 curved segments forming a rounded square) + let closed = Node::Vector(VectorNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(0.0, 0.0, 100.0, 100.0, 0.0), + network: VectorNetwork { + vertices: vec![(0.0, 0.0), (100.0, 0.0), (100.0, 100.0), (0.0, 100.0)], + segments: vec![ + VectorNetworkSegment { a: 0, b: 1, ta: (30.0, 0.0), tb: (-30.0, 0.0) }, + VectorNetworkSegment { a: 1, b: 2, ta: (0.0, 30.0), tb: (0.0, -30.0) }, + VectorNetworkSegment { a: 2, b: 3, ta: (-30.0, 0.0), tb: (30.0, 0.0) }, + VectorNetworkSegment { a: 3, b: 0, ta: (0.0, -30.0), tb: (0.0, 30.0) }, + ], + regions: vec![VectorNetworkRegion { + loops: vec![VectorNetworkLoop(vec![0, 1, 2, 3])], + fill_rule: FillRule::EvenOdd, + fills: None, + }], + }, + corner_radius: 0.0, + fills: Paints::new(vec![solid(59, 100, 220, 255)]), + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_width: 1.5, + stroke_width_profile: None, + stroke_align: StrokeAlign::Center, + stroke_cap: StrokeCap::Butt, + stroke_join: StrokeJoin::Miter, + stroke_miter_limit: StrokeMiterLimit(4.0), + stroke_dash_array: None, + marker_start_shape: StrokeMarkerPreset::None, + marker_end_shape: StrokeMarkerPreset::None, + layout_child: None, + }); + + // Open path (3 vertices, 2 segments, no region) + let open = Node::Vector(VectorNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(140.0, 0.0, 120.0, 80.0, 0.0), + network: VectorNetwork { + vertices: vec![(0.0, 80.0), (60.0, 0.0), (120.0, 80.0)], + segments: vec![ + VectorNetworkSegment { a: 0, b: 1, ta: (20.0, -30.0), tb: (-20.0, 10.0) }, + VectorNetworkSegment { a: 1, b: 2, ta: (20.0, 10.0), tb: (-20.0, -30.0) }, + ], + regions: vec![], + }, + corner_radius: 0.0, + fills: Paints::new(vec![]), + strokes: Paints::new(vec![solid(220, 59, 59, 255)]), + stroke_width: 3.0, + stroke_width_profile: None, + stroke_align: StrokeAlign::Center, + stroke_cap: StrokeCap::Round, + stroke_join: StrokeJoin::Round, + stroke_miter_limit: StrokeMiterLimit(4.0), + stroke_dash_array: None, + marker_start_shape: StrokeMarkerPreset::Circle, + marker_end_shape: StrokeMarkerPreset::EquilateralTriangle, + layout_child: None, + }); + + // Region with explicit fill + dashed stroke + let region_fill = Node::Vector(VectorNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(0.0, 140.0, 100.0, 100.0, 0.0), + network: VectorNetwork { + vertices: vec![(50.0, 0.0), (100.0, 100.0), (0.0, 100.0)], + segments: vec![ + VectorNetworkSegment { a: 0, b: 1, ta: (0.0, 0.0), tb: (0.0, 0.0) }, + VectorNetworkSegment { a: 1, b: 2, ta: (0.0, 0.0), tb: (0.0, 0.0) }, + VectorNetworkSegment { a: 2, b: 0, ta: (0.0, 0.0), tb: (0.0, 0.0) }, + ], + regions: vec![VectorNetworkRegion { + loops: vec![VectorNetworkLoop(vec![0, 1, 2])], + fill_rule: FillRule::NonZero, + fills: Some(Paints::new(vec![solid(255, 200, 40, 255)])), + }], + }, + corner_radius: 0.0, + fills: Paints::new(vec![solid(59, 180, 75, 255)]), + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_width: 2.0, + stroke_width_profile: None, + stroke_align: StrokeAlign::Center, + stroke_cap: StrokeCap::Butt, + stroke_join: StrokeJoin::Miter, + stroke_miter_limit: StrokeMiterLimit(4.0), + stroke_dash_array: Some(StrokeDashArray(vec![8.0, 4.0])), + marker_start_shape: StrokeMarkerPreset::None, + marker_end_shape: StrokeMarkerPreset::None, + layout_child: None, + }); + + // Variable-width stroke profile + let varwidth = Node::Vector(VectorNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(140.0, 140.0, 120.0, 80.0, 0.0), + network: VectorNetwork { + vertices: vec![(0.0, 40.0), (60.0, 0.0), (120.0, 40.0), (60.0, 80.0)], + segments: vec![ + VectorNetworkSegment { a: 0, b: 1, ta: (20.0, -20.0), tb: (-20.0, 10.0) }, + VectorNetworkSegment { a: 1, b: 2, ta: (20.0, 10.0), tb: (-20.0, -20.0) }, + VectorNetworkSegment { a: 2, b: 3, ta: (-20.0, 20.0), tb: (20.0, -10.0) }, + ], + regions: vec![], + }, + corner_radius: 0.0, + fills: Paints::new(vec![]), + strokes: Paints::new(vec![solid(128, 60, 200, 255)]), + stroke_width: 4.0, + stroke_width_profile: Some(cg::cg::varwidth::VarWidthProfile { + base: 2.0, + stops: vec![ + cg::cg::varwidth::WidthStop { u: 0.0, r: 1.0 }, + cg::cg::varwidth::WidthStop { u: 0.5, r: 6.0 }, + cg::cg::varwidth::WidthStop { u: 1.0, r: 1.0 }, + ], + }), + stroke_align: StrokeAlign::Center, + stroke_cap: StrokeCap::Round, + stroke_join: StrokeJoin::Round, + stroke_miter_limit: StrokeMiterLimit(4.0), + stroke_dash_array: None, + marker_start_shape: StrokeMarkerPreset::None, + marker_end_shape: StrokeMarkerPreset::None, + layout_child: None, + }); + + flat_scene("L0 Vector", vec![closed, open, region_fill, varwidth]) +} diff --git a/crates/grida-canvas/examples/fixtures/mod.rs b/crates/grida-canvas/examples/fixtures/mod.rs new file mode 100644 index 0000000000..2eeba87043 --- /dev/null +++ b/crates/grida-canvas/examples/fixtures/mod.rs @@ -0,0 +1,363 @@ +//! Shared helpers for L0 fixture generators. + +use std::collections::HashMap; + +use cg::cg::alignment::Alignment; +use cg::cg::color::CGColor; +use cg::cg::stroke_width::{SingularStrokeWidth, StrokeWidth}; +use cg::cg::tilemode::TileMode; +use cg::cg::types::*; +use math2::box_fit::BoxFit; +use cg::io::io_grida_fbs; +use cg::node::scene_graph::SceneGraph; +use cg::node::schema::*; +use math2::transform::AffineTransform; + +pub mod l0_boolean_operation; +pub mod l0_container; +pub mod l0_effects; +pub mod l0_group; +pub mod l0_effects_glass; +pub mod l0_image; +pub mod l0_image_filters; +pub mod l0_layout_flex; +pub mod l0_layout_position; +pub mod l0_layout_transform; +pub mod l0_masks; +pub mod l0_paints; +pub mod l0_paints_stack; +pub mod l0_shape_arc; +pub mod l0_shape_polygon; +pub mod l0_shapes; +pub mod l0_strokes; +pub mod l0_strokes_rect; +pub mod l0_type; +pub mod l0_type_features; +pub mod l0_type_fvar; +pub mod l0_vector; + +// ═════════════════════════════════════════════════════════════════════════════ +// Scene building +// ═════════════════════════════════════════════════════════════════════════════ + +/// Build a `Scene` from `(id, node)` pairs, parent→children links, and root ids. +pub fn build_scene( + name: &str, + bg: Option, + nodes: Vec<(NodeId, Node)>, + links: HashMap>, + roots: Vec, +) -> Scene { + let graph = SceneGraph::new_from_snapshot(nodes, links, roots); + Scene { + name: name.to_owned(), + graph, + background_color: bg, + } +} + +/// Build id_map and position_map with a prefix to avoid collisions in multi-scene files. every node ID to avoid collisions in multi-scene files. +pub fn build_maps_prefixed( + scene: &Scene, + id_map: &mut HashMap, + position_map: &mut HashMap, + prefix: &str, +) { + fn walk( + graph: &SceneGraph, + nid: &NodeId, + counter: &mut usize, + id_map: &mut HashMap, + position_map: &mut HashMap, + prefix: &str, + ) { + id_map.entry(*nid).or_insert_with(|| format!("{prefix}n{nid}")); + if let Some(children) = graph.get_children(nid) { + for (i, child) in children.clone().iter().enumerate() { + let pos = format!("a{i:04}"); + position_map.insert(*child, pos); + walk(graph, child, counter, id_map, position_map, prefix); + } + } + *counter += 1; + } + let mut counter = 0usize; + for root in scene.graph.roots() { + walk(&scene.graph, &root, &mut counter, id_map, position_map, prefix); + } +} + +fn fixtures_dir() -> std::path::PathBuf { + let manifest = std::path::Path::new(env!("CARGO_MANIFEST_DIR")); + manifest.join("../../fixtures/test-grida") +} + +/// Encode multiple scenes into a single `.grida` file and write to disk. +/// Each entry is `(scene_id_suffix, scene)`. The scene_id is derived from the scene name. +pub fn write_multi_fixture(scenes: &[(&str, Scene)], name: &str) { + let mut entries_data: Vec<( + String, + HashMap, + HashMap, + )> = Vec::new(); + + for (i, (key, scene)) in scenes.iter().enumerate() { + let scene_id = key.to_string(); + let mut id_map = HashMap::new(); + let mut position_map = HashMap::new(); + // Prefix node IDs with scene index to avoid collisions across scenes + // in the shared flat node list. + build_maps_prefixed(scene, &mut id_map, &mut position_map, &format!("s{}_", i)); + entries_data.push((scene_id, id_map, position_map)); + } + + let entries: Vec<( + &str, + &Scene, + &HashMap, + &HashMap, + )> = scenes + .iter() + .zip(entries_data.iter()) + .map(|((_, scene), (scene_id, id_map, position_map))| { + (scene_id.as_str(), scene, id_map, position_map) + }) + .collect(); + + let bytes = io_grida_fbs::encode_multi(&entries); + assert!(!bytes.is_empty(), "{name}: encoded bytes empty"); + + // Verify decode: all scenes should be recoverable + let decoded = io_grida_fbs::decode_all(&bytes) + .unwrap_or_else(|e| panic!("{name}: decode failed: {e}")); + assert_eq!( + decoded.len(), + scenes.len(), + "{name}: expected {} scenes, got {}", + scenes.len(), + decoded.len() + ); + for (i, ((_, original), decoded_scene)) in scenes.iter().zip(decoded.iter()).enumerate() { + assert_eq!( + original.name, decoded_scene.name, + "{name}: scene[{i}] name mismatch" + ); + } + + let dir = fixtures_dir(); + std::fs::create_dir_all(&dir).unwrap(); + let path = dir.join(format!("{name}.grida")); + std::fs::write(&path, &bytes).unwrap(); + eprintln!( + "Wrote {} bytes ({} scenes) to {}", + bytes.len(), + scenes.len(), + path.display() + ); +} + +// ═════════════════════════════════════════════════════════════════════════════ +// Paint builders +// ═════════════════════════════════════════════════════════════════════════════ + +pub fn solid(r: u8, g: u8, b: u8, a: u8) -> Paint { + Paint::Solid(SolidPaint { + active: true, + color: CGColor { r, g, b, a }, + blend_mode: BlendMode::Normal, + }) +} + +pub fn linear_gradient() -> Paint { + Paint::LinearGradient(LinearGradientPaint { + active: true, + xy1: Alignment::CENTER_LEFT, + xy2: Alignment::CENTER_RIGHT, + tile_mode: TileMode::default(), + transform: AffineTransform::default(), + stops: vec![ + GradientStop { offset: 0.0, color: CGColor { r: 255, g: 0, b: 0, a: 255 } }, + GradientStop { offset: 1.0, color: CGColor { r: 0, g: 0, b: 255, a: 255 } }, + ], + opacity: 1.0, + blend_mode: BlendMode::Normal, + }) +} + +pub fn radial_gradient() -> Paint { + Paint::RadialGradient(RadialGradientPaint { + active: true, + transform: AffineTransform::default(), + stops: vec![ + GradientStop { offset: 0.0, color: CGColor { r: 255, g: 255, b: 0, a: 255 } }, + GradientStop { offset: 1.0, color: CGColor { r: 0, g: 128, b: 0, a: 200 } }, + ], + opacity: 0.8, + blend_mode: BlendMode::Normal, + tile_mode: TileMode::default(), + }) +} + +pub fn sweep_gradient() -> Paint { + Paint::SweepGradient(SweepGradientPaint { + active: true, + transform: AffineTransform::default(), + stops: vec![ + GradientStop { offset: 0.0, color: CGColor { r: 0, g: 255, b: 255, a: 255 } }, + GradientStop { offset: 0.5, color: CGColor { r: 255, g: 0, b: 255, a: 255 } }, + GradientStop { offset: 1.0, color: CGColor { r: 255, g: 255, b: 0, a: 255 } }, + ], + opacity: 1.0, + blend_mode: BlendMode::Normal, + }) +} + +/// The system checker image bundled in the renderer. Use this for all fixture +/// image paints so they actually render in the native demo. +pub const SYSTEM_IMAGE: &str = "system://images/checker-16-strip-L98L92.png"; + +pub fn image_paint() -> Paint { + image_paint_with(ResourceRef::HASH(SYSTEM_IMAGE.to_owned()), ImagePaintFit::Fit(BoxFit::Cover)) +} + +pub fn image_paint_with(image: ResourceRef, fit: ImagePaintFit) -> Paint { + Paint::Image(ImagePaint { + active: true, + image, + fit, + filters: ImageFilters::default(), + opacity: 1.0, + blend_mode: BlendMode::Normal, + quarter_turns: 0, + alignement: Alignment::CENTER, + }) +} + +// ═════════════════════════════════════════════════════════════════════════════ +// Node builders +// ═════════════════════════════════════════════════════════════════════════════ + +/// Simple rectangle with one fill. +pub fn rect(x: f32, y: f32, w: f32, h: f32, fill: Paint) -> Node { + Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(x, y, w, h, 0.0), + size: Size { width: w, height: h }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![fill]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: None, + }) +} + +/// Rectangle with rotation. +pub fn rect_rotated(x: f32, y: f32, w: f32, h: f32, rotation: f32, fill: Paint) -> Node { + Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(x, y, w, h, rotation), + size: Size { width: w, height: h }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![fill]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: None, + }) +} + +/// Simple ellipse with one fill. +pub fn ellipse(x: f32, y: f32, w: f32, h: f32, fill: Paint) -> Node { + Node::Ellipse(EllipseNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(x, y, w, h, 0.0), + size: Size { width: w, height: h }, + fills: Paints::new(vec![fill]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + inner_radius: None, + start_angle: 0.0, + angle: None, + corner_radius: None, + effects: LayerEffects::default(), + layout_child: None, + }) +} + +/// Simple line. +pub fn line(x: f32, y: f32, length: f32, rotation: f32, stroke_width: f32) -> Node { + Node::Line(LineNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::new(x, y, rotation), + size: Size { width: length, height: 0.0 }, + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_width, + stroke_cap: StrokeCap::Butt, + stroke_miter_limit: StrokeMiterLimit(4.0), + stroke_dash_array: None, + _data_stroke_align: StrokeAlign::Center, + marker_start_shape: StrokeMarkerPreset::None, + marker_end_shape: StrokeMarkerPreset::None, + layout_child: None, + }) +} + +/// Simple text span. +pub fn text(x: f32, y: f32, content: &str, font_size: f32, font_weight: u32) -> Node { + Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(x, y, 0.0), + width: None, + height: None, + layout_child: None, + text: content.to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Inter", font_size); + ts.font_weight = FontWeight(font_weight); + ts + }, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + }) +} + +/// Simple flat scene: all nodes at the root level, auto-assigned positions. +pub fn flat_scene(name: &str, nodes: Vec) -> Scene { + let mut pairs = Vec::new(); + for (i, node) in nodes.into_iter().enumerate() { + pairs.push(((i + 1) as u64, node)); + } + let roots: Vec = pairs.iter().map(|(id, _)| *id).collect(); + build_scene(name, None, pairs, HashMap::new(), roots) +} + + diff --git a/crates/grida-canvas/examples/golden_type_decoration.rs b/crates/grida-canvas/examples/golden_type_decoration.rs index 00f0af156d..f13de23ee4 100644 --- a/crates/grida-canvas/examples/golden_type_decoration.rs +++ b/crates/grida-canvas/examples/golden_type_decoration.rs @@ -99,7 +99,7 @@ fn main() { text_decoration_color: Some(CGColor::RED), text_decoration_style: None, text_decoration_skip_ink: None, - text_decoration_thinkness: None, + text_decoration_thickness: None, }), font_family: "Geist".to_string(), font_size: font_size, @@ -153,7 +153,7 @@ fn main() { text_decoration_color: Some(CGColor::BLACK), text_decoration_style: Some(*style), text_decoration_skip_ink: None, - text_decoration_thinkness: None, + text_decoration_thickness: None, }), font_family: "Geist".to_string(), font_size: font_size, @@ -207,7 +207,7 @@ fn main() { text_decoration_color: Some(*color), text_decoration_style: None, text_decoration_skip_ink: None, - text_decoration_thinkness: None, + text_decoration_thickness: None, }), font_family: "Geist".to_string(), font_size: font_size, @@ -265,7 +265,7 @@ fn main() { text_decoration_color: Some(CGColor::BLACK), text_decoration_style: None, text_decoration_skip_ink: None, - text_decoration_thinkness: Some(*thickness), + text_decoration_thickness: Some(*thickness), }), font_family: "Geist".to_string(), font_size: font_size, @@ -317,7 +317,7 @@ fn main() { text_decoration_color: Some(CGColor::from_rgba(255, 0, 0, 255)), text_decoration_style: None, text_decoration_skip_ink: Some(*skip_ink), - text_decoration_thinkness: None, + text_decoration_thickness: None, }), font_family: "Geist".to_string(), font_size: font_size, @@ -388,7 +388,7 @@ fn main() { text_decoration_color: *color, text_decoration_style: *style, text_decoration_skip_ink: None, - text_decoration_thinkness: *thickness, + text_decoration_thickness: *thickness, }), font_family: "Geist".to_string(), font_size: font_size, @@ -445,7 +445,7 @@ fn main() { text_decoration_color: Some(CGColor::from_rgba(100, 100, 100, 255)), text_decoration_style: Some(TextDecorationStyle::Solid), text_decoration_skip_ink: None, - text_decoration_thinkness: Some(1.5), + text_decoration_thickness: Some(1.5), }), font_family: "Geist".to_string(), font_size: font_size, diff --git a/crates/grida-canvas/examples/golden_type_decoration_color.rs b/crates/grida-canvas/examples/golden_type_decoration_color.rs index f11251c965..04b2b5d3de 100644 --- a/crates/grida-canvas/examples/golden_type_decoration_color.rs +++ b/crates/grida-canvas/examples/golden_type_decoration_color.rs @@ -90,7 +90,7 @@ fn main() { text_decoration_color: Some(*color), text_decoration_style: None, text_decoration_skip_ink: None, - text_decoration_thinkness: Some(1.5), + text_decoration_thickness: Some(1.5), }), font_family: "Geist".to_string(), font_size: font_size, diff --git a/crates/grida-canvas/examples/golden_type_emoji_placeholder.rs b/crates/grida-canvas/examples/golden_type_emoji_placeholder.rs index 69482d4a8b..d6f21d6da1 100644 --- a/crates/grida-canvas/examples/golden_type_emoji_placeholder.rs +++ b/crates/grida-canvas/examples/golden_type_emoji_placeholder.rs @@ -108,7 +108,7 @@ fn main() { text_decoration_color: Some(CGColor::BLUE), text_decoration_style: None, text_decoration_skip_ink: None, - text_decoration_thinkness: None, + text_decoration_thickness: None, }); let mut ts = textstyle(&style, &None); ts.set_foreground_paint(&paint); diff --git a/crates/grida-canvas/examples/tool_gen_fixtures.rs b/crates/grida-canvas/examples/tool_gen_fixtures.rs new file mode 100644 index 0000000000..40f73a9519 --- /dev/null +++ b/crates/grida-canvas/examples/tool_gen_fixtures.rs @@ -0,0 +1,44 @@ +//! Fixture Generator Tool +//! +//! Packs all L0 scene builders into a single `L0.grida` file and writes it to +//! `fixtures/test-grida/`. +//! +//! ## Usage +//! +//! ```bash +//! cargo run --package cg --example tool_gen_fixtures +//! ``` +//! +//! ## Output +//! +//! On success the tool prints the byte count, scene count, and output path. + +mod fixtures; + +fn main() { + let scenes: Vec<(&str, _)> = vec![ + ("L0-shapes", fixtures::l0_shapes::build()), + ("L0-shape-arc", fixtures::l0_shape_arc::build()), + ("L0-shape-polygon", fixtures::l0_shape_polygon::build()), + ("L0-vector", fixtures::l0_vector::build()), + ("L0-paints", fixtures::l0_paints::build()), + ("L0-paints-stack", fixtures::l0_paints_stack::build()), + ("L0-strokes", fixtures::l0_strokes::build()), + ("L0-strokes-rect", fixtures::l0_strokes_rect::build()), + ("L0-image", fixtures::l0_image::build()), + ("L0-image-filters", fixtures::l0_image_filters::build()), + ("L0-effects", fixtures::l0_effects::build()), + ("L0-effects-glass", fixtures::l0_effects_glass::build()), + ("L0-type", fixtures::l0_type::build()), + ("L0-type-fvar", fixtures::l0_type_fvar::build()), + ("L0-type-features", fixtures::l0_type_features::build()), + ("L0-masks", fixtures::l0_masks::build()), + ("L0-boolean-operation", fixtures::l0_boolean_operation::build()), + ("L0-container", fixtures::l0_container::build()), + ("L0-group", fixtures::l0_group::build()), + ("L0-layout-position", fixtures::l0_layout_position::build()), + ("L0-layout-flex", fixtures::l0_layout_flex::build()), + ("L0-layout-transform", fixtures::l0_layout_transform::build()), + ]; + fixtures::write_multi_fixture(&scenes, "L0"); +} diff --git a/crates/grida-canvas/package.json b/crates/grida-canvas/package.json index a3d97ea174..9cde75502d 100644 --- a/crates/grida-canvas/package.json +++ b/crates/grida-canvas/package.json @@ -4,6 +4,10 @@ "description": "turbo ci rust wrapper", "scripts": { "build": "cargo build --release", + "flatc:clean": "rm -f src/io/generated/grida.rs", + "flatc:generate": "pnpm flatc:clean && python3 ../../bin/activate-flatc -- --rust -o src/io/generated ../../format/grida.fbs && mv src/io/generated/grida_generated.rs src/io/generated/grida.rs", + "generate": "pnpm flatc:generate", + "prebuild": "pnpm flatc:generate", "test": "cargo test" } } diff --git a/crates/grida-canvas/src/cg/types.rs b/crates/grida-canvas/src/cg/types.rs index ca1273fc58..6ae4b93426 100644 --- a/crates/grida-canvas/src/cg/types.rs +++ b/crates/grida-canvas/src/cg/types.rs @@ -1407,7 +1407,7 @@ pub struct TextDecorationRec { pub text_decoration_skip_ink: Option, /// The thickness of the decoration stroke as a multiplier of the thickness defined by the font. - pub text_decoration_thinkness: Option, + pub text_decoration_thickness: Option, } impl TextDecorationRec { @@ -1417,7 +1417,7 @@ impl TextDecorationRec { text_decoration_color: None, text_decoration_style: None, text_decoration_skip_ink: None, - text_decoration_thinkness: None, + text_decoration_thickness: None, } } @@ -1427,7 +1427,7 @@ impl TextDecorationRec { text_decoration_color: None, text_decoration_style: None, text_decoration_skip_ink: None, - text_decoration_thinkness: None, + text_decoration_thickness: None, } } @@ -1437,7 +1437,7 @@ impl TextDecorationRec { text_decoration_color: None, text_decoration_style: None, text_decoration_skip_ink: None, - text_decoration_thinkness: None, + text_decoration_thickness: None, } } } @@ -1454,7 +1454,7 @@ pub struct TextDecoration { pub text_decoration_color: CGColor, pub text_decoration_style: TextDecorationStyle, pub text_decoration_skip_ink: bool, - pub text_decoration_thinkness: f32, + pub text_decoration_thickness: f32, } impl Default for TextDecoration { @@ -1464,7 +1464,7 @@ impl Default for TextDecoration { text_decoration_color: CGColor::TRANSPARENT, text_decoration_style: TextDecorationStyle::Solid, text_decoration_skip_ink: true, - text_decoration_thinkness: 1.0, + text_decoration_thickness: 1.0, } } } @@ -1476,14 +1476,14 @@ impl FromWithContext for TextDecor .text_decoration_style .unwrap_or(TextDecorationStyle::default()); let text_decoration_skip_ink = value.text_decoration_skip_ink.unwrap_or(true); - let text_decoration_thinkness = value.text_decoration_thinkness.unwrap_or(1.0); + let text_decoration_thickness = value.text_decoration_thickness.unwrap_or(1.0); Self { text_decoration_line: value.text_decoration_line, text_decoration_color: text_decoration_color, text_decoration_style: text_decoration_style, text_decoration_skip_ink: text_decoration_skip_ink, - text_decoration_thinkness: text_decoration_thinkness, + text_decoration_thickness: text_decoration_thickness, } } } diff --git a/crates/grida-canvas/src/io/generated/.gitattributes b/crates/grida-canvas/src/io/generated/.gitattributes new file mode 100644 index 0000000000..2c1875e3d1 --- /dev/null +++ b/crates/grida-canvas/src/io/generated/.gitattributes @@ -0,0 +1 @@ +grida.rs linguist-generated=true diff --git a/crates/grida-canvas/src/io/generated/grida.rs b/crates/grida-canvas/src/io/generated/grida.rs new file mode 100644 index 0000000000..8cae8f9d85 --- /dev/null +++ b/crates/grida-canvas/src/io/generated/grida.rs @@ -0,0 +1,18899 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// @generated +extern crate alloc; + + +#[allow(unused_imports, dead_code)] +pub mod grida { + + +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_NODE_TYPE: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_NODE_TYPE: u8 = 14; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_NODE_TYPE: [NodeType; 15] = [ + NodeType::Exception, + NodeType::Scene, + NodeType::Group, + NodeType::InitialContainer, + NodeType::Container, + NodeType::BooleanOperation, + NodeType::Rectangle, + NodeType::Ellipse, + NodeType::Polygon, + NodeType::RegularPolygon, + NodeType::RegularStarPolygon, + NodeType::Path, + NodeType::Line, + NodeType::Vector, + NodeType::TextSpan, +]; + +/// node type +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct NodeType(pub u8); +#[allow(non_upper_case_globals)] +impl NodeType { + pub const Exception: Self = Self(0); + pub const Scene: Self = Self(1); + pub const Group: Self = Self(2); + pub const InitialContainer: Self = Self(3); + pub const Container: Self = Self(4); + pub const BooleanOperation: Self = Self(5); + pub const Rectangle: Self = Self(6); + pub const Ellipse: Self = Self(7); + pub const Polygon: Self = Self(8); + pub const RegularPolygon: Self = Self(9); + pub const RegularStarPolygon: Self = Self(10); + pub const Path: Self = Self(11); + pub const Line: Self = Self(12); + pub const Vector: Self = Self(13); + pub const TextSpan: Self = Self(14); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 14; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Exception, + Self::Scene, + Self::Group, + Self::InitialContainer, + Self::Container, + Self::BooleanOperation, + Self::Rectangle, + Self::Ellipse, + Self::Polygon, + Self::RegularPolygon, + Self::RegularStarPolygon, + Self::Path, + Self::Line, + Self::Vector, + Self::TextSpan, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Exception => Some("Exception"), + Self::Scene => Some("Scene"), + Self::Group => Some("Group"), + Self::InitialContainer => Some("InitialContainer"), + Self::Container => Some("Container"), + Self::BooleanOperation => Some("BooleanOperation"), + Self::Rectangle => Some("Rectangle"), + Self::Ellipse => Some("Ellipse"), + Self::Polygon => Some("Polygon"), + Self::RegularPolygon => Some("RegularPolygon"), + Self::RegularStarPolygon => Some("RegularStarPolygon"), + Self::Path => Some("Path"), + Self::Line => Some("Line"), + Self::Vector => Some("Vector"), + Self::TextSpan => Some("TextSpan"), + _ => None, + } + } +} +impl ::core::fmt::Debug for NodeType { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for NodeType { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for NodeType { + type Output = NodeType; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for NodeType { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for NodeType { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for NodeType {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_BASIC_SHAPE_NODE_TYPE: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_BASIC_SHAPE_NODE_TYPE: u8 = 5; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_BASIC_SHAPE_NODE_TYPE: [BasicShapeNodeType; 6] = [ + BasicShapeNodeType::Rectangle, + BasicShapeNodeType::Ellipse, + BasicShapeNodeType::Polygon, + BasicShapeNodeType::RegularPolygon, + BasicShapeNodeType::RegularStarPolygon, + BasicShapeNodeType::Path, +]; + +/// shape node type (flag within BasicShapeNode) +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct BasicShapeNodeType(pub u8); +#[allow(non_upper_case_globals)] +impl BasicShapeNodeType { + pub const Rectangle: Self = Self(0); + pub const Ellipse: Self = Self(1); + pub const Polygon: Self = Self(2); + pub const RegularPolygon: Self = Self(3); + pub const RegularStarPolygon: Self = Self(4); + pub const Path: Self = Self(5); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 5; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Rectangle, + Self::Ellipse, + Self::Polygon, + Self::RegularPolygon, + Self::RegularStarPolygon, + Self::Path, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Rectangle => Some("Rectangle"), + Self::Ellipse => Some("Ellipse"), + Self::Polygon => Some("Polygon"), + Self::RegularPolygon => Some("RegularPolygon"), + Self::RegularStarPolygon => Some("RegularStarPolygon"), + Self::Path => Some("Path"), + _ => None, + } + } +} +impl ::core::fmt::Debug for BasicShapeNodeType { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for BasicShapeNodeType { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for BasicShapeNodeType { + type Output = BasicShapeNodeType; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for BasicShapeNodeType { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for BasicShapeNodeType { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for BasicShapeNodeType {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_BLEND_MODE: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_BLEND_MODE: u8 = 15; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_BLEND_MODE: [BlendMode; 16] = [ + BlendMode::Normal, + BlendMode::Multiply, + BlendMode::Screen, + BlendMode::Overlay, + BlendMode::Darken, + BlendMode::Lighten, + BlendMode::ColorDodge, + BlendMode::ColorBurn, + BlendMode::HardLight, + BlendMode::SoftLight, + BlendMode::Difference, + BlendMode::Exclusion, + BlendMode::Hue, + BlendMode::Saturation, + BlendMode::Color, + BlendMode::Luminosity, +]; + +/// Rust: `BlendMode` (does not include pass-through) +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct BlendMode(pub u8); +#[allow(non_upper_case_globals)] +impl BlendMode { + pub const Normal: Self = Self(0); + pub const Multiply: Self = Self(1); + pub const Screen: Self = Self(2); + pub const Overlay: Self = Self(3); + pub const Darken: Self = Self(4); + pub const Lighten: Self = Self(5); + pub const ColorDodge: Self = Self(6); + pub const ColorBurn: Self = Self(7); + pub const HardLight: Self = Self(8); + pub const SoftLight: Self = Self(9); + pub const Difference: Self = Self(10); + pub const Exclusion: Self = Self(11); + pub const Hue: Self = Self(12); + pub const Saturation: Self = Self(13); + pub const Color: Self = Self(14); + pub const Luminosity: Self = Self(15); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 15; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Normal, + Self::Multiply, + Self::Screen, + Self::Overlay, + Self::Darken, + Self::Lighten, + Self::ColorDodge, + Self::ColorBurn, + Self::HardLight, + Self::SoftLight, + Self::Difference, + Self::Exclusion, + Self::Hue, + Self::Saturation, + Self::Color, + Self::Luminosity, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Normal => Some("Normal"), + Self::Multiply => Some("Multiply"), + Self::Screen => Some("Screen"), + Self::Overlay => Some("Overlay"), + Self::Darken => Some("Darken"), + Self::Lighten => Some("Lighten"), + Self::ColorDodge => Some("ColorDodge"), + Self::ColorBurn => Some("ColorBurn"), + Self::HardLight => Some("HardLight"), + Self::SoftLight => Some("SoftLight"), + Self::Difference => Some("Difference"), + Self::Exclusion => Some("Exclusion"), + Self::Hue => Some("Hue"), + Self::Saturation => Some("Saturation"), + Self::Color => Some("Color"), + Self::Luminosity => Some("Luminosity"), + _ => None, + } + } +} +impl ::core::fmt::Debug for BlendMode { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for BlendMode { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for BlendMode { + type Output = BlendMode; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for BlendMode { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for BlendMode { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for BlendMode {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_LAYER_BLEND_MODE: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_LAYER_BLEND_MODE: u8 = 100; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_LAYER_BLEND_MODE: [LayerBlendMode; 17] = [ + LayerBlendMode::Normal, + LayerBlendMode::Multiply, + LayerBlendMode::Screen, + LayerBlendMode::Overlay, + LayerBlendMode::Darken, + LayerBlendMode::Lighten, + LayerBlendMode::ColorDodge, + LayerBlendMode::ColorBurn, + LayerBlendMode::HardLight, + LayerBlendMode::SoftLight, + LayerBlendMode::Difference, + LayerBlendMode::Exclusion, + LayerBlendMode::Hue, + LayerBlendMode::Saturation, + LayerBlendMode::Color, + LayerBlendMode::Luminosity, + LayerBlendMode::PassThrough, +]; + +/// Archive model: flattened blend mode with pass-through included. +/// +/// This duplicates `BlendMode` variants and adds `pass_through`, avoiding a union/table wrapper. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct LayerBlendMode(pub u8); +#[allow(non_upper_case_globals)] +impl LayerBlendMode { + pub const Normal: Self = Self(0); + pub const Multiply: Self = Self(1); + pub const Screen: Self = Self(2); + pub const Overlay: Self = Self(3); + pub const Darken: Self = Self(4); + pub const Lighten: Self = Self(5); + pub const ColorDodge: Self = Self(6); + pub const ColorBurn: Self = Self(7); + pub const HardLight: Self = Self(8); + pub const SoftLight: Self = Self(9); + pub const Difference: Self = Self(10); + pub const Exclusion: Self = Self(11); + pub const Hue: Self = Self(12); + pub const Saturation: Self = Self(13); + pub const Color: Self = Self(14); + pub const Luminosity: Self = Self(15); + /// Archive-only sentinel: corresponds to Rust `LayerBlendMode::PassThrough`. + /// Set to 100 to avoid confusing it with `BlendMode` ids. + pub const PassThrough: Self = Self(100); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 100; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Normal, + Self::Multiply, + Self::Screen, + Self::Overlay, + Self::Darken, + Self::Lighten, + Self::ColorDodge, + Self::ColorBurn, + Self::HardLight, + Self::SoftLight, + Self::Difference, + Self::Exclusion, + Self::Hue, + Self::Saturation, + Self::Color, + Self::Luminosity, + Self::PassThrough, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Normal => Some("Normal"), + Self::Multiply => Some("Multiply"), + Self::Screen => Some("Screen"), + Self::Overlay => Some("Overlay"), + Self::Darken => Some("Darken"), + Self::Lighten => Some("Lighten"), + Self::ColorDodge => Some("ColorDodge"), + Self::ColorBurn => Some("ColorBurn"), + Self::HardLight => Some("HardLight"), + Self::SoftLight => Some("SoftLight"), + Self::Difference => Some("Difference"), + Self::Exclusion => Some("Exclusion"), + Self::Hue => Some("Hue"), + Self::Saturation => Some("Saturation"), + Self::Color => Some("Color"), + Self::Luminosity => Some("Luminosity"), + Self::PassThrough => Some("PassThrough"), + _ => None, + } + } +} +impl ::core::fmt::Debug for LayerBlendMode { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for LayerBlendMode { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for LayerBlendMode { + type Output = LayerBlendMode; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for LayerBlendMode { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for LayerBlendMode { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for LayerBlendMode {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_AXIS: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_AXIS: u8 = 1; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_AXIS: [Axis; 2] = [ + Axis::Horizontal, + Axis::Vertical, +]; + +/// Rust: `Axis` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct Axis(pub u8); +#[allow(non_upper_case_globals)] +impl Axis { + pub const Horizontal: Self = Self(0); + pub const Vertical: Self = Self(1); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 1; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Horizontal, + Self::Vertical, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Horizontal => Some("Horizontal"), + Self::Vertical => Some("Vertical"), + _ => None, + } + } +} +impl ::core::fmt::Debug for Axis { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for Axis { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for Axis { + type Output = Axis; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for Axis { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for Axis { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for Axis {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_TILE_MODE: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_TILE_MODE: u8 = 3; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_TILE_MODE: [TileMode; 4] = [ + TileMode::Clamp, + TileMode::Repeated, + TileMode::Mirror, + TileMode::Decal, +]; + +/// Rust: `TileMode` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct TileMode(pub u8); +#[allow(non_upper_case_globals)] +impl TileMode { + pub const Clamp: Self = Self(0); + pub const Repeated: Self = Self(1); + pub const Mirror: Self = Self(2); + pub const Decal: Self = Self(3); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 3; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Clamp, + Self::Repeated, + Self::Mirror, + Self::Decal, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Clamp => Some("Clamp"), + Self::Repeated => Some("Repeated"), + Self::Mirror => Some("Mirror"), + Self::Decal => Some("Decal"), + _ => None, + } + } +} +impl ::core::fmt::Debug for TileMode { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for TileMode { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for TileMode { + type Output = TileMode; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for TileMode { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for TileMode { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for TileMode {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_BOX_FIT: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_BOX_FIT: u8 = 3; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_BOX_FIT: [BoxFit; 4] = [ + BoxFit::Contain, + BoxFit::Cover, + BoxFit::Fill, + BoxFit::None, +]; + +/// Rust: `math2::box_fit::BoxFit` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct BoxFit(pub u8); +#[allow(non_upper_case_globals)] +impl BoxFit { + pub const Contain: Self = Self(0); + pub const Cover: Self = Self(1); + pub const Fill: Self = Self(2); + pub const None: Self = Self(3); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 3; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Contain, + Self::Cover, + Self::Fill, + Self::None, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Contain => Some("Contain"), + Self::Cover => Some("Cover"), + Self::Fill => Some("Fill"), + Self::None => Some("None"), + _ => None, + } + } +} +impl ::core::fmt::Debug for BoxFit { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for BoxFit { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for BoxFit { + type Output = BoxFit; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for BoxFit { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for BoxFit { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for BoxFit {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_IMAGE_REPEAT: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_IMAGE_REPEAT: u8 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_IMAGE_REPEAT: [ImageRepeat; 3] = [ + ImageRepeat::RepeatX, + ImageRepeat::RepeatY, + ImageRepeat::Repeat, +]; + +/// Rust: `ImageRepeat` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct ImageRepeat(pub u8); +#[allow(non_upper_case_globals)] +impl ImageRepeat { + pub const RepeatX: Self = Self(0); + pub const RepeatY: Self = Self(1); + pub const Repeat: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::RepeatX, + Self::RepeatY, + Self::Repeat, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::RepeatX => Some("RepeatX"), + Self::RepeatY => Some("RepeatY"), + Self::Repeat => Some("Repeat"), + _ => None, + } + } +} +impl ::core::fmt::Debug for ImageRepeat { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for ImageRepeat { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for ImageRepeat { + type Output = ImageRepeat; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for ImageRepeat { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for ImageRepeat { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for ImageRepeat {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_LAYOUT_MODE: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_LAYOUT_MODE: u8 = 1; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_LAYOUT_MODE: [LayoutMode; 2] = [ + LayoutMode::Normal, + LayoutMode::Flex, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct LayoutMode(pub u8); +#[allow(non_upper_case_globals)] +impl LayoutMode { + pub const Normal: Self = Self(0); + pub const Flex: Self = Self(1); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 1; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Normal, + Self::Flex, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Normal => Some("Normal"), + Self::Flex => Some("Flex"), + _ => None, + } + } +} +impl ::core::fmt::Debug for LayoutMode { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for LayoutMode { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for LayoutMode { + type Output = LayoutMode; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for LayoutMode { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for LayoutMode { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for LayoutMode {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_LAYOUT_WRAP: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_LAYOUT_WRAP: u8 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_LAYOUT_WRAP: [LayoutWrap; 3] = [ + LayoutWrap::None, + LayoutWrap::Wrap, + LayoutWrap::NoWrap, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct LayoutWrap(pub u8); +#[allow(non_upper_case_globals)] +impl LayoutWrap { + pub const None: Self = Self(0); + pub const Wrap: Self = Self(1); + pub const NoWrap: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::None, + Self::Wrap, + Self::NoWrap, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::None => Some("None"), + Self::Wrap => Some("Wrap"), + Self::NoWrap => Some("NoWrap"), + _ => None, + } + } +} +impl ::core::fmt::Debug for LayoutWrap { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for LayoutWrap { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for LayoutWrap { + type Output = LayoutWrap; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for LayoutWrap { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for LayoutWrap { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for LayoutWrap {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_LAYOUT_POSITIONING: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_LAYOUT_POSITIONING: u8 = 1; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_LAYOUT_POSITIONING: [LayoutPositioning; 2] = [ + LayoutPositioning::Auto, + LayoutPositioning::Absolute, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct LayoutPositioning(pub u8); +#[allow(non_upper_case_globals)] +impl LayoutPositioning { + pub const Auto: Self = Self(0); + pub const Absolute: Self = Self(1); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 1; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Auto, + Self::Absolute, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Auto => Some("Auto"), + Self::Absolute => Some("Absolute"), + _ => None, + } + } +} +impl ::core::fmt::Debug for LayoutPositioning { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for LayoutPositioning { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for LayoutPositioning { + type Output = LayoutPositioning; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for LayoutPositioning { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for LayoutPositioning { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for LayoutPositioning {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_MAIN_AXIS_ALIGNMENT: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_MAIN_AXIS_ALIGNMENT: u8 = 7; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_MAIN_AXIS_ALIGNMENT: [MainAxisAlignment; 8] = [ + MainAxisAlignment::None, + MainAxisAlignment::Start, + MainAxisAlignment::End, + MainAxisAlignment::Center, + MainAxisAlignment::SpaceBetween, + MainAxisAlignment::SpaceAround, + MainAxisAlignment::SpaceEvenly, + MainAxisAlignment::Stretch, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct MainAxisAlignment(pub u8); +#[allow(non_upper_case_globals)] +impl MainAxisAlignment { + pub const None: Self = Self(0); + pub const Start: Self = Self(1); + pub const End: Self = Self(2); + pub const Center: Self = Self(3); + pub const SpaceBetween: Self = Self(4); + pub const SpaceAround: Self = Self(5); + pub const SpaceEvenly: Self = Self(6); + pub const Stretch: Self = Self(7); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 7; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::None, + Self::Start, + Self::End, + Self::Center, + Self::SpaceBetween, + Self::SpaceAround, + Self::SpaceEvenly, + Self::Stretch, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::None => Some("None"), + Self::Start => Some("Start"), + Self::End => Some("End"), + Self::Center => Some("Center"), + Self::SpaceBetween => Some("SpaceBetween"), + Self::SpaceAround => Some("SpaceAround"), + Self::SpaceEvenly => Some("SpaceEvenly"), + Self::Stretch => Some("Stretch"), + _ => None, + } + } +} +impl ::core::fmt::Debug for MainAxisAlignment { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for MainAxisAlignment { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for MainAxisAlignment { + type Output = MainAxisAlignment; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for MainAxisAlignment { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for MainAxisAlignment { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for MainAxisAlignment {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_CROSS_AXIS_ALIGNMENT: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_CROSS_AXIS_ALIGNMENT: u8 = 4; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_CROSS_AXIS_ALIGNMENT: [CrossAxisAlignment; 5] = [ + CrossAxisAlignment::None, + CrossAxisAlignment::Start, + CrossAxisAlignment::End, + CrossAxisAlignment::Center, + CrossAxisAlignment::Stretch, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct CrossAxisAlignment(pub u8); +#[allow(non_upper_case_globals)] +impl CrossAxisAlignment { + pub const None: Self = Self(0); + pub const Start: Self = Self(1); + pub const End: Self = Self(2); + pub const Center: Self = Self(3); + pub const Stretch: Self = Self(4); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 4; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::None, + Self::Start, + Self::End, + Self::Center, + Self::Stretch, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::None => Some("None"), + Self::Start => Some("Start"), + Self::End => Some("End"), + Self::Center => Some("Center"), + Self::Stretch => Some("Stretch"), + _ => None, + } + } +} +impl ::core::fmt::Debug for CrossAxisAlignment { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for CrossAxisAlignment { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for CrossAxisAlignment { + type Output = CrossAxisAlignment; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for CrossAxisAlignment { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for CrossAxisAlignment { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for CrossAxisAlignment {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_STROKE_ALIGN: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_STROKE_ALIGN: u8 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_STROKE_ALIGN: [StrokeAlign; 3] = [ + StrokeAlign::Inside, + StrokeAlign::Center, + StrokeAlign::Outside, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct StrokeAlign(pub u8); +#[allow(non_upper_case_globals)] +impl StrokeAlign { + pub const Inside: Self = Self(0); + pub const Center: Self = Self(1); + pub const Outside: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Inside, + Self::Center, + Self::Outside, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Inside => Some("Inside"), + Self::Center => Some("Center"), + Self::Outside => Some("Outside"), + _ => None, + } + } +} +impl ::core::fmt::Debug for StrokeAlign { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for StrokeAlign { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for StrokeAlign { + type Output = StrokeAlign; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for StrokeAlign { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for StrokeAlign { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for StrokeAlign {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_STROKE_CAP: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_STROKE_CAP: u8 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_STROKE_CAP: [StrokeCap; 3] = [ + StrokeCap::Butt, + StrokeCap::Round, + StrokeCap::Square, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct StrokeCap(pub u8); +#[allow(non_upper_case_globals)] +impl StrokeCap { + pub const Butt: Self = Self(0); + pub const Round: Self = Self(1); + pub const Square: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Butt, + Self::Round, + Self::Square, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Butt => Some("Butt"), + Self::Round => Some("Round"), + Self::Square => Some("Square"), + _ => None, + } + } +} +impl ::core::fmt::Debug for StrokeCap { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for StrokeCap { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for StrokeCap { + type Output = StrokeCap; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for StrokeCap { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for StrokeCap { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for StrokeCap {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_STROKE_JOIN: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_STROKE_JOIN: u8 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_STROKE_JOIN: [StrokeJoin; 3] = [ + StrokeJoin::Miter, + StrokeJoin::Round, + StrokeJoin::Bevel, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct StrokeJoin(pub u8); +#[allow(non_upper_case_globals)] +impl StrokeJoin { + pub const Miter: Self = Self(0); + pub const Round: Self = Self(1); + pub const Bevel: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Miter, + Self::Round, + Self::Bevel, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Miter => Some("Miter"), + Self::Round => Some("Round"), + Self::Bevel => Some("Bevel"), + _ => None, + } + } +} +impl ::core::fmt::Debug for StrokeJoin { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for StrokeJoin { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for StrokeJoin { + type Output = StrokeJoin; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for StrokeJoin { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for StrokeJoin { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for StrokeJoin {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_STROKE_MARKER_PRESET: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_STROKE_MARKER_PRESET: u8 = 6; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_STROKE_MARKER_PRESET: [StrokeMarkerPreset; 7] = [ + StrokeMarkerPreset::None, + StrokeMarkerPreset::RightTriangleOpen, + StrokeMarkerPreset::EquilateralTriangle, + StrokeMarkerPreset::Circle, + StrokeMarkerPreset::Square, + StrokeMarkerPreset::Diamond, + StrokeMarkerPreset::VerticalBar, +]; + +/// Marker decoration placed at stroke endpoints or vector vertices. +/// +/// Unlike StrokeCap (which maps to native backend caps like Skia PaintCap), +/// StrokeMarkerPreset represents explicit marker geometry drawn on top of the +/// stroke path. When a decoration is present at an endpoint, the renderer +/// uses Butt cap at that endpoint and draws the marker geometry instead. +/// +/// See: docs/wg/feat-2d/curve-decoration.md +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct StrokeMarkerPreset(pub u8); +#[allow(non_upper_case_globals)] +impl StrokeMarkerPreset { + /// No decoration (endpoint uses the node's stroke_cap as normal). + pub const None: Self = Self(0); + /// Right triangle (90° at tip), open stroked chevron — not filled. + pub const RightTriangleOpen: Self = Self(1); + /// Filled equilateral triangle pointing forward. + pub const EquilateralTriangle: Self = Self(2); + /// Filled circle. + pub const Circle: Self = Self(3); + /// Filled axis-aligned square. + pub const Square: Self = Self(4); + /// Filled diamond (square rotated 45°). + pub const Diamond: Self = Self(5); + /// Filled vertical bar (rectangle) perpendicular to the stroke. + pub const VerticalBar: Self = Self(6); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 6; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::None, + Self::RightTriangleOpen, + Self::EquilateralTriangle, + Self::Circle, + Self::Square, + Self::Diamond, + Self::VerticalBar, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::None => Some("None"), + Self::RightTriangleOpen => Some("RightTriangleOpen"), + Self::EquilateralTriangle => Some("EquilateralTriangle"), + Self::Circle => Some("Circle"), + Self::Square => Some("Square"), + Self::Diamond => Some("Diamond"), + Self::VerticalBar => Some("VerticalBar"), + _ => None, + } + } +} +impl ::core::fmt::Debug for StrokeMarkerPreset { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for StrokeMarkerPreset { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for StrokeMarkerPreset { + type Output = StrokeMarkerPreset; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for StrokeMarkerPreset { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for StrokeMarkerPreset { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for StrokeMarkerPreset {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_TEXT_ALIGN: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_TEXT_ALIGN: u8 = 3; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_TEXT_ALIGN: [TextAlign; 4] = [ + TextAlign::Left, + TextAlign::Right, + TextAlign::Center, + TextAlign::Justify, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct TextAlign(pub u8); +#[allow(non_upper_case_globals)] +impl TextAlign { + pub const Left: Self = Self(0); + pub const Right: Self = Self(1); + pub const Center: Self = Self(2); + pub const Justify: Self = Self(3); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 3; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Left, + Self::Right, + Self::Center, + Self::Justify, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Left => Some("Left"), + Self::Right => Some("Right"), + Self::Center => Some("Center"), + Self::Justify => Some("Justify"), + _ => None, + } + } +} +impl ::core::fmt::Debug for TextAlign { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for TextAlign { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for TextAlign { + type Output = TextAlign; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for TextAlign { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for TextAlign { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for TextAlign {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_TEXT_ALIGN_VERTICAL: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_TEXT_ALIGN_VERTICAL: u8 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_TEXT_ALIGN_VERTICAL: [TextAlignVertical; 3] = [ + TextAlignVertical::Top, + TextAlignVertical::Center, + TextAlignVertical::Bottom, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct TextAlignVertical(pub u8); +#[allow(non_upper_case_globals)] +impl TextAlignVertical { + pub const Top: Self = Self(0); + pub const Center: Self = Self(1); + pub const Bottom: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Top, + Self::Center, + Self::Bottom, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Top => Some("Top"), + Self::Center => Some("Center"), + Self::Bottom => Some("Bottom"), + _ => None, + } + } +} +impl ::core::fmt::Debug for TextAlignVertical { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for TextAlignVertical { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for TextAlignVertical { + type Output = TextAlignVertical; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for TextAlignVertical { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for TextAlignVertical { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for TextAlignVertical {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_BOOLEAN_PATH_OPERATION: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_BOOLEAN_PATH_OPERATION: u8 = 3; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_BOOLEAN_PATH_OPERATION: [BooleanPathOperation; 4] = [ + BooleanPathOperation::Union, + BooleanPathOperation::Intersection, + BooleanPathOperation::Difference, + BooleanPathOperation::Xor, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct BooleanPathOperation(pub u8); +#[allow(non_upper_case_globals)] +impl BooleanPathOperation { + pub const Union: Self = Self(0); + pub const Intersection: Self = Self(1); + pub const Difference: Self = Self(2); + pub const Xor: Self = Self(3); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 3; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Union, + Self::Intersection, + Self::Difference, + Self::Xor, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Union => Some("Union"), + Self::Intersection => Some("Intersection"), + Self::Difference => Some("Difference"), + Self::Xor => Some("Xor"), + _ => None, + } + } +} +impl ::core::fmt::Debug for BooleanPathOperation { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for BooleanPathOperation { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for BooleanPathOperation { + type Output = BooleanPathOperation; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for BooleanPathOperation { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for BooleanPathOperation { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for BooleanPathOperation {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_SCENE_CONSTRAINTS_CHILDREN: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_SCENE_CONSTRAINTS_CHILDREN: u8 = 1; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_SCENE_CONSTRAINTS_CHILDREN: [SceneConstraintsChildren; 2] = [ + SceneConstraintsChildren::Single, + SceneConstraintsChildren::Multiple, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct SceneConstraintsChildren(pub u8); +#[allow(non_upper_case_globals)] +impl SceneConstraintsChildren { + pub const Single: Self = Self(0); + pub const Multiple: Self = Self(1); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 1; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Single, + Self::Multiple, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Single => Some("Single"), + Self::Multiple => Some("Multiple"), + _ => None, + } + } +} +impl ::core::fmt::Debug for SceneConstraintsChildren { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for SceneConstraintsChildren { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for SceneConstraintsChildren { + type Output = SceneConstraintsChildren; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for SceneConstraintsChildren { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for SceneConstraintsChildren { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for SceneConstraintsChildren {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_FILL_RULE: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_FILL_RULE: u8 = 1; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_FILL_RULE: [FillRule; 2] = [ + FillRule::NonZero, + FillRule::EvenOdd, +]; + +/// Rust: `FillRule` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct FillRule(pub u8); +#[allow(non_upper_case_globals)] +impl FillRule { + pub const NonZero: Self = Self(0); + pub const EvenOdd: Self = Self(1); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 1; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NonZero, + Self::EvenOdd, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NonZero => Some("NonZero"), + Self::EvenOdd => Some("EvenOdd"), + _ => None, + } + } +} +impl ::core::fmt::Debug for FillRule { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for FillRule { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for FillRule { + type Output = FillRule; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for FillRule { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for FillRule { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for FillRule {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_IMAGE_MASK_TYPE: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_IMAGE_MASK_TYPE: u8 = 1; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_IMAGE_MASK_TYPE: [ImageMaskType; 2] = [ + ImageMaskType::Alpha, + ImageMaskType::Luminance, +]; + +/// Rust: `ImageMaskType` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct ImageMaskType(pub u8); +#[allow(non_upper_case_globals)] +impl ImageMaskType { + pub const Alpha: Self = Self(0); + pub const Luminance: Self = Self(1); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 1; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Alpha, + Self::Luminance, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Alpha => Some("Alpha"), + Self::Luminance => Some("Luminance"), + _ => None, + } + } +} +impl ::core::fmt::Debug for ImageMaskType { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for ImageMaskType { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for ImageMaskType { + type Output = ImageMaskType; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for ImageMaskType { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for ImageMaskType { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for ImageMaskType {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_LAYER_MASK_TYPE: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_LAYER_MASK_TYPE: u8 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_LAYER_MASK_TYPE: [LayerMaskType; 3] = [ + LayerMaskType::NONE, + LayerMaskType::LayerMaskTypeImage, + LayerMaskType::LayerMaskTypeGeometry, +]; + +/// Rust: `LayerMaskType` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct LayerMaskType(pub u8); +#[allow(non_upper_case_globals)] +impl LayerMaskType { + pub const NONE: Self = Self(0); + pub const LayerMaskTypeImage: Self = Self(1); + pub const LayerMaskTypeGeometry: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NONE, + Self::LayerMaskTypeImage, + Self::LayerMaskTypeGeometry, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::LayerMaskTypeImage => Some("LayerMaskTypeImage"), + Self::LayerMaskTypeGeometry => Some("LayerMaskTypeGeometry"), + _ => None, + } + } +} +impl ::core::fmt::Debug for LayerMaskType { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for LayerMaskType { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for LayerMaskType { + type Output = LayerMaskType; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for LayerMaskType { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for LayerMaskType { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for LayerMaskType {} +pub struct LayerMaskTypeUnionTableOffset {} + +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_TEXT_TRANSFORM: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_TEXT_TRANSFORM: u8 = 3; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_TEXT_TRANSFORM: [TextTransform; 4] = [ + TextTransform::None, + TextTransform::Uppercase, + TextTransform::Lowercase, + TextTransform::Capitalize, +]; + +/// Rust: `TextTransform` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct TextTransform(pub u8); +#[allow(non_upper_case_globals)] +impl TextTransform { + pub const None: Self = Self(0); + pub const Uppercase: Self = Self(1); + pub const Lowercase: Self = Self(2); + pub const Capitalize: Self = Self(3); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 3; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::None, + Self::Uppercase, + Self::Lowercase, + Self::Capitalize, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::None => Some("None"), + Self::Uppercase => Some("Uppercase"), + Self::Lowercase => Some("Lowercase"), + Self::Capitalize => Some("Capitalize"), + _ => None, + } + } +} +impl ::core::fmt::Debug for TextTransform { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for TextTransform { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for TextTransform { + type Output = TextTransform; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for TextTransform { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for TextTransform { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for TextTransform {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_TEXT_DECORATION_LINE: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_TEXT_DECORATION_LINE: u8 = 3; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_TEXT_DECORATION_LINE: [TextDecorationLine; 4] = [ + TextDecorationLine::None, + TextDecorationLine::Underline, + TextDecorationLine::Overline, + TextDecorationLine::LineThrough, +]; + +/// Rust: `TextDecorationLine` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct TextDecorationLine(pub u8); +#[allow(non_upper_case_globals)] +impl TextDecorationLine { + pub const None: Self = Self(0); + pub const Underline: Self = Self(1); + pub const Overline: Self = Self(2); + pub const LineThrough: Self = Self(3); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 3; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::None, + Self::Underline, + Self::Overline, + Self::LineThrough, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::None => Some("None"), + Self::Underline => Some("Underline"), + Self::Overline => Some("Overline"), + Self::LineThrough => Some("LineThrough"), + _ => None, + } + } +} +impl ::core::fmt::Debug for TextDecorationLine { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for TextDecorationLine { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for TextDecorationLine { + type Output = TextDecorationLine; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for TextDecorationLine { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for TextDecorationLine { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for TextDecorationLine {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_TEXT_DECORATION_STYLE: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_TEXT_DECORATION_STYLE: u8 = 4; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_TEXT_DECORATION_STYLE: [TextDecorationStyle; 5] = [ + TextDecorationStyle::Solid, + TextDecorationStyle::Double, + TextDecorationStyle::Dotted, + TextDecorationStyle::Dashed, + TextDecorationStyle::Wavy, +]; + +/// Rust: `TextDecorationStyle` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct TextDecorationStyle(pub u8); +#[allow(non_upper_case_globals)] +impl TextDecorationStyle { + pub const Solid: Self = Self(0); + pub const Double: Self = Self(1); + pub const Dotted: Self = Self(2); + pub const Dashed: Self = Self(3); + pub const Wavy: Self = Self(4); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 4; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Solid, + Self::Double, + Self::Dotted, + Self::Dashed, + Self::Wavy, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Solid => Some("Solid"), + Self::Double => Some("Double"), + Self::Dotted => Some("Dotted"), + Self::Dashed => Some("Dashed"), + Self::Wavy => Some("Wavy"), + _ => None, + } + } +} +impl ::core::fmt::Debug for TextDecorationStyle { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for TextDecorationStyle { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for TextDecorationStyle { + type Output = TextDecorationStyle; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for TextDecorationStyle { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for TextDecorationStyle { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for TextDecorationStyle {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_FONT_OPTICAL_SIZING_KIND: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_FONT_OPTICAL_SIZING_KIND: u8 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_FONT_OPTICAL_SIZING_KIND: [FontOpticalSizingKind; 3] = [ + FontOpticalSizingKind::Auto, + FontOpticalSizingKind::None, + FontOpticalSizingKind::Fixed, +]; + +/// Rust: `FontOpticalSizing` (Auto | None | Fixed(f32)) +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct FontOpticalSizingKind(pub u8); +#[allow(non_upper_case_globals)] +impl FontOpticalSizingKind { + pub const Auto: Self = Self(0); + pub const None: Self = Self(1); + pub const Fixed: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Auto, + Self::None, + Self::Fixed, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Auto => Some("Auto"), + Self::None => Some("None"), + Self::Fixed => Some("Fixed"), + _ => None, + } + } +} +impl ::core::fmt::Debug for FontOpticalSizingKind { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for FontOpticalSizingKind { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for FontOpticalSizingKind { + type Output = FontOpticalSizingKind; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for FontOpticalSizingKind { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for FontOpticalSizingKind { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for FontOpticalSizingKind {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_TEXT_DIMENSION_KIND: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_TEXT_DIMENSION_KIND: u8 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_TEXT_DIMENSION_KIND: [TextDimensionKind; 3] = [ + TextDimensionKind::Normal, + TextDimensionKind::Fixed, + TextDimensionKind::Factor, +]; + +/// `TextLineHeight` (Normal | Fixed(f32) | Factor(f32)) +/// `TextLetterSpacing` (Normal | Fixed(f32) | Factor(f32)) +/// `TextWordSpacing` (Normal | Fixed(f32) | Factor(f32)) +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct TextDimensionKind(pub u8); +#[allow(non_upper_case_globals)] +impl TextDimensionKind { + pub const Normal: Self = Self(0); + pub const Fixed: Self = Self(1); + pub const Factor: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Normal, + Self::Fixed, + Self::Factor, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Normal => Some("Normal"), + Self::Fixed => Some("Fixed"), + Self::Factor => Some("Factor"), + _ => None, + } + } +} +impl ::core::fmt::Debug for TextDimensionKind { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for TextDimensionKind { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for TextDimensionKind { + type Output = TextDimensionKind; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for TextDimensionKind { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for TextDimensionKind { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for TextDimensionKind {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_RESOURCE_REF: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_RESOURCE_REF: u8 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_RESOURCE_REF: [ResourceRef; 3] = [ + ResourceRef::NONE, + ResourceRef::ResourceRefHASH, + ResourceRef::ResourceRefRID, +]; + +/// Rust: `ResourceRef` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct ResourceRef(pub u8); +#[allow(non_upper_case_globals)] +impl ResourceRef { + pub const NONE: Self = Self(0); + pub const ResourceRefHASH: Self = Self(1); + pub const ResourceRefRID: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NONE, + Self::ResourceRefHASH, + Self::ResourceRefRID, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::ResourceRefHASH => Some("ResourceRefHASH"), + Self::ResourceRefRID => Some("ResourceRefRID"), + _ => None, + } + } +} +impl ::core::fmt::Debug for ResourceRef { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for ResourceRef { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for ResourceRef { + type Output = ResourceRef; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for ResourceRef { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for ResourceRef { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for ResourceRef {} +pub struct ResourceRefUnionTableOffset {} + +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_IMAGE_PAINT_FIT: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_IMAGE_PAINT_FIT: u8 = 3; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_IMAGE_PAINT_FIT: [ImagePaintFit; 4] = [ + ImagePaintFit::NONE, + ImagePaintFit::ImagePaintFitFit, + ImagePaintFit::ImagePaintFitTransform, + ImagePaintFit::ImagePaintFitTile, +]; + +/// Rust: `ImagePaintFit` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct ImagePaintFit(pub u8); +#[allow(non_upper_case_globals)] +impl ImagePaintFit { + pub const NONE: Self = Self(0); + pub const ImagePaintFitFit: Self = Self(1); + pub const ImagePaintFitTransform: Self = Self(2); + pub const ImagePaintFitTile: Self = Self(3); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 3; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NONE, + Self::ImagePaintFitFit, + Self::ImagePaintFitTransform, + Self::ImagePaintFitTile, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::ImagePaintFitFit => Some("ImagePaintFitFit"), + Self::ImagePaintFitTransform => Some("ImagePaintFitTransform"), + Self::ImagePaintFitTile => Some("ImagePaintFitTile"), + _ => None, + } + } +} +impl ::core::fmt::Debug for ImagePaintFit { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for ImagePaintFit { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for ImagePaintFit { + type Output = ImagePaintFit; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for ImagePaintFit { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for ImagePaintFit { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for ImagePaintFit {} +pub struct ImagePaintFitUnionTableOffset {} + +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_PAINT: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_PAINT: u8 = 6; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_PAINT: [Paint; 7] = [ + Paint::NONE, + Paint::SolidPaint, + Paint::LinearGradientPaint, + Paint::RadialGradientPaint, + Paint::SweepGradientPaint, + Paint::DiamondGradientPaint, + Paint::ImagePaint, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct Paint(pub u8); +#[allow(non_upper_case_globals)] +impl Paint { + pub const NONE: Self = Self(0); + pub const SolidPaint: Self = Self(1); + pub const LinearGradientPaint: Self = Self(2); + pub const RadialGradientPaint: Self = Self(3); + pub const SweepGradientPaint: Self = Self(4); + pub const DiamondGradientPaint: Self = Self(5); + pub const ImagePaint: Self = Self(6); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 6; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NONE, + Self::SolidPaint, + Self::LinearGradientPaint, + Self::RadialGradientPaint, + Self::SweepGradientPaint, + Self::DiamondGradientPaint, + Self::ImagePaint, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::SolidPaint => Some("SolidPaint"), + Self::LinearGradientPaint => Some("LinearGradientPaint"), + Self::RadialGradientPaint => Some("RadialGradientPaint"), + Self::SweepGradientPaint => Some("SweepGradientPaint"), + Self::DiamondGradientPaint => Some("DiamondGradientPaint"), + Self::ImagePaint => Some("ImagePaint"), + _ => None, + } + } +} +impl ::core::fmt::Debug for Paint { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for Paint { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for Paint { + type Output = Paint; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for Paint { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for Paint { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for Paint {} +pub struct PaintUnionTableOffset {} + +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_EDGE_POINT: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_EDGE_POINT: u8 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_EDGE_POINT: [EdgePoint; 3] = [ + EdgePoint::NONE, + EdgePoint::EdgePointPosition2D, + EdgePoint::EdgePointNodeAnchor, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct EdgePoint(pub u8); +#[allow(non_upper_case_globals)] +impl EdgePoint { + pub const NONE: Self = Self(0); + pub const EdgePointPosition2D: Self = Self(1); + pub const EdgePointNodeAnchor: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NONE, + Self::EdgePointPosition2D, + Self::EdgePointNodeAnchor, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::EdgePointPosition2D => Some("EdgePointPosition2D"), + Self::EdgePointNodeAnchor => Some("EdgePointNodeAnchor"), + _ => None, + } + } +} +impl ::core::fmt::Debug for EdgePoint { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for EdgePoint { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for EdgePoint { + type Output = EdgePoint; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for EdgePoint { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for EdgePoint { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for EdgePoint {} +pub struct EdgePointUnionTableOffset {} + +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_FE_BLUR: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_FE_BLUR: u8 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_FE_BLUR: [FeBlur; 3] = [ + FeBlur::NONE, + FeBlur::FeGaussianBlur, + FeBlur::FeProgressiveBlur, +]; + +/// Rust: `FeBlur` (enum) +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct FeBlur(pub u8); +#[allow(non_upper_case_globals)] +impl FeBlur { + pub const NONE: Self = Self(0); + pub const FeGaussianBlur: Self = Self(1); + pub const FeProgressiveBlur: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NONE, + Self::FeGaussianBlur, + Self::FeProgressiveBlur, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::FeGaussianBlur => Some("FeGaussianBlur"), + Self::FeProgressiveBlur => Some("FeProgressiveBlur"), + _ => None, + } + } +} +impl ::core::fmt::Debug for FeBlur { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for FeBlur { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for FeBlur { + type Output = FeBlur; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for FeBlur { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for FeBlur { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for FeBlur {} +pub struct FeBlurUnionTableOffset {} + +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_FILTER_SHADOW_EFFECT_KIND: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_FILTER_SHADOW_EFFECT_KIND: u8 = 1; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_FILTER_SHADOW_EFFECT_KIND: [FilterShadowEffectKind; 2] = [ + FilterShadowEffectKind::DropShadow, + FilterShadowEffectKind::InnerShadow, +]; + +/// Rust: `FilterShadowEffect` (enum) +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct FilterShadowEffectKind(pub u8); +#[allow(non_upper_case_globals)] +impl FilterShadowEffectKind { + pub const DropShadow: Self = Self(0); + pub const InnerShadow: Self = Self(1); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 1; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::DropShadow, + Self::InnerShadow, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::DropShadow => Some("DropShadow"), + Self::InnerShadow => Some("InnerShadow"), + _ => None, + } + } +} +impl ::core::fmt::Debug for FilterShadowEffectKind { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for FilterShadowEffectKind { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for FilterShadowEffectKind { + type Output = FilterShadowEffectKind; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for FilterShadowEffectKind { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for FilterShadowEffectKind { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for FilterShadowEffectKind {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_NOISE_EFFECT_COLORS_KIND: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_NOISE_EFFECT_COLORS_KIND: u8 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_NOISE_EFFECT_COLORS_KIND: [NoiseEffectColorsKind; 3] = [ + NoiseEffectColorsKind::Mono, + NoiseEffectColorsKind::Duo, + NoiseEffectColorsKind::Multi, +]; + +/// Rust: `NoiseEffectColors` (enum) +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct NoiseEffectColorsKind(pub u8); +#[allow(non_upper_case_globals)] +impl NoiseEffectColorsKind { + pub const Mono: Self = Self(0); + pub const Duo: Self = Self(1); + pub const Multi: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Mono, + Self::Duo, + Self::Multi, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Mono => Some("Mono"), + Self::Duo => Some("Duo"), + Self::Multi => Some("Multi"), + _ => None, + } + } +} +impl ::core::fmt::Debug for NoiseEffectColorsKind { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for NoiseEffectColorsKind { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for NoiseEffectColorsKind { + type Output = NoiseEffectColorsKind; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for NoiseEffectColorsKind { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for NoiseEffectColorsKind { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for NoiseEffectColorsKind {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_CANONICAL_LAYER_SHAPE: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_CANONICAL_LAYER_SHAPE: u8 = 6; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_CANONICAL_LAYER_SHAPE: [CanonicalLayerShape; 7] = [ + CanonicalLayerShape::NONE, + CanonicalLayerShape::CanonicalShapeRectangular, + CanonicalLayerShape::CanonicalShapeElliptical, + CanonicalLayerShape::CanonicalShapePointsPolygon, + CanonicalLayerShape::CanonicalShapeRegularPolygon, + CanonicalLayerShape::CanonicalShapeRegularStarPolygon, + CanonicalLayerShape::CanonicalShapePath, +]; + +/// Canonical layer shape descriptor (geometry-only, layout-resolved). +/// +/// `CanonicalLayerShape` is a *minimal*, *layout-independent* description of a +/// primitive shape used by layer-backed nodes (e.g. `BasicShapeNode`). +/// +/// Core semantics: +/// - This union intentionally does NOT encode size (no width/height). +/// - The concrete geometry is produced by mapping the selected shape variant into +/// the node’s resolved layout box at render time. +/// - Shape-specific parameters are expressed in normalized or ratio form: +/// * points/polygon/path use 0..1 normalized coordinates (scaled to the box) +/// * ellipse ring/sector uses ratios + angles (interpreted in the box) +/// - All styling (fills, strokes, effects, corner traits, etc.) lives outside the +/// shape descriptor on the owning node/traits. This union is geometry-only. +/// +/// Evolution rules: +/// - New primitive shape variants may be added by introducing a new `CanonicalShape*` +/// table and adding it to this union (additive change). +/// - Consumers must tolerate unknown union members (e.g. skip, treat as `UnknownNode`, +/// or fall back to a rectangle) rather than hard-failing, to preserve forward +/// compatibility. +/// +/// Notes: +/// - The “Canonical” prefix indicates the representation is the stable, box-mapped +/// geometry form used in the archive, not a fully resolved mesh/path at a fixed size. +/// - Even when a variant currently has no fields (e.g. rectangular), it is kept as a +/// distinct member to preserve explicit author intent and allow future extensions +/// without changing other variants. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct CanonicalLayerShape(pub u8); +#[allow(non_upper_case_globals)] +impl CanonicalLayerShape { + pub const NONE: Self = Self(0); + pub const CanonicalShapeRectangular: Self = Self(1); + pub const CanonicalShapeElliptical: Self = Self(2); + pub const CanonicalShapePointsPolygon: Self = Self(3); + pub const CanonicalShapeRegularPolygon: Self = Self(4); + pub const CanonicalShapeRegularStarPolygon: Self = Self(5); + pub const CanonicalShapePath: Self = Self(6); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 6; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NONE, + Self::CanonicalShapeRectangular, + Self::CanonicalShapeElliptical, + Self::CanonicalShapePointsPolygon, + Self::CanonicalShapeRegularPolygon, + Self::CanonicalShapeRegularStarPolygon, + Self::CanonicalShapePath, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::CanonicalShapeRectangular => Some("CanonicalShapeRectangular"), + Self::CanonicalShapeElliptical => Some("CanonicalShapeElliptical"), + Self::CanonicalShapePointsPolygon => Some("CanonicalShapePointsPolygon"), + Self::CanonicalShapeRegularPolygon => Some("CanonicalShapeRegularPolygon"), + Self::CanonicalShapeRegularStarPolygon => Some("CanonicalShapeRegularStarPolygon"), + Self::CanonicalShapePath => Some("CanonicalShapePath"), + _ => None, + } + } +} +impl ::core::fmt::Debug for CanonicalLayerShape { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for CanonicalLayerShape { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for CanonicalLayerShape { + type Output = CanonicalLayerShape; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for CanonicalLayerShape { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for CanonicalLayerShape { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for CanonicalLayerShape {} +pub struct CanonicalLayerShapeUnionTableOffset {} + +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_LAYOUT_DIMENSION_UNIT: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_LAYOUT_DIMENSION_UNIT: u8 = 1; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_LAYOUT_DIMENSION_UNIT: [LayoutDimensionUnit; 2] = [ + LayoutDimensionUnit::LengthPx, + LayoutDimensionUnit::Percentage, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct LayoutDimensionUnit(pub u8); +#[allow(non_upper_case_globals)] +impl LayoutDimensionUnit { + pub const LengthPx: Self = Self(0); + pub const Percentage: Self = Self(1); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 1; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::LengthPx, + Self::Percentage, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::LengthPx => Some("LengthPx"), + Self::Percentage => Some("Percentage"), + _ => None, + } + } +} +impl ::core::fmt::Debug for LayoutDimensionUnit { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for LayoutDimensionUnit { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for LayoutDimensionUnit { + type Output = LayoutDimensionUnit; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for LayoutDimensionUnit { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for LayoutDimensionUnit { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for LayoutDimensionUnit {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_POSITIONING_SIDE_OFFSET_KIND: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_POSITIONING_SIDE_OFFSET_KIND: u8 = 1; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_POSITIONING_SIDE_OFFSET_KIND: [PositioningSideOffsetKind; 2] = [ + PositioningSideOffsetKind::Px, + PositioningSideOffsetKind::Percent, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct PositioningSideOffsetKind(pub u8); +#[allow(non_upper_case_globals)] +impl PositioningSideOffsetKind { + pub const Px: Self = Self(0); + pub const Percent: Self = Self(1); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 1; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::Px, + Self::Percent, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::Px => Some("Px"), + Self::Percent => Some("Percent"), + _ => None, + } + } +} +impl ::core::fmt::Debug for PositioningSideOffsetKind { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for PositioningSideOffsetKind { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for PositioningSideOffsetKind { + type Output = PositioningSideOffsetKind; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for PositioningSideOffsetKind { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for PositioningSideOffsetKind { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for PositioningSideOffsetKind {} +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_LAYOUT_POSITIONING_BASIS: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_LAYOUT_POSITIONING_BASIS: u8 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_LAYOUT_POSITIONING_BASIS: [LayoutPositioningBasis; 3] = [ + LayoutPositioningBasis::NONE, + LayoutPositioningBasis::LayoutPositioningCartesian, + LayoutPositioningBasis::LayoutPositioningInset, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct LayoutPositioningBasis(pub u8); +#[allow(non_upper_case_globals)] +impl LayoutPositioningBasis { + pub const NONE: Self = Self(0); + pub const LayoutPositioningCartesian: Self = Self(1); + pub const LayoutPositioningInset: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NONE, + Self::LayoutPositioningCartesian, + Self::LayoutPositioningInset, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::LayoutPositioningCartesian => Some("LayoutPositioningCartesian"), + Self::LayoutPositioningInset => Some("LayoutPositioningInset"), + _ => None, + } + } +} +impl ::core::fmt::Debug for LayoutPositioningBasis { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for LayoutPositioningBasis { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for LayoutPositioningBasis { + type Output = LayoutPositioningBasis; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for LayoutPositioningBasis { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for LayoutPositioningBasis { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for LayoutPositioningBasis {} +pub struct LayoutPositioningBasisUnionTableOffset {} + +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_NODE: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_NODE: u8 = 10; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_NODE: [Node; 11] = [ + Node::NONE, + Node::UnknownNode, + Node::SceneNode, + Node::GroupNode, + Node::InitialContainerNode, + Node::ContainerNode, + Node::BooleanOperationNode, + Node::BasicShapeNode, + Node::LineNode, + Node::VectorNode, + Node::TextSpanNode, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct Node(pub u8); +#[allow(non_upper_case_globals)] +impl Node { + pub const NONE: Self = Self(0); + pub const UnknownNode: Self = Self(1); + pub const SceneNode: Self = Self(2); + pub const GroupNode: Self = Self(3); + pub const InitialContainerNode: Self = Self(4); + pub const ContainerNode: Self = Self(5); + pub const BooleanOperationNode: Self = Self(6); + pub const BasicShapeNode: Self = Self(7); + pub const LineNode: Self = Self(8); + pub const VectorNode: Self = Self(9); + pub const TextSpanNode: Self = Self(10); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 10; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NONE, + Self::UnknownNode, + Self::SceneNode, + Self::GroupNode, + Self::InitialContainerNode, + Self::ContainerNode, + Self::BooleanOperationNode, + Self::BasicShapeNode, + Self::LineNode, + Self::VectorNode, + Self::TextSpanNode, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::UnknownNode => Some("UnknownNode"), + Self::SceneNode => Some("SceneNode"), + Self::GroupNode => Some("GroupNode"), + Self::InitialContainerNode => Some("InitialContainerNode"), + Self::ContainerNode => Some("ContainerNode"), + Self::BooleanOperationNode => Some("BooleanOperationNode"), + Self::BasicShapeNode => Some("BasicShapeNode"), + Self::LineNode => Some("LineNode"), + Self::VectorNode => Some("VectorNode"), + Self::TextSpanNode => Some("TextSpanNode"), + _ => None, + } + } +} +impl ::core::fmt::Debug for Node { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> ::flatbuffers::Follow<'a> for Node { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } +} + +impl ::flatbuffers::Push for Node { + type Output = Node; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } +} + +impl ::flatbuffers::EndianScalar for Node { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> ::flatbuffers::Verifiable for Node { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for Node {} +pub struct NodeUnionTableOffset {} + +/// Rust: `CGPoint { x: f32, y: f32 }` +// struct CGPoint, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct CGPoint(pub [u8; 8]); +impl Default for CGPoint { + fn default() -> Self { + Self([0; 8]) + } +} +impl ::core::fmt::Debug for CGPoint { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("CGPoint") + .field("x", &self.x()) + .field("y", &self.y()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for CGPoint {} +impl<'a> ::flatbuffers::Follow<'a> for CGPoint { + type Inner = &'a CGPoint; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a CGPoint>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a CGPoint { + type Inner = &'a CGPoint; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for CGPoint { + type Output = CGPoint; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const CGPoint as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for CGPoint { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> CGPoint { + #[allow(clippy::too_many_arguments)] + pub fn new( + x: f32, + y: f32, + ) -> Self { + let mut s = Self([0; 8]); + s.set_x(x); + s.set_y(y); + s + } + + pub fn x(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_x(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn y(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[4..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_y(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[4..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + +} + +/// `Alignment(pub f32, pub f32)` (cNDC, range typically [-1, 1]) +/// +/// Alignment(0,0) is the center of the rectangle. +// struct Alignment, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct Alignment(pub [u8; 8]); +impl Default for Alignment { + fn default() -> Self { + Self([0; 8]) + } +} +impl ::core::fmt::Debug for Alignment { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("Alignment") + .field("x", &self.x()) + .field("y", &self.y()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for Alignment {} +impl<'a> ::flatbuffers::Follow<'a> for Alignment { + type Inner = &'a Alignment; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a Alignment>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a Alignment { + type Inner = &'a Alignment; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for Alignment { + type Output = Alignment; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const Alignment as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for Alignment { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> Alignment { + #[allow(clippy::too_many_arguments)] + pub fn new( + x: f32, + y: f32, + ) -> Self { + let mut s = Self([0; 8]); + s.set_x(x); + s.set_y(y); + s + } + + pub fn x(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_x(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn y(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[4..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_y(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[4..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + +} + +/// Rust: `Uv(pub f32, pub f32)` (normalized [0, 1] domain) +// struct UV, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct UV(pub [u8; 8]); +impl Default for UV { + fn default() -> Self { + Self([0; 8]) + } +} +impl ::core::fmt::Debug for UV { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("UV") + .field("u", &self.u()) + .field("v", &self.v()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for UV {} +impl<'a> ::flatbuffers::Follow<'a> for UV { + type Inner = &'a UV; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a UV>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a UV { + type Inner = &'a UV; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for UV { + type Output = UV; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const UV as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for UV { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> UV { + #[allow(clippy::too_many_arguments)] + pub fn new( + u: f32, + v: f32, + ) -> Self { + let mut s = Self([0; 8]); + s.set_u(u); + s.set_v(v); + s + } + + pub fn u(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_u(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn v(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[4..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_v(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[4..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + +} + +/// Rust: (no dedicated cg struct) used throughout as (w,h). Keep for schema convenience. +// struct CGSize, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct CGSize(pub [u8; 8]); +impl Default for CGSize { + fn default() -> Self { + Self([0; 8]) + } +} +impl ::core::fmt::Debug for CGSize { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("CGSize") + .field("width", &self.width()) + .field("height", &self.height()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for CGSize {} +impl<'a> ::flatbuffers::Follow<'a> for CGSize { + type Inner = &'a CGSize; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a CGSize>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a CGSize { + type Inner = &'a CGSize; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for CGSize { + type Output = CGSize; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const CGSize as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for CGSize { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> CGSize { + #[allow(clippy::too_many_arguments)] + pub fn new( + width: f32, + height: f32, + ) -> Self { + let mut s = Self([0; 8]); + s.set_width(width); + s.set_height(height); + s + } + + pub fn width(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_width(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn height(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[4..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_height(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[4..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + +} + +/// RGBA in linear float space (0..1). +// struct RGBA32F, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct RGBA32F(pub [u8; 16]); +impl Default for RGBA32F { + fn default() -> Self { + Self([0; 16]) + } +} +impl ::core::fmt::Debug for RGBA32F { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("RGBA32F") + .field("r", &self.r()) + .field("g", &self.g()) + .field("b", &self.b()) + .field("a", &self.a()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for RGBA32F {} +impl<'a> ::flatbuffers::Follow<'a> for RGBA32F { + type Inner = &'a RGBA32F; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a RGBA32F>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a RGBA32F { + type Inner = &'a RGBA32F; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for RGBA32F { + type Output = RGBA32F; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const RGBA32F as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for RGBA32F { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> RGBA32F { + #[allow(clippy::too_many_arguments)] + pub fn new( + r: f32, + g: f32, + b: f32, + a: f32, + ) -> Self { + let mut s = Self([0; 16]); + s.set_r(r); + s.set_g(g); + s.set_b(b); + s.set_a(a); + s + } + + pub fn r(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_r(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn g(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[4..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_g(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[4..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn b(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[8..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_b(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[8..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn a(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[12..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_a(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[12..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + +} + +/// Rust: `CGTransform2D { m00..m12: f32 }` (and compatible with math2 `AffineTransform`). +/// +/// Matrix layout: +/// [ m00 m01 m02 ] +/// [ m10 m11 m12 ] +/// [ 0 0 1 ] +/// +/// Struct representation (no defaults in FlatBuffers structs). +// struct CGTransform2D, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct CGTransform2D(pub [u8; 24]); +impl Default for CGTransform2D { + fn default() -> Self { + Self([0; 24]) + } +} +impl ::core::fmt::Debug for CGTransform2D { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("CGTransform2D") + .field("m00", &self.m00()) + .field("m01", &self.m01()) + .field("m02", &self.m02()) + .field("m10", &self.m10()) + .field("m11", &self.m11()) + .field("m12", &self.m12()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for CGTransform2D {} +impl<'a> ::flatbuffers::Follow<'a> for CGTransform2D { + type Inner = &'a CGTransform2D; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a CGTransform2D>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a CGTransform2D { + type Inner = &'a CGTransform2D; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for CGTransform2D { + type Output = CGTransform2D; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const CGTransform2D as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for CGTransform2D { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> CGTransform2D { + #[allow(clippy::too_many_arguments)] + pub fn new( + m00: f32, + m01: f32, + m02: f32, + m10: f32, + m11: f32, + m12: f32, + ) -> Self { + let mut s = Self([0; 24]); + s.set_m00(m00); + s.set_m01(m01); + s.set_m02(m02); + s.set_m10(m10); + s.set_m11(m11); + s.set_m12(m12); + s + } + + pub fn m00(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_m00(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn m01(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[4..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_m01(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[4..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn m02(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[8..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_m02(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[8..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn m10(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[12..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_m10(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[12..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn m11(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[16..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_m11(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[16..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn m12(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[20..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_m12(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[20..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + +} + +/// Rust: `Radius { rx: f32, ry: f32 }` +// struct CGRadius, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct CGRadius(pub [u8; 8]); +impl Default for CGRadius { + fn default() -> Self { + Self([0; 8]) + } +} +impl ::core::fmt::Debug for CGRadius { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("CGRadius") + .field("rx", &self.rx()) + .field("ry", &self.ry()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for CGRadius {} +impl<'a> ::flatbuffers::Follow<'a> for CGRadius { + type Inner = &'a CGRadius; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a CGRadius>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a CGRadius { + type Inner = &'a CGRadius; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for CGRadius { + type Output = CGRadius; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const CGRadius as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for CGRadius { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> CGRadius { + #[allow(clippy::too_many_arguments)] + pub fn new( + rx: f32, + ry: f32, + ) -> Self { + let mut s = Self([0; 8]); + s.set_rx(rx); + s.set_ry(ry); + s + } + + pub fn rx(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_rx(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn ry(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[4..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_ry(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[4..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + +} + +// struct EdgeInsets, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct EdgeInsets(pub [u8; 16]); +impl Default for EdgeInsets { + fn default() -> Self { + Self([0; 16]) + } +} +impl ::core::fmt::Debug for EdgeInsets { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("EdgeInsets") + .field("top", &self.top()) + .field("right", &self.right()) + .field("bottom", &self.bottom()) + .field("left", &self.left()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for EdgeInsets {} +impl<'a> ::flatbuffers::Follow<'a> for EdgeInsets { + type Inner = &'a EdgeInsets; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a EdgeInsets>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a EdgeInsets { + type Inner = &'a EdgeInsets; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for EdgeInsets { + type Output = EdgeInsets; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const EdgeInsets as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for EdgeInsets { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> EdgeInsets { + #[allow(clippy::too_many_arguments)] + pub fn new( + top: f32, + right: f32, + bottom: f32, + left: f32, + ) -> Self { + let mut s = Self([0; 16]); + s.set_top(top); + s.set_right(right); + s.set_bottom(bottom); + s.set_left(left); + s + } + + pub fn top(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_top(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn right(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[4..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_right(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[4..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn bottom(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[8..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_bottom(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[8..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn left(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[12..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_left(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[12..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + +} + +/// Rust: `RectangularCornerRadius { tl,tr,bl,br: Radius }` +// struct RectangularCornerRadius, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct RectangularCornerRadius(pub [u8; 32]); +impl Default for RectangularCornerRadius { + fn default() -> Self { + Self([0; 32]) + } +} +impl ::core::fmt::Debug for RectangularCornerRadius { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("RectangularCornerRadius") + .field("tl", &self.tl()) + .field("tr", &self.tr()) + .field("bl", &self.bl()) + .field("br", &self.br()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for RectangularCornerRadius {} +impl<'a> ::flatbuffers::Follow<'a> for RectangularCornerRadius { + type Inner = &'a RectangularCornerRadius; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a RectangularCornerRadius>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a RectangularCornerRadius { + type Inner = &'a RectangularCornerRadius; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for RectangularCornerRadius { + type Output = RectangularCornerRadius; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const RectangularCornerRadius as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for RectangularCornerRadius { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> RectangularCornerRadius { + #[allow(clippy::too_many_arguments)] + pub fn new( + tl: &CGRadius, + tr: &CGRadius, + bl: &CGRadius, + br: &CGRadius, + ) -> Self { + let mut s = Self([0; 32]); + s.set_tl(tl); + s.set_tr(tr); + s.set_bl(bl); + s.set_br(br); + s + } + + pub fn tl(&self) -> &CGRadius { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot + unsafe { &*(self.0[0..].as_ptr() as *const CGRadius) } + } + + #[allow(clippy::identity_op)] + pub fn set_tl(&mut self, x: &CGRadius) { + self.0[0..0 + 8].copy_from_slice(&x.0) + } + + pub fn tr(&self) -> &CGRadius { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot + unsafe { &*(self.0[8..].as_ptr() as *const CGRadius) } + } + + #[allow(clippy::identity_op)] + pub fn set_tr(&mut self, x: &CGRadius) { + self.0[8..8 + 8].copy_from_slice(&x.0) + } + + pub fn bl(&self) -> &CGRadius { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot + unsafe { &*(self.0[16..].as_ptr() as *const CGRadius) } + } + + #[allow(clippy::identity_op)] + pub fn set_bl(&mut self, x: &CGRadius) { + self.0[16..16 + 8].copy_from_slice(&x.0) + } + + pub fn br(&self) -> &CGRadius { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot + unsafe { &*(self.0[24..].as_ptr() as *const CGRadius) } + } + + #[allow(clippy::identity_op)] + pub fn set_br(&mut self, x: &CGRadius) { + self.0[24..24 + 8].copy_from_slice(&x.0) + } + +} + +/// Per-side stroke widths (archive model). +/// +/// Struct representation. Note: structs cannot be null/omitted; all-zeros can be +/// interpreted as "not used" by codec/runtime if desired. +// struct RectangularStrokeWidth, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct RectangularStrokeWidth(pub [u8; 16]); +impl Default for RectangularStrokeWidth { + fn default() -> Self { + Self([0; 16]) + } +} +impl ::core::fmt::Debug for RectangularStrokeWidth { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("RectangularStrokeWidth") + .field("stroke_top_width", &self.stroke_top_width()) + .field("stroke_right_width", &self.stroke_right_width()) + .field("stroke_bottom_width", &self.stroke_bottom_width()) + .field("stroke_left_width", &self.stroke_left_width()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for RectangularStrokeWidth {} +impl<'a> ::flatbuffers::Follow<'a> for RectangularStrokeWidth { + type Inner = &'a RectangularStrokeWidth; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a RectangularStrokeWidth>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a RectangularStrokeWidth { + type Inner = &'a RectangularStrokeWidth; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for RectangularStrokeWidth { + type Output = RectangularStrokeWidth; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const RectangularStrokeWidth as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for RectangularStrokeWidth { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> RectangularStrokeWidth { + #[allow(clippy::too_many_arguments)] + pub fn new( + stroke_top_width: f32, + stroke_right_width: f32, + stroke_bottom_width: f32, + stroke_left_width: f32, + ) -> Self { + let mut s = Self([0; 16]); + s.set_stroke_top_width(stroke_top_width); + s.set_stroke_right_width(stroke_right_width); + s.set_stroke_bottom_width(stroke_bottom_width); + s.set_stroke_left_width(stroke_left_width); + s + } + + pub fn stroke_top_width(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_stroke_top_width(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn stroke_right_width(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[4..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_stroke_right_width(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[4..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn stroke_bottom_width(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[8..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_stroke_bottom_width(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[8..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn stroke_left_width(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[12..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_stroke_left_width(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[12..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + +} + +/// OpenType feature tag (4-byte ASCII, standard OpenType format). +/// +/// OpenType feature tags are exactly 4 characters, stored as 4 bytes. +/// This matches the binary OpenType format where tags are stored as [u8; 4]. +/// +/// Examples: +/// "kern" = {a:0x6B, b:0x65, c:0x72, d:0x6E} +/// "liga" = {a:0x6C, b:0x69, c:0x67, d:0x61} +/// "ss01" = {a:0x73, b:0x73, c:0x30, d:0x31} +/// +/// Codecs should convert between string tags (e.g., "kern") and this struct. +/// This approach allows any 4-character OpenType tag without schema evolution. +// struct OpenTypeFeatureTag, aligned to 1 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct OpenTypeFeatureTag(pub [u8; 4]); +impl Default for OpenTypeFeatureTag { + fn default() -> Self { + Self([0; 4]) + } +} +impl ::core::fmt::Debug for OpenTypeFeatureTag { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("OpenTypeFeatureTag") + .field("a", &self.a()) + .field("b", &self.b()) + .field("c", &self.c()) + .field("d", &self.d()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for OpenTypeFeatureTag {} +impl<'a> ::flatbuffers::Follow<'a> for OpenTypeFeatureTag { + type Inner = &'a OpenTypeFeatureTag; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a OpenTypeFeatureTag>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a OpenTypeFeatureTag { + type Inner = &'a OpenTypeFeatureTag; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for OpenTypeFeatureTag { + type Output = OpenTypeFeatureTag; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const OpenTypeFeatureTag as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(1) + } +} + +impl<'a> ::flatbuffers::Verifiable for OpenTypeFeatureTag { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> OpenTypeFeatureTag { + #[allow(clippy::too_many_arguments)] + pub fn new( + a: u8, + b: u8, + c: u8, + d: u8, + ) -> Self { + let mut s = Self([0; 4]); + s.set_a(a); + s.set_b(b); + s.set_c(c); + s.set_d(d); + s + } + + pub fn a(&self) -> u8 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_a(&mut self, x: u8) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn b(&self) -> u8 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[1..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_b(&mut self, x: u8) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[1..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn c(&self) -> u8 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[2..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_c(&mut self, x: u8) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[2..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn d(&self) -> u8 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[3..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_d(&mut self, x: u8) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[3..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + +} + +/// Rust: `FontWeight(pub u32)` +// struct FontWeight, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct FontWeight(pub [u8; 4]); +impl Default for FontWeight { + fn default() -> Self { + Self([0; 4]) + } +} +impl ::core::fmt::Debug for FontWeight { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("FontWeight") + .field("value", &self.value()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for FontWeight {} +impl<'a> ::flatbuffers::Follow<'a> for FontWeight { + type Inner = &'a FontWeight; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a FontWeight>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a FontWeight { + type Inner = &'a FontWeight; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for FontWeight { + type Output = FontWeight; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const FontWeight as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for FontWeight { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> FontWeight { + #[allow(clippy::too_many_arguments)] + pub fn new( + value: u32, + ) -> Self { + let mut s = Self([0; 4]); + s.set_value(value); + s + } + + pub fn value(&self) -> u32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_value(&mut self, x: u32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + +} + +// struct FontOpticalSizing, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct FontOpticalSizing(pub [u8; 8]); +impl Default for FontOpticalSizing { + fn default() -> Self { + Self([0; 8]) + } +} +impl ::core::fmt::Debug for FontOpticalSizing { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("FontOpticalSizing") + .field("kind", &self.kind()) + .field("value", &self.value()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for FontOpticalSizing {} +impl<'a> ::flatbuffers::Follow<'a> for FontOpticalSizing { + type Inner = &'a FontOpticalSizing; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a FontOpticalSizing>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a FontOpticalSizing { + type Inner = &'a FontOpticalSizing; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for FontOpticalSizing { + type Output = FontOpticalSizing; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const FontOpticalSizing as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for FontOpticalSizing { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> FontOpticalSizing { + #[allow(clippy::too_many_arguments)] + pub fn new( + kind: FontOpticalSizingKind, + value: f32, + ) -> Self { + let mut s = Self([0; 8]); + s.set_kind(kind); + s.set_value(value); + s + } + + pub fn kind(&self) -> FontOpticalSizingKind { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_kind(&mut self, x: FontOpticalSizingKind) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn value(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[4..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_value(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[4..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + +} + +// struct GradientStop, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct GradientStop(pub [u8; 20]); +impl Default for GradientStop { + fn default() -> Self { + Self([0; 20]) + } +} +impl ::core::fmt::Debug for GradientStop { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("GradientStop") + .field("stop_offset", &self.stop_offset()) + .field("stop_color", &self.stop_color()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for GradientStop {} +impl<'a> ::flatbuffers::Follow<'a> for GradientStop { + type Inner = &'a GradientStop; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a GradientStop>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a GradientStop { + type Inner = &'a GradientStop; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for GradientStop { + type Output = GradientStop; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const GradientStop as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for GradientStop { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> GradientStop { + #[allow(clippy::too_many_arguments)] + pub fn new( + stop_offset: f32, + stop_color: &RGBA32F, + ) -> Self { + let mut s = Self([0; 20]); + s.set_stop_offset(stop_offset); + s.set_stop_color(stop_color); + s + } + + pub fn stop_offset(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_stop_offset(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn stop_color(&self) -> &RGBA32F { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot + unsafe { &*(self.0[4..].as_ptr() as *const RGBA32F) } + } + + #[allow(clippy::identity_op)] + pub fn set_stop_color(&mut self, x: &RGBA32F) { + self.0[4..4 + 16].copy_from_slice(&x.0) + } + +} + +/// `ImageFilters` normalized to -0+ (center|default 0) +// struct ImageFilters, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct ImageFilters(pub [u8; 28]); +impl Default for ImageFilters { + fn default() -> Self { + Self([0; 28]) + } +} +impl ::core::fmt::Debug for ImageFilters { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("ImageFilters") + .field("exposure", &self.exposure()) + .field("contrast", &self.contrast()) + .field("saturation", &self.saturation()) + .field("temperature", &self.temperature()) + .field("tint", &self.tint()) + .field("highlights", &self.highlights()) + .field("shadows", &self.shadows()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for ImageFilters {} +impl<'a> ::flatbuffers::Follow<'a> for ImageFilters { + type Inner = &'a ImageFilters; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a ImageFilters>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a ImageFilters { + type Inner = &'a ImageFilters; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for ImageFilters { + type Output = ImageFilters; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const ImageFilters as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for ImageFilters { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> ImageFilters { + #[allow(clippy::too_many_arguments)] + pub fn new( + exposure: f32, + contrast: f32, + saturation: f32, + temperature: f32, + tint: f32, + highlights: f32, + shadows: f32, + ) -> Self { + let mut s = Self([0; 28]); + s.set_exposure(exposure); + s.set_contrast(contrast); + s.set_saturation(saturation); + s.set_temperature(temperature); + s.set_tint(tint); + s.set_highlights(highlights); + s.set_shadows(shadows); + s + } + + pub fn exposure(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_exposure(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn contrast(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[4..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_contrast(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[4..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn saturation(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[8..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_saturation(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[8..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn temperature(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[12..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_temperature(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[12..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn tint(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[16..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_tint(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[16..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn highlights(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[20..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_highlights(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[20..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn shadows(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[24..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_shadows(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[24..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + +} + +/// Rust: `ImageTile` +// struct ImageTile, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct ImageTile(pub [u8; 8]); +impl Default for ImageTile { + fn default() -> Self { + Self([0; 8]) + } +} +impl ::core::fmt::Debug for ImageTile { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("ImageTile") + .field("scale", &self.scale()) + .field("repeat", &self.repeat()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for ImageTile {} +impl<'a> ::flatbuffers::Follow<'a> for ImageTile { + type Inner = &'a ImageTile; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a ImageTile>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a ImageTile { + type Inner = &'a ImageTile; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for ImageTile { + type Output = ImageTile; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const ImageTile as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for ImageTile { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> ImageTile { + #[allow(clippy::too_many_arguments)] + pub fn new( + scale: f32, + repeat: ImageRepeat, + ) -> Self { + let mut s = Self([0; 8]); + s.set_scale(scale); + s.set_repeat(repeat); + s + } + + pub fn scale(&self) -> f32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_scale(&mut self, x: f32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn repeat(&self) -> ImageRepeat { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[4..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_repeat(&mut self, x: ImageRepeat) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[4..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + +} + +/// Rust: `(f32, f32)` vertex +/// +/// Stored as CGPoint (same coordinate space as node local geometry). +/// Indexed by position in the `vertices` array. +// struct VectorNetworkVertex, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct VectorNetworkVertex(pub [u8; 8]); +impl Default for VectorNetworkVertex { + fn default() -> Self { + Self([0; 8]) + } +} +impl ::core::fmt::Debug for VectorNetworkVertex { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("VectorNetworkVertex") + .field("vertex_position", &self.vertex_position()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for VectorNetworkVertex {} +impl<'a> ::flatbuffers::Follow<'a> for VectorNetworkVertex { + type Inner = &'a VectorNetworkVertex; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a VectorNetworkVertex>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a VectorNetworkVertex { + type Inner = &'a VectorNetworkVertex; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for VectorNetworkVertex { + type Output = VectorNetworkVertex; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const VectorNetworkVertex as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for VectorNetworkVertex { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> VectorNetworkVertex { + #[allow(clippy::too_many_arguments)] + pub fn new( + vertex_position: &CGPoint, + ) -> Self { + let mut s = Self([0; 8]); + s.set_vertex_position(vertex_position); + s + } + + pub fn vertex_position(&self) -> &CGPoint { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot + unsafe { &*(self.0[0..].as_ptr() as *const CGPoint) } + } + + #[allow(clippy::identity_op)] + pub fn set_vertex_position(&mut self, x: &CGPoint) { + self.0[0..0 + 8].copy_from_slice(&x.0) + } + +} + +/// Rust: `VectorNetworkSegment { a, b, ta, tb }` +/// +/// `tangent_a` / `tangent_b` are relative tangent vectors used for cubic béziers. +/// When both tangents are zero, the segment is a straight line. +// struct VectorNetworkSegment, aligned to 4 +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq)] +pub struct VectorNetworkSegment(pub [u8; 24]); +impl Default for VectorNetworkSegment { + fn default() -> Self { + Self([0; 24]) + } +} +impl ::core::fmt::Debug for VectorNetworkSegment { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct("VectorNetworkSegment") + .field("segment_vertex_a", &self.segment_vertex_a()) + .field("segment_vertex_b", &self.segment_vertex_b()) + .field("tangent_a", &self.tangent_a()) + .field("tangent_b", &self.tangent_b()) + .finish() + } +} + +impl ::flatbuffers::SimpleToVerifyInSlice for VectorNetworkSegment {} +impl<'a> ::flatbuffers::Follow<'a> for VectorNetworkSegment { + type Inner = &'a VectorNetworkSegment; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { <&'a VectorNetworkSegment>::follow(buf, loc) } + } +} +impl<'a> ::flatbuffers::Follow<'a> for &'a VectorNetworkSegment { + type Inner = &'a VectorNetworkSegment; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe { ::flatbuffers::follow_cast_ref::(buf, loc) } + } +} +impl<'b> ::flatbuffers::Push for VectorNetworkSegment { + type Output = VectorNetworkSegment; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = unsafe { ::core::slice::from_raw_parts(self as *const VectorNetworkSegment as *const u8, ::size()) }; + dst.copy_from_slice(src); + } + #[inline] + fn alignment() -> ::flatbuffers::PushAlignment { + ::flatbuffers::PushAlignment::new(4) + } +} + +impl<'a> ::flatbuffers::Verifiable for VectorNetworkSegment { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.in_buffer::(pos) + } +} + +impl<'a> VectorNetworkSegment { + #[allow(clippy::too_many_arguments)] + pub fn new( + segment_vertex_a: u32, + segment_vertex_b: u32, + tangent_a: &CGPoint, + tangent_b: &CGPoint, + ) -> Self { + let mut s = Self([0; 24]); + s.set_segment_vertex_a(segment_vertex_a); + s.set_segment_vertex_b(segment_vertex_b); + s.set_tangent_a(tangent_a); + s.set_tangent_b(tangent_b); + s + } + + pub fn segment_vertex_a(&self) -> u32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[0..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_segment_vertex_a(&mut self, x: u32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[0..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn segment_vertex_b(&self) -> u32 { + let mut mem = ::core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + ::flatbuffers::EndianScalar::from_little_endian(unsafe { + ::core::ptr::copy_nonoverlapping( + self.0[4..].as_ptr(), + mem.as_mut_ptr() as *mut u8, + ::core::mem::size_of::<::Scalar>(), + ); + mem.assume_init() + }) + } + + pub fn set_segment_vertex_b(&mut self, x: u32) { + let x_le = ::flatbuffers::EndianScalar::to_little_endian(x); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + unsafe { + ::core::ptr::copy_nonoverlapping( + &x_le as *const _ as *const u8, + self.0[4..].as_mut_ptr(), + ::core::mem::size_of::<::Scalar>(), + ); + } + } + + pub fn tangent_a(&self) -> &CGPoint { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot + unsafe { &*(self.0[8..].as_ptr() as *const CGPoint) } + } + + #[allow(clippy::identity_op)] + pub fn set_tangent_a(&mut self, x: &CGPoint) { + self.0[8..8 + 8].copy_from_slice(&x.0) + } + + pub fn tangent_b(&self) -> &CGPoint { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot + unsafe { &*(self.0[16..].as_ptr() as *const CGPoint) } + } + + #[allow(clippy::identity_op)] + pub fn set_tangent_b(&mut self, x: &CGPoint) { + self.0[16..16 + 8].copy_from_slice(&x.0) + } + +} + +pub enum NoneOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// `None` +pub struct None<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for None<'a> { + type Inner = None<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> None<'a> { + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + None { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + _args: &'args NoneArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = NoneBuilder::new(_fbb); + builder.finish() + } + +} + +impl ::flatbuffers::Verifiable for None<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .finish(); + Ok(()) + } +} +pub struct NoneArgs { +} +impl<'a> Default for NoneArgs { + #[inline] + fn default() -> Self { + NoneArgs { + } + } +} + +pub struct NoneBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> NoneBuilder<'a, 'b, A> { + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> NoneBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + NoneBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for None<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("None"); + ds.finish() + } +} +pub enum AutoOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Explicit length value models (archive input model; CSS-ish). +/// +/// NOTE: FlatBuffers unions can only include tables, not scalars/structs. +pub struct Auto<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for Auto<'a> { + type Inner = Auto<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> Auto<'a> { + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + Auto { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + _args: &'args AutoArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = AutoBuilder::new(_fbb); + builder.finish() + } + +} + +impl ::flatbuffers::Verifiable for Auto<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .finish(); + Ok(()) + } +} +pub struct AutoArgs { +} +impl<'a> Default for AutoArgs { + #[inline] + fn default() -> Self { + AutoArgs { + } + } +} + +pub struct AutoBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> AutoBuilder<'a, 'b, A> { + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> AutoBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + AutoBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for Auto<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("Auto"); + ds.finish() + } +} +pub enum NodeIdentifierOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Node identifier (temporary: string-based for compatibility with current editor). +/// +/// TODO: Update to use packed u32 (actor:8 | counter:24) for better performance. +/// Range: 0..=4_294_967_295. +/// +/// Current implementation uses string IDs to match TS editor model. +/// Future: migrate to struct NodeIdentifier { packed:uint; } for efficiency. +pub struct NodeIdentifier<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for NodeIdentifier<'a> { + type Inner = NodeIdentifier<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> NodeIdentifier<'a> { + pub const VT_ID: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + NodeIdentifier { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args NodeIdentifierArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = NodeIdentifierBuilder::new(_fbb); + if let Some(x) = args.id { builder.add_id(x); } + builder.finish() + } + + + /// Required: unique identifier string for the node. + #[inline] + pub fn id(&self) -> &'a str { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(NodeIdentifier::VT_ID, None).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for NodeIdentifier<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("id", Self::VT_ID, true)? + .finish(); + Ok(()) + } +} +pub struct NodeIdentifierArgs<'a> { + pub id: Option<::flatbuffers::WIPOffset<&'a str>>, +} +impl<'a> Default for NodeIdentifierArgs<'a> { + #[inline] + fn default() -> Self { + NodeIdentifierArgs { + id: None, // required field + } + } +} + +pub struct NodeIdentifierBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> NodeIdentifierBuilder<'a, 'b, A> { + #[inline] + pub fn add_id(&mut self, id: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(NodeIdentifier::VT_ID, id); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> NodeIdentifierBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + NodeIdentifierBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, NodeIdentifier::VT_ID,"id"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for NodeIdentifier<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("NodeIdentifier"); + ds.field("id", &self.id()); + ds.finish() + } +} +pub enum ParentReferenceOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Parent reference with fractional index position for ordering. +/// +/// Uses fractional indexing (orderable strings) to enable conflict-free +/// ordering in collaborative systems. The position string is designed to +/// sort correctly when compared lexicographically. +/// +/// Examples of fractional index strings: "!", " ~\"", "Qd&", "QeU", "Qe7", "QeO" +/// +/// Reference: Figma uses this same pattern (see `ParentIndex` in fig.kiwi). +/// This enables: +/// - Flat node structure (no nested children arrays) +/// - Efficient node moves (single node update, no parent reordering) +/// - Concurrent editing friendly ordering +/// +/// Note: Table (not struct) because it contains NodeIdentifier (a table). +/// This field is optional (can be null for root nodes). +pub struct ParentReference<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for ParentReference<'a> { + type Inner = ParentReference<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> ParentReference<'a> { + pub const VT_PARENT_ID: ::flatbuffers::VOffsetT = 4; + pub const VT_POSITION: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + ParentReference { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args ParentReferenceArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = ParentReferenceBuilder::new(_fbb); + if let Some(x) = args.position { builder.add_position(x); } + if let Some(x) = args.parent_id { builder.add_parent_id(x); } + builder.finish() + } + + + /// Parent node identifier + #[inline] + pub fn parent_id(&self) -> NodeIdentifier<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(ParentReference::VT_PARENT_ID, None).unwrap()} + } + /// Fractional index position string for ordering among siblings. + /// Empty string means "unsorted" or "default position". + /// Children are sorted by lexicographic comparison of position strings. + #[inline] + pub fn position(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(ParentReference::VT_POSITION, None)} + } +} + +impl ::flatbuffers::Verifiable for ParentReference<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("parent_id", Self::VT_PARENT_ID, true)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("position", Self::VT_POSITION, false)? + .finish(); + Ok(()) + } +} +pub struct ParentReferenceArgs<'a> { + pub parent_id: Option<::flatbuffers::WIPOffset>>, + pub position: Option<::flatbuffers::WIPOffset<&'a str>>, +} +impl<'a> Default for ParentReferenceArgs<'a> { + #[inline] + fn default() -> Self { + ParentReferenceArgs { + parent_id: None, // required field + position: None, + } + } +} + +pub struct ParentReferenceBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> ParentReferenceBuilder<'a, 'b, A> { + #[inline] + pub fn add_parent_id(&mut self, parent_id: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(ParentReference::VT_PARENT_ID, parent_id); + } + #[inline] + pub fn add_position(&mut self, position: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(ParentReference::VT_POSITION, position); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> ParentReferenceBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + ParentReferenceBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, ParentReference::VT_PARENT_ID,"parent_id"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for ParentReference<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("ParentReference"); + ds.field("parent_id", &self.parent_id()); + ds.field("position", &self.position()); + ds.finish() + } +} +pub enum LayerMaskTypeImageOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `LayerMaskType::Image(ImageMaskType)` +pub struct LayerMaskTypeImage<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for LayerMaskTypeImage<'a> { + type Inner = LayerMaskTypeImage<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> LayerMaskTypeImage<'a> { + pub const VT_IMAGE_MASK_TYPE: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + LayerMaskTypeImage { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args LayerMaskTypeImageArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = LayerMaskTypeImageBuilder::new(_fbb); + builder.add_image_mask_type(args.image_mask_type); + builder.finish() + } + + + #[inline] + pub fn image_mask_type(&self) -> ImageMaskType { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayerMaskTypeImage::VT_IMAGE_MASK_TYPE, Some(ImageMaskType::Alpha)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for LayerMaskTypeImage<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("image_mask_type", Self::VT_IMAGE_MASK_TYPE, false)? + .finish(); + Ok(()) + } +} +pub struct LayerMaskTypeImageArgs { + pub image_mask_type: ImageMaskType, +} +impl<'a> Default for LayerMaskTypeImageArgs { + #[inline] + fn default() -> Self { + LayerMaskTypeImageArgs { + image_mask_type: ImageMaskType::Alpha, + } + } +} + +pub struct LayerMaskTypeImageBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> LayerMaskTypeImageBuilder<'a, 'b, A> { + #[inline] + pub fn add_image_mask_type(&mut self, image_mask_type: ImageMaskType) { + self.fbb_.push_slot::(LayerMaskTypeImage::VT_IMAGE_MASK_TYPE, image_mask_type, ImageMaskType::Alpha); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> LayerMaskTypeImageBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + LayerMaskTypeImageBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for LayerMaskTypeImage<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("LayerMaskTypeImage"); + ds.field("image_mask_type", &self.image_mask_type()); + ds.finish() + } +} +pub enum LayerMaskTypeGeometryOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `LayerMaskType::Geometry` +pub struct LayerMaskTypeGeometry<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for LayerMaskTypeGeometry<'a> { + type Inner = LayerMaskTypeGeometry<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> LayerMaskTypeGeometry<'a> { + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + LayerMaskTypeGeometry { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + _args: &'args LayerMaskTypeGeometryArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = LayerMaskTypeGeometryBuilder::new(_fbb); + builder.finish() + } + +} + +impl ::flatbuffers::Verifiable for LayerMaskTypeGeometry<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .finish(); + Ok(()) + } +} +pub struct LayerMaskTypeGeometryArgs { +} +impl<'a> Default for LayerMaskTypeGeometryArgs { + #[inline] + fn default() -> Self { + LayerMaskTypeGeometryArgs { + } + } +} + +pub struct LayerMaskTypeGeometryBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> LayerMaskTypeGeometryBuilder<'a, 'b, A> { + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> LayerMaskTypeGeometryBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + LayerMaskTypeGeometryBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for LayerMaskTypeGeometry<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("LayerMaskTypeGeometry"); + ds.finish() + } +} +pub enum TextDimensionOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct TextDimension<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for TextDimension<'a> { + type Inner = TextDimension<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> TextDimension<'a> { + pub const VT_KIND: ::flatbuffers::VOffsetT = 4; + pub const VT_VALUE: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + TextDimension { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args TextDimensionArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = TextDimensionBuilder::new(_fbb); + if let Some(x) = args.value { builder.add_value(x); } + builder.add_kind(args.kind); + builder.finish() + } + + + #[inline] + pub fn kind(&self) -> TextDimensionKind { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextDimension::VT_KIND, Some(TextDimensionKind::Normal)).unwrap()} + } + #[inline] + pub fn value(&self) -> Option { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextDimension::VT_VALUE, None)} + } +} + +impl ::flatbuffers::Verifiable for TextDimension<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("kind", Self::VT_KIND, false)? + .visit_field::("value", Self::VT_VALUE, false)? + .finish(); + Ok(()) + } +} +pub struct TextDimensionArgs { + pub kind: TextDimensionKind, + pub value: Option, +} +impl<'a> Default for TextDimensionArgs { + #[inline] + fn default() -> Self { + TextDimensionArgs { + kind: TextDimensionKind::Normal, + value: None, + } + } +} + +pub struct TextDimensionBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> TextDimensionBuilder<'a, 'b, A> { + #[inline] + pub fn add_kind(&mut self, kind: TextDimensionKind) { + self.fbb_.push_slot::(TextDimension::VT_KIND, kind, TextDimensionKind::Normal); + } + #[inline] + pub fn add_value(&mut self, value: f32) { + self.fbb_.push_slot_always::(TextDimension::VT_VALUE, value); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> TextDimensionBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + TextDimensionBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for TextDimension<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("TextDimension"); + ds.field("kind", &self.kind()); + ds.field("value", &self.value()); + ds.finish() + } +} +pub enum FontFeatureOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `FontFeature { tag: String, value: bool }` +pub struct FontFeature<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for FontFeature<'a> { + type Inner = FontFeature<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> FontFeature<'a> { + pub const VT_OPEN_TYPE_FEATURE_TAG: ::flatbuffers::VOffsetT = 4; + pub const VT_OPEN_TYPE_FEATURE_VALUE: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + FontFeature { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args FontFeatureArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = FontFeatureBuilder::new(_fbb); + if let Some(x) = args.open_type_feature_tag { builder.add_open_type_feature_tag(x); } + builder.add_open_type_feature_value(args.open_type_feature_value); + builder.finish() + } + + + /// OpenType feature tag (4-byte encoding). + /// Codecs should convert between string ("kern") and OpenTypeFeatureTag struct. + #[inline] + pub fn open_type_feature_tag(&self) -> Option<&'a OpenTypeFeatureTag> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FontFeature::VT_OPEN_TYPE_FEATURE_TAG, None)} + } + #[inline] + pub fn open_type_feature_value(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FontFeature::VT_OPEN_TYPE_FEATURE_VALUE, Some(false)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for FontFeature<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("open_type_feature_tag", Self::VT_OPEN_TYPE_FEATURE_TAG, false)? + .visit_field::("open_type_feature_value", Self::VT_OPEN_TYPE_FEATURE_VALUE, false)? + .finish(); + Ok(()) + } +} +pub struct FontFeatureArgs<'a> { + pub open_type_feature_tag: Option<&'a OpenTypeFeatureTag>, + pub open_type_feature_value: bool, +} +impl<'a> Default for FontFeatureArgs<'a> { + #[inline] + fn default() -> Self { + FontFeatureArgs { + open_type_feature_tag: None, + open_type_feature_value: false, + } + } +} + +pub struct FontFeatureBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> FontFeatureBuilder<'a, 'b, A> { + #[inline] + pub fn add_open_type_feature_tag(&mut self, open_type_feature_tag: &OpenTypeFeatureTag) { + self.fbb_.push_slot_always::<&OpenTypeFeatureTag>(FontFeature::VT_OPEN_TYPE_FEATURE_TAG, open_type_feature_tag); + } + #[inline] + pub fn add_open_type_feature_value(&mut self, open_type_feature_value: bool) { + self.fbb_.push_slot::(FontFeature::VT_OPEN_TYPE_FEATURE_VALUE, open_type_feature_value, false); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> FontFeatureBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + FontFeatureBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for FontFeature<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("FontFeature"); + ds.field("open_type_feature_tag", &self.open_type_feature_tag()); + ds.field("open_type_feature_value", &self.open_type_feature_value()); + ds.finish() + } +} +pub enum FontVariationOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `FontVariation { axis: String, value: f32 }` +pub struct FontVariation<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for FontVariation<'a> { + type Inner = FontVariation<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> FontVariation<'a> { + pub const VT_VARIATION_AXIS: ::flatbuffers::VOffsetT = 4; + pub const VT_VARIATION_VALUE: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + FontVariation { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args FontVariationArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = FontVariationBuilder::new(_fbb); + builder.add_variation_value(args.variation_value); + if let Some(x) = args.variation_axis { builder.add_variation_axis(x); } + builder.finish() + } + + + #[inline] + pub fn variation_axis(&self) -> &'a str { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(FontVariation::VT_VARIATION_AXIS, None).unwrap()} + } + #[inline] + pub fn variation_value(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FontVariation::VT_VARIATION_VALUE, Some(0.0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for FontVariation<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("variation_axis", Self::VT_VARIATION_AXIS, true)? + .visit_field::("variation_value", Self::VT_VARIATION_VALUE, false)? + .finish(); + Ok(()) + } +} +pub struct FontVariationArgs<'a> { + pub variation_axis: Option<::flatbuffers::WIPOffset<&'a str>>, + pub variation_value: f32, +} +impl<'a> Default for FontVariationArgs<'a> { + #[inline] + fn default() -> Self { + FontVariationArgs { + variation_axis: None, // required field + variation_value: 0.0, + } + } +} + +pub struct FontVariationBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> FontVariationBuilder<'a, 'b, A> { + #[inline] + pub fn add_variation_axis(&mut self, variation_axis: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(FontVariation::VT_VARIATION_AXIS, variation_axis); + } + #[inline] + pub fn add_variation_value(&mut self, variation_value: f32) { + self.fbb_.push_slot::(FontVariation::VT_VARIATION_VALUE, variation_value, 0.0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> FontVariationBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + FontVariationBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, FontVariation::VT_VARIATION_AXIS,"variation_axis"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for FontVariation<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("FontVariation"); + ds.field("variation_axis", &self.variation_axis()); + ds.field("variation_value", &self.variation_value()); + ds.finish() + } +} +pub enum TextDecorationRecOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `TextDecorationRec` +/// +/// Archive model notes: +/// - `decoration_color` uses RGBA32F (float space) to match this schema's color choice. +pub struct TextDecorationRec<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for TextDecorationRec<'a> { + type Inner = TextDecorationRec<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> TextDecorationRec<'a> { + pub const VT_TEXT_DECORATION_LINE: ::flatbuffers::VOffsetT = 4; + pub const VT_TEXT_DECORATION_STYLE: ::flatbuffers::VOffsetT = 6; + pub const VT_TEXT_DECORATION_SKIP_INK: ::flatbuffers::VOffsetT = 8; + pub const VT_TEXT_DECORATION_THICKNESS: ::flatbuffers::VOffsetT = 10; + pub const VT_TEXT_DECORATION_COLOR: ::flatbuffers::VOffsetT = 12; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + TextDecorationRec { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args TextDecorationRecArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = TextDecorationRecBuilder::new(_fbb); + if let Some(x) = args.text_decoration_color { builder.add_text_decoration_color(x); } + builder.add_text_decoration_thickness(args.text_decoration_thickness); + builder.add_text_decoration_skip_ink(args.text_decoration_skip_ink); + builder.add_text_decoration_style(args.text_decoration_style); + builder.add_text_decoration_line(args.text_decoration_line); + builder.finish() + } + + + #[inline] + pub fn text_decoration_line(&self) -> TextDecorationLine { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextDecorationRec::VT_TEXT_DECORATION_LINE, Some(TextDecorationLine::None)).unwrap()} + } + #[inline] + pub fn text_decoration_style(&self) -> TextDecorationStyle { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextDecorationRec::VT_TEXT_DECORATION_STYLE, Some(TextDecorationStyle::Solid)).unwrap()} + } + #[inline] + pub fn text_decoration_skip_ink(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextDecorationRec::VT_TEXT_DECORATION_SKIP_INK, Some(true)).unwrap()} + } + #[inline] + pub fn text_decoration_thickness(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextDecorationRec::VT_TEXT_DECORATION_THICKNESS, Some(1.0)).unwrap()} + } + /// decoration color override, if unset, inherits + #[inline] + pub fn text_decoration_color(&self) -> Option<&'a RGBA32F> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextDecorationRec::VT_TEXT_DECORATION_COLOR, None)} + } +} + +impl ::flatbuffers::Verifiable for TextDecorationRec<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("text_decoration_line", Self::VT_TEXT_DECORATION_LINE, false)? + .visit_field::("text_decoration_style", Self::VT_TEXT_DECORATION_STYLE, false)? + .visit_field::("text_decoration_skip_ink", Self::VT_TEXT_DECORATION_SKIP_INK, false)? + .visit_field::("text_decoration_thickness", Self::VT_TEXT_DECORATION_THICKNESS, false)? + .visit_field::("text_decoration_color", Self::VT_TEXT_DECORATION_COLOR, false)? + .finish(); + Ok(()) + } +} +pub struct TextDecorationRecArgs<'a> { + pub text_decoration_line: TextDecorationLine, + pub text_decoration_style: TextDecorationStyle, + pub text_decoration_skip_ink: bool, + pub text_decoration_thickness: f32, + pub text_decoration_color: Option<&'a RGBA32F>, +} +impl<'a> Default for TextDecorationRecArgs<'a> { + #[inline] + fn default() -> Self { + TextDecorationRecArgs { + text_decoration_line: TextDecorationLine::None, + text_decoration_style: TextDecorationStyle::Solid, + text_decoration_skip_ink: true, + text_decoration_thickness: 1.0, + text_decoration_color: None, + } + } +} + +pub struct TextDecorationRecBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> TextDecorationRecBuilder<'a, 'b, A> { + #[inline] + pub fn add_text_decoration_line(&mut self, text_decoration_line: TextDecorationLine) { + self.fbb_.push_slot::(TextDecorationRec::VT_TEXT_DECORATION_LINE, text_decoration_line, TextDecorationLine::None); + } + #[inline] + pub fn add_text_decoration_style(&mut self, text_decoration_style: TextDecorationStyle) { + self.fbb_.push_slot::(TextDecorationRec::VT_TEXT_DECORATION_STYLE, text_decoration_style, TextDecorationStyle::Solid); + } + #[inline] + pub fn add_text_decoration_skip_ink(&mut self, text_decoration_skip_ink: bool) { + self.fbb_.push_slot::(TextDecorationRec::VT_TEXT_DECORATION_SKIP_INK, text_decoration_skip_ink, true); + } + #[inline] + pub fn add_text_decoration_thickness(&mut self, text_decoration_thickness: f32) { + self.fbb_.push_slot::(TextDecorationRec::VT_TEXT_DECORATION_THICKNESS, text_decoration_thickness, 1.0); + } + #[inline] + pub fn add_text_decoration_color(&mut self, text_decoration_color: &RGBA32F) { + self.fbb_.push_slot_always::<&RGBA32F>(TextDecorationRec::VT_TEXT_DECORATION_COLOR, text_decoration_color); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> TextDecorationRecBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + TextDecorationRecBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for TextDecorationRec<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("TextDecorationRec"); + ds.field("text_decoration_line", &self.text_decoration_line()); + ds.field("text_decoration_style", &self.text_decoration_style()); + ds.field("text_decoration_skip_ink", &self.text_decoration_skip_ink()); + ds.field("text_decoration_thickness", &self.text_decoration_thickness()); + ds.field("text_decoration_color", &self.text_decoration_color()); + ds.finish() + } +} +pub enum TextStyleRecOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// `TextStyleRec {}` +pub struct TextStyleRec<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for TextStyleRec<'a> { + type Inner = TextStyleRec<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> TextStyleRec<'a> { + pub const VT_TEXT_DECORATION: ::flatbuffers::VOffsetT = 4; + pub const VT_FONT_FAMILY: ::flatbuffers::VOffsetT = 6; + pub const VT_FONT_SIZE: ::flatbuffers::VOffsetT = 8; + pub const VT_FONT_WEIGHT: ::flatbuffers::VOffsetT = 10; + pub const VT_FONT_WIDTH: ::flatbuffers::VOffsetT = 12; + pub const VT_FONT_STYLE_ITALIC: ::flatbuffers::VOffsetT = 14; + pub const VT_FONT_KERNING: ::flatbuffers::VOffsetT = 16; + pub const VT_FONT_OPTICAL_SIZING: ::flatbuffers::VOffsetT = 18; + pub const VT_FONT_FEATURES: ::flatbuffers::VOffsetT = 20; + pub const VT_FONT_VARIATIONS: ::flatbuffers::VOffsetT = 22; + pub const VT_LETTER_SPACING: ::flatbuffers::VOffsetT = 24; + pub const VT_WORD_SPACING: ::flatbuffers::VOffsetT = 26; + pub const VT_LINE_HEIGHT: ::flatbuffers::VOffsetT = 28; + pub const VT_TEXT_TRANSFORM: ::flatbuffers::VOffsetT = 30; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + TextStyleRec { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args TextStyleRecArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = TextStyleRecBuilder::new(_fbb); + if let Some(x) = args.line_height { builder.add_line_height(x); } + if let Some(x) = args.word_spacing { builder.add_word_spacing(x); } + if let Some(x) = args.letter_spacing { builder.add_letter_spacing(x); } + if let Some(x) = args.font_variations { builder.add_font_variations(x); } + if let Some(x) = args.font_features { builder.add_font_features(x); } + if let Some(x) = args.font_optical_sizing { builder.add_font_optical_sizing(x); } + builder.add_font_width(args.font_width); + if let Some(x) = args.font_weight { builder.add_font_weight(x); } + builder.add_font_size(args.font_size); + if let Some(x) = args.font_family { builder.add_font_family(x); } + if let Some(x) = args.text_decoration { builder.add_text_decoration(x); } + builder.add_text_transform(args.text_transform); + builder.add_font_kerning(args.font_kerning); + builder.add_font_style_italic(args.font_style_italic); + builder.finish() + } + + + #[inline] + pub fn text_decoration(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(TextStyleRec::VT_TEXT_DECORATION, None)} + } + #[inline] + pub fn font_family(&self) -> &'a str { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(TextStyleRec::VT_FONT_FAMILY, None).unwrap()} + } + #[inline] + pub fn font_size(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextStyleRec::VT_FONT_SIZE, Some(14.0)).unwrap()} + } + #[inline] + pub fn font_weight(&self) -> &'a FontWeight { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextStyleRec::VT_FONT_WEIGHT, None).unwrap()} + } + #[inline] + pub fn font_width(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextStyleRec::VT_FONT_WIDTH, Some(0.0)).unwrap()} + } + #[inline] + pub fn font_style_italic(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextStyleRec::VT_FONT_STYLE_ITALIC, Some(false)).unwrap()} + } + #[inline] + pub fn font_kerning(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextStyleRec::VT_FONT_KERNING, Some(true)).unwrap()} + } + #[inline] + pub fn font_optical_sizing(&self) -> Option<&'a FontOpticalSizing> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextStyleRec::VT_FONT_OPTICAL_SIZING, None)} + } + #[inline] + pub fn font_features(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(TextStyleRec::VT_FONT_FEATURES, None)} + } + #[inline] + pub fn font_variations(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(TextStyleRec::VT_FONT_VARIATIONS, None)} + } + #[inline] + pub fn letter_spacing(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(TextStyleRec::VT_LETTER_SPACING, None)} + } + #[inline] + pub fn word_spacing(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(TextStyleRec::VT_WORD_SPACING, None)} + } + #[inline] + pub fn line_height(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(TextStyleRec::VT_LINE_HEIGHT, None)} + } + #[inline] + pub fn text_transform(&self) -> TextTransform { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextStyleRec::VT_TEXT_TRANSFORM, Some(TextTransform::None)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for TextStyleRec<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("text_decoration", Self::VT_TEXT_DECORATION, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("font_family", Self::VT_FONT_FAMILY, true)? + .visit_field::("font_size", Self::VT_FONT_SIZE, false)? + .visit_field::("font_weight", Self::VT_FONT_WEIGHT, true)? + .visit_field::("font_width", Self::VT_FONT_WIDTH, false)? + .visit_field::("font_style_italic", Self::VT_FONT_STYLE_ITALIC, false)? + .visit_field::("font_kerning", Self::VT_FONT_KERNING, false)? + .visit_field::("font_optical_sizing", Self::VT_FONT_OPTICAL_SIZING, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("font_features", Self::VT_FONT_FEATURES, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("font_variations", Self::VT_FONT_VARIATIONS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("letter_spacing", Self::VT_LETTER_SPACING, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("word_spacing", Self::VT_WORD_SPACING, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("line_height", Self::VT_LINE_HEIGHT, false)? + .visit_field::("text_transform", Self::VT_TEXT_TRANSFORM, false)? + .finish(); + Ok(()) + } +} +pub struct TextStyleRecArgs<'a> { + pub text_decoration: Option<::flatbuffers::WIPOffset>>, + pub font_family: Option<::flatbuffers::WIPOffset<&'a str>>, + pub font_size: f32, + pub font_weight: Option<&'a FontWeight>, + pub font_width: f32, + pub font_style_italic: bool, + pub font_kerning: bool, + pub font_optical_sizing: Option<&'a FontOpticalSizing>, + pub font_features: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub font_variations: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub letter_spacing: Option<::flatbuffers::WIPOffset>>, + pub word_spacing: Option<::flatbuffers::WIPOffset>>, + pub line_height: Option<::flatbuffers::WIPOffset>>, + pub text_transform: TextTransform, +} +impl<'a> Default for TextStyleRecArgs<'a> { + #[inline] + fn default() -> Self { + TextStyleRecArgs { + text_decoration: None, + font_family: None, // required field + font_size: 14.0, + font_weight: None, // required field + font_width: 0.0, + font_style_italic: false, + font_kerning: true, + font_optical_sizing: None, + font_features: None, + font_variations: None, + letter_spacing: None, + word_spacing: None, + line_height: None, + text_transform: TextTransform::None, + } + } +} + +pub struct TextStyleRecBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> TextStyleRecBuilder<'a, 'b, A> { + #[inline] + pub fn add_text_decoration(&mut self, text_decoration: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(TextStyleRec::VT_TEXT_DECORATION, text_decoration); + } + #[inline] + pub fn add_font_family(&mut self, font_family: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(TextStyleRec::VT_FONT_FAMILY, font_family); + } + #[inline] + pub fn add_font_size(&mut self, font_size: f32) { + self.fbb_.push_slot::(TextStyleRec::VT_FONT_SIZE, font_size, 14.0); + } + #[inline] + pub fn add_font_weight(&mut self, font_weight: &FontWeight) { + self.fbb_.push_slot_always::<&FontWeight>(TextStyleRec::VT_FONT_WEIGHT, font_weight); + } + #[inline] + pub fn add_font_width(&mut self, font_width: f32) { + self.fbb_.push_slot::(TextStyleRec::VT_FONT_WIDTH, font_width, 0.0); + } + #[inline] + pub fn add_font_style_italic(&mut self, font_style_italic: bool) { + self.fbb_.push_slot::(TextStyleRec::VT_FONT_STYLE_ITALIC, font_style_italic, false); + } + #[inline] + pub fn add_font_kerning(&mut self, font_kerning: bool) { + self.fbb_.push_slot::(TextStyleRec::VT_FONT_KERNING, font_kerning, true); + } + #[inline] + pub fn add_font_optical_sizing(&mut self, font_optical_sizing: &FontOpticalSizing) { + self.fbb_.push_slot_always::<&FontOpticalSizing>(TextStyleRec::VT_FONT_OPTICAL_SIZING, font_optical_sizing); + } + #[inline] + pub fn add_font_features(&mut self, font_features: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(TextStyleRec::VT_FONT_FEATURES, font_features); + } + #[inline] + pub fn add_font_variations(&mut self, font_variations: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(TextStyleRec::VT_FONT_VARIATIONS, font_variations); + } + #[inline] + pub fn add_letter_spacing(&mut self, letter_spacing: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(TextStyleRec::VT_LETTER_SPACING, letter_spacing); + } + #[inline] + pub fn add_word_spacing(&mut self, word_spacing: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(TextStyleRec::VT_WORD_SPACING, word_spacing); + } + #[inline] + pub fn add_line_height(&mut self, line_height: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(TextStyleRec::VT_LINE_HEIGHT, line_height); + } + #[inline] + pub fn add_text_transform(&mut self, text_transform: TextTransform) { + self.fbb_.push_slot::(TextStyleRec::VT_TEXT_TRANSFORM, text_transform, TextTransform::None); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> TextStyleRecBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + TextStyleRecBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, TextStyleRec::VT_FONT_FAMILY,"font_family"); + self.fbb_.required(o, TextStyleRec::VT_FONT_WEIGHT,"font_weight"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for TextStyleRec<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("TextStyleRec"); + ds.field("text_decoration", &self.text_decoration()); + ds.field("font_family", &self.font_family()); + ds.field("font_size", &self.font_size()); + ds.field("font_weight", &self.font_weight()); + ds.field("font_width", &self.font_width()); + ds.field("font_style_italic", &self.font_style_italic()); + ds.field("font_kerning", &self.font_kerning()); + ds.field("font_optical_sizing", &self.font_optical_sizing()); + ds.field("font_features", &self.font_features()); + ds.field("font_variations", &self.font_variations()); + ds.field("letter_spacing", &self.letter_spacing()); + ds.field("word_spacing", &self.word_spacing()); + ds.field("line_height", &self.line_height()); + ds.field("text_transform", &self.text_transform()); + ds.finish() + } +} +pub enum SolidPaintOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct SolidPaint<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for SolidPaint<'a> { + type Inner = SolidPaint<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> SolidPaint<'a> { + pub const VT_ACTIVE: ::flatbuffers::VOffsetT = 4; + pub const VT_COLOR: ::flatbuffers::VOffsetT = 6; + pub const VT_BLEND_MODE: ::flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + SolidPaint { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args SolidPaintArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = SolidPaintBuilder::new(_fbb); + if let Some(x) = args.color { builder.add_color(x); } + builder.add_blend_mode(args.blend_mode); + builder.add_active(args.active); + builder.finish() + } + + + #[inline] + pub fn active(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(SolidPaint::VT_ACTIVE, Some(true)).unwrap()} + } + #[inline] + pub fn color(&self) -> Option<&'a RGBA32F> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(SolidPaint::VT_COLOR, None)} + } + #[inline] + pub fn blend_mode(&self) -> BlendMode { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(SolidPaint::VT_BLEND_MODE, Some(BlendMode::Normal)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for SolidPaint<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("active", Self::VT_ACTIVE, false)? + .visit_field::("color", Self::VT_COLOR, false)? + .visit_field::("blend_mode", Self::VT_BLEND_MODE, false)? + .finish(); + Ok(()) + } +} +pub struct SolidPaintArgs<'a> { + pub active: bool, + pub color: Option<&'a RGBA32F>, + pub blend_mode: BlendMode, +} +impl<'a> Default for SolidPaintArgs<'a> { + #[inline] + fn default() -> Self { + SolidPaintArgs { + active: true, + color: None, + blend_mode: BlendMode::Normal, + } + } +} + +pub struct SolidPaintBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> SolidPaintBuilder<'a, 'b, A> { + #[inline] + pub fn add_active(&mut self, active: bool) { + self.fbb_.push_slot::(SolidPaint::VT_ACTIVE, active, true); + } + #[inline] + pub fn add_color(&mut self, color: &RGBA32F) { + self.fbb_.push_slot_always::<&RGBA32F>(SolidPaint::VT_COLOR, color); + } + #[inline] + pub fn add_blend_mode(&mut self, blend_mode: BlendMode) { + self.fbb_.push_slot::(SolidPaint::VT_BLEND_MODE, blend_mode, BlendMode::Normal); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> SolidPaintBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + SolidPaintBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for SolidPaint<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("SolidPaint"); + ds.field("active", &self.active()); + ds.field("color", &self.color()); + ds.field("blend_mode", &self.blend_mode()); + ds.finish() + } +} +pub enum LinearGradientPaintOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct LinearGradientPaint<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for LinearGradientPaint<'a> { + type Inner = LinearGradientPaint<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> LinearGradientPaint<'a> { + pub const VT_ACTIVE: ::flatbuffers::VOffsetT = 4; + pub const VT_XY1: ::flatbuffers::VOffsetT = 6; + pub const VT_XY2: ::flatbuffers::VOffsetT = 8; + pub const VT_TILE_MODE: ::flatbuffers::VOffsetT = 10; + pub const VT_TRANSFORM: ::flatbuffers::VOffsetT = 12; + pub const VT_STOPS: ::flatbuffers::VOffsetT = 14; + pub const VT_OPACITY: ::flatbuffers::VOffsetT = 16; + pub const VT_BLEND_MODE: ::flatbuffers::VOffsetT = 18; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + LinearGradientPaint { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args LinearGradientPaintArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = LinearGradientPaintBuilder::new(_fbb); + builder.add_opacity(args.opacity); + if let Some(x) = args.stops { builder.add_stops(x); } + if let Some(x) = args.transform { builder.add_transform(x); } + if let Some(x) = args.xy2 { builder.add_xy2(x); } + if let Some(x) = args.xy1 { builder.add_xy1(x); } + builder.add_blend_mode(args.blend_mode); + builder.add_tile_mode(args.tile_mode); + builder.add_active(args.active); + builder.finish() + } + + + #[inline] + pub fn active(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LinearGradientPaint::VT_ACTIVE, Some(true)).unwrap()} + } + #[inline] + pub fn xy1(&self) -> Option<&'a Alignment> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LinearGradientPaint::VT_XY1, None)} + } + #[inline] + pub fn xy2(&self) -> Option<&'a Alignment> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LinearGradientPaint::VT_XY2, None)} + } + #[inline] + pub fn tile_mode(&self) -> TileMode { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LinearGradientPaint::VT_TILE_MODE, Some(TileMode::Clamp)).unwrap()} + } + /// transform of the gradient, if empty(unset) canonical is identity + #[inline] + pub fn transform(&self) -> Option<&'a CGTransform2D> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LinearGradientPaint::VT_TRANSFORM, None)} + } + #[inline] + pub fn stops(&self) -> Option<::flatbuffers::Vector<'a, GradientStop>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, GradientStop>>>(LinearGradientPaint::VT_STOPS, None)} + } + #[inline] + pub fn opacity(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LinearGradientPaint::VT_OPACITY, Some(1.0)).unwrap()} + } + #[inline] + pub fn blend_mode(&self) -> BlendMode { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LinearGradientPaint::VT_BLEND_MODE, Some(BlendMode::Normal)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for LinearGradientPaint<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("active", Self::VT_ACTIVE, false)? + .visit_field::("xy1", Self::VT_XY1, false)? + .visit_field::("xy2", Self::VT_XY2, false)? + .visit_field::("tile_mode", Self::VT_TILE_MODE, false)? + .visit_field::("transform", Self::VT_TRANSFORM, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, GradientStop>>>("stops", Self::VT_STOPS, false)? + .visit_field::("opacity", Self::VT_OPACITY, false)? + .visit_field::("blend_mode", Self::VT_BLEND_MODE, false)? + .finish(); + Ok(()) + } +} +pub struct LinearGradientPaintArgs<'a> { + pub active: bool, + pub xy1: Option<&'a Alignment>, + pub xy2: Option<&'a Alignment>, + pub tile_mode: TileMode, + pub transform: Option<&'a CGTransform2D>, + pub stops: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, GradientStop>>>, + pub opacity: f32, + pub blend_mode: BlendMode, +} +impl<'a> Default for LinearGradientPaintArgs<'a> { + #[inline] + fn default() -> Self { + LinearGradientPaintArgs { + active: true, + xy1: None, + xy2: None, + tile_mode: TileMode::Clamp, + transform: None, + stops: None, + opacity: 1.0, + blend_mode: BlendMode::Normal, + } + } +} + +pub struct LinearGradientPaintBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> LinearGradientPaintBuilder<'a, 'b, A> { + #[inline] + pub fn add_active(&mut self, active: bool) { + self.fbb_.push_slot::(LinearGradientPaint::VT_ACTIVE, active, true); + } + #[inline] + pub fn add_xy1(&mut self, xy1: &Alignment) { + self.fbb_.push_slot_always::<&Alignment>(LinearGradientPaint::VT_XY1, xy1); + } + #[inline] + pub fn add_xy2(&mut self, xy2: &Alignment) { + self.fbb_.push_slot_always::<&Alignment>(LinearGradientPaint::VT_XY2, xy2); + } + #[inline] + pub fn add_tile_mode(&mut self, tile_mode: TileMode) { + self.fbb_.push_slot::(LinearGradientPaint::VT_TILE_MODE, tile_mode, TileMode::Clamp); + } + #[inline] + pub fn add_transform(&mut self, transform: &CGTransform2D) { + self.fbb_.push_slot_always::<&CGTransform2D>(LinearGradientPaint::VT_TRANSFORM, transform); + } + #[inline] + pub fn add_stops(&mut self, stops: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , GradientStop>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(LinearGradientPaint::VT_STOPS, stops); + } + #[inline] + pub fn add_opacity(&mut self, opacity: f32) { + self.fbb_.push_slot::(LinearGradientPaint::VT_OPACITY, opacity, 1.0); + } + #[inline] + pub fn add_blend_mode(&mut self, blend_mode: BlendMode) { + self.fbb_.push_slot::(LinearGradientPaint::VT_BLEND_MODE, blend_mode, BlendMode::Normal); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> LinearGradientPaintBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + LinearGradientPaintBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for LinearGradientPaint<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("LinearGradientPaint"); + ds.field("active", &self.active()); + ds.field("xy1", &self.xy1()); + ds.field("xy2", &self.xy2()); + ds.field("tile_mode", &self.tile_mode()); + ds.field("transform", &self.transform()); + ds.field("stops", &self.stops()); + ds.field("opacity", &self.opacity()); + ds.field("blend_mode", &self.blend_mode()); + ds.finish() + } +} +pub enum RadialGradientPaintOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct RadialGradientPaint<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for RadialGradientPaint<'a> { + type Inner = RadialGradientPaint<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> RadialGradientPaint<'a> { + pub const VT_ACTIVE: ::flatbuffers::VOffsetT = 4; + pub const VT_TRANSFORM: ::flatbuffers::VOffsetT = 6; + pub const VT_STOPS: ::flatbuffers::VOffsetT = 8; + pub const VT_OPACITY: ::flatbuffers::VOffsetT = 10; + pub const VT_BLEND_MODE: ::flatbuffers::VOffsetT = 12; + pub const VT_TILE_MODE: ::flatbuffers::VOffsetT = 14; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + RadialGradientPaint { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args RadialGradientPaintArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = RadialGradientPaintBuilder::new(_fbb); + builder.add_opacity(args.opacity); + if let Some(x) = args.stops { builder.add_stops(x); } + if let Some(x) = args.transform { builder.add_transform(x); } + builder.add_tile_mode(args.tile_mode); + builder.add_blend_mode(args.blend_mode); + builder.add_active(args.active); + builder.finish() + } + + + #[inline] + pub fn active(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(RadialGradientPaint::VT_ACTIVE, Some(true)).unwrap()} + } + /// transform of the gradient, if empty(unset) canonical is identity + #[inline] + pub fn transform(&self) -> Option<&'a CGTransform2D> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(RadialGradientPaint::VT_TRANSFORM, None)} + } + #[inline] + pub fn stops(&self) -> Option<::flatbuffers::Vector<'a, GradientStop>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, GradientStop>>>(RadialGradientPaint::VT_STOPS, None)} + } + #[inline] + pub fn opacity(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(RadialGradientPaint::VT_OPACITY, Some(1.0)).unwrap()} + } + #[inline] + pub fn blend_mode(&self) -> BlendMode { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(RadialGradientPaint::VT_BLEND_MODE, Some(BlendMode::Normal)).unwrap()} + } + #[inline] + pub fn tile_mode(&self) -> TileMode { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(RadialGradientPaint::VT_TILE_MODE, Some(TileMode::Clamp)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for RadialGradientPaint<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("active", Self::VT_ACTIVE, false)? + .visit_field::("transform", Self::VT_TRANSFORM, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, GradientStop>>>("stops", Self::VT_STOPS, false)? + .visit_field::("opacity", Self::VT_OPACITY, false)? + .visit_field::("blend_mode", Self::VT_BLEND_MODE, false)? + .visit_field::("tile_mode", Self::VT_TILE_MODE, false)? + .finish(); + Ok(()) + } +} +pub struct RadialGradientPaintArgs<'a> { + pub active: bool, + pub transform: Option<&'a CGTransform2D>, + pub stops: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, GradientStop>>>, + pub opacity: f32, + pub blend_mode: BlendMode, + pub tile_mode: TileMode, +} +impl<'a> Default for RadialGradientPaintArgs<'a> { + #[inline] + fn default() -> Self { + RadialGradientPaintArgs { + active: true, + transform: None, + stops: None, + opacity: 1.0, + blend_mode: BlendMode::Normal, + tile_mode: TileMode::Clamp, + } + } +} + +pub struct RadialGradientPaintBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> RadialGradientPaintBuilder<'a, 'b, A> { + #[inline] + pub fn add_active(&mut self, active: bool) { + self.fbb_.push_slot::(RadialGradientPaint::VT_ACTIVE, active, true); + } + #[inline] + pub fn add_transform(&mut self, transform: &CGTransform2D) { + self.fbb_.push_slot_always::<&CGTransform2D>(RadialGradientPaint::VT_TRANSFORM, transform); + } + #[inline] + pub fn add_stops(&mut self, stops: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , GradientStop>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(RadialGradientPaint::VT_STOPS, stops); + } + #[inline] + pub fn add_opacity(&mut self, opacity: f32) { + self.fbb_.push_slot::(RadialGradientPaint::VT_OPACITY, opacity, 1.0); + } + #[inline] + pub fn add_blend_mode(&mut self, blend_mode: BlendMode) { + self.fbb_.push_slot::(RadialGradientPaint::VT_BLEND_MODE, blend_mode, BlendMode::Normal); + } + #[inline] + pub fn add_tile_mode(&mut self, tile_mode: TileMode) { + self.fbb_.push_slot::(RadialGradientPaint::VT_TILE_MODE, tile_mode, TileMode::Clamp); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> RadialGradientPaintBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + RadialGradientPaintBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for RadialGradientPaint<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("RadialGradientPaint"); + ds.field("active", &self.active()); + ds.field("transform", &self.transform()); + ds.field("stops", &self.stops()); + ds.field("opacity", &self.opacity()); + ds.field("blend_mode", &self.blend_mode()); + ds.field("tile_mode", &self.tile_mode()); + ds.finish() + } +} +pub enum DiamondGradientPaintOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct DiamondGradientPaint<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for DiamondGradientPaint<'a> { + type Inner = DiamondGradientPaint<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> DiamondGradientPaint<'a> { + pub const VT_ACTIVE: ::flatbuffers::VOffsetT = 4; + pub const VT_TRANSFORM: ::flatbuffers::VOffsetT = 6; + pub const VT_STOPS: ::flatbuffers::VOffsetT = 8; + pub const VT_OPACITY: ::flatbuffers::VOffsetT = 10; + pub const VT_BLEND_MODE: ::flatbuffers::VOffsetT = 12; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + DiamondGradientPaint { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args DiamondGradientPaintArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = DiamondGradientPaintBuilder::new(_fbb); + builder.add_opacity(args.opacity); + if let Some(x) = args.stops { builder.add_stops(x); } + if let Some(x) = args.transform { builder.add_transform(x); } + builder.add_blend_mode(args.blend_mode); + builder.add_active(args.active); + builder.finish() + } + + + #[inline] + pub fn active(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(DiamondGradientPaint::VT_ACTIVE, Some(true)).unwrap()} + } + /// transform of the gradient, if empty(unset) canonical is identity + #[inline] + pub fn transform(&self) -> Option<&'a CGTransform2D> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(DiamondGradientPaint::VT_TRANSFORM, None)} + } + #[inline] + pub fn stops(&self) -> Option<::flatbuffers::Vector<'a, GradientStop>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, GradientStop>>>(DiamondGradientPaint::VT_STOPS, None)} + } + #[inline] + pub fn opacity(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(DiamondGradientPaint::VT_OPACITY, Some(1.0)).unwrap()} + } + #[inline] + pub fn blend_mode(&self) -> BlendMode { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(DiamondGradientPaint::VT_BLEND_MODE, Some(BlendMode::Normal)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for DiamondGradientPaint<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("active", Self::VT_ACTIVE, false)? + .visit_field::("transform", Self::VT_TRANSFORM, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, GradientStop>>>("stops", Self::VT_STOPS, false)? + .visit_field::("opacity", Self::VT_OPACITY, false)? + .visit_field::("blend_mode", Self::VT_BLEND_MODE, false)? + .finish(); + Ok(()) + } +} +pub struct DiamondGradientPaintArgs<'a> { + pub active: bool, + pub transform: Option<&'a CGTransform2D>, + pub stops: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, GradientStop>>>, + pub opacity: f32, + pub blend_mode: BlendMode, +} +impl<'a> Default for DiamondGradientPaintArgs<'a> { + #[inline] + fn default() -> Self { + DiamondGradientPaintArgs { + active: true, + transform: None, + stops: None, + opacity: 1.0, + blend_mode: BlendMode::Normal, + } + } +} + +pub struct DiamondGradientPaintBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> DiamondGradientPaintBuilder<'a, 'b, A> { + #[inline] + pub fn add_active(&mut self, active: bool) { + self.fbb_.push_slot::(DiamondGradientPaint::VT_ACTIVE, active, true); + } + #[inline] + pub fn add_transform(&mut self, transform: &CGTransform2D) { + self.fbb_.push_slot_always::<&CGTransform2D>(DiamondGradientPaint::VT_TRANSFORM, transform); + } + #[inline] + pub fn add_stops(&mut self, stops: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , GradientStop>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(DiamondGradientPaint::VT_STOPS, stops); + } + #[inline] + pub fn add_opacity(&mut self, opacity: f32) { + self.fbb_.push_slot::(DiamondGradientPaint::VT_OPACITY, opacity, 1.0); + } + #[inline] + pub fn add_blend_mode(&mut self, blend_mode: BlendMode) { + self.fbb_.push_slot::(DiamondGradientPaint::VT_BLEND_MODE, blend_mode, BlendMode::Normal); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> DiamondGradientPaintBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + DiamondGradientPaintBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for DiamondGradientPaint<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("DiamondGradientPaint"); + ds.field("active", &self.active()); + ds.field("transform", &self.transform()); + ds.field("stops", &self.stops()); + ds.field("opacity", &self.opacity()); + ds.field("blend_mode", &self.blend_mode()); + ds.finish() + } +} +pub enum SweepGradientPaintOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct SweepGradientPaint<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for SweepGradientPaint<'a> { + type Inner = SweepGradientPaint<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> SweepGradientPaint<'a> { + pub const VT_ACTIVE: ::flatbuffers::VOffsetT = 4; + pub const VT_TRANSFORM: ::flatbuffers::VOffsetT = 6; + pub const VT_STOPS: ::flatbuffers::VOffsetT = 8; + pub const VT_OPACITY: ::flatbuffers::VOffsetT = 10; + pub const VT_BLEND_MODE: ::flatbuffers::VOffsetT = 12; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + SweepGradientPaint { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args SweepGradientPaintArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = SweepGradientPaintBuilder::new(_fbb); + builder.add_opacity(args.opacity); + if let Some(x) = args.stops { builder.add_stops(x); } + if let Some(x) = args.transform { builder.add_transform(x); } + builder.add_blend_mode(args.blend_mode); + builder.add_active(args.active); + builder.finish() + } + + + #[inline] + pub fn active(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(SweepGradientPaint::VT_ACTIVE, Some(true)).unwrap()} + } + /// transform of the gradient, if empty(unset) canonical is identity + #[inline] + pub fn transform(&self) -> Option<&'a CGTransform2D> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(SweepGradientPaint::VT_TRANSFORM, None)} + } + #[inline] + pub fn stops(&self) -> Option<::flatbuffers::Vector<'a, GradientStop>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, GradientStop>>>(SweepGradientPaint::VT_STOPS, None)} + } + #[inline] + pub fn opacity(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(SweepGradientPaint::VT_OPACITY, Some(1.0)).unwrap()} + } + #[inline] + pub fn blend_mode(&self) -> BlendMode { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(SweepGradientPaint::VT_BLEND_MODE, Some(BlendMode::Normal)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for SweepGradientPaint<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("active", Self::VT_ACTIVE, false)? + .visit_field::("transform", Self::VT_TRANSFORM, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, GradientStop>>>("stops", Self::VT_STOPS, false)? + .visit_field::("opacity", Self::VT_OPACITY, false)? + .visit_field::("blend_mode", Self::VT_BLEND_MODE, false)? + .finish(); + Ok(()) + } +} +pub struct SweepGradientPaintArgs<'a> { + pub active: bool, + pub transform: Option<&'a CGTransform2D>, + pub stops: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, GradientStop>>>, + pub opacity: f32, + pub blend_mode: BlendMode, +} +impl<'a> Default for SweepGradientPaintArgs<'a> { + #[inline] + fn default() -> Self { + SweepGradientPaintArgs { + active: true, + transform: None, + stops: None, + opacity: 1.0, + blend_mode: BlendMode::Normal, + } + } +} + +pub struct SweepGradientPaintBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> SweepGradientPaintBuilder<'a, 'b, A> { + #[inline] + pub fn add_active(&mut self, active: bool) { + self.fbb_.push_slot::(SweepGradientPaint::VT_ACTIVE, active, true); + } + #[inline] + pub fn add_transform(&mut self, transform: &CGTransform2D) { + self.fbb_.push_slot_always::<&CGTransform2D>(SweepGradientPaint::VT_TRANSFORM, transform); + } + #[inline] + pub fn add_stops(&mut self, stops: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , GradientStop>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(SweepGradientPaint::VT_STOPS, stops); + } + #[inline] + pub fn add_opacity(&mut self, opacity: f32) { + self.fbb_.push_slot::(SweepGradientPaint::VT_OPACITY, opacity, 1.0); + } + #[inline] + pub fn add_blend_mode(&mut self, blend_mode: BlendMode) { + self.fbb_.push_slot::(SweepGradientPaint::VT_BLEND_MODE, blend_mode, BlendMode::Normal); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> SweepGradientPaintBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + SweepGradientPaintBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for SweepGradientPaint<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("SweepGradientPaint"); + ds.field("active", &self.active()); + ds.field("transform", &self.transform()); + ds.field("stops", &self.stops()); + ds.field("opacity", &self.opacity()); + ds.field("blend_mode", &self.blend_mode()); + ds.finish() + } +} +pub enum ResourceRefHASHOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `ResourceRef::HASH(String)` +pub struct ResourceRefHASH<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for ResourceRefHASH<'a> { + type Inner = ResourceRefHASH<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> ResourceRefHASH<'a> { + pub const VT_HASH: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + ResourceRefHASH { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args ResourceRefHASHArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = ResourceRefHASHBuilder::new(_fbb); + if let Some(x) = args.hash { builder.add_hash(x); } + builder.finish() + } + + + #[inline] + pub fn hash(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(ResourceRefHASH::VT_HASH, None)} + } +} + +impl ::flatbuffers::Verifiable for ResourceRefHASH<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("hash", Self::VT_HASH, false)? + .finish(); + Ok(()) + } +} +pub struct ResourceRefHASHArgs<'a> { + pub hash: Option<::flatbuffers::WIPOffset<&'a str>>, +} +impl<'a> Default for ResourceRefHASHArgs<'a> { + #[inline] + fn default() -> Self { + ResourceRefHASHArgs { + hash: None, + } + } +} + +pub struct ResourceRefHASHBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> ResourceRefHASHBuilder<'a, 'b, A> { + #[inline] + pub fn add_hash(&mut self, hash: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(ResourceRefHASH::VT_HASH, hash); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> ResourceRefHASHBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + ResourceRefHASHBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for ResourceRefHASH<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("ResourceRefHASH"); + ds.field("hash", &self.hash()); + ds.finish() + } +} +pub enum ResourceRefRIDOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `ResourceRef::RID(String)` +pub struct ResourceRefRID<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for ResourceRefRID<'a> { + type Inner = ResourceRefRID<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> ResourceRefRID<'a> { + pub const VT_RID: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + ResourceRefRID { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args ResourceRefRIDArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = ResourceRefRIDBuilder::new(_fbb); + if let Some(x) = args.rid { builder.add_rid(x); } + builder.finish() + } + + + #[inline] + pub fn rid(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(ResourceRefRID::VT_RID, None)} + } +} + +impl ::flatbuffers::Verifiable for ResourceRefRID<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("rid", Self::VT_RID, false)? + .finish(); + Ok(()) + } +} +pub struct ResourceRefRIDArgs<'a> { + pub rid: Option<::flatbuffers::WIPOffset<&'a str>>, +} +impl<'a> Default for ResourceRefRIDArgs<'a> { + #[inline] + fn default() -> Self { + ResourceRefRIDArgs { + rid: None, + } + } +} + +pub struct ResourceRefRIDBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> ResourceRefRIDBuilder<'a, 'b, A> { + #[inline] + pub fn add_rid(&mut self, rid: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(ResourceRefRID::VT_RID, rid); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> ResourceRefRIDBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + ResourceRefRIDBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for ResourceRefRID<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("ResourceRefRID"); + ds.field("rid", &self.rid()); + ds.finish() + } +} +pub enum ImagePaintFitFitOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `ImagePaintFit::Fit(BoxFit)` +pub struct ImagePaintFitFit<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for ImagePaintFitFit<'a> { + type Inner = ImagePaintFitFit<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> ImagePaintFitFit<'a> { + pub const VT_BOX_FIT: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + ImagePaintFitFit { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args ImagePaintFitFitArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = ImagePaintFitFitBuilder::new(_fbb); + builder.add_box_fit(args.box_fit); + builder.finish() + } + + + #[inline] + pub fn box_fit(&self) -> BoxFit { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ImagePaintFitFit::VT_BOX_FIT, Some(BoxFit::Cover)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for ImagePaintFitFit<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("box_fit", Self::VT_BOX_FIT, false)? + .finish(); + Ok(()) + } +} +pub struct ImagePaintFitFitArgs { + pub box_fit: BoxFit, +} +impl<'a> Default for ImagePaintFitFitArgs { + #[inline] + fn default() -> Self { + ImagePaintFitFitArgs { + box_fit: BoxFit::Cover, + } + } +} + +pub struct ImagePaintFitFitBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> ImagePaintFitFitBuilder<'a, 'b, A> { + #[inline] + pub fn add_box_fit(&mut self, box_fit: BoxFit) { + self.fbb_.push_slot::(ImagePaintFitFit::VT_BOX_FIT, box_fit, BoxFit::Cover); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> ImagePaintFitFitBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + ImagePaintFitFitBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for ImagePaintFitFit<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("ImagePaintFitFit"); + ds.field("box_fit", &self.box_fit()); + ds.finish() + } +} +pub enum ImagePaintFitTransformOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `ImagePaintFit::Transform(AffineTransform)` +pub struct ImagePaintFitTransform<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for ImagePaintFitTransform<'a> { + type Inner = ImagePaintFitTransform<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> ImagePaintFitTransform<'a> { + pub const VT_TRANSFORM: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + ImagePaintFitTransform { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args ImagePaintFitTransformArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = ImagePaintFitTransformBuilder::new(_fbb); + if let Some(x) = args.transform { builder.add_transform(x); } + builder.finish() + } + + + #[inline] + pub fn transform(&self) -> Option<&'a CGTransform2D> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ImagePaintFitTransform::VT_TRANSFORM, None)} + } +} + +impl ::flatbuffers::Verifiable for ImagePaintFitTransform<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("transform", Self::VT_TRANSFORM, false)? + .finish(); + Ok(()) + } +} +pub struct ImagePaintFitTransformArgs<'a> { + pub transform: Option<&'a CGTransform2D>, +} +impl<'a> Default for ImagePaintFitTransformArgs<'a> { + #[inline] + fn default() -> Self { + ImagePaintFitTransformArgs { + transform: None, + } + } +} + +pub struct ImagePaintFitTransformBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> ImagePaintFitTransformBuilder<'a, 'b, A> { + #[inline] + pub fn add_transform(&mut self, transform: &CGTransform2D) { + self.fbb_.push_slot_always::<&CGTransform2D>(ImagePaintFitTransform::VT_TRANSFORM, transform); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> ImagePaintFitTransformBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + ImagePaintFitTransformBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for ImagePaintFitTransform<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("ImagePaintFitTransform"); + ds.field("transform", &self.transform()); + ds.finish() + } +} +pub enum ImagePaintFitTileOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `ImagePaintFit::Tile(ImageTile)` +pub struct ImagePaintFitTile<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for ImagePaintFitTile<'a> { + type Inner = ImagePaintFitTile<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> ImagePaintFitTile<'a> { + pub const VT_TILE: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + ImagePaintFitTile { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args ImagePaintFitTileArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = ImagePaintFitTileBuilder::new(_fbb); + if let Some(x) = args.tile { builder.add_tile(x); } + builder.finish() + } + + + #[inline] + pub fn tile(&self) -> Option<&'a ImageTile> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ImagePaintFitTile::VT_TILE, None)} + } +} + +impl ::flatbuffers::Verifiable for ImagePaintFitTile<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("tile", Self::VT_TILE, false)? + .finish(); + Ok(()) + } +} +pub struct ImagePaintFitTileArgs<'a> { + pub tile: Option<&'a ImageTile>, +} +impl<'a> Default for ImagePaintFitTileArgs<'a> { + #[inline] + fn default() -> Self { + ImagePaintFitTileArgs { + tile: None, + } + } +} + +pub struct ImagePaintFitTileBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> ImagePaintFitTileBuilder<'a, 'b, A> { + #[inline] + pub fn add_tile(&mut self, tile: &ImageTile) { + self.fbb_.push_slot_always::<&ImageTile>(ImagePaintFitTile::VT_TILE, tile); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> ImagePaintFitTileBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + ImagePaintFitTileBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for ImagePaintFitTile<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("ImagePaintFitTile"); + ds.field("tile", &self.tile()); + ds.finish() + } +} +pub enum ImagePaintOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `ImagePaint` +pub struct ImagePaint<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for ImagePaint<'a> { + type Inner = ImagePaint<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> ImagePaint<'a> { + pub const VT_ACTIVE: ::flatbuffers::VOffsetT = 4; + pub const VT_IMAGE_TYPE: ::flatbuffers::VOffsetT = 6; + pub const VT_IMAGE: ::flatbuffers::VOffsetT = 8; + pub const VT_QUARTER_TURNS: ::flatbuffers::VOffsetT = 10; + pub const VT_ALIGNEMENT: ::flatbuffers::VOffsetT = 12; + pub const VT_FIT_TYPE: ::flatbuffers::VOffsetT = 14; + pub const VT_FIT: ::flatbuffers::VOffsetT = 16; + pub const VT_OPACITY: ::flatbuffers::VOffsetT = 18; + pub const VT_BLEND_MODE: ::flatbuffers::VOffsetT = 20; + pub const VT_FILTERS: ::flatbuffers::VOffsetT = 22; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + ImagePaint { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args ImagePaintArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = ImagePaintBuilder::new(_fbb); + if let Some(x) = args.filters { builder.add_filters(x); } + builder.add_opacity(args.opacity); + if let Some(x) = args.fit { builder.add_fit(x); } + if let Some(x) = args.alignement { builder.add_alignement(x); } + if let Some(x) = args.image { builder.add_image(x); } + builder.add_blend_mode(args.blend_mode); + builder.add_fit_type(args.fit_type); + builder.add_quarter_turns(args.quarter_turns); + builder.add_image_type(args.image_type); + builder.add_active(args.active); + builder.finish() + } + + + #[inline] + pub fn active(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ImagePaint::VT_ACTIVE, Some(true)).unwrap()} + } + #[inline] + pub fn image_type(&self) -> ResourceRef { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ImagePaint::VT_IMAGE_TYPE, Some(ResourceRef::NONE)).unwrap()} + } + #[inline] + pub fn image(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>(ImagePaint::VT_IMAGE, None)} + } + #[inline] + pub fn quarter_turns(&self) -> u8 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ImagePaint::VT_QUARTER_TURNS, Some(0)).unwrap()} + } + /// NOTE: Rust field name is `alignement` (typo preserved for 1:1) + #[inline] + pub fn alignement(&self) -> Option<&'a Alignment> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ImagePaint::VT_ALIGNEMENT, None)} + } + #[inline] + pub fn fit_type(&self) -> ImagePaintFit { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ImagePaint::VT_FIT_TYPE, Some(ImagePaintFit::NONE)).unwrap()} + } + #[inline] + pub fn fit(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>(ImagePaint::VT_FIT, None)} + } + #[inline] + pub fn opacity(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ImagePaint::VT_OPACITY, Some(1.0)).unwrap()} + } + #[inline] + pub fn blend_mode(&self) -> BlendMode { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ImagePaint::VT_BLEND_MODE, Some(BlendMode::Normal)).unwrap()} + } + #[inline] + pub fn filters(&self) -> Option<&'a ImageFilters> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ImagePaint::VT_FILTERS, None)} + } + #[inline] + #[allow(non_snake_case)] + pub fn image_as_resource_ref_hash(&self) -> Option> { + if self.image_type() == ResourceRef::ResourceRefHASH { + self.image().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { ResourceRefHASH::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn image_as_resource_ref_rid(&self) -> Option> { + if self.image_type() == ResourceRef::ResourceRefRID { + self.image().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { ResourceRefRID::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn fit_as_image_paint_fit_fit(&self) -> Option> { + if self.fit_type() == ImagePaintFit::ImagePaintFitFit { + self.fit().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { ImagePaintFitFit::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn fit_as_image_paint_fit_transform(&self) -> Option> { + if self.fit_type() == ImagePaintFit::ImagePaintFitTransform { + self.fit().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { ImagePaintFitTransform::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn fit_as_image_paint_fit_tile(&self) -> Option> { + if self.fit_type() == ImagePaintFit::ImagePaintFitTile { + self.fit().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { ImagePaintFitTile::init_from_table(t) } + }) + } else { + None + } + } + +} + +impl ::flatbuffers::Verifiable for ImagePaint<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("active", Self::VT_ACTIVE, false)? + .visit_union::("image_type", Self::VT_IMAGE_TYPE, "image", Self::VT_IMAGE, false, |key, v, pos| { + match key { + ResourceRef::ResourceRefHASH => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("ResourceRef::ResourceRefHASH", pos), + ResourceRef::ResourceRefRID => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("ResourceRef::ResourceRefRID", pos), + _ => Ok(()), + } + })? + .visit_field::("quarter_turns", Self::VT_QUARTER_TURNS, false)? + .visit_field::("alignement", Self::VT_ALIGNEMENT, false)? + .visit_union::("fit_type", Self::VT_FIT_TYPE, "fit", Self::VT_FIT, false, |key, v, pos| { + match key { + ImagePaintFit::ImagePaintFitFit => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("ImagePaintFit::ImagePaintFitFit", pos), + ImagePaintFit::ImagePaintFitTransform => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("ImagePaintFit::ImagePaintFitTransform", pos), + ImagePaintFit::ImagePaintFitTile => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("ImagePaintFit::ImagePaintFitTile", pos), + _ => Ok(()), + } + })? + .visit_field::("opacity", Self::VT_OPACITY, false)? + .visit_field::("blend_mode", Self::VT_BLEND_MODE, false)? + .visit_field::("filters", Self::VT_FILTERS, false)? + .finish(); + Ok(()) + } +} +pub struct ImagePaintArgs<'a> { + pub active: bool, + pub image_type: ResourceRef, + pub image: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, + pub quarter_turns: u8, + pub alignement: Option<&'a Alignment>, + pub fit_type: ImagePaintFit, + pub fit: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, + pub opacity: f32, + pub blend_mode: BlendMode, + pub filters: Option<&'a ImageFilters>, +} +impl<'a> Default for ImagePaintArgs<'a> { + #[inline] + fn default() -> Self { + ImagePaintArgs { + active: true, + image_type: ResourceRef::NONE, + image: None, + quarter_turns: 0, + alignement: None, + fit_type: ImagePaintFit::NONE, + fit: None, + opacity: 1.0, + blend_mode: BlendMode::Normal, + filters: None, + } + } +} + +pub struct ImagePaintBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> ImagePaintBuilder<'a, 'b, A> { + #[inline] + pub fn add_active(&mut self, active: bool) { + self.fbb_.push_slot::(ImagePaint::VT_ACTIVE, active, true); + } + #[inline] + pub fn add_image_type(&mut self, image_type: ResourceRef) { + self.fbb_.push_slot::(ImagePaint::VT_IMAGE_TYPE, image_type, ResourceRef::NONE); + } + #[inline] + pub fn add_image(&mut self, image: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(ImagePaint::VT_IMAGE, image); + } + #[inline] + pub fn add_quarter_turns(&mut self, quarter_turns: u8) { + self.fbb_.push_slot::(ImagePaint::VT_QUARTER_TURNS, quarter_turns, 0); + } + #[inline] + pub fn add_alignement(&mut self, alignement: &Alignment) { + self.fbb_.push_slot_always::<&Alignment>(ImagePaint::VT_ALIGNEMENT, alignement); + } + #[inline] + pub fn add_fit_type(&mut self, fit_type: ImagePaintFit) { + self.fbb_.push_slot::(ImagePaint::VT_FIT_TYPE, fit_type, ImagePaintFit::NONE); + } + #[inline] + pub fn add_fit(&mut self, fit: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(ImagePaint::VT_FIT, fit); + } + #[inline] + pub fn add_opacity(&mut self, opacity: f32) { + self.fbb_.push_slot::(ImagePaint::VT_OPACITY, opacity, 1.0); + } + #[inline] + pub fn add_blend_mode(&mut self, blend_mode: BlendMode) { + self.fbb_.push_slot::(ImagePaint::VT_BLEND_MODE, blend_mode, BlendMode::Normal); + } + #[inline] + pub fn add_filters(&mut self, filters: &ImageFilters) { + self.fbb_.push_slot_always::<&ImageFilters>(ImagePaint::VT_FILTERS, filters); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> ImagePaintBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + ImagePaintBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for ImagePaint<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("ImagePaint"); + ds.field("active", &self.active()); + ds.field("image_type", &self.image_type()); + match self.image_type() { + ResourceRef::ResourceRefHASH => { + if let Some(x) = self.image_as_resource_ref_hash() { + ds.field("image", &x) + } else { + ds.field("image", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + ResourceRef::ResourceRefRID => { + if let Some(x) = self.image_as_resource_ref_rid() { + ds.field("image", &x) + } else { + ds.field("image", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + _ => { + let x: Option<()> = None; + ds.field("image", &x) + }, + }; + ds.field("quarter_turns", &self.quarter_turns()); + ds.field("alignement", &self.alignement()); + ds.field("fit_type", &self.fit_type()); + match self.fit_type() { + ImagePaintFit::ImagePaintFitFit => { + if let Some(x) = self.fit_as_image_paint_fit_fit() { + ds.field("fit", &x) + } else { + ds.field("fit", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + ImagePaintFit::ImagePaintFitTransform => { + if let Some(x) = self.fit_as_image_paint_fit_transform() { + ds.field("fit", &x) + } else { + ds.field("fit", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + ImagePaintFit::ImagePaintFitTile => { + if let Some(x) = self.fit_as_image_paint_fit_tile() { + ds.field("fit", &x) + } else { + ds.field("fit", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + _ => { + let x: Option<()> = None; + ds.field("fit", &x) + }, + }; + ds.field("opacity", &self.opacity()); + ds.field("blend_mode", &self.blend_mode()); + ds.field("filters", &self.filters()); + ds.finish() + } +} +pub enum PaintStackItemOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct PaintStackItem<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for PaintStackItem<'a> { + type Inner = PaintStackItem<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> PaintStackItem<'a> { + pub const VT_PAINT_TYPE: ::flatbuffers::VOffsetT = 4; + pub const VT_PAINT: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + PaintStackItem { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args PaintStackItemArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = PaintStackItemBuilder::new(_fbb); + if let Some(x) = args.paint { builder.add_paint(x); } + builder.add_paint_type(args.paint_type); + builder.finish() + } + + + #[inline] + pub fn paint_type(&self) -> Paint { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(PaintStackItem::VT_PAINT_TYPE, Some(Paint::NONE)).unwrap()} + } + #[inline] + pub fn paint(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>(PaintStackItem::VT_PAINT, None)} + } + #[inline] + #[allow(non_snake_case)] + pub fn paint_as_solid_paint(&self) -> Option> { + if self.paint_type() == Paint::SolidPaint { + self.paint().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { SolidPaint::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn paint_as_linear_gradient_paint(&self) -> Option> { + if self.paint_type() == Paint::LinearGradientPaint { + self.paint().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { LinearGradientPaint::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn paint_as_radial_gradient_paint(&self) -> Option> { + if self.paint_type() == Paint::RadialGradientPaint { + self.paint().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { RadialGradientPaint::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn paint_as_sweep_gradient_paint(&self) -> Option> { + if self.paint_type() == Paint::SweepGradientPaint { + self.paint().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { SweepGradientPaint::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn paint_as_diamond_gradient_paint(&self) -> Option> { + if self.paint_type() == Paint::DiamondGradientPaint { + self.paint().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { DiamondGradientPaint::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn paint_as_image_paint(&self) -> Option> { + if self.paint_type() == Paint::ImagePaint { + self.paint().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { ImagePaint::init_from_table(t) } + }) + } else { + None + } + } + +} + +impl ::flatbuffers::Verifiable for PaintStackItem<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_union::("paint_type", Self::VT_PAINT_TYPE, "paint", Self::VT_PAINT, false, |key, v, pos| { + match key { + Paint::SolidPaint => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Paint::SolidPaint", pos), + Paint::LinearGradientPaint => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Paint::LinearGradientPaint", pos), + Paint::RadialGradientPaint => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Paint::RadialGradientPaint", pos), + Paint::SweepGradientPaint => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Paint::SweepGradientPaint", pos), + Paint::DiamondGradientPaint => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Paint::DiamondGradientPaint", pos), + Paint::ImagePaint => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Paint::ImagePaint", pos), + _ => Ok(()), + } + })? + .finish(); + Ok(()) + } +} +pub struct PaintStackItemArgs { + pub paint_type: Paint, + pub paint: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, +} +impl<'a> Default for PaintStackItemArgs { + #[inline] + fn default() -> Self { + PaintStackItemArgs { + paint_type: Paint::NONE, + paint: None, + } + } +} + +pub struct PaintStackItemBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> PaintStackItemBuilder<'a, 'b, A> { + #[inline] + pub fn add_paint_type(&mut self, paint_type: Paint) { + self.fbb_.push_slot::(PaintStackItem::VT_PAINT_TYPE, paint_type, Paint::NONE); + } + #[inline] + pub fn add_paint(&mut self, paint: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(PaintStackItem::VT_PAINT, paint); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> PaintStackItemBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + PaintStackItemBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for PaintStackItem<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("PaintStackItem"); + ds.field("paint_type", &self.paint_type()); + match self.paint_type() { + Paint::SolidPaint => { + if let Some(x) = self.paint_as_solid_paint() { + ds.field("paint", &x) + } else { + ds.field("paint", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Paint::LinearGradientPaint => { + if let Some(x) = self.paint_as_linear_gradient_paint() { + ds.field("paint", &x) + } else { + ds.field("paint", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Paint::RadialGradientPaint => { + if let Some(x) = self.paint_as_radial_gradient_paint() { + ds.field("paint", &x) + } else { + ds.field("paint", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Paint::SweepGradientPaint => { + if let Some(x) = self.paint_as_sweep_gradient_paint() { + ds.field("paint", &x) + } else { + ds.field("paint", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Paint::DiamondGradientPaint => { + if let Some(x) = self.paint_as_diamond_gradient_paint() { + ds.field("paint", &x) + } else { + ds.field("paint", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Paint::ImagePaint => { + if let Some(x) = self.paint_as_image_paint() { + ds.field("paint", &x) + } else { + ds.field("paint", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + _ => { + let x: Option<()> = None; + ds.field("paint", &x) + }, + }; + ds.finish() + } +} +pub enum Guide2DOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct Guide2D<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for Guide2D<'a> { + type Inner = Guide2D<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> Guide2D<'a> { + pub const VT_AXIS: ::flatbuffers::VOffsetT = 4; + pub const VT_GUIDE_OFFSET: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + Guide2D { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args Guide2DArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = Guide2DBuilder::new(_fbb); + builder.add_guide_offset(args.guide_offset); + builder.add_axis(args.axis); + builder.finish() + } + + + #[inline] + pub fn axis(&self) -> Axis { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Guide2D::VT_AXIS, Some(Axis::Horizontal)).unwrap()} + } + #[inline] + pub fn guide_offset(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Guide2D::VT_GUIDE_OFFSET, Some(0.0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for Guide2D<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("axis", Self::VT_AXIS, false)? + .visit_field::("guide_offset", Self::VT_GUIDE_OFFSET, false)? + .finish(); + Ok(()) + } +} +pub struct Guide2DArgs { + pub axis: Axis, + pub guide_offset: f32, +} +impl<'a> Default for Guide2DArgs { + #[inline] + fn default() -> Self { + Guide2DArgs { + axis: Axis::Horizontal, + guide_offset: 0.0, + } + } +} + +pub struct Guide2DBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> Guide2DBuilder<'a, 'b, A> { + #[inline] + pub fn add_axis(&mut self, axis: Axis) { + self.fbb_.push_slot::(Guide2D::VT_AXIS, axis, Axis::Horizontal); + } + #[inline] + pub fn add_guide_offset(&mut self, guide_offset: f32) { + self.fbb_.push_slot::(Guide2D::VT_GUIDE_OFFSET, guide_offset, 0.0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> Guide2DBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + Guide2DBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for Guide2D<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("Guide2D"); + ds.field("axis", &self.axis()); + ds.field("guide_offset", &self.guide_offset()); + ds.finish() + } +} +pub enum EdgePointPosition2DOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct EdgePointPosition2D<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for EdgePointPosition2D<'a> { + type Inner = EdgePointPosition2D<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> EdgePointPosition2D<'a> { + pub const VT_X: ::flatbuffers::VOffsetT = 4; + pub const VT_Y: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + EdgePointPosition2D { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args EdgePointPosition2DArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = EdgePointPosition2DBuilder::new(_fbb); + builder.add_y(args.y); + builder.add_x(args.x); + builder.finish() + } + + + #[inline] + pub fn x(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(EdgePointPosition2D::VT_X, Some(0.0)).unwrap()} + } + #[inline] + pub fn y(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(EdgePointPosition2D::VT_Y, Some(0.0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for EdgePointPosition2D<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("x", Self::VT_X, false)? + .visit_field::("y", Self::VT_Y, false)? + .finish(); + Ok(()) + } +} +pub struct EdgePointPosition2DArgs { + pub x: f32, + pub y: f32, +} +impl<'a> Default for EdgePointPosition2DArgs { + #[inline] + fn default() -> Self { + EdgePointPosition2DArgs { + x: 0.0, + y: 0.0, + } + } +} + +pub struct EdgePointPosition2DBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> EdgePointPosition2DBuilder<'a, 'b, A> { + #[inline] + pub fn add_x(&mut self, x: f32) { + self.fbb_.push_slot::(EdgePointPosition2D::VT_X, x, 0.0); + } + #[inline] + pub fn add_y(&mut self, y: f32) { + self.fbb_.push_slot::(EdgePointPosition2D::VT_Y, y, 0.0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> EdgePointPosition2DBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + EdgePointPosition2DBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for EdgePointPosition2D<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("EdgePointPosition2D"); + ds.field("x", &self.x()); + ds.field("y", &self.y()); + ds.finish() + } +} +pub enum EdgePointNodeAnchorOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct EdgePointNodeAnchor<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for EdgePointNodeAnchor<'a> { + type Inner = EdgePointNodeAnchor<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> EdgePointNodeAnchor<'a> { + pub const VT_TARGET: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + EdgePointNodeAnchor { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args EdgePointNodeAnchorArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = EdgePointNodeAnchorBuilder::new(_fbb); + if let Some(x) = args.target { builder.add_target(x); } + builder.finish() + } + + + #[inline] + pub fn target(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(EdgePointNodeAnchor::VT_TARGET, None)} + } +} + +impl ::flatbuffers::Verifiable for EdgePointNodeAnchor<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("target", Self::VT_TARGET, false)? + .finish(); + Ok(()) + } +} +pub struct EdgePointNodeAnchorArgs<'a> { + pub target: Option<::flatbuffers::WIPOffset>>, +} +impl<'a> Default for EdgePointNodeAnchorArgs<'a> { + #[inline] + fn default() -> Self { + EdgePointNodeAnchorArgs { + target: None, + } + } +} + +pub struct EdgePointNodeAnchorBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> EdgePointNodeAnchorBuilder<'a, 'b, A> { + #[inline] + pub fn add_target(&mut self, target: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(EdgePointNodeAnchor::VT_TARGET, target); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> EdgePointNodeAnchorBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + EdgePointNodeAnchorBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for EdgePointNodeAnchor<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("EdgePointNodeAnchor"); + ds.field("target", &self.target()); + ds.finish() + } +} +pub enum Edge2DOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct Edge2D<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for Edge2D<'a> { + type Inner = Edge2D<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> Edge2D<'a> { + pub const VT_ID: ::flatbuffers::VOffsetT = 4; + pub const VT_A_TYPE: ::flatbuffers::VOffsetT = 6; + pub const VT_A: ::flatbuffers::VOffsetT = 8; + pub const VT_B_TYPE: ::flatbuffers::VOffsetT = 10; + pub const VT_B: ::flatbuffers::VOffsetT = 12; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + Edge2D { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args Edge2DArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = Edge2DBuilder::new(_fbb); + if let Some(x) = args.b { builder.add_b(x); } + if let Some(x) = args.a { builder.add_a(x); } + if let Some(x) = args.id { builder.add_id(x); } + builder.add_b_type(args.b_type); + builder.add_a_type(args.a_type); + builder.finish() + } + + + #[inline] + pub fn id(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(Edge2D::VT_ID, None)} + } + #[inline] + pub fn a_type(&self) -> EdgePoint { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Edge2D::VT_A_TYPE, Some(EdgePoint::NONE)).unwrap()} + } + #[inline] + pub fn a(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>(Edge2D::VT_A, None)} + } + #[inline] + pub fn b_type(&self) -> EdgePoint { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Edge2D::VT_B_TYPE, Some(EdgePoint::NONE)).unwrap()} + } + #[inline] + pub fn b(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>(Edge2D::VT_B, None)} + } + #[inline] + #[allow(non_snake_case)] + pub fn a_as_edge_point_position_2_d(&self) -> Option> { + if self.a_type() == EdgePoint::EdgePointPosition2D { + self.a().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { EdgePointPosition2D::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn a_as_edge_point_node_anchor(&self) -> Option> { + if self.a_type() == EdgePoint::EdgePointNodeAnchor { + self.a().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { EdgePointNodeAnchor::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn b_as_edge_point_position_2_d(&self) -> Option> { + if self.b_type() == EdgePoint::EdgePointPosition2D { + self.b().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { EdgePointPosition2D::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn b_as_edge_point_node_anchor(&self) -> Option> { + if self.b_type() == EdgePoint::EdgePointNodeAnchor { + self.b().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { EdgePointNodeAnchor::init_from_table(t) } + }) + } else { + None + } + } + +} + +impl ::flatbuffers::Verifiable for Edge2D<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("id", Self::VT_ID, false)? + .visit_union::("a_type", Self::VT_A_TYPE, "a", Self::VT_A, false, |key, v, pos| { + match key { + EdgePoint::EdgePointPosition2D => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("EdgePoint::EdgePointPosition2D", pos), + EdgePoint::EdgePointNodeAnchor => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("EdgePoint::EdgePointNodeAnchor", pos), + _ => Ok(()), + } + })? + .visit_union::("b_type", Self::VT_B_TYPE, "b", Self::VT_B, false, |key, v, pos| { + match key { + EdgePoint::EdgePointPosition2D => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("EdgePoint::EdgePointPosition2D", pos), + EdgePoint::EdgePointNodeAnchor => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("EdgePoint::EdgePointNodeAnchor", pos), + _ => Ok(()), + } + })? + .finish(); + Ok(()) + } +} +pub struct Edge2DArgs<'a> { + pub id: Option<::flatbuffers::WIPOffset<&'a str>>, + pub a_type: EdgePoint, + pub a: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, + pub b_type: EdgePoint, + pub b: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, +} +impl<'a> Default for Edge2DArgs<'a> { + #[inline] + fn default() -> Self { + Edge2DArgs { + id: None, + a_type: EdgePoint::NONE, + a: None, + b_type: EdgePoint::NONE, + b: None, + } + } +} + +pub struct Edge2DBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> Edge2DBuilder<'a, 'b, A> { + #[inline] + pub fn add_id(&mut self, id: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Edge2D::VT_ID, id); + } + #[inline] + pub fn add_a_type(&mut self, a_type: EdgePoint) { + self.fbb_.push_slot::(Edge2D::VT_A_TYPE, a_type, EdgePoint::NONE); + } + #[inline] + pub fn add_a(&mut self, a: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Edge2D::VT_A, a); + } + #[inline] + pub fn add_b_type(&mut self, b_type: EdgePoint) { + self.fbb_.push_slot::(Edge2D::VT_B_TYPE, b_type, EdgePoint::NONE); + } + #[inline] + pub fn add_b(&mut self, b: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(Edge2D::VT_B, b); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> Edge2DBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + Edge2DBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for Edge2D<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("Edge2D"); + ds.field("id", &self.id()); + ds.field("a_type", &self.a_type()); + match self.a_type() { + EdgePoint::EdgePointPosition2D => { + if let Some(x) = self.a_as_edge_point_position_2_d() { + ds.field("a", &x) + } else { + ds.field("a", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + EdgePoint::EdgePointNodeAnchor => { + if let Some(x) = self.a_as_edge_point_node_anchor() { + ds.field("a", &x) + } else { + ds.field("a", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + _ => { + let x: Option<()> = None; + ds.field("a", &x) + }, + }; + ds.field("b_type", &self.b_type()); + match self.b_type() { + EdgePoint::EdgePointPosition2D => { + if let Some(x) = self.b_as_edge_point_position_2_d() { + ds.field("b", &x) + } else { + ds.field("b", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + EdgePoint::EdgePointNodeAnchor => { + if let Some(x) = self.b_as_edge_point_node_anchor() { + ds.field("b", &x) + } else { + ds.field("b", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + _ => { + let x: Option<()> = None; + ds.field("b", &x) + }, + }; + ds.finish() + } +} +pub enum VectorNetworkLoopOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `VectorNetworkLoop(pub Vec)` +/// +/// A closed contour defined by indices into `segments`. +pub struct VectorNetworkLoop<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for VectorNetworkLoop<'a> { + type Inner = VectorNetworkLoop<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> VectorNetworkLoop<'a> { + pub const VT_LOOP_SEGMENT_INDICES: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + VectorNetworkLoop { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args VectorNetworkLoopArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = VectorNetworkLoopBuilder::new(_fbb); + if let Some(x) = args.loop_segment_indices { builder.add_loop_segment_indices(x); } + builder.finish() + } + + + #[inline] + pub fn loop_segment_indices(&self) -> Option<::flatbuffers::Vector<'a, u32>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, u32>>>(VectorNetworkLoop::VT_LOOP_SEGMENT_INDICES, None)} + } +} + +impl ::flatbuffers::Verifiable for VectorNetworkLoop<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, u32>>>("loop_segment_indices", Self::VT_LOOP_SEGMENT_INDICES, false)? + .finish(); + Ok(()) + } +} +pub struct VectorNetworkLoopArgs<'a> { + pub loop_segment_indices: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, u32>>>, +} +impl<'a> Default for VectorNetworkLoopArgs<'a> { + #[inline] + fn default() -> Self { + VectorNetworkLoopArgs { + loop_segment_indices: None, + } + } +} + +pub struct VectorNetworkLoopBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> VectorNetworkLoopBuilder<'a, 'b, A> { + #[inline] + pub fn add_loop_segment_indices(&mut self, loop_segment_indices: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , u32>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(VectorNetworkLoop::VT_LOOP_SEGMENT_INDICES, loop_segment_indices); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> VectorNetworkLoopBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + VectorNetworkLoopBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for VectorNetworkLoop<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("VectorNetworkLoop"); + ds.field("loop_segment_indices", &self.loop_segment_indices()); + ds.finish() + } +} +pub enum VectorNetworkRegionOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `VectorNetworkRegion { loops, fill_rule, fills }` +/// +/// Archive model uses `region_fill_paints` (empty = no fill) instead of Option wrappers. +pub struct VectorNetworkRegion<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for VectorNetworkRegion<'a> { + type Inner = VectorNetworkRegion<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> VectorNetworkRegion<'a> { + pub const VT_REGION_LOOPS: ::flatbuffers::VOffsetT = 4; + pub const VT_REGION_FILL_RULE: ::flatbuffers::VOffsetT = 6; + pub const VT_REGION_FILL_PAINTS: ::flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + VectorNetworkRegion { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args VectorNetworkRegionArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = VectorNetworkRegionBuilder::new(_fbb); + if let Some(x) = args.region_fill_paints { builder.add_region_fill_paints(x); } + if let Some(x) = args.region_loops { builder.add_region_loops(x); } + builder.add_region_fill_rule(args.region_fill_rule); + builder.finish() + } + + + #[inline] + pub fn region_loops(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(VectorNetworkRegion::VT_REGION_LOOPS, None)} + } + #[inline] + pub fn region_fill_rule(&self) -> FillRule { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(VectorNetworkRegion::VT_REGION_FILL_RULE, Some(FillRule::NonZero)).unwrap()} + } + #[inline] + pub fn region_fill_paints(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(VectorNetworkRegion::VT_REGION_FILL_PAINTS, None)} + } +} + +impl ::flatbuffers::Verifiable for VectorNetworkRegion<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("region_loops", Self::VT_REGION_LOOPS, false)? + .visit_field::("region_fill_rule", Self::VT_REGION_FILL_RULE, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("region_fill_paints", Self::VT_REGION_FILL_PAINTS, false)? + .finish(); + Ok(()) + } +} +pub struct VectorNetworkRegionArgs<'a> { + pub region_loops: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub region_fill_rule: FillRule, + pub region_fill_paints: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, +} +impl<'a> Default for VectorNetworkRegionArgs<'a> { + #[inline] + fn default() -> Self { + VectorNetworkRegionArgs { + region_loops: None, + region_fill_rule: FillRule::NonZero, + region_fill_paints: None, + } + } +} + +pub struct VectorNetworkRegionBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> VectorNetworkRegionBuilder<'a, 'b, A> { + #[inline] + pub fn add_region_loops(&mut self, region_loops: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(VectorNetworkRegion::VT_REGION_LOOPS, region_loops); + } + #[inline] + pub fn add_region_fill_rule(&mut self, region_fill_rule: FillRule) { + self.fbb_.push_slot::(VectorNetworkRegion::VT_REGION_FILL_RULE, region_fill_rule, FillRule::NonZero); + } + #[inline] + pub fn add_region_fill_paints(&mut self, region_fill_paints: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(VectorNetworkRegion::VT_REGION_FILL_PAINTS, region_fill_paints); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> VectorNetworkRegionBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + VectorNetworkRegionBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for VectorNetworkRegion<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("VectorNetworkRegion"); + ds.field("region_loops", &self.region_loops()); + ds.field("region_fill_rule", &self.region_fill_rule()); + ds.field("region_fill_paints", &self.region_fill_paints()); + ds.finish() + } +} +pub enum VectorNetworkDataOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `VectorNetwork { vertices, segments, regions }` +pub struct VectorNetworkData<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for VectorNetworkData<'a> { + type Inner = VectorNetworkData<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> VectorNetworkData<'a> { + pub const VT_VERTICES: ::flatbuffers::VOffsetT = 4; + pub const VT_SEGMENTS: ::flatbuffers::VOffsetT = 6; + pub const VT_REGIONS: ::flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + VectorNetworkData { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args VectorNetworkDataArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = VectorNetworkDataBuilder::new(_fbb); + if let Some(x) = args.regions { builder.add_regions(x); } + if let Some(x) = args.segments { builder.add_segments(x); } + if let Some(x) = args.vertices { builder.add_vertices(x); } + builder.finish() + } + + + #[inline] + pub fn vertices(&self) -> Option<::flatbuffers::Vector<'a, CGPoint>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, CGPoint>>>(VectorNetworkData::VT_VERTICES, None)} + } + #[inline] + pub fn segments(&self) -> Option<::flatbuffers::Vector<'a, VectorNetworkSegment>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, VectorNetworkSegment>>>(VectorNetworkData::VT_SEGMENTS, None)} + } + #[inline] + pub fn regions(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(VectorNetworkData::VT_REGIONS, None)} + } +} + +impl ::flatbuffers::Verifiable for VectorNetworkData<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, CGPoint>>>("vertices", Self::VT_VERTICES, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, VectorNetworkSegment>>>("segments", Self::VT_SEGMENTS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("regions", Self::VT_REGIONS, false)? + .finish(); + Ok(()) + } +} +pub struct VectorNetworkDataArgs<'a> { + pub vertices: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, CGPoint>>>, + pub segments: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, VectorNetworkSegment>>>, + pub regions: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, +} +impl<'a> Default for VectorNetworkDataArgs<'a> { + #[inline] + fn default() -> Self { + VectorNetworkDataArgs { + vertices: None, + segments: None, + regions: None, + } + } +} + +pub struct VectorNetworkDataBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> VectorNetworkDataBuilder<'a, 'b, A> { + #[inline] + pub fn add_vertices(&mut self, vertices: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , CGPoint>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(VectorNetworkData::VT_VERTICES, vertices); + } + #[inline] + pub fn add_segments(&mut self, segments: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , VectorNetworkSegment>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(VectorNetworkData::VT_SEGMENTS, segments); + } + #[inline] + pub fn add_regions(&mut self, regions: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(VectorNetworkData::VT_REGIONS, regions); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> VectorNetworkDataBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + VectorNetworkDataBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for VectorNetworkData<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("VectorNetworkData"); + ds.field("vertices", &self.vertices()); + ds.field("segments", &self.segments()); + ds.field("regions", &self.regions()); + ds.finish() + } +} +pub enum FeGaussianBlurOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `FeGaussianBlur { radius: f32 }` +pub struct FeGaussianBlur<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for FeGaussianBlur<'a> { + type Inner = FeGaussianBlur<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> FeGaussianBlur<'a> { + pub const VT_RADIUS: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + FeGaussianBlur { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args FeGaussianBlurArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = FeGaussianBlurBuilder::new(_fbb); + builder.add_radius(args.radius); + builder.finish() + } + + + #[inline] + pub fn radius(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeGaussianBlur::VT_RADIUS, Some(0.0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for FeGaussianBlur<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("radius", Self::VT_RADIUS, false)? + .finish(); + Ok(()) + } +} +pub struct FeGaussianBlurArgs { + pub radius: f32, +} +impl<'a> Default for FeGaussianBlurArgs { + #[inline] + fn default() -> Self { + FeGaussianBlurArgs { + radius: 0.0, + } + } +} + +pub struct FeGaussianBlurBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> FeGaussianBlurBuilder<'a, 'b, A> { + #[inline] + pub fn add_radius(&mut self, radius: f32) { + self.fbb_.push_slot::(FeGaussianBlur::VT_RADIUS, radius, 0.0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> FeGaussianBlurBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + FeGaussianBlurBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for FeGaussianBlur<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("FeGaussianBlur"); + ds.field("radius", &self.radius()); + ds.finish() + } +} +pub enum FeProgressiveBlurOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `FeProgressiveBlur { start: Alignment, end: Alignment, radius, radius2 }` +pub struct FeProgressiveBlur<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for FeProgressiveBlur<'a> { + type Inner = FeProgressiveBlur<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> FeProgressiveBlur<'a> { + pub const VT_START: ::flatbuffers::VOffsetT = 4; + pub const VT_END: ::flatbuffers::VOffsetT = 6; + pub const VT_RADIUS: ::flatbuffers::VOffsetT = 8; + pub const VT_RADIUS2: ::flatbuffers::VOffsetT = 10; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + FeProgressiveBlur { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args FeProgressiveBlurArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = FeProgressiveBlurBuilder::new(_fbb); + builder.add_radius2(args.radius2); + builder.add_radius(args.radius); + if let Some(x) = args.end { builder.add_end(x); } + if let Some(x) = args.start { builder.add_start(x); } + builder.finish() + } + + + #[inline] + pub fn start(&self) -> Option<&'a Alignment> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeProgressiveBlur::VT_START, None)} + } + #[inline] + pub fn end(&self) -> Option<&'a Alignment> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeProgressiveBlur::VT_END, None)} + } + #[inline] + pub fn radius(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeProgressiveBlur::VT_RADIUS, Some(0.0)).unwrap()} + } + #[inline] + pub fn radius2(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeProgressiveBlur::VT_RADIUS2, Some(0.0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for FeProgressiveBlur<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("start", Self::VT_START, false)? + .visit_field::("end", Self::VT_END, false)? + .visit_field::("radius", Self::VT_RADIUS, false)? + .visit_field::("radius2", Self::VT_RADIUS2, false)? + .finish(); + Ok(()) + } +} +pub struct FeProgressiveBlurArgs<'a> { + pub start: Option<&'a Alignment>, + pub end: Option<&'a Alignment>, + pub radius: f32, + pub radius2: f32, +} +impl<'a> Default for FeProgressiveBlurArgs<'a> { + #[inline] + fn default() -> Self { + FeProgressiveBlurArgs { + start: None, + end: None, + radius: 0.0, + radius2: 0.0, + } + } +} + +pub struct FeProgressiveBlurBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> FeProgressiveBlurBuilder<'a, 'b, A> { + #[inline] + pub fn add_start(&mut self, start: &Alignment) { + self.fbb_.push_slot_always::<&Alignment>(FeProgressiveBlur::VT_START, start); + } + #[inline] + pub fn add_end(&mut self, end: &Alignment) { + self.fbb_.push_slot_always::<&Alignment>(FeProgressiveBlur::VT_END, end); + } + #[inline] + pub fn add_radius(&mut self, radius: f32) { + self.fbb_.push_slot::(FeProgressiveBlur::VT_RADIUS, radius, 0.0); + } + #[inline] + pub fn add_radius2(&mut self, radius2: f32) { + self.fbb_.push_slot::(FeProgressiveBlur::VT_RADIUS2, radius2, 0.0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> FeProgressiveBlurBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + FeProgressiveBlurBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for FeProgressiveBlur<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("FeProgressiveBlur"); + ds.field("start", &self.start()); + ds.field("end", &self.end()); + ds.field("radius", &self.radius()); + ds.field("radius2", &self.radius2()); + ds.finish() + } +} +pub enum FeLayerBlurOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `FeLayerBlur { blur: FeBlur, active: bool }` +pub struct FeLayerBlur<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for FeLayerBlur<'a> { + type Inner = FeLayerBlur<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> FeLayerBlur<'a> { + pub const VT_ACTIVE: ::flatbuffers::VOffsetT = 4; + pub const VT_BLUR_TYPE: ::flatbuffers::VOffsetT = 6; + pub const VT_BLUR: ::flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + FeLayerBlur { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args FeLayerBlurArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = FeLayerBlurBuilder::new(_fbb); + if let Some(x) = args.blur { builder.add_blur(x); } + builder.add_blur_type(args.blur_type); + builder.add_active(args.active); + builder.finish() + } + + + #[inline] + pub fn active(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeLayerBlur::VT_ACTIVE, Some(true)).unwrap()} + } + #[inline] + pub fn blur_type(&self) -> FeBlur { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeLayerBlur::VT_BLUR_TYPE, Some(FeBlur::NONE)).unwrap()} + } + #[inline] + pub fn blur(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>(FeLayerBlur::VT_BLUR, None)} + } + #[inline] + #[allow(non_snake_case)] + pub fn blur_as_fe_gaussian_blur(&self) -> Option> { + if self.blur_type() == FeBlur::FeGaussianBlur { + self.blur().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { FeGaussianBlur::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn blur_as_fe_progressive_blur(&self) -> Option> { + if self.blur_type() == FeBlur::FeProgressiveBlur { + self.blur().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { FeProgressiveBlur::init_from_table(t) } + }) + } else { + None + } + } + +} + +impl ::flatbuffers::Verifiable for FeLayerBlur<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("active", Self::VT_ACTIVE, false)? + .visit_union::("blur_type", Self::VT_BLUR_TYPE, "blur", Self::VT_BLUR, false, |key, v, pos| { + match key { + FeBlur::FeGaussianBlur => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("FeBlur::FeGaussianBlur", pos), + FeBlur::FeProgressiveBlur => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("FeBlur::FeProgressiveBlur", pos), + _ => Ok(()), + } + })? + .finish(); + Ok(()) + } +} +pub struct FeLayerBlurArgs { + pub active: bool, + pub blur_type: FeBlur, + pub blur: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, +} +impl<'a> Default for FeLayerBlurArgs { + #[inline] + fn default() -> Self { + FeLayerBlurArgs { + active: true, + blur_type: FeBlur::NONE, + blur: None, + } + } +} + +pub struct FeLayerBlurBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> FeLayerBlurBuilder<'a, 'b, A> { + #[inline] + pub fn add_active(&mut self, active: bool) { + self.fbb_.push_slot::(FeLayerBlur::VT_ACTIVE, active, true); + } + #[inline] + pub fn add_blur_type(&mut self, blur_type: FeBlur) { + self.fbb_.push_slot::(FeLayerBlur::VT_BLUR_TYPE, blur_type, FeBlur::NONE); + } + #[inline] + pub fn add_blur(&mut self, blur: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(FeLayerBlur::VT_BLUR, blur); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> FeLayerBlurBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + FeLayerBlurBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for FeLayerBlur<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("FeLayerBlur"); + ds.field("active", &self.active()); + ds.field("blur_type", &self.blur_type()); + match self.blur_type() { + FeBlur::FeGaussianBlur => { + if let Some(x) = self.blur_as_fe_gaussian_blur() { + ds.field("blur", &x) + } else { + ds.field("blur", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + FeBlur::FeProgressiveBlur => { + if let Some(x) = self.blur_as_fe_progressive_blur() { + ds.field("blur", &x) + } else { + ds.field("blur", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + _ => { + let x: Option<()> = None; + ds.field("blur", &x) + }, + }; + ds.finish() + } +} +pub enum FeBackdropBlurOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `FeBackdropBlur { blur: FeBlur, active: bool }` +pub struct FeBackdropBlur<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for FeBackdropBlur<'a> { + type Inner = FeBackdropBlur<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> FeBackdropBlur<'a> { + pub const VT_ACTIVE: ::flatbuffers::VOffsetT = 4; + pub const VT_BLUR_TYPE: ::flatbuffers::VOffsetT = 6; + pub const VT_BLUR: ::flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + FeBackdropBlur { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args FeBackdropBlurArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = FeBackdropBlurBuilder::new(_fbb); + if let Some(x) = args.blur { builder.add_blur(x); } + builder.add_blur_type(args.blur_type); + builder.add_active(args.active); + builder.finish() + } + + + #[inline] + pub fn active(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeBackdropBlur::VT_ACTIVE, Some(true)).unwrap()} + } + #[inline] + pub fn blur_type(&self) -> FeBlur { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeBackdropBlur::VT_BLUR_TYPE, Some(FeBlur::NONE)).unwrap()} + } + #[inline] + pub fn blur(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>(FeBackdropBlur::VT_BLUR, None)} + } + #[inline] + #[allow(non_snake_case)] + pub fn blur_as_fe_gaussian_blur(&self) -> Option> { + if self.blur_type() == FeBlur::FeGaussianBlur { + self.blur().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { FeGaussianBlur::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn blur_as_fe_progressive_blur(&self) -> Option> { + if self.blur_type() == FeBlur::FeProgressiveBlur { + self.blur().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { FeProgressiveBlur::init_from_table(t) } + }) + } else { + None + } + } + +} + +impl ::flatbuffers::Verifiable for FeBackdropBlur<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("active", Self::VT_ACTIVE, false)? + .visit_union::("blur_type", Self::VT_BLUR_TYPE, "blur", Self::VT_BLUR, false, |key, v, pos| { + match key { + FeBlur::FeGaussianBlur => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("FeBlur::FeGaussianBlur", pos), + FeBlur::FeProgressiveBlur => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("FeBlur::FeProgressiveBlur", pos), + _ => Ok(()), + } + })? + .finish(); + Ok(()) + } +} +pub struct FeBackdropBlurArgs { + pub active: bool, + pub blur_type: FeBlur, + pub blur: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, +} +impl<'a> Default for FeBackdropBlurArgs { + #[inline] + fn default() -> Self { + FeBackdropBlurArgs { + active: true, + blur_type: FeBlur::NONE, + blur: None, + } + } +} + +pub struct FeBackdropBlurBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> FeBackdropBlurBuilder<'a, 'b, A> { + #[inline] + pub fn add_active(&mut self, active: bool) { + self.fbb_.push_slot::(FeBackdropBlur::VT_ACTIVE, active, true); + } + #[inline] + pub fn add_blur_type(&mut self, blur_type: FeBlur) { + self.fbb_.push_slot::(FeBackdropBlur::VT_BLUR_TYPE, blur_type, FeBlur::NONE); + } + #[inline] + pub fn add_blur(&mut self, blur: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(FeBackdropBlur::VT_BLUR, blur); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> FeBackdropBlurBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + FeBackdropBlurBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for FeBackdropBlur<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("FeBackdropBlur"); + ds.field("active", &self.active()); + ds.field("blur_type", &self.blur_type()); + match self.blur_type() { + FeBlur::FeGaussianBlur => { + if let Some(x) = self.blur_as_fe_gaussian_blur() { + ds.field("blur", &x) + } else { + ds.field("blur", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + FeBlur::FeProgressiveBlur => { + if let Some(x) = self.blur_as_fe_progressive_blur() { + ds.field("blur", &x) + } else { + ds.field("blur", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + _ => { + let x: Option<()> = None; + ds.field("blur", &x) + }, + }; + ds.finish() + } +} +pub enum FeShadowOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `FeShadow { dx, dy, blur, spread, color, active }` +pub struct FeShadow<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for FeShadow<'a> { + type Inner = FeShadow<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> FeShadow<'a> { + pub const VT_ACTIVE: ::flatbuffers::VOffsetT = 4; + pub const VT_DX: ::flatbuffers::VOffsetT = 6; + pub const VT_DY: ::flatbuffers::VOffsetT = 8; + pub const VT_BLUR: ::flatbuffers::VOffsetT = 10; + pub const VT_SPREAD: ::flatbuffers::VOffsetT = 12; + pub const VT_COLOR: ::flatbuffers::VOffsetT = 14; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + FeShadow { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args FeShadowArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = FeShadowBuilder::new(_fbb); + if let Some(x) = args.color { builder.add_color(x); } + builder.add_spread(args.spread); + builder.add_blur(args.blur); + builder.add_dy(args.dy); + builder.add_dx(args.dx); + builder.add_active(args.active); + builder.finish() + } + + + #[inline] + pub fn active(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeShadow::VT_ACTIVE, Some(true)).unwrap()} + } + #[inline] + pub fn dx(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeShadow::VT_DX, Some(0.0)).unwrap()} + } + #[inline] + pub fn dy(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeShadow::VT_DY, Some(0.0)).unwrap()} + } + #[inline] + pub fn blur(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeShadow::VT_BLUR, Some(0.0)).unwrap()} + } + #[inline] + pub fn spread(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeShadow::VT_SPREAD, Some(0.0)).unwrap()} + } + #[inline] + pub fn color(&self) -> Option<&'a RGBA32F> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeShadow::VT_COLOR, None)} + } +} + +impl ::flatbuffers::Verifiable for FeShadow<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("active", Self::VT_ACTIVE, false)? + .visit_field::("dx", Self::VT_DX, false)? + .visit_field::("dy", Self::VT_DY, false)? + .visit_field::("blur", Self::VT_BLUR, false)? + .visit_field::("spread", Self::VT_SPREAD, false)? + .visit_field::("color", Self::VT_COLOR, false)? + .finish(); + Ok(()) + } +} +pub struct FeShadowArgs<'a> { + pub active: bool, + pub dx: f32, + pub dy: f32, + pub blur: f32, + pub spread: f32, + pub color: Option<&'a RGBA32F>, +} +impl<'a> Default for FeShadowArgs<'a> { + #[inline] + fn default() -> Self { + FeShadowArgs { + active: true, + dx: 0.0, + dy: 0.0, + blur: 0.0, + spread: 0.0, + color: None, + } + } +} + +pub struct FeShadowBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> FeShadowBuilder<'a, 'b, A> { + #[inline] + pub fn add_active(&mut self, active: bool) { + self.fbb_.push_slot::(FeShadow::VT_ACTIVE, active, true); + } + #[inline] + pub fn add_dx(&mut self, dx: f32) { + self.fbb_.push_slot::(FeShadow::VT_DX, dx, 0.0); + } + #[inline] + pub fn add_dy(&mut self, dy: f32) { + self.fbb_.push_slot::(FeShadow::VT_DY, dy, 0.0); + } + #[inline] + pub fn add_blur(&mut self, blur: f32) { + self.fbb_.push_slot::(FeShadow::VT_BLUR, blur, 0.0); + } + #[inline] + pub fn add_spread(&mut self, spread: f32) { + self.fbb_.push_slot::(FeShadow::VT_SPREAD, spread, 0.0); + } + #[inline] + pub fn add_color(&mut self, color: &RGBA32F) { + self.fbb_.push_slot_always::<&RGBA32F>(FeShadow::VT_COLOR, color); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> FeShadowBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + FeShadowBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for FeShadow<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("FeShadow"); + ds.field("active", &self.active()); + ds.field("dx", &self.dx()); + ds.field("dy", &self.dy()); + ds.field("blur", &self.blur()); + ds.field("spread", &self.spread()); + ds.field("color", &self.color()); + ds.finish() + } +} +pub enum FilterShadowEffectOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Struct-tagged representation of Rust `FilterShadowEffect`. +pub struct FilterShadowEffect<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for FilterShadowEffect<'a> { + type Inner = FilterShadowEffect<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> FilterShadowEffect<'a> { + pub const VT_KIND: ::flatbuffers::VOffsetT = 4; + pub const VT_SHADOW: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + FilterShadowEffect { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args FilterShadowEffectArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = FilterShadowEffectBuilder::new(_fbb); + if let Some(x) = args.shadow { builder.add_shadow(x); } + builder.add_kind(args.kind); + builder.finish() + } + + + #[inline] + pub fn kind(&self) -> FilterShadowEffectKind { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FilterShadowEffect::VT_KIND, Some(FilterShadowEffectKind::DropShadow)).unwrap()} + } + #[inline] + pub fn shadow(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(FilterShadowEffect::VT_SHADOW, None)} + } +} + +impl ::flatbuffers::Verifiable for FilterShadowEffect<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("kind", Self::VT_KIND, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("shadow", Self::VT_SHADOW, false)? + .finish(); + Ok(()) + } +} +pub struct FilterShadowEffectArgs<'a> { + pub kind: FilterShadowEffectKind, + pub shadow: Option<::flatbuffers::WIPOffset>>, +} +impl<'a> Default for FilterShadowEffectArgs<'a> { + #[inline] + fn default() -> Self { + FilterShadowEffectArgs { + kind: FilterShadowEffectKind::DropShadow, + shadow: None, + } + } +} + +pub struct FilterShadowEffectBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> FilterShadowEffectBuilder<'a, 'b, A> { + #[inline] + pub fn add_kind(&mut self, kind: FilterShadowEffectKind) { + self.fbb_.push_slot::(FilterShadowEffect::VT_KIND, kind, FilterShadowEffectKind::DropShadow); + } + #[inline] + pub fn add_shadow(&mut self, shadow: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(FilterShadowEffect::VT_SHADOW, shadow); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> FilterShadowEffectBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + FilterShadowEffectBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for FilterShadowEffect<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("FilterShadowEffect"); + ds.field("kind", &self.kind()); + ds.field("shadow", &self.shadow()); + ds.finish() + } +} +pub enum NoiseEffectColorsOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Struct-tagged representation of Rust `NoiseEffectColors`. +pub struct NoiseEffectColors<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for NoiseEffectColors<'a> { + type Inner = NoiseEffectColors<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> NoiseEffectColors<'a> { + pub const VT_KIND: ::flatbuffers::VOffsetT = 4; + pub const VT_MONO_COLOR: ::flatbuffers::VOffsetT = 6; + pub const VT_DUO_COLOR1: ::flatbuffers::VOffsetT = 8; + pub const VT_DUO_COLOR2: ::flatbuffers::VOffsetT = 10; + pub const VT_MULTI_OPACITY: ::flatbuffers::VOffsetT = 12; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + NoiseEffectColors { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args NoiseEffectColorsArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = NoiseEffectColorsBuilder::new(_fbb); + builder.add_multi_opacity(args.multi_opacity); + if let Some(x) = args.duo_color2 { builder.add_duo_color2(x); } + if let Some(x) = args.duo_color1 { builder.add_duo_color1(x); } + if let Some(x) = args.mono_color { builder.add_mono_color(x); } + builder.add_kind(args.kind); + builder.finish() + } + + + #[inline] + pub fn kind(&self) -> NoiseEffectColorsKind { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(NoiseEffectColors::VT_KIND, Some(NoiseEffectColorsKind::Mono)).unwrap()} + } + #[inline] + pub fn mono_color(&self) -> Option<&'a RGBA32F> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(NoiseEffectColors::VT_MONO_COLOR, None)} + } + #[inline] + pub fn duo_color1(&self) -> Option<&'a RGBA32F> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(NoiseEffectColors::VT_DUO_COLOR1, None)} + } + #[inline] + pub fn duo_color2(&self) -> Option<&'a RGBA32F> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(NoiseEffectColors::VT_DUO_COLOR2, None)} + } + #[inline] + pub fn multi_opacity(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(NoiseEffectColors::VT_MULTI_OPACITY, Some(0.0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for NoiseEffectColors<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("kind", Self::VT_KIND, false)? + .visit_field::("mono_color", Self::VT_MONO_COLOR, false)? + .visit_field::("duo_color1", Self::VT_DUO_COLOR1, false)? + .visit_field::("duo_color2", Self::VT_DUO_COLOR2, false)? + .visit_field::("multi_opacity", Self::VT_MULTI_OPACITY, false)? + .finish(); + Ok(()) + } +} +pub struct NoiseEffectColorsArgs<'a> { + pub kind: NoiseEffectColorsKind, + pub mono_color: Option<&'a RGBA32F>, + pub duo_color1: Option<&'a RGBA32F>, + pub duo_color2: Option<&'a RGBA32F>, + pub multi_opacity: f32, +} +impl<'a> Default for NoiseEffectColorsArgs<'a> { + #[inline] + fn default() -> Self { + NoiseEffectColorsArgs { + kind: NoiseEffectColorsKind::Mono, + mono_color: None, + duo_color1: None, + duo_color2: None, + multi_opacity: 0.0, + } + } +} + +pub struct NoiseEffectColorsBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> NoiseEffectColorsBuilder<'a, 'b, A> { + #[inline] + pub fn add_kind(&mut self, kind: NoiseEffectColorsKind) { + self.fbb_.push_slot::(NoiseEffectColors::VT_KIND, kind, NoiseEffectColorsKind::Mono); + } + #[inline] + pub fn add_mono_color(&mut self, mono_color: &RGBA32F) { + self.fbb_.push_slot_always::<&RGBA32F>(NoiseEffectColors::VT_MONO_COLOR, mono_color); + } + #[inline] + pub fn add_duo_color1(&mut self, duo_color1: &RGBA32F) { + self.fbb_.push_slot_always::<&RGBA32F>(NoiseEffectColors::VT_DUO_COLOR1, duo_color1); + } + #[inline] + pub fn add_duo_color2(&mut self, duo_color2: &RGBA32F) { + self.fbb_.push_slot_always::<&RGBA32F>(NoiseEffectColors::VT_DUO_COLOR2, duo_color2); + } + #[inline] + pub fn add_multi_opacity(&mut self, multi_opacity: f32) { + self.fbb_.push_slot::(NoiseEffectColors::VT_MULTI_OPACITY, multi_opacity, 0.0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> NoiseEffectColorsBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + NoiseEffectColorsBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for NoiseEffectColors<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("NoiseEffectColors"); + ds.field("kind", &self.kind()); + ds.field("mono_color", &self.mono_color()); + ds.field("duo_color1", &self.duo_color1()); + ds.field("duo_color2", &self.duo_color2()); + ds.field("multi_opacity", &self.multi_opacity()); + ds.finish() + } +} +pub enum FeNoiseEffectOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `FeNoiseEffect` +pub struct FeNoiseEffect<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for FeNoiseEffect<'a> { + type Inner = FeNoiseEffect<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> FeNoiseEffect<'a> { + pub const VT_ACTIVE: ::flatbuffers::VOffsetT = 4; + pub const VT_NOISE_SIZE: ::flatbuffers::VOffsetT = 6; + pub const VT_DENSITY: ::flatbuffers::VOffsetT = 8; + pub const VT_NUM_OCTAVES: ::flatbuffers::VOffsetT = 10; + pub const VT_SEED: ::flatbuffers::VOffsetT = 12; + pub const VT_COLORING: ::flatbuffers::VOffsetT = 14; + pub const VT_BLEND_MODE: ::flatbuffers::VOffsetT = 16; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + FeNoiseEffect { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args FeNoiseEffectArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = FeNoiseEffectBuilder::new(_fbb); + if let Some(x) = args.coloring { builder.add_coloring(x); } + builder.add_seed(args.seed); + builder.add_num_octaves(args.num_octaves); + builder.add_density(args.density); + builder.add_noise_size(args.noise_size); + builder.add_blend_mode(args.blend_mode); + builder.add_active(args.active); + builder.finish() + } + + + #[inline] + pub fn active(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeNoiseEffect::VT_ACTIVE, Some(true)).unwrap()} + } + #[inline] + pub fn noise_size(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeNoiseEffect::VT_NOISE_SIZE, Some(0.0)).unwrap()} + } + #[inline] + pub fn density(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeNoiseEffect::VT_DENSITY, Some(0.0)).unwrap()} + } + #[inline] + pub fn num_octaves(&self) -> i32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeNoiseEffect::VT_NUM_OCTAVES, Some(0)).unwrap()} + } + #[inline] + pub fn seed(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeNoiseEffect::VT_SEED, Some(0.0)).unwrap()} + } + #[inline] + pub fn coloring(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(FeNoiseEffect::VT_COLORING, None)} + } + #[inline] + pub fn blend_mode(&self) -> BlendMode { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeNoiseEffect::VT_BLEND_MODE, Some(BlendMode::Normal)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for FeNoiseEffect<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("active", Self::VT_ACTIVE, false)? + .visit_field::("noise_size", Self::VT_NOISE_SIZE, false)? + .visit_field::("density", Self::VT_DENSITY, false)? + .visit_field::("num_octaves", Self::VT_NUM_OCTAVES, false)? + .visit_field::("seed", Self::VT_SEED, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("coloring", Self::VT_COLORING, false)? + .visit_field::("blend_mode", Self::VT_BLEND_MODE, false)? + .finish(); + Ok(()) + } +} +pub struct FeNoiseEffectArgs<'a> { + pub active: bool, + pub noise_size: f32, + pub density: f32, + pub num_octaves: i32, + pub seed: f32, + pub coloring: Option<::flatbuffers::WIPOffset>>, + pub blend_mode: BlendMode, +} +impl<'a> Default for FeNoiseEffectArgs<'a> { + #[inline] + fn default() -> Self { + FeNoiseEffectArgs { + active: true, + noise_size: 0.0, + density: 0.0, + num_octaves: 0, + seed: 0.0, + coloring: None, + blend_mode: BlendMode::Normal, + } + } +} + +pub struct FeNoiseEffectBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> FeNoiseEffectBuilder<'a, 'b, A> { + #[inline] + pub fn add_active(&mut self, active: bool) { + self.fbb_.push_slot::(FeNoiseEffect::VT_ACTIVE, active, true); + } + #[inline] + pub fn add_noise_size(&mut self, noise_size: f32) { + self.fbb_.push_slot::(FeNoiseEffect::VT_NOISE_SIZE, noise_size, 0.0); + } + #[inline] + pub fn add_density(&mut self, density: f32) { + self.fbb_.push_slot::(FeNoiseEffect::VT_DENSITY, density, 0.0); + } + #[inline] + pub fn add_num_octaves(&mut self, num_octaves: i32) { + self.fbb_.push_slot::(FeNoiseEffect::VT_NUM_OCTAVES, num_octaves, 0); + } + #[inline] + pub fn add_seed(&mut self, seed: f32) { + self.fbb_.push_slot::(FeNoiseEffect::VT_SEED, seed, 0.0); + } + #[inline] + pub fn add_coloring(&mut self, coloring: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(FeNoiseEffect::VT_COLORING, coloring); + } + #[inline] + pub fn add_blend_mode(&mut self, blend_mode: BlendMode) { + self.fbb_.push_slot::(FeNoiseEffect::VT_BLEND_MODE, blend_mode, BlendMode::Normal); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> FeNoiseEffectBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + FeNoiseEffectBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for FeNoiseEffect<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("FeNoiseEffect"); + ds.field("active", &self.active()); + ds.field("noise_size", &self.noise_size()); + ds.field("density", &self.density()); + ds.field("num_octaves", &self.num_octaves()); + ds.field("seed", &self.seed()); + ds.field("coloring", &self.coloring()); + ds.field("blend_mode", &self.blend_mode()); + ds.finish() + } +} +pub enum FeLiquidGlassOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `FeLiquidGlass` +pub struct FeLiquidGlass<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for FeLiquidGlass<'a> { + type Inner = FeLiquidGlass<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> FeLiquidGlass<'a> { + pub const VT_ACTIVE: ::flatbuffers::VOffsetT = 4; + pub const VT_LIGHT_INTENSITY: ::flatbuffers::VOffsetT = 6; + pub const VT_LIGHT_ANGLE: ::flatbuffers::VOffsetT = 8; + pub const VT_REFRACTION: ::flatbuffers::VOffsetT = 10; + pub const VT_DEPTH: ::flatbuffers::VOffsetT = 12; + pub const VT_DISPERSION: ::flatbuffers::VOffsetT = 14; + pub const VT_BLUR_RADIUS: ::flatbuffers::VOffsetT = 16; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + FeLiquidGlass { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args FeLiquidGlassArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = FeLiquidGlassBuilder::new(_fbb); + builder.add_blur_radius(args.blur_radius); + builder.add_dispersion(args.dispersion); + builder.add_depth(args.depth); + builder.add_refraction(args.refraction); + builder.add_light_angle(args.light_angle); + builder.add_light_intensity(args.light_intensity); + builder.add_active(args.active); + builder.finish() + } + + + #[inline] + pub fn active(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeLiquidGlass::VT_ACTIVE, Some(true)).unwrap()} + } + #[inline] + pub fn light_intensity(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeLiquidGlass::VT_LIGHT_INTENSITY, Some(0.0)).unwrap()} + } + #[inline] + pub fn light_angle(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeLiquidGlass::VT_LIGHT_ANGLE, Some(0.0)).unwrap()} + } + #[inline] + pub fn refraction(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeLiquidGlass::VT_REFRACTION, Some(0.0)).unwrap()} + } + #[inline] + pub fn depth(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeLiquidGlass::VT_DEPTH, Some(0.0)).unwrap()} + } + #[inline] + pub fn dispersion(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeLiquidGlass::VT_DISPERSION, Some(0.0)).unwrap()} + } + #[inline] + pub fn blur_radius(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(FeLiquidGlass::VT_BLUR_RADIUS, Some(0.0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for FeLiquidGlass<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("active", Self::VT_ACTIVE, false)? + .visit_field::("light_intensity", Self::VT_LIGHT_INTENSITY, false)? + .visit_field::("light_angle", Self::VT_LIGHT_ANGLE, false)? + .visit_field::("refraction", Self::VT_REFRACTION, false)? + .visit_field::("depth", Self::VT_DEPTH, false)? + .visit_field::("dispersion", Self::VT_DISPERSION, false)? + .visit_field::("blur_radius", Self::VT_BLUR_RADIUS, false)? + .finish(); + Ok(()) + } +} +pub struct FeLiquidGlassArgs { + pub active: bool, + pub light_intensity: f32, + pub light_angle: f32, + pub refraction: f32, + pub depth: f32, + pub dispersion: f32, + pub blur_radius: f32, +} +impl<'a> Default for FeLiquidGlassArgs { + #[inline] + fn default() -> Self { + FeLiquidGlassArgs { + active: true, + light_intensity: 0.0, + light_angle: 0.0, + refraction: 0.0, + depth: 0.0, + dispersion: 0.0, + blur_radius: 0.0, + } + } +} + +pub struct FeLiquidGlassBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> FeLiquidGlassBuilder<'a, 'b, A> { + #[inline] + pub fn add_active(&mut self, active: bool) { + self.fbb_.push_slot::(FeLiquidGlass::VT_ACTIVE, active, true); + } + #[inline] + pub fn add_light_intensity(&mut self, light_intensity: f32) { + self.fbb_.push_slot::(FeLiquidGlass::VT_LIGHT_INTENSITY, light_intensity, 0.0); + } + #[inline] + pub fn add_light_angle(&mut self, light_angle: f32) { + self.fbb_.push_slot::(FeLiquidGlass::VT_LIGHT_ANGLE, light_angle, 0.0); + } + #[inline] + pub fn add_refraction(&mut self, refraction: f32) { + self.fbb_.push_slot::(FeLiquidGlass::VT_REFRACTION, refraction, 0.0); + } + #[inline] + pub fn add_depth(&mut self, depth: f32) { + self.fbb_.push_slot::(FeLiquidGlass::VT_DEPTH, depth, 0.0); + } + #[inline] + pub fn add_dispersion(&mut self, dispersion: f32) { + self.fbb_.push_slot::(FeLiquidGlass::VT_DISPERSION, dispersion, 0.0); + } + #[inline] + pub fn add_blur_radius(&mut self, blur_radius: f32) { + self.fbb_.push_slot::(FeLiquidGlass::VT_BLUR_RADIUS, blur_radius, 0.0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> FeLiquidGlassBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + FeLiquidGlassBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for FeLiquidGlass<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("FeLiquidGlass"); + ds.field("active", &self.active()); + ds.field("light_intensity", &self.light_intensity()); + ds.field("light_angle", &self.light_angle()); + ds.field("refraction", &self.refraction()); + ds.field("depth", &self.depth()); + ds.field("dispersion", &self.dispersion()); + ds.field("blur_radius", &self.blur_radius()); + ds.finish() + } +} +pub enum LayerEffectsOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Effects trait used by nodes (Rust: `LayerEffects`). +/// +/// Note: must be a table because it contains vectors (FlatBuffers structs cannot contain vectors). +pub struct LayerEffects<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for LayerEffects<'a> { + type Inner = LayerEffects<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> LayerEffects<'a> { + pub const VT_FE_BLUR: ::flatbuffers::VOffsetT = 4; + pub const VT_FE_BACKDROP_BLUR: ::flatbuffers::VOffsetT = 6; + pub const VT_FE_GLASS: ::flatbuffers::VOffsetT = 8; + pub const VT_FE_SHADOWS: ::flatbuffers::VOffsetT = 10; + pub const VT_FE_NOISES: ::flatbuffers::VOffsetT = 12; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + LayerEffects { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args LayerEffectsArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = LayerEffectsBuilder::new(_fbb); + if let Some(x) = args.fe_noises { builder.add_fe_noises(x); } + if let Some(x) = args.fe_shadows { builder.add_fe_shadows(x); } + if let Some(x) = args.fe_glass { builder.add_fe_glass(x); } + if let Some(x) = args.fe_backdrop_blur { builder.add_fe_backdrop_blur(x); } + if let Some(x) = args.fe_blur { builder.add_fe_blur(x); } + builder.finish() + } + + + #[inline] + pub fn fe_blur(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LayerEffects::VT_FE_BLUR, None)} + } + #[inline] + pub fn fe_backdrop_blur(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LayerEffects::VT_FE_BACKDROP_BLUR, None)} + } + #[inline] + pub fn fe_glass(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LayerEffects::VT_FE_GLASS, None)} + } + #[inline] + pub fn fe_shadows(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(LayerEffects::VT_FE_SHADOWS, None)} + } + #[inline] + pub fn fe_noises(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(LayerEffects::VT_FE_NOISES, None)} + } +} + +impl ::flatbuffers::Verifiable for LayerEffects<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("fe_blur", Self::VT_FE_BLUR, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("fe_backdrop_blur", Self::VT_FE_BACKDROP_BLUR, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("fe_glass", Self::VT_FE_GLASS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("fe_shadows", Self::VT_FE_SHADOWS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("fe_noises", Self::VT_FE_NOISES, false)? + .finish(); + Ok(()) + } +} +pub struct LayerEffectsArgs<'a> { + pub fe_blur: Option<::flatbuffers::WIPOffset>>, + pub fe_backdrop_blur: Option<::flatbuffers::WIPOffset>>, + pub fe_glass: Option<::flatbuffers::WIPOffset>>, + pub fe_shadows: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub fe_noises: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, +} +impl<'a> Default for LayerEffectsArgs<'a> { + #[inline] + fn default() -> Self { + LayerEffectsArgs { + fe_blur: None, + fe_backdrop_blur: None, + fe_glass: None, + fe_shadows: None, + fe_noises: None, + } + } +} + +pub struct LayerEffectsBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> LayerEffectsBuilder<'a, 'b, A> { + #[inline] + pub fn add_fe_blur(&mut self, fe_blur: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LayerEffects::VT_FE_BLUR, fe_blur); + } + #[inline] + pub fn add_fe_backdrop_blur(&mut self, fe_backdrop_blur: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LayerEffects::VT_FE_BACKDROP_BLUR, fe_backdrop_blur); + } + #[inline] + pub fn add_fe_glass(&mut self, fe_glass: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LayerEffects::VT_FE_GLASS, fe_glass); + } + #[inline] + pub fn add_fe_shadows(&mut self, fe_shadows: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(LayerEffects::VT_FE_SHADOWS, fe_shadows); + } + #[inline] + pub fn add_fe_noises(&mut self, fe_noises: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(LayerEffects::VT_FE_NOISES, fe_noises); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> LayerEffectsBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + LayerEffectsBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for LayerEffects<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("LayerEffects"); + ds.field("fe_blur", &self.fe_blur()); + ds.field("fe_backdrop_blur", &self.fe_backdrop_blur()); + ds.field("fe_glass", &self.fe_glass()); + ds.field("fe_shadows", &self.fe_shadows()); + ds.field("fe_noises", &self.fe_noises()); + ds.finish() + } +} +pub enum StrokeStyleOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct StrokeStyle<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for StrokeStyle<'a> { + type Inner = StrokeStyle<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> StrokeStyle<'a> { + pub const VT_STROKE_ALIGN: ::flatbuffers::VOffsetT = 4; + pub const VT_STROKE_CAP: ::flatbuffers::VOffsetT = 6; + pub const VT_STROKE_JOIN: ::flatbuffers::VOffsetT = 8; + pub const VT_STROKE_MITER_LIMIT: ::flatbuffers::VOffsetT = 10; + pub const VT_STROKE_DASH_ARRAY: ::flatbuffers::VOffsetT = 12; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + StrokeStyle { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args StrokeStyleArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = StrokeStyleBuilder::new(_fbb); + if let Some(x) = args.stroke_dash_array { builder.add_stroke_dash_array(x); } + builder.add_stroke_miter_limit(args.stroke_miter_limit); + builder.add_stroke_join(args.stroke_join); + builder.add_stroke_cap(args.stroke_cap); + builder.add_stroke_align(args.stroke_align); + builder.finish() + } + + + #[inline] + pub fn stroke_align(&self) -> StrokeAlign { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(StrokeStyle::VT_STROKE_ALIGN, Some(StrokeAlign::Inside)).unwrap()} + } + #[inline] + pub fn stroke_cap(&self) -> StrokeCap { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(StrokeStyle::VT_STROKE_CAP, Some(StrokeCap::Butt)).unwrap()} + } + #[inline] + pub fn stroke_join(&self) -> StrokeJoin { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(StrokeStyle::VT_STROKE_JOIN, Some(StrokeJoin::Miter)).unwrap()} + } + #[inline] + pub fn stroke_miter_limit(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(StrokeStyle::VT_STROKE_MITER_LIMIT, Some(4.0)).unwrap()} + } + /// dash array in logical pixels. Empty or omitted means "no dash". + #[inline] + pub fn stroke_dash_array(&self) -> Option<::flatbuffers::Vector<'a, f32>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, f32>>>(StrokeStyle::VT_STROKE_DASH_ARRAY, None)} + } +} + +impl ::flatbuffers::Verifiable for StrokeStyle<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("stroke_align", Self::VT_STROKE_ALIGN, false)? + .visit_field::("stroke_cap", Self::VT_STROKE_CAP, false)? + .visit_field::("stroke_join", Self::VT_STROKE_JOIN, false)? + .visit_field::("stroke_miter_limit", Self::VT_STROKE_MITER_LIMIT, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, f32>>>("stroke_dash_array", Self::VT_STROKE_DASH_ARRAY, false)? + .finish(); + Ok(()) + } +} +pub struct StrokeStyleArgs<'a> { + pub stroke_align: StrokeAlign, + pub stroke_cap: StrokeCap, + pub stroke_join: StrokeJoin, + pub stroke_miter_limit: f32, + pub stroke_dash_array: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, f32>>>, +} +impl<'a> Default for StrokeStyleArgs<'a> { + #[inline] + fn default() -> Self { + StrokeStyleArgs { + stroke_align: StrokeAlign::Inside, + stroke_cap: StrokeCap::Butt, + stroke_join: StrokeJoin::Miter, + stroke_miter_limit: 4.0, + stroke_dash_array: None, + } + } +} + +pub struct StrokeStyleBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> StrokeStyleBuilder<'a, 'b, A> { + #[inline] + pub fn add_stroke_align(&mut self, stroke_align: StrokeAlign) { + self.fbb_.push_slot::(StrokeStyle::VT_STROKE_ALIGN, stroke_align, StrokeAlign::Inside); + } + #[inline] + pub fn add_stroke_cap(&mut self, stroke_cap: StrokeCap) { + self.fbb_.push_slot::(StrokeStyle::VT_STROKE_CAP, stroke_cap, StrokeCap::Butt); + } + #[inline] + pub fn add_stroke_join(&mut self, stroke_join: StrokeJoin) { + self.fbb_.push_slot::(StrokeStyle::VT_STROKE_JOIN, stroke_join, StrokeJoin::Miter); + } + #[inline] + pub fn add_stroke_miter_limit(&mut self, stroke_miter_limit: f32) { + self.fbb_.push_slot::(StrokeStyle::VT_STROKE_MITER_LIMIT, stroke_miter_limit, 4.0); + } + #[inline] + pub fn add_stroke_dash_array(&mut self, stroke_dash_array: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , f32>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(StrokeStyle::VT_STROKE_DASH_ARRAY, stroke_dash_array); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> StrokeStyleBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + StrokeStyleBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for StrokeStyle<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("StrokeStyle"); + ds.field("stroke_align", &self.stroke_align()); + ds.field("stroke_cap", &self.stroke_cap()); + ds.field("stroke_join", &self.stroke_join()); + ds.field("stroke_miter_limit", &self.stroke_miter_limit()); + ds.field("stroke_dash_array", &self.stroke_dash_array()); + ds.finish() + } +} +pub enum VariableWidthStopOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// A single stop in a variable-width stroke profile. +/// +/// - `u` is the normalized position along the stroke in [0, 1]. +/// - `r` is the half-width ("radius") at this position in pixels. +pub struct VariableWidthStop<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for VariableWidthStop<'a> { + type Inner = VariableWidthStop<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> VariableWidthStop<'a> { + pub const VT_U: ::flatbuffers::VOffsetT = 4; + pub const VT_R: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + VariableWidthStop { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args VariableWidthStopArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = VariableWidthStopBuilder::new(_fbb); + builder.add_r(args.r); + builder.add_u(args.u); + builder.finish() + } + + + #[inline] + pub fn u(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(VariableWidthStop::VT_U, Some(0.0)).unwrap()} + } + #[inline] + pub fn r(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(VariableWidthStop::VT_R, Some(0.0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for VariableWidthStop<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("u", Self::VT_U, false)? + .visit_field::("r", Self::VT_R, false)? + .finish(); + Ok(()) + } +} +pub struct VariableWidthStopArgs { + pub u: f32, + pub r: f32, +} +impl<'a> Default for VariableWidthStopArgs { + #[inline] + fn default() -> Self { + VariableWidthStopArgs { + u: 0.0, + r: 0.0, + } + } +} + +pub struct VariableWidthStopBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> VariableWidthStopBuilder<'a, 'b, A> { + #[inline] + pub fn add_u(&mut self, u: f32) { + self.fbb_.push_slot::(VariableWidthStop::VT_U, u, 0.0); + } + #[inline] + pub fn add_r(&mut self, r: f32) { + self.fbb_.push_slot::(VariableWidthStop::VT_R, r, 0.0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> VariableWidthStopBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + VariableWidthStopBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for VariableWidthStop<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("VariableWidthStop"); + ds.field("u", &self.u()); + ds.field("r", &self.r()); + ds.finish() + } +} +pub enum VariableWidthProfileOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Variable-width stroke profile. +/// +/// Notes: +/// - This matches TS `cg.VariableWidthProfile` and Rust `cg::varwidth::{WidthStop, VarWidthProfile}` at the wire level. +/// - `base` is intentionally not stored here; renderers should derive a base half-width from the node's `stroke_width` +/// when `stops` is empty (see Rust `VarWidthSampler` behavior). +pub struct VariableWidthProfile<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for VariableWidthProfile<'a> { + type Inner = VariableWidthProfile<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> VariableWidthProfile<'a> { + pub const VT_STOPS: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + VariableWidthProfile { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args VariableWidthProfileArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = VariableWidthProfileBuilder::new(_fbb); + if let Some(x) = args.stops { builder.add_stops(x); } + builder.finish() + } + + + #[inline] + pub fn stops(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(VariableWidthProfile::VT_STOPS, None)} + } +} + +impl ::flatbuffers::Verifiable for VariableWidthProfile<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("stops", Self::VT_STOPS, false)? + .finish(); + Ok(()) + } +} +pub struct VariableWidthProfileArgs<'a> { + pub stops: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, +} +impl<'a> Default for VariableWidthProfileArgs<'a> { + #[inline] + fn default() -> Self { + VariableWidthProfileArgs { + stops: None, + } + } +} + +pub struct VariableWidthProfileBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> VariableWidthProfileBuilder<'a, 'b, A> { + #[inline] + pub fn add_stops(&mut self, stops: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(VariableWidthProfile::VT_STOPS, stops); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> VariableWidthProfileBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + VariableWidthProfileBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for VariableWidthProfile<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("VariableWidthProfile"); + ds.field("stops", &self.stops()); + ds.finish() + } +} +pub enum StrokeGeometryTraitOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct StrokeGeometryTrait<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for StrokeGeometryTrait<'a> { + type Inner = StrokeGeometryTrait<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> StrokeGeometryTrait<'a> { + pub const VT_STROKE_WIDTH: ::flatbuffers::VOffsetT = 4; + pub const VT_STROKE_STYLE: ::flatbuffers::VOffsetT = 6; + pub const VT_STROKE_WIDTH_PROFILE: ::flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + StrokeGeometryTrait { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args StrokeGeometryTraitArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = StrokeGeometryTraitBuilder::new(_fbb); + if let Some(x) = args.stroke_width_profile { builder.add_stroke_width_profile(x); } + if let Some(x) = args.stroke_style { builder.add_stroke_style(x); } + builder.add_stroke_width(args.stroke_width); + builder.finish() + } + + + #[inline] + pub fn stroke_width(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(StrokeGeometryTrait::VT_STROKE_WIDTH, Some(0.0)).unwrap()} + } + #[inline] + pub fn stroke_style(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(StrokeGeometryTrait::VT_STROKE_STYLE, None)} + } + #[inline] + pub fn stroke_width_profile(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(StrokeGeometryTrait::VT_STROKE_WIDTH_PROFILE, None)} + } +} + +impl ::flatbuffers::Verifiable for StrokeGeometryTrait<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("stroke_width", Self::VT_STROKE_WIDTH, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("stroke_style", Self::VT_STROKE_STYLE, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("stroke_width_profile", Self::VT_STROKE_WIDTH_PROFILE, false)? + .finish(); + Ok(()) + } +} +pub struct StrokeGeometryTraitArgs<'a> { + pub stroke_width: f32, + pub stroke_style: Option<::flatbuffers::WIPOffset>>, + pub stroke_width_profile: Option<::flatbuffers::WIPOffset>>, +} +impl<'a> Default for StrokeGeometryTraitArgs<'a> { + #[inline] + fn default() -> Self { + StrokeGeometryTraitArgs { + stroke_width: 0.0, + stroke_style: None, + stroke_width_profile: None, + } + } +} + +pub struct StrokeGeometryTraitBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> StrokeGeometryTraitBuilder<'a, 'b, A> { + #[inline] + pub fn add_stroke_width(&mut self, stroke_width: f32) { + self.fbb_.push_slot::(StrokeGeometryTrait::VT_STROKE_WIDTH, stroke_width, 0.0); + } + #[inline] + pub fn add_stroke_style(&mut self, stroke_style: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(StrokeGeometryTrait::VT_STROKE_STYLE, stroke_style); + } + #[inline] + pub fn add_stroke_width_profile(&mut self, stroke_width_profile: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(StrokeGeometryTrait::VT_STROKE_WIDTH_PROFILE, stroke_width_profile); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> StrokeGeometryTraitBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + StrokeGeometryTraitBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for StrokeGeometryTrait<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("StrokeGeometryTrait"); + ds.field("stroke_width", &self.stroke_width()); + ds.field("stroke_style", &self.stroke_style()); + ds.field("stroke_width_profile", &self.stroke_width_profile()); + ds.finish() + } +} +pub enum RectangularStrokeGeometryTraitOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct RectangularStrokeGeometryTrait<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for RectangularStrokeGeometryTrait<'a> { + type Inner = RectangularStrokeGeometryTrait<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> RectangularStrokeGeometryTrait<'a> { + pub const VT_RECTANGULAR_STROKE_WIDTH: ::flatbuffers::VOffsetT = 4; + pub const VT_STROKE_STYLE: ::flatbuffers::VOffsetT = 6; + pub const VT_STROKE_WIDTH_PROFILE: ::flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + RectangularStrokeGeometryTrait { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args RectangularStrokeGeometryTraitArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = RectangularStrokeGeometryTraitBuilder::new(_fbb); + if let Some(x) = args.stroke_width_profile { builder.add_stroke_width_profile(x); } + if let Some(x) = args.stroke_style { builder.add_stroke_style(x); } + if let Some(x) = args.rectangular_stroke_width { builder.add_rectangular_stroke_width(x); } + builder.finish() + } + + + #[inline] + pub fn rectangular_stroke_width(&self) -> Option<&'a RectangularStrokeWidth> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(RectangularStrokeGeometryTrait::VT_RECTANGULAR_STROKE_WIDTH, None)} + } + #[inline] + pub fn stroke_style(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(RectangularStrokeGeometryTrait::VT_STROKE_STYLE, None)} + } + #[inline] + pub fn stroke_width_profile(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(RectangularStrokeGeometryTrait::VT_STROKE_WIDTH_PROFILE, None)} + } +} + +impl ::flatbuffers::Verifiable for RectangularStrokeGeometryTrait<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("rectangular_stroke_width", Self::VT_RECTANGULAR_STROKE_WIDTH, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("stroke_style", Self::VT_STROKE_STYLE, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("stroke_width_profile", Self::VT_STROKE_WIDTH_PROFILE, false)? + .finish(); + Ok(()) + } +} +pub struct RectangularStrokeGeometryTraitArgs<'a> { + pub rectangular_stroke_width: Option<&'a RectangularStrokeWidth>, + pub stroke_style: Option<::flatbuffers::WIPOffset>>, + pub stroke_width_profile: Option<::flatbuffers::WIPOffset>>, +} +impl<'a> Default for RectangularStrokeGeometryTraitArgs<'a> { + #[inline] + fn default() -> Self { + RectangularStrokeGeometryTraitArgs { + rectangular_stroke_width: None, + stroke_style: None, + stroke_width_profile: None, + } + } +} + +pub struct RectangularStrokeGeometryTraitBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> RectangularStrokeGeometryTraitBuilder<'a, 'b, A> { + #[inline] + pub fn add_rectangular_stroke_width(&mut self, rectangular_stroke_width: &RectangularStrokeWidth) { + self.fbb_.push_slot_always::<&RectangularStrokeWidth>(RectangularStrokeGeometryTrait::VT_RECTANGULAR_STROKE_WIDTH, rectangular_stroke_width); + } + #[inline] + pub fn add_stroke_style(&mut self, stroke_style: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(RectangularStrokeGeometryTrait::VT_STROKE_STYLE, stroke_style); + } + #[inline] + pub fn add_stroke_width_profile(&mut self, stroke_width_profile: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(RectangularStrokeGeometryTrait::VT_STROKE_WIDTH_PROFILE, stroke_width_profile); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> RectangularStrokeGeometryTraitBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + RectangularStrokeGeometryTraitBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for RectangularStrokeGeometryTrait<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("RectangularStrokeGeometryTrait"); + ds.field("rectangular_stroke_width", &self.rectangular_stroke_width()); + ds.field("stroke_style", &self.stroke_style()); + ds.field("stroke_width_profile", &self.stroke_width_profile()); + ds.finish() + } +} +pub enum CornerRadiusTraitOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct CornerRadiusTrait<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for CornerRadiusTrait<'a> { + type Inner = CornerRadiusTrait<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> CornerRadiusTrait<'a> { + pub const VT_CORNER_RADIUS: ::flatbuffers::VOffsetT = 4; + pub const VT_CORNER_SMOOTHING: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + CornerRadiusTrait { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args CornerRadiusTraitArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = CornerRadiusTraitBuilder::new(_fbb); + builder.add_corner_smoothing(args.corner_smoothing); + if let Some(x) = args.corner_radius { builder.add_corner_radius(x); } + builder.finish() + } + + + #[inline] + pub fn corner_radius(&self) -> Option<&'a CGRadius> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(CornerRadiusTrait::VT_CORNER_RADIUS, None)} + } + #[inline] + pub fn corner_smoothing(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(CornerRadiusTrait::VT_CORNER_SMOOTHING, Some(0.0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for CornerRadiusTrait<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("corner_radius", Self::VT_CORNER_RADIUS, false)? + .visit_field::("corner_smoothing", Self::VT_CORNER_SMOOTHING, false)? + .finish(); + Ok(()) + } +} +pub struct CornerRadiusTraitArgs<'a> { + pub corner_radius: Option<&'a CGRadius>, + pub corner_smoothing: f32, +} +impl<'a> Default for CornerRadiusTraitArgs<'a> { + #[inline] + fn default() -> Self { + CornerRadiusTraitArgs { + corner_radius: None, + corner_smoothing: 0.0, + } + } +} + +pub struct CornerRadiusTraitBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> CornerRadiusTraitBuilder<'a, 'b, A> { + #[inline] + pub fn add_corner_radius(&mut self, corner_radius: &CGRadius) { + self.fbb_.push_slot_always::<&CGRadius>(CornerRadiusTrait::VT_CORNER_RADIUS, corner_radius); + } + #[inline] + pub fn add_corner_smoothing(&mut self, corner_smoothing: f32) { + self.fbb_.push_slot::(CornerRadiusTrait::VT_CORNER_SMOOTHING, corner_smoothing, 0.0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> CornerRadiusTraitBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + CornerRadiusTraitBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for CornerRadiusTrait<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("CornerRadiusTrait"); + ds.field("corner_radius", &self.corner_radius()); + ds.field("corner_smoothing", &self.corner_smoothing()); + ds.finish() + } +} +pub enum RectangularCornerRadiusTraitOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct RectangularCornerRadiusTrait<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for RectangularCornerRadiusTrait<'a> { + type Inner = RectangularCornerRadiusTrait<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> RectangularCornerRadiusTrait<'a> { + pub const VT_RECTANGULAR_CORNER_RADIUS: ::flatbuffers::VOffsetT = 4; + pub const VT_CORNER_SMOOTHING: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + RectangularCornerRadiusTrait { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args RectangularCornerRadiusTraitArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = RectangularCornerRadiusTraitBuilder::new(_fbb); + builder.add_corner_smoothing(args.corner_smoothing); + if let Some(x) = args.rectangular_corner_radius { builder.add_rectangular_corner_radius(x); } + builder.finish() + } + + + #[inline] + pub fn rectangular_corner_radius(&self) -> Option<&'a RectangularCornerRadius> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(RectangularCornerRadiusTrait::VT_RECTANGULAR_CORNER_RADIUS, None)} + } + #[inline] + pub fn corner_smoothing(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(RectangularCornerRadiusTrait::VT_CORNER_SMOOTHING, Some(0.0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for RectangularCornerRadiusTrait<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("rectangular_corner_radius", Self::VT_RECTANGULAR_CORNER_RADIUS, false)? + .visit_field::("corner_smoothing", Self::VT_CORNER_SMOOTHING, false)? + .finish(); + Ok(()) + } +} +pub struct RectangularCornerRadiusTraitArgs<'a> { + pub rectangular_corner_radius: Option<&'a RectangularCornerRadius>, + pub corner_smoothing: f32, +} +impl<'a> Default for RectangularCornerRadiusTraitArgs<'a> { + #[inline] + fn default() -> Self { + RectangularCornerRadiusTraitArgs { + rectangular_corner_radius: None, + corner_smoothing: 0.0, + } + } +} + +pub struct RectangularCornerRadiusTraitBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> RectangularCornerRadiusTraitBuilder<'a, 'b, A> { + #[inline] + pub fn add_rectangular_corner_radius(&mut self, rectangular_corner_radius: &RectangularCornerRadius) { + self.fbb_.push_slot_always::<&RectangularCornerRadius>(RectangularCornerRadiusTrait::VT_RECTANGULAR_CORNER_RADIUS, rectangular_corner_radius); + } + #[inline] + pub fn add_corner_smoothing(&mut self, corner_smoothing: f32) { + self.fbb_.push_slot::(RectangularCornerRadiusTrait::VT_CORNER_SMOOTHING, corner_smoothing, 0.0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> RectangularCornerRadiusTraitBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + RectangularCornerRadiusTraitBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for RectangularCornerRadiusTrait<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("RectangularCornerRadiusTrait"); + ds.field("rectangular_corner_radius", &self.rectangular_corner_radius()); + ds.field("corner_smoothing", &self.corner_smoothing()); + ds.finish() + } +} +pub enum CanonicalEllipticalShapeRingSectorParametersOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Rust: `EllipticalRingSectorShape` (arc/ring sector data for ellipses) +pub struct CanonicalEllipticalShapeRingSectorParameters<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for CanonicalEllipticalShapeRingSectorParameters<'a> { + type Inner = CanonicalEllipticalShapeRingSectorParameters<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> CanonicalEllipticalShapeRingSectorParameters<'a> { + pub const VT_INNER_RADIUS_RATIO: ::flatbuffers::VOffsetT = 4; + pub const VT_START_ANGLE: ::flatbuffers::VOffsetT = 6; + pub const VT_ANGLE: ::flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + CanonicalEllipticalShapeRingSectorParameters { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args CanonicalEllipticalShapeRingSectorParametersArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = CanonicalEllipticalShapeRingSectorParametersBuilder::new(_fbb); + builder.add_angle(args.angle); + builder.add_start_angle(args.start_angle); + builder.add_inner_radius_ratio(args.inner_radius_ratio); + builder.finish() + } + + + /// Inner radius ratio (0..1) + #[inline] + pub fn inner_radius_ratio(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(CanonicalEllipticalShapeRingSectorParameters::VT_INNER_RADIUS_RATIO, Some(0.0)).unwrap()} + } + /// Start angle in degrees + #[inline] + pub fn start_angle(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(CanonicalEllipticalShapeRingSectorParameters::VT_START_ANGLE, Some(0.0)).unwrap()} + } + /// Sweep angle in degrees (end_angle = start_angle + angle) + #[inline] + pub fn angle(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(CanonicalEllipticalShapeRingSectorParameters::VT_ANGLE, Some(360.0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for CanonicalEllipticalShapeRingSectorParameters<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("inner_radius_ratio", Self::VT_INNER_RADIUS_RATIO, false)? + .visit_field::("start_angle", Self::VT_START_ANGLE, false)? + .visit_field::("angle", Self::VT_ANGLE, false)? + .finish(); + Ok(()) + } +} +pub struct CanonicalEllipticalShapeRingSectorParametersArgs { + pub inner_radius_ratio: f32, + pub start_angle: f32, + pub angle: f32, +} +impl<'a> Default for CanonicalEllipticalShapeRingSectorParametersArgs { + #[inline] + fn default() -> Self { + CanonicalEllipticalShapeRingSectorParametersArgs { + inner_radius_ratio: 0.0, + start_angle: 0.0, + angle: 360.0, + } + } +} + +pub struct CanonicalEllipticalShapeRingSectorParametersBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> CanonicalEllipticalShapeRingSectorParametersBuilder<'a, 'b, A> { + #[inline] + pub fn add_inner_radius_ratio(&mut self, inner_radius_ratio: f32) { + self.fbb_.push_slot::(CanonicalEllipticalShapeRingSectorParameters::VT_INNER_RADIUS_RATIO, inner_radius_ratio, 0.0); + } + #[inline] + pub fn add_start_angle(&mut self, start_angle: f32) { + self.fbb_.push_slot::(CanonicalEllipticalShapeRingSectorParameters::VT_START_ANGLE, start_angle, 0.0); + } + #[inline] + pub fn add_angle(&mut self, angle: f32) { + self.fbb_.push_slot::(CanonicalEllipticalShapeRingSectorParameters::VT_ANGLE, angle, 360.0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> CanonicalEllipticalShapeRingSectorParametersBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + CanonicalEllipticalShapeRingSectorParametersBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for CanonicalEllipticalShapeRingSectorParameters<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("CanonicalEllipticalShapeRingSectorParameters"); + ds.field("inner_radius_ratio", &self.inner_radius_ratio()); + ds.field("start_angle", &self.start_angle()); + ds.field("angle", &self.angle()); + ds.finish() + } +} +pub enum CanonicalShapeRectangularOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// rectangle, rounded rectangle +pub struct CanonicalShapeRectangular<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for CanonicalShapeRectangular<'a> { + type Inner = CanonicalShapeRectangular<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> CanonicalShapeRectangular<'a> { + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + CanonicalShapeRectangular { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + _args: &'args CanonicalShapeRectangularArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = CanonicalShapeRectangularBuilder::new(_fbb); + builder.finish() + } + +} + +impl ::flatbuffers::Verifiable for CanonicalShapeRectangular<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .finish(); + Ok(()) + } +} +pub struct CanonicalShapeRectangularArgs { +} +impl<'a> Default for CanonicalShapeRectangularArgs { + #[inline] + fn default() -> Self { + CanonicalShapeRectangularArgs { + } + } +} + +pub struct CanonicalShapeRectangularBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> CanonicalShapeRectangularBuilder<'a, 'b, A> { + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> CanonicalShapeRectangularBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + CanonicalShapeRectangularBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for CanonicalShapeRectangular<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("CanonicalShapeRectangular"); + ds.finish() + } +} +pub enum CanonicalShapeEllipticalOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// circle, ellipse by default and also can represent ring, sector, ring+sector +pub struct CanonicalShapeElliptical<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for CanonicalShapeElliptical<'a> { + type Inner = CanonicalShapeElliptical<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> CanonicalShapeElliptical<'a> { + pub const VT_RING_SECTOR_DATA: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + CanonicalShapeElliptical { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args CanonicalShapeEllipticalArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = CanonicalShapeEllipticalBuilder::new(_fbb); + if let Some(x) = args.ring_sector_data { builder.add_ring_sector_data(x); } + builder.finish() + } + + + #[inline] + pub fn ring_sector_data(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(CanonicalShapeElliptical::VT_RING_SECTOR_DATA, None)} + } +} + +impl ::flatbuffers::Verifiable for CanonicalShapeElliptical<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("ring_sector_data", Self::VT_RING_SECTOR_DATA, false)? + .finish(); + Ok(()) + } +} +pub struct CanonicalShapeEllipticalArgs<'a> { + pub ring_sector_data: Option<::flatbuffers::WIPOffset>>, +} +impl<'a> Default for CanonicalShapeEllipticalArgs<'a> { + #[inline] + fn default() -> Self { + CanonicalShapeEllipticalArgs { + ring_sector_data: None, + } + } +} + +pub struct CanonicalShapeEllipticalBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> CanonicalShapeEllipticalBuilder<'a, 'b, A> { + #[inline] + pub fn add_ring_sector_data(&mut self, ring_sector_data: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(CanonicalShapeElliptical::VT_RING_SECTOR_DATA, ring_sector_data); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> CanonicalShapeEllipticalBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + CanonicalShapeEllipticalBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for CanonicalShapeElliptical<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("CanonicalShapeElliptical"); + ds.field("ring_sector_data", &self.ring_sector_data()); + ds.finish() + } +} +pub enum CanonicalShapePointsPolygonOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// polygon (any shapes defined by points) +pub struct CanonicalShapePointsPolygon<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for CanonicalShapePointsPolygon<'a> { + type Inner = CanonicalShapePointsPolygon<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> CanonicalShapePointsPolygon<'a> { + pub const VT_POINTS: ::flatbuffers::VOffsetT = 4; + pub const VT_FILL_RULE: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + CanonicalShapePointsPolygon { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args CanonicalShapePointsPolygonArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = CanonicalShapePointsPolygonBuilder::new(_fbb); + if let Some(x) = args.points { builder.add_points(x); } + builder.add_fill_rule(args.fill_rule); + builder.finish() + } + + + #[inline] + pub fn points(&self) -> Option<::flatbuffers::Vector<'a, CGPoint>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, CGPoint>>>(CanonicalShapePointsPolygon::VT_POINTS, None)} + } + #[inline] + pub fn fill_rule(&self) -> FillRule { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(CanonicalShapePointsPolygon::VT_FILL_RULE, Some(FillRule::NonZero)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for CanonicalShapePointsPolygon<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, CGPoint>>>("points", Self::VT_POINTS, false)? + .visit_field::("fill_rule", Self::VT_FILL_RULE, false)? + .finish(); + Ok(()) + } +} +pub struct CanonicalShapePointsPolygonArgs<'a> { + pub points: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, CGPoint>>>, + pub fill_rule: FillRule, +} +impl<'a> Default for CanonicalShapePointsPolygonArgs<'a> { + #[inline] + fn default() -> Self { + CanonicalShapePointsPolygonArgs { + points: None, + fill_rule: FillRule::NonZero, + } + } +} + +pub struct CanonicalShapePointsPolygonBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> CanonicalShapePointsPolygonBuilder<'a, 'b, A> { + #[inline] + pub fn add_points(&mut self, points: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , CGPoint>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(CanonicalShapePointsPolygon::VT_POINTS, points); + } + #[inline] + pub fn add_fill_rule(&mut self, fill_rule: FillRule) { + self.fbb_.push_slot::(CanonicalShapePointsPolygon::VT_FILL_RULE, fill_rule, FillRule::NonZero); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> CanonicalShapePointsPolygonBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + CanonicalShapePointsPolygonBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for CanonicalShapePointsPolygon<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("CanonicalShapePointsPolygon"); + ds.field("points", &self.points()); + ds.field("fill_rule", &self.fill_rule()); + ds.finish() + } +} +pub enum CanonicalShapeRegularPolygonOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// regular polygon +pub struct CanonicalShapeRegularPolygon<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for CanonicalShapeRegularPolygon<'a> { + type Inner = CanonicalShapeRegularPolygon<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> CanonicalShapeRegularPolygon<'a> { + pub const VT_POINT_COUNT: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + CanonicalShapeRegularPolygon { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args CanonicalShapeRegularPolygonArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = CanonicalShapeRegularPolygonBuilder::new(_fbb); + builder.add_point_count(args.point_count); + builder.finish() + } + + + #[inline] + pub fn point_count(&self) -> u32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(CanonicalShapeRegularPolygon::VT_POINT_COUNT, Some(0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for CanonicalShapeRegularPolygon<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("point_count", Self::VT_POINT_COUNT, false)? + .finish(); + Ok(()) + } +} +pub struct CanonicalShapeRegularPolygonArgs { + pub point_count: u32, +} +impl<'a> Default for CanonicalShapeRegularPolygonArgs { + #[inline] + fn default() -> Self { + CanonicalShapeRegularPolygonArgs { + point_count: 0, + } + } +} + +pub struct CanonicalShapeRegularPolygonBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> CanonicalShapeRegularPolygonBuilder<'a, 'b, A> { + #[inline] + pub fn add_point_count(&mut self, point_count: u32) { + self.fbb_.push_slot::(CanonicalShapeRegularPolygon::VT_POINT_COUNT, point_count, 0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> CanonicalShapeRegularPolygonBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + CanonicalShapeRegularPolygonBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for CanonicalShapeRegularPolygon<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("CanonicalShapeRegularPolygon"); + ds.field("point_count", &self.point_count()); + ds.finish() + } +} +pub enum CanonicalShapeRegularStarPolygonOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// regular star-ish polygon +pub struct CanonicalShapeRegularStarPolygon<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for CanonicalShapeRegularStarPolygon<'a> { + type Inner = CanonicalShapeRegularStarPolygon<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> CanonicalShapeRegularStarPolygon<'a> { + pub const VT_POINT_COUNT: ::flatbuffers::VOffsetT = 4; + pub const VT_INNER_RADIUS_RATIO: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + CanonicalShapeRegularStarPolygon { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args CanonicalShapeRegularStarPolygonArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = CanonicalShapeRegularStarPolygonBuilder::new(_fbb); + builder.add_inner_radius_ratio(args.inner_radius_ratio); + builder.add_point_count(args.point_count); + builder.finish() + } + + + #[inline] + pub fn point_count(&self) -> u32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(CanonicalShapeRegularStarPolygon::VT_POINT_COUNT, Some(0)).unwrap()} + } + #[inline] + pub fn inner_radius_ratio(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(CanonicalShapeRegularStarPolygon::VT_INNER_RADIUS_RATIO, Some(0.0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for CanonicalShapeRegularStarPolygon<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("point_count", Self::VT_POINT_COUNT, false)? + .visit_field::("inner_radius_ratio", Self::VT_INNER_RADIUS_RATIO, false)? + .finish(); + Ok(()) + } +} +pub struct CanonicalShapeRegularStarPolygonArgs { + pub point_count: u32, + pub inner_radius_ratio: f32, +} +impl<'a> Default for CanonicalShapeRegularStarPolygonArgs { + #[inline] + fn default() -> Self { + CanonicalShapeRegularStarPolygonArgs { + point_count: 0, + inner_radius_ratio: 0.0, + } + } +} + +pub struct CanonicalShapeRegularStarPolygonBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> CanonicalShapeRegularStarPolygonBuilder<'a, 'b, A> { + #[inline] + pub fn add_point_count(&mut self, point_count: u32) { + self.fbb_.push_slot::(CanonicalShapeRegularStarPolygon::VT_POINT_COUNT, point_count, 0); + } + #[inline] + pub fn add_inner_radius_ratio(&mut self, inner_radius_ratio: f32) { + self.fbb_.push_slot::(CanonicalShapeRegularStarPolygon::VT_INNER_RADIUS_RATIO, inner_radius_ratio, 0.0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> CanonicalShapeRegularStarPolygonBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + CanonicalShapeRegularStarPolygonBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for CanonicalShapeRegularStarPolygon<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("CanonicalShapeRegularStarPolygon"); + ds.field("point_count", &self.point_count()); + ds.field("inner_radius_ratio", &self.inner_radius_ratio()); + ds.finish() + } +} +pub enum CanonicalShapePathOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// path +pub struct CanonicalShapePath<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for CanonicalShapePath<'a> { + type Inner = CanonicalShapePath<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> CanonicalShapePath<'a> { + pub const VT_D: ::flatbuffers::VOffsetT = 4; + pub const VT_FILL_RULE: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + CanonicalShapePath { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args CanonicalShapePathArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = CanonicalShapePathBuilder::new(_fbb); + if let Some(x) = args.d { builder.add_d(x); } + builder.add_fill_rule(args.fill_rule); + builder.finish() + } + + + #[inline] + pub fn d(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(CanonicalShapePath::VT_D, None)} + } + #[inline] + pub fn fill_rule(&self) -> FillRule { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(CanonicalShapePath::VT_FILL_RULE, Some(FillRule::NonZero)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for CanonicalShapePath<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("d", Self::VT_D, false)? + .visit_field::("fill_rule", Self::VT_FILL_RULE, false)? + .finish(); + Ok(()) + } +} +pub struct CanonicalShapePathArgs<'a> { + pub d: Option<::flatbuffers::WIPOffset<&'a str>>, + pub fill_rule: FillRule, +} +impl<'a> Default for CanonicalShapePathArgs<'a> { + #[inline] + fn default() -> Self { + CanonicalShapePathArgs { + d: None, + fill_rule: FillRule::NonZero, + } + } +} + +pub struct CanonicalShapePathBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> CanonicalShapePathBuilder<'a, 'b, A> { + #[inline] + pub fn add_d(&mut self, d: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(CanonicalShapePath::VT_D, d); + } + #[inline] + pub fn add_fill_rule(&mut self, fill_rule: FillRule) { + self.fbb_.push_slot::(CanonicalShapePath::VT_FILL_RULE, fill_rule, FillRule::NonZero); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> CanonicalShapePathBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + CanonicalShapePathBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for CanonicalShapePath<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("CanonicalShapePath"); + ds.field("d", &self.d()); + ds.field("fill_rule", &self.fill_rule()); + ds.finish() + } +} +pub enum LayoutDimensionValueOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Dimension value. (width/height) +/// +/// Canonical mapping: +/// - TS `number` or `{type:"length", unit:"px"}` -> `Px` +/// - TS `{type:"percentage"}` -> `Percent` +pub struct LayoutDimensionValue<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for LayoutDimensionValue<'a> { + type Inner = LayoutDimensionValue<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> LayoutDimensionValue<'a> { + pub const VT_UNIT: ::flatbuffers::VOffsetT = 4; + pub const VT_VALUE: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + LayoutDimensionValue { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args LayoutDimensionValueArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = LayoutDimensionValueBuilder::new(_fbb); + if let Some(x) = args.value { builder.add_value(x); } + builder.add_unit(args.unit); + builder.finish() + } + + + #[inline] + pub fn unit(&self) -> LayoutDimensionUnit { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutDimensionValue::VT_UNIT, Some(LayoutDimensionUnit::LengthPx)).unwrap()} + } + #[inline] + pub fn value(&self) -> Option { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutDimensionValue::VT_VALUE, None)} + } +} + +impl ::flatbuffers::Verifiable for LayoutDimensionValue<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("unit", Self::VT_UNIT, false)? + .visit_field::("value", Self::VT_VALUE, false)? + .finish(); + Ok(()) + } +} +pub struct LayoutDimensionValueArgs { + pub unit: LayoutDimensionUnit, + pub value: Option, +} +impl<'a> Default for LayoutDimensionValueArgs { + #[inline] + fn default() -> Self { + LayoutDimensionValueArgs { + unit: LayoutDimensionUnit::LengthPx, + value: None, + } + } +} + +pub struct LayoutDimensionValueBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> LayoutDimensionValueBuilder<'a, 'b, A> { + #[inline] + pub fn add_unit(&mut self, unit: LayoutDimensionUnit) { + self.fbb_.push_slot::(LayoutDimensionValue::VT_UNIT, unit, LayoutDimensionUnit::LengthPx); + } + #[inline] + pub fn add_value(&mut self, value: f32) { + self.fbb_.push_slot_always::(LayoutDimensionValue::VT_VALUE, value); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> LayoutDimensionValueBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + LayoutDimensionValueBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for LayoutDimensionValue<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("LayoutDimensionValue"); + ds.field("unit", &self.unit()); + ds.field("value", &self.value()); + ds.finish() + } +} +pub enum LayoutDimensionStyleOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// `LayoutDimensionStyle {}` +pub struct LayoutDimensionStyle<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for LayoutDimensionStyle<'a> { + type Inner = LayoutDimensionStyle<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> LayoutDimensionStyle<'a> { + pub const VT_LAYOUT_TARGET_WIDTH: ::flatbuffers::VOffsetT = 4; + pub const VT_LAYOUT_TARGET_HEIGHT: ::flatbuffers::VOffsetT = 6; + pub const VT_LAYOUT_TARGET_ASPECT_RATIO: ::flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + LayoutDimensionStyle { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args LayoutDimensionStyleArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = LayoutDimensionStyleBuilder::new(_fbb); + if let Some(x) = args.layout_target_aspect_ratio { builder.add_layout_target_aspect_ratio(x); } + if let Some(x) = args.layout_target_height { builder.add_layout_target_height(x); } + if let Some(x) = args.layout_target_width { builder.add_layout_target_width(x); } + builder.finish() + } + + + /// unset = auto + #[inline] + pub fn layout_target_width(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LayoutDimensionStyle::VT_LAYOUT_TARGET_WIDTH, None)} + } + /// unset = auto + #[inline] + pub fn layout_target_height(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LayoutDimensionStyle::VT_LAYOUT_TARGET_HEIGHT, None)} + } + /// Preferred layout aspect ratio. + /// + /// Represents a proportional relationship between width and height expressed + /// as a ratio pair (e.g. `(16, 9)`, `(4, 3)`, `(1, 1)`). + /// + /// (0, 0) represents and is handled as "unset". + /// + /// Notes: + /// - This does not define geometry by itself. It is a sizing preference that + /// layout engines may consult when resolving under-specified dimensions + /// (e.g. when either width or height is "auto") or when proportional sizing + /// is explicitly required by the layout model. + /// - When both width and height are definitively specified, this should have + /// no effect and must not override explicit dimensions. + /// - Layout engines may ignore this if aspect-ratio-aware sizing is not supported. + /// + /// Encoding: + /// - Stored as a tuple (width, height) for parity with TS `layout_target_aspect_ratio?: [number, number]`. + #[inline] + pub fn layout_target_aspect_ratio(&self) -> Option<&'a CGSize> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutDimensionStyle::VT_LAYOUT_TARGET_ASPECT_RATIO, None)} + } +} + +impl ::flatbuffers::Verifiable for LayoutDimensionStyle<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("layout_target_width", Self::VT_LAYOUT_TARGET_WIDTH, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("layout_target_height", Self::VT_LAYOUT_TARGET_HEIGHT, false)? + .visit_field::("layout_target_aspect_ratio", Self::VT_LAYOUT_TARGET_ASPECT_RATIO, false)? + .finish(); + Ok(()) + } +} +pub struct LayoutDimensionStyleArgs<'a> { + pub layout_target_width: Option<::flatbuffers::WIPOffset>>, + pub layout_target_height: Option<::flatbuffers::WIPOffset>>, + pub layout_target_aspect_ratio: Option<&'a CGSize>, +} +impl<'a> Default for LayoutDimensionStyleArgs<'a> { + #[inline] + fn default() -> Self { + LayoutDimensionStyleArgs { + layout_target_width: None, + layout_target_height: None, + layout_target_aspect_ratio: None, + } + } +} + +pub struct LayoutDimensionStyleBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> LayoutDimensionStyleBuilder<'a, 'b, A> { + #[inline] + pub fn add_layout_target_width(&mut self, layout_target_width: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LayoutDimensionStyle::VT_LAYOUT_TARGET_WIDTH, layout_target_width); + } + #[inline] + pub fn add_layout_target_height(&mut self, layout_target_height: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LayoutDimensionStyle::VT_LAYOUT_TARGET_HEIGHT, layout_target_height); + } + #[inline] + pub fn add_layout_target_aspect_ratio(&mut self, layout_target_aspect_ratio: &CGSize) { + self.fbb_.push_slot_always::<&CGSize>(LayoutDimensionStyle::VT_LAYOUT_TARGET_ASPECT_RATIO, layout_target_aspect_ratio); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> LayoutDimensionStyleBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + LayoutDimensionStyleBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for LayoutDimensionStyle<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("LayoutDimensionStyle"); + ds.field("layout_target_width", &self.layout_target_width()); + ds.field("layout_target_height", &self.layout_target_height()); + ds.field("layout_target_aspect_ratio", &self.layout_target_aspect_ratio()); + ds.finish() + } +} +pub enum LayoutPositioningCartesianOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// x,y static positioning model +pub struct LayoutPositioningCartesian<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for LayoutPositioningCartesian<'a> { + type Inner = LayoutPositioningCartesian<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> LayoutPositioningCartesian<'a> { + pub const VT_X: ::flatbuffers::VOffsetT = 4; + pub const VT_Y: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + LayoutPositioningCartesian { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args LayoutPositioningCartesianArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = LayoutPositioningCartesianBuilder::new(_fbb); + builder.add_y(args.y); + builder.add_x(args.x); + builder.finish() + } + + + #[inline] + pub fn x(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutPositioningCartesian::VT_X, Some(0.0)).unwrap()} + } + #[inline] + pub fn y(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutPositioningCartesian::VT_Y, Some(0.0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for LayoutPositioningCartesian<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("x", Self::VT_X, false)? + .visit_field::("y", Self::VT_Y, false)? + .finish(); + Ok(()) + } +} +pub struct LayoutPositioningCartesianArgs { + pub x: f32, + pub y: f32, +} +impl<'a> Default for LayoutPositioningCartesianArgs { + #[inline] + fn default() -> Self { + LayoutPositioningCartesianArgs { + x: 0.0, + y: 0.0, + } + } +} + +pub struct LayoutPositioningCartesianBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> LayoutPositioningCartesianBuilder<'a, 'b, A> { + #[inline] + pub fn add_x(&mut self, x: f32) { + self.fbb_.push_slot::(LayoutPositioningCartesian::VT_X, x, 0.0); + } + #[inline] + pub fn add_y(&mut self, y: f32) { + self.fbb_.push_slot::(LayoutPositioningCartesian::VT_Y, y, 0.0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> LayoutPositioningCartesianBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + LayoutPositioningCartesianBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for LayoutPositioningCartesian<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("LayoutPositioningCartesian"); + ds.field("x", &self.x()); + ds.field("y", &self.y()); + ds.finish() + } +} +pub enum PositioningSideOffsetValueOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct PositioningSideOffsetValue<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for PositioningSideOffsetValue<'a> { + type Inner = PositioningSideOffsetValue<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> PositioningSideOffsetValue<'a> { + pub const VT_KIND: ::flatbuffers::VOffsetT = 4; + pub const VT_VALUE: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + PositioningSideOffsetValue { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args PositioningSideOffsetValueArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = PositioningSideOffsetValueBuilder::new(_fbb); + if let Some(x) = args.value { builder.add_value(x); } + builder.add_kind(args.kind); + builder.finish() + } + + + #[inline] + pub fn kind(&self) -> PositioningSideOffsetKind { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(PositioningSideOffsetValue::VT_KIND, Some(PositioningSideOffsetKind::Px)).unwrap()} + } + #[inline] + pub fn value(&self) -> Option { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(PositioningSideOffsetValue::VT_VALUE, None)} + } +} + +impl ::flatbuffers::Verifiable for PositioningSideOffsetValue<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("kind", Self::VT_KIND, false)? + .visit_field::("value", Self::VT_VALUE, false)? + .finish(); + Ok(()) + } +} +pub struct PositioningSideOffsetValueArgs { + pub kind: PositioningSideOffsetKind, + pub value: Option, +} +impl<'a> Default for PositioningSideOffsetValueArgs { + #[inline] + fn default() -> Self { + PositioningSideOffsetValueArgs { + kind: PositioningSideOffsetKind::Px, + value: None, + } + } +} + +pub struct PositioningSideOffsetValueBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> PositioningSideOffsetValueBuilder<'a, 'b, A> { + #[inline] + pub fn add_kind(&mut self, kind: PositioningSideOffsetKind) { + self.fbb_.push_slot::(PositioningSideOffsetValue::VT_KIND, kind, PositioningSideOffsetKind::Px); + } + #[inline] + pub fn add_value(&mut self, value: f32) { + self.fbb_.push_slot_always::(PositioningSideOffsetValue::VT_VALUE, value); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> PositioningSideOffsetValueBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + PositioningSideOffsetValueBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for PositioningSideOffsetValue<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("PositioningSideOffsetValue"); + ds.field("kind", &self.kind()); + ds.field("value", &self.value()); + ds.finish() + } +} +pub enum LayoutPositioningInsetOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// left, top, right, bottom positioning model (css standard) +pub struct LayoutPositioningInset<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for LayoutPositioningInset<'a> { + type Inner = LayoutPositioningInset<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> LayoutPositioningInset<'a> { + pub const VT_TOP: ::flatbuffers::VOffsetT = 4; + pub const VT_RIGHT: ::flatbuffers::VOffsetT = 6; + pub const VT_BOTTOM: ::flatbuffers::VOffsetT = 8; + pub const VT_LEFT: ::flatbuffers::VOffsetT = 10; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + LayoutPositioningInset { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args LayoutPositioningInsetArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = LayoutPositioningInsetBuilder::new(_fbb); + if let Some(x) = args.left { builder.add_left(x); } + if let Some(x) = args.bottom { builder.add_bottom(x); } + if let Some(x) = args.right { builder.add_right(x); } + if let Some(x) = args.top { builder.add_top(x); } + builder.finish() + } + + + #[inline] + pub fn top(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LayoutPositioningInset::VT_TOP, None)} + } + #[inline] + pub fn right(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LayoutPositioningInset::VT_RIGHT, None)} + } + #[inline] + pub fn bottom(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LayoutPositioningInset::VT_BOTTOM, None)} + } + #[inline] + pub fn left(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LayoutPositioningInset::VT_LEFT, None)} + } +} + +impl ::flatbuffers::Verifiable for LayoutPositioningInset<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("top", Self::VT_TOP, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("right", Self::VT_RIGHT, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("bottom", Self::VT_BOTTOM, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("left", Self::VT_LEFT, false)? + .finish(); + Ok(()) + } +} +pub struct LayoutPositioningInsetArgs<'a> { + pub top: Option<::flatbuffers::WIPOffset>>, + pub right: Option<::flatbuffers::WIPOffset>>, + pub bottom: Option<::flatbuffers::WIPOffset>>, + pub left: Option<::flatbuffers::WIPOffset>>, +} +impl<'a> Default for LayoutPositioningInsetArgs<'a> { + #[inline] + fn default() -> Self { + LayoutPositioningInsetArgs { + top: None, + right: None, + bottom: None, + left: None, + } + } +} + +pub struct LayoutPositioningInsetBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> LayoutPositioningInsetBuilder<'a, 'b, A> { + #[inline] + pub fn add_top(&mut self, top: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LayoutPositioningInset::VT_TOP, top); + } + #[inline] + pub fn add_right(&mut self, right: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LayoutPositioningInset::VT_RIGHT, right); + } + #[inline] + pub fn add_bottom(&mut self, bottom: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LayoutPositioningInset::VT_BOTTOM, bottom); + } + #[inline] + pub fn add_left(&mut self, left: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LayoutPositioningInset::VT_LEFT, left); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> LayoutPositioningInsetBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + LayoutPositioningInsetBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for LayoutPositioningInset<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("LayoutPositioningInset"); + ds.field("top", &self.top()); + ds.field("right", &self.right()); + ds.field("bottom", &self.bottom()); + ds.field("left", &self.left()); + ds.finish() + } +} +pub enum LayoutContainerStyleOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct LayoutContainerStyle<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for LayoutContainerStyle<'a> { + type Inner = LayoutContainerStyle<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> LayoutContainerStyle<'a> { + pub const VT_LAYOUT_MODE: ::flatbuffers::VOffsetT = 4; + pub const VT_LAYOUT_DIRECTION: ::flatbuffers::VOffsetT = 6; + pub const VT_LAYOUT_WRAP: ::flatbuffers::VOffsetT = 8; + pub const VT_LAYOUT_MAIN_AXIS_ALIGNMENT: ::flatbuffers::VOffsetT = 10; + pub const VT_LAYOUT_CROSS_AXIS_ALIGNMENT: ::flatbuffers::VOffsetT = 12; + pub const VT_LAYOUT_PADDING: ::flatbuffers::VOffsetT = 14; + pub const VT_LAYOUT_MAIN_AXIS_GAP: ::flatbuffers::VOffsetT = 16; + pub const VT_LAYOUT_CROSS_AXIS_GAP: ::flatbuffers::VOffsetT = 18; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + LayoutContainerStyle { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args LayoutContainerStyleArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = LayoutContainerStyleBuilder::new(_fbb); + builder.add_layout_cross_axis_gap(args.layout_cross_axis_gap); + builder.add_layout_main_axis_gap(args.layout_main_axis_gap); + if let Some(x) = args.layout_padding { builder.add_layout_padding(x); } + builder.add_layout_cross_axis_alignment(args.layout_cross_axis_alignment); + builder.add_layout_main_axis_alignment(args.layout_main_axis_alignment); + builder.add_layout_wrap(args.layout_wrap); + builder.add_layout_direction(args.layout_direction); + builder.add_layout_mode(args.layout_mode); + builder.finish() + } + + + #[inline] + pub fn layout_mode(&self) -> LayoutMode { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutContainerStyle::VT_LAYOUT_MODE, Some(LayoutMode::Normal)).unwrap()} + } + #[inline] + pub fn layout_direction(&self) -> Axis { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutContainerStyle::VT_LAYOUT_DIRECTION, Some(Axis::Horizontal)).unwrap()} + } + #[inline] + pub fn layout_wrap(&self) -> LayoutWrap { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutContainerStyle::VT_LAYOUT_WRAP, Some(LayoutWrap::None)).unwrap()} + } + #[inline] + pub fn layout_main_axis_alignment(&self) -> MainAxisAlignment { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutContainerStyle::VT_LAYOUT_MAIN_AXIS_ALIGNMENT, Some(MainAxisAlignment::None)).unwrap()} + } + #[inline] + pub fn layout_cross_axis_alignment(&self) -> CrossAxisAlignment { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutContainerStyle::VT_LAYOUT_CROSS_AXIS_ALIGNMENT, Some(CrossAxisAlignment::None)).unwrap()} + } + #[inline] + pub fn layout_padding(&self) -> Option<&'a EdgeInsets> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutContainerStyle::VT_LAYOUT_PADDING, None)} + } + #[inline] + pub fn layout_main_axis_gap(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutContainerStyle::VT_LAYOUT_MAIN_AXIS_GAP, Some(0.0)).unwrap()} + } + #[inline] + pub fn layout_cross_axis_gap(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutContainerStyle::VT_LAYOUT_CROSS_AXIS_GAP, Some(0.0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for LayoutContainerStyle<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("layout_mode", Self::VT_LAYOUT_MODE, false)? + .visit_field::("layout_direction", Self::VT_LAYOUT_DIRECTION, false)? + .visit_field::("layout_wrap", Self::VT_LAYOUT_WRAP, false)? + .visit_field::("layout_main_axis_alignment", Self::VT_LAYOUT_MAIN_AXIS_ALIGNMENT, false)? + .visit_field::("layout_cross_axis_alignment", Self::VT_LAYOUT_CROSS_AXIS_ALIGNMENT, false)? + .visit_field::("layout_padding", Self::VT_LAYOUT_PADDING, false)? + .visit_field::("layout_main_axis_gap", Self::VT_LAYOUT_MAIN_AXIS_GAP, false)? + .visit_field::("layout_cross_axis_gap", Self::VT_LAYOUT_CROSS_AXIS_GAP, false)? + .finish(); + Ok(()) + } +} +pub struct LayoutContainerStyleArgs<'a> { + pub layout_mode: LayoutMode, + pub layout_direction: Axis, + pub layout_wrap: LayoutWrap, + pub layout_main_axis_alignment: MainAxisAlignment, + pub layout_cross_axis_alignment: CrossAxisAlignment, + pub layout_padding: Option<&'a EdgeInsets>, + pub layout_main_axis_gap: f32, + pub layout_cross_axis_gap: f32, +} +impl<'a> Default for LayoutContainerStyleArgs<'a> { + #[inline] + fn default() -> Self { + LayoutContainerStyleArgs { + layout_mode: LayoutMode::Normal, + layout_direction: Axis::Horizontal, + layout_wrap: LayoutWrap::None, + layout_main_axis_alignment: MainAxisAlignment::None, + layout_cross_axis_alignment: CrossAxisAlignment::None, + layout_padding: None, + layout_main_axis_gap: 0.0, + layout_cross_axis_gap: 0.0, + } + } +} + +pub struct LayoutContainerStyleBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> LayoutContainerStyleBuilder<'a, 'b, A> { + #[inline] + pub fn add_layout_mode(&mut self, layout_mode: LayoutMode) { + self.fbb_.push_slot::(LayoutContainerStyle::VT_LAYOUT_MODE, layout_mode, LayoutMode::Normal); + } + #[inline] + pub fn add_layout_direction(&mut self, layout_direction: Axis) { + self.fbb_.push_slot::(LayoutContainerStyle::VT_LAYOUT_DIRECTION, layout_direction, Axis::Horizontal); + } + #[inline] + pub fn add_layout_wrap(&mut self, layout_wrap: LayoutWrap) { + self.fbb_.push_slot::(LayoutContainerStyle::VT_LAYOUT_WRAP, layout_wrap, LayoutWrap::None); + } + #[inline] + pub fn add_layout_main_axis_alignment(&mut self, layout_main_axis_alignment: MainAxisAlignment) { + self.fbb_.push_slot::(LayoutContainerStyle::VT_LAYOUT_MAIN_AXIS_ALIGNMENT, layout_main_axis_alignment, MainAxisAlignment::None); + } + #[inline] + pub fn add_layout_cross_axis_alignment(&mut self, layout_cross_axis_alignment: CrossAxisAlignment) { + self.fbb_.push_slot::(LayoutContainerStyle::VT_LAYOUT_CROSS_AXIS_ALIGNMENT, layout_cross_axis_alignment, CrossAxisAlignment::None); + } + #[inline] + pub fn add_layout_padding(&mut self, layout_padding: &EdgeInsets) { + self.fbb_.push_slot_always::<&EdgeInsets>(LayoutContainerStyle::VT_LAYOUT_PADDING, layout_padding); + } + #[inline] + pub fn add_layout_main_axis_gap(&mut self, layout_main_axis_gap: f32) { + self.fbb_.push_slot::(LayoutContainerStyle::VT_LAYOUT_MAIN_AXIS_GAP, layout_main_axis_gap, 0.0); + } + #[inline] + pub fn add_layout_cross_axis_gap(&mut self, layout_cross_axis_gap: f32) { + self.fbb_.push_slot::(LayoutContainerStyle::VT_LAYOUT_CROSS_AXIS_GAP, layout_cross_axis_gap, 0.0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> LayoutContainerStyleBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + LayoutContainerStyleBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for LayoutContainerStyle<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("LayoutContainerStyle"); + ds.field("layout_mode", &self.layout_mode()); + ds.field("layout_direction", &self.layout_direction()); + ds.field("layout_wrap", &self.layout_wrap()); + ds.field("layout_main_axis_alignment", &self.layout_main_axis_alignment()); + ds.field("layout_cross_axis_alignment", &self.layout_cross_axis_alignment()); + ds.field("layout_padding", &self.layout_padding()); + ds.field("layout_main_axis_gap", &self.layout_main_axis_gap()); + ds.field("layout_cross_axis_gap", &self.layout_cross_axis_gap()); + ds.finish() + } +} +pub enum LayoutChildStyleOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct LayoutChildStyle<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for LayoutChildStyle<'a> { + type Inner = LayoutChildStyle<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> LayoutChildStyle<'a> { + pub const VT_LAYOUT_POSITIONING: ::flatbuffers::VOffsetT = 4; + pub const VT_LAYOUT_GROW: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + LayoutChildStyle { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args LayoutChildStyleArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = LayoutChildStyleBuilder::new(_fbb); + builder.add_layout_grow(args.layout_grow); + builder.add_layout_positioning(args.layout_positioning); + builder.finish() + } + + + #[inline] + pub fn layout_positioning(&self) -> LayoutPositioning { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutChildStyle::VT_LAYOUT_POSITIONING, Some(LayoutPositioning::Auto)).unwrap()} + } + #[inline] + pub fn layout_grow(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutChildStyle::VT_LAYOUT_GROW, Some(0.0)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for LayoutChildStyle<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("layout_positioning", Self::VT_LAYOUT_POSITIONING, false)? + .visit_field::("layout_grow", Self::VT_LAYOUT_GROW, false)? + .finish(); + Ok(()) + } +} +pub struct LayoutChildStyleArgs { + pub layout_positioning: LayoutPositioning, + pub layout_grow: f32, +} +impl<'a> Default for LayoutChildStyleArgs { + #[inline] + fn default() -> Self { + LayoutChildStyleArgs { + layout_positioning: LayoutPositioning::Auto, + layout_grow: 0.0, + } + } +} + +pub struct LayoutChildStyleBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> LayoutChildStyleBuilder<'a, 'b, A> { + #[inline] + pub fn add_layout_positioning(&mut self, layout_positioning: LayoutPositioning) { + self.fbb_.push_slot::(LayoutChildStyle::VT_LAYOUT_POSITIONING, layout_positioning, LayoutPositioning::Auto); + } + #[inline] + pub fn add_layout_grow(&mut self, layout_grow: f32) { + self.fbb_.push_slot::(LayoutChildStyle::VT_LAYOUT_GROW, layout_grow, 0.0); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> LayoutChildStyleBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + LayoutChildStyleBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for LayoutChildStyle<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("LayoutChildStyle"); + ds.field("layout_positioning", &self.layout_positioning()); + ds.field("layout_grow", &self.layout_grow()); + ds.finish() + } +} +pub enum LayoutStyleOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct LayoutStyle<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for LayoutStyle<'a> { + type Inner = LayoutStyle<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> LayoutStyle<'a> { + pub const VT_LAYOUT_POSITION_TYPE: ::flatbuffers::VOffsetT = 4; + pub const VT_LAYOUT_POSITION: ::flatbuffers::VOffsetT = 6; + pub const VT_LAYOUT_DIMENSIONS: ::flatbuffers::VOffsetT = 8; + pub const VT_LAYOUT_CONTAINER: ::flatbuffers::VOffsetT = 10; + pub const VT_LAYOUT_CHILD: ::flatbuffers::VOffsetT = 12; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + LayoutStyle { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args LayoutStyleArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = LayoutStyleBuilder::new(_fbb); + if let Some(x) = args.layout_child { builder.add_layout_child(x); } + if let Some(x) = args.layout_container { builder.add_layout_container(x); } + if let Some(x) = args.layout_dimensions { builder.add_layout_dimensions(x); } + if let Some(x) = args.layout_position { builder.add_layout_position(x); } + builder.add_layout_position_type(args.layout_position_type); + builder.finish() + } + + + #[inline] + pub fn layout_position_type(&self) -> LayoutPositioningBasis { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayoutStyle::VT_LAYOUT_POSITION_TYPE, Some(LayoutPositioningBasis::NONE)).unwrap()} + } + #[inline] + pub fn layout_position(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>(LayoutStyle::VT_LAYOUT_POSITION, None)} + } + #[inline] + pub fn layout_dimensions(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LayoutStyle::VT_LAYOUT_DIMENSIONS, None)} + } + #[inline] + pub fn layout_container(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LayoutStyle::VT_LAYOUT_CONTAINER, None)} + } + #[inline] + pub fn layout_child(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LayoutStyle::VT_LAYOUT_CHILD, None)} + } + #[inline] + #[allow(non_snake_case)] + pub fn layout_position_as_layout_positioning_cartesian(&self) -> Option> { + if self.layout_position_type() == LayoutPositioningBasis::LayoutPositioningCartesian { + self.layout_position().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { LayoutPositioningCartesian::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn layout_position_as_layout_positioning_inset(&self) -> Option> { + if self.layout_position_type() == LayoutPositioningBasis::LayoutPositioningInset { + self.layout_position().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { LayoutPositioningInset::init_from_table(t) } + }) + } else { + None + } + } + +} + +impl ::flatbuffers::Verifiable for LayoutStyle<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_union::("layout_position_type", Self::VT_LAYOUT_POSITION_TYPE, "layout_position", Self::VT_LAYOUT_POSITION, false, |key, v, pos| { + match key { + LayoutPositioningBasis::LayoutPositioningCartesian => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LayoutPositioningBasis::LayoutPositioningCartesian", pos), + LayoutPositioningBasis::LayoutPositioningInset => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LayoutPositioningBasis::LayoutPositioningInset", pos), + _ => Ok(()), + } + })? + .visit_field::<::flatbuffers::ForwardsUOffset>("layout_dimensions", Self::VT_LAYOUT_DIMENSIONS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("layout_container", Self::VT_LAYOUT_CONTAINER, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("layout_child", Self::VT_LAYOUT_CHILD, false)? + .finish(); + Ok(()) + } +} +pub struct LayoutStyleArgs<'a> { + pub layout_position_type: LayoutPositioningBasis, + pub layout_position: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, + pub layout_dimensions: Option<::flatbuffers::WIPOffset>>, + pub layout_container: Option<::flatbuffers::WIPOffset>>, + pub layout_child: Option<::flatbuffers::WIPOffset>>, +} +impl<'a> Default for LayoutStyleArgs<'a> { + #[inline] + fn default() -> Self { + LayoutStyleArgs { + layout_position_type: LayoutPositioningBasis::NONE, + layout_position: None, + layout_dimensions: None, + layout_container: None, + layout_child: None, + } + } +} + +pub struct LayoutStyleBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> LayoutStyleBuilder<'a, 'b, A> { + #[inline] + pub fn add_layout_position_type(&mut self, layout_position_type: LayoutPositioningBasis) { + self.fbb_.push_slot::(LayoutStyle::VT_LAYOUT_POSITION_TYPE, layout_position_type, LayoutPositioningBasis::NONE); + } + #[inline] + pub fn add_layout_position(&mut self, layout_position: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(LayoutStyle::VT_LAYOUT_POSITION, layout_position); + } + #[inline] + pub fn add_layout_dimensions(&mut self, layout_dimensions: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LayoutStyle::VT_LAYOUT_DIMENSIONS, layout_dimensions); + } + #[inline] + pub fn add_layout_container(&mut self, layout_container: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LayoutStyle::VT_LAYOUT_CONTAINER, layout_container); + } + #[inline] + pub fn add_layout_child(&mut self, layout_child: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LayoutStyle::VT_LAYOUT_CHILD, layout_child); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> LayoutStyleBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + LayoutStyleBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for LayoutStyle<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("LayoutStyle"); + ds.field("layout_position_type", &self.layout_position_type()); + match self.layout_position_type() { + LayoutPositioningBasis::LayoutPositioningCartesian => { + if let Some(x) = self.layout_position_as_layout_positioning_cartesian() { + ds.field("layout_position", &x) + } else { + ds.field("layout_position", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + LayoutPositioningBasis::LayoutPositioningInset => { + if let Some(x) = self.layout_position_as_layout_positioning_inset() { + ds.field("layout_position", &x) + } else { + ds.field("layout_position", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + _ => { + let x: Option<()> = None; + ds.field("layout_position", &x) + }, + }; + ds.field("layout_dimensions", &self.layout_dimensions()); + ds.field("layout_container", &self.layout_container()); + ds.field("layout_child", &self.layout_child()); + ds.finish() + } +} +pub enum TextSpanNodePropertiesOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct TextSpanNodeProperties<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for TextSpanNodeProperties<'a> { + type Inner = TextSpanNodeProperties<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> TextSpanNodeProperties<'a> { + pub const VT_STROKE_GEOMETRY: ::flatbuffers::VOffsetT = 4; + pub const VT_FILL_PAINTS: ::flatbuffers::VOffsetT = 6; + pub const VT_STROKE_PAINTS: ::flatbuffers::VOffsetT = 8; + pub const VT_TEXT: ::flatbuffers::VOffsetT = 10; + pub const VT_TEXT_STYLE: ::flatbuffers::VOffsetT = 12; + pub const VT_TEXT_ALIGN: ::flatbuffers::VOffsetT = 14; + pub const VT_TEXT_ALIGN_VERTICAL: ::flatbuffers::VOffsetT = 16; + pub const VT_MAX_LINES: ::flatbuffers::VOffsetT = 18; + pub const VT_ELLIPSIS: ::flatbuffers::VOffsetT = 20; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + TextSpanNodeProperties { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args TextSpanNodePropertiesArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = TextSpanNodePropertiesBuilder::new(_fbb); + if let Some(x) = args.ellipsis { builder.add_ellipsis(x); } + builder.add_max_lines(args.max_lines); + if let Some(x) = args.text_style { builder.add_text_style(x); } + if let Some(x) = args.text { builder.add_text(x); } + if let Some(x) = args.stroke_paints { builder.add_stroke_paints(x); } + if let Some(x) = args.fill_paints { builder.add_fill_paints(x); } + if let Some(x) = args.stroke_geometry { builder.add_stroke_geometry(x); } + builder.add_text_align_vertical(args.text_align_vertical); + builder.add_text_align(args.text_align); + builder.finish() + } + + + #[inline] + pub fn stroke_geometry(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(TextSpanNodeProperties::VT_STROKE_GEOMETRY, None)} + } + #[inline] + pub fn fill_paints(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(TextSpanNodeProperties::VT_FILL_PAINTS, None)} + } + #[inline] + pub fn stroke_paints(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(TextSpanNodeProperties::VT_STROKE_PAINTS, None)} + } + #[inline] + pub fn text(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(TextSpanNodeProperties::VT_TEXT, None)} + } + #[inline] + pub fn text_style(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(TextSpanNodeProperties::VT_TEXT_STYLE, None)} + } + #[inline] + pub fn text_align(&self) -> TextAlign { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextSpanNodeProperties::VT_TEXT_ALIGN, Some(TextAlign::Left)).unwrap()} + } + #[inline] + pub fn text_align_vertical(&self) -> TextAlignVertical { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextSpanNodeProperties::VT_TEXT_ALIGN_VERTICAL, Some(TextAlignVertical::Top)).unwrap()} + } + #[inline] + pub fn max_lines(&self) -> u32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TextSpanNodeProperties::VT_MAX_LINES, Some(0)).unwrap()} + } + #[inline] + pub fn ellipsis(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(TextSpanNodeProperties::VT_ELLIPSIS, None)} + } +} + +impl ::flatbuffers::Verifiable for TextSpanNodeProperties<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("stroke_geometry", Self::VT_STROKE_GEOMETRY, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("fill_paints", Self::VT_FILL_PAINTS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("stroke_paints", Self::VT_STROKE_PAINTS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("text", Self::VT_TEXT, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("text_style", Self::VT_TEXT_STYLE, false)? + .visit_field::("text_align", Self::VT_TEXT_ALIGN, false)? + .visit_field::("text_align_vertical", Self::VT_TEXT_ALIGN_VERTICAL, false)? + .visit_field::("max_lines", Self::VT_MAX_LINES, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("ellipsis", Self::VT_ELLIPSIS, false)? + .finish(); + Ok(()) + } +} +pub struct TextSpanNodePropertiesArgs<'a> { + pub stroke_geometry: Option<::flatbuffers::WIPOffset>>, + pub fill_paints: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub stroke_paints: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub text: Option<::flatbuffers::WIPOffset<&'a str>>, + pub text_style: Option<::flatbuffers::WIPOffset>>, + pub text_align: TextAlign, + pub text_align_vertical: TextAlignVertical, + pub max_lines: u32, + pub ellipsis: Option<::flatbuffers::WIPOffset<&'a str>>, +} +impl<'a> Default for TextSpanNodePropertiesArgs<'a> { + #[inline] + fn default() -> Self { + TextSpanNodePropertiesArgs { + stroke_geometry: None, + fill_paints: None, + stroke_paints: None, + text: None, + text_style: None, + text_align: TextAlign::Left, + text_align_vertical: TextAlignVertical::Top, + max_lines: 0, + ellipsis: None, + } + } +} + +pub struct TextSpanNodePropertiesBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> TextSpanNodePropertiesBuilder<'a, 'b, A> { + #[inline] + pub fn add_stroke_geometry(&mut self, stroke_geometry: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(TextSpanNodeProperties::VT_STROKE_GEOMETRY, stroke_geometry); + } + #[inline] + pub fn add_fill_paints(&mut self, fill_paints: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(TextSpanNodeProperties::VT_FILL_PAINTS, fill_paints); + } + #[inline] + pub fn add_stroke_paints(&mut self, stroke_paints: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(TextSpanNodeProperties::VT_STROKE_PAINTS, stroke_paints); + } + #[inline] + pub fn add_text(&mut self, text: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(TextSpanNodeProperties::VT_TEXT, text); + } + #[inline] + pub fn add_text_style(&mut self, text_style: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(TextSpanNodeProperties::VT_TEXT_STYLE, text_style); + } + #[inline] + pub fn add_text_align(&mut self, text_align: TextAlign) { + self.fbb_.push_slot::(TextSpanNodeProperties::VT_TEXT_ALIGN, text_align, TextAlign::Left); + } + #[inline] + pub fn add_text_align_vertical(&mut self, text_align_vertical: TextAlignVertical) { + self.fbb_.push_slot::(TextSpanNodeProperties::VT_TEXT_ALIGN_VERTICAL, text_align_vertical, TextAlignVertical::Top); + } + #[inline] + pub fn add_max_lines(&mut self, max_lines: u32) { + self.fbb_.push_slot::(TextSpanNodeProperties::VT_MAX_LINES, max_lines, 0); + } + #[inline] + pub fn add_ellipsis(&mut self, ellipsis: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(TextSpanNodeProperties::VT_ELLIPSIS, ellipsis); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> TextSpanNodePropertiesBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + TextSpanNodePropertiesBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for TextSpanNodeProperties<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("TextSpanNodeProperties"); + ds.field("stroke_geometry", &self.stroke_geometry()); + ds.field("fill_paints", &self.fill_paints()); + ds.field("stroke_paints", &self.stroke_paints()); + ds.field("text", &self.text()); + ds.field("text_style", &self.text_style()); + ds.field("text_align", &self.text_align()); + ds.field("text_align_vertical", &self.text_align_vertical()); + ds.field("max_lines", &self.max_lines()); + ds.field("ellipsis", &self.ellipsis()); + ds.finish() + } +} +pub enum SystemNodeTraitOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Universal node trait. +pub struct SystemNodeTrait<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for SystemNodeTrait<'a> { + type Inner = SystemNodeTrait<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> SystemNodeTrait<'a> { + pub const VT_ID: ::flatbuffers::VOffsetT = 4; + pub const VT_ACTIVE: ::flatbuffers::VOffsetT = 6; + pub const VT_NAME: ::flatbuffers::VOffsetT = 8; + pub const VT_LOCKED: ::flatbuffers::VOffsetT = 10; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + SystemNodeTrait { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args SystemNodeTraitArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = SystemNodeTraitBuilder::new(_fbb); + if let Some(x) = args.name { builder.add_name(x); } + if let Some(x) = args.id { builder.add_id(x); } + builder.add_locked(args.locked); + builder.add_active(args.active); + builder.finish() + } + + + /// unique identifier for the node. (required) + #[inline] + pub fn id(&self) -> NodeIdentifier<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(SystemNodeTrait::VT_ID, None).unwrap()} + } + /// whether the node is active. (visible, active) + #[inline] + pub fn active(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(SystemNodeTrait::VT_ACTIVE, Some(true)).unwrap()} + } + /// name of the node. (optional) + #[inline] + pub fn name(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(SystemNodeTrait::VT_NAME, None)} + } + /// whether the node is locked. (locked, editor) + #[inline] + pub fn locked(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(SystemNodeTrait::VT_LOCKED, Some(false)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for SystemNodeTrait<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("id", Self::VT_ID, true)? + .visit_field::("active", Self::VT_ACTIVE, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("name", Self::VT_NAME, false)? + .visit_field::("locked", Self::VT_LOCKED, false)? + .finish(); + Ok(()) + } +} +pub struct SystemNodeTraitArgs<'a> { + pub id: Option<::flatbuffers::WIPOffset>>, + pub active: bool, + pub name: Option<::flatbuffers::WIPOffset<&'a str>>, + pub locked: bool, +} +impl<'a> Default for SystemNodeTraitArgs<'a> { + #[inline] + fn default() -> Self { + SystemNodeTraitArgs { + id: None, // required field + active: true, + name: None, + locked: false, + } + } +} + +pub struct SystemNodeTraitBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> SystemNodeTraitBuilder<'a, 'b, A> { + #[inline] + pub fn add_id(&mut self, id: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(SystemNodeTrait::VT_ID, id); + } + #[inline] + pub fn add_active(&mut self, active: bool) { + self.fbb_.push_slot::(SystemNodeTrait::VT_ACTIVE, active, true); + } + #[inline] + pub fn add_name(&mut self, name: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(SystemNodeTrait::VT_NAME, name); + } + #[inline] + pub fn add_locked(&mut self, locked: bool) { + self.fbb_.push_slot::(SystemNodeTrait::VT_LOCKED, locked, false); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> SystemNodeTraitBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + SystemNodeTraitBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, SystemNodeTrait::VT_ID,"id"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for SystemNodeTrait<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("SystemNodeTrait"); + ds.field("id", &self.id()); + ds.field("active", &self.active()); + ds.field("name", &self.name()); + ds.field("locked", &self.locked()); + ds.finish() + } +} +pub enum LayerTraitOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Shared layer fields used by all layer-node variants. +/// Layer is what usually user think of as a node. each layer is non-virtual, a real render target. +pub struct LayerTrait<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for LayerTrait<'a> { + type Inner = LayerTrait<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> LayerTrait<'a> { + pub const VT_PARENT: ::flatbuffers::VOffsetT = 4; + pub const VT_OPACITY: ::flatbuffers::VOffsetT = 6; + pub const VT_BLEND_MODE: ::flatbuffers::VOffsetT = 8; + pub const VT_MASK_TYPE_TYPE: ::flatbuffers::VOffsetT = 10; + pub const VT_MASK_TYPE: ::flatbuffers::VOffsetT = 12; + pub const VT_EFFECTS: ::flatbuffers::VOffsetT = 14; + pub const VT_LAYOUT: ::flatbuffers::VOffsetT = 16; + pub const VT_POST_LAYOUT_TRANSFORM: ::flatbuffers::VOffsetT = 18; + pub const VT_POST_LAYOUT_TRANSFORM_ORIGIN: ::flatbuffers::VOffsetT = 20; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + LayerTrait { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args LayerTraitArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = LayerTraitBuilder::new(_fbb); + if let Some(x) = args.post_layout_transform_origin { builder.add_post_layout_transform_origin(x); } + if let Some(x) = args.post_layout_transform { builder.add_post_layout_transform(x); } + if let Some(x) = args.layout { builder.add_layout(x); } + if let Some(x) = args.effects { builder.add_effects(x); } + if let Some(x) = args.mask_type { builder.add_mask_type(x); } + builder.add_opacity(args.opacity); + if let Some(x) = args.parent { builder.add_parent(x); } + builder.add_mask_type_type(args.mask_type_type); + builder.add_blend_mode(args.blend_mode); + builder.finish() + } + + + /// Parent reference (optional; root nodes omit this). + /// + /// When present, this node is a child of the referenced parent. + /// Children are ordered by `position` (lexicographic sort). + /// + /// Reference: Aligned with Figma's `ParentIndex` pattern (fig.kiwi). + /// This replaces the previous `children:[NodeIdentifier]` array model. + /// + /// To compute children of a parent node: + /// 1. Filter all nodes where `parent.parent_id == parent.id` + /// 2. Sort by `parent.position` (lexicographic comparison) + #[inline] + pub fn parent(&self) -> ParentReference<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LayerTrait::VT_PARENT, None).unwrap()} + } + /// opacity of the layer. + #[inline] + pub fn opacity(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayerTrait::VT_OPACITY, Some(1.0)).unwrap()} + } + /// Blend mode (archive model). + /// + /// Default is `pass_through`. + #[inline] + pub fn blend_mode(&self) -> LayerBlendMode { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayerTrait::VT_BLEND_MODE, Some(LayerBlendMode::PassThrough)).unwrap()} + } + #[inline] + pub fn mask_type_type(&self) -> LayerMaskType { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayerTrait::VT_MASK_TYPE_TYPE, Some(LayerMaskType::NONE)).unwrap()} + } + /// Rust: `LayerMaskType` (union; NONE means the node is not a mask) + #[inline] + pub fn mask_type(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>(LayerTrait::VT_MASK_TYPE, None)} + } + /// layer effects. + #[inline] + pub fn effects(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LayerTrait::VT_EFFECTS, None)} + } + /// Geometry transform baseline (identity by default). + /// Layout (optional, depending on node type / usage). + #[inline] + pub fn layout(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LayerTrait::VT_LAYOUT, None)} + } + /// post-layout transform, this reflects how css transform is applied after the layout is resolved. this is currently how grida handles rotation. in the future, this might change. + #[inline] + pub fn post_layout_transform(&self) -> Option<&'a CGTransform2D> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayerTrait::VT_POST_LAYOUT_TRANSFORM, None)} + } + #[inline] + pub fn post_layout_transform_origin(&self) -> Option<&'a Alignment> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LayerTrait::VT_POST_LAYOUT_TRANSFORM_ORIGIN, None)} + } + #[inline] + #[allow(non_snake_case)] + pub fn mask_type_as_layer_mask_type_image(&self) -> Option> { + if self.mask_type_type() == LayerMaskType::LayerMaskTypeImage { + self.mask_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { LayerMaskTypeImage::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn mask_type_as_layer_mask_type_geometry(&self) -> Option> { + if self.mask_type_type() == LayerMaskType::LayerMaskTypeGeometry { + self.mask_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { LayerMaskTypeGeometry::init_from_table(t) } + }) + } else { + None + } + } + +} + +impl ::flatbuffers::Verifiable for LayerTrait<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("parent", Self::VT_PARENT, true)? + .visit_field::("opacity", Self::VT_OPACITY, false)? + .visit_field::("blend_mode", Self::VT_BLEND_MODE, false)? + .visit_union::("mask_type_type", Self::VT_MASK_TYPE_TYPE, "mask_type", Self::VT_MASK_TYPE, false, |key, v, pos| { + match key { + LayerMaskType::LayerMaskTypeImage => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LayerMaskType::LayerMaskTypeImage", pos), + LayerMaskType::LayerMaskTypeGeometry => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LayerMaskType::LayerMaskTypeGeometry", pos), + _ => Ok(()), + } + })? + .visit_field::<::flatbuffers::ForwardsUOffset>("effects", Self::VT_EFFECTS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("layout", Self::VT_LAYOUT, false)? + .visit_field::("post_layout_transform", Self::VT_POST_LAYOUT_TRANSFORM, false)? + .visit_field::("post_layout_transform_origin", Self::VT_POST_LAYOUT_TRANSFORM_ORIGIN, false)? + .finish(); + Ok(()) + } +} +pub struct LayerTraitArgs<'a> { + pub parent: Option<::flatbuffers::WIPOffset>>, + pub opacity: f32, + pub blend_mode: LayerBlendMode, + pub mask_type_type: LayerMaskType, + pub mask_type: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, + pub effects: Option<::flatbuffers::WIPOffset>>, + pub layout: Option<::flatbuffers::WIPOffset>>, + pub post_layout_transform: Option<&'a CGTransform2D>, + pub post_layout_transform_origin: Option<&'a Alignment>, +} +impl<'a> Default for LayerTraitArgs<'a> { + #[inline] + fn default() -> Self { + LayerTraitArgs { + parent: None, // required field + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask_type_type: LayerMaskType::NONE, + mask_type: None, + effects: None, + layout: None, + post_layout_transform: None, + post_layout_transform_origin: None, + } + } +} + +pub struct LayerTraitBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> LayerTraitBuilder<'a, 'b, A> { + #[inline] + pub fn add_parent(&mut self, parent: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LayerTrait::VT_PARENT, parent); + } + #[inline] + pub fn add_opacity(&mut self, opacity: f32) { + self.fbb_.push_slot::(LayerTrait::VT_OPACITY, opacity, 1.0); + } + #[inline] + pub fn add_blend_mode(&mut self, blend_mode: LayerBlendMode) { + self.fbb_.push_slot::(LayerTrait::VT_BLEND_MODE, blend_mode, LayerBlendMode::PassThrough); + } + #[inline] + pub fn add_mask_type_type(&mut self, mask_type_type: LayerMaskType) { + self.fbb_.push_slot::(LayerTrait::VT_MASK_TYPE_TYPE, mask_type_type, LayerMaskType::NONE); + } + #[inline] + pub fn add_mask_type(&mut self, mask_type: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(LayerTrait::VT_MASK_TYPE, mask_type); + } + #[inline] + pub fn add_effects(&mut self, effects: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LayerTrait::VT_EFFECTS, effects); + } + #[inline] + pub fn add_layout(&mut self, layout: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LayerTrait::VT_LAYOUT, layout); + } + #[inline] + pub fn add_post_layout_transform(&mut self, post_layout_transform: &CGTransform2D) { + self.fbb_.push_slot_always::<&CGTransform2D>(LayerTrait::VT_POST_LAYOUT_TRANSFORM, post_layout_transform); + } + #[inline] + pub fn add_post_layout_transform_origin(&mut self, post_layout_transform_origin: &Alignment) { + self.fbb_.push_slot_always::<&Alignment>(LayerTrait::VT_POST_LAYOUT_TRANSFORM_ORIGIN, post_layout_transform_origin); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> LayerTraitBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + LayerTraitBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, LayerTrait::VT_PARENT,"parent"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for LayerTrait<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("LayerTrait"); + ds.field("parent", &self.parent()); + ds.field("opacity", &self.opacity()); + ds.field("blend_mode", &self.blend_mode()); + ds.field("mask_type_type", &self.mask_type_type()); + match self.mask_type_type() { + LayerMaskType::LayerMaskTypeImage => { + if let Some(x) = self.mask_type_as_layer_mask_type_image() { + ds.field("mask_type", &x) + } else { + ds.field("mask_type", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + LayerMaskType::LayerMaskTypeGeometry => { + if let Some(x) = self.mask_type_as_layer_mask_type_geometry() { + ds.field("mask_type", &x) + } else { + ds.field("mask_type", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + _ => { + let x: Option<()> = None; + ds.field("mask_type", &x) + }, + }; + ds.field("effects", &self.effects()); + ds.field("layout", &self.layout()); + ds.field("post_layout_transform", &self.post_layout_transform()); + ds.field("post_layout_transform_origin", &self.post_layout_transform_origin()); + ds.finish() + } +} +pub enum UnknownNodeOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Placeholder, unused. +pub struct UnknownNode<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for UnknownNode<'a> { + type Inner = UnknownNode<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> UnknownNode<'a> { + pub const VT_NODE: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + UnknownNode { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args UnknownNodeArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = UnknownNodeBuilder::new(_fbb); + if let Some(x) = args.node { builder.add_node(x); } + builder.finish() + } + + + #[inline] + pub fn node(&self) -> SystemNodeTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(UnknownNode::VT_NODE, None).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for UnknownNode<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("node", Self::VT_NODE, true)? + .finish(); + Ok(()) + } +} +pub struct UnknownNodeArgs<'a> { + pub node: Option<::flatbuffers::WIPOffset>>, +} +impl<'a> Default for UnknownNodeArgs<'a> { + #[inline] + fn default() -> Self { + UnknownNodeArgs { + node: None, // required field + } + } +} + +pub struct UnknownNodeBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> UnknownNodeBuilder<'a, 'b, A> { + #[inline] + pub fn add_node(&mut self, node: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(UnknownNode::VT_NODE, node); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> UnknownNodeBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + UnknownNodeBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, UnknownNode::VT_NODE,"node"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for UnknownNode<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("UnknownNode"); + ds.field("node", &self.node()); + ds.finish() + } +} +pub enum SceneNodeOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Node variant: Scene. +/// +/// SceneNode is special and doesn't use NodeCommon like other nodes. +/// It inlines only the relevant fields from NodeCommon. +pub struct SceneNode<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for SceneNode<'a> { + type Inner = SceneNode<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> SceneNode<'a> { + pub const VT_NODE: ::flatbuffers::VOffsetT = 4; + pub const VT_CONSTRAINTS_CHILDREN: ::flatbuffers::VOffsetT = 6; + pub const VT_SCENE_BACKGROUND_COLOR: ::flatbuffers::VOffsetT = 8; + pub const VT_GUIDES: ::flatbuffers::VOffsetT = 10; + pub const VT_EDGES: ::flatbuffers::VOffsetT = 12; + pub const VT_POSITION: ::flatbuffers::VOffsetT = 14; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + SceneNode { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args SceneNodeArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = SceneNodeBuilder::new(_fbb); + if let Some(x) = args.position { builder.add_position(x); } + if let Some(x) = args.edges { builder.add_edges(x); } + if let Some(x) = args.guides { builder.add_guides(x); } + if let Some(x) = args.scene_background_color { builder.add_scene_background_color(x); } + if let Some(x) = args.node { builder.add_node(x); } + builder.add_constraints_children(args.constraints_children); + builder.finish() + } + + + #[inline] + pub fn node(&self) -> SystemNodeTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(SceneNode::VT_NODE, None).unwrap()} + } + /// Scene-specific properties. + #[inline] + pub fn constraints_children(&self) -> SceneConstraintsChildren { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(SceneNode::VT_CONSTRAINTS_CHILDREN, Some(SceneConstraintsChildren::Single)).unwrap()} + } + /// Scene background color (solid color only, RGBA32F). + /// + /// This is a simple solid color background. For gradient or image backgrounds, + /// use a background container node instead. + #[inline] + pub fn scene_background_color(&self) -> Option<&'a RGBA32F> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(SceneNode::VT_SCENE_BACKGROUND_COLOR, None)} + } + #[inline] + pub fn guides(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(SceneNode::VT_GUIDES, None)} + } + #[inline] + pub fn edges(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(SceneNode::VT_EDGES, None)} + } + /// Fractional index position string for ordering among siblings. + /// Empty string means "unsorted" or "default position". + /// Children are sorted by lexicographic comparison of position strings. + #[inline] + pub fn position(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(SceneNode::VT_POSITION, None)} + } +} + +impl ::flatbuffers::Verifiable for SceneNode<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("node", Self::VT_NODE, true)? + .visit_field::("constraints_children", Self::VT_CONSTRAINTS_CHILDREN, false)? + .visit_field::("scene_background_color", Self::VT_SCENE_BACKGROUND_COLOR, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("guides", Self::VT_GUIDES, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("edges", Self::VT_EDGES, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("position", Self::VT_POSITION, false)? + .finish(); + Ok(()) + } +} +pub struct SceneNodeArgs<'a> { + pub node: Option<::flatbuffers::WIPOffset>>, + pub constraints_children: SceneConstraintsChildren, + pub scene_background_color: Option<&'a RGBA32F>, + pub guides: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub edges: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub position: Option<::flatbuffers::WIPOffset<&'a str>>, +} +impl<'a> Default for SceneNodeArgs<'a> { + #[inline] + fn default() -> Self { + SceneNodeArgs { + node: None, // required field + constraints_children: SceneConstraintsChildren::Single, + scene_background_color: None, + guides: None, + edges: None, + position: None, + } + } +} + +pub struct SceneNodeBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> SceneNodeBuilder<'a, 'b, A> { + #[inline] + pub fn add_node(&mut self, node: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(SceneNode::VT_NODE, node); + } + #[inline] + pub fn add_constraints_children(&mut self, constraints_children: SceneConstraintsChildren) { + self.fbb_.push_slot::(SceneNode::VT_CONSTRAINTS_CHILDREN, constraints_children, SceneConstraintsChildren::Single); + } + #[inline] + pub fn add_scene_background_color(&mut self, scene_background_color: &RGBA32F) { + self.fbb_.push_slot_always::<&RGBA32F>(SceneNode::VT_SCENE_BACKGROUND_COLOR, scene_background_color); + } + #[inline] + pub fn add_guides(&mut self, guides: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(SceneNode::VT_GUIDES, guides); + } + #[inline] + pub fn add_edges(&mut self, edges: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(SceneNode::VT_EDGES, edges); + } + #[inline] + pub fn add_position(&mut self, position: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(SceneNode::VT_POSITION, position); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> SceneNodeBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + SceneNodeBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, SceneNode::VT_NODE,"node"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for SceneNode<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("SceneNode"); + ds.field("node", &self.node()); + ds.field("constraints_children", &self.constraints_children()); + ds.field("scene_background_color", &self.scene_background_color()); + ds.field("guides", &self.guides()); + ds.field("edges", &self.edges()); + ds.field("position", &self.position()); + ds.finish() + } +} +pub enum InitialContainerNodeOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Node variant: Initial container. +pub struct InitialContainerNode<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for InitialContainerNode<'a> { + type Inner = InitialContainerNode<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> InitialContainerNode<'a> { + pub const VT_NODE: ::flatbuffers::VOffsetT = 4; + pub const VT_LAYER: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + InitialContainerNode { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args InitialContainerNodeArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = InitialContainerNodeBuilder::new(_fbb); + if let Some(x) = args.layer { builder.add_layer(x); } + if let Some(x) = args.node { builder.add_node(x); } + builder.finish() + } + + + #[inline] + pub fn node(&self) -> SystemNodeTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(InitialContainerNode::VT_NODE, None).unwrap()} + } + #[inline] + pub fn layer(&self) -> LayerTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(InitialContainerNode::VT_LAYER, None).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for InitialContainerNode<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("node", Self::VT_NODE, true)? + .visit_field::<::flatbuffers::ForwardsUOffset>("layer", Self::VT_LAYER, true)? + .finish(); + Ok(()) + } +} +pub struct InitialContainerNodeArgs<'a> { + pub node: Option<::flatbuffers::WIPOffset>>, + pub layer: Option<::flatbuffers::WIPOffset>>, +} +impl<'a> Default for InitialContainerNodeArgs<'a> { + #[inline] + fn default() -> Self { + InitialContainerNodeArgs { + node: None, // required field + layer: None, // required field + } + } +} + +pub struct InitialContainerNodeBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> InitialContainerNodeBuilder<'a, 'b, A> { + #[inline] + pub fn add_node(&mut self, node: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(InitialContainerNode::VT_NODE, node); + } + #[inline] + pub fn add_layer(&mut self, layer: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(InitialContainerNode::VT_LAYER, layer); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> InitialContainerNodeBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + InitialContainerNodeBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, InitialContainerNode::VT_NODE,"node"); + self.fbb_.required(o, InitialContainerNode::VT_LAYER,"layer"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for InitialContainerNode<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("InitialContainerNode"); + ds.field("node", &self.node()); + ds.field("layer", &self.layer()); + ds.finish() + } +} +pub enum ContainerNodeOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Node variant: Container. +pub struct ContainerNode<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for ContainerNode<'a> { + type Inner = ContainerNode<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> ContainerNode<'a> { + pub const VT_NODE: ::flatbuffers::VOffsetT = 4; + pub const VT_LAYER: ::flatbuffers::VOffsetT = 6; + pub const VT_STROKE_GEOMETRY: ::flatbuffers::VOffsetT = 8; + pub const VT_CORNER_RADIUS: ::flatbuffers::VOffsetT = 10; + pub const VT_FILL_PAINTS: ::flatbuffers::VOffsetT = 12; + pub const VT_STROKE_PAINTS: ::flatbuffers::VOffsetT = 14; + pub const VT_CLIPS_CONTENT: ::flatbuffers::VOffsetT = 16; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + ContainerNode { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args ContainerNodeArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = ContainerNodeBuilder::new(_fbb); + if let Some(x) = args.stroke_paints { builder.add_stroke_paints(x); } + if let Some(x) = args.fill_paints { builder.add_fill_paints(x); } + if let Some(x) = args.corner_radius { builder.add_corner_radius(x); } + if let Some(x) = args.stroke_geometry { builder.add_stroke_geometry(x); } + if let Some(x) = args.layer { builder.add_layer(x); } + if let Some(x) = args.node { builder.add_node(x); } + builder.add_clips_content(args.clips_content); + builder.finish() + } + + + #[inline] + pub fn node(&self) -> SystemNodeTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(ContainerNode::VT_NODE, None).unwrap()} + } + #[inline] + pub fn layer(&self) -> LayerTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(ContainerNode::VT_LAYER, None).unwrap()} + } + #[inline] + pub fn stroke_geometry(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(ContainerNode::VT_STROKE_GEOMETRY, None)} + } + #[inline] + pub fn corner_radius(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(ContainerNode::VT_CORNER_RADIUS, None)} + } + #[inline] + pub fn fill_paints(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(ContainerNode::VT_FILL_PAINTS, None)} + } + #[inline] + pub fn stroke_paints(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(ContainerNode::VT_STROKE_PAINTS, None)} + } + /// Content-only clip flag (children only). + #[inline] + pub fn clips_content(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ContainerNode::VT_CLIPS_CONTENT, Some(false)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for ContainerNode<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("node", Self::VT_NODE, true)? + .visit_field::<::flatbuffers::ForwardsUOffset>("layer", Self::VT_LAYER, true)? + .visit_field::<::flatbuffers::ForwardsUOffset>("stroke_geometry", Self::VT_STROKE_GEOMETRY, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("corner_radius", Self::VT_CORNER_RADIUS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("fill_paints", Self::VT_FILL_PAINTS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("stroke_paints", Self::VT_STROKE_PAINTS, false)? + .visit_field::("clips_content", Self::VT_CLIPS_CONTENT, false)? + .finish(); + Ok(()) + } +} +pub struct ContainerNodeArgs<'a> { + pub node: Option<::flatbuffers::WIPOffset>>, + pub layer: Option<::flatbuffers::WIPOffset>>, + pub stroke_geometry: Option<::flatbuffers::WIPOffset>>, + pub corner_radius: Option<::flatbuffers::WIPOffset>>, + pub fill_paints: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub stroke_paints: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub clips_content: bool, +} +impl<'a> Default for ContainerNodeArgs<'a> { + #[inline] + fn default() -> Self { + ContainerNodeArgs { + node: None, // required field + layer: None, // required field + stroke_geometry: None, + corner_radius: None, + fill_paints: None, + stroke_paints: None, + clips_content: false, + } + } +} + +pub struct ContainerNodeBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> ContainerNodeBuilder<'a, 'b, A> { + #[inline] + pub fn add_node(&mut self, node: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(ContainerNode::VT_NODE, node); + } + #[inline] + pub fn add_layer(&mut self, layer: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(ContainerNode::VT_LAYER, layer); + } + #[inline] + pub fn add_stroke_geometry(&mut self, stroke_geometry: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(ContainerNode::VT_STROKE_GEOMETRY, stroke_geometry); + } + #[inline] + pub fn add_corner_radius(&mut self, corner_radius: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(ContainerNode::VT_CORNER_RADIUS, corner_radius); + } + #[inline] + pub fn add_fill_paints(&mut self, fill_paints: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(ContainerNode::VT_FILL_PAINTS, fill_paints); + } + #[inline] + pub fn add_stroke_paints(&mut self, stroke_paints: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(ContainerNode::VT_STROKE_PAINTS, stroke_paints); + } + #[inline] + pub fn add_clips_content(&mut self, clips_content: bool) { + self.fbb_.push_slot::(ContainerNode::VT_CLIPS_CONTENT, clips_content, false); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> ContainerNodeBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + ContainerNodeBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, ContainerNode::VT_NODE,"node"); + self.fbb_.required(o, ContainerNode::VT_LAYER,"layer"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for ContainerNode<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("ContainerNode"); + ds.field("node", &self.node()); + ds.field("layer", &self.layer()); + ds.field("stroke_geometry", &self.stroke_geometry()); + ds.field("corner_radius", &self.corner_radius()); + ds.field("fill_paints", &self.fill_paints()); + ds.field("stroke_paints", &self.stroke_paints()); + ds.field("clips_content", &self.clips_content()); + ds.finish() + } +} +pub enum GroupNodeOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Node variant: Group. +pub struct GroupNode<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for GroupNode<'a> { + type Inner = GroupNode<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> GroupNode<'a> { + pub const VT_NODE: ::flatbuffers::VOffsetT = 4; + pub const VT_LAYER: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + GroupNode { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args GroupNodeArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = GroupNodeBuilder::new(_fbb); + if let Some(x) = args.layer { builder.add_layer(x); } + if let Some(x) = args.node { builder.add_node(x); } + builder.finish() + } + + + #[inline] + pub fn node(&self) -> SystemNodeTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(GroupNode::VT_NODE, None).unwrap()} + } + #[inline] + pub fn layer(&self) -> LayerTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(GroupNode::VT_LAYER, None).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for GroupNode<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("node", Self::VT_NODE, true)? + .visit_field::<::flatbuffers::ForwardsUOffset>("layer", Self::VT_LAYER, true)? + .finish(); + Ok(()) + } +} +pub struct GroupNodeArgs<'a> { + pub node: Option<::flatbuffers::WIPOffset>>, + pub layer: Option<::flatbuffers::WIPOffset>>, +} +impl<'a> Default for GroupNodeArgs<'a> { + #[inline] + fn default() -> Self { + GroupNodeArgs { + node: None, // required field + layer: None, // required field + } + } +} + +pub struct GroupNodeBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> GroupNodeBuilder<'a, 'b, A> { + #[inline] + pub fn add_node(&mut self, node: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(GroupNode::VT_NODE, node); + } + #[inline] + pub fn add_layer(&mut self, layer: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(GroupNode::VT_LAYER, layer); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> GroupNodeBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + GroupNodeBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, GroupNode::VT_NODE,"node"); + self.fbb_.required(o, GroupNode::VT_LAYER,"layer"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for GroupNode<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("GroupNode"); + ds.field("node", &self.node()); + ds.field("layer", &self.layer()); + ds.finish() + } +} +pub enum BooleanOperationNodeOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Node variant: Boolean operation. +pub struct BooleanOperationNode<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for BooleanOperationNode<'a> { + type Inner = BooleanOperationNode<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> BooleanOperationNode<'a> { + pub const VT_NODE: ::flatbuffers::VOffsetT = 4; + pub const VT_LAYER: ::flatbuffers::VOffsetT = 6; + pub const VT_OP: ::flatbuffers::VOffsetT = 8; + pub const VT_CORNER_RADIUS: ::flatbuffers::VOffsetT = 10; + pub const VT_FILL_PAINTS: ::flatbuffers::VOffsetT = 12; + pub const VT_STROKE_GEOMETRY: ::flatbuffers::VOffsetT = 14; + pub const VT_STROKE_PAINTS: ::flatbuffers::VOffsetT = 16; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + BooleanOperationNode { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args BooleanOperationNodeArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = BooleanOperationNodeBuilder::new(_fbb); + if let Some(x) = args.stroke_paints { builder.add_stroke_paints(x); } + if let Some(x) = args.stroke_geometry { builder.add_stroke_geometry(x); } + if let Some(x) = args.fill_paints { builder.add_fill_paints(x); } + if let Some(x) = args.corner_radius { builder.add_corner_radius(x); } + if let Some(x) = args.layer { builder.add_layer(x); } + if let Some(x) = args.node { builder.add_node(x); } + builder.add_op(args.op); + builder.finish() + } + + + #[inline] + pub fn node(&self) -> SystemNodeTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(BooleanOperationNode::VT_NODE, None).unwrap()} + } + #[inline] + pub fn layer(&self) -> LayerTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(BooleanOperationNode::VT_LAYER, None).unwrap()} + } + #[inline] + pub fn op(&self) -> BooleanPathOperation { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(BooleanOperationNode::VT_OP, Some(BooleanPathOperation::Union)).unwrap()} + } + #[inline] + pub fn corner_radius(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(BooleanOperationNode::VT_CORNER_RADIUS, None)} + } + #[inline] + pub fn fill_paints(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(BooleanOperationNode::VT_FILL_PAINTS, None)} + } + #[inline] + pub fn stroke_geometry(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(BooleanOperationNode::VT_STROKE_GEOMETRY, None)} + } + #[inline] + pub fn stroke_paints(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(BooleanOperationNode::VT_STROKE_PAINTS, None)} + } +} + +impl ::flatbuffers::Verifiable for BooleanOperationNode<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("node", Self::VT_NODE, true)? + .visit_field::<::flatbuffers::ForwardsUOffset>("layer", Self::VT_LAYER, true)? + .visit_field::("op", Self::VT_OP, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("corner_radius", Self::VT_CORNER_RADIUS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("fill_paints", Self::VT_FILL_PAINTS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("stroke_geometry", Self::VT_STROKE_GEOMETRY, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("stroke_paints", Self::VT_STROKE_PAINTS, false)? + .finish(); + Ok(()) + } +} +pub struct BooleanOperationNodeArgs<'a> { + pub node: Option<::flatbuffers::WIPOffset>>, + pub layer: Option<::flatbuffers::WIPOffset>>, + pub op: BooleanPathOperation, + pub corner_radius: Option<::flatbuffers::WIPOffset>>, + pub fill_paints: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub stroke_geometry: Option<::flatbuffers::WIPOffset>>, + pub stroke_paints: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, +} +impl<'a> Default for BooleanOperationNodeArgs<'a> { + #[inline] + fn default() -> Self { + BooleanOperationNodeArgs { + node: None, // required field + layer: None, // required field + op: BooleanPathOperation::Union, + corner_radius: None, + fill_paints: None, + stroke_geometry: None, + stroke_paints: None, + } + } +} + +pub struct BooleanOperationNodeBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> BooleanOperationNodeBuilder<'a, 'b, A> { + #[inline] + pub fn add_node(&mut self, node: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(BooleanOperationNode::VT_NODE, node); + } + #[inline] + pub fn add_layer(&mut self, layer: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(BooleanOperationNode::VT_LAYER, layer); + } + #[inline] + pub fn add_op(&mut self, op: BooleanPathOperation) { + self.fbb_.push_slot::(BooleanOperationNode::VT_OP, op, BooleanPathOperation::Union); + } + #[inline] + pub fn add_corner_radius(&mut self, corner_radius: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(BooleanOperationNode::VT_CORNER_RADIUS, corner_radius); + } + #[inline] + pub fn add_fill_paints(&mut self, fill_paints: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(BooleanOperationNode::VT_FILL_PAINTS, fill_paints); + } + #[inline] + pub fn add_stroke_geometry(&mut self, stroke_geometry: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(BooleanOperationNode::VT_STROKE_GEOMETRY, stroke_geometry); + } + #[inline] + pub fn add_stroke_paints(&mut self, stroke_paints: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(BooleanOperationNode::VT_STROKE_PAINTS, stroke_paints); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> BooleanOperationNodeBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + BooleanOperationNodeBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, BooleanOperationNode::VT_NODE,"node"); + self.fbb_.required(o, BooleanOperationNode::VT_LAYER,"layer"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for BooleanOperationNode<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("BooleanOperationNode"); + ds.field("node", &self.node()); + ds.field("layer", &self.layer()); + ds.field("op", &self.op()); + ds.field("corner_radius", &self.corner_radius()); + ds.field("fill_paints", &self.fill_paints()); + ds.field("stroke_geometry", &self.stroke_geometry()); + ds.field("stroke_paints", &self.stroke_paints()); + ds.finish() + } +} +pub enum BasicShapeNodeOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct BasicShapeNode<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for BasicShapeNode<'a> { + type Inner = BasicShapeNode<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> BasicShapeNode<'a> { + pub const VT_NODE: ::flatbuffers::VOffsetT = 4; + pub const VT_LAYER: ::flatbuffers::VOffsetT = 6; + pub const VT_TYPE_: ::flatbuffers::VOffsetT = 8; + pub const VT_SHAPE_TYPE: ::flatbuffers::VOffsetT = 10; + pub const VT_SHAPE: ::flatbuffers::VOffsetT = 12; + pub const VT_CORNER_RADIUS: ::flatbuffers::VOffsetT = 14; + pub const VT_CORNER_SMOOTHING: ::flatbuffers::VOffsetT = 16; + pub const VT_FILL_PAINTS: ::flatbuffers::VOffsetT = 18; + pub const VT_STROKE_STYLE: ::flatbuffers::VOffsetT = 20; + pub const VT_STROKE_WIDTH: ::flatbuffers::VOffsetT = 22; + pub const VT_STROKE_WIDTH_PROFILE: ::flatbuffers::VOffsetT = 24; + pub const VT_RECTANGULAR_CORNER_RADIUS: ::flatbuffers::VOffsetT = 26; + pub const VT_RECTANGULAR_STROKE_WIDTH: ::flatbuffers::VOffsetT = 28; + pub const VT_STROKE_PAINTS: ::flatbuffers::VOffsetT = 30; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + BasicShapeNode { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args BasicShapeNodeArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = BasicShapeNodeBuilder::new(_fbb); + if let Some(x) = args.stroke_paints { builder.add_stroke_paints(x); } + if let Some(x) = args.rectangular_stroke_width { builder.add_rectangular_stroke_width(x); } + if let Some(x) = args.rectangular_corner_radius { builder.add_rectangular_corner_radius(x); } + if let Some(x) = args.stroke_width_profile { builder.add_stroke_width_profile(x); } + builder.add_stroke_width(args.stroke_width); + if let Some(x) = args.stroke_style { builder.add_stroke_style(x); } + if let Some(x) = args.fill_paints { builder.add_fill_paints(x); } + builder.add_corner_smoothing(args.corner_smoothing); + builder.add_corner_radius(args.corner_radius); + if let Some(x) = args.shape { builder.add_shape(x); } + if let Some(x) = args.layer { builder.add_layer(x); } + if let Some(x) = args.node { builder.add_node(x); } + builder.add_shape_type(args.shape_type); + builder.add_type_(args.type_); + builder.finish() + } + + + #[inline] + pub fn node(&self) -> SystemNodeTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(BasicShapeNode::VT_NODE, None).unwrap()} + } + #[inline] + pub fn layer(&self) -> LayerTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(BasicShapeNode::VT_LAYER, None).unwrap()} + } + /// shape of the type, must align with the shape. this is kept to keep the node type semantics. + #[inline] + pub fn type_(&self) -> BasicShapeNodeType { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(BasicShapeNode::VT_TYPE_, Some(BasicShapeNodeType::Rectangle)).unwrap()} + } + #[inline] + pub fn shape_type(&self) -> CanonicalLayerShape { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(BasicShapeNode::VT_SHAPE_TYPE, Some(CanonicalLayerShape::NONE)).unwrap()} + } + #[inline] + pub fn shape(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>(BasicShapeNode::VT_SHAPE, None)} + } + #[inline] + pub fn corner_radius(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(BasicShapeNode::VT_CORNER_RADIUS, Some(0.0)).unwrap()} + } + #[inline] + pub fn corner_smoothing(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(BasicShapeNode::VT_CORNER_SMOOTHING, Some(0.0)).unwrap()} + } + #[inline] + pub fn fill_paints(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(BasicShapeNode::VT_FILL_PAINTS, None)} + } + #[inline] + pub fn stroke_style(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(BasicShapeNode::VT_STROKE_STYLE, None)} + } + #[inline] + pub fn stroke_width(&self) -> f32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(BasicShapeNode::VT_STROKE_WIDTH, Some(0.0)).unwrap()} + } + #[inline] + pub fn stroke_width_profile(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(BasicShapeNode::VT_STROKE_WIDTH_PROFILE, None)} + } + #[inline] + pub fn rectangular_corner_radius(&self) -> Option<&'a RectangularCornerRadius> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(BasicShapeNode::VT_RECTANGULAR_CORNER_RADIUS, None)} + } + #[inline] + pub fn rectangular_stroke_width(&self) -> Option<&'a RectangularStrokeWidth> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(BasicShapeNode::VT_RECTANGULAR_STROKE_WIDTH, None)} + } + #[inline] + pub fn stroke_paints(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(BasicShapeNode::VT_STROKE_PAINTS, None)} + } + #[inline] + #[allow(non_snake_case)] + pub fn shape_as_canonical_shape_rectangular(&self) -> Option> { + if self.shape_type() == CanonicalLayerShape::CanonicalShapeRectangular { + self.shape().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { CanonicalShapeRectangular::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn shape_as_canonical_shape_elliptical(&self) -> Option> { + if self.shape_type() == CanonicalLayerShape::CanonicalShapeElliptical { + self.shape().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { CanonicalShapeElliptical::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn shape_as_canonical_shape_points_polygon(&self) -> Option> { + if self.shape_type() == CanonicalLayerShape::CanonicalShapePointsPolygon { + self.shape().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { CanonicalShapePointsPolygon::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn shape_as_canonical_shape_regular_polygon(&self) -> Option> { + if self.shape_type() == CanonicalLayerShape::CanonicalShapeRegularPolygon { + self.shape().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { CanonicalShapeRegularPolygon::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn shape_as_canonical_shape_regular_star_polygon(&self) -> Option> { + if self.shape_type() == CanonicalLayerShape::CanonicalShapeRegularStarPolygon { + self.shape().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { CanonicalShapeRegularStarPolygon::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn shape_as_canonical_shape_path(&self) -> Option> { + if self.shape_type() == CanonicalLayerShape::CanonicalShapePath { + self.shape().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { CanonicalShapePath::init_from_table(t) } + }) + } else { + None + } + } + +} + +impl ::flatbuffers::Verifiable for BasicShapeNode<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("node", Self::VT_NODE, true)? + .visit_field::<::flatbuffers::ForwardsUOffset>("layer", Self::VT_LAYER, true)? + .visit_field::("type_", Self::VT_TYPE_, false)? + .visit_union::("shape_type", Self::VT_SHAPE_TYPE, "shape", Self::VT_SHAPE, false, |key, v, pos| { + match key { + CanonicalLayerShape::CanonicalShapeRectangular => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("CanonicalLayerShape::CanonicalShapeRectangular", pos), + CanonicalLayerShape::CanonicalShapeElliptical => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("CanonicalLayerShape::CanonicalShapeElliptical", pos), + CanonicalLayerShape::CanonicalShapePointsPolygon => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("CanonicalLayerShape::CanonicalShapePointsPolygon", pos), + CanonicalLayerShape::CanonicalShapeRegularPolygon => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("CanonicalLayerShape::CanonicalShapeRegularPolygon", pos), + CanonicalLayerShape::CanonicalShapeRegularStarPolygon => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("CanonicalLayerShape::CanonicalShapeRegularStarPolygon", pos), + CanonicalLayerShape::CanonicalShapePath => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("CanonicalLayerShape::CanonicalShapePath", pos), + _ => Ok(()), + } + })? + .visit_field::("corner_radius", Self::VT_CORNER_RADIUS, false)? + .visit_field::("corner_smoothing", Self::VT_CORNER_SMOOTHING, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("fill_paints", Self::VT_FILL_PAINTS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("stroke_style", Self::VT_STROKE_STYLE, false)? + .visit_field::("stroke_width", Self::VT_STROKE_WIDTH, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("stroke_width_profile", Self::VT_STROKE_WIDTH_PROFILE, false)? + .visit_field::("rectangular_corner_radius", Self::VT_RECTANGULAR_CORNER_RADIUS, false)? + .visit_field::("rectangular_stroke_width", Self::VT_RECTANGULAR_STROKE_WIDTH, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("stroke_paints", Self::VT_STROKE_PAINTS, false)? + .finish(); + Ok(()) + } +} +pub struct BasicShapeNodeArgs<'a> { + pub node: Option<::flatbuffers::WIPOffset>>, + pub layer: Option<::flatbuffers::WIPOffset>>, + pub type_: BasicShapeNodeType, + pub shape_type: CanonicalLayerShape, + pub shape: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, + pub corner_radius: f32, + pub corner_smoothing: f32, + pub fill_paints: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub stroke_style: Option<::flatbuffers::WIPOffset>>, + pub stroke_width: f32, + pub stroke_width_profile: Option<::flatbuffers::WIPOffset>>, + pub rectangular_corner_radius: Option<&'a RectangularCornerRadius>, + pub rectangular_stroke_width: Option<&'a RectangularStrokeWidth>, + pub stroke_paints: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, +} +impl<'a> Default for BasicShapeNodeArgs<'a> { + #[inline] + fn default() -> Self { + BasicShapeNodeArgs { + node: None, // required field + layer: None, // required field + type_: BasicShapeNodeType::Rectangle, + shape_type: CanonicalLayerShape::NONE, + shape: None, + corner_radius: 0.0, + corner_smoothing: 0.0, + fill_paints: None, + stroke_style: None, + stroke_width: 0.0, + stroke_width_profile: None, + rectangular_corner_radius: None, + rectangular_stroke_width: None, + stroke_paints: None, + } + } +} + +pub struct BasicShapeNodeBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> BasicShapeNodeBuilder<'a, 'b, A> { + #[inline] + pub fn add_node(&mut self, node: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(BasicShapeNode::VT_NODE, node); + } + #[inline] + pub fn add_layer(&mut self, layer: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(BasicShapeNode::VT_LAYER, layer); + } + #[inline] + pub fn add_type_(&mut self, type_: BasicShapeNodeType) { + self.fbb_.push_slot::(BasicShapeNode::VT_TYPE_, type_, BasicShapeNodeType::Rectangle); + } + #[inline] + pub fn add_shape_type(&mut self, shape_type: CanonicalLayerShape) { + self.fbb_.push_slot::(BasicShapeNode::VT_SHAPE_TYPE, shape_type, CanonicalLayerShape::NONE); + } + #[inline] + pub fn add_shape(&mut self, shape: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(BasicShapeNode::VT_SHAPE, shape); + } + #[inline] + pub fn add_corner_radius(&mut self, corner_radius: f32) { + self.fbb_.push_slot::(BasicShapeNode::VT_CORNER_RADIUS, corner_radius, 0.0); + } + #[inline] + pub fn add_corner_smoothing(&mut self, corner_smoothing: f32) { + self.fbb_.push_slot::(BasicShapeNode::VT_CORNER_SMOOTHING, corner_smoothing, 0.0); + } + #[inline] + pub fn add_fill_paints(&mut self, fill_paints: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(BasicShapeNode::VT_FILL_PAINTS, fill_paints); + } + #[inline] + pub fn add_stroke_style(&mut self, stroke_style: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(BasicShapeNode::VT_STROKE_STYLE, stroke_style); + } + #[inline] + pub fn add_stroke_width(&mut self, stroke_width: f32) { + self.fbb_.push_slot::(BasicShapeNode::VT_STROKE_WIDTH, stroke_width, 0.0); + } + #[inline] + pub fn add_stroke_width_profile(&mut self, stroke_width_profile: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(BasicShapeNode::VT_STROKE_WIDTH_PROFILE, stroke_width_profile); + } + #[inline] + pub fn add_rectangular_corner_radius(&mut self, rectangular_corner_radius: &RectangularCornerRadius) { + self.fbb_.push_slot_always::<&RectangularCornerRadius>(BasicShapeNode::VT_RECTANGULAR_CORNER_RADIUS, rectangular_corner_radius); + } + #[inline] + pub fn add_rectangular_stroke_width(&mut self, rectangular_stroke_width: &RectangularStrokeWidth) { + self.fbb_.push_slot_always::<&RectangularStrokeWidth>(BasicShapeNode::VT_RECTANGULAR_STROKE_WIDTH, rectangular_stroke_width); + } + #[inline] + pub fn add_stroke_paints(&mut self, stroke_paints: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(BasicShapeNode::VT_STROKE_PAINTS, stroke_paints); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> BasicShapeNodeBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + BasicShapeNodeBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, BasicShapeNode::VT_NODE,"node"); + self.fbb_.required(o, BasicShapeNode::VT_LAYER,"layer"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for BasicShapeNode<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("BasicShapeNode"); + ds.field("node", &self.node()); + ds.field("layer", &self.layer()); + ds.field("type_", &self.type_()); + ds.field("shape_type", &self.shape_type()); + match self.shape_type() { + CanonicalLayerShape::CanonicalShapeRectangular => { + if let Some(x) = self.shape_as_canonical_shape_rectangular() { + ds.field("shape", &x) + } else { + ds.field("shape", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + CanonicalLayerShape::CanonicalShapeElliptical => { + if let Some(x) = self.shape_as_canonical_shape_elliptical() { + ds.field("shape", &x) + } else { + ds.field("shape", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + CanonicalLayerShape::CanonicalShapePointsPolygon => { + if let Some(x) = self.shape_as_canonical_shape_points_polygon() { + ds.field("shape", &x) + } else { + ds.field("shape", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + CanonicalLayerShape::CanonicalShapeRegularPolygon => { + if let Some(x) = self.shape_as_canonical_shape_regular_polygon() { + ds.field("shape", &x) + } else { + ds.field("shape", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + CanonicalLayerShape::CanonicalShapeRegularStarPolygon => { + if let Some(x) = self.shape_as_canonical_shape_regular_star_polygon() { + ds.field("shape", &x) + } else { + ds.field("shape", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + CanonicalLayerShape::CanonicalShapePath => { + if let Some(x) = self.shape_as_canonical_shape_path() { + ds.field("shape", &x) + } else { + ds.field("shape", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + _ => { + let x: Option<()> = None; + ds.field("shape", &x) + }, + }; + ds.field("corner_radius", &self.corner_radius()); + ds.field("corner_smoothing", &self.corner_smoothing()); + ds.field("fill_paints", &self.fill_paints()); + ds.field("stroke_style", &self.stroke_style()); + ds.field("stroke_width", &self.stroke_width()); + ds.field("stroke_width_profile", &self.stroke_width_profile()); + ds.field("rectangular_corner_radius", &self.rectangular_corner_radius()); + ds.field("rectangular_stroke_width", &self.rectangular_stroke_width()); + ds.field("stroke_paints", &self.stroke_paints()); + ds.finish() + } +} +pub enum LineNodeOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Node variant: Line. +pub struct LineNode<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for LineNode<'a> { + type Inner = LineNode<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> LineNode<'a> { + pub const VT_NODE: ::flatbuffers::VOffsetT = 4; + pub const VT_LAYER: ::flatbuffers::VOffsetT = 6; + pub const VT_STROKE_GEOMETRY: ::flatbuffers::VOffsetT = 8; + pub const VT_STROKE_PAINTS: ::flatbuffers::VOffsetT = 10; + pub const VT_MARKER_START_SHAPE: ::flatbuffers::VOffsetT = 12; + pub const VT_MARKER_END_SHAPE: ::flatbuffers::VOffsetT = 14; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + LineNode { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args LineNodeArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = LineNodeBuilder::new(_fbb); + if let Some(x) = args.stroke_paints { builder.add_stroke_paints(x); } + if let Some(x) = args.stroke_geometry { builder.add_stroke_geometry(x); } + if let Some(x) = args.layer { builder.add_layer(x); } + if let Some(x) = args.node { builder.add_node(x); } + builder.add_marker_end_shape(args.marker_end_shape); + builder.add_marker_start_shape(args.marker_start_shape); + builder.finish() + } + + + #[inline] + pub fn node(&self) -> SystemNodeTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LineNode::VT_NODE, None).unwrap()} + } + #[inline] + pub fn layer(&self) -> LayerTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LineNode::VT_LAYER, None).unwrap()} + } + #[inline] + pub fn stroke_geometry(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(LineNode::VT_STROKE_GEOMETRY, None)} + } + #[inline] + pub fn stroke_paints(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(LineNode::VT_STROKE_PAINTS, None)} + } + #[inline] + pub fn marker_start_shape(&self) -> StrokeMarkerPreset { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LineNode::VT_MARKER_START_SHAPE, Some(StrokeMarkerPreset::None)).unwrap()} + } + #[inline] + pub fn marker_end_shape(&self) -> StrokeMarkerPreset { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(LineNode::VT_MARKER_END_SHAPE, Some(StrokeMarkerPreset::None)).unwrap()} + } +} + +impl ::flatbuffers::Verifiable for LineNode<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("node", Self::VT_NODE, true)? + .visit_field::<::flatbuffers::ForwardsUOffset>("layer", Self::VT_LAYER, true)? + .visit_field::<::flatbuffers::ForwardsUOffset>("stroke_geometry", Self::VT_STROKE_GEOMETRY, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("stroke_paints", Self::VT_STROKE_PAINTS, false)? + .visit_field::("marker_start_shape", Self::VT_MARKER_START_SHAPE, false)? + .visit_field::("marker_end_shape", Self::VT_MARKER_END_SHAPE, false)? + .finish(); + Ok(()) + } +} +pub struct LineNodeArgs<'a> { + pub node: Option<::flatbuffers::WIPOffset>>, + pub layer: Option<::flatbuffers::WIPOffset>>, + pub stroke_geometry: Option<::flatbuffers::WIPOffset>>, + pub stroke_paints: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub marker_start_shape: StrokeMarkerPreset, + pub marker_end_shape: StrokeMarkerPreset, +} +impl<'a> Default for LineNodeArgs<'a> { + #[inline] + fn default() -> Self { + LineNodeArgs { + node: None, // required field + layer: None, // required field + stroke_geometry: None, + stroke_paints: None, + marker_start_shape: StrokeMarkerPreset::None, + marker_end_shape: StrokeMarkerPreset::None, + } + } +} + +pub struct LineNodeBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> LineNodeBuilder<'a, 'b, A> { + #[inline] + pub fn add_node(&mut self, node: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LineNode::VT_NODE, node); + } + #[inline] + pub fn add_layer(&mut self, layer: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LineNode::VT_LAYER, layer); + } + #[inline] + pub fn add_stroke_geometry(&mut self, stroke_geometry: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(LineNode::VT_STROKE_GEOMETRY, stroke_geometry); + } + #[inline] + pub fn add_stroke_paints(&mut self, stroke_paints: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(LineNode::VT_STROKE_PAINTS, stroke_paints); + } + #[inline] + pub fn add_marker_start_shape(&mut self, marker_start_shape: StrokeMarkerPreset) { + self.fbb_.push_slot::(LineNode::VT_MARKER_START_SHAPE, marker_start_shape, StrokeMarkerPreset::None); + } + #[inline] + pub fn add_marker_end_shape(&mut self, marker_end_shape: StrokeMarkerPreset) { + self.fbb_.push_slot::(LineNode::VT_MARKER_END_SHAPE, marker_end_shape, StrokeMarkerPreset::None); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> LineNodeBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + LineNodeBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, LineNode::VT_NODE,"node"); + self.fbb_.required(o, LineNode::VT_LAYER,"layer"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for LineNode<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("LineNode"); + ds.field("node", &self.node()); + ds.field("layer", &self.layer()); + ds.field("stroke_geometry", &self.stroke_geometry()); + ds.field("stroke_paints", &self.stroke_paints()); + ds.field("marker_start_shape", &self.marker_start_shape()); + ds.field("marker_end_shape", &self.marker_end_shape()); + ds.finish() + } +} +pub enum VectorNodeOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Node variant: Vector. +pub struct VectorNode<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for VectorNode<'a> { + type Inner = VectorNode<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> VectorNode<'a> { + pub const VT_NODE: ::flatbuffers::VOffsetT = 4; + pub const VT_LAYER: ::flatbuffers::VOffsetT = 6; + pub const VT_STROKE_GEOMETRY: ::flatbuffers::VOffsetT = 8; + pub const VT_STROKE_PAINTS: ::flatbuffers::VOffsetT = 10; + pub const VT_MARKER_START_SHAPE: ::flatbuffers::VOffsetT = 12; + pub const VT_MARKER_END_SHAPE: ::flatbuffers::VOffsetT = 14; + pub const VT_CORNER_RADIUS: ::flatbuffers::VOffsetT = 16; + pub const VT_FILL_PAINTS: ::flatbuffers::VOffsetT = 18; + pub const VT_VECTOR_NETWORK_DATA: ::flatbuffers::VOffsetT = 20; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + VectorNode { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args VectorNodeArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = VectorNodeBuilder::new(_fbb); + if let Some(x) = args.vector_network_data { builder.add_vector_network_data(x); } + if let Some(x) = args.fill_paints { builder.add_fill_paints(x); } + if let Some(x) = args.corner_radius { builder.add_corner_radius(x); } + if let Some(x) = args.stroke_paints { builder.add_stroke_paints(x); } + if let Some(x) = args.stroke_geometry { builder.add_stroke_geometry(x); } + if let Some(x) = args.layer { builder.add_layer(x); } + if let Some(x) = args.node { builder.add_node(x); } + builder.add_marker_end_shape(args.marker_end_shape); + builder.add_marker_start_shape(args.marker_start_shape); + builder.finish() + } + + + #[inline] + pub fn node(&self) -> SystemNodeTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(VectorNode::VT_NODE, None).unwrap()} + } + #[inline] + pub fn layer(&self) -> LayerTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(VectorNode::VT_LAYER, None).unwrap()} + } + #[inline] + pub fn stroke_geometry(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(VectorNode::VT_STROKE_GEOMETRY, None)} + } + #[inline] + pub fn stroke_paints(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(VectorNode::VT_STROKE_PAINTS, None)} + } + #[inline] + pub fn marker_start_shape(&self) -> StrokeMarkerPreset { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(VectorNode::VT_MARKER_START_SHAPE, Some(StrokeMarkerPreset::None)).unwrap()} + } + #[inline] + pub fn marker_end_shape(&self) -> StrokeMarkerPreset { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(VectorNode::VT_MARKER_END_SHAPE, Some(StrokeMarkerPreset::None)).unwrap()} + } + #[inline] + pub fn corner_radius(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(VectorNode::VT_CORNER_RADIUS, None)} + } + #[inline] + pub fn fill_paints(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(VectorNode::VT_FILL_PAINTS, None)} + } + #[inline] + pub fn vector_network_data(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(VectorNode::VT_VECTOR_NETWORK_DATA, None)} + } +} + +impl ::flatbuffers::Verifiable for VectorNode<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("node", Self::VT_NODE, true)? + .visit_field::<::flatbuffers::ForwardsUOffset>("layer", Self::VT_LAYER, true)? + .visit_field::<::flatbuffers::ForwardsUOffset>("stroke_geometry", Self::VT_STROKE_GEOMETRY, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("stroke_paints", Self::VT_STROKE_PAINTS, false)? + .visit_field::("marker_start_shape", Self::VT_MARKER_START_SHAPE, false)? + .visit_field::("marker_end_shape", Self::VT_MARKER_END_SHAPE, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("corner_radius", Self::VT_CORNER_RADIUS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("fill_paints", Self::VT_FILL_PAINTS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset>("vector_network_data", Self::VT_VECTOR_NETWORK_DATA, false)? + .finish(); + Ok(()) + } +} +pub struct VectorNodeArgs<'a> { + pub node: Option<::flatbuffers::WIPOffset>>, + pub layer: Option<::flatbuffers::WIPOffset>>, + pub stroke_geometry: Option<::flatbuffers::WIPOffset>>, + pub stroke_paints: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub marker_start_shape: StrokeMarkerPreset, + pub marker_end_shape: StrokeMarkerPreset, + pub corner_radius: Option<::flatbuffers::WIPOffset>>, + pub fill_paints: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub vector_network_data: Option<::flatbuffers::WIPOffset>>, +} +impl<'a> Default for VectorNodeArgs<'a> { + #[inline] + fn default() -> Self { + VectorNodeArgs { + node: None, // required field + layer: None, // required field + stroke_geometry: None, + stroke_paints: None, + marker_start_shape: StrokeMarkerPreset::None, + marker_end_shape: StrokeMarkerPreset::None, + corner_radius: None, + fill_paints: None, + vector_network_data: None, + } + } +} + +pub struct VectorNodeBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> VectorNodeBuilder<'a, 'b, A> { + #[inline] + pub fn add_node(&mut self, node: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(VectorNode::VT_NODE, node); + } + #[inline] + pub fn add_layer(&mut self, layer: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(VectorNode::VT_LAYER, layer); + } + #[inline] + pub fn add_stroke_geometry(&mut self, stroke_geometry: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(VectorNode::VT_STROKE_GEOMETRY, stroke_geometry); + } + #[inline] + pub fn add_stroke_paints(&mut self, stroke_paints: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(VectorNode::VT_STROKE_PAINTS, stroke_paints); + } + #[inline] + pub fn add_marker_start_shape(&mut self, marker_start_shape: StrokeMarkerPreset) { + self.fbb_.push_slot::(VectorNode::VT_MARKER_START_SHAPE, marker_start_shape, StrokeMarkerPreset::None); + } + #[inline] + pub fn add_marker_end_shape(&mut self, marker_end_shape: StrokeMarkerPreset) { + self.fbb_.push_slot::(VectorNode::VT_MARKER_END_SHAPE, marker_end_shape, StrokeMarkerPreset::None); + } + #[inline] + pub fn add_corner_radius(&mut self, corner_radius: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(VectorNode::VT_CORNER_RADIUS, corner_radius); + } + #[inline] + pub fn add_fill_paints(&mut self, fill_paints: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(VectorNode::VT_FILL_PAINTS, fill_paints); + } + #[inline] + pub fn add_vector_network_data(&mut self, vector_network_data: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(VectorNode::VT_VECTOR_NETWORK_DATA, vector_network_data); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> VectorNodeBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + VectorNodeBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, VectorNode::VT_NODE,"node"); + self.fbb_.required(o, VectorNode::VT_LAYER,"layer"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for VectorNode<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("VectorNode"); + ds.field("node", &self.node()); + ds.field("layer", &self.layer()); + ds.field("stroke_geometry", &self.stroke_geometry()); + ds.field("stroke_paints", &self.stroke_paints()); + ds.field("marker_start_shape", &self.marker_start_shape()); + ds.field("marker_end_shape", &self.marker_end_shape()); + ds.field("corner_radius", &self.corner_radius()); + ds.field("fill_paints", &self.fill_paints()); + ds.field("vector_network_data", &self.vector_network_data()); + ds.finish() + } +} +pub enum TextSpanNodeOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Node variant: Text span. +pub struct TextSpanNode<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for TextSpanNode<'a> { + type Inner = TextSpanNode<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> TextSpanNode<'a> { + pub const VT_NODE: ::flatbuffers::VOffsetT = 4; + pub const VT_LAYER: ::flatbuffers::VOffsetT = 6; + pub const VT_PROPERTIES: ::flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + TextSpanNode { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args TextSpanNodeArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = TextSpanNodeBuilder::new(_fbb); + if let Some(x) = args.properties { builder.add_properties(x); } + if let Some(x) = args.layer { builder.add_layer(x); } + if let Some(x) = args.node { builder.add_node(x); } + builder.finish() + } + + + #[inline] + pub fn node(&self) -> SystemNodeTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(TextSpanNode::VT_NODE, None).unwrap()} + } + #[inline] + pub fn layer(&self) -> LayerTrait<'a> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(TextSpanNode::VT_LAYER, None).unwrap()} + } + #[inline] + pub fn properties(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(TextSpanNode::VT_PROPERTIES, None)} + } +} + +impl ::flatbuffers::Verifiable for TextSpanNode<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("node", Self::VT_NODE, true)? + .visit_field::<::flatbuffers::ForwardsUOffset>("layer", Self::VT_LAYER, true)? + .visit_field::<::flatbuffers::ForwardsUOffset>("properties", Self::VT_PROPERTIES, false)? + .finish(); + Ok(()) + } +} +pub struct TextSpanNodeArgs<'a> { + pub node: Option<::flatbuffers::WIPOffset>>, + pub layer: Option<::flatbuffers::WIPOffset>>, + pub properties: Option<::flatbuffers::WIPOffset>>, +} +impl<'a> Default for TextSpanNodeArgs<'a> { + #[inline] + fn default() -> Self { + TextSpanNodeArgs { + node: None, // required field + layer: None, // required field + properties: None, + } + } +} + +pub struct TextSpanNodeBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> TextSpanNodeBuilder<'a, 'b, A> { + #[inline] + pub fn add_node(&mut self, node: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(TextSpanNode::VT_NODE, node); + } + #[inline] + pub fn add_layer(&mut self, layer: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(TextSpanNode::VT_LAYER, layer); + } + #[inline] + pub fn add_properties(&mut self, properties: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(TextSpanNode::VT_PROPERTIES, properties); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> TextSpanNodeBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + TextSpanNodeBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_.required(o, TextSpanNode::VT_NODE,"node"); + self.fbb_.required(o, TextSpanNode::VT_LAYER,"layer"); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for TextSpanNode<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("TextSpanNode"); + ds.field("node", &self.node()); + ds.field("layer", &self.layer()); + ds.field("properties", &self.properties()); + ds.finish() + } +} +pub enum NodeSlotOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Wrapper table for a single Node union entry in a flat node vector. +/// +/// FlatBuffers Rust codegen does not support `[Node]` (vector of unions) directly. +/// Using `[NodeSlot]` (vector of tables each containing a union field) is the +/// canonical workaround — identical in spirit to `PaintStackItem` wrapping `Paint`. +/// See: https://github.com/google/flatbuffers/issues/8011 +pub struct NodeSlot<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for NodeSlot<'a> { + type Inner = NodeSlot<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> NodeSlot<'a> { + pub const VT_NODE_TYPE: ::flatbuffers::VOffsetT = 4; + pub const VT_NODE: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + NodeSlot { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args NodeSlotArgs + ) -> ::flatbuffers::WIPOffset> { + let mut builder = NodeSlotBuilder::new(_fbb); + if let Some(x) = args.node { builder.add_node(x); } + builder.add_node_type(args.node_type); + builder.finish() + } + + + #[inline] + pub fn node_type(&self) -> Node { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(NodeSlot::VT_NODE_TYPE, Some(Node::NONE)).unwrap()} + } + #[inline] + pub fn node(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>(NodeSlot::VT_NODE, None)} + } + #[inline] + #[allow(non_snake_case)] + pub fn node_as_unknown_node(&self) -> Option> { + if self.node_type() == Node::UnknownNode { + self.node().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { UnknownNode::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn node_as_scene_node(&self) -> Option> { + if self.node_type() == Node::SceneNode { + self.node().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { SceneNode::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn node_as_group_node(&self) -> Option> { + if self.node_type() == Node::GroupNode { + self.node().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { GroupNode::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn node_as_initial_container_node(&self) -> Option> { + if self.node_type() == Node::InitialContainerNode { + self.node().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { InitialContainerNode::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn node_as_container_node(&self) -> Option> { + if self.node_type() == Node::ContainerNode { + self.node().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { ContainerNode::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn node_as_boolean_operation_node(&self) -> Option> { + if self.node_type() == Node::BooleanOperationNode { + self.node().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { BooleanOperationNode::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn node_as_basic_shape_node(&self) -> Option> { + if self.node_type() == Node::BasicShapeNode { + self.node().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { BasicShapeNode::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn node_as_line_node(&self) -> Option> { + if self.node_type() == Node::LineNode { + self.node().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { LineNode::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn node_as_vector_node(&self) -> Option> { + if self.node_type() == Node::VectorNode { + self.node().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { VectorNode::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn node_as_text_span_node(&self) -> Option> { + if self.node_type() == Node::TextSpanNode { + self.node().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { TextSpanNode::init_from_table(t) } + }) + } else { + None + } + } + +} + +impl ::flatbuffers::Verifiable for NodeSlot<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_union::("node_type", Self::VT_NODE_TYPE, "node", Self::VT_NODE, false, |key, v, pos| { + match key { + Node::UnknownNode => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Node::UnknownNode", pos), + Node::SceneNode => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Node::SceneNode", pos), + Node::GroupNode => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Node::GroupNode", pos), + Node::InitialContainerNode => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Node::InitialContainerNode", pos), + Node::ContainerNode => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Node::ContainerNode", pos), + Node::BooleanOperationNode => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Node::BooleanOperationNode", pos), + Node::BasicShapeNode => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Node::BasicShapeNode", pos), + Node::LineNode => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Node::LineNode", pos), + Node::VectorNode => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Node::VectorNode", pos), + Node::TextSpanNode => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("Node::TextSpanNode", pos), + _ => Ok(()), + } + })? + .finish(); + Ok(()) + } +} +pub struct NodeSlotArgs { + pub node_type: Node, + pub node: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, +} +impl<'a> Default for NodeSlotArgs { + #[inline] + fn default() -> Self { + NodeSlotArgs { + node_type: Node::NONE, + node: None, + } + } +} + +pub struct NodeSlotBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> NodeSlotBuilder<'a, 'b, A> { + #[inline] + pub fn add_node_type(&mut self, node_type: Node) { + self.fbb_.push_slot::(NodeSlot::VT_NODE_TYPE, node_type, Node::NONE); + } + #[inline] + pub fn add_node(&mut self, node: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(NodeSlot::VT_NODE, node); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> NodeSlotBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + NodeSlotBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for NodeSlot<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("NodeSlot"); + ds.field("node_type", &self.node_type()); + match self.node_type() { + Node::UnknownNode => { + if let Some(x) = self.node_as_unknown_node() { + ds.field("node", &x) + } else { + ds.field("node", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Node::SceneNode => { + if let Some(x) = self.node_as_scene_node() { + ds.field("node", &x) + } else { + ds.field("node", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Node::GroupNode => { + if let Some(x) = self.node_as_group_node() { + ds.field("node", &x) + } else { + ds.field("node", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Node::InitialContainerNode => { + if let Some(x) = self.node_as_initial_container_node() { + ds.field("node", &x) + } else { + ds.field("node", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Node::ContainerNode => { + if let Some(x) = self.node_as_container_node() { + ds.field("node", &x) + } else { + ds.field("node", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Node::BooleanOperationNode => { + if let Some(x) = self.node_as_boolean_operation_node() { + ds.field("node", &x) + } else { + ds.field("node", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Node::BasicShapeNode => { + if let Some(x) = self.node_as_basic_shape_node() { + ds.field("node", &x) + } else { + ds.field("node", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Node::LineNode => { + if let Some(x) = self.node_as_line_node() { + ds.field("node", &x) + } else { + ds.field("node", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Node::VectorNode => { + if let Some(x) = self.node_as_vector_node() { + ds.field("node", &x) + } else { + ds.field("node", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Node::TextSpanNode => { + if let Some(x) = self.node_as_text_span_node() { + ds.field("node", &x) + } else { + ds.field("node", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + _ => { + let x: Option<()> = None; + ds.field("node", &x) + }, + }; + ds.finish() + } +} +pub enum CanvasDocumentOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct CanvasDocument<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for CanvasDocument<'a> { + type Inner = CanvasDocument<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> CanvasDocument<'a> { + pub const VT_SCHEMA_VERSION: ::flatbuffers::VOffsetT = 4; + pub const VT_NODES: ::flatbuffers::VOffsetT = 6; + pub const VT_SCENES: ::flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + CanvasDocument { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args CanvasDocumentArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = CanvasDocumentBuilder::new(_fbb); + if let Some(x) = args.scenes { builder.add_scenes(x); } + if let Some(x) = args.nodes { builder.add_nodes(x); } + if let Some(x) = args.schema_version { builder.add_schema_version(x); } + builder.finish() + } + + + /// Schema version string (keep in sync with TS `grida.program.document.SCHEMA_VERSION`). + #[inline] + pub fn schema_version(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>(CanvasDocument::VT_SCHEMA_VERSION, None)} + } + /// Flat node repository. + /// + /// Stored as `[NodeSlot]` (vector of wrapper tables) rather than `[Node]` + /// (vector of unions) to maintain compatibility with Rust FlatBuffers codegen, + /// which does not support vectors of unions directly. + #[inline] + pub fn nodes(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(CanvasDocument::VT_NODES, None)} + } + /// Scene node ids (scene nodes are also stored in `nodes`). + #[inline] + pub fn scenes(&self) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>(CanvasDocument::VT_SCENES, None)} + } +} + +impl ::flatbuffers::Verifiable for CanvasDocument<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("schema_version", Self::VT_SCHEMA_VERSION, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("nodes", Self::VT_NODES, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("scenes", Self::VT_SCENES, false)? + .finish(); + Ok(()) + } +} +pub struct CanvasDocumentArgs<'a> { + pub schema_version: Option<::flatbuffers::WIPOffset<&'a str>>, + pub nodes: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, + pub scenes: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>>>, +} +impl<'a> Default for CanvasDocumentArgs<'a> { + #[inline] + fn default() -> Self { + CanvasDocumentArgs { + schema_version: None, + nodes: None, + scenes: None, + } + } +} + +pub struct CanvasDocumentBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> CanvasDocumentBuilder<'a, 'b, A> { + #[inline] + pub fn add_schema_version(&mut self, schema_version: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(CanvasDocument::VT_SCHEMA_VERSION, schema_version); + } + #[inline] + pub fn add_nodes(&mut self, nodes: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(CanvasDocument::VT_NODES, nodes); + } + #[inline] + pub fn add_scenes(&mut self, scenes: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b , ::flatbuffers::ForwardsUOffset>>>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>(CanvasDocument::VT_SCENES, scenes); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> CanvasDocumentBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + CanvasDocumentBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for CanvasDocument<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("CanvasDocument"); + ds.field("schema_version", &self.schema_version()); + ds.field("nodes", &self.nodes()); + ds.field("scenes", &self.scenes()); + ds.finish() + } +} +pub enum GridaFileOffset {} +#[derive(Copy, Clone, PartialEq)] + +/// Top-level wrapper (allows future multi-document bundles, signatures, etc.) +pub struct GridaFile<'a> { + pub _tab: ::flatbuffers::Table<'a>, +} + +impl<'a> ::flatbuffers::Follow<'a> for GridaFile<'a> { + type Inner = GridaFile<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { ::flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> GridaFile<'a> { + pub const VT_DOCUMENT: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + GridaFile { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: ::flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args GridaFileArgs<'args> + ) -> ::flatbuffers::WIPOffset> { + let mut builder = GridaFileBuilder::new(_fbb); + if let Some(x) = args.document { builder.add_document(x); } + builder.finish() + } + + + #[inline] + pub fn document(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::<::flatbuffers::ForwardsUOffset>(GridaFile::VT_DOCUMENT, None)} + } +} + +impl ::flatbuffers::Verifiable for GridaFile<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, pos: usize + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>("document", Self::VT_DOCUMENT, false)? + .finish(); + Ok(()) + } +} +pub struct GridaFileArgs<'a> { + pub document: Option<::flatbuffers::WIPOffset>>, +} +impl<'a> Default for GridaFileArgs<'a> { + #[inline] + fn default() -> Self { + GridaFileArgs { + document: None, + } + } +} + +pub struct GridaFileBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> GridaFileBuilder<'a, 'b, A> { + #[inline] + pub fn add_document(&mut self, document: ::flatbuffers::WIPOffset>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset>(GridaFile::VT_DOCUMENT, document); + } + #[inline] + pub fn new(_fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>) -> GridaFileBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + GridaFileBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } +} + +impl ::core::fmt::Debug for GridaFile<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("GridaFile"); + ds.field("document", &self.document()); + ds.finish() + } +} +#[inline] +/// Verifies that a buffer of bytes contains a `GridaFile` +/// and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_grida_file_unchecked`. +pub fn root_as_grida_file(buf: &[u8]) -> Result, ::flatbuffers::InvalidFlatbuffer> { + ::flatbuffers::root::(buf) +} +#[inline] +/// Verifies that a buffer of bytes contains a size prefixed +/// `GridaFile` and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `size_prefixed_root_as_grida_file_unchecked`. +pub fn size_prefixed_root_as_grida_file(buf: &[u8]) -> Result, ::flatbuffers::InvalidFlatbuffer> { + ::flatbuffers::size_prefixed_root::(buf) +} +#[inline] +/// Verifies, with the given options, that a buffer of bytes +/// contains a `GridaFile` and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_grida_file_unchecked`. +pub fn root_as_grida_file_with_opts<'b, 'o>( + opts: &'o ::flatbuffers::VerifierOptions, + buf: &'b [u8], +) -> Result, ::flatbuffers::InvalidFlatbuffer> { + ::flatbuffers::root_with_opts::>(opts, buf) +} +#[inline] +/// Verifies, with the given verifier options, that a buffer of +/// bytes contains a size prefixed `GridaFile` and returns +/// it. Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_grida_file_unchecked`. +pub fn size_prefixed_root_as_grida_file_with_opts<'b, 'o>( + opts: &'o ::flatbuffers::VerifierOptions, + buf: &'b [u8], +) -> Result, ::flatbuffers::InvalidFlatbuffer> { + ::flatbuffers::size_prefixed_root_with_opts::>(opts, buf) +} +#[inline] +/// Assumes, without verification, that a buffer of bytes contains a GridaFile and returns it. +/// # Safety +/// Callers must trust the given bytes do indeed contain a valid `GridaFile`. +pub unsafe fn root_as_grida_file_unchecked(buf: &[u8]) -> GridaFile<'_> { + unsafe { ::flatbuffers::root_unchecked::(buf) } +} +#[inline] +/// Assumes, without verification, that a buffer of bytes contains a size prefixed GridaFile and returns it. +/// # Safety +/// Callers must trust the given bytes do indeed contain a valid size prefixed `GridaFile`. +pub unsafe fn size_prefixed_root_as_grida_file_unchecked(buf: &[u8]) -> GridaFile<'_> { + unsafe { ::flatbuffers::size_prefixed_root_unchecked::(buf) } +} +pub const GRIDA_FILE_IDENTIFIER: &str = "GRID"; + +#[inline] +pub fn grida_file_buffer_has_identifier(buf: &[u8]) -> bool { + ::flatbuffers::buffer_has_identifier(buf, GRIDA_FILE_IDENTIFIER, false) +} + +#[inline] +pub fn grida_file_size_prefixed_buffer_has_identifier(buf: &[u8]) -> bool { + ::flatbuffers::buffer_has_identifier(buf, GRIDA_FILE_IDENTIFIER, true) +} + +pub const GRIDA_FILE_EXTENSION: &str = "grida"; + +#[inline] +pub fn finish_grida_file_buffer<'a, 'b, A: ::flatbuffers::Allocator + 'a>( + fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + root: ::flatbuffers::WIPOffset>) { + fbb.finish(root, Some(GRIDA_FILE_IDENTIFIER)); +} + +#[inline] +pub fn finish_size_prefixed_grida_file_buffer<'a, 'b, A: ::flatbuffers::Allocator + 'a>(fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, root: ::flatbuffers::WIPOffset>) { + fbb.finish_size_prefixed(root, Some(GRIDA_FILE_IDENTIFIER)); +} +} // pub mod grida + diff --git a/crates/grida-canvas/src/io/generated/mod.rs b/crates/grida-canvas/src/io/generated/mod.rs new file mode 100644 index 0000000000..ab7de45c21 --- /dev/null +++ b/crates/grida-canvas/src/io/generated/mod.rs @@ -0,0 +1,18 @@ +//! Auto-generated FlatBuffers bindings — **committed to git**. +//! +//! Generated by `flatc --rust` from `format/grida.fbs`. Do not edit by hand. +//! This file is committed because `io_grida_fbs.rs` and the test fixtures +//! compile against its types; keeping it in-tree lets `cargo build` work from +//! a clean checkout without requiring `flatc`. +//! +//! To regenerate (from the repo root): +//! +//! ```sh +//! pnpm --filter @crates/grida-canvas generate +//! ``` +//! +//! CI verifies freshness — if `grida.fbs` changes but this file is stale, +//! the `check-generated-fbs` workflow will fail. + +#[allow(dead_code, unused_imports, clippy::all)] +pub mod grida; diff --git a/crates/grida-canvas/src/io/io_figma.rs b/crates/grida-canvas/src/io/io_figma.rs index 33102fd1ef..4bf9a34345 100644 --- a/crates/grida-canvas/src/io/io_figma.rs +++ b/crates/grida-canvas/src/io/io_figma.rs @@ -1292,7 +1292,7 @@ impl FigmaConverter { text_decoration_color: None, text_decoration_style: None, text_decoration_skip_ink: None, - text_decoration_thinkness: None, + text_decoration_thickness: None, }), font_family: style .font_family diff --git a/crates/grida-canvas/src/io/io_grida.rs b/crates/grida-canvas/src/io/io_grida.rs index 81e402ac23..a0b86d8f52 100644 --- a/crates/grida-canvas/src/io/io_grida.rs +++ b/crates/grida-canvas/src/io/io_grida.rs @@ -1033,7 +1033,7 @@ pub struct JSONTextSpanNode { alias = "textDecorationThickness", default )] - pub text_decoration_thinkness: Option, + pub text_decoration_thickness: Option, #[serde(rename = "line_height", alias = "lineHeight", default)] pub line_height: Option, @@ -1431,7 +1431,7 @@ impl From for TextSpanNodeRec { text_decoration_color: Some(node.text_decoration_color), text_decoration_style: node.text_decoration_style, text_decoration_skip_ink: node.text_decoration_skip_ink, - text_decoration_thinkness: node.text_decoration_thinkness, + text_decoration_thickness: node.text_decoration_thickness, }), font_family: node.font_family.unwrap_or_else(|| "".to_string()), font_size: node.font_size.unwrap_or(14.0), @@ -3214,7 +3214,7 @@ mod tests { #[test] fn parse_grida_file_new_format() { let json = r#"{ - "version": "0.90.0-beta+20260108", + "version": "0.91.0-beta+20260311", "document": { "nodes": { "main": { @@ -3271,7 +3271,7 @@ mod tests { fn parse_grida_file_with_container_children() { // Test that container nodes with children in links work correctly let json = r#"{ - "version": "0.90.0-beta+20260108", + "version": "0.91.0-beta+20260311", "document": { "nodes": { "main": { @@ -3338,7 +3338,7 @@ mod tests { fn test_nested_children_population() { // Test that deeply nested children get properly populated from links let json = r#"{ - "version": "0.90.0-beta+20260108", + "version": "0.91.0-beta+20260311", "document": { "nodes": { "main": { diff --git a/crates/grida-canvas/src/io/io_grida_fbs.rs b/crates/grida-canvas/src/io/io_grida_fbs.rs new file mode 100644 index 0000000000..04f7458349 --- /dev/null +++ b/crates/grida-canvas/src/io/io_grida_fbs.rs @@ -0,0 +1,3287 @@ +//! FlatBuffers (`.grida`) → Rust runtime decoder. +//! +//! Converts a `GridaFile` FlatBuffers binary into a `Scene`. +//! +//! The FBS document stores nodes in a flat `[NodeSlot]` list. Each layer node +//! carries a `ParentReference` (parent id + fractional-index position string) +//! so the tree can be reconstructed after decoding. Scene nodes are the roots. +//! +//! ## Usage +//! +//! ```no_run +//! use cg::io::io_grida_fbs; +//! let bytes = std::fs::read("example.grida").unwrap(); +//! let scene = io_grida_fbs::decode(&bytes).unwrap(); +//! ``` + +use std::collections::HashMap; + +use math2::{box_fit::BoxFit, transform::AffineTransform}; + +/// Schema version emitted by the Rust FlatBuffers writer. +/// +/// Keep in sync with the TS constant `grida.program.document.SCHEMA_VERSION` +/// (`packages/grida-canvas-schema/grida.ts`). +pub const SCHEMA_VERSION: &str = "0.91.0-beta+20260311"; + +use crate::cg::{ + alignment::Alignment, + color::CGColor, + fe::{ + FeBackdropBlur, FeBlur, FeGaussianBlur, FeLayerBlur, FeLiquidGlass, FeNoiseEffect, + FeShadow, FilterShadowEffect, NoiseEffectColors, + }, + stroke_dasharray::StrokeDashArray, + stroke_width::{RectangularStrokeWidth, SingularStrokeWidth, StrokeWidth}, + tilemode::TileMode, + types::{ + Axis, BlendMode, BooleanPathOperation, CGPoint, ContainerClipFlag, CornerSmoothing, + CrossAxisAlignment, EdgeInsets, FontWeight, GradientStop, ImageFilters, ImagePaint, + ImagePaintFit, LayerBlendMode, LayerMaskType, LayoutGap, LayoutMode, LayoutPositioning, + LayoutWrap, LinearGradientPaint, MainAxisAlignment, Paint, Paints, RadialGradientPaint, + RectangularCornerRadius, ResourceRef, SolidPaint, StrokeAlign, StrokeCap, StrokeJoin, + StrokeMarkerPreset, StrokeMiterLimit, SweepGradientPaint, TextAlign, TextAlignVertical, + TextStyleRec, + }, +}; +use crate::node::{ + id::NodeIdGenerator, + scene_graph::SceneGraph, + schema::{ + BooleanPathOperationNodeRec, ContainerNodeRec, EllipseNodeRec, GroupNodeRec, + InitialContainerNodeRec, LayerEffects, LayoutChildStyle, LayoutContainerStyle, + LayoutDimensionStyle, LayoutPositioningBasis, LineNodeRec, Node, RectangleNodeRec, + RegularPolygonNodeRec, RegularStarPolygonNodeRec, Scene, Size, StrokeStyle, + TextSpanNodeRec, VectorNodeRec, + }, +}; +use crate::vectornetwork::{ + VectorNetwork, VectorNetworkLoop, VectorNetworkRegion, VectorNetworkSegment, +}; + +use super::generated::grida::grida as fbs; + +// ───────────────────────────────────────────────────────────────────────────── +// Error type +// ───────────────────────────────────────────────────────────────────────────── + +#[derive(Debug)] +pub enum FbsDecodeError { + InvalidBuffer(flatbuffers::InvalidFlatbuffer), + MissingDocument, + MissingScene, +} + +impl std::fmt::Display for FbsDecodeError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + FbsDecodeError::InvalidBuffer(e) => write!(f, "invalid FlatBuffer: {e}"), + FbsDecodeError::MissingDocument => write!(f, "GridaFile.document is null"), + FbsDecodeError::MissingScene => write!(f, "document has no scenes"), + } + } +} + +impl std::error::Error for FbsDecodeError {} + +impl From for FbsDecodeError { + fn from(e: flatbuffers::InvalidFlatbuffer) -> Self { + FbsDecodeError::InvalidBuffer(e) + } +} + +// ═════════════════════════════════════════════════════════════════════════════ +// Shared intermediate structs — decoded once, threaded into every node builder +// ═════════════════════════════════════════════════════════════════════════════ + +/// Fields common to every layer-bearing node, decoded from `LayerTrait`. +struct LayerCommon { + active: bool, + opacity: f32, + blend_mode: LayerBlendMode, + mask: Option, + effects: LayerEffects, + /// Rotation in degrees — only used by Container/InitialContainer nodes + /// that store rotation as a plain f32 field. For shape/line/text nodes + /// use `rotation_cos_sin` instead to avoid lossy degree conversion. + rotation: f32, + /// Raw (cos, sin) extracted directly from the FBS `CGTransform2D` matrix. + /// Used by shape/line/text/group decoders to build transforms without + /// lossy `atan2 → to_degrees → to_radians → sin_cos` round-trips. + rotation_cos_sin: (f32, f32), + layout_child: Option, +} + +/// Spatial properties for shape-like nodes (everything except Container and +/// InitialContainer) — position, size, and the transform that bakes them together. +struct ShapeLayout { + x: f32, + y: f32, + size: Size, + /// `from_box_center(x, y, w, h, rotation)` — the canonical shape transform. + transform: AffineTransform, + width: Option, + height: Option, +} + +fn decode_layer_common(sys: &fbs::SystemNodeTrait<'_>, layer: &fbs::LayerTrait<'_>) -> LayerCommon { + let layout = layer.layout(); + let plt = layer.post_layout_transform(); + LayerCommon { + active: sys.active(), + opacity: layer.opacity(), + blend_mode: decode_layer_blend_mode(layer.blend_mode()), + mask: decode_mask_type(layer.mask_type_type()), + effects: decode_layer_effects(layer.effects()), + rotation: extract_rotation_degrees(plt), + rotation_cos_sin: extract_rotation_cos_sin(plt), + layout_child: layout.as_ref().and_then(decode_layout_child_style), + } +} + +fn decode_shape_layout(layer: &fbs::LayerTrait<'_>, cos_sin: (f32, f32)) -> ShapeLayout { + let layout = layer.layout(); + let (x, y) = layout.as_ref().map(decode_layout_xy).unwrap_or((0.0, 0.0)); + let (w, h) = layout.as_ref().map(decode_dimensions).unwrap_or((None, None)); + let size = Size { + width: w.unwrap_or(0.0), + height: h.unwrap_or(0.0), + }; + let (cos, sin) = cos_sin; + let transform = + AffineTransform::from_box_center_raw(x, y, size.width, size.height, cos, sin); + ShapeLayout { + x, + y, + size, + transform, + width: w, + height: h, + } +} + +fn singular_stroke_width(w: f32) -> SingularStrokeWidth { + if w == 0.0 { + SingularStrokeWidth(None) + } else { + SingularStrokeWidth(Some(w)) + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Public entry point +// ───────────────────────────────────────────────────────────────────────────── + +/// Result of decoding a `.grida` FlatBuffers binary that also carries the +/// ID mapping needed for re-encoding. +pub struct DecodeResult { + /// The decoded scenes (typically one). + pub scenes: Vec, + /// Mapping from internal `NodeId` to the original string IDs stored in the + /// FBS file. Required for [`encode`] round-trips. + pub id_map: HashMap, + /// The string IDs of the scene nodes, in document order. + pub scene_ids: Vec, + /// Mapping from internal `NodeId` to the original fractional-index position + /// string stored in the FBS file. Required for [`encode`] round-trips so + /// that child ordering is preserved exactly. + pub position_map: HashMap, +} + +/// Decode a `.grida` FlatBuffers binary into a `Scene`. +/// +/// Picks the first scene listed in `CanvasDocument.scenes`. If the document +/// contains multiple scenes, use `decode_all` and index into the result. +pub fn decode(bytes: &[u8]) -> Result { + let scenes = decode_all(bytes)?; + scenes + .into_iter() + .next() + .ok_or(FbsDecodeError::MissingScene) +} + +/// Decode a `.grida` FlatBuffers binary and return the full [`DecodeResult`] +/// including the ID mapping needed for round-trip encoding. +pub fn decode_with_id_map(bytes: &[u8]) -> Result { + decode_all_inner(bytes) +} + +/// Decode a `.grida` FlatBuffers binary into all `Scene`s present in the document. +pub fn decode_all(bytes: &[u8]) -> Result, FbsDecodeError> { + decode_all_inner(bytes).map(|r| r.scenes) +} + +fn decode_all_inner(bytes: &[u8]) -> Result { + let grida_file = flatbuffers::root::(bytes)?; + let document = grida_file + .document() + .ok_or(FbsDecodeError::MissingDocument)?; + + // ── 1. Collect scene node IDs (scene ordering) ────────────────────────── + let mut scene_ids_ordered: Vec = Vec::new(); + if let Some(scenes_vec) = document.scenes() { + for i in 0..scenes_vec.len() { + scene_ids_ordered.push(scenes_vec.get(i).id().to_owned()); + } + } + + // ── 2. Decode all node slots ───────────────────────────────────────────── + + struct NodeEntry { + id: String, + parent: Option<(String, String)>, // (parent_id, fractional-index position) + node: Node, + } + + struct SceneMeta { + #[allow(dead_code)] + id: String, + name: String, + background_color: Option, + } + + let mut node_entries: Vec = Vec::new(); + let mut scene_metas: HashMap = HashMap::new(); + + /// Helper macro: every layer-bearing node type follows the same pattern of + /// extracting `sys`, `layer`, `id`, `parent` from the slot, then calling a + /// decoder. This macro eliminates that boilerplate and makes it impossible + /// to forget any step. + macro_rules! decode_layer_node { + ($slot:expr, $accessor:ident, $decode_fn:expr) => { + if let Some(typed) = $slot.$accessor() { + let sys = typed.node(); + let layer = typed.layer(); + let id = sys.id().id().to_owned(); + let parent = decode_parent_ref(&layer); + let lc = decode_layer_common(&sys, &layer); + let node = $decode_fn(&lc, &layer, &typed); + node_entries.push(NodeEntry { id, parent, node }); + } + }; + } + + if let Some(nodes_vec) = document.nodes() { + for i in 0..nodes_vec.len() { + let slot = nodes_vec.get(i); + match slot.node_type() { + fbs::Node::SceneNode => { + if let Some(sn) = slot.node_as_scene_node() { + let sys = sn.node(); + let id = sys.id().id().to_owned(); + let name = sys.name().unwrap_or("").to_owned(); + let bg = sn + .scene_background_color() + .map(decode_rgba32f_to_cg_color); + scene_metas.insert( + id.clone(), + SceneMeta { + id, + name, + background_color: bg, + }, + ); + } + } + fbs::Node::GroupNode => { + decode_layer_node!(slot, node_as_group_node, decode_group_node); + } + fbs::Node::ContainerNode => { + decode_layer_node!(slot, node_as_container_node, decode_container_node); + } + fbs::Node::InitialContainerNode => { + decode_layer_node!( + slot, + node_as_initial_container_node, + decode_initial_container_node + ); + } + fbs::Node::BasicShapeNode => { + decode_layer_node!(slot, node_as_basic_shape_node, decode_basic_shape_node); + } + fbs::Node::VectorNode => { + decode_layer_node!(slot, node_as_vector_node, decode_vector_node); + } + fbs::Node::LineNode => { + decode_layer_node!(slot, node_as_line_node, decode_line_node); + } + fbs::Node::TextSpanNode => { + decode_layer_node!(slot, node_as_text_span_node, decode_text_span_node); + } + fbs::Node::BooleanOperationNode => { + decode_layer_node!( + slot, + node_as_boolean_operation_node, + decode_boolean_operation_node + ); + } + fbs::Node::UnknownNode | fbs::Node::NONE | _ => {} + } + } + } + + // ── 3. Build ID mapping (string → internal NodeId) ─────────────────────── + let mut string_to_internal_id: HashMap = HashMap::new(); + let mut id_generator = NodeIdGenerator::new(); + + for e in &node_entries { + string_to_internal_id + .entry(e.id.clone()) + .or_insert_with(|| id_generator.next()); + } + for (sid, _) in &scene_metas { + string_to_internal_id + .entry(sid.clone()) + .or_insert_with(|| id_generator.next()); + } + + let get_id = |s: &String| string_to_internal_id.get(s).copied(); + + // ── 4. Build children_by_parent (sorted by fractional index) ───────────── + let mut children_by_parent: HashMap> = HashMap::new(); + for e in &node_entries { + if let Some((parent_id, position)) = &e.parent { + children_by_parent + .entry(parent_id.clone()) + .or_default() + .push((e.id.clone(), position.clone())); + } + } + for children in children_by_parent.values_mut() { + children.sort_by(|a, b| a.1.cmp(&b.1)); + } + + let node_pairs: Vec<_> = node_entries + .iter() + .filter_map(|e| Some((get_id(&e.id)?, e.node.clone()))) + .collect(); + + let internal_links: HashMap<_, Vec<_>> = children_by_parent + .iter() + .filter_map(|(parent_str, children)| { + let parent_internal = get_id(parent_str)?; + let child_internals: Vec<_> = children + .iter() + .filter_map(|(child_str, _)| get_id(child_str)) + .collect(); + if child_internals.is_empty() { + None + } else { + Some((parent_internal, child_internals)) + } + }) + .collect(); + + // ── 5. Produce one Scene per listed scene id ────────────────────────────── + let mut scenes: Vec = Vec::new(); + + let iter: Box> = if !scene_ids_ordered.is_empty() { + Box::new(scene_ids_ordered.iter()) + } else { + Box::new(scene_metas.keys()) + }; + + for scene_id_str in iter { + let meta = scene_metas.get(scene_id_str); + let name = meta.map(|m| m.name.clone()).unwrap_or_default(); + let background_color = meta.and_then(|m| m.background_color); + + let roots_strings = children_by_parent + .get(scene_id_str) + .cloned() + .unwrap_or_default(); + let roots_internal: Vec<_> = roots_strings + .iter() + .filter_map(|(child_str, _)| get_id(child_str)) + .collect(); + + let graph = SceneGraph::new_from_snapshot( + node_pairs.clone(), + internal_links.clone(), + roots_internal, + ); + + scenes.push(Scene { + name, + graph, + background_color, + }); + } + + // Build the reverse id map (internal → string) for round-trip encoding. + let id_map: HashMap = string_to_internal_id + .iter() + .map(|(s, &nid)| (nid, s.clone())) + .collect(); + + // Build the position map (internal NodeId → original position string) + // so the encoder can preserve child ordering exactly. + let mut position_map: HashMap = HashMap::new(); + for e in &node_entries { + if let Some((_parent_id, position)) = &e.parent { + if let Some(&nid) = string_to_internal_id.get(&e.id) { + position_map.insert(nid, position.clone()); + } + } + } + + Ok(DecodeResult { + scenes, + id_map, + scene_ids: scene_ids_ordered, + position_map, + }) +} + +// ───────────────────────────────────────────────────────────────────────────── +// Hierarchy helpers +// ───────────────────────────────────────────────────────────────────────────── + +fn decode_parent_ref(layer: &fbs::LayerTrait<'_>) -> Option<(String, String)> { + let parent_ref = layer.parent(); + let parent_id = parent_ref.parent_id().id().to_owned(); + if parent_id.is_empty() { + return None; + } + let position = parent_ref.position().unwrap_or("").to_owned(); + Some((parent_id, position)) +} + +// ───────────────────────────────────────────────────────────────────────────── +// Color helpers +// ───────────────────────────────────────────────────────────────────────────── + +fn decode_rgba32f_to_cg_color(rgba: &fbs::RGBA32F) -> CGColor { + CGColor { + r: (rgba.r().clamp(0.0, 1.0) * 255.0).round() as u8, + g: (rgba.g().clamp(0.0, 1.0) * 255.0).round() as u8, + b: (rgba.b().clamp(0.0, 1.0) * 255.0).round() as u8, + a: (rgba.a().clamp(0.0, 1.0) * 255.0).round() as u8, + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Enum mapping macro + all enum conversions +// ───────────────────────────────────────────────────────────────────────────── + +/// Generate a matched pair of `decode_*` and `encode_*` functions for a +/// 1-to-1 enum mapping between an FBS type and a Rust type. +/// +/// Syntax: +/// `enum_map!(decode_fn, encode_fn, FbsType, RustType, default, { Variant1, Variant2, … });` +/// +/// The `default` is returned by `decode_fn` when the FBS value doesn't match +/// any listed variant (forward-compat for new enum members added later). +macro_rules! enum_map { + ($decode:ident, $encode:ident, $fbs:ty, $rust:ty, $default:expr, { $($v:ident),+ $(,)? }) => { + fn $decode(v: $fbs) -> $rust { + match v { $( <$fbs>::$v => <$rust>::$v, )+ _ => $default, } + } + fn $encode(v: $rust) -> $fbs { + match v { $( <$rust>::$v => <$fbs>::$v, )+ } + } + }; +} + +enum_map!(decode_blend_mode, encode_blend_mode, fbs::BlendMode, BlendMode, BlendMode::Normal, { + Normal, Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn, + HardLight, SoftLight, Difference, Exclusion, Hue, Saturation, Color, Luminosity, +}); + +fn decode_layer_blend_mode(fbs_mode: fbs::LayerBlendMode) -> LayerBlendMode { + match fbs_mode { + fbs::LayerBlendMode::PassThrough => LayerBlendMode::PassThrough, + other => LayerBlendMode::Blend(decode_blend_mode(fbs::BlendMode(other.0))), + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Paint decoding +// ───────────────────────────────────────────────────────────────────────────── + +fn decode_gradient_stops(stops: flatbuffers::Vector<'_, fbs::GradientStop>) -> Vec { + (0..stops.len()) + .map(|i| { + let s = stops.get(i); + let color = decode_rgba32f_to_cg_color(s.stop_color()); + GradientStop { + offset: s.stop_offset(), + color, + } + }) + .collect() +} + +fn decode_fbs_transform(t: &fbs::CGTransform2D) -> AffineTransform { + AffineTransform::from_acebdf(t.m00(), t.m01(), t.m02(), t.m10(), t.m11(), t.m12()) +} + +fn extract_rotation_degrees(transform: Option<&fbs::CGTransform2D>) -> f32 { + match transform { + Some(t) => t.m10().atan2(t.m00()).to_degrees(), + None => 0.0, + } +} + +/// Extract the raw (cos, sin) pair directly from the `CGTransform2D` matrix, +/// avoiding the lossy `atan2 → to_degrees → to_radians → sin_cos` chain. +fn extract_rotation_cos_sin(transform: Option<&fbs::CGTransform2D>) -> (f32, f32) { + match transform { + Some(t) => (t.m00(), t.m10()), + None => (1.0, 0.0), + } +} + +fn decode_paint_item(item: &fbs::PaintStackItem<'_>) -> Option { + match item.paint_type() { + fbs::Paint::SolidPaint => { + let sp = item.paint_as_solid_paint()?; + let color = sp + .color() + .map(decode_rgba32f_to_cg_color) + .unwrap_or(CGColor::TRANSPARENT); + Some(Paint::Solid(SolidPaint { + active: sp.active(), + color, + blend_mode: decode_blend_mode(sp.blend_mode()), + })) + } + fbs::Paint::LinearGradientPaint => { + let lgp = item.paint_as_linear_gradient_paint()?; + let stops = lgp.stops().map(decode_gradient_stops).unwrap_or_default(); + let transform = lgp + .transform() + .map(decode_fbs_transform) + .unwrap_or_default(); + let xy1 = lgp + .xy1() + .map(|a| Alignment(a.x(), a.y())) + .unwrap_or(Alignment::CENTER_LEFT); + let xy2 = lgp + .xy2() + .map(|a| Alignment(a.x(), a.y())) + .unwrap_or(Alignment::CENTER_RIGHT); + Some(Paint::LinearGradient(LinearGradientPaint { + active: lgp.active(), + xy1, + xy2, + tile_mode: TileMode::default(), + transform, + stops, + opacity: lgp.opacity(), + blend_mode: decode_blend_mode(lgp.blend_mode()), + })) + } + fbs::Paint::RadialGradientPaint => { + let rgp = item.paint_as_radial_gradient_paint()?; + let stops = rgp.stops().map(decode_gradient_stops).unwrap_or_default(); + let transform = rgp + .transform() + .map(decode_fbs_transform) + .unwrap_or_default(); + Some(Paint::RadialGradient(RadialGradientPaint { + active: rgp.active(), + transform, + stops, + opacity: rgp.opacity(), + blend_mode: decode_blend_mode(rgp.blend_mode()), + tile_mode: TileMode::default(), + })) + } + fbs::Paint::SweepGradientPaint => { + let sgp = item.paint_as_sweep_gradient_paint()?; + let stops = sgp.stops().map(decode_gradient_stops).unwrap_or_default(); + let transform = sgp + .transform() + .map(decode_fbs_transform) + .unwrap_or_default(); + Some(Paint::SweepGradient(SweepGradientPaint { + active: sgp.active(), + transform, + stops, + opacity: sgp.opacity(), + blend_mode: decode_blend_mode(sgp.blend_mode()), + })) + } + fbs::Paint::ImagePaint => { + let ip = item.paint_as_image_paint()?; + let image_ref = if let Some(hash_ref) = ip.image_as_resource_ref_hash() { + ResourceRef::HASH(hash_ref.hash().unwrap_or("").to_owned()) + } else if let Some(rid_ref) = ip.image_as_resource_ref_rid() { + ResourceRef::RID(rid_ref.rid().unwrap_or("").to_owned()) + } else { + return None; + }; + let alignement = ip + .alignement() + .map(|a| Alignment(a.x(), a.y())) + .unwrap_or(Alignment::CENTER); + let fit = decode_image_paint_fit(&ip); + Some(Paint::Image(ImagePaint { + active: ip.active(), + image: image_ref, + quarter_turns: ip.quarter_turns(), + alignement, + fit, + opacity: ip.opacity(), + blend_mode: decode_blend_mode(ip.blend_mode()), + filters: ImageFilters::default(), + })) + } + _ => None, + } +} + +fn decode_image_paint_fit(ip: &fbs::ImagePaint<'_>) -> ImagePaintFit { + match ip.fit_type() { + fbs::ImagePaintFit::ImagePaintFitFit => { + let box_fit = ip + .fit_as_image_paint_fit_fit() + .map(|f| decode_box_fit(f.box_fit())) + .unwrap_or(BoxFit::Cover); + ImagePaintFit::Fit(box_fit) + } + fbs::ImagePaintFit::ImagePaintFitTransform => { + let transform = ip + .fit_as_image_paint_fit_transform() + .and_then(|f| f.transform()) + .map(decode_fbs_transform) + .unwrap_or_default(); + ImagePaintFit::Transform(transform) + } + _ => ImagePaintFit::Fit(BoxFit::Cover), + } +} + +enum_map!(decode_box_fit, encode_box_fit, fbs::BoxFit, BoxFit, BoxFit::Cover, { + Contain, Cover, Fill, None, +}); + +fn decode_paints_vec( + vec: Option>>>, +) -> Paints { + let items = match vec { + Some(v) => v, + None => return Paints::new(Vec::::new()), + }; + let paints: Vec<_> = (0..items.len()) + .filter_map(|i| decode_paint_item(&items.get(i))) + .collect(); + Paints::new(paints) +} + +// ───────────────────────────────────────────────────────────────────────────── +// Effects decoding +// ───────────────────────────────────────────────────────────────────────────── + +/// Decode a blur union (currently always Gaussian) from the FBS blur payload. +fn decode_fe_blur(gaussian: Option>) -> FeBlur { + FeBlur::Gaussian(FeGaussianBlur { + radius: gaussian.map(|g| g.radius()).unwrap_or(0.0), + }) +} + +fn decode_layer_effects(effects: Option>) -> LayerEffects { + let effects = match effects { + Some(e) => e, + None => return LayerEffects::default(), + }; + + let mut out = LayerEffects::default(); + + if let Some(lb) = effects.fe_blur() { + out.blur = Some(FeLayerBlur { + blur: decode_fe_blur(lb.blur_as_fe_gaussian_blur()), + active: lb.active(), + }); + } + + if let Some(bb) = effects.fe_backdrop_blur() { + out.backdrop_blur = Some(FeBackdropBlur { + blur: decode_fe_blur(bb.blur_as_fe_gaussian_blur()), + active: bb.active(), + }); + } + + if let Some(shadows_vec) = effects.fe_shadows() { + for i in 0..shadows_vec.len() { + let effect = shadows_vec.get(i); + if let Some(shadow_fbs) = effect.shadow() { + let shadow = decode_fe_shadow(&shadow_fbs); + if effect.kind() == fbs::FilterShadowEffectKind::InnerShadow { + out.shadows.push(FilterShadowEffect::InnerShadow(shadow)); + } else { + out.shadows.push(FilterShadowEffect::DropShadow(shadow)); + } + } + } + } + + if let Some(lg) = effects.fe_glass() { + out.glass = Some(FeLiquidGlass { + light_intensity: lg.light_intensity(), + light_angle: lg.light_angle(), + refraction: lg.refraction(), + depth: lg.depth(), + dispersion: lg.dispersion(), + blur_radius: lg.blur_radius(), + active: lg.active(), + }); + } + + if let Some(noises_vec) = effects.fe_noises() { + for i in 0..noises_vec.len() { + let ne = noises_vec.get(i); + out.noises.push(decode_fe_noise(&ne)); + } + } + + out +} + +fn decode_fe_shadow(s: &fbs::FeShadow<'_>) -> FeShadow { + FeShadow { + dx: s.dx(), + dy: s.dy(), + blur: s.blur(), + spread: s.spread(), + color: s.color().map(decode_rgba32f_to_cg_color).unwrap_or(CGColor { r: 0, g: 0, b: 0, a: 64 }), + active: s.active(), + } +} + +fn decode_fe_noise(ne: &fbs::FeNoiseEffect<'_>) -> FeNoiseEffect { + const DEFAULT_MONO: CGColor = CGColor { r: 0, g: 0, b: 0, a: 64 }; + let default_mono = || NoiseEffectColors::Mono { color: DEFAULT_MONO }; + + let coloring = ne + .coloring() + .map(|c| match c.kind() { + fbs::NoiseEffectColorsKind::Mono => NoiseEffectColors::Mono { + color: c.mono_color().map(decode_rgba32f_to_cg_color).unwrap_or(DEFAULT_MONO), + }, + fbs::NoiseEffectColorsKind::Duo => NoiseEffectColors::Duo { + color1: c.duo_color1().map(decode_rgba32f_to_cg_color).unwrap_or(CGColor { r: 0, g: 0, b: 0, a: 128 }), + color2: c.duo_color2().map(decode_rgba32f_to_cg_color).unwrap_or(CGColor { r: 255, g: 255, b: 255, a: 128 }), + }, + fbs::NoiseEffectColorsKind::Multi => NoiseEffectColors::Multi { opacity: c.multi_opacity() }, + _ => default_mono(), + }) + .unwrap_or_else(default_mono); + + FeNoiseEffect { + active: ne.active(), + noise_size: ne.noise_size(), + density: ne.density(), + num_octaves: ne.num_octaves(), + seed: ne.seed(), + coloring, + blend_mode: decode_blend_mode(ne.blend_mode()), + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Stroke decoding +// ───────────────────────────────────────────────────────────────────────────── + +fn decode_stroke_style_from_fbs(ss: Option>) -> StrokeStyle { + let ss = match ss { + Some(s) => s, + None => return StrokeStyle::default(), + }; + StrokeStyle { + stroke_align: decode_stroke_align(ss.stroke_align()), + stroke_cap: decode_stroke_cap(ss.stroke_cap()), + stroke_join: decode_stroke_join(ss.stroke_join()), + stroke_miter_limit: StrokeMiterLimit(ss.stroke_miter_limit()), + stroke_dash_array: ss + .stroke_dash_array() + .filter(|v| v.len() > 0) + .map(|v| StrokeDashArray((0..v.len()).map(|i| v.get(i)).collect())), + } +} + +enum_map!(decode_stroke_align, encode_stroke_align, fbs::StrokeAlign, StrokeAlign, StrokeAlign::Center, { + Inside, Center, Outside, +}); +enum_map!(decode_stroke_cap, encode_stroke_cap, fbs::StrokeCap, StrokeCap, StrokeCap::Butt, { + Butt, Round, Square, +}); +enum_map!(decode_stroke_join, encode_stroke_join, fbs::StrokeJoin, StrokeJoin, StrokeJoin::Miter, { + Miter, Round, Bevel, +}); +enum_map!(decode_stroke_marker, encode_stroke_marker, fbs::StrokeMarkerPreset, StrokeMarkerPreset, StrokeMarkerPreset::None, { + None, RightTriangleOpen, EquilateralTriangle, Circle, Square, Diamond, VerticalBar, +}); +enum_map!(decode_boolean_path_op, encode_boolean_path_op, fbs::BooleanPathOperation, BooleanPathOperation, BooleanPathOperation::Union, { + Union, Intersection, Difference, Xor, +}); +enum_map!(decode_text_align, encode_text_align, fbs::TextAlign, TextAlign, TextAlign::Left, { + Left, Center, Right, Justify, +}); +enum_map!(decode_text_align_vertical, encode_text_align_vertical, fbs::TextAlignVertical, TextAlignVertical, TextAlignVertical::Top, { + Top, Center, Bottom, +}); + +/// Decode a `StrokeGeometryTrait` into `(StrokeStyle, f32 stroke_width)`. +fn decode_stroke_geometry_trait(sg: Option>) -> (StrokeStyle, f32) { + let sg = match sg { + Some(s) => s, + None => return (StrokeStyle::default(), 0.0), + }; + let style = decode_stroke_style_from_fbs(sg.stroke_style()); + (style, sg.stroke_width()) +} + +/// Decode a `RectangularStrokeGeometryTrait` into `(StrokeStyle, StrokeWidth)`. +fn decode_rectangular_stroke_geometry( + sg: Option>, +) -> (StrokeStyle, StrokeWidth) { + let sg = match sg { + Some(s) => s, + None => return (StrokeStyle::default(), StrokeWidth::None), + }; + let style = decode_stroke_style_from_fbs(sg.stroke_style()); + let width = match sg.rectangular_stroke_width() { + Some(rsw) => { + let top = rsw.stroke_top_width(); + let right = rsw.stroke_right_width(); + let bottom = rsw.stroke_bottom_width(); + let left = rsw.stroke_left_width(); + if top == right && right == bottom && bottom == left { + if top == 0.0 { + StrokeWidth::None + } else { + StrokeWidth::Uniform(top) + } + } else { + StrokeWidth::Rectangular(RectangularStrokeWidth { + stroke_top_width: top, + stroke_right_width: right, + stroke_bottom_width: bottom, + stroke_left_width: left, + }) + } + } + None => StrokeWidth::None, + }; + (style, width) +} + +// ───────────────────────────────────────────────────────────────────────────── +// Corner radius / smoothing +// ───────────────────────────────────────────────────────────────────────────── + +fn decode_corner_radius(cr: Option>) -> RectangularCornerRadius { + use crate::cg::types::Radius; + match cr.and_then(|t| t.rectangular_corner_radius()) { + Some(rcr) => RectangularCornerRadius { + tl: Radius::elliptical(rcr.tl().rx(), rcr.tl().ry()), + tr: Radius::elliptical(rcr.tr().rx(), rcr.tr().ry()), + bl: Radius::elliptical(rcr.bl().rx(), rcr.bl().ry()), + br: Radius::elliptical(rcr.br().rx(), rcr.br().ry()), + }, + None => RectangularCornerRadius::default(), + } +} + +fn decode_corner_smoothing(cr: Option>) -> CornerSmoothing { + match cr { + Some(cr) => CornerSmoothing(cr.corner_smoothing()), + None => CornerSmoothing::default(), + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Layout decoding +// ───────────────────────────────────────────────────────────────────────────── + +/// Extract (x, y) from the layout position, regardless of whether it is encoded +/// as Cartesian or Inset. For Inset, `left` and `top` are used as x and y +/// (matching the JSON path where `layout_inset_left`/`layout_inset_top` are the +/// position of non-container shapes). +fn decode_layout_xy(ls: &fbs::LayoutStyle<'_>) -> (f32, f32) { + match ls.layout_position_type() { + fbs::LayoutPositioningBasis::LayoutPositioningCartesian => ls + .layout_position_as_layout_positioning_cartesian() + .map(|c| (c.x(), c.y())) + .unwrap_or((0.0, 0.0)), + fbs::LayoutPositioningBasis::LayoutPositioningInset => ls + .layout_position_as_layout_positioning_inset() + .map(|inset| { + let left = inset.left().and_then(|v| v.value()).unwrap_or(0.0); + let top = inset.top().and_then(|v| v.value()).unwrap_or(0.0); + (left, top) + }) + .unwrap_or((0.0, 0.0)), + _ => (0.0, 0.0), + } +} + +fn decode_layout_position(ls: &fbs::LayoutStyle<'_>) -> LayoutPositioningBasis { + match ls.layout_position_type() { + fbs::LayoutPositioningBasis::LayoutPositioningCartesian => { + if let Some(cart) = ls.layout_position_as_layout_positioning_cartesian() { + LayoutPositioningBasis::Cartesian(CGPoint::new(cart.x(), cart.y())) + } else { + LayoutPositioningBasis::zero() + } + } + fbs::LayoutPositioningBasis::LayoutPositioningInset => { + if let Some(inset) = ls.layout_position_as_layout_positioning_inset() { + let top = inset.top().and_then(|v| v.value()).unwrap_or(0.0); + let right = inset.right().and_then(|v| v.value()).unwrap_or(0.0); + let bottom = inset.bottom().and_then(|v| v.value()).unwrap_or(0.0); + let left = inset.left().and_then(|v| v.value()).unwrap_or(0.0); + LayoutPositioningBasis::Inset(EdgeInsets { + top, + right, + bottom, + left, + }) + } else { + LayoutPositioningBasis::zero() + } + } + _ => LayoutPositioningBasis::zero(), + } +} + +fn decode_dimensions(ls: &fbs::LayoutStyle<'_>) -> (Option, Option) { + match ls.layout_dimensions() { + Some(dim) => { + let w = decode_dimension_value(dim.layout_target_width()); + let h = decode_dimension_value(dim.layout_target_height()); + (w, h) + } + None => (None, None), + } +} + +fn decode_dimension_value(dv: Option>) -> Option { + let dv = dv?; + match dv.unit() { + fbs::LayoutDimensionUnit::LengthPx => dv.value(), + _ => None, + } +} + +fn decode_layout_dimension_style(ls: &fbs::LayoutStyle<'_>) -> LayoutDimensionStyle { + let dim = ls.layout_dimensions(); + LayoutDimensionStyle { + layout_target_width: dim + .as_ref() + .and_then(|d| decode_dimension_value(d.layout_target_width())), + layout_target_height: dim + .as_ref() + .and_then(|d| decode_dimension_value(d.layout_target_height())), + layout_min_width: None, + layout_max_width: None, + layout_min_height: None, + layout_max_height: None, + layout_target_aspect_ratio: None, + } +} + +fn decode_layout_container_style(ls: &fbs::LayoutStyle<'_>) -> LayoutContainerStyle { + match ls.layout_container() { + Some(lc) => { + let layout_mode = if lc.layout_mode() == fbs::LayoutMode::Flex { + LayoutMode::Flex + } else { + LayoutMode::Normal + }; + let layout_direction = if lc.layout_direction() == fbs::Axis::Vertical { + Axis::Vertical + } else { + Axis::Horizontal + }; + let layout_wrap = match lc.layout_wrap() { + fbs::LayoutWrap::Wrap => Some(LayoutWrap::Wrap), + fbs::LayoutWrap::NoWrap => Some(LayoutWrap::NoWrap), + _ => None, + }; + let layout_main_axis_alignment = + decode_main_axis_alignment(lc.layout_main_axis_alignment()); + let layout_cross_axis_alignment = + decode_cross_axis_alignment(lc.layout_cross_axis_alignment()); + let layout_padding = lc.layout_padding().map(|p| EdgeInsets { + top: p.top(), + right: p.right(), + bottom: p.bottom(), + left: p.left(), + }); + let main_gap = lc.layout_main_axis_gap(); + let cross_gap = lc.layout_cross_axis_gap(); + let layout_gap = if main_gap > 0.0 || cross_gap > 0.0 { + Some(LayoutGap { + main_axis_gap: main_gap, + cross_axis_gap: cross_gap, + }) + } else { + None + }; + LayoutContainerStyle { + layout_mode, + layout_direction, + layout_wrap, + layout_main_axis_alignment, + layout_cross_axis_alignment, + layout_padding, + layout_gap, + } + } + None => LayoutContainerStyle::default(), + } +} + +/// Like `enum_map!` but the decode function returns `Option` — `None` +/// for any FBS value not in the listed variants (e.g. the FBS `None` sentinel). +macro_rules! enum_map_opt { + ($decode:ident, $encode:ident, $fbs:ty, $rust:ty, { $($v:ident),+ $(,)? }) => { + fn $decode(v: $fbs) -> Option<$rust> { + match v { $( <$fbs>::$v => Some(<$rust>::$v), )+ _ => None, } + } + fn $encode(v: $rust) -> $fbs { + match v { $( <$rust>::$v => <$fbs>::$v, )+ } + } + }; +} + +enum_map_opt!(decode_main_axis_alignment, encode_main_axis_alignment, fbs::MainAxisAlignment, MainAxisAlignment, { + Start, Center, End, SpaceBetween, SpaceAround, SpaceEvenly, Stretch, +}); +enum_map_opt!(decode_cross_axis_alignment, encode_cross_axis_alignment, fbs::CrossAxisAlignment, CrossAxisAlignment, { + Start, Center, End, Stretch, +}); + +fn decode_layout_child_style(ls: &fbs::LayoutStyle<'_>) -> Option { + let lc = ls.layout_child()?; + let layout_positioning = match lc.layout_positioning() { + fbs::LayoutPositioning::Absolute => LayoutPositioning::Absolute, + _ => LayoutPositioning::Auto, + }; + Some(LayoutChildStyle { + layout_grow: lc.layout_grow(), + layout_positioning, + }) +} + +fn decode_mask_type(fbs_mask_type: fbs::LayerMaskType) -> Option { + use crate::cg::types::ImageMaskType; + match fbs_mask_type { + fbs::LayerMaskType::NONE => None, + fbs::LayerMaskType::LayerMaskTypeImage => Some(LayerMaskType::Image(ImageMaskType::Alpha)), + fbs::LayerMaskType::LayerMaskTypeGeometry => Some(LayerMaskType::Geometry), + _ => None, + } +} + +// ═════════════════════════════════════════════════════════════════════════════ +// Node-specific decoders +// +// Every function below receives a pre-decoded `LayerCommon` so the shared +// fields (active, opacity, blend_mode, mask, effects, rotation, layout_child) +// are decoded exactly once and cannot diverge between node types. +// ═════════════════════════════════════════════════════════════════════════════ + +fn decode_vector_network(vnd: Option>) -> VectorNetwork { + let Some(vnd) = vnd else { + return VectorNetwork::default(); + }; + + let vertices: Vec<(f32, f32)> = vnd + .vertices() + .map(|v| (0..v.len()).map(|i| { let p = v.get(i); (p.x(), p.y()) }).collect()) + .unwrap_or_default(); + + let segments: Vec = vnd + .segments() + .map(|s| { + (0..s.len()) + .map(|i| { + let seg = s.get(i); + VectorNetworkSegment { + a: seg.segment_vertex_a() as usize, + b: seg.segment_vertex_b() as usize, + ta: (seg.tangent_a().x(), seg.tangent_a().y()), + tb: (seg.tangent_b().x(), seg.tangent_b().y()), + } + }) + .collect() + }) + .unwrap_or_default(); + + let regions: Vec = vnd + .regions() + .map(|rs| { + (0..rs.len()) + .filter_map(|i| { + let region = rs.get(i); + let loops: Vec = region + .region_loops() + .map(|ls| { + (0..ls.len()) + .filter_map(|j| { + let lp = ls.get(j); + lp.loop_segment_indices().map(|idx| { + VectorNetworkLoop( + (0..idx.len()).map(|k| idx.get(k) as usize).collect(), + ) + }) + }) + .collect() + }) + .unwrap_or_default(); + let fill_rule = match region.region_fill_rule() { + fbs::FillRule::EvenOdd => crate::cg::types::FillRule::EvenOdd, + _ => crate::cg::types::FillRule::NonZero, + }; + let fills = region + .region_fill_paints() + .map(|p| decode_paints_vec(Some(p))); + Some(VectorNetworkRegion { + loops, + fill_rule, + fills, + }) + }) + .collect() + }) + .unwrap_or_default(); + + VectorNetwork { + vertices, + segments, + regions, + } +} + +fn decode_group_node( + lc: &LayerCommon, + layer: &fbs::LayerTrait<'_>, + _gn: &fbs::GroupNode<'_>, +) -> Node { + let sl = decode_shape_layout(layer, lc.rotation_cos_sin); + Node::Group(GroupNodeRec { + active: lc.active, + opacity: lc.opacity, + blend_mode: lc.blend_mode, + mask: lc.mask, + transform: Some(sl.transform), + }) +} + +fn decode_container_node( + lc: &LayerCommon, + layer: &fbs::LayerTrait<'_>, + cn: &fbs::ContainerNode<'_>, +) -> Node { + let layout = layer.layout(); + let position = layout.as_ref().map(decode_layout_position).unwrap_or_default(); + let layout_container = layout.as_ref().map(decode_layout_container_style).unwrap_or_default(); + let layout_dimensions = layout.as_ref().map(decode_layout_dimension_style).unwrap_or_default(); + let (stroke_style, stroke_width) = decode_rectangular_stroke_geometry(cn.stroke_geometry()); + + Node::Container(ContainerNodeRec { + active: lc.active, + opacity: lc.opacity, + blend_mode: lc.blend_mode, + mask: lc.mask, + rotation: lc.rotation, + position, + layout_container, + layout_dimensions, + layout_child: lc.layout_child.clone(), + corner_radius: decode_corner_radius(cn.corner_radius()), + corner_smoothing: decode_corner_smoothing(cn.corner_radius()), + fills: decode_paints_vec(cn.fill_paints()), + strokes: decode_paints_vec(cn.stroke_paints()), + stroke_style, + stroke_width, + effects: lc.effects.clone(), + clip: cn.clips_content() as ContainerClipFlag, + }) +} + +fn decode_initial_container_node( + lc: &LayerCommon, + layer: &fbs::LayerTrait<'_>, + _icn: &fbs::InitialContainerNode<'_>, +) -> Node { + let layout = layer.layout(); + let lcs = layout.as_ref().map(decode_layout_container_style).unwrap_or_default(); + Node::InitialContainer(InitialContainerNodeRec { + active: lc.active, + layout_mode: lcs.layout_mode, + layout_direction: lcs.layout_direction, + layout_wrap: lcs.layout_wrap.unwrap_or(LayoutWrap::NoWrap), + layout_main_axis_alignment: lcs.layout_main_axis_alignment.unwrap_or(MainAxisAlignment::Start), + layout_cross_axis_alignment: lcs.layout_cross_axis_alignment.unwrap_or(CrossAxisAlignment::Start), + padding: lcs.layout_padding.unwrap_or_default(), + layout_gap: lcs.layout_gap.unwrap_or(LayoutGap { + main_axis_gap: 0.0, + cross_axis_gap: 0.0, + }), + }) +} + +fn decode_basic_shape_node( + lc: &LayerCommon, + layer: &fbs::LayerTrait<'_>, + bsn: &fbs::BasicShapeNode<'_>, +) -> Node { + use fbs::CanonicalLayerShape as BST; + + let sl = decode_shape_layout(layer, lc.rotation_cos_sin); + let fills = decode_paints_vec(bsn.fill_paints()); + let strokes = decode_paints_vec(bsn.stroke_paints()); + // For rectangles the TS encoder writes per-corner rectangular_corner_radius; + // for polygons/stars it writes the scalar corner_radius field. + let corner_radius = { + use crate::cg::types::Radius; + if let Some(rcr) = bsn.rectangular_corner_radius() { + RectangularCornerRadius { + tl: Radius::elliptical(rcr.tl().rx(), rcr.tl().ry()), + tr: Radius::elliptical(rcr.tr().rx(), rcr.tr().ry()), + bl: Radius::elliptical(rcr.bl().rx(), rcr.bl().ry()), + br: Radius::elliptical(rcr.br().rx(), rcr.br().ry()), + } + } else { + let r = Radius::circular(bsn.corner_radius()); + RectangularCornerRadius { tl: r, tr: r, bl: r, br: r } + } + }; + let stroke_style = decode_stroke_style_from_fbs(bsn.stroke_style()); + let stroke_width_f32 = bsn.stroke_width(); + + match bsn.shape_type() { + BST::CanonicalShapeRectangular => Node::Rectangle(RectangleNodeRec { + active: lc.active, + opacity: lc.opacity, + blend_mode: lc.blend_mode, + mask: lc.mask, + transform: sl.transform, + size: sl.size, + corner_radius, + corner_smoothing: CornerSmoothing::default(), + fills, + strokes, + stroke_style, + stroke_width: if stroke_width_f32 == 0.0 { + StrokeWidth::None + } else { + StrokeWidth::Uniform(stroke_width_f32) + }, + effects: lc.effects.clone(), + layout_child: lc.layout_child.clone(), + }), + BST::CanonicalShapeElliptical => { + let ring = bsn + .shape_as_canonical_shape_elliptical() + .and_then(|s| s.ring_sector_data()); + let (inner_radius, start_angle, angle) = match ring { + Some(r) => { + let ir = r.inner_radius_ratio(); + let sa = r.start_angle(); + let a = r.angle(); + ( + if ir != 0.0 { Some(ir) } else { None }, + sa, + if a != 360.0 { Some(a) } else { None }, + ) + } + None => (None, 0.0, None), + }; + Node::Ellipse(EllipseNodeRec { + active: lc.active, + opacity: lc.opacity, + blend_mode: lc.blend_mode, + mask: lc.mask, + transform: sl.transform, + size: sl.size, + fills, + strokes, + stroke_style, + stroke_width: singular_stroke_width(stroke_width_f32), + inner_radius, + start_angle, + angle, + // corner_radius is not in the FBS schema; defaults to None + corner_radius: None, + effects: lc.effects.clone(), + layout_child: lc.layout_child.clone(), + }) + } + BST::CanonicalShapeRegularPolygon => { + let point_count = bsn + .shape_as_canonical_shape_regular_polygon() + .map(|s| s.point_count() as usize) + .unwrap_or(5); + Node::RegularPolygon(RegularPolygonNodeRec { + active: lc.active, + opacity: lc.opacity, + blend_mode: lc.blend_mode, + mask: lc.mask, + transform: sl.transform, + size: sl.size, + point_count, + corner_radius: corner_radius.tl.rx, + fills, + strokes, + stroke_style, + stroke_width: singular_stroke_width(stroke_width_f32), + effects: lc.effects.clone(), + layout_child: lc.layout_child.clone(), + }) + } + BST::CanonicalShapeRegularStarPolygon => { + let (point_count, inner_radius) = bsn + .shape_as_canonical_shape_regular_star_polygon() + .map(|s| (s.point_count() as usize, s.inner_radius_ratio())) + .unwrap_or((5, 0.4)); + Node::RegularStarPolygon(RegularStarPolygonNodeRec { + active: lc.active, + opacity: lc.opacity, + blend_mode: lc.blend_mode, + mask: lc.mask, + transform: sl.transform, + size: sl.size, + point_count, + inner_radius, + corner_radius: corner_radius.tl.rx, + fills, + strokes, + stroke_style, + stroke_width: singular_stroke_width(stroke_width_f32), + effects: lc.effects.clone(), + layout_child: lc.layout_child.clone(), + }) + } + _ => Node::Vector(VectorNodeRec { + active: lc.active, + opacity: lc.opacity, + blend_mode: lc.blend_mode, + mask: lc.mask, + transform: sl.transform, + network: VectorNetwork::default(), + corner_radius: 0.0, + fills, + strokes, + stroke_width: stroke_width_f32, + stroke_width_profile: None, + stroke_align: stroke_style.stroke_align, + stroke_cap: stroke_style.stroke_cap, + stroke_join: stroke_style.stroke_join, + stroke_miter_limit: stroke_style.stroke_miter_limit, + stroke_dash_array: stroke_style.stroke_dash_array, + marker_start_shape: StrokeMarkerPreset::None, + marker_end_shape: StrokeMarkerPreset::None, + layout_child: lc.layout_child.clone(), + effects: lc.effects.clone(), + }), + } +} + +fn decode_vector_node( + lc: &LayerCommon, + layer: &fbs::LayerTrait<'_>, + vn: &fbs::VectorNode<'_>, +) -> Node { + let sl = decode_shape_layout(layer, lc.rotation_cos_sin); + let (stroke_style, stroke_width_f32) = decode_stroke_geometry_trait(vn.stroke_geometry()); + + Node::Vector(VectorNodeRec { + active: lc.active, + opacity: lc.opacity, + blend_mode: lc.blend_mode, + mask: lc.mask, + transform: sl.transform, + network: decode_vector_network(vn.vector_network_data()), + corner_radius: 0.0, + fills: decode_paints_vec(vn.fill_paints()), + strokes: decode_paints_vec(vn.stroke_paints()), + stroke_width: stroke_width_f32, + stroke_width_profile: None, + stroke_align: stroke_style.stroke_align, + stroke_cap: stroke_style.stroke_cap, + stroke_join: stroke_style.stroke_join, + stroke_miter_limit: stroke_style.stroke_miter_limit, + stroke_dash_array: stroke_style.stroke_dash_array, + marker_start_shape: decode_stroke_marker(vn.marker_start_shape()), + marker_end_shape: decode_stroke_marker(vn.marker_end_shape()), + layout_child: lc.layout_child.clone(), + effects: lc.effects.clone(), + }) +} + +fn decode_line_node( + lc: &LayerCommon, + layer: &fbs::LayerTrait<'_>, + ln: &fbs::LineNode<'_>, +) -> Node { + let sl = decode_shape_layout(layer, lc.rotation_cos_sin); + let sg = ln.stroke_geometry(); + let stroke_width = sg.as_ref().map(|s| s.stroke_width()).unwrap_or(0.0); + let stroke_cap = sg + .as_ref() + .and_then(|s| s.stroke_style()) + .map(|ss| decode_stroke_cap(ss.stroke_cap())) + .unwrap_or_default(); + let miter_limit = sg + .as_ref() + .and_then(|s| s.stroke_style()) + .map(|ss| StrokeMiterLimit(ss.stroke_miter_limit())) + .unwrap_or_default(); + let stroke_dash_array = sg + .as_ref() + .and_then(|s| s.stroke_style()) + .and_then(|ss| { + ss.stroke_dash_array() + .filter(|v| v.len() > 0) + .map(|v| StrokeDashArray((0..v.len()).map(|i| v.get(i)).collect())) + }); + + // Lines use translation + rotation (no center-origin) and height=0. + // Use raw cos/sin to avoid lossy degree conversion. + let (cos, sin) = lc.rotation_cos_sin; + let transform = AffineTransform::from_translation_rotation_raw(sl.x, sl.y, cos, sin); + let size = Size { + width: sl.size.width, + height: 0.0, + }; + + Node::Line(LineNodeRec { + active: lc.active, + opacity: lc.opacity, + blend_mode: lc.blend_mode, + mask: lc.mask, + transform, + size, + strokes: decode_paints_vec(ln.stroke_paints()), + stroke_width, + stroke_cap, + stroke_miter_limit: miter_limit, + stroke_dash_array, + _data_stroke_align: StrokeAlign::Center, + effects: lc.effects.clone(), + layout_child: lc.layout_child.clone(), + marker_start_shape: decode_stroke_marker(ln.marker_start_shape()), + marker_end_shape: decode_stroke_marker(ln.marker_end_shape()), + }) +} + +fn decode_boolean_operation_node( + lc: &LayerCommon, + layer: &fbs::LayerTrait<'_>, + bon: &fbs::BooleanOperationNode<'_>, +) -> Node { + let sl = decode_shape_layout(layer, lc.rotation_cos_sin); + let op = decode_boolean_path_op(bon.op()); + let corner_r = bon + .corner_radius() + .and_then(|cr| cr.corner_radius()) + .map(|r| r.rx()); + let (stroke_style, stroke_width_f32) = decode_stroke_geometry_trait(bon.stroke_geometry()); + + Node::BooleanOperation(BooleanPathOperationNodeRec { + active: lc.active, + opacity: lc.opacity, + blend_mode: lc.blend_mode, + mask: lc.mask, + effects: lc.effects.clone(), + transform: Some(sl.transform), + op, + corner_radius: corner_r, + fills: decode_paints_vec(bon.fill_paints()), + strokes: decode_paints_vec(bon.stroke_paints()), + stroke_style, + stroke_width: singular_stroke_width(stroke_width_f32), + }) +} + +fn decode_text_span_node( + lc: &LayerCommon, + layer: &fbs::LayerTrait<'_>, + tn: &fbs::TextSpanNode<'_>, +) -> Node { + let sl = decode_shape_layout(layer, lc.rotation_cos_sin); + // Text uses translation + rotation (no center-origin). + // Use raw cos/sin to avoid lossy degree conversion. + let (cos, sin) = lc.rotation_cos_sin; + let transform = AffineTransform::from_translation_rotation_raw(sl.x, sl.y, cos, sin); + + let props = tn.properties(); + let text = props + .as_ref() + .and_then(|p| p.text()) + .unwrap_or("") + .to_owned(); + + let text_style = props + .as_ref() + .and_then(|p| p.text_style()) + .map(|ts| { + let mut rec = TextStyleRec::from_font(ts.font_family(), ts.font_size()); + rec.font_weight = FontWeight(ts.font_weight().value()); + rec + }) + .unwrap_or_else(|| TextStyleRec::from_font("Inter", 14.0)); + + let text_align = props + .as_ref() + .map(|p| decode_text_align(p.text_align())) + .unwrap_or(TextAlign::Left); + + let text_align_vertical = props + .as_ref() + .map(|p| decode_text_align_vertical(p.text_align_vertical())) + .unwrap_or(TextAlignVertical::Top); + + let fill_paints = props + .as_ref() + .map(|p| decode_paints_vec(p.fill_paints())) + .unwrap_or_else(|| Paints::new(Vec::::new())); + let stroke_paints = props + .as_ref() + .map(|p| decode_paints_vec(p.stroke_paints())) + .unwrap_or_else(|| Paints::new(Vec::::new())); + let stroke_width = props + .as_ref() + .and_then(|p| p.stroke_geometry()) + .map(|sg| sg.stroke_width()) + .unwrap_or(0.0); + let stroke_align = props + .as_ref() + .and_then(|p| p.stroke_geometry()) + .and_then(|sg| sg.stroke_style()) + .map(|ss| decode_stroke_align(ss.stroke_align())) + .unwrap_or(StrokeAlign::Center); + + Node::TextSpan(TextSpanNodeRec { + active: lc.active, + transform, + width: sl.width, + height: sl.height, + layout_child: lc.layout_child.clone(), + text, + text_style, + text_align, + text_align_vertical, + max_lines: None, + ellipsis: None, + fills: fill_paints, + strokes: stroke_paints, + stroke_width, + stroke_align, + opacity: lc.opacity, + blend_mode: lc.blend_mode, + mask: lc.mask, + effects: lc.effects.clone(), + }) +} + +// ═════════════════════════════════════════════════════════════════════════════ +// Encoder — Scene → FlatBuffers binary (`.grida`) +// +// The encode path is the exact inverse of the decode path above. +// Given a `Scene` and an ID mapping, it produces a `.grida` FlatBuffers +// binary that round-trips through decode identically. +// ═════════════════════════════════════════════════════════════════════════════ + +use crate::node::schema::NodeId; + +/// Encode a `Scene` into a `.grida` FlatBuffers binary. +/// +/// - `scene`: the scene to encode. +/// - `scene_id`: the string ID for the scene node (e.g. `"scene1"`). +/// - `id_map`: maps internal `NodeId` → string IDs. +/// +/// Returns the encoded bytes (including the `"GRID"` file identifier). +pub fn encode( + scene: &Scene, + scene_id: &str, + id_map: &HashMap, + position_map: &HashMap, +) -> Vec { + let mut fbb = flatbuffers::FlatBufferBuilder::with_capacity(4096); + + // ── 1. Encode all nodes ───────────────────────────────────────────────── + let mut node_slot_offsets = Vec::new(); + + // 1a. Scene node + let scene_slot = encode_scene_node(&mut fbb, scene, scene_id); + node_slot_offsets.push(scene_slot); + + // 1b. Layer nodes — walk the tree in order (roots first, then children) + for root_id in scene.graph.roots() { + encode_tree_recursive( + &mut fbb, + &scene.graph, + root_id, + scene_id, + id_map, + position_map, + &mut node_slot_offsets, + ); + } + + // ── 2. Build nodes vector ─────────────────────────────────────────────── + let nodes_vec = fbb.create_vector(&node_slot_offsets); + + // ── 3. Build scenes array ─────────────────────────────────────────────── + let scene_id_str = fbb.create_string(scene_id); + let scene_nid = fbs::NodeIdentifier::create( + &mut fbb, + &fbs::NodeIdentifierArgs { id: Some(scene_id_str) }, + ); + let scenes_vec = fbb.create_vector(&[scene_nid]); + + // ── 4. Build CanvasDocument ───────────────────────────────────────────── + let schema_version_str = fbb.create_string(SCHEMA_VERSION); + let doc = fbs::CanvasDocument::create( + &mut fbb, + &fbs::CanvasDocumentArgs { + schema_version: Some(schema_version_str), + nodes: Some(nodes_vec), + scenes: Some(scenes_vec), + }, + ); + + // ── 5. Build GridaFile root ───────────────────────────────────────────── + let root = fbs::GridaFile::create( + &mut fbb, + &fbs::GridaFileArgs { document: Some(doc) }, + ); + + fbb.finish(root, Some("GRID")); + fbb.finished_data().to_vec() +} + +/// Encode multiple scenes into a single `.grida` FlatBuffers binary. +/// +/// Each entry is `(scene_id, scene, id_map, position_map)`. +/// All scenes share the same flat `nodes` vector; each scene's nodes +/// are prefixed with a scene-type NodeSlot that references `scene_id`. +pub fn encode_multi( + entries: &[( + &str, + &Scene, + &HashMap, + &HashMap, + )], +) -> Vec { + let mut fbb = flatbuffers::FlatBufferBuilder::with_capacity(8192); + let mut node_slot_offsets = Vec::new(); + let mut scene_nids = Vec::new(); + + for (scene_id, scene, id_map, position_map) in entries { + // Scene node + let scene_slot = encode_scene_node(&mut fbb, scene, scene_id); + node_slot_offsets.push(scene_slot); + + // Layer nodes + for root_id in scene.graph.roots() { + encode_tree_recursive( + &mut fbb, + &scene.graph, + root_id, + scene_id, + id_map, + position_map, + &mut node_slot_offsets, + ); + } + + // Scene identifier + let scene_id_str = fbb.create_string(scene_id); + let scene_nid = fbs::NodeIdentifier::create( + &mut fbb, + &fbs::NodeIdentifierArgs { + id: Some(scene_id_str), + }, + ); + scene_nids.push(scene_nid); + } + + let nodes_vec = fbb.create_vector(&node_slot_offsets); + let scenes_vec = fbb.create_vector(&scene_nids); + let schema_version_str = fbb.create_string(SCHEMA_VERSION); + let doc = fbs::CanvasDocument::create( + &mut fbb, + &fbs::CanvasDocumentArgs { + schema_version: Some(schema_version_str), + nodes: Some(nodes_vec), + scenes: Some(scenes_vec), + }, + ); + let root = fbs::GridaFile::create( + &mut fbb, + &fbs::GridaFileArgs { document: Some(doc) }, + ); + fbb.finish(root, Some("GRID")); + fbb.finished_data().to_vec() +} + +/// Recursively encode a node and all its children into NodeSlots. +fn encode_tree_recursive<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + graph: &SceneGraph, + node_id: &NodeId, + parent_id: &str, + id_map: &HashMap, + position_map: &HashMap, + out: &mut Vec>>, +) { + let node = match graph.get_node(node_id) { + Ok(n) => n, + Err(_) => return, + }; + let string_id = match id_map.get(node_id) { + Some(s) => s.as_str(), + None => return, + }; + + // Use the original position string from the FBS file if available. + // Fall back to generating base-62-style position strings that stay + // lexicographically sorted: a0..a9, aa..az, b00..b0z, etc. + let position = match position_map.get(node_id) { + Some(pos) => pos.clone(), + None => { + let siblings = graph + .get_children(&graph.get_parent(node_id).unwrap_or(0)) + .map(|v| v.as_slice()) + .unwrap_or(&[]); + let idx = siblings.iter().position(|id| id == node_id).unwrap_or(0); + generate_fractional_position(idx) + } + }; + + let slot = encode_node(fbb, node, string_id, parent_id, &position); + out.push(slot); + + // Recurse into children + if let Some(children) = graph.get_children(node_id) { + for child_id in children.clone() { + encode_tree_recursive(fbb, graph, &child_id, string_id, id_map, position_map, out); + } + } +} + +/// Generate a lexicographically sortable position string for child index `idx`. +/// Produces: a0, a1, ..., a9, aa, ab, ..., az, b00, b01, ..., b0z, b10, ... +/// This matches the pattern used by fractional-indexing libraries. +fn generate_fractional_position(idx: usize) -> String { + if idx < 36 { + // a0..a9, aa..az (single char after 'a') + let ch = if idx < 10 { + (b'0' + idx as u8) as char + } else { + (b'a' + (idx - 10) as u8) as char + }; + format!("a{ch}") + } else { + // b00..b0z, b10..b1z, etc. + let rem = idx - 36; + let hi = rem / 36; + let lo = rem % 36; + let hi_ch = if hi < 10 { + (b'0' + hi as u8) as char + } else { + (b'a' + (hi - 10) as u8) as char + }; + let lo_ch = if lo < 10 { + (b'0' + lo as u8) as char + } else { + (b'a' + (lo - 10) as u8) as char + }; + format!("b{hi_ch}{lo_ch}") + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Scene node encoding +// ───────────────────────────────────────────────────────────────────────────── + +fn encode_scene_node<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + scene: &Scene, + scene_id: &str, +) -> flatbuffers::WIPOffset> { + let sys = encode_system_node_trait(fbb, scene_id, &scene.name, true, false); + + let bg = scene.background_color.map(|c| encode_color_to_rgba32f(&c)); + + let sn = fbs::SceneNode::create(fbb, &fbs::SceneNodeArgs { + node: Some(sys), + scene_background_color: bg.as_ref(), + ..Default::default() + }); + + make_node_slot(fbb, fbs::Node::SceneNode, sn.as_union_value()) +} + +// ───────────────────────────────────────────────────────────────────────────── +// Dispatch: Node enum → typed encoder +// ───────────────────────────────────────────────────────────────────────────── + +fn encode_node<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + node: &Node, + node_id: &str, + parent_id: &str, + position: &str, +) -> flatbuffers::WIPOffset> { + match node { + Node::Container(r) => encode_container_node(fbb, r, node_id, parent_id, position), + Node::InitialContainer(r) => { + encode_initial_container_node(fbb, r, node_id, parent_id, position) + } + Node::Rectangle(r) => encode_basic_shape_node( + fbb, + node_id, + parent_id, + position, + fbs::CanonicalLayerShape::CanonicalShapeRectangular, + fbs::BasicShapeNodeType::Rectangle, + BasicShapeFields::Rectangle(r), + ), + Node::Ellipse(r) => encode_basic_shape_node( + fbb, + node_id, + parent_id, + position, + fbs::CanonicalLayerShape::CanonicalShapeElliptical, + fbs::BasicShapeNodeType::Ellipse, + BasicShapeFields::Ellipse(r), + ), + Node::RegularPolygon(r) => encode_basic_shape_node( + fbb, + node_id, + parent_id, + position, + fbs::CanonicalLayerShape::CanonicalShapeRegularPolygon, + fbs::BasicShapeNodeType::RegularPolygon, + BasicShapeFields::RegularPolygon(r), + ), + Node::RegularStarPolygon(r) => encode_basic_shape_node( + fbb, + node_id, + parent_id, + position, + fbs::CanonicalLayerShape::CanonicalShapeRegularStarPolygon, + fbs::BasicShapeNodeType::RegularStarPolygon, + BasicShapeFields::RegularStarPolygon(r), + ), + Node::Group(r) => encode_group_node(fbb, r, node_id, parent_id, position), + Node::Line(r) => encode_line_node(fbb, r, node_id, parent_id, position), + Node::Vector(r) => encode_vector_node(fbb, r, node_id, parent_id, position), + Node::TextSpan(r) => encode_text_span_node(fbb, r, node_id, parent_id, position), + Node::BooleanOperation(r) => { + encode_boolean_operation_node(fbb, r, node_id, parent_id, position) + } + // Fallback: encode as UnknownNode + _ => { + let sys = encode_system_node_trait(fbb, node_id, "", true, false); + let un = fbs::UnknownNode::create(fbb, &fbs::UnknownNodeArgs { node: Some(sys) }); + make_node_slot(fbb, fbs::Node::UnknownNode, un.as_union_value()) + } + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Shared helper: SystemNodeTrait +// ───────────────────────────────────────────────────────────────────────────── + +fn encode_system_node_trait<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + id: &str, + name: &str, + active: bool, + locked: bool, +) -> flatbuffers::WIPOffset> { + let id_str = fbb.create_string(id); + let nid = fbs::NodeIdentifier::create(fbb, &fbs::NodeIdentifierArgs { id: Some(id_str) }); + let name_str = if !name.is_empty() { + Some(fbb.create_string(name)) + } else { + None + }; + fbs::SystemNodeTrait::create( + fbb, + &fbs::SystemNodeTraitArgs { + id: Some(nid), + active, + name: name_str, + locked, + }, + ) +} + +// ───────────────────────────────────────────────────────────────────────────── +// Shared helper: LayerTrait +// ───────────────────────────────────────────────────────────────────────────── + +struct LayerTraitInput<'a, 'b> { + parent_id: &'b str, + position: &'b str, + opacity: f32, + blend_mode: LayerBlendMode, + mask: Option, + effects: &'b LayerEffects, + /// Post-layout transform matrix (cos/sin values directly from the source + /// transform, avoiding lossy radians→degrees→radians conversion). + post_layout_transform: Option, + layout: Option>>, +} + +fn encode_layer_trait<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + input: &LayerTraitInput<'a, '_>, +) -> flatbuffers::WIPOffset> { + // Parent reference + let parent_id_str = fbb.create_string(input.parent_id); + let parent_nid = + fbs::NodeIdentifier::create(fbb, &fbs::NodeIdentifierArgs { id: Some(parent_id_str) }); + let pos_str = fbb.create_string(input.position); + let parent_ref = fbs::ParentReference::create( + fbb, + &fbs::ParentReferenceArgs { + parent_id: Some(parent_nid), + position: Some(pos_str), + }, + ); + + // Blend mode + let fbs_blend_mode = encode_layer_blend_mode(input.blend_mode); + + // Mask type — union requires BOTH discriminant and payload + let (fbs_mask_disc, fbs_mask_payload) = encode_mask_type(fbb, input.mask); + + // Effects + let effects = encode_layer_effects(fbb, input.effects); + + fbs::LayerTrait::create( + fbb, + &fbs::LayerTraitArgs { + parent: Some(parent_ref), + opacity: input.opacity, + blend_mode: fbs_blend_mode, + mask_type_type: fbs_mask_disc, + mask_type: fbs_mask_payload, + effects, + layout: input.layout, + post_layout_transform: input.post_layout_transform.as_ref(), + post_layout_transform_origin: None, + }, + ) +} + +// ───────────────────────────────────────────────────────────────────────────── +// Color encoding +// ───────────────────────────────────────────────────────────────────────────── + +/// Build a `CGTransform2D` rotation matrix from rotation in degrees. +/// Used for container nodes which store rotation as a separate scalar. +fn rotation_degrees_to_transform(degrees: f32) -> Option { + if degrees == 0.0 { + None + } else { + let rad = degrees.to_radians(); + let (sin, cos) = rad.sin_cos(); + Some(fbs::CGTransform2D::new(cos, -sin, 0.0, sin, cos, 0.0)) + } +} + +/// Build a `CGTransform2D` rotation matrix directly from an `AffineTransform`'s +/// cos/sin components, avoiding the lossy radians→degrees→radians conversion. +/// Returns `None` only when the rotation is **exactly** identity (cos=1, sin=0), +/// preserving even tiny near-zero rotations for perfect round-trip fidelity. +fn affine_to_rotation_transform(t: &AffineTransform) -> Option { + let cos = t.matrix[0][0]; + let sin = t.matrix[1][0]; + // Only skip when exactly identity — even sub-epsilon rotations must survive + // round-trips so that decode(encode(decode(bytes))) is bit-identical. + if cos == 1.0 && sin == 0.0 { + None + } else { + Some(fbs::CGTransform2D::new(cos, -sin, 0.0, sin, cos, 0.0)) + } +} + +fn encode_color_to_rgba32f(c: &CGColor) -> fbs::RGBA32F { + fbs::RGBA32F::new( + c.r as f32 / 255.0, + c.g as f32 / 255.0, + c.b as f32 / 255.0, + c.a as f32 / 255.0, + ) +} + +// ───────────────────────────────────────────────────────────────────────────── +// Blend mode encoding +// ───────────────────────────────────────────────────────────────────────────── + +fn encode_layer_blend_mode(lbm: LayerBlendMode) -> fbs::LayerBlendMode { + match lbm { + LayerBlendMode::PassThrough => fbs::LayerBlendMode::PassThrough, + LayerBlendMode::Blend(bm) => fbs::LayerBlendMode(encode_blend_mode(bm).0), + } +} + +fn encode_mask_type<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + mask: Option, +) -> (fbs::LayerMaskType, Option>) { + match mask { + None => (fbs::LayerMaskType::NONE, None), + Some(LayerMaskType::Image(imt)) => { + let fbs_imt = match imt { + crate::cg::types::ImageMaskType::Alpha => fbs::ImageMaskType::Alpha, + crate::cg::types::ImageMaskType::Luminance => fbs::ImageMaskType::Luminance, + }; + let table = fbs::LayerMaskTypeImage::create( + fbb, + &fbs::LayerMaskTypeImageArgs { + image_mask_type: fbs_imt, + }, + ); + ( + fbs::LayerMaskType::LayerMaskTypeImage, + Some(table.as_union_value()), + ) + } + Some(LayerMaskType::Geometry) => { + let table = fbs::LayerMaskTypeGeometry::create( + fbb, + &fbs::LayerMaskTypeGeometryArgs {}, + ); + ( + fbs::LayerMaskType::LayerMaskTypeGeometry, + Some(table.as_union_value()), + ) + } + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Paint encoding +// ───────────────────────────────────────────────────────────────────────────── + +fn encode_paints<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + paints: &Paints, +) -> Option>>>> { + if paints.is_empty() { + return None; + } + let items: Vec<_> = paints + .as_slice() + .iter() + .filter_map(|p| encode_paint_item(fbb, p)) + .collect(); + Some(fbb.create_vector(&items)) +} + +fn encode_paint_item<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + paint: &Paint, +) -> Option>> { + match paint { + Paint::Solid(sp) => { + let color = encode_color_to_rgba32f(&sp.color); + let solid = fbs::SolidPaint::create(fbb, &fbs::SolidPaintArgs { + active: sp.active, + color: Some(&color), + blend_mode: encode_blend_mode(sp.blend_mode), + }); + Some(fbs::PaintStackItem::create(fbb, &fbs::PaintStackItemArgs { + paint_type: fbs::Paint::SolidPaint, + paint: Some(solid.as_union_value()), + })) + } + Paint::LinearGradient(lg) => { + let stops = encode_gradient_stops(fbb, &lg.stops); + let xy1 = fbs::Alignment::new(lg.xy1.0, lg.xy1.1); + let xy2 = fbs::Alignment::new(lg.xy2.0, lg.xy2.1); + let transform = encode_affine_to_cg_transform(&lg.transform); + let lgp = fbs::LinearGradientPaint::create(fbb, &fbs::LinearGradientPaintArgs { + active: lg.active, + xy1: Some(&xy1), + xy2: Some(&xy2), + stops: Some(stops), + opacity: lg.opacity, + blend_mode: encode_blend_mode(lg.blend_mode), + transform: Some(&transform), + ..Default::default() + }); + Some(fbs::PaintStackItem::create(fbb, &fbs::PaintStackItemArgs { + paint_type: fbs::Paint::LinearGradientPaint, + paint: Some(lgp.as_union_value()), + })) + } + Paint::RadialGradient(rg) => { + let stops = encode_gradient_stops(fbb, &rg.stops); + let transform = encode_affine_to_cg_transform(&rg.transform); + let rgp = fbs::RadialGradientPaint::create(fbb, &fbs::RadialGradientPaintArgs { + active: rg.active, + stops: Some(stops), + opacity: rg.opacity, + blend_mode: encode_blend_mode(rg.blend_mode), + transform: Some(&transform), + ..Default::default() + }); + Some(fbs::PaintStackItem::create(fbb, &fbs::PaintStackItemArgs { + paint_type: fbs::Paint::RadialGradientPaint, + paint: Some(rgp.as_union_value()), + })) + } + Paint::SweepGradient(sg) => { + let stops = encode_gradient_stops(fbb, &sg.stops); + let transform = encode_affine_to_cg_transform(&sg.transform); + let sgp = fbs::SweepGradientPaint::create(fbb, &fbs::SweepGradientPaintArgs { + active: sg.active, + stops: Some(stops), + opacity: sg.opacity, + blend_mode: encode_blend_mode(sg.blend_mode), + transform: Some(&transform), + }); + Some(fbs::PaintStackItem::create(fbb, &fbs::PaintStackItemArgs { + paint_type: fbs::Paint::SweepGradientPaint, + paint: Some(sgp.as_union_value()), + })) + } + Paint::Image(ip) => { + let image_ref_offset = match &ip.image { + ResourceRef::HASH(h) => { + let hash_str = fbb.create_string(h); + let href = fbs::ResourceRefHASH::create(fbb, &fbs::ResourceRefHASHArgs { hash: Some(hash_str) }); + (fbs::ResourceRef::ResourceRefHASH, href.as_union_value()) + } + ResourceRef::RID(r) => { + let rid_str = fbb.create_string(r); + let rref = fbs::ResourceRefRID::create(fbb, &fbs::ResourceRefRIDArgs { rid: Some(rid_str) }); + (fbs::ResourceRef::ResourceRefRID, rref.as_union_value()) + } + }; + let alignment = fbs::Alignment::new(ip.alignement.0, ip.alignement.1); + let (fit_type, fit_value) = encode_image_paint_fit(fbb, &ip.fit); + let ip_offset = fbs::ImagePaint::create(fbb, &fbs::ImagePaintArgs { + active: ip.active, + image_type: image_ref_offset.0, + image: Some(image_ref_offset.1), + quarter_turns: ip.quarter_turns, + alignement: Some(&alignment), + fit_type, + fit: Some(fit_value), + opacity: ip.opacity, + blend_mode: encode_blend_mode(ip.blend_mode), + ..Default::default() + }); + Some(fbs::PaintStackItem::create(fbb, &fbs::PaintStackItemArgs { + paint_type: fbs::Paint::ImagePaint, + paint: Some(ip_offset.as_union_value()), + })) + } + _ => None, + } +} + +fn encode_image_paint_fit<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + fit: &ImagePaintFit, +) -> (fbs::ImagePaintFit, flatbuffers::WIPOffset) { + match fit { + ImagePaintFit::Fit(box_fit) => { + let f = fbs::ImagePaintFitFit::create(fbb, &fbs::ImagePaintFitFitArgs { box_fit: encode_box_fit(*box_fit) }); + (fbs::ImagePaintFit::ImagePaintFitFit, f.as_union_value()) + } + ImagePaintFit::Transform(t) => { + let ct = encode_affine_to_cg_transform(t); + let f = fbs::ImagePaintFitTransform::create(fbb, &fbs::ImagePaintFitTransformArgs { transform: Some(&ct) }); + (fbs::ImagePaintFit::ImagePaintFitTransform, f.as_union_value()) + } + ImagePaintFit::Tile(tile) => { + let fbs_repeat = match tile.repeat { + crate::cg::types::ImageRepeat::RepeatX => fbs::ImageRepeat::RepeatX, + crate::cg::types::ImageRepeat::RepeatY => fbs::ImageRepeat::RepeatY, + crate::cg::types::ImageRepeat::Repeat => fbs::ImageRepeat::Repeat, + }; + let fbs_tile = fbs::ImageTile::new(tile.scale, fbs_repeat); + let f = fbs::ImagePaintFitTile::create(fbb, &fbs::ImagePaintFitTileArgs { tile: Some(&fbs_tile) }); + (fbs::ImagePaintFit::ImagePaintFitTile, f.as_union_value()) + } + } +} + +fn encode_gradient_stops<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + stops: &[GradientStop], +) -> flatbuffers::WIPOffset> { + let fbs_stops: Vec<_> = stops + .iter() + .map(|s| { + let color = encode_color_to_rgba32f(&s.color); + fbs::GradientStop::new(s.offset, &color) + }) + .collect(); + fbb.create_vector(&fbs_stops) +} + +fn encode_affine_to_cg_transform(t: &AffineTransform) -> fbs::CGTransform2D { + fbs::CGTransform2D::new( + t.matrix[0][0], // m00 = a + t.matrix[0][1], // m01 = c + t.matrix[0][2], // m02 = tx + t.matrix[1][0], // m10 = b + t.matrix[1][1], // m11 = d + t.matrix[1][2], // m12 = ty + ) +} + +// ───────────────────────────────────────────────────────────────────────────── +// Effects encoding +// ───────────────────────────────────────────────────────────────────────────── + +fn encode_layer_effects<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + effects: &LayerEffects, +) -> Option>> { + let has_any = effects.blur.is_some() + || effects.backdrop_blur.is_some() + || !effects.shadows.is_empty() + || effects.glass.is_some() + || !effects.noises.is_empty(); + if !has_any { + return None; + } + + let blur_offset = effects.blur.as_ref().map(|lb| { + let radius = match &lb.blur { FeBlur::Gaussian(g) => g.radius, _ => 0.0 }; + let gaussian = fbs::FeGaussianBlur::create(fbb, &fbs::FeGaussianBlurArgs { radius }); + fbs::FeLayerBlur::create(fbb, &fbs::FeLayerBlurArgs { + active: lb.active, + blur_type: fbs::FeBlur::FeGaussianBlur, + blur: Some(gaussian.as_union_value()), + }) + }); + + let backdrop_blur_offset = effects.backdrop_blur.as_ref().map(|bb| { + let radius = match &bb.blur { FeBlur::Gaussian(g) => g.radius, _ => 0.0 }; + let gaussian = fbs::FeGaussianBlur::create(fbb, &fbs::FeGaussianBlurArgs { radius }); + fbs::FeBackdropBlur::create(fbb, &fbs::FeBackdropBlurArgs { + active: bb.active, + blur_type: fbs::FeBlur::FeGaussianBlur, + blur: Some(gaussian.as_union_value()), + }) + }); + + let shadows_offset = if effects.shadows.is_empty() { + None + } else { + let shadow_items: Vec<_> = effects.shadows.iter().map(|s| encode_filter_shadow_effect(fbb, s)).collect(); + Some(fbb.create_vector(&shadow_items)) + }; + + let glass_offset = effects.glass.as_ref().map(|lg| { + fbs::FeLiquidGlass::create(fbb, &fbs::FeLiquidGlassArgs { + active: lg.active, + light_intensity: lg.light_intensity, + light_angle: lg.light_angle, + refraction: lg.refraction, + depth: lg.depth, + dispersion: lg.dispersion, + blur_radius: lg.blur_radius, + }) + }); + + let noises_offset = if effects.noises.is_empty() { + None + } else { + let noise_items: Vec<_> = effects.noises.iter().map(|n| encode_fe_noise_effect(fbb, n)).collect(); + Some(fbb.create_vector(&noise_items)) + }; + + Some(fbs::LayerEffects::create(fbb, &fbs::LayerEffectsArgs { + fe_blur: blur_offset, + fe_backdrop_blur: backdrop_blur_offset, + fe_shadows: shadows_offset, + fe_glass: glass_offset, + fe_noises: noises_offset, + })) +} + +fn encode_filter_shadow_effect<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + effect: &FilterShadowEffect, +) -> flatbuffers::WIPOffset> { + let (kind, shadow) = match effect { + FilterShadowEffect::DropShadow(s) => (fbs::FilterShadowEffectKind::DropShadow, s), + FilterShadowEffect::InnerShadow(s) => (fbs::FilterShadowEffectKind::InnerShadow, s), + }; + let color = encode_color_to_rgba32f(&shadow.color); + let shadow_offset = fbs::FeShadow::create(fbb, &fbs::FeShadowArgs { + active: shadow.active, dx: shadow.dx, dy: shadow.dy, + blur: shadow.blur, spread: shadow.spread, color: Some(&color), + }); + fbs::FilterShadowEffect::create(fbb, &fbs::FilterShadowEffectArgs { + kind, shadow: Some(shadow_offset), + }) +} + +fn encode_fe_noise_effect<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + noise: &FeNoiseEffect, +) -> flatbuffers::WIPOffset> { + let coloring = encode_noise_colors(fbb, &noise.coloring); + fbs::FeNoiseEffect::create(fbb, &fbs::FeNoiseEffectArgs { + active: noise.active, noise_size: noise.noise_size, density: noise.density, + num_octaves: noise.num_octaves, seed: noise.seed, coloring: Some(coloring), + blend_mode: encode_blend_mode(noise.blend_mode), + }) +} + +fn encode_noise_colors<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + colors: &NoiseEffectColors, +) -> flatbuffers::WIPOffset> { + match colors { + NoiseEffectColors::Mono { color } => { + let c = encode_color_to_rgba32f(color); + fbs::NoiseEffectColors::create(fbb, &fbs::NoiseEffectColorsArgs { + kind: fbs::NoiseEffectColorsKind::Mono, mono_color: Some(&c), ..Default::default() + }) + } + NoiseEffectColors::Duo { color1, color2 } => { + let c1 = encode_color_to_rgba32f(color1); + let c2 = encode_color_to_rgba32f(color2); + fbs::NoiseEffectColors::create(fbb, &fbs::NoiseEffectColorsArgs { + kind: fbs::NoiseEffectColorsKind::Duo, duo_color1: Some(&c1), duo_color2: Some(&c2), ..Default::default() + }) + } + NoiseEffectColors::Multi { opacity } => { + fbs::NoiseEffectColors::create(fbb, &fbs::NoiseEffectColorsArgs { + kind: fbs::NoiseEffectColorsKind::Multi, multi_opacity: *opacity, ..Default::default() + }) + } + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Stroke encoding +// ───────────────────────────────────────────────────────────────────────────── + +fn encode_stroke_style<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + ss: &StrokeStyle, +) -> flatbuffers::WIPOffset> { + let dash = ss.stroke_dash_array.as_ref().map(|da| { + let floats: Vec = da.0.clone(); + fbb.create_vector(&floats) + }); + fbs::StrokeStyle::create( + fbb, + &fbs::StrokeStyleArgs { + stroke_align: encode_stroke_align(ss.stroke_align), + stroke_cap: encode_stroke_cap(ss.stroke_cap), + stroke_join: encode_stroke_join(ss.stroke_join), + stroke_miter_limit: ss.stroke_miter_limit.0, + stroke_dash_array: dash, + }, + ) +} + +// ───────────────────────────────────────────────────────────────────────────── +// Layout encoding +// ───────────────────────────────────────────────────────────────────────────── + +fn encode_px_offset<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + v: f32, +) -> flatbuffers::WIPOffset> { + fbs::PositioningSideOffsetValue::create( + fbb, + &fbs::PositioningSideOffsetValueArgs { + kind: fbs::PositioningSideOffsetKind::Px, + value: Some(v), + }, + ) +} + +fn encode_dim_px<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + v: Option, +) -> Option>> { + v.map(|px| { + fbs::LayoutDimensionValue::create( + fbb, + &fbs::LayoutDimensionValueArgs { + unit: fbs::LayoutDimensionUnit::LengthPx, + value: Some(px), + }, + ) + }) +} + +fn encode_dimensions<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + w: Option, + h: Option, +) -> flatbuffers::WIPOffset> { + let dim_w = encode_dim_px(fbb, w); + let dim_h = encode_dim_px(fbb, h); + fbs::LayoutDimensionStyle::create( + fbb, + &fbs::LayoutDimensionStyleArgs { + layout_target_width: dim_w, + layout_target_height: dim_h, + layout_target_aspect_ratio: None, + }, + ) +} + +fn encode_layout_child_style<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + child: &Option, +) -> Option>> { + child.as_ref().map(|lc| { + let pos = match lc.layout_positioning { + LayoutPositioning::Absolute => fbs::LayoutPositioning::Absolute, + LayoutPositioning::Auto => fbs::LayoutPositioning::Auto, + }; + fbs::LayoutChildStyle::create( + fbb, + &fbs::LayoutChildStyleArgs { + layout_grow: lc.layout_grow, + layout_positioning: pos, + }, + ) + }) +} + +fn encode_layout_position<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + pos: &LayoutPositioningBasis, +) -> ( + fbs::LayoutPositioningBasis, + Option>, +) { + match pos { + LayoutPositioningBasis::Cartesian(p) => { + let cart = fbs::LayoutPositioningCartesian::create( + fbb, + &fbs::LayoutPositioningCartesianArgs { x: p.x, y: p.y }, + ); + ( + fbs::LayoutPositioningBasis::LayoutPositioningCartesian, + Some(cart.as_union_value()), + ) + } + LayoutPositioningBasis::Inset(ei) => { + let left = encode_px_offset(fbb, ei.left); + let top = encode_px_offset(fbb, ei.top); + let right = encode_px_offset(fbb, ei.right); + let bottom = encode_px_offset(fbb, ei.bottom); + let inset = fbs::LayoutPositioningInset::create( + fbb, + &fbs::LayoutPositioningInsetArgs { + left: Some(left), + top: Some(top), + right: Some(right), + bottom: Some(bottom), + }, + ); + ( + fbs::LayoutPositioningBasis::LayoutPositioningInset, + Some(inset.as_union_value()), + ) + } + #[allow(deprecated)] + _ => (fbs::LayoutPositioningBasis::NONE, None), + } +} + +// ─── LayoutStyle builders ──────────────────────────────────────────────────── + +/// Build a LayoutStyle for shape nodes (position as Inset, dimensions, child style). +fn encode_shape_layout<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + x: f32, + y: f32, + width: Option, + height: Option, + layout_child: &Option, +) -> flatbuffers::WIPOffset> { + let left = encode_px_offset(fbb, x); + let top = encode_px_offset(fbb, y); + let inset = fbs::LayoutPositioningInset::create( + fbb, + &fbs::LayoutPositioningInsetArgs { + left: Some(left), + top: Some(top), + right: None, + bottom: None, + }, + ); + let dims = encode_dimensions(fbb, width, height); + let child = encode_layout_child_style(fbb, layout_child); + fbs::LayoutStyle::create( + fbb, + &fbs::LayoutStyleArgs { + layout_position_type: fbs::LayoutPositioningBasis::LayoutPositioningInset, + layout_position: Some(inset.as_union_value()), + layout_dimensions: Some(dims), + layout_container: None, + layout_child: child, + }, + ) +} + +/// Build a LayoutStyle for container nodes (position, dimensions, container style, child style). +fn encode_container_layout<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + position: &LayoutPositioningBasis, + dimensions: &LayoutDimensionStyle, + container_style: &LayoutContainerStyle, + layout_child: &Option, +) -> flatbuffers::WIPOffset> { + let (pos_type, pos_offset) = encode_layout_position(fbb, position); + + // Container style — use FBS `::None` sentinels for unset optional enum fields + // so the decoder can distinguish "not set" from "explicitly set to default". + let padding = container_style.layout_padding.as_ref().map(|p| { + fbs::EdgeInsets::new(p.top, p.right, p.bottom, p.left) + }); + let lc_fbs = Some(fbs::LayoutContainerStyle::create( + fbb, + &fbs::LayoutContainerStyleArgs { + layout_mode: match container_style.layout_mode { + LayoutMode::Flex => fbs::LayoutMode::Flex, + LayoutMode::Normal => fbs::LayoutMode::Normal, + }, + layout_direction: match container_style.layout_direction { + Axis::Horizontal => fbs::Axis::Horizontal, + Axis::Vertical => fbs::Axis::Vertical, + }, + layout_wrap: container_style + .layout_wrap + .map(|w| match w { + LayoutWrap::Wrap => fbs::LayoutWrap::Wrap, + LayoutWrap::NoWrap => fbs::LayoutWrap::NoWrap, + }) + .unwrap_or(fbs::LayoutWrap::None), + layout_main_axis_alignment: container_style + .layout_main_axis_alignment + .map(encode_main_axis_alignment) + .unwrap_or(fbs::MainAxisAlignment::None), + layout_cross_axis_alignment: container_style + .layout_cross_axis_alignment + .map(encode_cross_axis_alignment) + .unwrap_or(fbs::CrossAxisAlignment::None), + layout_padding: padding.as_ref(), + layout_main_axis_gap: container_style + .layout_gap + .as_ref() + .map(|g| g.main_axis_gap) + .unwrap_or(0.0), + layout_cross_axis_gap: container_style + .layout_gap + .as_ref() + .map(|g| g.cross_axis_gap) + .unwrap_or(0.0), + }, + )); + + let dims = encode_dimensions(fbb, dimensions.layout_target_width, dimensions.layout_target_height); + let child = encode_layout_child_style(fbb, layout_child); + fbs::LayoutStyle::create( + fbb, + &fbs::LayoutStyleArgs { + layout_position_type: pos_type, + layout_position: pos_offset, + layout_dimensions: Some(dims), + layout_container: lc_fbs, + layout_child: child, + }, + ) +} + +// ─── Shared encoder helpers ────────────────────────────────────────────────── + +/// Wrap a typed FBS node into a `NodeSlot`. +fn make_node_slot<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + node_type: fbs::Node, + node: flatbuffers::WIPOffset, +) -> flatbuffers::WIPOffset> { + fbs::NodeSlot::create( + fbb, + &fbs::NodeSlotArgs { + node_type, + node: Some(node), + }, + ) +} + +/// Create a `StrokeGeometryTrait` from a `StrokeStyle` and a scalar width. +fn encode_stroke_geometry<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + ss: &StrokeStyle, + width: f32, +) -> flatbuffers::WIPOffset> { + let stroke_style_offset = encode_stroke_style(fbb, ss); + fbs::StrokeGeometryTrait::create( + fbb, + &fbs::StrokeGeometryTraitArgs { + stroke_style: Some(stroke_style_offset), + stroke_width: width, + stroke_width_profile: None, + }, + ) +} + +// ───────────────────────────────────────────────────────────────────────────── +// Node-specific encoders +// ───────────────────────────────────────────────────────────────────────────── + +fn encode_container_node<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + r: &ContainerNodeRec, + node_id: &str, + parent_id: &str, + position: &str, +) -> flatbuffers::WIPOffset> { + let sys = encode_system_node_trait(fbb, node_id, "", r.active, false); + let layout = encode_container_layout( + fbb, + &r.position, + &r.layout_dimensions, + &r.layout_container, + &r.layout_child, + ); + let layer = encode_layer_trait( + fbb, + &LayerTraitInput { + parent_id, + position, + opacity: r.opacity, + blend_mode: r.blend_mode, + mask: r.mask, + effects: &r.effects, + post_layout_transform: rotation_degrees_to_transform(r.rotation), + layout: Some(layout), + }, + ); + + // Corner radius + let rcr = encode_rectangular_corner_radius(&r.corner_radius); + let cr_trait = fbs::RectangularCornerRadiusTrait::create( + fbb, + &fbs::RectangularCornerRadiusTraitArgs { + rectangular_corner_radius: Some(&rcr), + corner_smoothing: r.corner_smoothing.0, + }, + ); + + // Stroke geometry + let stroke_style_offset = encode_stroke_style(fbb, &r.stroke_style); + let rsw = encode_rectangular_stroke_width(&r.stroke_width); + let sg = fbs::RectangularStrokeGeometryTrait::create( + fbb, + &fbs::RectangularStrokeGeometryTraitArgs { + stroke_style: Some(stroke_style_offset), + rectangular_stroke_width: rsw.as_ref(), + stroke_width_profile: None, + }, + ); + + let fill_offsets = encode_paints(fbb, &r.fills); + let stroke_offsets = encode_paints(fbb, &r.strokes); + + let cn = fbs::ContainerNode::create(fbb, &fbs::ContainerNodeArgs { + node: Some(sys), layer: Some(layer), + corner_radius: Some(cr_trait), stroke_geometry: Some(sg), + fill_paints: fill_offsets, stroke_paints: stroke_offsets, + clips_content: r.clip, + }); + make_node_slot(fbb, fbs::Node::ContainerNode, cn.as_union_value()) +} + +fn encode_initial_container_node<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + r: &InitialContainerNodeRec, + node_id: &str, + parent_id: &str, + position: &str, +) -> flatbuffers::WIPOffset> { + let sys = encode_system_node_trait(fbb, node_id, "", r.active, false); + + // Build container-style layout + let container_style = LayoutContainerStyle { + layout_mode: r.layout_mode, + layout_direction: r.layout_direction, + layout_wrap: Some(r.layout_wrap), + layout_main_axis_alignment: Some(r.layout_main_axis_alignment), + layout_cross_axis_alignment: Some(r.layout_cross_axis_alignment), + layout_padding: Some(r.padding), + layout_gap: Some(r.layout_gap), + }; + let layout = encode_container_layout( + fbb, + &LayoutPositioningBasis::zero(), + &LayoutDimensionStyle::default(), + &container_style, + &None, + ); + let default_effects = LayerEffects::default(); + let layer = encode_layer_trait( + fbb, + &LayerTraitInput { + parent_id, + position, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: &default_effects, + post_layout_transform: None, + layout: Some(layout), + }, + ); + + let icn = fbs::InitialContainerNode::create(fbb, &fbs::InitialContainerNodeArgs { + node: Some(sys), layer: Some(layer), + }); + make_node_slot(fbb, fbs::Node::InitialContainerNode, icn.as_union_value()) +} + +fn encode_group_node<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + r: &GroupNodeRec, + node_id: &str, + parent_id: &str, + position: &str, +) -> flatbuffers::WIPOffset> { + let (x, y) = match &r.transform { + Some(t) => (t.x(), t.y()), + None => (0.0, 0.0), + }; + let plt = r.transform.as_ref().and_then(affine_to_rotation_transform); + + let sys = encode_system_node_trait(fbb, node_id, "", r.active, false); + let layout = encode_shape_layout(fbb, x, y, None, None, &None); + let default_effects = LayerEffects::default(); + let layer = encode_layer_trait( + fbb, + &LayerTraitInput { + parent_id, + position, + opacity: r.opacity, + blend_mode: r.blend_mode, + mask: r.mask, + effects: &default_effects, + post_layout_transform: plt, + layout: Some(layout), + }, + ); + + let gn = fbs::GroupNode::create(fbb, &fbs::GroupNodeArgs { + node: Some(sys), layer: Some(layer), + }); + make_node_slot(fbb, fbs::Node::GroupNode, gn.as_union_value()) +} + +/// Unified data source for BasicShapeNode encoding. +enum BasicShapeFields<'a> { + Rectangle(&'a RectangleNodeRec), + Ellipse(&'a EllipseNodeRec), + RegularPolygon(&'a RegularPolygonNodeRec), + RegularStarPolygon(&'a RegularStarPolygonNodeRec), +} + +fn encode_basic_shape_node<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + node_id: &str, + parent_id: &str, + position: &str, + shape_type: fbs::CanonicalLayerShape, + node_type: fbs::BasicShapeNodeType, + fields: BasicShapeFields<'_>, +) -> flatbuffers::WIPOffset> { + // Extract common fields from the variant + let (active, opacity, blend_mode, mask, effects, transform, size, fills, strokes, layout_child) = + match &fields { + BasicShapeFields::Rectangle(r) => ( + r.active, r.opacity, r.blend_mode, r.mask, &r.effects, &r.transform, &r.size, + &r.fills, &r.strokes, &r.layout_child, + ), + BasicShapeFields::Ellipse(e) => ( + e.active, e.opacity, e.blend_mode, e.mask, &e.effects, &e.transform, &e.size, + &e.fills, &e.strokes, &e.layout_child, + ), + BasicShapeFields::RegularPolygon(p) => ( + p.active, p.opacity, p.blend_mode, p.mask, &p.effects, &p.transform, &p.size, + &p.fills, &p.strokes, &p.layout_child, + ), + BasicShapeFields::RegularStarPolygon(s) => ( + s.active, s.opacity, s.blend_mode, s.mask, &s.effects, &s.transform, &s.size, + &s.fills, &s.strokes, &s.layout_child, + ), + }; + + // Reverse-engineer x, y from from_box_center transform + let (x, y) = reverse_from_box_center(transform, size.width, size.height); + let plt = affine_to_rotation_transform(transform); + + let sys = encode_system_node_trait(fbb, node_id, "", active, false); + let layout = encode_shape_layout( + fbb, + x, + y, + Some(size.width), + Some(size.height), + layout_child, + ); + let layer = encode_layer_trait( + fbb, + &LayerTraitInput { + parent_id, + position, + opacity, + blend_mode, + mask, + effects, + post_layout_transform: plt, + layout: Some(layout), + }, + ); + + let fill_offsets = encode_paints(fbb, fills); + let stroke_offsets = encode_paints(fbb, strokes); + + // Corner radius (scalar for polygon/star, rectangular for rectangle) + let scalar_cr = match &fields { + BasicShapeFields::Rectangle(r) => r.corner_radius.tl.rx, + BasicShapeFields::Ellipse(_) => 0.0, + BasicShapeFields::RegularPolygon(p) => p.corner_radius, + BasicShapeFields::RegularStarPolygon(s) => s.corner_radius, + }; + let rect_cr = match &fields { + BasicShapeFields::Rectangle(r) => Some(encode_rectangular_corner_radius(&r.corner_radius)), + _ => None, + }; + + // Stroke + let (stroke_width_f32, stroke_style) = match &fields { + BasicShapeFields::Rectangle(r) => (r.stroke_width.max(), &r.stroke_style), + BasicShapeFields::Ellipse(e) => (e.stroke_width.0.unwrap_or(0.0), &e.stroke_style), + BasicShapeFields::RegularPolygon(p) => (p.stroke_width.0.unwrap_or(0.0), &p.stroke_style), + BasicShapeFields::RegularStarPolygon(s) => { + (s.stroke_width.0.unwrap_or(0.0), &s.stroke_style) + } + }; + let stroke_style_offset = encode_stroke_style(fbb, stroke_style); + + // Shape descriptor + let shape_offset = match &fields { + BasicShapeFields::Rectangle(_) => { + fbs::CanonicalShapeRectangular::create(fbb, &fbs::CanonicalShapeRectangularArgs {}).as_union_value() + } + BasicShapeFields::Ellipse(e) => { + let inner = e.inner_radius.unwrap_or(0.0); + let angle = e.angle.unwrap_or(360.0); + let ring_sector_data = if inner != 0.0 || angle != 360.0 || e.start_angle != 0.0 { + Some(fbs::CanonicalEllipticalShapeRingSectorParameters::create( + fbb, + &fbs::CanonicalEllipticalShapeRingSectorParametersArgs { + inner_radius_ratio: inner, + start_angle: e.start_angle, + angle, + }, + )) + } else { + None + }; + fbs::CanonicalShapeElliptical::create( + fbb, + &fbs::CanonicalShapeEllipticalArgs { ring_sector_data }, + ) + .as_union_value() + } + BasicShapeFields::RegularPolygon(p) => { + fbs::CanonicalShapeRegularPolygon::create(fbb, &fbs::CanonicalShapeRegularPolygonArgs { + point_count: p.point_count as u32, + }).as_union_value() + } + BasicShapeFields::RegularStarPolygon(s) => { + fbs::CanonicalShapeRegularStarPolygon::create(fbb, &fbs::CanonicalShapeRegularStarPolygonArgs { + point_count: s.point_count as u32, + inner_radius_ratio: s.inner_radius, + }).as_union_value() + } + }; + + let bsn = fbs::BasicShapeNode::create(fbb, &fbs::BasicShapeNodeArgs { + node: Some(sys), layer: Some(layer), + type_: node_type, shape_type, shape: Some(shape_offset), + corner_radius: scalar_cr, fill_paints: fill_offsets, + stroke_style: Some(stroke_style_offset), stroke_width: stroke_width_f32, + rectangular_corner_radius: rect_cr.as_ref(), + stroke_paints: stroke_offsets, + ..Default::default() + }); + + make_node_slot(fbb, fbs::Node::BasicShapeNode, bsn.as_union_value()) +} + +fn encode_line_node<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + r: &LineNodeRec, + node_id: &str, + parent_id: &str, + position: &str, +) -> flatbuffers::WIPOffset> { + // Lines use AffineTransform::new(x, y, rotation) + let x = r.transform.x(); + let y = r.transform.y(); + let plt = affine_to_rotation_transform(&r.transform); + + let sys = encode_system_node_trait(fbb, node_id, "", r.active, false); + let layout = encode_shape_layout(fbb, x, y, Some(r.size.width), None, &r.layout_child); + let layer = encode_layer_trait( + fbb, + &LayerTraitInput { + parent_id, + position, + opacity: r.opacity, + blend_mode: r.blend_mode, + mask: r.mask, + effects: &r.effects, + post_layout_transform: plt, + layout: Some(layout), + }, + ); + + let sg = encode_stroke_geometry(fbb, &StrokeStyle { + stroke_align: r._data_stroke_align, + stroke_cap: r.stroke_cap, + stroke_join: StrokeJoin::Miter, + stroke_miter_limit: r.stroke_miter_limit, + stroke_dash_array: r.stroke_dash_array.clone(), + }, r.stroke_width); + + let stroke_offsets = encode_paints(fbb, &r.strokes); + + let ln = fbs::LineNode::create(fbb, &fbs::LineNodeArgs { + node: Some(sys), layer: Some(layer), stroke_geometry: Some(sg), + stroke_paints: stroke_offsets, + marker_start_shape: encode_stroke_marker(r.marker_start_shape), + marker_end_shape: encode_stroke_marker(r.marker_end_shape), + }); + make_node_slot(fbb, fbs::Node::LineNode, ln.as_union_value()) +} + +fn encode_vector_node<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + r: &VectorNodeRec, + node_id: &str, + parent_id: &str, + position: &str, +) -> flatbuffers::WIPOffset> { + let x = r.transform.x(); + let y = r.transform.y(); + let plt = affine_to_rotation_transform(&r.transform); + + let sys = encode_system_node_trait(fbb, node_id, "", r.active, false); + let layout = encode_shape_layout(fbb, x, y, None, None, &r.layout_child); + let layer = encode_layer_trait( + fbb, + &LayerTraitInput { + parent_id, + position, + opacity: r.opacity, + blend_mode: r.blend_mode, + mask: r.mask, + effects: &r.effects, + post_layout_transform: plt, + layout: Some(layout), + }, + ); + + // Vector network + let vn = encode_vector_network(fbb, &r.network); + + let sg = encode_stroke_geometry(fbb, &StrokeStyle { + stroke_align: r.stroke_align, + stroke_cap: r.stroke_cap, + stroke_join: r.stroke_join, + stroke_miter_limit: r.stroke_miter_limit, + stroke_dash_array: r.stroke_dash_array.clone(), + }, r.stroke_width); + + let fill_offsets = encode_paints(fbb, &r.fills); + let stroke_offsets = encode_paints(fbb, &r.strokes); + + let vn_node = fbs::VectorNode::create(fbb, &fbs::VectorNodeArgs { + node: Some(sys), layer: Some(layer), stroke_geometry: Some(sg), + stroke_paints: stroke_offsets, fill_paints: fill_offsets, + vector_network_data: vn, + marker_start_shape: encode_stroke_marker(r.marker_start_shape), + marker_end_shape: encode_stroke_marker(r.marker_end_shape), + ..Default::default() + }); + make_node_slot(fbb, fbs::Node::VectorNode, vn_node.as_union_value()) +} + +fn encode_text_span_node<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + r: &TextSpanNodeRec, + node_id: &str, + parent_id: &str, + position: &str, +) -> flatbuffers::WIPOffset> { + let x = r.transform.x(); + let y = r.transform.y(); + let plt = affine_to_rotation_transform(&r.transform); + + let sys = encode_system_node_trait(fbb, node_id, "", r.active, false); + let layout = encode_shape_layout(fbb, x, y, r.width, r.height, &r.layout_child); + let layer = encode_layer_trait( + fbb, + &LayerTraitInput { + parent_id, + position, + opacity: r.opacity, + blend_mode: r.blend_mode, + mask: r.mask, + effects: &r.effects, + post_layout_transform: plt, + layout: Some(layout), + }, + ); + + // Text style + let font_family_str = fbb.create_string(&r.text_style.font_family); + let font_weight = fbs::FontWeight::new(r.text_style.font_weight.0); + let text_style = fbs::TextStyleRec::create(fbb, &fbs::TextStyleRecArgs { + font_family: Some(font_family_str), + font_size: r.text_style.font_size, + font_weight: Some(&font_weight), + ..Default::default() + }); + + let text_str = fbb.create_string(&r.text); + let fill_offsets = encode_paints(fbb, &r.fills); + let stroke_offsets = encode_paints(fbb, &r.strokes); + + let sg = encode_stroke_geometry(fbb, &StrokeStyle { + stroke_align: r.stroke_align, + stroke_cap: StrokeCap::Butt, + stroke_join: StrokeJoin::Miter, + stroke_miter_limit: StrokeMiterLimit::default(), + stroke_dash_array: None, + }, r.stroke_width); + + let props = fbs::TextSpanNodeProperties::create(fbb, &fbs::TextSpanNodePropertiesArgs { + text: Some(text_str), text_style: Some(text_style), + text_align: encode_text_align(r.text_align), + text_align_vertical: encode_text_align_vertical(r.text_align_vertical), + fill_paints: fill_offsets, stroke_paints: stroke_offsets, + stroke_geometry: Some(sg), + ..Default::default() + }); + + let tn = fbs::TextSpanNode::create(fbb, &fbs::TextSpanNodeArgs { + node: Some(sys), layer: Some(layer), properties: Some(props), + }); + make_node_slot(fbb, fbs::Node::TextSpanNode, tn.as_union_value()) +} + +fn encode_boolean_operation_node<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + r: &BooleanPathOperationNodeRec, + node_id: &str, + parent_id: &str, + position: &str, +) -> flatbuffers::WIPOffset> { + let sys = encode_system_node_trait(fbb, node_id, "", r.active, false); + let layout = encode_shape_layout(fbb, 0.0, 0.0, None, None, &None); + let layer = encode_layer_trait( + fbb, + &LayerTraitInput { + parent_id, + position, + opacity: r.opacity, + blend_mode: r.blend_mode, + mask: r.mask, + effects: &r.effects, + post_layout_transform: None, + layout: Some(layout), + }, + ); + + let op = encode_boolean_path_op(r.op); + + // Corner radius + let cr_offset = r.corner_radius.map(|cr| { + let radius = fbs::CGRadius::new(cr, cr); + let cr_trait = fbs::CornerRadiusTrait::create( + fbb, + &fbs::CornerRadiusTraitArgs { + corner_radius: Some(&radius), + corner_smoothing: 0.0, + }, + ); + cr_trait + }); + + let sg = encode_stroke_geometry(fbb, &r.stroke_style, r.stroke_width.0.unwrap_or(0.0)); + let fill_offsets = encode_paints(fbb, &r.fills); + let stroke_offsets = encode_paints(fbb, &r.strokes); + + let bon = fbs::BooleanOperationNode::create( + fbb, + &fbs::BooleanOperationNodeArgs { + node: Some(sys), + layer: Some(layer), + op, + corner_radius: cr_offset, + fill_paints: fill_offsets, + stroke_geometry: Some(sg), + stroke_paints: stroke_offsets, + }, + ); + make_node_slot(fbb, fbs::Node::BooleanOperationNode, bon.as_union_value()) +} + +// ───────────────────────────────────────────────────────────────────────────── +// Vector network encoding +// ───────────────────────────────────────────────────────────────────────────── + +fn encode_vector_network<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + network: &VectorNetwork, +) -> Option>> { + if network.vertices.is_empty() && network.segments.is_empty() && network.regions.is_empty() { + return None; + } + + let vertices: Vec = network + .vertices + .iter() + .map(|(x, y)| fbs::CGPoint::new(*x, *y)) + .collect(); + let vertices_vec = fbb.create_vector(&vertices); + + let segments: Vec = network + .segments + .iter() + .map(|s| { + let ta = fbs::CGPoint::new(s.ta.0, s.ta.1); + let tb = fbs::CGPoint::new(s.tb.0, s.tb.1); + fbs::VectorNetworkSegment::new(s.a as u32, s.b as u32, &ta, &tb) + }) + .collect(); + let segments_vec = fbb.create_vector(&segments); + + let region_offsets: Vec<_> = network + .regions + .iter() + .map(|r| encode_vector_network_region(fbb, r)) + .collect(); + let regions_vec = fbb.create_vector(®ion_offsets); + + Some(fbs::VectorNetworkData::create( + fbb, + &fbs::VectorNetworkDataArgs { + vertices: Some(vertices_vec), + segments: Some(segments_vec), + regions: Some(regions_vec), + }, + )) +} + +fn encode_vector_network_region<'a, A: flatbuffers::Allocator + 'a>( + fbb: &mut flatbuffers::FlatBufferBuilder<'a, A>, + region: &VectorNetworkRegion, +) -> flatbuffers::WIPOffset> { + let loops: Vec<_> = region + .loops + .iter() + .map(|l| { + let indices: Vec = l.0.iter().map(|&i| i as u32).collect(); + let indices_vec = fbb.create_vector(&indices); + fbs::VectorNetworkLoop::create( + fbb, + &fbs::VectorNetworkLoopArgs { + loop_segment_indices: Some(indices_vec), + }, + ) + }) + .collect(); + let loops_vec = fbb.create_vector(&loops); + + let fill_rule = match region.fill_rule { + crate::cg::types::FillRule::EvenOdd => fbs::FillRule::EvenOdd, + crate::cg::types::FillRule::NonZero => fbs::FillRule::NonZero, + }; + + let fills_offset = region + .fills + .as_ref() + .and_then(|p| encode_paints(fbb, p)); + + fbs::VectorNetworkRegion::create( + fbb, + &fbs::VectorNetworkRegionArgs { + region_loops: Some(loops_vec), + region_fill_rule: fill_rule, + region_fill_paints: fills_offset, + }, + ) +} + +// ───────────────────────────────────────────────────────────────────────────── +// Geometry helpers for encoding +// ───────────────────────────────────────────────────────────────────────────── + +fn encode_rectangular_corner_radius( + cr: &RectangularCornerRadius, +) -> fbs::RectangularCornerRadius { + let tl = fbs::CGRadius::new(cr.tl.rx, cr.tl.ry); + let tr = fbs::CGRadius::new(cr.tr.rx, cr.tr.ry); + let bl = fbs::CGRadius::new(cr.bl.rx, cr.bl.ry); + let br = fbs::CGRadius::new(cr.br.rx, cr.br.ry); + fbs::RectangularCornerRadius::new(&tl, &tr, &bl, &br) +} + +fn encode_rectangular_stroke_width(sw: &StrokeWidth) -> Option { + match sw { + StrokeWidth::None => Some(fbs::RectangularStrokeWidth::new(0.0, 0.0, 0.0, 0.0)), + StrokeWidth::Uniform(w) => Some(fbs::RectangularStrokeWidth::new(*w, *w, *w, *w)), + StrokeWidth::Rectangular(rsw) => Some(fbs::RectangularStrokeWidth::new( + rsw.stroke_top_width, + rsw.stroke_right_width, + rsw.stroke_bottom_width, + rsw.stroke_left_width, + )), + } +} + +/// Reverse-engineer (x, y) from an `AffineTransform` that was created via +/// `AffineTransform::from_box_center(x, y, w, h, rotation_deg)`. +/// +/// `from_box_center` = `from_box(x, y, w, h, deg, 0.5, 0.5)`: +/// tx = x + (w/2)*(1-cos) + sin*(h/2) +/// ty = y + (h/2)*(1-cos) - sin*(w/2) +/// +/// So: x = tx - (w/2)*(1-cos) - sin*(h/2) +/// y = ty - (h/2)*(1-cos) + sin*(w/2) +fn reverse_from_box_center(t: &AffineTransform, w: f32, h: f32) -> (f32, f32) { + let cos = t.matrix[0][0]; + let sin = t.matrix[1][0]; + let tx = t.matrix[0][2]; + let ty = t.matrix[1][2]; + let x = tx - (w / 2.0) * (1.0 - cos) - sin * (h / 2.0); + let y = ty - (h / 2.0) * (1.0 - cos) + sin * (w / 2.0); + (x, y) +} diff --git a/crates/grida-canvas/src/io/mod.rs b/crates/grida-canvas/src/io/mod.rs index 94b5a8297b..e59de298fd 100644 --- a/crates/grida-canvas/src/io/mod.rs +++ b/crates/grida-canvas/src/io/mod.rs @@ -1,6 +1,10 @@ #[cfg(feature = "figma")] pub mod io_figma; +pub mod generated; + +pub mod io_grida_fbs; + pub mod id_converter; pub mod io_css; pub mod io_grida; diff --git a/crates/grida-canvas/src/node/scene_graph.rs b/crates/grida-canvas/src/node/scene_graph.rs index 817858b4b7..1c9f07a607 100644 --- a/crates/grida-canvas/src/node/scene_graph.rs +++ b/crates/grida-canvas/src/node/scene_graph.rs @@ -263,6 +263,14 @@ impl SceneGraph { self.nodes.is_empty() } + /// Iterate over all `(NodeId, &Node)` pairs in the graph. + /// + /// The iteration order is not guaranteed; callers should use `roots()` + + /// `get_children()` if they need tree order. + pub fn nodes_iter(&self) -> impl Iterator { + self.nodes.iter() + } + // ------------------------------------------------------------------------- // Tree Traversal Methods // ------------------------------------------------------------------------- diff --git a/crates/grida-canvas/src/sk/mappings.rs b/crates/grida-canvas/src/sk/mappings.rs index 4e28b503a2..f295aeac86 100644 --- a/crates/grida-canvas/src/sk/mappings.rs +++ b/crates/grida-canvas/src/sk/mappings.rs @@ -157,7 +157,7 @@ impl From for skia_safe::textlayout::Decoration { // }, color: decoration.text_decoration_color.into(), style: decoration.text_decoration_style.into(), - thickness_multiplier: decoration.text_decoration_thinkness, + thickness_multiplier: decoration.text_decoration_thickness, } } } diff --git a/crates/grida-canvas/src/text/attributed_text_conv.rs b/crates/grida-canvas/src/text/attributed_text_conv.rs index 3fd0dd81f1..b2f80f3a9f 100644 --- a/crates/grida-canvas/src/text/attributed_text_conv.rs +++ b/crates/grida-canvas/src/text/attributed_text_conv.rs @@ -267,7 +267,7 @@ impl From<&TextStyleRec> for TextStyle { a: c.a as f32 / 255.0, }), d.text_decoration_skip_ink.unwrap_or(true), - d.text_decoration_thinkness.unwrap_or(1.0), + d.text_decoration_thickness.unwrap_or(1.0), ) } else { ( @@ -336,7 +336,7 @@ impl From<&TextStyle> for TextStyleRec { ) }), text_decoration_skip_ink: Some(s.text_decoration_skip_ink), - text_decoration_thinkness: Some(s.text_decoration_thickness), + text_decoration_thickness: Some(s.text_decoration_thickness), }) }; diff --git a/crates/grida-canvas/src/window/application.rs b/crates/grida-canvas/src/window/application.rs index d6f5101f3a..7bb1b72365 100644 --- a/crates/grida-canvas/src/window/application.rs +++ b/crates/grida-canvas/src/window/application.rs @@ -295,7 +295,9 @@ impl ApplicationApi for UnknownTargetApplication { } } } - ApplicationCommand::None => {} + ApplicationCommand::None + | ApplicationCommand::NextScene + | ApplicationCommand::PrevScene => {} } false diff --git a/crates/grida-canvas/src/window/command.rs b/crates/grida-canvas/src/window/command.rs index df974c6832..8063accc99 100644 --- a/crates/grida-canvas/src/window/command.rs +++ b/crates/grida-canvas/src/window/command.rs @@ -7,4 +7,6 @@ pub enum ApplicationCommand { Pan { tx: f32, ty: f32 }, ToggleDebugMode, TryCopyAsPNG, + NextScene, + PrevScene, } diff --git a/crates/grida-canvas/tests/fbs_roundtrip.rs b/crates/grida-canvas/tests/fbs_roundtrip.rs new file mode 100644 index 0000000000..6cce8e08d5 --- /dev/null +++ b/crates/grida-canvas/tests/fbs_roundtrip.rs @@ -0,0 +1,1697 @@ +//! In-memory round-trip tests for the `.grida` FlatBuffers encoder/decoder. +//! +//! Test binary: `fbs_roundtrip` (this file). Each `gen_*` test builds a scene +//! in Rust, encodes → decodes → compares every node's `Debug` output. No files +//! are written to disk. +//! +//! - **Compile-time breakage**: any schema change will cause a build error. +//! - **Exhaustive coverage**: every node type, paint variant, effect kind, +//! and stroke/corner/layout option is exercised. + +use std::collections::HashMap; + +use cg::cg::alignment::Alignment; +use cg::cg::color::CGColor; +use cg::cg::fe::*; +use cg::cg::stroke_dasharray::StrokeDashArray; +use cg::cg::stroke_width::{RectangularStrokeWidth, SingularStrokeWidth, StrokeWidth}; +use cg::cg::tilemode::TileMode; +use cg::cg::types::*; +use cg::io::io_grida_fbs; +use cg::node::scene_graph::SceneGraph; +use cg::node::schema::*; +use cg::vectornetwork::*; +use math2::transform::AffineTransform; + +// ═════════════════════════════════════════════════════════════════════════════ +// Helpers +// ═════════════════════════════════════════════════════════════════════════════ + +/// Build a `Scene` from a list of `(id, node)` pairs and a parent→children map. +/// All top-level entries (those whose id is NOT a child of any other entry) become roots. +fn build_scene( + name: &str, + bg: Option, + nodes: Vec<(NodeId, Node)>, + links: HashMap>, + roots: Vec, +) -> Scene { + let graph = SceneGraph::new_from_snapshot(nodes, links, roots); + Scene { + name: name.to_owned(), + graph, + background_color: bg, + } +} + +/// Build `id_map` and `position_map` for a scene, matching the convention used +/// by the TS encoder (string node IDs and fractional-index position keys). +fn build_maps( + scene: &Scene, + id_map: &mut HashMap, + position_map: &mut HashMap, +) { + fn walk( + graph: &SceneGraph, + nid: &NodeId, + counter: &mut usize, + id_map: &mut HashMap, + position_map: &mut HashMap, + ) { + id_map.entry(*nid).or_insert_with(|| format!("n{nid}")); + if let Some(children) = graph.get_children(nid) { + for (i, child) in children.clone().iter().enumerate() { + // Zero-pad to ensure lexicographic order matches insertion order + let pos = format!("a{i:04}"); + position_map.insert(*child, pos); + walk(graph, child, counter, id_map, position_map); + } + } + *counter += 1; + } + let mut counter = 0usize; + for root in scene.graph.roots() { + walk(&scene.graph, &root, &mut counter, id_map, position_map); + } +} + +/// Encode a scene, then decode it, and assert every node's `Debug` output matches. +fn assert_roundtrip_scene(scene: &Scene, scene_id: &str, label: &str) { + let mut id_map: HashMap = HashMap::new(); + let mut position_map: HashMap = HashMap::new(); + build_maps(scene, &mut id_map, &mut position_map); + + // Encode + let bytes = io_grida_fbs::encode(scene, scene_id, &id_map, &position_map); + assert!(!bytes.is_empty(), "{label}: encoded bytes empty"); + + // Decode + let dr = io_grida_fbs::decode_with_id_map(&bytes) + .unwrap_or_else(|e| panic!("{label}: decode failed: {e}")); + assert!(!dr.scenes.is_empty(), "{label}: no scenes decoded"); + let scene2 = &dr.scenes[0]; + + // Compare scene name + assert_eq!(scene.name, scene2.name, "{label}: scene name mismatch"); + + // Compare background color + assert_eq!( + format!("{:?}", scene.background_color), + format!("{:?}", scene2.background_color), + "{label}: background_color mismatch" + ); + + // Collect and compare all nodes + let nodes1 = collect_debug(&scene.graph); + let nodes2 = collect_debug(&scene2.graph); + assert_eq!( + nodes1.len(), + nodes2.len(), + "{label}: node count mismatch ({} vs {})", + nodes1.len(), + nodes2.len() + ); + for (i, (d1, d2)) in nodes1.iter().zip(nodes2.iter()).enumerate() { + assert_eq!( + d1, d2, + "{label}: node[{i}] mismatch.\n--- original ---\n{d1}\n--- decoded ---\n{d2}" + ); + } + + // Also verify encode stability: encode again and compare bytes + let bytes2 = io_grida_fbs::encode(scene2, &dr.scene_ids[0], &dr.id_map, &dr.position_map); + let dr2 = io_grida_fbs::decode_with_id_map(&bytes2) + .unwrap_or_else(|e| panic!("{label}: decode 2 failed: {e}")); + let bytes3 = io_grida_fbs::encode( + &dr2.scenes[0], + &dr2.scene_ids[0], + &dr2.id_map, + &dr2.position_map, + ); + assert_eq!( + bytes2, bytes3, + "{label}: encode not stable (len {} vs {})", + bytes2.len(), + bytes3.len() + ); +} + +fn collect_debug(graph: &SceneGraph) -> Vec { + let mut out = Vec::new(); + for root in graph.roots() { + collect_debug_preorder(graph, &root, &mut out); + } + out +} + +fn collect_debug_preorder(graph: &SceneGraph, nid: &NodeId, out: &mut Vec) { + if let Ok(node) = graph.get_node(nid) { + out.push(format!("{node:?}")); + if let Some(children) = graph.get_children(nid) { + for child in children.clone() { + collect_debug_preorder(graph, &child, out); + } + } + } +} + +// ═════════════════════════════════════════════════════════════════════════════ +// Paint builders +// ═════════════════════════════════════════════════════════════════════════════ + +fn solid(r: u8, g: u8, b: u8, a: u8) -> Paint { + Paint::Solid(SolidPaint { + active: true, + color: CGColor { r, g, b, a }, + blend_mode: BlendMode::Normal, + }) +} + +fn linear_gradient() -> Paint { + Paint::LinearGradient(LinearGradientPaint { + active: true, + xy1: Alignment::CENTER_LEFT, + xy2: Alignment::CENTER_RIGHT, + tile_mode: TileMode::default(), + transform: AffineTransform::default(), + stops: vec![ + GradientStop { + offset: 0.0, + color: CGColor { + r: 255, + g: 0, + b: 0, + a: 255, + }, + }, + GradientStop { + offset: 1.0, + color: CGColor { + r: 0, + g: 0, + b: 255, + a: 255, + }, + }, + ], + opacity: 1.0, + blend_mode: BlendMode::Normal, + }) +} + +fn radial_gradient() -> Paint { + Paint::RadialGradient(RadialGradientPaint { + active: true, + transform: AffineTransform::default(), + stops: vec![ + GradientStop { + offset: 0.0, + color: CGColor { + r: 255, + g: 255, + b: 0, + a: 255, + }, + }, + GradientStop { + offset: 1.0, + color: CGColor { + r: 0, + g: 128, + b: 0, + a: 200, + }, + }, + ], + opacity: 0.8, + blend_mode: BlendMode::Screen, + tile_mode: TileMode::default(), + }) +} + +fn sweep_gradient() -> Paint { + Paint::SweepGradient(SweepGradientPaint { + active: true, + transform: AffineTransform::default(), + stops: vec![ + GradientStop { + offset: 0.0, + color: CGColor { + r: 0, + g: 255, + b: 255, + a: 255, + }, + }, + GradientStop { + offset: 0.5, + color: CGColor { + r: 255, + g: 0, + b: 255, + a: 255, + }, + }, + GradientStop { + offset: 1.0, + color: CGColor { + r: 255, + g: 255, + b: 0, + a: 255, + }, + }, + ], + opacity: 0.9, + blend_mode: BlendMode::Overlay, + }) +} + +fn image_paint() -> Paint { + Paint::Image(ImagePaint { + active: true, + image: ResourceRef::HASH("abc123hash".to_owned()), + quarter_turns: 1, + alignement: Alignment::TOP_LEFT, + fit: ImagePaintFit::Fit(math2::box_fit::BoxFit::Cover), + opacity: 0.95, + blend_mode: BlendMode::Multiply, + filters: ImageFilters::default(), + }) +} + +// ═════════════════════════════════════════════════════════════════════════════ +// Effect builders +// ═════════════════════════════════════════════════════════════════════════════ + +fn full_effects() -> LayerEffects { + LayerEffects { + blur: Some(FeLayerBlur { + blur: FeBlur::Gaussian(FeGaussianBlur { radius: 4.0 }), + active: true, + }), + backdrop_blur: Some(FeBackdropBlur { + blur: FeBlur::Gaussian(FeGaussianBlur { radius: 8.0 }), + active: true, + }), + shadows: vec![ + FilterShadowEffect::DropShadow(FeShadow { + dx: 2.0, + dy: 3.0, + blur: 6.0, + spread: 1.0, + color: CGColor { + r: 0, + g: 0, + b: 0, + a: 128, + }, + active: true, + }), + FilterShadowEffect::InnerShadow(FeShadow { + dx: -1.0, + dy: -1.0, + blur: 2.0, + spread: 0.0, + color: CGColor { + r: 255, + g: 255, + b: 255, + a: 64, + }, + active: false, + }), + ], + glass: Some(FeLiquidGlass { + light_intensity: 0.7, + light_angle: 45.0, + refraction: 1.5, + depth: 0.3, + dispersion: 0.1, + blur_radius: 3.0, + active: true, + }), + noises: vec![ + FeNoiseEffect { + noise_size: 100.0, + density: 0.5, + num_octaves: 4, + seed: 42.0, + coloring: NoiseEffectColors::Mono { + color: CGColor { + r: 128, + g: 128, + b: 128, + a: 80, + }, + }, + active: true, + blend_mode: BlendMode::Overlay, + }, + FeNoiseEffect { + noise_size: 50.0, + density: 0.8, + num_octaves: 2, + seed: 7.0, + coloring: NoiseEffectColors::Duo { + color1: CGColor { + r: 0, + g: 0, + b: 0, + a: 200, + }, + color2: CGColor { + r: 255, + g: 255, + b: 255, + a: 200, + }, + }, + active: true, + blend_mode: BlendMode::SoftLight, + }, + FeNoiseEffect { + noise_size: 200.0, + density: 0.3, + num_octaves: 1, + seed: 0.0, + coloring: NoiseEffectColors::Multi { opacity: 0.6 }, + active: false, + blend_mode: BlendMode::Normal, + }, + ], + } +} + +// ═════════════════════════════════════════════════════════════════════════════ +// Stroke / corner radius builders +// ═════════════════════════════════════════════════════════════════════════════ + +fn dashed_stroke_style() -> StrokeStyle { + StrokeStyle { + stroke_align: StrokeAlign::Outside, + stroke_cap: StrokeCap::Round, + stroke_join: StrokeJoin::Round, + stroke_miter_limit: StrokeMiterLimit(8.0), + stroke_dash_array: Some(StrokeDashArray(vec![5.0, 3.0, 1.0, 3.0])), + } +} + +fn per_side_corner_radius() -> RectangularCornerRadius { + RectangularCornerRadius { + tl: Radius::elliptical(10.0, 10.0), + tr: Radius::elliptical(20.0, 15.0), + bl: Radius::elliptical(5.0, 5.0), + br: Radius::elliptical(0.0, 0.0), + } +} + +fn rectangular_stroke_width() -> StrokeWidth { + StrokeWidth::Rectangular(RectangularStrokeWidth { + stroke_top_width: 1.0, + stroke_right_width: 2.0, + stroke_bottom_width: 3.0, + stroke_left_width: 4.0, + }) +} + +// ═════════════════════════════════════════════════════════════════════════════ +// Tests — one per node type / feature area +// ═════════════════════════════════════════════════════════════════════════════ + +// ─── Rectangle ────────────────────────────────────────────────────────────── + +#[test] +fn gen_rectangle_basic() { + let rect = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 0.85, + blend_mode: LayerBlendMode::Blend(BlendMode::Multiply), + mask: None, + transform: AffineTransform::from_box_center(50.0, 60.0, 200.0, 100.0, 30.0), + size: Size { + width: 200.0, + height: 100.0, + }, + corner_radius: per_side_corner_radius(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(255, 0, 0, 255), linear_gradient()]), + strokes: Paints::new(vec![solid(0, 0, 255, 255)]), + stroke_style: dashed_stroke_style(), + stroke_width: StrokeWidth::Uniform(2.5), + effects: full_effects(), + layout_child: Some(LayoutChildStyle { + layout_grow: 1.0, + layout_positioning: LayoutPositioning::Absolute, + }), + }); + + let scene = build_scene( + "Rectangle Test", + Some(CGColor { + r: 240, + g: 240, + b: 240, + a: 255, + }), + vec![(1, rect)], + HashMap::new(), + vec![1], + ); + assert_roundtrip_scene(&scene, "s1", "rectangle_basic"); +} + +#[test] +fn gen_rectangle_per_side_stroke() { + let rect = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 0.0, 80.0, 80.0, 0.0), + size: Size { + width: 80.0, + height: 80.0, + }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(200, 200, 200, 255)]), + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_style: StrokeStyle { + stroke_align: StrokeAlign::Inside, + stroke_cap: StrokeCap::Square, + stroke_join: StrokeJoin::Bevel, + stroke_miter_limit: StrokeMiterLimit(4.0), + stroke_dash_array: None, + }, + // Note: BasicShapeNode encodes stroke_width as a single f32 via `max()`, + // so per-side (Rectangular) stroke widths are collapsed on roundtrip. + // Use Uniform here; Container nodes support Rectangular stroke widths. + stroke_width: StrokeWidth::Uniform(4.0), + effects: LayerEffects::default(), + layout_child: None, + }); + + let scene = build_scene("RectStroke", None, vec![(1, rect)], HashMap::new(), vec![1]); + assert_roundtrip_scene(&scene, "s1", "rectangle_per_side_stroke"); +} + +// ─── Ellipse ──────────────────────────────────────────────────────────────── + +#[test] +fn gen_ellipse() { + let ellipse = Node::Ellipse(EllipseNodeRec { + active: true, + opacity: 0.6, + blend_mode: LayerBlendMode::Blend(BlendMode::Screen), + mask: None, + transform: AffineTransform::from_box_center(100.0, 100.0, 90.0, 60.0, 0.0), + size: Size { + width: 90.0, + height: 60.0, + }, + fills: Paints::new(vec![radial_gradient()]), + strokes: Paints::new(vec![solid(128, 0, 128, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(Some(1.5)), + inner_radius: None, + start_angle: 0.0, + angle: None, + corner_radius: None, + effects: LayerEffects::default(), + layout_child: None, + }); + + let scene = build_scene("Ellipse Test", None, vec![(1, ellipse)], HashMap::new(), vec![1]); + assert_roundtrip_scene(&scene, "s1", "ellipse"); +} + +#[test] +fn gen_ellipse_arc() { + // Donut (inner_radius only) + let donut = Node::Ellipse(EllipseNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 0.0, 100.0, 100.0, 0.0), + size: Size { width: 100.0, height: 100.0 }, + fills: Paints::new(vec![solid(0, 200, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + inner_radius: Some(0.5), + start_angle: 0.0, + angle: None, + corner_radius: None, + effects: LayerEffects::default(), + layout_child: None, + }); + + // Pie wedge (start_angle + angle) + let pie = Node::Ellipse(EllipseNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(120.0, 0.0, 100.0, 100.0, 0.0), + size: Size { width: 100.0, height: 100.0 }, + fills: Paints::new(vec![solid(200, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + inner_radius: None, + start_angle: 45.0, + angle: Some(90.0), + // Note: corner_radius is not in the FBS schema, so it won't roundtrip. + corner_radius: None, + effects: LayerEffects::default(), + layout_child: None, + }); + + // Arc sector (inner_radius + start_angle + angle) + let arc = Node::Ellipse(EllipseNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(240.0, 0.0, 100.0, 100.0, 0.0), + size: Size { width: 100.0, height: 100.0 }, + fills: Paints::new(vec![solid(0, 0, 200, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + inner_radius: Some(0.6), + start_angle: 0.0, + angle: Some(270.0), + corner_radius: None, + effects: LayerEffects::default(), + layout_child: None, + }); + + let scene = build_scene( + "Ellipse Arcs", + None, + vec![(1, donut), (2, pie), (3, arc)], + HashMap::new(), + vec![1, 2, 3], + ); + assert_roundtrip_scene(&scene, "s1", "ellipse_arc"); +} + +// ─── Regular Polygon ──────────────────────────────────────────────────────── + +#[test] +fn gen_regular_polygon() { + let poly = Node::RegularPolygon(RegularPolygonNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(0.0, 0.0, 100.0, 100.0, 0.0), + size: Size { + width: 100.0, + height: 100.0, + }, + point_count: 6, + corner_radius: 5.0, + fills: Paints::new(vec![sweep_gradient()]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + layout_child: None, + }); + + let scene = build_scene("Polygon", None, vec![(1, poly)], HashMap::new(), vec![1]); + assert_roundtrip_scene(&scene, "s1", "regular_polygon"); +} + +// ─── Regular Star Polygon ─────────────────────────────────────────────────── + +#[test] +fn gen_regular_star_polygon() { + let star = Node::RegularStarPolygon(RegularStarPolygonNodeRec { + active: true, + opacity: 0.9, + blend_mode: LayerBlendMode::Blend(BlendMode::Overlay), + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(50.0, 50.0, 120.0, 120.0, 15.0), + size: Size { + width: 120.0, + height: 120.0, + }, + point_count: 5, + inner_radius: 0.4, + corner_radius: 3.0, + fills: Paints::new(vec![solid(255, 215, 0, 255)]), + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(Some(2.0)), + layout_child: None, + }); + + let scene = build_scene("Star", None, vec![(1, star)], HashMap::new(), vec![1]); + assert_roundtrip_scene(&scene, "s1", "regular_star_polygon"); +} + +// ─── Line ─────────────────────────────────────────────────────────────────── + +#[test] +fn gen_line() { + let line = Node::Line(LineNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::new(10.0, 20.0, 45.0), + size: Size { + width: 200.0, + height: 0.0, + }, + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_width: 3.0, + stroke_cap: StrokeCap::Round, + stroke_miter_limit: StrokeMiterLimit(4.0), + stroke_dash_array: Some(StrokeDashArray(vec![10.0, 5.0])), + _data_stroke_align: StrokeAlign::Center, + marker_start_shape: StrokeMarkerPreset::Circle, + marker_end_shape: StrokeMarkerPreset::EquilateralTriangle, + layout_child: None, + }); + + let scene = build_scene("Line", None, vec![(1, line)], HashMap::new(), vec![1]); + assert_roundtrip_scene(&scene, "s1", "line"); +} + +// ─── Text Span ────────────────────────────────────────────────────────────── + +#[test] +fn gen_text_span() { + let text = Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(30.0, 40.0, 0.0), + width: Some(250.0), + height: Some(80.0), + layout_child: Some(LayoutChildStyle { + layout_grow: 0.0, + layout_positioning: LayoutPositioning::Auto, + }), + text: "Hello, Grida!".to_owned(), + text_style: { + let mut ts = TextStyleRec::from_font("Roboto", 24.0); + ts.font_weight = FontWeight(700); + ts + }, + text_align: TextAlign::Center, + text_align_vertical: TextAlignVertical::Center, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![solid(255, 0, 0, 128)]), + stroke_width: 0.5, + stroke_align: StrokeAlign::Outside, + opacity: 0.95, + blend_mode: LayerBlendMode::Blend(BlendMode::Normal), + mask: None, + effects: LayerEffects { + blur: None, + backdrop_blur: None, + shadows: vec![FilterShadowEffect::DropShadow(FeShadow { + dx: 1.0, + dy: 1.0, + blur: 2.0, + spread: 0.0, + color: CGColor { + r: 0, + g: 0, + b: 0, + a: 100, + }, + active: true, + })], + glass: None, + noises: vec![], + }, + }); + + let scene = build_scene("Text", None, vec![(1, text)], HashMap::new(), vec![1]); + assert_roundtrip_scene(&scene, "s1", "text_span"); +} + +// ─── Vector Network ───────────────────────────────────────────────────────── + +#[test] +fn gen_vector_node() { + let vector = Node::Vector(VectorNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::from_box_center(0.0, 0.0, 100.0, 100.0, 0.0), + network: VectorNetwork { + vertices: vec![(0.0, 0.0), (100.0, 0.0), (100.0, 100.0), (0.0, 100.0)], + segments: vec![ + VectorNetworkSegment { + a: 0, + b: 1, + ta: (30.0, 0.0), + tb: (-30.0, 0.0), + }, + VectorNetworkSegment { + a: 1, + b: 2, + ta: (0.0, 30.0), + tb: (0.0, -30.0), + }, + VectorNetworkSegment { + a: 2, + b: 3, + ta: (-30.0, 0.0), + tb: (30.0, 0.0), + }, + VectorNetworkSegment { + a: 3, + b: 0, + ta: (0.0, -30.0), + tb: (0.0, 30.0), + }, + ], + regions: vec![VectorNetworkRegion { + loops: vec![VectorNetworkLoop(vec![0, 1, 2, 3])], + fill_rule: FillRule::EvenOdd, + fills: Some(Paints::new(vec![solid(100, 200, 50, 255)])), + }], + }, + corner_radius: 0.0, + fills: Paints::new(vec![solid(50, 100, 200, 255)]), + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_width: 1.5, + stroke_width_profile: None, + stroke_align: StrokeAlign::Center, + stroke_cap: StrokeCap::Butt, + stroke_join: StrokeJoin::Miter, + stroke_miter_limit: StrokeMiterLimit(4.0), + stroke_dash_array: None, + marker_start_shape: StrokeMarkerPreset::Diamond, + marker_end_shape: StrokeMarkerPreset::VerticalBar, + layout_child: None, + }); + + let scene = build_scene("Vector", None, vec![(1, vector)], HashMap::new(), vec![1]); + assert_roundtrip_scene(&scene, "s1", "vector_node"); +} + +// ─── Boolean Operation ────────────────────────────────────────────────────── + +#[test] +fn gen_boolean_operation() { + // boolean op contains children (shapes), but the BooleanPathOperationNodeRec + // itself only holds the op metadata; children are in the graph links. + let bool_op = Node::BooleanOperation(BooleanPathOperationNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: Some(AffineTransform::from_box_center(0.0, 0.0, 100.0, 100.0, 0.0)), + op: BooleanPathOperation::Intersection, + corner_radius: Some(4.0), + fills: Paints::new(vec![solid(200, 100, 50, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(Some(1.0)), + }); + + let child_rect = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 0.0, 60.0, 60.0, 0.0), + size: Size { + width: 60.0, + height: 60.0, + }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: None, + }); + + let mut links = HashMap::new(); + links.insert(1u64, vec![2u64]); + + let scene = build_scene( + "Boolean", + None, + vec![(1, bool_op), (2, child_rect)], + links, + vec![1], + ); + assert_roundtrip_scene(&scene, "s1", "boolean_operation"); +} + +// ─── Group ────────────────────────────────────────────────────────────────── + +#[test] +fn gen_group() { + let group = Node::Group(GroupNodeRec { + active: true, + opacity: 0.8, + blend_mode: LayerBlendMode::Blend(BlendMode::Darken), + mask: None, + transform: Some(AffineTransform::from_box_center(10.0, 20.0, 0.0, 0.0, 45.0)), + }); + + let child_ellipse = Node::Ellipse(EllipseNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 0.0, 50.0, 50.0, 0.0), + size: Size { + width: 50.0, + height: 50.0, + }, + fills: Paints::new(vec![solid(0, 255, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + inner_radius: None, + start_angle: 0.0, + angle: None, + corner_radius: None, + effects: LayerEffects::default(), + layout_child: None, + }); + + let mut links = HashMap::new(); + links.insert(1u64, vec![2u64]); + + let scene = build_scene( + "Group", + None, + vec![(1, group), (2, child_ellipse)], + links, + vec![1], + ); + assert_roundtrip_scene(&scene, "s1", "group"); +} + +// ─── Container ────────────────────────────────────────────────────────────── + +#[test] +fn gen_container_with_layout() { + let container = Node::Container(ContainerNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + rotation: 0.0, + position: LayoutPositioningBasis::Inset(EdgeInsets { + top: 10.0, + right: 0.0, + bottom: 0.0, + left: 20.0, + }), + layout_container: LayoutContainerStyle { + layout_mode: LayoutMode::Flex, + layout_direction: Axis::Horizontal, + layout_wrap: Some(LayoutWrap::Wrap), + layout_main_axis_alignment: Some(MainAxisAlignment::SpaceBetween), + layout_cross_axis_alignment: Some(CrossAxisAlignment::Center), + layout_padding: Some(EdgeInsets { + top: 8.0, + right: 12.0, + bottom: 8.0, + left: 12.0, + }), + layout_gap: Some(LayoutGap { + main_axis_gap: 10.0, + cross_axis_gap: 5.0, + }), + }, + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(400.0), + layout_target_height: Some(300.0), + layout_min_width: None, + layout_max_width: None, + layout_min_height: None, + layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: per_side_corner_radius(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(245, 245, 245, 255)]), + strokes: Paints::new(vec![solid(200, 200, 200, 255)]), + stroke_style: StrokeStyle { + stroke_align: StrokeAlign::Inside, + stroke_cap: StrokeCap::Butt, + stroke_join: StrokeJoin::Miter, + stroke_miter_limit: StrokeMiterLimit(4.0), + stroke_dash_array: None, + }, + stroke_width: rectangular_stroke_width(), + effects: LayerEffects::default(), + clip: true, + }); + + // A child that tests layout_child properties + let child = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 0.0, 80.0, 40.0, 0.0), + size: Size { + width: 80.0, + height: 40.0, + }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(100, 149, 237, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: Some(LayoutChildStyle { + layout_grow: 1.0, + layout_positioning: LayoutPositioning::Auto, + }), + }); + + let mut links = HashMap::new(); + links.insert(1u64, vec![2u64]); + + let scene = build_scene( + "Container Layout", + None, + vec![(1, container), (2, child)], + links, + vec![1], + ); + assert_roundtrip_scene(&scene, "s1", "container_with_layout"); +} + +#[test] +fn gen_container_rotated() { + let container = Node::Container(ContainerNodeRec { + active: true, + opacity: 0.5, + blend_mode: LayerBlendMode::Blend(BlendMode::ColorBurn), + mask: None, + // Use 90.0 (exact multiple of 90) to avoid cos/sin float precision + // loss during roundtrip. Non-cardinal angles like 30.0 lose precision + // (e.g. 30.0 → 30.000002) when stored as cos/sin in the transform matrix. + rotation: 90.0, + position: LayoutPositioningBasis::Cartesian(CGPoint::new(100.0, 50.0)), + layout_container: LayoutContainerStyle::default(), + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(200.0), + layout_target_height: Some(150.0), + layout_min_width: None, + layout_max_width: None, + layout_min_height: None, + layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![image_paint()]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: full_effects(), + clip: false, + }); + + let scene = build_scene( + "RotatedContainer", + None, + vec![(1, container)], + HashMap::new(), + vec![1], + ); + assert_roundtrip_scene(&scene, "s1", "container_rotated"); +} + +// ─── InitialContainer ─────────────────────────────────────────────────────── + +#[test] +fn gen_initial_container() { + let ic = Node::InitialContainer(InitialContainerNodeRec { + active: true, + layout_mode: LayoutMode::Flex, + layout_direction: Axis::Vertical, + layout_wrap: LayoutWrap::NoWrap, + layout_main_axis_alignment: MainAxisAlignment::Center, + layout_cross_axis_alignment: CrossAxisAlignment::Stretch, + padding: EdgeInsets { + top: 16.0, + right: 16.0, + bottom: 16.0, + left: 16.0, + }, + layout_gap: LayoutGap { + main_axis_gap: 8.0, + cross_axis_gap: 0.0, + }, + }); + + let child = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 0.0, 100.0, 50.0, 0.0), + size: Size { + width: 100.0, + height: 50.0, + }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(50, 150, 50, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: None, + }); + + let mut links = HashMap::new(); + links.insert(1u64, vec![2u64]); + + let scene = build_scene( + "InitialContainer", + None, + vec![(1, ic), (2, child)], + links, + vec![1], + ); + assert_roundtrip_scene(&scene, "s1", "initial_container"); +} + +// ─── Masks ────────────────────────────────────────────────────────────────── + +#[test] +fn gen_mask_types() { + let image_mask = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: Some(LayerMaskType::Image(ImageMaskType::Alpha)), + transform: AffineTransform::from_box_center(0.0, 0.0, 100.0, 100.0, 0.0), + size: Size { + width: 100.0, + height: 100.0, + }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(255, 255, 255, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: None, + }); + + let geo_mask = Node::Ellipse(EllipseNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: Some(LayerMaskType::Geometry), + transform: AffineTransform::from_box_center(50.0, 50.0, 80.0, 80.0, 0.0), + size: Size { + width: 80.0, + height: 80.0, + }, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + inner_radius: None, + start_angle: 0.0, + angle: None, + corner_radius: None, + effects: LayerEffects::default(), + layout_child: None, + }); + + let scene = build_scene( + "Masks", + None, + vec![(1, image_mask), (2, geo_mask)], + HashMap::new(), + vec![1, 2], + ); + assert_roundtrip_scene(&scene, "s1", "mask_types"); +} + +// ─── All blend modes ──────────────────────────────────────────────────────── + +#[test] +fn gen_all_blend_modes() { + let blend_modes = [ + BlendMode::Normal, + BlendMode::Multiply, + BlendMode::Screen, + BlendMode::Overlay, + BlendMode::Darken, + BlendMode::Lighten, + BlendMode::ColorDodge, + BlendMode::ColorBurn, + BlendMode::HardLight, + BlendMode::SoftLight, + BlendMode::Difference, + BlendMode::Exclusion, + BlendMode::Hue, + BlendMode::Saturation, + BlendMode::Color, + BlendMode::Luminosity, + ]; + + let mut nodes = Vec::new(); + for (i, &bm) in blend_modes.iter().enumerate() { + let id = (i + 1) as u64; + nodes.push(( + id, + Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::Blend(bm), + mask: None, + transform: AffineTransform::from_box_center( + (i as f32) * 20.0, + 0.0, + 10.0, + 10.0, + 0.0, + ), + size: Size { + width: 10.0, + height: 10.0, + }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(128, 128, 128, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: None, + }), + )); + } + + // Also test PassThrough + nodes.push(( + 100, + Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 50.0, 10.0, 10.0, 0.0), + size: Size { + width: 10.0, + height: 10.0, + }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: None, + }), + )); + + let roots: Vec = nodes.iter().map(|(id, _)| *id).collect(); + let scene = build_scene("BlendModes", None, nodes, HashMap::new(), roots); + assert_roundtrip_scene(&scene, "s1", "all_blend_modes"); +} + +// ─── All paint types on a single node ─────────────────────────────────────── + +#[test] +fn gen_all_paint_types() { + let rect = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 0.0, 100.0, 100.0, 0.0), + size: Size { + width: 100.0, + height: 100.0, + }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![ + solid(255, 0, 0, 255), + linear_gradient(), + radial_gradient(), + sweep_gradient(), + image_paint(), + ]), + strokes: Paints::new(vec![solid(0, 0, 0, 255), linear_gradient()]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::Uniform(1.0), + effects: LayerEffects::default(), + layout_child: None, + }); + + let scene = build_scene( + "AllPaints", + None, + vec![(1, rect)], + HashMap::new(), + vec![1], + ); + assert_roundtrip_scene(&scene, "s1", "all_paint_types"); +} + +// ─── All effects on a single node ─────────────────────────────────────────── + +#[test] +fn gen_all_effects() { + let rect = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 0.0, 100.0, 100.0, 0.0), + size: Size { + width: 100.0, + height: 100.0, + }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(200, 200, 200, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: full_effects(), + layout_child: None, + }); + + let scene = build_scene( + "AllEffects", + None, + vec![(1, rect)], + HashMap::new(), + vec![1], + ); + assert_roundtrip_scene(&scene, "s1", "all_effects"); +} + +// ─── Inactive / edge cases ────────────────────────────────────────────────── + +#[test] +fn gen_inactive_node() { + let rect = Node::Rectangle(RectangleNodeRec { + active: false, + opacity: 0.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 0.0, 1.0, 1.0, 0.0), + size: Size { + width: 1.0, + height: 1.0, + }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: None, + }); + + let scene = build_scene( + "Inactive", + None, + vec![(1, rect)], + HashMap::new(), + vec![1], + ); + assert_roundtrip_scene(&scene, "s1", "inactive_node"); +} + +// ─── Deep nesting ─────────────────────────────────────────────────────────── + +#[test] +fn gen_deep_nesting() { + // Container → Group → Container → Rectangle + let c1 = Node::Container(ContainerNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + rotation: 0.0, + position: LayoutPositioningBasis::Cartesian(CGPoint::new(0.0, 0.0)), + layout_container: LayoutContainerStyle::default(), + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(500.0), + layout_target_height: Some(500.0), + layout_min_width: None, + layout_max_width: None, + layout_min_height: None, + layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(255, 255, 255, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + clip: true, + }); + + let g = Node::Group(GroupNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: Some(AffineTransform::from_box_center(0.0, 0.0, 0.0, 0.0, 0.0)), + }); + + let c2 = Node::Container(ContainerNodeRec { + active: true, + opacity: 0.9, + blend_mode: LayerBlendMode::Blend(BlendMode::Normal), + mask: None, + // Use 0.0 to avoid cos/sin → atan2 float precision loss on roundtrip. + // Non-cardinal angles lose precision (e.g. 15.0 → 15.000001), and + // 180.0 aliases to -180.0 via atan2. + rotation: 0.0, + position: LayoutPositioningBasis::Inset(EdgeInsets { + top: 50.0, + right: 50.0, + bottom: 50.0, + left: 50.0, + }), + layout_container: LayoutContainerStyle { + layout_mode: LayoutMode::Flex, + layout_direction: Axis::Vertical, + layout_wrap: None, + layout_main_axis_alignment: Some(MainAxisAlignment::Start), + layout_cross_axis_alignment: None, + layout_padding: None, + layout_gap: None, + }, + layout_dimensions: LayoutDimensionStyle { + layout_target_width: Some(200.0), + layout_target_height: Some(200.0), + layout_min_width: None, + layout_max_width: None, + layout_min_height: None, + layout_max_height: None, + layout_target_aspect_ratio: None, + }, + layout_child: None, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![linear_gradient()]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + clip: false, + }); + + let leaf = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(10.0, 10.0, 50.0, 50.0, 0.0), + size: Size { + width: 50.0, + height: 50.0, + }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![solid(255, 0, 128, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: None, + }); + + let mut links = HashMap::new(); + links.insert(1u64, vec![2u64]); + links.insert(2u64, vec![3u64]); + links.insert(3u64, vec![4u64]); + + let scene = build_scene( + "DeepNesting", + Some(CGColor { + r: 30, + g: 30, + b: 30, + a: 255, + }), + vec![(1, c1), (2, g), (3, c2), (4, leaf)], + links, + vec![1], + ); + assert_roundtrip_scene(&scene, "s1", "deep_nesting"); +} + +// ─── All stroke marker presets ────────────────────────────────────────────── + +#[test] +fn gen_all_stroke_markers() { + let markers = [ + (StrokeMarkerPreset::None, StrokeMarkerPreset::RightTriangleOpen), + (StrokeMarkerPreset::EquilateralTriangle, StrokeMarkerPreset::Circle), + (StrokeMarkerPreset::Square, StrokeMarkerPreset::Diamond), + (StrokeMarkerPreset::VerticalBar, StrokeMarkerPreset::None), + ]; + + let mut nodes = Vec::new(); + for (i, (start, end)) in markers.iter().enumerate() { + let id = (i + 1) as u64; + nodes.push(( + id, + Node::Line(LineNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + transform: AffineTransform::new(0.0, (i as f32) * 30.0, 0.0), + size: Size { + width: 100.0, + height: 0.0, + }, + strokes: Paints::new(vec![solid(0, 0, 0, 255)]), + stroke_width: 2.0, + stroke_cap: StrokeCap::Butt, + stroke_miter_limit: StrokeMiterLimit(4.0), + stroke_dash_array: None, + _data_stroke_align: StrokeAlign::Center, + marker_start_shape: *start, + marker_end_shape: *end, + layout_child: None, + }), + )); + } + + let roots: Vec = nodes.iter().map(|(id, _)| *id).collect(); + let scene = build_scene("Markers", None, nodes, HashMap::new(), roots); + assert_roundtrip_scene(&scene, "s1", "all_stroke_markers"); +} + +// ─── Boolean operation variants ───────────────────────────────────────────── + +#[test] +fn gen_all_boolean_ops() { + let ops = [ + BooleanPathOperation::Union, + BooleanPathOperation::Intersection, + BooleanPathOperation::Difference, + BooleanPathOperation::Xor, + ]; + + let mut nodes = Vec::new(); + for (i, &op) in ops.iter().enumerate() { + let id = (i + 1) as u64; + nodes.push(( + id, + Node::BooleanOperation(BooleanPathOperationNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + // The encoder ignores transform; the decoder always returns + // Some(from_translation_rotation_raw(0,0,1,0)) which has -0.0 + // in the -sin slot. Match the exact decoded representation. + transform: Some(AffineTransform::from_translation_rotation_raw( + 0.0, 0.0, 1.0, 0.0, + )), + op, + corner_radius: None, + fills: Paints::new(vec![solid(100, 100, 100, 255)]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: SingularStrokeWidth(None), + }), + )); + } + + let roots: Vec = nodes.iter().map(|(id, _)| *id).collect(); + let scene = build_scene("BoolOps", None, nodes, HashMap::new(), roots); + assert_roundtrip_scene(&scene, "s1", "all_boolean_ops"); +} + +// ─── Text alignment variants ──────────────────────────────────────────────── + +#[test] +fn gen_text_align_variants() { + let aligns = [ + (TextAlign::Left, TextAlignVertical::Top), + (TextAlign::Center, TextAlignVertical::Center), + (TextAlign::Right, TextAlignVertical::Bottom), + (TextAlign::Justify, TextAlignVertical::Top), + ]; + + let mut nodes = Vec::new(); + for (i, &(h, v)) in aligns.iter().enumerate() { + let id = (i + 1) as u64; + nodes.push(( + id, + Node::TextSpan(TextSpanNodeRec { + active: true, + transform: AffineTransform::new(0.0, (i as f32) * 50.0, 0.0), + width: Some(200.0), + height: None, + layout_child: None, + text: format!("Align {i}"), + text_style: TextStyleRec::from_font("Inter", 16.0), + text_align: h, + text_align_vertical: v, + max_lines: None, + ellipsis: None, + fills: Paints::new(vec![solid(0, 0, 0, 255)]), + strokes: Paints::new(vec![]), + stroke_width: 0.0, + stroke_align: StrokeAlign::Center, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + effects: LayerEffects::default(), + }), + )); + } + + let roots: Vec = nodes.iter().map(|(id, _)| *id).collect(); + let scene = build_scene("TextAligns", None, nodes, HashMap::new(), roots); + assert_roundtrip_scene(&scene, "s1", "text_align_variants"); +} + +// ─── Image paint with ResourceRef::RID ────────────────────────────────────── + +#[test] +fn gen_image_paint_rid() { + let rect = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 0.0, 200.0, 150.0, 0.0), + size: Size { + width: 200.0, + height: 150.0, + }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![Paint::Image(ImagePaint { + active: true, + image: ResourceRef::RID("res://images/photo.jpg".to_owned()), + quarter_turns: 0, + alignement: Alignment::CENTER, + fit: ImagePaintFit::Fit(math2::box_fit::BoxFit::Contain), + opacity: 1.0, + blend_mode: BlendMode::Normal, + filters: ImageFilters::default(), + })]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: None, + }); + + let scene = build_scene( + "ImagePaintRID", + None, + vec![(1, rect)], + HashMap::new(), + vec![1], + ); + assert_roundtrip_scene(&scene, "s1", "image_paint_rid"); +} + +// ─── Image paint with transform fit ───────────────────────────────────────── + +#[test] +fn gen_image_paint_transform_fit() { + let rect = Node::Rectangle(RectangleNodeRec { + active: true, + opacity: 1.0, + blend_mode: LayerBlendMode::PassThrough, + mask: None, + transform: AffineTransform::from_box_center(0.0, 0.0, 100.0, 100.0, 0.0), + size: Size { + width: 100.0, + height: 100.0, + }, + corner_radius: RectangularCornerRadius::default(), + corner_smoothing: CornerSmoothing(0.0), + fills: Paints::new(vec![Paint::Image(ImagePaint { + active: true, + image: ResourceRef::HASH("def456".to_owned()), + quarter_turns: 2, + alignement: Alignment::BOTTOM_RIGHT, + fit: ImagePaintFit::Transform(AffineTransform::from_acebdf( + 0.5, 0.0, 10.0, 0.0, 0.5, 20.0, + )), + opacity: 0.8, + blend_mode: BlendMode::Screen, + filters: ImageFilters::default(), + })]), + strokes: Paints::new(vec![]), + stroke_style: StrokeStyle::default(), + stroke_width: StrokeWidth::None, + effects: LayerEffects::default(), + layout_child: None, + }); + + let scene = build_scene( + "ImageTransformFit", + None, + vec![(1, rect)], + HashMap::new(), + vec![1], + ); + assert_roundtrip_scene(&scene, "s1", "image_paint_transform_fit"); +} diff --git a/crates/grida-dev/Cargo.toml b/crates/grida-dev/Cargo.toml index 9538fec493..8faf234970 100644 --- a/crates/grida-dev/Cargo.toml +++ b/crates/grida-dev/Cargo.toml @@ -47,3 +47,4 @@ indicatif = "0.17" toml = "0.9.8" glob = "0.3.3" arboard = "3" +zip = { version = "8.2.0", default-features = false, features = ["deflate-flate2"] } diff --git a/crates/grida-dev/src/grida_file.rs b/crates/grida-dev/src/grida_file.rs new file mode 100644 index 0000000000..a4ca244bd2 --- /dev/null +++ b/crates/grida-dev/src/grida_file.rs @@ -0,0 +1,99 @@ +//! `.grida` file format detection and decoding. +//! +//! A `.grida` file is one of two variants: +//! - **Raw FlatBuffers** – identified by the `"GRID"` file identifier at bytes 4–7. +//! - **ZIP archive** – identified by PK magic bytes; contains `manifest.json` and +//! `document.grida` (a raw FlatBuffers binary) plus optional `images/` and `bitmaps/`. + +use anyhow::{anyhow, Context, Result}; +use cg::io::{id_converter::IdConverter, io_grida, io_grida_fbs}; +use cg::node::schema::Scene; + +/// Detected variant of a `.grida` file. +enum Format { + RawFbs, + Zip, + Json, + Unknown, +} + +fn detect(bytes: &[u8]) -> Format { + // ZIP magic: PK\x03\x04 or PK\x05\x06 + if bytes.len() >= 4 + && bytes[0] == 0x50 + && bytes[1] == 0x4b + && ((bytes[2] == 0x03 && bytes[3] == 0x04) || (bytes[2] == 0x05 && bytes[3] == 0x06)) + { + return Format::Zip; + } + // Raw FlatBuffers: file identifier "GRID" at bytes 4–7 + if bytes.len() >= 8 && &bytes[4..8] == b"GRID" { + return Format::RawFbs; + } + // JSON: starts with '{' or '[' (after optional UTF-8 BOM / whitespace) + let trimmed = bytes + .iter() + .position(|&b| !b.is_ascii_whitespace() && b != 0xEF && b != 0xBB && b != 0xBF) + .map(|i| bytes[i]) + .unwrap_or(0); + if trimmed == b'{' || trimmed == b'[' { + return Format::Json; + } + Format::Unknown +} + +/// Extracts the raw FlatBuffers bytes from a `.grida` ZIP archive. +fn extract_fbs_from_zip(bytes: &[u8]) -> Result> { + use std::io::{Cursor, Read}; + let cursor = Cursor::new(bytes); + let mut archive = zip::ZipArchive::new(cursor).context("failed to open .grida ZIP")?; + + anyhow::ensure!( + archive.by_name("manifest.json").is_ok(), + ".grida ZIP is missing manifest.json" + ); + + let mut doc_file = archive + .by_name("document.grida") + .context(".grida ZIP is missing document.grida")?; + let mut fbs_bytes = Vec::with_capacity(doc_file.size() as usize); + doc_file + .read_to_end(&mut fbs_bytes) + .context("failed to read document.grida from ZIP")?; + Ok(fbs_bytes) +} + +/// Decodes a `.grida` file (raw FlatBuffers or ZIP) into a [`Scene`]. +/// +/// If the file contains multiple scenes, only the first is returned. +/// Use [`decode_all`] to get all scenes. +pub fn decode(bytes: &[u8]) -> Result { + decode_all(bytes)? + .into_iter() + .next() + .ok_or_else(|| anyhow!("no scenes found in .grida file")) +} + +/// Decodes a `.grida` file into all [`Scene`]s it contains. +pub fn decode_all(bytes: &[u8]) -> Result> { + match detect(bytes) { + Format::RawFbs => io_grida_fbs::decode_all(bytes).map_err(|err| anyhow!("{err}")), + Format::Zip => { + let fbs_bytes = extract_fbs_from_zip(bytes)?; + io_grida_fbs::decode_all(&fbs_bytes).map_err(|err| anyhow!("{err}")) + } + Format::Json => { + let json_str = std::str::from_utf8(bytes).context("invalid UTF-8 in JSON scene")?; + let file = io_grida::parse(json_str) + .map_err(|err| anyhow!("failed to parse JSON scene: {err}"))?; + let mut converter = IdConverter::new(); + let scene = converter + .convert_json_canvas_file(file) + .map_err(|err| anyhow!("failed to convert JSON scene: {err}"))?; + Ok(vec![scene]) + } + Format::Unknown => Err(anyhow!( + "unrecognized file format: expected a .grida FlatBuffers binary, ZIP archive, or JSON" + )), + } +} diff --git a/crates/grida-dev/src/main.rs b/crates/grida-dev/src/main.rs index b5a606ecda..e57922efd3 100644 --- a/crates/grida-dev/src/main.rs +++ b/crates/grida-dev/src/main.rs @@ -2,7 +2,7 @@ use anyhow::{anyhow, Context, Result}; use cg::cg::prelude::*; use cg::cg::types::ResourceRef; use cg::helpers::webfont_helper::{find_font_files, load_webfonts_metadata}; -use cg::io::{io_figma::FigmaConverter, io_grida}; +use cg::io::io_figma::FigmaConverter; use cg::node::factory::NodeFactory; use cg::node::scene_graph::{Parent, SceneGraph}; use cg::node::schema::{Node, Scene, Size}; @@ -17,8 +17,9 @@ use figma_api::apis::{ use futures::channel::mpsc; use futures::future::join_all; use grida_dev::platform::native_demo::{ - run_demo_window, run_demo_window_with, run_demo_window_with_drop, + run_demo_window, run_demo_window_multi, run_demo_window_with, run_demo_window_with_drop, }; +mod grida_file; mod reftest; use image::image_dimensions; use math2::transform::AffineTransform; @@ -124,8 +125,16 @@ async fn main() -> Result<()> { } async fn run_scene(source: &str) -> Result<()> { - let scene = load_scene_from_source(source).await?; - run_demo_window(scene).await; + let scenes = load_scenes_from_source(source).await?; + if scenes.is_empty() { + return Err(anyhow!("no scenes decoded from source: {source}")); + } + if scenes.len() > 1 { + println!("Loaded {} scenes (PageUp/PageDown to switch)", scenes.len()); + run_demo_window_multi(scenes).await; + } else { + run_demo_window(scenes.into_iter().next().unwrap()).await; + } Ok(()) } @@ -277,26 +286,29 @@ async fn run_master() -> Result<()> { } async fn load_scene_from_source(source: &str) -> Result { - let data = if is_url(source) { + let bytes = read_source_bytes(source).await?; + grida_file::decode(&bytes) +} + +async fn load_scenes_from_source(source: &str) -> Result> { + let bytes = read_source_bytes(source).await?; + grida_file::decode_all(&bytes) +} + +async fn read_source_bytes(source: &str) -> Result> { + if is_url(source) { reqwest::get(source) .await .with_context(|| format!("failed to download scene from {source}"))? - .text() + .bytes() .await - .context("failed to read downloaded scene body")? + .context("failed to read downloaded scene body") + .map(|b| b.to_vec()) } else { - async_fs::read_to_string(source) + async_fs::read(source) .await - .with_context(|| format!("failed to read scene file at {source}"))? - }; - - let file = - io_grida::parse(&data).context("failed to parse scene JSON. expected a `.grida` export")?; - - let mut converter = cg::io::id_converter::IdConverter::new(); - converter - .convert_json_canvas_file(file) - .map_err(|err| anyhow!(err)) + .with_context(|| format!("failed to read scene file at {source}")) + } } async fn load_figma_scene(args: &FigmaArgs) -> Result<(Scene, FigmaConverter)> { diff --git a/crates/grida-dev/src/platform/native_application.rs b/crates/grida-dev/src/platform/native_application.rs index d6c92abba4..335b4fc68b 100644 --- a/crates/grida-dev/src/platform/native_application.rs +++ b/crates/grida-dev/src/platform/native_application.rs @@ -1,8 +1,8 @@ use super::winit::{winit_window, WinitResult}; -use cg::node::schema::Size; -use cg::resources::{FontMessage, ImageMessage}; +use cg::node::schema::{Scene, Size}; +use cg::resources::{load_scene_images, FontMessage, ImageMessage}; use cg::runtime::camera::Camera2D; -use cg::window::application::{ApplicationApi, HostEvent, UnknownTargetApplication}; +use cg::window::application::{ApplicationApi, HostEvent, HostEventCallback, UnknownTargetApplication}; use cg::window::command::ApplicationCommand; use cg::window::state::AnySurfaceState; use futures::channel::mpsc; @@ -72,7 +72,11 @@ fn handle_key_pressed( _ => ApplicationCommand::None, } } else { - ApplicationCommand::None + match key { + Key::Named(winit::keyboard::NamedKey::PageDown) => ApplicationCommand::NextScene, + Key::Named(winit::keyboard::NamedKey::PageUp) => ApplicationCommand::PrevScene, + _ => ApplicationCommand::None, + } } } @@ -84,6 +88,14 @@ pub struct NativeApplication { pub(crate) modifiers: winit::keyboard::ModifiersState, file_drop_tx: Option>, fit_scene_on_load: bool, + /// All scenes loaded from the file (for PageUp/PageDown switching). + pub(crate) scenes: Vec, + /// Index of the currently displayed scene in `scenes`. + pub(crate) scene_index: usize, + /// Image channel sender for loading scene images on scene switch. + pub(crate) image_tx: Option>, + /// Host event callback for notifying the event loop of image load completion. + pub(crate) event_cb: Option, } impl NativeApplication { @@ -154,6 +166,10 @@ impl NativeApplication { modifiers: winit::keyboard::ModifiersState::default(), file_drop_tx, fit_scene_on_load, + scenes: Vec::new(), + scene_index: 0, + image_tx: None, + event_cb: None, }; std::thread::spawn(move || loop { @@ -217,8 +233,52 @@ impl NativeApplicationHandler for NativeApplication { } } - match handle_window_event(&event, &self.modifiers) { - cmd => { + let cmd = handle_window_event(&event, &self.modifiers); + match &cmd { + ApplicationCommand::NextScene | ApplicationCommand::PrevScene => { + if !self.scenes.is_empty() { + let new_index = match &cmd { + ApplicationCommand::NextScene => { + (self.scene_index + 1) % self.scenes.len() + } + ApplicationCommand::PrevScene => { + (self.scene_index + self.scenes.len() - 1) % self.scenes.len() + } + _ => unreachable!(), + }; + if new_index != self.scene_index { + self.scene_index = new_index; + let scene = self.scenes[new_index].clone(); + let title = format!( + "[{}/{}] {}", + new_index + 1, + self.scenes.len(), + scene.name, + ); + eprintln!("{title}"); + + // Load scene images in background for the new scene. + if let (Some(image_tx), Some(event_cb)) = + (self.image_tx.clone(), self.event_cb.clone()) + { + let scene_for_images = scene.clone(); + std::thread::spawn(move || { + futures::executor::block_on(async move { + load_scene_images(&scene_for_images, image_tx, event_cb).await; + }); + }); + } + + let renderer = self.app.renderer_mut(); + renderer.load_scene(scene); + fit_camera_to_scene(renderer); + renderer.queue_unstable(); + self.window.request_redraw(); + self.window.set_title(&title); + } + } + } + _ => { let is_copy_png = matches!(cmd, ApplicationCommand::TryCopyAsPNG); let ok = self.app.command(cmd); diff --git a/crates/grida-dev/src/platform/native_demo.rs b/crates/grida-dev/src/platform/native_demo.rs index e3676c341b..4df1781a40 100644 --- a/crates/grida-dev/src/platform/native_demo.rs +++ b/crates/grida-dev/src/platform/native_demo.rs @@ -13,6 +13,16 @@ pub async fn run_demo_window(scene: Scene) { run_demo_window_with(scene, |_, _, _, _| {}).await; } +/// Run a demo window with multiple scenes (PageUp/PageDown to switch). +#[allow(dead_code)] +pub async fn run_demo_window_multi(scenes: Vec) { + let first = scenes + .first() + .cloned() + .expect("run_demo_window_multi requires at least one scene"); + run_demo_window_core_multi(first, scenes, |_, _, _, _| {}, None).await; +} + pub async fn run_demo_window_with(scene: Scene, init: F) where F: FnOnce( @@ -22,7 +32,7 @@ where winit::event_loop::EventLoopProxy, ), { - run_demo_window_core(scene, init, None).await; + run_demo_window_core_multi(scene.clone(), vec![scene], init, None).await; } pub async fn run_demo_window_with_drop(scene: Scene, init: F, drop_tx: UnboundedSender) @@ -34,11 +44,12 @@ where winit::event_loop::EventLoopProxy, ), { - run_demo_window_core(scene, init, Some(drop_tx)).await; + run_demo_window_core_multi(scene.clone(), vec![scene], init, Some(drop_tx)).await; } -async fn run_demo_window_core( +async fn run_demo_window_core_multi( scene: Scene, + all_scenes: Vec, init: F, file_drop_tx: Option>, ) where @@ -82,6 +93,10 @@ async fn run_demo_window_core( let _ = proxy_clone.send_event(event); }) }; + // Store image_tx and event_cb for scene-switch image loading. + app.image_tx = Some(tx.clone()); + app.event_cb = Some(event_cb.clone()); + std::thread::spawn(move || { let event_cb = event_cb.clone(); futures::executor::block_on(async move { @@ -99,6 +114,12 @@ async fn run_demo_window_core( let renderer = app.app.renderer_mut(); renderer.load_scene(scene.clone()); } + app.scenes = all_scenes; + app.scene_index = 0; + if app.scenes.len() > 1 { + let title = format!("[1/{}] {}", app.scenes.len(), scene.name); + app.window.set_title(&title); + } app.app.devtools_rendering_set_show_fps_meter(true); app.app.devtools_rendering_set_show_stats(true); app.app.devtools_rendering_set_show_hit_testing(true); diff --git a/crates/math2/src/transform.rs b/crates/math2/src/transform.rs index b278c2e427..fb64e5cc11 100644 --- a/crates/math2/src/transform.rs +++ b/crates/math2/src/transform.rs @@ -95,6 +95,42 @@ impl AffineTransform { Self::from_box(x, y, w, h, deg, 0.5, 0.5) } + /// Like [`from_box`] but takes pre-computed `cos` and `sin` values instead + /// of a degree angle. This avoids the lossy `degrees → radians → sin_cos` + /// round-trip when the original cos/sin are available (e.g. from a stored + /// rotation matrix). + pub fn from_box_raw( + x: f32, + y: f32, + w: f32, + h: f32, + cos: f32, + sin: f32, + origin_x: f32, + origin_y: f32, + ) -> Self { + let ox = w * origin_x; + let oy = h * origin_y; + let tx = x + ox * (1.0 - cos) + sin * oy; + let ty = y + oy * (1.0 - cos) - sin * ox; + Self { + matrix: [[cos, -sin, tx], [sin, cos, ty]], + } + } + + /// Like [`from_box_center`] but takes pre-computed `cos` and `sin`. + pub fn from_box_center_raw(x: f32, y: f32, w: f32, h: f32, cos: f32, sin: f32) -> Self { + Self::from_box_raw(x, y, w, h, cos, sin, 0.5, 0.5) + } + + /// Creates a transform with translation and rotation from raw cos/sin. + /// Equivalent to `new(tx, ty, radians)` but without computing sin_cos. + pub fn from_translation_rotation_raw(tx: f32, ty: f32, cos: f32, sin: f32) -> Self { + Self { + matrix: [[cos, -sin, tx], [sin, cos, ty]], + } + } + pub fn x(&self) -> f32 { self.matrix[0][2] } diff --git a/editor/grida-canvas-hosted/playground/playground.tsx b/editor/grida-canvas-hosted/playground/playground.tsx index b71c792ecd..c96952fb67 100644 --- a/editor/grida-canvas-hosted/playground/playground.tsx +++ b/editor/grida-canvas-hosted/playground/playground.tsx @@ -497,11 +497,34 @@ export default function CanvasPlayground({ } } } catch (error) { - // File not found or other error - continue to fallback if (error instanceof Error && error.message.includes("not found")) { // File doesn't exist yet - this is fine, continue to fallback + } else if ( + error instanceof Error && + /decode|schema|corrupt|unreadable|invalid|flatbuffers/i.test( + error.message + ) + ) { + // Decode failure (likely a schema change) or other corruption. + // Quarantine the stale files so the user's data is preserved + // for possible future migration, then fall through to the + // default document. + console.warn( + "OPFS document unreadable (possible schema change), quarantining:", + error + ); + try { + await opfs?.quarantine(); + } catch (quarantineError) { + console.error( + "Failed to quarantine stale OPFS data:", + quarantineError + ); + } } else { - console.error("Failed to load from OPFS:", error); + // Transient or runtime error (e.g. from reset() / loadImages()). + // Do not quarantine - rethrow so the caller can handle it. + console.error("OPFS load error (not quarantining):", error); } } diff --git a/editor/grida-canvas/editor.ts b/editor/grida-canvas/editor.ts index 9f2274b071..820e9a3bcd 100644 --- a/editor/grida-canvas/editor.ts +++ b/editor/grida-canvas/editor.ts @@ -2891,9 +2891,11 @@ export class Editor * - OPFS persistence (playground `Cmd/Ctrl+S`) * * What it does: - * - Collects **used** image paint `src` references (res://images/). + * - Collects **used** image paint `src` references (res://images/), excluding system:// built-ins. * - Parses ref from each src, resolves bytes from WASM, produces `images/.` entries. * - Document keeps `src` unchanged (no rewrite). + * - `system://` images (built-in runtime resources) are excluded — they are + * auto-registered by the WASM runtime on load and must not be embedded. * * For DOM backend (hosted HTML flow), we keep external `src` values as-is and do not embed. * @@ -2912,7 +2914,9 @@ export class Editor .document as grida.program.document.Document; const images: Record = {}; - const usedSrcs = new dq.DocumentStateQuery(snapshot).image_srcs(); + const usedSrcs = new dq.DocumentStateQuery( + snapshot + ).persistable_image_srcs(); if (this.backend !== "canvas" || !this._m_wasm_canvas_scene) { throw new Error( "`archivedir()` requires the canvas/WASM backend to be mounted." @@ -3149,7 +3153,7 @@ export class Editor : document; const p = JSON.stringify({ - version: "0.90.0-beta+20260108", + version: grida.program.document.SCHEMA_VERSION, document: payloadDocument, }); surface.loadScene(p); diff --git a/editor/grida-canvas/query/index.ts b/editor/grida-canvas/query/index.ts index d3e5b55acc..4e0b65eaad 100644 --- a/editor/grida-canvas/query/index.ts +++ b/editor/grida-canvas/query/index.ts @@ -654,8 +654,7 @@ export namespace dq { /** * Returns unique image `src` references used by image paints. * - * - Persisted: typically `hex16` (content hash id) - * - Runtime: typically `blob:` or `mem://...` + * Includes all protocol schemes (`res://`, `system://`, etc.). */ image_srcs(): string[] { return Array.from( @@ -666,6 +665,19 @@ export namespace dq { ) ); } + + /** + * Returns unique image `src` references that must be persisted in archives. + * + * Excludes `system://` images (built-in resources baked into the runtime) + * since they are auto-registered on load and must not be embedded in + * `.grida` archives. + */ + persistable_image_srcs(): string[] { + return this.image_srcs().filter( + (src) => !src.startsWith("system://") + ); + } } // note: paint extraction uses `editor.resolvePaints` for correctness across all node variants diff --git a/editor/public/examples/canvas/blank.grida1 b/editor/public/examples/canvas/blank.grida1 index b544e846de..b3b55a6fd0 100644 --- a/editor/public/examples/canvas/blank.grida1 +++ b/editor/public/examples/canvas/blank.grida1 @@ -1,5 +1,5 @@ { - "version": "0.90.0-beta+20260108", + "version": "0.91.0-beta+20260311", "document": { "nodes": { "blank": { diff --git a/editor/public/examples/canvas/component-01.grida1 b/editor/public/examples/canvas/component-01.grida1 index 20c863f2bd..a317e9d619 100644 --- a/editor/public/examples/canvas/component-01.grida1 +++ b/editor/public/examples/canvas/component-01.grida1 @@ -1,5 +1,5 @@ { - "version": "0.90.0-beta+20260108", + "version": "0.91.0-beta+20260311", "document": { "nodes": { "component": { diff --git a/editor/public/examples/canvas/globals-01.grida1 b/editor/public/examples/canvas/globals-01.grida1 index bb610c2eb6..793211f93d 100644 --- a/editor/public/examples/canvas/globals-01.grida1 +++ b/editor/public/examples/canvas/globals-01.grida1 @@ -1,5 +1,5 @@ { - "version": "0.90.0-beta+20260108", + "version": "0.91.0-beta+20260311", "document": { "nodes": { "root": { diff --git a/editor/public/examples/canvas/helloworld.grida1 b/editor/public/examples/canvas/helloworld.grida1 index 9776368082..0b51a553d6 100644 --- a/editor/public/examples/canvas/helloworld.grida1 +++ b/editor/public/examples/canvas/helloworld.grida1 @@ -1,5 +1,5 @@ { - "version": "0.90.0-beta+20260108", + "version": "0.91.0-beta+20260311", "document": { "nodes": { "454:341": { diff --git a/editor/public/examples/canvas/hero-main-demo.grida1 b/editor/public/examples/canvas/hero-main-demo.grida1 index d5e7aece5c..3d8ab01642 100644 --- a/editor/public/examples/canvas/hero-main-demo.grida1 +++ b/editor/public/examples/canvas/hero-main-demo.grida1 @@ -9889,5 +9889,5 @@ "main" ] }, - "version": "0.90.0-beta+20260108" + "version": "0.91.0-beta+20260311" } \ No newline at end of file diff --git a/editor/public/examples/canvas/layout-01.grida1 b/editor/public/examples/canvas/layout-01.grida1 index f95d0f3509..df3bd6dfac 100644 --- a/editor/public/examples/canvas/layout-01.grida1 +++ b/editor/public/examples/canvas/layout-01.grida1 @@ -1,5 +1,5 @@ { - "version": "0.90.0-beta+20260108", + "version": "0.91.0-beta+20260311", "document": { "nodes": { "173:49": { diff --git a/editor/public/examples/canvas/poster-happy-new-year-2026.grida1 b/editor/public/examples/canvas/poster-happy-new-year-2026.grida1 index 8a79f73d78..f9cda71acb 100644 --- a/editor/public/examples/canvas/poster-happy-new-year-2026.grida1 +++ b/editor/public/examples/canvas/poster-happy-new-year-2026.grida1 @@ -1,5 +1,5 @@ { - "version": "0.90.0-beta+20260108", + "version": "0.91.0-beta+20260311", "document": { "links": { "main": [ diff --git a/editor/scaffolds/editor/editor.tsx b/editor/scaffolds/editor/editor.tsx index 2d91dd8543..b1912f88a3 100644 --- a/editor/scaffolds/editor/editor.tsx +++ b/editor/scaffolds/editor/editor.tsx @@ -159,7 +159,7 @@ async function saveHostedGridaCanvasDocument( .update({ data: document ? ({ - __schema_version: "0.90.0-beta+20260108", + __schema_version: grida.program.document.SCHEMA_VERSION, ...document, } satisfies CanvasDocumentSnapshotSchema as {}) : null, diff --git a/editor/scaffolds/editor/init.ts b/editor/scaffolds/editor/init.ts index 35db4e89f7..0ba2534fad 100644 --- a/editor/scaffolds/editor/init.ts +++ b/editor/scaffolds/editor/init.ts @@ -31,6 +31,7 @@ import { Data } from "@/lib/data"; import { FormStartPage } from "@/theme/templates/formstart"; import type { MenuGroup } from "./menu"; import { editor } from "@/grida-canvas"; +import grida from "@grida/schema"; import { DataFormat } from "../data-format"; export function initialEditorState(init: EditorInit): EditorState { @@ -316,7 +317,7 @@ function __init_canvas( // check the version if ( (data as SchemaMayVaryDocumentServerObject).__schema_version !== - "0.90.0-beta+20260108" + grida.program.document.SCHEMA_VERSION ) { return { __schema_version: (data as SchemaMayVaryDocumentServerObject) @@ -349,7 +350,7 @@ function __init_form_start_page_state( // check the version if ( - (data as FormStartPageSchema).__schema_version !== "0.90.0-beta+20260108" + (data as FormStartPageSchema).__schema_version !== grida.program.document.SCHEMA_VERSION ) { return { __schema_version: (data as FormStartPageSchema).__schema_version, diff --git a/editor/scaffolds/editor/sync/agent-startpage.sync.tsx b/editor/scaffolds/editor/sync/agent-startpage.sync.tsx index f91ca5359a..a79ed67e2a 100644 --- a/editor/scaffolds/editor/sync/agent-startpage.sync.tsx +++ b/editor/scaffolds/editor/sync/agent-startpage.sync.tsx @@ -6,6 +6,7 @@ import { useDebounce, usePrevious } from "@uidotdev/usehooks"; import type { FormStartPageSchema } from "@/grida-forms-hosted/types"; import { useEditorState } from "@/scaffolds/editor/use-editor"; import equal from "deep-equal"; +import grida from "@grida/schema"; export function useSyncFormAgentStartPage() { const [state, dispatch] = useEditorState(); @@ -30,7 +31,7 @@ export function useSyncFormAgentStartPage() { .update({ start_page: debounced ? ({ - __schema_version: "0.90.0-beta+20260108", + __schema_version: grida.program.document.SCHEMA_VERSION, template_id: startpagestate!.template_id, ...debounced, } satisfies FormStartPageSchema as {}) diff --git a/fixtures/test-grida/L0.grida b/fixtures/test-grida/L0.grida new file mode 100644 index 0000000000..e9dd4edf40 Binary files /dev/null and b/fixtures/test-grida/L0.grida differ diff --git a/fixtures/test-grida/README.md b/fixtures/test-grida/README.md index 6cc392e29a..6e38a59fbc 100644 --- a/fixtures/test-grida/README.md +++ b/fixtures/test-grida/README.md @@ -4,15 +4,18 @@ This directory contains **meaningful** `.grida` files used for **testing**. ### File formats -- **`.grida` files**: Modern format using ZIP/FlatBuffer binary format. These are the current production format. +- **`.grida` files**: Modern format. Two sub-variants: + - **ZIP/FlatBuffer**: Production format. ZIP archive containing a FlatBuffers binary with "GRID" magic header. + - **Raw FlatBuffer**: Bare FlatBuffers binary (no ZIP wrapper). Used for Rust decoder unit tests (`crates/grida-canvas/src/io/io_grida_fbs.rs`). - **`.grida1.zip` files**: Legacy/test-only format containing JSON snapshots in a ZIP archive. Used for internal testing and fixtures. Not part of the public `.grida` file format specification. ### Naming convention - **Prefix**: `d[n]` is a simple counter (`d1`, `d2`, `d3`, ...). - **Schema version specifier**: we encode the schema version **build metadata date** as `yyyymmdd`. - - Example: schema version `0.90.0-beta+20260108` → version specifier `20260108` + - Example: schema version `0.91.0-beta+20260311` → version specifier `20260311` - **Note**: this `yyyymmdd` is **not** the authoring date of the file. +- **`L0.grida`**: Multi-scene raw FlatBuffer fixture generated by the fixture tool (`cargo run --package cg --example tool_gen_fixtures`). Exercises every node type, paint variant, effect, stroke option, mask type, and layout configuration across multiple scenes. In-memory round-trip coverage is in `cargo test --package cg --test fbs_roundtrip`. ### Support expectations (important) @@ -22,10 +25,16 @@ This directory contains **meaningful** `.grida` files used for **testing**. ### Changelog +- **0.91.0-beta+20260311** ⚠️ Breaking FBS schema change: + - Added `NodeSlot` wrapper table in `grida.fbs` to work around a `flatc --rust` limitation (Rust codegen does not support `[Node]` — vectors of unions). + - `CanvasDocument.nodes` field type changed: `[Node]` → `[NodeSlot]`. + - `CanvasDocument` field IDs reindexed as a result: `nodes` moved to `id:1`, `scenes` moved to `id:2`. + - Added Rust FlatBuffers decoder: `crates/grida-canvas/src/io/io_grida_fbs.rs`. + - **0.90.0-beta+20260108**: Migrated from legacy `.grida` (JSON/ZIP) format to new `.grida` (ZIP/FlatBuffer) binary format. Legacy snapshot files are now stored as `.grida1.zip` for test fixtures.
-`grida1` `0.89.0` -> `0.90.0` +grida1 0.89.00.90.0 field renames | `0.89.0` | `0.90.0` | | ---------------------- | ----------------------------- | @@ -51,4 +60,4 @@ This directory contains **meaningful** `.grida` files used for **testing**. --- -> Current Version: `0.90.0-beta+20260108` (last updated: 2026-01-08) +> Current Version: `0.91.0-beta+20260311` (last updated: 2026-03-11) diff --git a/format/CHANGELOG.md b/format/CHANGELOG.md new file mode 100644 index 0000000000..d2ab578bee --- /dev/null +++ b/format/CHANGELOG.md @@ -0,0 +1,20 @@ +# `format/grida.fbs` Changelog + +## `0.91.0-beta+20260311` ⚠️ Breaking + +- **`NodeSlot` wrapper table added**: `flatc --rust` does not support `[Node]` + (vector of unions) directly. The canonical workaround is wrapping each union + entry in a table — identical in spirit to `PaintStackItem` wrapping `Paint`. + See: +- **`CanvasDocument.nodes`** field type changed: `[Node]` → `[NodeSlot]`. +- **`CanvasDocument` field IDs reindexed**: `nodes` → `id:1`, `scenes` → `id:2` + (previously `id:2` / `id:3`). Any document serialized with `0.90.x` is **not + readable** by a `0.91.x` decoder without migration. +- **Rust decoder added**: `crates/grida-canvas/src/io/io_grida_fbs.rs` decodes + raw `.grida` FlatBuffers binaries into the internal `Scene` representation. + +## `0.90.0-beta+20260108` + +- Initial stable FlatBuffers schema. Replaced the legacy JSON/ZIP `.grida` format. +- File identifier `"GRID"`, extension `"grida"`. +- Production format: ZIP archive containing a FlatBuffers binary. diff --git a/format/README.md b/format/README.md index b7ad0b219b..6855b3f6ff 100644 --- a/format/README.md +++ b/format/README.md @@ -54,5 +54,13 @@ python3 bin/activate-flatc -- --ts --ts-no-import-ext -o /tmp/grida-fbs-gen/ts f python3 bin/activate-flatc -- --rust -o /tmp/grida-fbs-gen/rust format/grida.fbs ``` -> Note: In-repo generated code locations + automation scripts are intentionally -> not committed yet; we’ll add them once the schema stabilizes. +> In-repo generated code + automation: +> +> - **TypeScript**: `packages/grida-format/` — **committed**; regenerated on `pnpm build` via `prebuild`. Changes to generated TS files are expected in PRs that modify `grida.fbs`. +> - **Rust**: `crates/grida-canvas/src/io/generated/` — **committed**; regenerated on `pnpm build` via `prebuild`. Changes to generated Rust files are expected in PRs that modify `grida.fbs`. +> +> **Contributor workflow**: after editing `grida.fbs`, run `pnpm build` (or the individual `prebuild` scripts in each package) to regenerate bindings, then commit the updated generated files alongside your schema change. + +## Changelog + +See [CHANGELOG.md](./CHANGELOG.md). diff --git a/format/TODO.md b/format/TODO.md index 4caae921cc..5a1bd2ede4 100644 --- a/format/TODO.md +++ b/format/TODO.md @@ -24,3 +24,11 @@ This document tracks **design flaws and improvement candidates** in the current We should migrate to a table-backed vertex model (e.g. `[VectorNetworkVertex]`) where each vertex can evolve safely over time while preserving explicit intent. **Breaking.** --- + +### 2. `CanonicalEllipticalShapeRingSectorParameters` missing `corner_radius` + +The ellipse arc's `corner_radius` field (`EllipseNodeRec.corner_radius: Option`) controls rounding of arc endpoints. It exists in the Rust runtime model but has no corresponding field in `CanonicalEllipticalShapeRingSectorParameters`. The value is silently lost on FBS roundtrip. + +**Fix**: Add `corner_radius: float = 0.0;` to `CanonicalEllipticalShapeRingSectorParameters` in `grida.fbs`, then update encoder/decoder. **Evolution.** + +--- diff --git a/format/grida.fbs b/format/grida.fbs index d6957f5c98..00ce7f40e5 100644 --- a/format/grida.fbs +++ b/format/grida.fbs @@ -1281,7 +1281,7 @@ table LayerTrait { /// Default is `pass_through`. blend_mode:LayerBlendMode = PassThrough; - /// Rust: `LayerMaskType` (union; default is Image(alpha) since it's the first union member) + /// Rust: `LayerMaskType` (union; NONE means the node is not a mask) mask_type:LayerMaskType; /// layer effects. @@ -1513,15 +1513,29 @@ union Node { // Document root // ----------------------------------------------------------------------------- +/// Wrapper table for a single Node union entry in a flat node vector. +/// +/// FlatBuffers Rust codegen does not support `[Node]` (vector of unions) directly. +/// Using `[NodeSlot]` (vector of tables each containing a union field) is the +/// canonical workaround — identical in spirit to `PaintStackItem` wrapping `Paint`. +/// See: https://github.com/google/flatbuffers/issues/8011 +table NodeSlot { + node:Node; +} + table CanvasDocument { /// Schema version string (keep in sync with TS `grida.program.document.SCHEMA_VERSION`). schema_version:string (id: 0); /// Flat node repository. - nodes:[Node] (id: 2); + /// + /// Stored as `[NodeSlot]` (vector of wrapper tables) rather than `[Node]` + /// (vector of unions) to maintain compatibility with Rust FlatBuffers codegen, + /// which does not support vectors of unions directly. + nodes:[NodeSlot] (id: 1); /// Scene node ids (scene nodes are also stored in `nodes`). - scenes:[NodeIdentifier] (id: 3); + scenes:[NodeIdentifier] (id: 2); } /// Top-level wrapper (allows future multi-document bundles, signatures, etc.) diff --git a/packages/grida-canvas-io/format.ts b/packages/grida-canvas-io/format.ts index da3fb2eaca..47f8fb430f 100644 --- a/packages/grida-canvas-io/format.ts +++ b/packages/grida-canvas-io/format.ts @@ -2,7 +2,7 @@ import grida from "@grida/schema"; import cg from "@grida/cg"; import type cmath from "@grida/cmath"; import * as fbs from "@grida/format"; -import { unionToPaint, unionListToNode, unionToFeBlur } from "@grida/format"; +import { unionToPaint, unionToNode, unionToFeBlur } from "@grida/format"; import type { vn } from "@grida/schema"; import * as flatbuffers from "flatbuffers"; import { generateNKeysBetween } from "@grida/sequence"; @@ -960,15 +960,31 @@ export namespace format { // Nodes don't have blend_mode directly - it's not part of the TS node model const blendMode: fbs.LayerBlendMode = fbs.LayerBlendMode.PassThrough; - // Encode mask_type (LayerMaskType union) - // Default to Image(Alpha) - create LayerMaskTypeImage - fbs.LayerMaskTypeImage.startLayerMaskTypeImage(builder); - fbs.LayerMaskTypeImage.addImageMaskType( - builder, - fbs.ImageMaskType.Alpha - ); - const maskTypeOffset = - fbs.LayerMaskTypeImage.endLayerMaskTypeImage(builder); + // Encode mask_type (LayerMaskType union) — only when the node is actually a mask + const nodeWithMask = node as grida.program.nodes.Node & + Partial; + let maskTypeOffset: flatbuffers.Offset | undefined = undefined; + let maskTypeEnum: fbs.LayerMaskType = fbs.LayerMaskType.NONE; + if (nodeWithMask.mask != null) { + if (nodeWithMask.mask === "geometry") { + fbs.LayerMaskTypeGeometry.startLayerMaskTypeGeometry(builder); + maskTypeOffset = + fbs.LayerMaskTypeGeometry.endLayerMaskTypeGeometry(builder); + maskTypeEnum = fbs.LayerMaskType.LayerMaskTypeGeometry; + } else { + // ImageMaskType: "alpha" | "luminance" + fbs.LayerMaskTypeImage.startLayerMaskTypeImage(builder); + fbs.LayerMaskTypeImage.addImageMaskType( + builder, + nodeWithMask.mask === "luminance" + ? fbs.ImageMaskType.Luminance + : fbs.ImageMaskType.Alpha + ); + maskTypeOffset = + fbs.LayerMaskTypeImage.endLayerMaskTypeImage(builder); + maskTypeEnum = fbs.LayerMaskType.LayerMaskTypeImage; + } + } // Encode effects let effectsOffset: flatbuffers.Offset | undefined = undefined; @@ -1027,12 +1043,11 @@ export namespace format { // 3. Blend mode fbs.LayerTrait.addBlendMode(builder, blendMode); - // 4. Mask type - fbs.LayerTrait.addMaskTypeType( - builder, - fbs.LayerMaskType.LayerMaskTypeImage - ); - fbs.LayerTrait.addMaskType(builder, maskTypeOffset); + // 4. Mask type (only set when the node is a mask) + if (maskTypeOffset !== undefined) { + fbs.LayerTrait.addMaskTypeType(builder, maskTypeEnum); + fbs.LayerTrait.addMaskType(builder, maskTypeOffset); + } // 5. Effects if (effectsOffset !== undefined) { @@ -4430,8 +4445,7 @@ export namespace format { // Deterministic ordering: sort by string id nodeIds.sort(); - const nodeOffsets: flatbuffers.Offset[] = []; - const nodeTypes: fbs.Node[] = []; + const nodeSlotOffsets: flatbuffers.Offset[] = []; for (const nodeId of nodeIds) { const node = document.nodes[nodeId]!; const parentRef = nodeToParentRef.get(nodeId); @@ -4483,18 +4497,16 @@ export namespace format { parentRef, layoutOffset ); - nodeOffsets.push(nodeOffset); - nodeTypes.push(nodeType); + // Wrap in NodeSlot table (avoids vector-of-unions, enables Rust codegen) + fbs.NodeSlot.startNodeSlot(builder); + fbs.NodeSlot.addNodeType(builder, nodeType); + fbs.NodeSlot.addNode(builder, nodeOffset); + nodeSlotOffsets.push(fbs.NodeSlot.endNodeSlot(builder)); } - // Create both nodesType and nodes vectors for union - const nodesTypeOffset = fbs.CanvasDocument.createNodesTypeVector( - builder, - nodeTypes - ); const nodesOffset = fbs.CanvasDocument.createNodesVector( builder, - nodeOffsets + nodeSlotOffsets ); // Encode scenes array @@ -4508,7 +4520,6 @@ export namespace format { // Build CanvasDocument table fbs.CanvasDocument.startCanvasDocument(builder); fbs.CanvasDocument.addSchemaVersion(builder, schemaVersionOffset); - fbs.CanvasDocument.addNodesType(builder, nodesTypeOffset); fbs.CanvasDocument.addNodes(builder, nodesOffset); fbs.CanvasDocument.addScenes(builder, scenesOffset); const documentOffset = fbs.CanvasDocument.endCanvasDocument(builder); @@ -4518,7 +4529,7 @@ export namespace format { fbs.GridaFile.addDocument(builder, documentOffset); const rootOffset = fbs.GridaFile.endGridaFile(builder); - builder.finish(rootOffset); + builder.finish(rootOffset, "GRID"); return builder.asUint8Array(); } @@ -5438,15 +5449,14 @@ export namespace format { const nodeCount = document.nodesLength(); for (let i = 0; i < nodeCount; i++) { - const nodeType = document.nodesType(i); - if (nodeType === null || nodeType === fbs.Node.NONE) continue; - - // Get typed node table using union - const typedNode = unionListToNode( - nodeType, - (index: number, obj: any) => document.nodes(index, obj), - i - ); + const slot = document.nodes(i); + if (!slot) continue; + + const nodeType = slot.nodeType(); + if (nodeType === fbs.Node.NONE) continue; + + // Unwrap NodeSlot to get the typed node table + const typedNode = unionToNode(nodeType, (obj: any) => slot.node(obj)); if (!typedNode) continue; // SceneNode is special - it doesn't use LayerTrait diff --git a/packages/grida-canvas-io/index.ts b/packages/grida-canvas-io/index.ts index 2531c9218f..1a13509f9c 100644 --- a/packages/grida-canvas-io/index.ts +++ b/packages/grida-canvas-io/index.ts @@ -1434,6 +1434,88 @@ export namespace io { const file = await fileHandle.getFile(); return new Uint8Array(await file.arrayBuffer()); } + + /** + * Quarantines all document files into `_quarantine/