Repository navigation
#3976 - PNG/SVG: draw brackets and labels of copolymers, components, mixtures and formulations #4053
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
konstantin-mordovskih
wants to merge
9
commits into
master
Choose a base branch
from
3976-render-sgroup-brackets
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
#3976 - PNG/SVG: draw brackets and labels of copolymers, components, mixtures and formulations #4053
Changes from 8 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
630c981
#3976: Draw brackets and labels of bracketed S-groups in PNG and SVG
konstantin-mordovskih 90fd838
#3976: Update memory bank for S-group rendering
konstantin-mordovskih ddbfbba
#3976: Use the rendering label mode for missing brackets and fix stal…
konstantin-mordovskih 5d55bd6
Merge branch 'master' into 3976-render-sgroup-brackets
konstantin-mordovskih efc9405
Merge branch 'master' into 3976-render-sgroup-brackets
konstantin-mordovskih 49a02a5
#3976: Read the data field name through textOf and pin the unnamed case
konstantin-mordovskih 658b709
#3976: Format the SGroupCanvas constructor for clang-format
konstantin-mordovskih 9db6ad5
#3976: Update Windows references of repeating unit and multiple group…
konstantin-mordovskih c384ff2
#3976: Address the review of S-group brackets rendering
konstantin-mordovskih File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| # S-groups are drawn by one renderer class per type over a shared default | ||
|
|
||
| **Date:** 2026-11-10 · **Status:** Accepted · **Ticket:** #3976 | ||
|
|
||
| ## Context | ||
|
|
||
| `MoleculeRenderInternal::_initSGroups` was one function with a branch per S-group type. Each branch computed | ||
| brackets, hooks and the label position with its own arithmetic, the label went to the bracket written last, | ||
| and the copolymer, component, mixture and formulation types had no branch at all. The ticket adds the drawing | ||
| of those four types and changes the rules for the rest: hooks of a fixed length towards the atoms, the label | ||
| at the lower end of the closing bracket found by position, the repeat pattern at its upper end. The team lead | ||
| asked for a structure in which a parent class draws by default and a type with a custom drawing overrides it. | ||
|
|
||
| ## Decision | ||
|
|
||
| A `SGroupRenderer` base class draws an S-group by the rules of the ticket. One subclass per drawn type | ||
| overrides only what differs: the label text, the repeat pattern, the source of the brackets, the hook length, | ||
| the label offset and placement, or the whole drawing for data S-groups. A factory maps the type to its class | ||
| and returns nothing for a type that is not drawn. The drawers see the molecule drawing through `SGroupCanvas` | ||
| and never through `MoleculeRenderInternal`; the rules that read a bracket on the page (closing bracket, ends, | ||
| hook side) live in `SGroupBrackets`, in page coordinates. | ||
|
|
||
| The renderer places no brackets of its own for bracketed groups: a group that arrives without brackets gets | ||
| them from the layout's `SGroupLayout`, run on the renderer's copy of the molecule. | ||
|
|
||
| ## Alternatives considered | ||
|
|
||
| - Keep the single function and add four branches. Rejected: the label and hook arithmetic would exist in nine | ||
| copies, and the lead asked for the class structure. | ||
| - One class with a label table for the types that differ only by their label text (component, mixture, | ||
| formulation). Rejected for uniformity: a subclass per type is a few lines, and a custom drawing for any type | ||
| stays a one-step change. | ||
| - Brackets for groups without them by the renderer's former rule, a pair three line widths outside the atom | ||
| labels. Rejected: the ticket requires the layout's rules, so that a structure looks the same whether its | ||
| brackets were placed on load or at drawing time. | ||
|
|
||
| ## Consequences | ||
|
|
||
| - A new drawn type is a subclass and a line in the factory; a change to the common rules is one place. | ||
| - The order and direction of brackets in a file no longer matter to the picture; invariant A12 is now a | ||
| writing convention. | ||
| - The former drawing of generic groups and superatoms is preserved through overrides, and a change to the base | ||
| must keep them as they are. | ||
| - Rendering a molecule with a bracketed group without brackets copies the molecule, as contracted superatoms | ||
| already did. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| # Brackets and labels of S-groups in a picture | ||
|
|
||
| > **Read when:** a ticket is about how an S-group looks in PNG, SVG, PDF or EMF: its brackets, their hooks, its | ||
| > label or its repeat pattern. | ||
| > **Skip when:** the question is where the brackets stand in the structure: that is | ||
| > [sgroup-brackets.md](./sgroup-brackets.md). | ||
|
|
||
| Verified on 2026-11-10. Ticket #3976, under the polymer epic #3971. | ||
|
|
||
| ## Problem | ||
|
|
||
| A picture showed the brackets and the label of repeating units, multiple groups, superatoms and generic groups | ||
| only. A copolymer, a component, a mixture or a formulation had its brackets in the file and nothing in the | ||
| picture: a block copolymer of two repeating units showed the two inner pairs with `n` and nothing around them. | ||
| A structure without bracket coordinates got a pair placed by rules of the renderer's own, not those of the | ||
| layout, and the hooks of a bracket grew with its length. | ||
|
|
||
| ## Interface | ||
|
|
||
| Nothing to call: every rendering of a molecule or a reaction, in every output format, with no option. | ||
|
|
||
| ## Expected behaviour | ||
|
|
||
| **When** a bracketed S-group (repeating unit, copolymer, component, mixture, formulation) has brackets, **then** | ||
| they are drawn where they are, in any direction; a zero-length bracket is not drawn. | ||
|
|
||
| **When** such a group has no brackets, or only zero-length ones (CDX, CDXML, CXSMILES, a structure built through | ||
| the API), **then** it is drawn with brackets placed by the rules of [sgroup-brackets.md](./sgroup-brackets.md), | ||
| at the default font and in the label mode of the rendering; the structure itself is not changed. | ||
|
|
||
| **When** a bracket of a bracketed group or of a multiple group is drawn, **then** its hooks are 0.15 bond lengths | ||
| long, perpendicular to the bracket and turned towards the centre of the group's atoms. The hooks of generic | ||
| groups and superatoms stay 0.15 of the bracket's length, as before. | ||
|
|
||
| **When** a group has a label, **then** it stands at the lower end of the closing bracket: its top edge level | ||
| with that end, its left edge 0.05 bond lengths right of the bracket, horizontal whatever the bracket's direction. | ||
| The closing bracket is the rightmost one by its middle, of brackets one above the other the lower one; the lower | ||
| end is the one lower on the page, of a horizontal bracket its left end. This holds for brackets stored in any | ||
| order, swapped in the file or turned with the molecule. The labels: a repeating unit its label from the file or | ||
| `n`; a copolymer `co`, or `alt`, `ran`, `blk` by its subtype; a component `c`, or `cN` by its order; a mixture | ||
| `mix`; a formulation `f`; a multiple group its multiplier. A superatom's label stays where it was: its bottom | ||
| edge level with the lower end, a line width right of the bracket. A generic group has no label. | ||
|
|
||
| **When** a repeating unit or a copolymer has a repeat pattern other than head-to-tail, **then** `hh` | ||
| (head-to-head) or `eu` (either, unknown, or not set) stands at the upper end of the closing bracket: its bottom | ||
| edge level with that end, the same offset to the right. | ||
|
|
||
| **When** groups are nested, **then** all of them are drawn. Labels and repeat patterns do not move to make room: | ||
| they may overlap the bracket of a parent or of a neighbouring group. | ||
|
|
||
| **When** a data S-group has a value, **then** it is drawn where its position says, as before. A relative value | ||
| without atoms of its own, whose parents give it no frame, is not drawn; before this change it had no position | ||
| and was not visible either. | ||
|
|
||
| ## Guarantees | ||
|
|
||
| Deterministic for given coordinates; the same drawing in PNG, SVG, PDF and EMF. The forty structures of the | ||
| ticket are pinned as SVG in the integration harness, one reference for the CI platforms, since the glyphs come from | ||
| the font built into the renderer; an ARM Mac differs in the sixth decimal of the coordinates. | ||
|
|
||
| ## Limitations | ||
|
|
||
| - A repeating unit of one atom without a label has brackets 0.2 bond lengths apart, so their hooks overlap. | ||
| - Nothing keeps a label clear of the bracket of a neighbouring group, or a bracket clear of a label standing | ||
| within its margin. | ||
| - Brackets placed by the renderer for a group without them use the default font, not `render-font-size`. | ||
| - A generic or multiple group whose file has fewer than two real brackets gets the renderer's own pair, three | ||
| line widths outside its atom labels, as before. | ||
| - The picture of an unnamed superatom no longer reserves room for its empty label, so it is a little smaller | ||
| than before. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.