bookcover-3d-web 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +159 -0
- package/README_mockup.webp +0 -0
- package/README_sample.webp +0 -0
- package/dist/geometry.d.ts +12 -0
- package/dist/geometry.d.ts.map +1 -0
- package/dist/geometry.js +390 -0
- package/dist/geometry.js.map +1 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +404 -0
- package/dist/index.js.map +1 -0
- package/dist/math.d.ts +15 -0
- package/dist/math.d.ts.map +1 -0
- package/dist/math.js +92 -0
- package/dist/math.js.map +1 -0
- package/dist/photo.d.ts +6 -0
- package/dist/photo.d.ts.map +1 -0
- package/dist/photo.js +72 -0
- package/dist/photo.js.map +1 -0
- package/dist/svg.d.ts +12 -0
- package/dist/svg.d.ts.map +1 -0
- package/dist/svg.js +40 -0
- package/dist/svg.js.map +1 -0
- package/dist/types.d.ts +33 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/webgl.d.ts +15 -0
- package/dist/webgl.d.ts.map +1 -0
- package/dist/webgl.js +119 -0
- package/dist/webgl.js.map +1 -0
- package/package.json +18 -0
- package/src/backgrounds/coffee_table.jpg +0 -0
- package/src/backgrounds/table_side.jpg +0 -0
- package/src/backgrounds/table_with_book.jpg +0 -0
- package/src/backgrounds/table_with_laptop.jpg +0 -0
- package/src/backgrounds/wood.jpg +0 -0
- package/src/backgrounds_originals/coffee_table.jpg +0 -0
- package/src/backgrounds_originals/table_side.jpg +0 -0
- package/src/backgrounds_originals/table_with_book.jpg +0 -0
- package/src/backgrounds_originals/table_with_laptop.jpg +0 -0
- package/src/backgrounds_originals/wood.jpg +0 -0
- package/src/geometry.ts +513 -0
- package/src/index.ts +507 -0
- package/src/math.ts +84 -0
- package/src/photo.ts +77 -0
- package/src/svg.ts +46 -0
- package/src/types.ts +49 -0
- package/src/webgl.ts +131 -0
- package/tsconfig.json +19 -0
- package/tsconfig.tsbuildinfo +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
|
|
2
|
+
# bookcover-3d-web
|
|
3
|
+
|
|
4
|
+
Create 3D images of books by providing the book cover designs. Part of the [bookcover](https://github.com/gracious-tech/bookcover) generation system.
|
|
5
|
+
|
|
6
|
+
```
|
|
7
|
+
npm install bookcover-3d-web
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
This is a WebGL 3D book renderer with no external graphics dependencies.
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import {Book3DRenderer, generate} from 'bookcover-3d-web'
|
|
16
|
+
import type {BookFaces, CoverType, GenerateOptions} from 'bookcover-3d-web'
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Both exports take the same SVG face inputs and produce the same kind of output. The
|
|
20
|
+
difference is lifecycle: `generate` is a one-shot helper that creates and destroys a
|
|
21
|
+
renderer internally, while `Book3DRenderer` keeps the WebGL context alive so you can
|
|
22
|
+
re-render cheaply (e.g. on mouse drag) without reloading textures.
|
|
23
|
+
|
|
24
|
+
Use `generate` for static exports. Use `Book3DRenderer` for interactive previews.
|
|
25
|
+
|
|
26
|
+
## `generate(svgs, options?): Promise<Uint8Array>`
|
|
27
|
+
|
|
28
|
+
Creates a renderer, loads the SVGs, renders once, returns PNG bytes, then cleans up.
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import {generate} from 'bookcover-3d-web'
|
|
32
|
+
|
|
33
|
+
const png = await generate(
|
|
34
|
+
{front: frontSvg, back: backSvg, spine: spineSvg},
|
|
35
|
+
{cover_type: 'paperback', azimuth: -30, width: 800, height: 600},
|
|
36
|
+
)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
interface BookFaces {
|
|
41
|
+
front: string // SVG string
|
|
42
|
+
back: string // SVG string
|
|
43
|
+
spine?: string // SVG string (optional — depth_mm used if absent)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface GenerateOptions {
|
|
47
|
+
cover_type?: 'paperback'|'paperback_coil'|'paperback_wire'|'paperback_stitch'|'hardcover'|'hardcover_jacket'
|
|
48
|
+
azimuth?: number // horizontal camera angle in degrees (default: -30)
|
|
49
|
+
elevation?: number // vertical camera angle in degrees (default: 20)
|
|
50
|
+
roll?: number // clockwise rotation in degrees (default: 0)
|
|
51
|
+
width?: number // canvas width in pixels (default: 800)
|
|
52
|
+
height?: number // canvas height in pixels (default: 600)
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## `Book3DRenderer`
|
|
57
|
+
|
|
58
|
+
Persistent renderer for interactive use. Load SVGs once; call `render()` repeatedly
|
|
59
|
+
with different angles without reloading textures each time.
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import {Book3DRenderer} from 'bookcover-3d-web'
|
|
63
|
+
|
|
64
|
+
// Create once
|
|
65
|
+
const renderer = new Book3DRenderer(800, 600)
|
|
66
|
+
|
|
67
|
+
// Load SVGs and build geometry (do this when the cover changes)
|
|
68
|
+
await renderer.load({front: frontSvg, back: backSvg, spine: spineSvg}, 'paperback')
|
|
69
|
+
|
|
70
|
+
// Render at any angle — fast, no texture reload
|
|
71
|
+
renderer.render(-30, 20) // azimuth, elevation
|
|
72
|
+
|
|
73
|
+
// Export the current frame
|
|
74
|
+
const png = await renderer.to_png()
|
|
75
|
+
|
|
76
|
+
// Free GPU resources when done
|
|
77
|
+
renderer.destroy()
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Full API
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
const renderer = new Book3DRenderer(width?, height?)
|
|
84
|
+
|
|
85
|
+
// Load cover face SVGs and build 3D geometry
|
|
86
|
+
await renderer.load(svgs: BookFaces, cover_type?: CoverType, depth_mm?: number)
|
|
87
|
+
|
|
88
|
+
// Render at camera angles (all in degrees)
|
|
89
|
+
renderer.render(azimuth?, elevation?, zoom?, roll?, light_az?, light_el?, ambient?, exposure?)
|
|
90
|
+
|
|
91
|
+
// Resize without recreating WebGL context
|
|
92
|
+
renderer.resize(width, height)
|
|
93
|
+
|
|
94
|
+
// Get projected width/height ratio at default viewing angle
|
|
95
|
+
renderer.get_projected_aspect(): number
|
|
96
|
+
|
|
97
|
+
// Composite onto a background photo
|
|
98
|
+
await renderer.composite_photo(background: ImageBitmap, options?: PhotoCompositeOptions)
|
|
99
|
+
|
|
100
|
+
// Export current frame
|
|
101
|
+
await renderer.snapshot(): Promise<ImageBitmap>
|
|
102
|
+
await renderer.to_png(): Promise<Uint8Array>
|
|
103
|
+
|
|
104
|
+
// Free GPU resources
|
|
105
|
+
renderer.destroy()
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Photo compositing
|
|
109
|
+
|
|
110
|
+
`composite_photo` renders the book at a certain angle and composites it over a
|
|
111
|
+
background image, with a shadow derived from the light direction. It returns an
|
|
112
|
+
`ImageBitmap` at the background's native resolution.
|
|
113
|
+
|
|
114
|
+

|
|
115
|
+
|
|
116
|
+
The library ships a set of built-in background photos via `BACKGROUNDS`. Each entry has
|
|
117
|
+
an `id` (to identify which image to load) and pre-tuned camera/lighting options that
|
|
118
|
+
make the book look natural in that scene. Pass the background entry directly as the
|
|
119
|
+
`options` argument — it extends `PhotoCompositeOptions`.
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
import {Book3DRenderer, BACKGROUNDS} from 'bookcover-3d-web'
|
|
123
|
+
import type {Background} from 'bookcover-3d-web'
|
|
124
|
+
|
|
125
|
+
// Find the background you want
|
|
126
|
+
const bg: Background = BACKGROUNDS.find(b => b.id === 'coffee_table')!
|
|
127
|
+
|
|
128
|
+
// Load the image however you serve your assets
|
|
129
|
+
const img = await fetch(`/assets/backgrounds/${bg.id}.webp`)
|
|
130
|
+
const blob = await img.blob()
|
|
131
|
+
const bitmap = await createImageBitmap(blob)
|
|
132
|
+
|
|
133
|
+
// Render the book, then composite — pass the background entry as options
|
|
134
|
+
await renderer.load({front: frontSvg, back: backSvg, spine: spineSvg})
|
|
135
|
+
const result = await renderer.composite_photo(bitmap, bg)
|
|
136
|
+
|
|
137
|
+
// result is an ImageBitmap at the background's native resolution
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Available background IDs: `table_with_book`, `wood`, `coffee_table`, `table_with_laptop`,
|
|
141
|
+
`table_side`.
|
|
142
|
+
|
|
143
|
+
You can also composite onto your own image by passing a plain `PhotoCompositeOptions`
|
|
144
|
+
object (all fields optional — defaults give a flat overhead perspective):
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
interface PhotoCompositeOptions {
|
|
148
|
+
azimuth?: number // horizontal camera angle in degrees (default: -15)
|
|
149
|
+
elevation?: number // vertical camera angle in degrees (default: 35)
|
|
150
|
+
zoom?: number
|
|
151
|
+
roll?: number // clockwise rotation in degrees (default: 0)
|
|
152
|
+
book_scale?: number // book width as fraction of background width (default: 0.55)
|
|
153
|
+
offset_x?: number // position offset as fraction of background width (0 = centred)
|
|
154
|
+
offset_y?: number // position offset as fraction of background height (0 = centred)
|
|
155
|
+
light_az?: number // light horizontal angle in degrees
|
|
156
|
+
light_el?: number // light vertical angle in degrees
|
|
157
|
+
ambient?: number // ambient light level 0–1
|
|
158
|
+
}
|
|
159
|
+
```
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CoverType } from './types.js';
|
|
2
|
+
/** A single face ready for GPU upload: interleaved [xyz, uv, normal] × 4 verts + 6 indices */
|
|
3
|
+
export interface FaceData {
|
|
4
|
+
vertices: number[];
|
|
5
|
+
indices: number[];
|
|
6
|
+
texture: WebGLTexture | null;
|
|
7
|
+
color: [number, number, number];
|
|
8
|
+
}
|
|
9
|
+
/** Build all faces of the book using normalised dimensions (h = 1).
|
|
10
|
+
* w = cover_width / cover_height, d = spine_width / cover_height. */
|
|
11
|
+
export declare function build_faces(w: number, h: number, d: number, front_tex: WebGLTexture, back_tex: WebGLTexture, spine_tex: WebGLTexture | null, cover_type: CoverType, page_tex: WebGLTexture): FaceData[];
|
|
12
|
+
//# sourceMappingURL=geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../src/geometry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,YAAY,CAAA;AAuBzC,8FAA8F;AAC9F,MAAM,WAAW,QAAQ;IACrB,QAAQ,EAAC,MAAM,EAAE,CAAA;IACjB,OAAO,EAAC,MAAM,EAAE,CAAA;IAChB,OAAO,EAAC,YAAY,GAAG,IAAI,CAAA;IAC3B,KAAK,EAAC,CAAC,MAAM,EAAC,MAAM,EAAC,MAAM,CAAC,CAAA;CAC/B;AAmcD;sEACsE;AACtE,wBAAgB,WAAW,CACvB,CAAC,EAAC,MAAM,EACR,CAAC,EAAC,MAAM,EACR,CAAC,EAAC,MAAM,EACR,SAAS,EAAC,YAAY,EACtB,QAAQ,EAAC,YAAY,EACrB,SAAS,EAAC,YAAY,GAAG,IAAI,EAC7B,UAAU,EAAC,SAAS,EACpB,QAAQ,EAAC,YAAY,GACvB,QAAQ,EAAE,CAkBX"}
|
package/dist/geometry.js
ADDED
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
// Book box geometry — builds the vertex/index data for a given cover size
|
|
2
|
+
// Hardback board overhang (how much cover extends beyond pages on top/bottom/fore-edge)
|
|
3
|
+
// and board thickness (depth each board consumes from total spine width), in normalised units (h=1.0)
|
|
4
|
+
const BOARD_EXTEND = 0.02;
|
|
5
|
+
const BOARD_THICKNESS = 0.007;
|
|
6
|
+
// Cream colour for page-edge faces (fore-edge, top, bottom)
|
|
7
|
+
const PAGE_COLOR = [0.94, 0.91, 0.86];
|
|
8
|
+
// Hole colour: same warm cream as page edges but darkened
|
|
9
|
+
const HOLE_COLOR = [0.38, 0.36, 0.33];
|
|
10
|
+
// Hole spacing (centre-to-centre) and size in normalised units (h=1.0 = cover height)
|
|
11
|
+
const HOLE_PITCH = 0.032; // tighter spacing, roughly twice as many holes
|
|
12
|
+
const HOLE_W = 0.010; // rectangle half-width (along Z / spine depth axis)
|
|
13
|
+
const HOLE_H = 0.008; // rectangle half-height (along Y / book height axis)
|
|
14
|
+
const HOLE_CORNER = 0.003; // corner radius for rounded rect
|
|
15
|
+
const HOLE_MARGIN = 0.025; // inset from spine edge to hole centre on cover faces
|
|
16
|
+
const HOLE_EDGE_GAP = 0.018; // margin from top/bottom cover edge to first/last hole centre
|
|
17
|
+
const HOLE_SEGS = 4; // segments per rounded corner (quarter-circle)
|
|
18
|
+
const HOLE_EPSILON = 0.001; // z nudge to prevent z-fighting with underlying face
|
|
19
|
+
/** Build a filled rounded-rectangle on a cover face for coil/wire hole rendering.
|
|
20
|
+
* The shape sits in the XY plane at a fixed z; nx/ny/nz is the face normal.
|
|
21
|
+
* Corners are approximated with HOLE_SEGS arc segments each. */
|
|
22
|
+
function make_hole_rect(cx, cy, cz, nx, ny, nz) {
|
|
23
|
+
const verts = [];
|
|
24
|
+
const indices = [];
|
|
25
|
+
// Inner rect extents (full half-extents minus corner radius)
|
|
26
|
+
const iw = HOLE_W - HOLE_CORNER;
|
|
27
|
+
const ih = HOLE_H - HOLE_CORNER;
|
|
28
|
+
// Corner centres (dx, dy) and starting angle for each of the 4 corners
|
|
29
|
+
const corners = [
|
|
30
|
+
[iw, ih, 0], // top-right, 0° → 90°
|
|
31
|
+
[-iw, ih, Math.PI / 2], // top-left, 90° → 180°
|
|
32
|
+
[-iw, -ih, Math.PI], // bottom-left, 180° → 270°
|
|
33
|
+
[iw, -ih, Math.PI * 1.5], // bottom-right,270° → 360°
|
|
34
|
+
];
|
|
35
|
+
// Center vertex (index 0)
|
|
36
|
+
verts.push(cx, cy, cz, 0.5, 0.5, nx, ny, nz);
|
|
37
|
+
// Perimeter vertices — HOLE_SEGS+1 points per corner arc
|
|
38
|
+
for (const [ox, oy, start_a] of corners) {
|
|
39
|
+
for (let s = 0; s <= HOLE_SEGS; s++) {
|
|
40
|
+
const a = start_a + (s / HOLE_SEGS) * (Math.PI / 2);
|
|
41
|
+
verts.push(cx + ox + Math.cos(a) * HOLE_CORNER, cy + oy + Math.sin(a) * HOLE_CORNER, cz, 0.5, 0.5, nx, ny, nz);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Fan triangles from center to each consecutive pair of perimeter verts
|
|
45
|
+
const perimeter = corners.length * (HOLE_SEGS + 1);
|
|
46
|
+
for (let i = 0; i < perimeter; i++)
|
|
47
|
+
indices.push(0, 1 + i, 1 + (i + 1) % perimeter);
|
|
48
|
+
return { vertices: verts, indices, texture: null, color: HOLE_COLOR };
|
|
49
|
+
}
|
|
50
|
+
/** Build painted-on binding holes on front and back cover faces for coil/wire bindings */
|
|
51
|
+
function build_holes(hw, hh, hd) {
|
|
52
|
+
const faces = [];
|
|
53
|
+
// Fill from near the top edge to near the bottom edge
|
|
54
|
+
const usable = hh * 2 - HOLE_EDGE_GAP * 2;
|
|
55
|
+
const hole_count = Math.max(1, Math.round(usable / HOLE_PITCH) + 1);
|
|
56
|
+
const span = (hole_count - 1) * HOLE_PITCH;
|
|
57
|
+
const y0 = span / 2;
|
|
58
|
+
for (let i = 0; i < hole_count; i++) {
|
|
59
|
+
const cy = y0 - i * HOLE_PITCH;
|
|
60
|
+
const cx = -hw + HOLE_MARGIN;
|
|
61
|
+
// Front cover (+z normal), nudged forward to avoid z-fighting
|
|
62
|
+
faces.push(make_hole_rect(cx, cy, hd + HOLE_EPSILON, 0, 0, 1));
|
|
63
|
+
// Back cover (-z normal), nudged backward
|
|
64
|
+
faces.push(make_hole_rect(cx, cy, -(hd + HOLE_EPSILON), 0, 0, -1));
|
|
65
|
+
}
|
|
66
|
+
return faces;
|
|
67
|
+
}
|
|
68
|
+
/** Build a quad face from 4 [x,y,z,u,v] vertices + a flat normal */
|
|
69
|
+
function make_face(verts, nx, ny, nz, tex, color = [1, 1, 1]) {
|
|
70
|
+
const vertices = [];
|
|
71
|
+
for (const [x, y, z, u, v] of verts)
|
|
72
|
+
vertices.push(x, y, z, u, v, nx, ny, nz);
|
|
73
|
+
return { vertices, indices: [0, 1, 2, 0, 2, 3], texture: tex, color };
|
|
74
|
+
}
|
|
75
|
+
// Saddle-stitch curve: how far from the spine edge the covers bend, and subdivision count
|
|
76
|
+
const STITCH_CURVE_W = 0.011; // ~2.5mm normalised (h=1.0 = cover height ~229mm)
|
|
77
|
+
const STITCH_CURVE_SEGS = 5; // strip columns across the curved region
|
|
78
|
+
/** Build the top or bottom edge face for saddle-stitch: flat across most of the width,
|
|
79
|
+
* curving to a point only in the STITCH_CURVE_W region near the spine, matching the covers. */
|
|
80
|
+
function make_stitch_edge(hw, y, vhd, ny, page_tex) {
|
|
81
|
+
const verts = [];
|
|
82
|
+
const idx = [];
|
|
83
|
+
const cw = Math.min(STITCH_CURVE_W, hw);
|
|
84
|
+
const flip = ny < 0;
|
|
85
|
+
// Columns from fore-edge to spine: [x, z_front, z_back]
|
|
86
|
+
const cols = [
|
|
87
|
+
[hw, vhd, -vhd], // fore-edge
|
|
88
|
+
[-hw + cw, vhd, -vhd], // start of curve
|
|
89
|
+
];
|
|
90
|
+
// Curve region — mirrors make_stitch_cover: t=0 at spine (z=0), t=1 at curve end (z=±vhd)
|
|
91
|
+
for (let i = STITCH_CURVE_SEGS - 1; i >= 0; i--) {
|
|
92
|
+
const t = i / STITCH_CURVE_SEGS;
|
|
93
|
+
const z = vhd * (1 - Math.cos(t * Math.PI / 2));
|
|
94
|
+
cols.push([-hw + t * cw, z, -z]);
|
|
95
|
+
}
|
|
96
|
+
for (let c = 0; c < cols.length - 1; c++) {
|
|
97
|
+
const [x0, zf0, zb0] = cols[c];
|
|
98
|
+
const [x1, zf1, zb1] = cols[c + 1];
|
|
99
|
+
const u0 = (x0 + hw) / (2 * hw);
|
|
100
|
+
const u1 = (x1 + hw) / (2 * hw);
|
|
101
|
+
const base = (verts.length / 8);
|
|
102
|
+
// Top (ny>0): spine-front, fore-front, fore-back, spine-back
|
|
103
|
+
// Bottom (ny<0): spine-back, fore-back, fore-front, spine-front
|
|
104
|
+
if (!flip) {
|
|
105
|
+
verts.push(x1, y, zf1, u1, 0, 0, ny, 0);
|
|
106
|
+
verts.push(x0, y, zf0, u0, 0, 0, ny, 0);
|
|
107
|
+
verts.push(x0, y, zb0, u0, 1, 0, ny, 0);
|
|
108
|
+
verts.push(x1, y, zb1, u1, 1, 0, ny, 0);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
verts.push(x1, y, zb1, u1, 1, 0, ny, 0);
|
|
112
|
+
verts.push(x0, y, zb0, u0, 1, 0, ny, 0);
|
|
113
|
+
verts.push(x0, y, zf0, u0, 0, 0, ny, 0);
|
|
114
|
+
verts.push(x1, y, zf1, u1, 0, 0, ny, 0);
|
|
115
|
+
}
|
|
116
|
+
idx.push(base, base + 1, base + 2, base, base + 2, base + 3);
|
|
117
|
+
}
|
|
118
|
+
return { vertices: verts, indices: idx, texture: page_tex, color: [1, 1, 1] };
|
|
119
|
+
}
|
|
120
|
+
/** Build one curved cover panel for saddle-stitch binding.
|
|
121
|
+
* sign = +1 for front (normal points +z), -1 for back (-z).
|
|
122
|
+
* The spine edge (x = -hw) bends inward to z = 0 over STITCH_CURVE_W. */
|
|
123
|
+
function make_stitch_cover(hw, hh, hd, sign, tex) {
|
|
124
|
+
const verts = [];
|
|
125
|
+
const idx = [];
|
|
126
|
+
const cw = Math.min(STITCH_CURVE_W, hw);
|
|
127
|
+
// Columns from spine edge to fore-edge, each with (x, z, u)
|
|
128
|
+
const cols = [];
|
|
129
|
+
// Curved region: cosine ease from z=0 at spine to z=±hd at curve end
|
|
130
|
+
for (let i = 0; i <= STITCH_CURVE_SEGS; i++) {
|
|
131
|
+
const t = i / STITCH_CURVE_SEGS;
|
|
132
|
+
cols.push({
|
|
133
|
+
x: -hw + t * cw,
|
|
134
|
+
z: sign * hd * (1 - Math.cos(t * Math.PI / 2)),
|
|
135
|
+
u: (-hw + t * cw + hw) / (2 * hw),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
// Flat region: single column at fore-edge
|
|
139
|
+
cols.push({ x: hw, z: sign * hd, u: 1.0 });
|
|
140
|
+
// Back face UVs are mirrored horizontally (u=0 at fore-edge, u=1 at spine)
|
|
141
|
+
if (sign < 0) {
|
|
142
|
+
for (const c of cols)
|
|
143
|
+
c.u = 1 - c.u;
|
|
144
|
+
}
|
|
145
|
+
// Vertex strip: top and bottom vert per column
|
|
146
|
+
for (const { x, z, u } of cols) {
|
|
147
|
+
verts.push(x, hh, z, u, 0, 0, 0, sign);
|
|
148
|
+
verts.push(x, -hh, z, u, 1, 0, 0, sign);
|
|
149
|
+
}
|
|
150
|
+
// Quads between adjacent column pairs
|
|
151
|
+
for (let c = 0; c < cols.length - 1; c++) {
|
|
152
|
+
const tl = c * 2, bl = c * 2 + 1;
|
|
153
|
+
const tr = (c + 1) * 2, br = (c + 1) * 2 + 1;
|
|
154
|
+
idx.push(tl, tr, br, tl, br, bl);
|
|
155
|
+
}
|
|
156
|
+
return { vertices: verts, indices: idx, texture: tex, color: [1, 1, 1] };
|
|
157
|
+
}
|
|
158
|
+
/** Build faces for a saddle-stitch binding: covers curve inward to meet at the spine fold */
|
|
159
|
+
function build_stitch(hw, hh, hd, front_tex, back_tex, _spine_tex, page_tex) {
|
|
160
|
+
const vhd = hd;
|
|
161
|
+
return [
|
|
162
|
+
make_stitch_cover(hw, hh, vhd, 1, front_tex),
|
|
163
|
+
make_stitch_cover(hw, hh, vhd, -1, back_tex),
|
|
164
|
+
// Spine fold edge — covers meet at z=0 here so this is a zero-width seam;
|
|
165
|
+
// render a thin sliver of page color as a visual hint of the fold
|
|
166
|
+
make_face([
|
|
167
|
+
[-hw, hh, -0.001, 0, 0],
|
|
168
|
+
[-hw, hh, 0.001, 1, 0],
|
|
169
|
+
[-hw, -hh, 0.001, 1, 1],
|
|
170
|
+
[-hw, -hh, -0.001, 0, 1],
|
|
171
|
+
], -1, 0, 0, null, PAGE_COLOR),
|
|
172
|
+
// Fore-edge (x = +hw)
|
|
173
|
+
make_face([
|
|
174
|
+
[hw, hh, vhd, 0, 0],
|
|
175
|
+
[hw, hh, -vhd, 0, 1],
|
|
176
|
+
[hw, -hh, -vhd, 1, 1],
|
|
177
|
+
[hw, -hh, vhd, 1, 0],
|
|
178
|
+
], 1, 0, 0, page_tex),
|
|
179
|
+
// Top and bottom — curved strip matching the cover profile
|
|
180
|
+
make_stitch_edge(hw, hh, vhd, 1, page_tex),
|
|
181
|
+
make_stitch_edge(hw, -hh, vhd, -1, page_tex),
|
|
182
|
+
];
|
|
183
|
+
}
|
|
184
|
+
/** Build faces for a paperback (simple box, no overhang or board thickness) */
|
|
185
|
+
function build_paperback(hw, hh, hd, front_tex, back_tex, spine_tex, page_tex) {
|
|
186
|
+
return [
|
|
187
|
+
// Front (z = +hd)
|
|
188
|
+
make_face([
|
|
189
|
+
[-hw, hh, hd, 0, 0],
|
|
190
|
+
[hw, hh, hd, 1, 0],
|
|
191
|
+
[hw, -hh, hd, 1, 1],
|
|
192
|
+
[-hw, -hh, hd, 0, 1],
|
|
193
|
+
], 0, 0, 1, front_tex),
|
|
194
|
+
// Back (z = -hd)
|
|
195
|
+
make_face([
|
|
196
|
+
[hw, hh, -hd, 0, 0],
|
|
197
|
+
[-hw, hh, -hd, 1, 0],
|
|
198
|
+
[-hw, -hh, -hd, 1, 1],
|
|
199
|
+
[hw, -hh, -hd, 0, 1],
|
|
200
|
+
], 0, 0, -1, back_tex),
|
|
201
|
+
// Spine (x = -hw)
|
|
202
|
+
make_face([
|
|
203
|
+
[-hw, hh, -hd, 0, 0],
|
|
204
|
+
[-hw, hh, hd, 1, 0],
|
|
205
|
+
[-hw, -hh, hd, 1, 1],
|
|
206
|
+
[-hw, -hh, -hd, 0, 1],
|
|
207
|
+
], -1, 0, 0, spine_tex, PAGE_COLOR),
|
|
208
|
+
// Fore-edge (x = +hw)
|
|
209
|
+
make_face([
|
|
210
|
+
[hw, hh, hd, 0, 0],
|
|
211
|
+
[hw, hh, -hd, 0, 1],
|
|
212
|
+
[hw, -hh, -hd, 1, 1],
|
|
213
|
+
[hw, -hh, hd, 1, 0],
|
|
214
|
+
], 1, 0, 0, page_tex),
|
|
215
|
+
// Top (y = +hh)
|
|
216
|
+
make_face([
|
|
217
|
+
[-hw, hh, hd, 0, 0],
|
|
218
|
+
[hw, hh, hd, 1, 0],
|
|
219
|
+
[hw, hh, -hd, 1, 1],
|
|
220
|
+
[-hw, hh, -hd, 0, 1],
|
|
221
|
+
], 0, 1, 0, page_tex),
|
|
222
|
+
// Bottom (y = -hh)
|
|
223
|
+
make_face([
|
|
224
|
+
[-hw, -hh, -hd, 0, 0],
|
|
225
|
+
[hw, -hh, -hd, 1, 0],
|
|
226
|
+
[hw, -hh, hd, 1, 1],
|
|
227
|
+
[-hw, -hh, hd, 0, 1],
|
|
228
|
+
], 0, -1, 0, page_tex),
|
|
229
|
+
];
|
|
230
|
+
}
|
|
231
|
+
/** Build faces for a hardcover book with accurate interior trim vs cover trim.
|
|
232
|
+
* Cover panels use full SVG dimensions; page block is inset by board overhang/thickness.
|
|
233
|
+
* Front and back boards are separate (not connected at the fore-edge).
|
|
234
|
+
* Board edge colour is sampled from the cover textures (material wraps around). */
|
|
235
|
+
function build_hardcover(hw, hh, hd, front_tex, back_tex, spine_tex, page_tex) {
|
|
236
|
+
// Page block extents — all four boards consume BOARD_THICKNESS, interior shifts/moves intact
|
|
237
|
+
const py = hh - BOARD_EXTEND; // page half-height (top/bottom inset)
|
|
238
|
+
const pz = hd - BOARD_THICKNESS; // page half-depth (front/back boards consume thickness)
|
|
239
|
+
const sx = -hw + BOARD_THICKNESS; // page block left edge (spine board pushes it right)
|
|
240
|
+
const fx = hw - BOARD_EXTEND; // page block right edge (fore-edge inset)
|
|
241
|
+
// UV sample points for board edges — sample near corners of the cover textures
|
|
242
|
+
// where solid background colour is most likely.
|
|
243
|
+
// Front cover: u=0 is spine, u=1 is fore-edge, v=0 is top, v=1 is bottom
|
|
244
|
+
const f_uv = [0.98, 0.98];
|
|
245
|
+
// Back cover: u=0 is fore-edge, u=1 is spine
|
|
246
|
+
const b_uv = [0.02, 0.98];
|
|
247
|
+
// Spine board surfaces — sample spine texture center, fall back to front cover spine edge
|
|
248
|
+
const cloth_tex = spine_tex ?? front_tex;
|
|
249
|
+
const s_uv = spine_tex ? [0.5, 0.5] : [0.02, 0.5];
|
|
250
|
+
const faces = [];
|
|
251
|
+
// -- Cover panels (full size from SVG) --
|
|
252
|
+
// Front cover (z = +hd)
|
|
253
|
+
faces.push(make_face([
|
|
254
|
+
[-hw, hh, hd, 0, 0],
|
|
255
|
+
[hw, hh, hd, 1, 0],
|
|
256
|
+
[hw, -hh, hd, 1, 1],
|
|
257
|
+
[-hw, -hh, hd, 0, 1],
|
|
258
|
+
], 0, 0, 1, front_tex));
|
|
259
|
+
// Back cover (z = -hd)
|
|
260
|
+
faces.push(make_face([
|
|
261
|
+
[hw, hh, -hd, 0, 0],
|
|
262
|
+
[-hw, hh, -hd, 1, 0],
|
|
263
|
+
[-hw, -hh, -hd, 1, 1],
|
|
264
|
+
[hw, -hh, -hd, 0, 1],
|
|
265
|
+
], 0, 0, -1, back_tex));
|
|
266
|
+
// Spine (x = -hw) — full cover height and depth
|
|
267
|
+
faces.push(make_face([
|
|
268
|
+
[-hw, hh, -hd, 0, 0],
|
|
269
|
+
[-hw, hh, hd, 1, 0],
|
|
270
|
+
[-hw, -hh, hd, 1, 1],
|
|
271
|
+
[-hw, -hh, -hd, 0, 1],
|
|
272
|
+
], -1, 0, 0, spine_tex, PAGE_COLOR));
|
|
273
|
+
// -- Page block (inset from cover) --
|
|
274
|
+
// Page fore-edge (x = +fx) — page block right edge
|
|
275
|
+
faces.push(make_face([
|
|
276
|
+
[fx, py, pz, 0, 0],
|
|
277
|
+
[fx, py, -pz, 0, 1],
|
|
278
|
+
[fx, -py, -pz, 1, 1],
|
|
279
|
+
[fx, -py, pz, 1, 0],
|
|
280
|
+
], 1, 0, 0, page_tex));
|
|
281
|
+
// Page top (y = +py) — spine board inner edge to page fore-edge
|
|
282
|
+
faces.push(make_face([
|
|
283
|
+
[sx, py, pz, 0, 0],
|
|
284
|
+
[fx, py, pz, 1, 0],
|
|
285
|
+
[fx, py, -pz, 1, 1],
|
|
286
|
+
[sx, py, -pz, 0, 1],
|
|
287
|
+
], 0, 1, 0, page_tex));
|
|
288
|
+
// Page bottom (y = -py) — spine board inner edge to page fore-edge
|
|
289
|
+
faces.push(make_face([
|
|
290
|
+
[sx, -py, -pz, 0, 0],
|
|
291
|
+
[fx, -py, -pz, 1, 0],
|
|
292
|
+
[fx, -py, pz, 1, 1],
|
|
293
|
+
[sx, -py, pz, 0, 1],
|
|
294
|
+
], 0, -1, 0, page_tex));
|
|
295
|
+
// -- Fore-edge board strips (at x = +hw, facing +x) --
|
|
296
|
+
// Front and back boards are independent — gap between them is open (no connection)
|
|
297
|
+
// Front board edge (full height, z from +pz to +hd)
|
|
298
|
+
faces.push(make_face([
|
|
299
|
+
[hw, hh, hd, f_uv[0], f_uv[1]],
|
|
300
|
+
[hw, hh, pz, f_uv[0], f_uv[1]],
|
|
301
|
+
[hw, -hh, pz, f_uv[0], f_uv[1]],
|
|
302
|
+
[hw, -hh, hd, f_uv[0], f_uv[1]],
|
|
303
|
+
], 1, 0, 0, front_tex));
|
|
304
|
+
// Back board edge (full height, z from -hd to -pz)
|
|
305
|
+
faces.push(make_face([
|
|
306
|
+
[hw, hh, -pz, b_uv[0], b_uv[1]],
|
|
307
|
+
[hw, hh, -hd, b_uv[0], b_uv[1]],
|
|
308
|
+
[hw, -hh, -hd, b_uv[0], b_uv[1]],
|
|
309
|
+
[hw, -hh, -pz, b_uv[0], b_uv[1]],
|
|
310
|
+
], 1, 0, 0, back_tex));
|
|
311
|
+
// -- Top board strips (at y = +hh, facing +y) --
|
|
312
|
+
// Front board top (full width, z from +pz to +hd)
|
|
313
|
+
faces.push(make_face([
|
|
314
|
+
[-hw, hh, hd, f_uv[0], f_uv[1]],
|
|
315
|
+
[hw, hh, hd, f_uv[0], f_uv[1]],
|
|
316
|
+
[hw, hh, pz, f_uv[0], f_uv[1]],
|
|
317
|
+
[-hw, hh, pz, f_uv[0], f_uv[1]],
|
|
318
|
+
], 0, 1, 0, front_tex));
|
|
319
|
+
// Back board top (full width, z from -hd to -pz)
|
|
320
|
+
faces.push(make_face([
|
|
321
|
+
[-hw, hh, -pz, b_uv[0], b_uv[1]],
|
|
322
|
+
[hw, hh, -pz, b_uv[0], b_uv[1]],
|
|
323
|
+
[hw, hh, -hd, b_uv[0], b_uv[1]],
|
|
324
|
+
[-hw, hh, -hd, b_uv[0], b_uv[1]],
|
|
325
|
+
], 0, 1, 0, back_tex));
|
|
326
|
+
// -- Bottom board strips (at y = -hh, facing -y) --
|
|
327
|
+
// Front board bottom (full width, z from +pz to +hd)
|
|
328
|
+
faces.push(make_face([
|
|
329
|
+
[-hw, -hh, pz, f_uv[0], f_uv[1]],
|
|
330
|
+
[hw, -hh, pz, f_uv[0], f_uv[1]],
|
|
331
|
+
[hw, -hh, hd, f_uv[0], f_uv[1]],
|
|
332
|
+
[-hw, -hh, hd, f_uv[0], f_uv[1]],
|
|
333
|
+
], 0, -1, 0, front_tex));
|
|
334
|
+
// Back board bottom (full width, z from -hd to -pz)
|
|
335
|
+
faces.push(make_face([
|
|
336
|
+
[-hw, -hh, -hd, b_uv[0], b_uv[1]],
|
|
337
|
+
[hw, -hh, -hd, b_uv[0], b_uv[1]],
|
|
338
|
+
[hw, -hh, -pz, b_uv[0], b_uv[1]],
|
|
339
|
+
[-hw, -hh, -pz, b_uv[0], b_uv[1]],
|
|
340
|
+
], 0, -1, 0, back_tex));
|
|
341
|
+
// -- Spine board surfaces --
|
|
342
|
+
// The spine board has thickness BOARD_THICKNESS (sx - (-hw)).
|
|
343
|
+
// Its outer face is the spine panel already rendered above.
|
|
344
|
+
// These faces close the top, bottom, and inner ledges of the spine board.
|
|
345
|
+
// Spine board top (y = +hh, x from -hw to sx, z from -pz to +pz)
|
|
346
|
+
faces.push(make_face([
|
|
347
|
+
[-hw, hh, pz, s_uv[0], s_uv[1]],
|
|
348
|
+
[sx, hh, pz, s_uv[0], s_uv[1]],
|
|
349
|
+
[sx, hh, -pz, s_uv[0], s_uv[1]],
|
|
350
|
+
[-hw, hh, -pz, s_uv[0], s_uv[1]],
|
|
351
|
+
], 0, 1, 0, cloth_tex));
|
|
352
|
+
// Spine board bottom (y = -hh, x from -hw to sx, z from -pz to +pz)
|
|
353
|
+
faces.push(make_face([
|
|
354
|
+
[-hw, -hh, -pz, s_uv[0], s_uv[1]],
|
|
355
|
+
[sx, -hh, -pz, s_uv[0], s_uv[1]],
|
|
356
|
+
[sx, -hh, pz, s_uv[0], s_uv[1]],
|
|
357
|
+
[-hw, -hh, pz, s_uv[0], s_uv[1]],
|
|
358
|
+
], 0, -1, 0, cloth_tex));
|
|
359
|
+
// Spine board inner ledge top (y = +py, x from -hw to sx) — closes gap at page level
|
|
360
|
+
faces.push(make_face([
|
|
361
|
+
[-hw, py, pz, s_uv[0], s_uv[1]],
|
|
362
|
+
[sx, py, pz, s_uv[0], s_uv[1]],
|
|
363
|
+
[sx, py, -pz, s_uv[0], s_uv[1]],
|
|
364
|
+
[-hw, py, -pz, s_uv[0], s_uv[1]],
|
|
365
|
+
], 0, 1, 0, cloth_tex));
|
|
366
|
+
// Spine board inner ledge bottom (y = -py, x from -hw to sx)
|
|
367
|
+
faces.push(make_face([
|
|
368
|
+
[-hw, -py, -pz, s_uv[0], s_uv[1]],
|
|
369
|
+
[sx, -py, -pz, s_uv[0], s_uv[1]],
|
|
370
|
+
[sx, -py, pz, s_uv[0], s_uv[1]],
|
|
371
|
+
[-hw, -py, pz, s_uv[0], s_uv[1]],
|
|
372
|
+
], 0, -1, 0, cloth_tex));
|
|
373
|
+
return faces;
|
|
374
|
+
}
|
|
375
|
+
/** Build all faces of the book using normalised dimensions (h = 1).
|
|
376
|
+
* w = cover_width / cover_height, d = spine_width / cover_height. */
|
|
377
|
+
export function build_faces(w, h, d, front_tex, back_tex, spine_tex, cover_type, page_tex) {
|
|
378
|
+
// Half-extents
|
|
379
|
+
const hw = w / 2, hh = h / 2, hd = d / 2;
|
|
380
|
+
if (cover_type === 'hardcover' || cover_type === 'hardcover_jacket')
|
|
381
|
+
return build_hardcover(hw, hh, hd, front_tex, back_tex, spine_tex, page_tex);
|
|
382
|
+
if (cover_type === 'paperback_stitch')
|
|
383
|
+
return build_stitch(hw, hh, hd, front_tex, back_tex, spine_tex, page_tex);
|
|
384
|
+
const faces = build_paperback(hw, hh, hd, front_tex, back_tex, spine_tex, page_tex);
|
|
385
|
+
// Coil and wire bindings get painted-on holes near the spine edge
|
|
386
|
+
if (cover_type === 'paperback_coil' || cover_type === 'paperback_wire')
|
|
387
|
+
faces.push(...build_holes(hw, hh, hd));
|
|
388
|
+
return faces;
|
|
389
|
+
}
|
|
390
|
+
//# sourceMappingURL=geometry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.js","sourceRoot":"","sources":["../src/geometry.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export type { BookFaces, CoverType, GenerateOptions, Background, PhotoCompositeOptions } from './types.js';
|
|
2
|
+
export { BACKGROUNDS } from './photo.js';
|
|
3
|
+
import type { BookFaces, CoverType, GenerateOptions, PhotoCompositeOptions } from './types.js';
|
|
4
|
+
/** Persistent WebGL book renderer. Create once, call load() when covers change, render() cheaply. */
|
|
5
|
+
export declare class Book3DRenderer {
|
|
6
|
+
readonly canvas: OffscreenCanvas | HTMLCanvasElement;
|
|
7
|
+
private _gl_state;
|
|
8
|
+
private _faces;
|
|
9
|
+
private _w;
|
|
10
|
+
private _h;
|
|
11
|
+
private _d;
|
|
12
|
+
private _cover_height;
|
|
13
|
+
private _textures;
|
|
14
|
+
private _page_tex;
|
|
15
|
+
constructor(width?: number, height?: number);
|
|
16
|
+
/** Resize the render canvas without recreating the WebGL context or re-uploading textures */
|
|
17
|
+
resize(width: number, height: number): void;
|
|
18
|
+
/** Projected aspect ratio (width/height) of the book at the default viewing angle */
|
|
19
|
+
get_projected_aspect(): number;
|
|
20
|
+
private static _try_offscreen_webgl;
|
|
21
|
+
/** Initialise WebGL on first use */
|
|
22
|
+
private _init_gl;
|
|
23
|
+
/** Load new cover SVGs and re-upload geometry / textures.
|
|
24
|
+
* depth_mm: book thickness in mm, used when no spine SVG is present (e.g. coil/wire bindings).
|
|
25
|
+
* Pass 0 for bindings where the cover faces meet (e.g. saddle stitch). */
|
|
26
|
+
load(svgs: BookFaces, cover_type?: CoverType, depth_mm?: number): Promise<void>;
|
|
27
|
+
/** Render the book at the given camera angles (degrees), zoom multiplier, and clockwise roll */
|
|
28
|
+
render(azimuth?: number, elevation?: number, zoom?: number, roll?: number, light_az?: number, light_el?: number, ambient?: number, exposure?: number): void;
|
|
29
|
+
/** Return the current frame as an ImageBitmap */
|
|
30
|
+
snapshot(): Promise<ImageBitmap>;
|
|
31
|
+
/** Render and return the current frame as PNG bytes */
|
|
32
|
+
to_png(): Promise<Uint8Array>;
|
|
33
|
+
/** Composite the book onto a background ImageBitmap at a flat-on-table angle.
|
|
34
|
+
* Renders at the given angles (defaulting to a flat overhead perspective),
|
|
35
|
+
* then draws the result centred over the background. */
|
|
36
|
+
composite_photo(background: ImageBitmap, options?: PhotoCompositeOptions): Promise<ImageBitmap>;
|
|
37
|
+
/** Free all WebGL resources */
|
|
38
|
+
destroy(): void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* One-shot render: load the SVGs, render at the given angle, return PNG bytes.
|
|
42
|
+
*/
|
|
43
|
+
export declare function generate(svgs: BookFaces, options?: GenerateOptions): Promise<Uint8Array>;
|
|
44
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAC,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,qBAAqB,EAAC,MAAM,YAAY,CAAA;AACxG,OAAO,EAAC,WAAW,EAAC,MAAM,YAAY,CAAA;AACtC,OAAO,KAAK,EAAC,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,qBAAqB,EAAC,MAAM,YAAY,CAAA;AAgE5F,qGAAqG;AACrG,qBAAa,cAAc;IAEvB,QAAQ,CAAC,MAAM,EAAC,eAAe,GAAG,iBAAiB,CAAA;IACnD,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,EAAE,CAAI;IACd,OAAO,CAAC,EAAE,CAAI;IACd,OAAO,CAAC,EAAE,CAAM;IAEhB,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,SAAS,CAA2B;gBAGhC,KAAK,SAAgB,EAAE,MAAM,SAAiB;IAa1D,6FAA6F;IAC7F,MAAM,CAAC,KAAK,EAAC,MAAM,EAAE,MAAM,EAAC,MAAM,GAAE,IAAI;IAKxC,qFAAqF;IACrF,oBAAoB,IAAG,MAAM;IAS7B,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAYnC,oCAAoC;IACpC,OAAO,CAAC,QAAQ;IA+BhB;;+EAE2E;IACrE,IAAI,CAAC,IAAI,EAAC,SAAS,EAAE,UAAU,GAAC,SAAuB,EAAE,QAAQ,CAAC,EAAC,MAAM,GAAE,OAAO,CAAC,IAAI,CAAC;IAsE9F,gGAAgG;IAChG,MAAM,CAAC,OAAO,SAAkB,EAAE,SAAS,SAAoB,EAAE,IAAI,SAAM,EAAE,IAAI,SAAI,EACjF,QAAQ,SAAmB,EAAE,QAAQ,SAAmB,EAAE,OAAO,SAAkB,EACnF,QAAQ,SAAM,GAAE,IAAI;IA4ExB,iDAAiD;IAC3C,QAAQ,IAAG,OAAO,CAAC,WAAW,CAAC;IAIrC,uDAAuD;IACjD,MAAM,IAAG,OAAO,CAAC,UAAU,CAAC;IAclC;;6DAEyD;IACnD,eAAe,CAAC,UAAU,EAAC,WAAW,EAAE,OAAO,GAAC,qBAA0B,GAAE,OAAO,CAAC,WAAW,CAAC;IAqItG,+BAA+B;IAC/B,OAAO,IAAG,IAAI;CAiBjB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAC,SAAS,EAAE,OAAO,GAAC,eAAoB,GAAE,OAAO,CAAC,UAAU,CAAC,CAkB/F"}
|