mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-29 12:57:09 -06:00
* DOCX: read every VML shape in a `w:pict`, and a `v:group`'s members (#1643) `read_vml` took `pict.els().find(..)`, the first `v:*` child that is not a `v:shapetype`, and read only that one. So a `w:pict` holding several shapes kept the first and dropped the rest, and a `v:group` was read as a single shape -- or, with no text box in it, as nothing at all -- losing every member. Both are gone after a save, since saving writes the model back as DrawingML. Read all of them instead: - `read_vml_all` walks every `v:*` child of a `w:pict` and emits one object each; `read_vml` keeps returning the first for the two places that show a single drawing (an OLE object's picture, a `mc:Fallback` preview). - a `v:group` becomes an `InlineObject::Group`, its members mapped from the space `coordsize`/`coordorigin` give it onto the group's own box, nested groups flattened into it -- what `group_members` already does for a DrawingML `wpg:wgp`, so the model, the renderer and the writer need no change. Nesting is bounded at `MAX_VML_GROUP_DEPTH`, members at `MAX_GROUP_CHILDREN`. - `read_vml_shape` is the old per-shape body, taking the group's scale so a member's `width`/`height` (and a `v:line`'s `from`/`to`) come through in the group's coordinates. `boxes()` in the text-box tests now asks for `text_boxes()` rather than `text_box()`, which only reports an object that is itself a box and so could not see one inside a group; its assertions are unchanged. * DOCX: cover a `v:group` holding several text boxes (#1643) @KNUFFIXX reported the same loss from the other end: an inline `v:group` with two `_x0000_t202` boxes side by side came through a convert as box A only, in both a tall-B and a too-short-B variant, against Word reading both. A text box is the one member a group used to keep -- `vml_textbox` recurses to the first box that has content -- so this case looked half-working rather than broken, and it is worth pinning separately from the shape cases. On `main` the group collapses to a single `Shape { kind: TextBox, w: 400, h: 100 }` wearing the group's own size and holding box A's story; here both boxes read, keep their own stories and positions, and survive a save. Built in code from the reported fixture rather than committing the .docx. * DOCX: cover the shapetype lookup for a group's member (#1643) Word writes each `v:shapetype` once, at its first use, as a child of the `w:pict` -- so a group's member refers to one that is its parent's sibling, not its own. Reading all shapes means `read_vml_shape` is now called for a member as well as for a top-level shape, and both need the picture to find it, which is why `pict` is threaded through the group walk. Two tests: a member with no geometry and no colours of its own, taking its diamond from the shapetype's `o:spt` and its fill from its `fillcolor`, and the same for a shape outside a group, which is the case the lookup was written for.