| 1 | > See [`svg-image-embedding.md`](./svg-image-embedding.md) for SVG image syntax and crop-policy enforcement. |
| 2 | |
| 3 | # Image Layout Specification |
| 4 | |
| 5 | Neutral geometry and review rules for every image placement. This file calculates the selected composition; it never chooses a resource, pattern, or automatic left/right or top/bottom layout. |
| 6 | |
| 7 | **When to run**: whenever an image will be placed. Use the current page composition to select its region first, then apply the relevant single-item, adjacent, overlay, or multi-item calculation below. |
| 8 | |
| 9 | --- |
| 10 | |
| 11 | ## 1. Ownership and Inputs |
| 12 | |
| 13 | | Role | Owns | |
| 14 | |---|---| |
| 15 | | Default Strategist | Resource choice, semantic role, crop boundary, and preferred image/content or image/shape relationship | |
| 16 | | Image_Generator | Composition inside each generated bitmap for its planned container | |
| 17 | | Default Executor | Final SVG regions and geometry; may adapt the preferred relationship while preserving binding resource, content, and crop constraints | |
| 18 | | Quick Generate main agent | The planning and realization decisions above in one active context | |
| 19 | |
| 20 | This specification and [`image-layout-patterns.md`](./image-layout-patterns.md) are the always-read geometry and composition vocabulary; [`svg-image-embedding.md`](./svg-image-embedding.md) owns embedding. Default and Quick SVG authoring also load [`svg-effects.md`](./svg-effects.md) and [`native-shape-authoring.md`](./native-shape-authoring.md) before realization, so apply their contracts directly when a selected construction needs effects, preset geometry, or Boolean geometry. Other routes follow their own documented load triggers. |
| 21 | |
| 22 | ### 1.1 Geometry notation |
| 23 | |
| 24 | | Symbol | Meaning | |
| 25 | |---|---| |
| 26 | | `(x0, y0, W, H)` | Current selected page region | |
| 27 | | `(ws, hs)` | Measured source width and height | |
| 28 | | `R = ws / hs` | Source aspect ratio | |
| 29 | | `Q = W / H` | Selected-region aspect ratio | |
| 30 | | `g`, `gx`, `gy` | Gap between adjacent regions, columns, or rows | |
| 31 | | `ax`, `ay` | Horizontal and vertical anchor fractions in `[0,1]` | |
| 32 | |
| 33 | All dimensions must be finite and positive. Derive `R` from current measured source data rather than a requested or previously planned size. |
| 34 | |
| 35 | --- |
| 36 | |
| 37 | ## 2. Aspect-Ratio Placement |
| 38 | |
| 39 | ### 2.1 Contain |
| 40 | |
| 41 | Contain keeps the complete source visible inside `(W,H)`: |
| 42 | |
| 43 | ```text |
| 44 | if R >= Q: |
| 45 | w = W |
| 46 | h = W / R |
| 47 | else: |
| 48 | h = H |
| 49 | w = H × R |
| 50 | |
| 51 | x = x0 + ax × (W - w) |
| 52 | y = y0 + ay × (H - h) |
| 53 | ``` |
| 54 | |
| 55 | Centered contain uses `ax = ay = 0.5`. SVG realization normally maps this to a legal `meet` anchor. |
| 56 | |
| 57 | ### 2.2 Fill |
| 58 | |
| 59 | Fill covers `(W,H)` without distortion and crops overflow: |
| 60 | |
| 61 | ```text |
| 62 | if R >= Q: |
| 63 | h = H |
| 64 | w = H × R |
| 65 | else: |
| 66 | w = W |
| 67 | h = W / R |
| 68 | |
| 69 | overflow_x = w - W |
| 70 | overflow_y = h - H |
| 71 | x = x0 - ax × overflow_x |
| 72 | y = y0 - ay × overflow_y |
| 73 | ``` |
| 74 | |
| 75 | Centered fill uses `ax = ay = 0.5`. SVG realization normally maps this to a legal `slice` anchor. Use fill only when the active crop boundary permits the computed loss and the anchor protects the declared focal content. |
| 76 | |
| 77 | ### 2.3 Mode selection |
| 78 | |
| 79 | | Need | Geometry | |
| 80 | |---|---| |
| 81 | | Complete source, evidence, or edge content | Contain | |
| 82 | | Region coverage with a focal-safe crop | Fill | |
| 83 | | Complete source plus a detail view | One contain placement plus a separately justified crop | |
| 84 | | Irregular or repeated source windows | Apply the selected region math first, then load the owning crop/shape reference | |
| 85 | |
| 86 | --- |
| 87 | |
| 88 | ## 3. Single Image |
| 89 | |
| 90 | Place a standalone item by applying §2 to its selected region. The region itself comes from the page hierarchy; source ratio determines the item geometry inside it, not the page structure. |
| 91 | |
| 92 | For an item adjacent to another region, divide only the available selected region. Let `q_item` and `q_other` be positive visual weights for the image and the other content. |
| 93 | |
| 94 | ### 3.1 Horizontal adjacency |
| 95 | |
| 96 | ```text |
| 97 | available = W - g |
| 98 | item_width = available × q_item / (q_item + q_other) |
| 99 | other_width = available - item_width |
| 100 | ``` |
| 101 | |
| 102 | Both regions use height `H`. Place either region first according to the selected composition; no fixed share is implied. |
| 103 | |
| 104 | ### 3.2 Vertical adjacency |
| 105 | |
| 106 | ```text |
| 107 | available = H - g |
| 108 | item_height = available × q_item / (q_item + q_other) |
| 109 | other_height = available - item_height |
| 110 | ``` |
| 111 | |
| 112 | Both regions use width `W`. Place either region first according to the selected composition. |
| 113 | |
| 114 | ### 3.3 Overlay and inset |
| 115 | |
| 116 | An overlay keeps the image region and overlay region independently measurable. An inset selects a child region `(xi, yi, Wi, Hi)` inside the current region, then reapplies §2 using the same source ratio. Do not derive either region from an assumed percentage; size it from the actual hierarchy, copy, focal content, and required separation. |
| 117 | |
| 118 | --- |
| 119 | |
| 120 | ## 4. Multiple Images |
| 121 | |
| 122 | ### 4.1 Equal grid |
| 123 | |
| 124 | For `c` columns and `r` rows: |
| 125 | |
| 126 | ```text |
| 127 | cell_width = (W - (c - 1) × gx) / c |
| 128 | cell_height = (H - (r - 1) × gy) / r |
| 129 | |
| 130 | cell_x(col) = x0 + col × (cell_width + gx) |
| 131 | cell_y(row) = y0 + row × (cell_height + gy) |
| 132 | ``` |
| 133 | |
| 134 | Use equal cells when peer comparison is the message. Apply contain or fill independently to each source within its cell. |
| 135 | |
| 136 | ### 4.2 Weighted tracks |
| 137 | |
| 138 | For column weights `u[1]…u[c]` and row weights `v[1]…v[r]`: |
| 139 | |
| 140 | ```text |
| 141 | available_width = W - (c - 1) × gx |
| 142 | available_height = H - (r - 1) × gy |
| 143 | |
| 144 | column_width[j] = available_width × u[j] / sum(u) |
| 145 | row_height[k] = available_height × v[k] / sum(v) |
| 146 | ``` |
| 147 | |
| 148 | Use weighted tracks when one item is primary. A spanning item receives the sum of its tracks plus the internal gaps it crosses. |
| 149 | |
| 150 | ### 4.3 Free multi-item composition |
| 151 | |
| 152 | **Mandatory**: For montage, arc, overlap, or another non-grid arrangement, give |
| 153 | every carrier a finite center and positive size, give every intended overlap an |
| 154 | unambiguous front item, and verify the visible union against `(W,H)`. |
| 155 | |
| 156 | **Default — shared direction (may override when deliberate disorder serves the |
| 157 | communication job)**: Select one direction generator and derive related carriers |
| 158 | from shared geometry. An override still declares a bounded placement/angle rule |
| 159 | so disorder is authored rather than accidental. Use the following state: |
| 160 | |
| 161 | | State | Definition | |
| 162 | |---|---| |
| 163 | | `p[i] = (cx[i], cy[i])` | Explicit center of item `i` | |
| 164 | | `(w[i], h[i])` | Explicit positive carrier size | |
| 165 | | `s[i] > 0` | Optional shared size rhythm: `(w[i], h[i]) = s[i] × (w0, h0)` | |
| 166 | | `P` (optional) | Parent contour controlling the outer silhouette, shared seam, reveal, or attachment path | |
| 167 | | `V[i]` | Visible carrier after applying its clip and, when `P` is a silhouette, intersecting it with `P` | |
| 168 | | `z[i]` | Stacking rank required for carriers that overlap | |
| 169 | |
| 170 | For a straight shared direction `θ`, calculate centers in its local frame: |
| 171 | |
| 172 | ```text |
| 173 | d = (cos(θ), sin(θ)) |
| 174 | n = (-sin(θ), cos(θ)) |
| 175 | p[i] = p0 + t[i] × d + e[i] × n |
| 176 | ``` |
| 177 | |
| 178 | Choose `t[i]` and transverse offset `e[i]` as explicit sequences; add `s[i]` |
| 179 | when scale carries the rhythm. Reuse a progression when rhythm is intended; do |
| 180 | not substitute unrelated per-item values. |
| 181 | |
| 182 | | Generator | Executable rule | |
| 183 | |---|---| |
| 184 | | `vector` | Use the straight-frame equation with ordered `t[i]`; set `t[i+1] = t[i] + advance[i]`, where each `advance[i] > 0`. Control overlap through `advance[i]`, not an accidental negative gap. | |
| 185 | | `shared-baseline` | Choose baseline `B(t) = b + t × d`. If `r[i]` is the carrier's half-extent along `n`, place `p[i] = B(t[i]) + r[i] × n`; this keeps one carrier edge on the same baseline while sizes vary. | |
| 186 | | `curve-spine` | Choose ordered parameters `u[i]` on `C(u)` with `||C'(u[i])|| > 0`. Set `d[i] = normalize(C'(u[i]))`, `n[i] = (-d[i].y, d[i].x)`, and `p[i] = C(u[i]) + e[i] × n[i]`; at a zero derivative, use the secant between nearest distinct samples or another generator. | |
| 187 | | `panel` | Define one convex 2D quadrilateral `A,B,C,D` in consistent winding and `F(u,v) = (1-u)(1-v)A + u(1-v)B + uvC + (1-u)vD`. Split monotone `u`/`v` intervals; each cell uses its four `F` corners. | |
| 188 | |
| 189 | For each intended overlap, calculate `area(V[i] ∩ V[j]) > 0` and assign the |
| 190 | front item through `z[i]` and `z[j]`. `P` must visibly control at least one |
| 191 | listed structural role; otherwise use the selected region boundary and omit it. |
| 192 | |
| 193 | **Reference — not a constraint**: Use one of these angle mechanisms according to the selected composition: |
| 194 | |
| 195 | | Mechanism | Geometry | |
| 196 | |---|---| |
| 197 | | Clip-shape angle | Keep the bitmap upright and angle only the carrier contour or clip path. | |
| 198 | | Parent-group rotation | Build the complete arrangement first, then rotate its carriers, frames, and attached labels together around one pivot. | |
| 199 | | Tangent rotation | On `curve-spine`, rotate item `i` around `p[i]` by `atan2(d[i].y, d[i].x)` when the carriers should follow the path. | |
| 200 | |
| 201 | **Forbidden — unsupported image deformation**: Do not use shear, skew, or true perspective mapping. A `panel` is a set of 2D quadrilateral clips/crops; it does not warp the image plane. |
| 202 | |
| 203 | --- |
| 204 | |
| 205 | ## 5. Composition Checks |
| 206 | |
| 207 | | Check | Required response | |
| 208 | |---|---| |
| 209 | | Computed width or height is non-positive | Re-select the page regions or reduce gaps | |
| 210 | | Contain leaves unusable residual space | Recompose the surrounding regions; do not stretch the source | |
| 211 | | Fill removes focal or required content | Change anchor, enlarge the region, or use contain | |
| 212 | | Adjacent text/content region cannot carry its material | Reweight or change the selected relationship | |
| 213 | | Equal cells imply equality that the content does not have | Use weighted tracks or a free composition | |
| 214 | | Peer images use inconsistent visual scale without meaning | Normalize their regions or make the hierarchy explicit | |
| 215 | | A free carrier lacks an explicit center or positive size, or an intended overlap lacks stacking order | Supply the missing geometry or z-order before drawing | |
| 216 | | Items intended as one system lack both a shared direction and a deliberate-disorder rule | Derive them from one vector, baseline, curve, panel, or bounded override | |
| 217 | | Per-item angles vary without a shared direction or deliberate-disorder rule | Use one parent-group angle, a shared clip-shape direction, curve tangents, or a bounded angle rhythm | |
| 218 | | The parent contour does not affect silhouette, seam, reveal, or attachment | Remove it or reconstruct the carriers from that contour | |
| 219 | | A panel depends on shear, skew, or perspective warping | Replace it with 2D quadrilateral carriers and focal-safe crops | |
| 220 | | Gaps, alignments, or overlaps drift without purpose | Recalculate from the shared region and gap values | |
| 221 | |
| 222 | The final geometry must express the active page hierarchy, preserve the selected resource relationships, and remain valid under the conditionally loaded technical contracts. |
| 223 |