Share
Embed
Writer layout in Collabora Online
Collabora Online Team Time Trainings 2025 (https://collaboraonline.github.io/post/communicate/#tea-time-trainings)
Video record: https://www.youtube.com/watch?v=NuXKgqvc3cc
Miklos V
June 27, 2025
Transcript
27 slides
-
5 Page frame Parent: root frame Without a corresponding
model object (SwNode) These are double linked (pNext, pPrev) Contains a double linked list of SwLayoutFrames • At least a SwBodyFrame for the text content • Optional SwHeaderFrame and SwFooterFrame • Order as expected: header, body, footer -
6 Text frame Typical parent: body frame Most important
frame: SwTextFrame Layout counterpart an SwTextNode object mnOffset member refers to the m_Text of SwTextNode • Unless some redlines are hidden SwTextFrame is registered in an SwTextNode • notified in case the SwTextNode changes -
7 Frame area, frame print area It’s all about margins
Frame area • Absolute rectangle, includes the margins Frame print area • Relative rectangle, excludes the margins -
8 Layout frame Frame with children are layout frames
Normal SwFrame has no lowers Examples: body frame, table frame -
9 Flow frame Allowed to split: Derived not only
from SwFrame, but also from SwFlowFrame These are the frames that are allowed at page breaks May continue on the next page, e.g., paragraphs, tables Floating table: table in allowed-to-split fly frame • A recent addition in 2023, SwFlyAtContentFrame wasn’t an SwFlowFrame before Also used for chained fly frames -
10 Anchored objects Fly or draw An anchored object:
text frames, graphics, OLE objects and drawing objects Are anchored at a certain SwFrame, page frame or text frame SwAnchoredObject with SwFlyFrame and SwAnchoredDrawObject subclasses SwFlyFrame subclasses: SwFlyAtContentFrame for at-char, SwFlyInContentFrame for as-char Anchor frame: m_pDrawObjs stores what is anchored at here My anchor: mpAnchorFrame All fly frames are also tracked per-page (expect as-char fly frames) -
11 Layout algorithm Heavily simplified First goal: determine the
frame area and the frame print area for each frame Debugging starting points: • MakeAll(): does everything • MakePos(): just the position, not the size nor the frame print area • Format(): frame area size and the print area • Also: layout XML dump -
12 Relationship: nodes and frames Model and view SwModify:
you can register into this, used for nodes SwClient: you can listen with this SwTextNode ↔ SwTextFrame SwTableNode <-> SwTabFrame Mostly 1 node → N frames Exception: hidden redlines may result in 1 frame → N nodes • See work from Michael Stahl -
13 Creation of frames MakeFrames() at some SwNode classes
These create and insert new SwFrames into an existing layout E.g. press "ENTER" at the end of a paragraph • A new SwTextNode will be inserted into the nodes array • This new SwTextNode executes MakeFrames() • Creates SwTextFrame(s) and inserts it into the layout -
14 Table layout Table, headers, rows, cells Table frame:
may be split (table frame → SwTable) Inside: row frames (row frame → SwTableLine) Inside: cell frames (cell frame → SwTableBox) There are no columns, they are a UI-level concept in Writer -
15 Indexes and Positions Type safety pays off Paragraph
index: SwNodeOffset Inside that: character index Layout level: text frame index, TextFrameIndex • Again, important for hidden redlines -
17 Coordinate system All frames are in absolute units
Twips: 1/20th of a point Origo: top left corner of the root frame Inside a frame: frame area is also absolute Frame print area: relative position -
19 Fonts Script type adds complexity SwFont is actually
3 fonts SubSubFont is 1 font Separate for Latin, CTL and CJK script types Layout goes with the relevant font, automatically -
20 How incremental update works An example (simplified) Insert
a character: SwTextNode is modified, pings its clients SwTextFrame::SwClientNotify is called SwCharRange is constructed SwTextFrame::Format() is performed SwTextFormatter is created SwTextFormatter::BuildPortions re-creates the frame’s portions -
21 Model vs View positions Canvas coordinates ↔ paragraph numbers
SwTextFrame::GetCharRect(): twips coordinates from an SwPosition (node index, content index) • Inherently may not be perfect, think of e.g. headers SwTextFrame::GetModelPositionForViewPoint(): SwPosition from coordinates -
22 Field layout A single character, except when not
Fields are a single dummy character in the model May expand to multiple characters Cursor is always at a model position, so you can’t move your cursor inside a field, typically Accessibility still needs the position of each & every layout character • SwSpecialPos helps with this -
23 Caches A speed vs memory trade-off Is SwCache
a cache? All portions inside a text frame are in SwCache, so we limit memory usage by not storing all portions of a long document At the same time, always possible to re-create these portions Kind of a cache -
25 Layout tree navigation What wasn’t mentioned so far
Visit the tree by following the upper, lower, next and previous pointers SwFlowFrame is not an SwFrame • Follow/precede pointers there, AKA previous leaf, next leaf Split frames: first is master, everybody else is a follow -
26 Working with the layout A complex part of the
codebase Take notes as you work in a problem, otherwise you won’t solve the bug • https://people.gnome.org/~michael/data/2016-04-29-solvi ng-problems.pdf Use the layout XML dump Once the problem is fixed, always cover your fix with a test -
27 Further reading OOo wiki & in-code documentation https://web.archive.org/web/20240703103909/https://wiki.openo
ffice.org/wiki/Writer/Core_And_Layout https://web.archive.org/web/20240703234819/https://wiki.openo ffice.org/wiki/Writer/Text_Formatting Core.git sw/README.md