summaryrefslogtreecommitdiffstats
path: root/layout/docs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
commit8dd16259287f58f9273002717ec4d27e97127719 (patch)
tree3863e62a53829a84037444beab3abd4ed9dfc7d0 /layout/docs
parentReleasing progress-linux version 126.0.1-1~progress7.99u1. (diff)
downloadfirefox-8dd16259287f58f9273002717ec4d27e97127719.tar.xz
firefox-8dd16259287f58f9273002717ec4d27e97127719.zip
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'layout/docs')
-rw-r--r--layout/docs/DynamicChangeHandling.md83
-rw-r--r--layout/docs/LayoutOverview.md529
-rw-r--r--layout/docs/StyleSystemOverview.md173
-rw-r--r--layout/docs/index.rst14
4 files changed, 794 insertions, 5 deletions
diff --git a/layout/docs/DynamicChangeHandling.md b/layout/docs/DynamicChangeHandling.md
new file mode 100644
index 0000000000..50df613412
--- /dev/null
+++ b/layout/docs/DynamicChangeHandling.md
@@ -0,0 +1,83 @@
+# Dynamic change handling along the rendering pipeline
+
+The ability to make changes to the DOM from script is a major feature of
+the Web platform. Web authors rely on the concept (though there are a
+few exceptions, such as animations) that changing the DOM from script
+leads to the same rendering that would have resulted from starting from
+that DOM tree. They also rely on the performance characteristics of
+these changes: small changes to the DOM that have small effects should
+have proportionally small processing time. This means that Gecko needs
+to efficiently propagate changes from the content tree to style, the
+frame tree, the geometry of the frame tree, and the screen.
+
+For many types of changes, however, there is substantial overhead to
+processing a change, no matter how small. For example, reflow must
+propagate from the top of the frame tree down to the frames that are
+dirty, no matter how small the change. One very common way around this
+is to batch up changes. We batch up changes in lots of ways, for
+example:
+
+- The content sink adds multiple nodes to the DOM tree before
+ notifying listeners that they\'ve been added. This allows notifying
+ once about an ancestor rather than for each of its descendants, or
+ notifying about a group of descendants all at once, which speeds up
+ the processing of those notifications.
+- We batch up nodes that require style reresolution (recomputation of
+ selector matching and processing the resulting style changes). This
+ batching is tree based, so it not only merges multiple notifications
+ on the same element, but also merges a notification on an ancestor
+ with a notification on its descendant (since *some* of these
+ notifications imply that style reresolution is required on all
+ descendants).
+- We wait to reconstruct frames that require reconstruction (after
+ destroying frames eagerly). This, like the tree-based style
+ reresolution batching, avoids duplication both for same-element
+ notifications and ancestor-descendant notifications, even though it
+ doesn\'t actually do any tree-based caching.
+- We postpone doing reflows until needed. As for style reresolution,
+ this maintains tree-based dirty bits (see the description of
+ NS\_FRAME\_IS\_DIRTY and NS\_FRAME\_HAS\_DIRTY\_CHILDREN under
+ Reflow).
+- We allow the OS to queue up multiple invalidates before repainting
+ (though we will likely switch to controlling that ourselves). This
+ leads to a single repaint of some set of pixels where there might
+ otherwise have been multiple (though it may also lead to more pixels
+ being repainted if multiple rectangles are merged to a single one).
+
+Having changes buffered up means, however, that various pieces of
+information (layout, style, etc.) may not be up-to-date. Some things
+require up-to-date information: for example, we don\'t want to expose
+the details of our buffering to Web page script since the programming
+model of Web page script assumes that DOM changes take effect
+\"immediately\", i.e., that the script shouldn\'t be able to detect any
+buffering. Many Web pages depend on this.
+
+We therefore have ways to flush these different sorts of buffers. There
+are methods called FlushPendingNotifications on nsIDocument and
+nsIPresShell, that take an argument of what things to flush:
+
+- Flush\_Content: create all the content nodes from data buffered in
+ the parser
+- Flush\_ContentAndNotify: the above, plus notify document observers
+ about the creation of all nodes created so far
+- Flush\_Style: the above, plus make sure style data are up-to-date
+- Flush\_Frames: the above, plus make sure all frame construction has
+ happened (currently the same as Flush\_Style)
+- Flush\_InterruptibleLayout: the above, plus perform layout (Reflow),
+ but allow interrupting layout if it takes too long
+- Flush\_Layout: the above, plus ensure layout (Reflow) runs to
+ completion
+- Flush\_Display (should never be used): the above, plus ensure
+ repainting happens
+
+The major way that notifications of changes propagate from the content
+code to layout and other areas of code is through the
+nsIDocumentObserver and nsIMutationObserver interfaces. Classes can
+implement this interface to listen to notifications of changes for an
+entire document or for a subtree of the content tree.
+
+WRITE ME: \... layout document observer implementations
+
+TODO: how style system optimizes away rerunning selector matching
+
+TODO: style changes and nsChangeHint
diff --git a/layout/docs/LayoutOverview.md b/layout/docs/LayoutOverview.md
new file mode 100644
index 0000000000..0375ab5480
--- /dev/null
+++ b/layout/docs/LayoutOverview.md
@@ -0,0 +1,529 @@
+# Layout Overview
+
+Much of the layout code deals with operations on the frame tree (or
+rendering tree). In the frame tree, each node represents a rectangle
+(or, for SVG, other shapes). The frame tree has a shape similar to the
+content tree, since many content nodes have one corresponding frame,
+though it differs in a few ways, since some content nodes have more than
+one frame or don\'t have any frames at all. When elements are
+display:none in CSS or undisplayed for certain other reasons, they
+won\'t have any frames. When elements are broken across lines or pages,
+they have multiple frames; elements may also have multiple frames when
+multiple frames nested inside each other are needed to display a single
+element (for example, a table, a table cell, or many types of form
+controls).
+
+Each node in the frame tree is an instance of a class derived from
+`nsIFrame`. As with the content tree, there is a substantial type
+hierarchy, but the type hierarchy is very different: it includes types
+like text frames, blocks and inlines, the various parts of tables, flex
+and grid containers, and the various types of HTML form controls.
+
+Frames are allocated within an arena owned by the PresShell. Each frame
+is owned by its parent; frames are not reference counted, and code must
+not hold on to pointers to frames. To mitigate potential security bugs
+when pointers to destroyed frames, we use [frame
+poisoning](http://robert.ocallahan.org/2010/10/mitigating-dangling-pointer-bugs-using_15.html),
+which takes two parts. When a frame is destroyed other than at the end
+of life of the presentation, we fill its memory with a pattern
+consisting of a repeated pointer to inaccessible memory, and then put
+the memory on a per-frame-class freelist. This means that if code
+accesses the memory through a dangling pointer, it will either crash
+quickly by dereferencing the poison pattern or it will find a valid
+frame.
+
+Like the content tree, frames must be accessed only from the UI thread.
+
+The frame tree should not store any important data, i.e. any data that
+cannot be recomputed on-the-fly. While the frame tree does usually
+persist while a page is being displayed, frames are often destroyed and
+recreated in response to certain style changes, and in the future we may
+do the same to reduce memory use for pages that are currently inactive.
+There were a number of cases where this rule was violated in the past
+and we stored important data in the frame tree; however, most (though
+not quite all) such cases are now fixed.
+
+The rectangle represented by the frame is what CSS calls the element\'s
+border box. This is the outside edge of the border (or the inside edge
+of the margin). The margin lives outside the border; and the padding
+lives inside the border. In addition to nsIFrame::GetRect, we also have
+the APIs nsIFrame::GetPaddingRect to get the padding box (the outside
+edge of the padding, or inside edge of the border) and
+nsIFrame::GetContentRect to get the content box (the outside edge of the
+content, or inside edge of the padding). These APIs may produce out of
+date results when reflow is needed (or has not yet occurred).
+
+In addition to tracking a rectangle, frames also track two overflow
+areas: ink overflow and scrollable overflow. These overflow areas
+represent the union of the area needed by the frame and by all its
+descendants. The ink overflow is used for painting-related
+optimizations: it is a rectangle covering all of the area that might be
+painted when the frame and all of its descendants paint. The scrollable
+overflow represents the area that the user should be able to scroll to
+to see the frame and all of its descendants. In some cases differences
+between the frame\'s rect and its overflow happen because of descendants
+that stick out of the frame; in other cases they occur because of some
+characteristic of the frame itself. The two overflow areas are similar,
+but there are differences: for example, margins are part of scrollable
+overflow but not ink overflow, whereas text-shadows are part of ink
+overflow but not scrollable overflow.
+
+When frames are broken across lines, columns, or pages, we create
+multiple frames representing the multiple rectangles of the element. The
+first one is the primary frame, and the rest are its continuations
+(which are more likely to be destroyed and recreated during reflow).
+These frames are linked together as continuations: they have a
+doubly-linked list that can be used to traverse the continuations using
+nsIFrame::GetPrevContinuation and nsIFrame::GetNextContinuation.
+(Currently continuations always have the same style data, though we may
+at some point want to break that invariant.)
+
+Continuations are sometimes siblings of each other (i.e.
+nsIFrame::GetNextContinuation and nsIFrame::GetNextSibling might return
+the same frame), and sometimes not. For example, if a paragraph contains
+a span which contains a link, and the link is split across lines, then
+the continuations of the span are siblings (since they are both children
+of the paragraph), but the continuations of the link are not siblings
+(since each continuation of the link is descended from a different
+continuation of the span). Traversing the entire frame tree does **not**
+require explicit traversal of any frames\' continuations-list, since all
+of the continuations are descendants of the element containing the
+break.
+
+We also use continuations for cases (most importantly, bidi reordering,
+where left-to-right text and right-to-left text need to be separated
+into different continuations since they may not form a contiguous
+rectangle) where the continuations should not be rewrapped during
+reflow: we call these continuations fixed rather than fluid.
+nsIFrame::GetNextInFlow and nsIFrame::GetPrevInFlow traverse only the
+fluid continuations and do not cross fixed continuation boundaries.
+
+If an inline frame has non-inline children, then we split the original
+inline frame into parts. The original inline\'s children are distributed
+into these parts like so: The children of the original inline are
+grouped into runs of inline and non-inline, and runs of inline get an
+inline parent, while runs of non-inline get an anonymous block parent.
+We call this \'ib-splitting\' or \'block-inside-inline splitting\'. This
+splitting proceeds recursively up the frame tree until all non-inlines
+inside inlines are ancestors of a block frame with anonymous block
+wrappers in between. This splitting maintains the relative order between
+these child frames, and the relationship between the parts of a split
+inline is maintained using an ib-sibling chain. It is important to note
+that any wrappers created during frame construction (such as for tables)
+might not be included in the ib-sibling chain depending on when this
+wrapper creation takes place.
+
+TODO: nsBox craziness from
+<https://bugzilla.mozilla.org/show_bug.cgi?id=524925#c64>
+
+TODO: link to documentation of block and inline layout
+
+TODO: link to documentation of scrollframes
+
+TODO: link to documentation of XUL frame classes
+
+Code (note that most files in base and generic have useful one line
+descriptions at the top that show up in DXR):
+
+- [layout/base/](http://dxr.mozilla.org/mozilla-central/source/layout/base/)
+ contains objects that coordinate everything and a bunch of other
+ miscellaneous things
+- [layout/generic/](http://dxr.mozilla.org/mozilla-central/source/layout/generic/)
+ contains the basic frame classes as well as support code for their
+ reflow methods (ReflowInput, ReflowOutput)
+- [layout/forms/](http://dxr.mozilla.org/mozilla-central/source/layout/forms/)
+ contains frame classes for HTML form controls
+- [layout/tables/](http://dxr.mozilla.org/mozilla-central/source/layout/tables/)
+ contains frame classes for CSS/HTML tables
+- [layout/mathml/](http://dxr.mozilla.org/mozilla-central/source/layout/mathml/)
+ contains frame classes for MathML
+- [layout/svg/](http://dxr.mozilla.org/mozilla-central/source/layout/svg/)
+ contains frame classes for SVG
+- [layout/xul/](http://dxr.mozilla.org/mozilla-central/source/layout/xul/)
+ contains frame classes for the XUL box model and for various XUL
+ widgets
+
+Bugzilla:
+
+- All of the components whose names begin with \"Layout\" in the
+ \"Core\" product
+
+Further documentation:
+
+- Talk: [Introduction to graphics/layout
+ architecture](https://air.mozilla.org/introduction-to-graphics-layout-architecture/)
+ (Robert O\'Callahan, 2014-04-18)
+- Talk: [Layout and
+ Styles](https://air.mozilla.org/bz-layout-and-styles/) (Boris
+ Zbarsky, 2014-10-14)
+
+## Frame Construction
+
+Frame construction is the process of creating frames. This is done when
+styles change in ways that require frames to be created or recreated or
+when nodes are inserted into the document. The content tree and the
+frame tree don\'t have quite the same shape, and the frame construction
+process does some of the work of creating the right shape for the frame
+tree. It handles the aspects of creating the right shape that don\'t
+depend on layout information. So for example, frame construction handles
+the work needed to implement [table anonymous
+objects](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) but
+does not handle frames that need to be created when an element is broken
+across lines or pages.
+
+The basic unit of frame construction is a run of contiguous children of
+a single parent element. When asked to construct frames for such a run
+of children, the frame constructor first determines, based on the
+siblings and parent of the nodes involved, where in the frame tree the
+new frames should be inserted. Then the frame constructor walks through
+the list of content nodes involved and for each one creates a temporary
+data structure called a **frame construction item**. The frame
+construction item encapsulates various information needed to create the
+frames for the content node: its style data, some metadata about how one
+would create a frame for this node based on its namespace, tag name, and
+styles, and some data about what sort of frame will be created. This
+list of frame construction items is then analyzed to see whether
+constructing frames based on it and inserting them at the chosen
+insertion point will produce a valid frame tree. If it will not, the
+frame constructor either fixes up the list of frame construction items
+so that the resulting frame tree would be valid or throws away the list
+of frame construction items and requests the destruction and re-creation
+of the frame for the parent element so that it has a chance to create a
+list of frame construction items that it `<em>`{=html}can`</em>`{=html}
+fix up.
+
+Once the frame constructor has a list of frame construction items and an
+insertion point that would lead to a valid frame tree, it goes ahead and
+creates frames based on those items. Creation of a non-leaf frame
+recursively attempts to create frames for the children of that frame\'s
+element, so in effect frames are created in a depth-first traversal of
+the content tree.
+
+The vast majority of the code in the frame constructor, therefore, falls
+into one of these categories:
+
+- Code to determine the correct insertion point in the frame tree for
+ new frames.
+- Code to create, for a given content node, frame construction items.
+ This involves some searches through static data tables for metadata
+ about the frame to be created.
+- Code to analyze the list of frame construction items.
+- Code to fix up the list of frame construction items.
+- Code to create frames from frame construction items.
+
+Code:
+[layout/base/nsCSSFrameConstructor.h](http://dxr.mozilla.org/mozilla-central/source/layout/base/nsCSSFrameConstructor.h)
+and
+[layout/base/nsCSSFrameConstructor.cpp](http://dxr.mozilla.org/mozilla-central/source/layout/base/nsCSSFrameConstructor.cpp)
+
+## Physical Sizes vs. Logical Sizes
+
+TODO: Discuss inline-size (typically width) and block size (typically
+height), writing modes, and the various logical vs. physical size/rect
+types.
+
+## Reflow
+
+Reflow is the process of computing the positions and sizes of frames.
+(After all, frames represent rectangles, and at some point we need to
+figure out exactly \*what\* rectangle.) Reflow is done recursively, with
+each frame\'s Reflow method calling the Reflow methods on that frame\'s
+descendants.
+
+In many cases, the correct results are defined by CSS specifications
+(particularly [CSS 2.1](http://www.w3.org/TR/CSS21/visudet.html)). In
+some cases, the details are not defined by CSS, though in some (but not
+all) of those cases we are constrained by Web compatibility. When the
+details are defined by CSS, however, the code to compute the layout is
+generally structured somewhat differently from the way it is described
+in the CSS specifications, since the CSS specifications are generally
+written in terms of constraints, whereas our layout code consists of
+algorithms optimized for incremental recomputation.
+
+The reflow generally starts from the root of the frame tree, though some
+other types of frame can act as \"reflow roots\" and start a reflow from
+them (nsTextControlFrame is one example; see the
+[NS\_FRAME\_REFLOW\_ROOT](https://searchfox.org/mozilla-central/search?q=symbol:E_%3CT_nsFrameState%3E_NS_FRAME_REFLOW_ROOT&redirect=true)
+frame state bit). Reflow roots must obey the invariant that a change
+inside one of their descendants never changes their rect or overflow
+areas (though currently scrollbars are reflow roots but don\'t quite
+obey this invariant).
+
+In many cases, we want to reflow a part of the frame tree, and we want
+this reflow to be efficient. For example, when content is added or
+removed from the document tree or when styles change, we want the amount
+of work we need to redo to be proportional to the amount of content. We
+also want to efficiently handle a series of changes to the same content.
+
+To do this, we maintain two bits on frames:
+[NS\_FRAME\_IS\_DIRTY](https://searchfox.org/mozilla-central/search?q=symbol:E_%3CT_nsFrameState%3E_NS_FRAME_IS_DIRTY&redirect=true)
+indicates that a frame and all of its descendants require reflow.
+[NS\_FRAME\_HAS\_DIRTY\_CHILDREN](https://searchfox.org/mozilla-central/search?q=symbol:E_%3CT_nsFrameState%3E_NS_FRAME_HAS_DIRTY_CHILDREN&redirect=true)
+indicates that a frame has a descendant that is dirty or has had a
+descendant removed (i.e., that it has a child that has
+NS\_FRAME\_IS\_DIRTY or NS\_FRAME\_HAS\_DIRTY\_CHILDREN or it had a
+child removed). These bits allow coalescing of multiple updates; this
+coalescing is done in PresShell, which tracks the set of reflow roots
+that require reflow. The bits are set during calls to
+[PresShell::FrameNeedsReflow](https://searchfox.org/mozilla-central/search?q=PresShell%3A%3AFrameNeedsReflow&path=)
+and are cleared during reflow.
+
+The layout algorithms used by many of the frame classes are those
+specified in CSS, which are based on the traditional document formatting
+model, where widths are input and heights are output.
+
+In some cases, however, widths need to be determined based on the
+content. This depends on two *intrinsic widths*: the minimum intrinsic
+width (see
+[nsIFrame::GetMinISize](https://searchfox.org/mozilla-central/search?q=nsIFrame%3A%3AGetMinISize&path=))
+and the preferred intrinsic width (see
+[nsIFrame::GetPrefISize](https://searchfox.org/mozilla-central/search?q=nsIFrame%3A%3AGetPrefISize&path=)).
+The concept of what these widths represent is best explained by
+describing what they are on a paragraph containing only text: in such a
+paragraph the minimum intrinsic width is the width of the longest word,
+and the preferred intrinsic width is the width of the entire paragraph
+laid out on one line.
+
+Intrinsic widths are invalidated separately from the dirty bits
+described above. When a caller informs the pres shell that a frame needs
+reflow (PresShell::FrameNeedsReflow), it passes one of three options:
+
+- eResize indicates that no intrinsic widths are dirty
+- eTreeChange indicates that intrinsic widths on it and its ancestors
+ are dirty (which happens, for example, if new children are added to
+ it)
+- eStyleChange indicates that intrinsic widths on it, its ancestors,
+ and its descendants are dirty (for example, if the font-size
+ changes)
+
+Reflow is the area where the XUL frame classes (those that inherit from
+nsBoxFrame or nsLeafBoxFrame) are most different from the rest. Instead
+of using nsIFrame::Reflow, they do their layout computations using
+intrinsic size methods called GetMinSize, GetPrefSize, and GetMaxSize
+(which report intrinsic sizes in two dimensions) and a final layout
+method called Layout. In many cases these methods defer some of the
+computation to a separate object called a layout manager.
+
+When an individual frame\'s Reflow method is called, most of the input
+is provided on an object called ReflowInput and the output is filled in
+to an object called ReflowOutput. After reflow, the caller (usually the
+parent) is responsible for setting the frame\'s size based on the
+metrics reported. (This can make some computations during reflow
+difficult, since the new size is found in either the reflow state or the
+metrics, but the frame\'s size is still the old size. However, it\'s
+useful for invalidating the correct areas that need to be repainted.)
+
+One major difference worth noting is that in XUL layout, the size of the
+child is set prior to its parent calling its Layout method. (Once
+invalidation uses display lists and is no longer tangled up in Reflow,
+it may be worth switching non-XUL layout to work this way as well.)
+
+## Painting
+
+TODO: display lists (and event handling)
+
+TODO: layers
+
+## Pagination
+
+Pagination (also known as fragmentation) is a concept used in printing,
+print-preview, and multicolumn layout.
+
+### Continuations in the Frame Tree
+
+To render a DOM node, represented as `nsIContent` object, Gecko creates
+zero or more frames (`nsIFrame` objects). Each frame represents a
+rectangular area usually corresponding to the node\'s CSS box as
+described by the CSS specs. Simple elements are often representable with
+exactly one frame, but sometimes an element needs to be represented with
+more than one frame. For example, text breaking across lines:
+
+ xxxxxx AAAA
+ AAA xxxxxxx
+
+The A element is a single DOM node but obviously a single rectangular
+frame isn\'t going to represent its layout precisely.
+
+Similarly, consider text breaking across pages:
+
+ | BBBBBBBBBB |
+ | BBBBBBBBBB |
+ +------------+
+
+ +------------+
+ | BBBBBBBBBB |
+ | BBBBBBBBBB |
+ | |
+
+Again, a single rectangular frame cannot represent the layout of the
+node. Columns are similar.
+
+Another case where a single DOM node is represented by multiple frames
+is when a text node contains bidirectional text (e.g. both Hebrew and
+English text). In this case, the text node and its inline ancestors are
+split so that each frame contains only unidirectional text.
+
+The first frame for an element is called the **primary frame**. The
+other frames are called **continuation frames**. Primary frames are
+created by `nsCSSFrameConstructor` in response to content insertion
+notifications. Continuation frames are created during bidi resolution,
+and during reflow, when reflow detects that a content element cannot be
+fully laid out within the constraints assigned (e.g., when inline text
+will not fit within a particular width constraint, or when a block
+cannot be laid out within a particular height constraint).
+
+Continuation frames created during reflow are called \"fluid\"
+continuations (or \"in-flows\"). Other continuation frames (currently,
+those created during bidi resolution), are, in contrast, \"non-fluid\".
+The `NS_FRAME_IS_FLUID_CONTINUATION` state bit indicates whether a
+continuation frame is fluid or not.
+
+The frames for an element are put in a doubly-linked list. The links are
+accessible via `nsIFrame::GetNextContinuation` and
+`nsIFrame::GetPrevContinuation`. If only fluid continuations are to be
+accessed, `nsIFrame::GetNextInFlow` and `nsIFrame::GetPrevInFlow` are
+used instead.
+
+The following diagram shows the relationship between the original frame
+tree considering just primary frames, and a possible layout with
+breaking and continuations:
+
+ Original frame tree Frame tree with A broken into three parts
+ Root Root
+ | / | \
+ A A1 A2 A3
+ / \ / | | |
+ B C B C1 C2 C3
+ | /|\ | | | \ |
+ D E F G D E F G1 G2
+
+Certain kinds of frames create multiple child frames for the same
+content element:
+
+- `nsPageSequenceFrame` creates multiple page children, each one
+ associated with the entire document, separated by page breaks
+- `nsColumnSetFrame` creates multiple block children, each one
+ associated with the column element, separated by column breaks
+- `nsBlockFrame` creates multiple inline children, each one associated
+ with the same inline element, separated by line breaks, or by
+ changes in text direction
+- `nsTableColFrame` creates non-fluid continuations for itself if it
+ has span=\"N\" and N \> 1
+- If a block frame is a multi-column container and has
+ `column-span:all` children, it creates multiple `nsColumnSetFrame`
+ children, which are linked together as non-fluid continuations.
+ Similarly, if a block frame is within a multi-column formatting
+ context and has `column-span:all` children, it is chopped into
+ several flows, which are linked together as non-fluid continuations
+ as well. See documentation and example frame trees in
+ [`nsCSSFrameConstructor::ConstructBlock()`](https://searchfox.org/mozilla-central/rev/d24696b5abaf9fb75f7985952eab50d5f4ed52ac/layout/base/nsCSSFrameConstructor.cpp#10431).
+
+#### Overflow Container Continuations
+
+Sometimes the content of a frame needs to break across pages even though
+the frame itself is complete. This usually happens if an element with
+fixed height has overflow that doesn\'t fit on one page. In this case,
+the completed frame is \"overflow incomplete\", and special
+continuations are created to hold its overflow. These continuations are
+called \"overflow containers\". They are invisible, and are kept on a
+special list in their parent. See documentation in
+[nsContainerFrame.h](https://searchfox.org/mozilla-central/source/layout/generic/nsContainerFrame.h)
+and example trees in [bug 379349 comment
+3](https://bugzilla.mozilla.org/show_bug.cgi?id=379349#c3).
+
+This infrastructure was extended in [bug
+154892](https://bugzilla.mozilla.org/show_bug.cgi?id=154892) to also
+manage continuations for absolutely-positioned frames.
+
+#### Relationship of continuations to frame tree structure
+
+It is worth emphasizing two points about the relationship of the
+prev-continuation / next-continuation linkage to the existing frame tree
+structure.
+
+First, if you want to traverse the frame tree or a subtree thereof to
+examine all the frames once, you do `<em>`{=html}not`</em>`{=html} want
+to traverse next-continuation links. All continuations are reachable by
+traversing the `GetNextSibling` links from the result of `GetFirstChild`
+for all child lists.
+
+Second, the following property holds:
+
+- Consider two frames F1 and F2 where F1\'s next-continuation is F2
+ and their respective parent frames are P1 and P2. Then either P1\'s
+ next continuation is P2, or P1 == P2, because P is responsible for
+ breaking F1 and F2.
+
+In other words, continuations are sometimes siblings of each other, and
+sometimes not. If their parent content was broken at the same point,
+then they are not siblings, since they are children of different
+continuations of the parent. So in the frame tree for the markup
+
+` <p>This is <b><i>some <br/>text</i></b>.</p>`
+
+the two continuations for the `b` element are siblings (unless the line
+break is also a page break), but the two continuations for the `i`
+element are not.
+
+There is an exception to that property when F1 is a first-in-flow float
+placeholder. In that case F2\'s parent will be the next-in-flow of F1\'s
+containing block.
+
+### Reflow statuses
+
+The aStatus argument of Reflow reflects that. `IsComplete()` means that
+we reflowed all the content and no more next-in-flows are needed. At
+that point there may still be next in flows, but the parent will delete
+them. `IsIncomplete()` means \"some content did not fit in this frame\".
+`IsOverflowIncomplete()` means that the frame is itself complete, but
+some of its content didn\'t fit: this triggers the creation of overflow
+containers for the frame\'s continuations. `IsIncomplete()` and
+`NextInFlowNeedsReflow()` means \"some content did not fit in this frame
+AND it must be reflowed\". These values are defined and documented in
+[nsIFrame.h](https://searchfox.org/mozilla-central/source/layout/generic/nsIFrame.h)
+(search for \"Reflow status\").
+
+### Dynamic Reflow Considerations
+
+When we reflow a frame F with fluid continuations, two things can
+happen:
+
+- Some child frames do not fit in the passed-in width or height
+ constraint. These frames must be \"pushed\" to F\'s next-in-flow. If
+ F has no next-in-flow, we must create one under F\'s parent\'s
+ next-in-flow \-\-- or if F\'s parent is managing the breaking of F,
+ then we create F\'s next in flow directly under F\'s parent. If F is
+ a block, it pushes overflowing child frames to its \"overflow\"
+ child list and forces F\'s next in flow to be reflowed. When we
+ reflow a block, we pull the child frames from the prev-in-flow\'s
+ overflow list into the current frame.
+- All child frames fit in the passed-in width or height constraint.
+ Then child frames must be \"pulled\" from F\'s next-in-flow to fill
+ in the available space. If F\'s next-in-flow becomes empty, we may
+ be able to delete it.
+
+In both of these situations we might end up with a frame F containing
+two child frames, one of which is a continuation of the other. This is
+incorrect. We might also create holes, where there are frames P1 P2 and
+P3, P1 has child F1 and P3 has child F2, but P2 has no F child.
+
+A strategy for avoiding these issues is this: When pulling a frame F2
+from parent P2 to prev-in-flow P1, if F2 is a breakable container, then:
+
+- If F2 has no prev-in-flow F1 in P1, then create a new primary frame
+ F1 in P1 for F2\'s content, with F2 as its next-in-flow.
+- Pull children from F2 to F1 until F2 is empty or we run out of
+ space. If F2 goes empty, pull from the next non-empty next-in-flow.
+ Empty continuations with no next-in-flows can be deleted.
+
+When pushing a frame F1 from parent P1 to P2, where F1 has a
+next-in-flow F2 (which must be a child of P2):
+
+- Merge F2 into F1 by moving all F2\'s children into F1, then deleting
+ F2
+
+For inline frames F, we have our own custom strategy that coalesces
+adjacent inline frames. This need not change.
+
+We do need to implement this strategy when F is a normal in-flow block,
+a floating block, and eventually an absolutely positioned block.
diff --git a/layout/docs/StyleSystemOverview.md b/layout/docs/StyleSystemOverview.md
new file mode 100644
index 0000000000..bed5fd057f
--- /dev/null
+++ b/layout/docs/StyleSystemOverview.md
@@ -0,0 +1,173 @@
+# Style System Overview
+
+## Quantum CSS (Stylo)
+
+Starting with Firefox 57 and later, Gecko makes use of the parallel
+style system written in Rust that comes from Servo. There\'s an
+[overview](https://hacks.mozilla.org/2017/08/inside-a-super-fast-css-engine-quantum-css-aka-stylo/)
+of this with graphics to help explain what\'s going on. The [Servo
+wiki](https://github.com/servo/servo/wiki/Layout-Overview) has some more
+details.
+
+## Gecko
+
+The rest of the style section section describes the Gecko style system
+used in Firefox 56 and earlier. Some bits may still apply, but it likely
+needs revising.
+
+In order to display the content, Gecko needs to compute the styles
+relevant to each DOM node. It does this based on the model described in
+the CSS specifications: this model applies to style specified in CSS
+(e.g. by a \'style\' element, an \'xml-stylesheet\' processing
+instruction or a \'style\' attribute), style specified by presentation
+attributes, and the default style specified by our own user agent style
+sheets. There are two major sets of data structures within the style
+system:
+
+- first, data structures that represent sources of style data, such as
+ CSS style sheets or data from stylistic HTML attributes
+- second, data structures that represent computed style for a given
+ DOM node.
+
+These sets of data structures are mostly distinct (for example, they
+store values in different ways).
+
+The loading of CSS style sheets from the network is managed by the [CSS
+loader](https://dxr.mozilla.org/mozilla-central/source/layout/style/Loader.h);
+they are then tokenized by the [CSS
+scanner](https://dxr.mozilla.org/mozilla-central/source/layout/style/nsCSSScanner.h)
+and parsed by the [CSS
+parser](https://dxr.mozilla.org/mozilla-central/source/layout/style/nsCSSParser.h).
+Those that are attached to the document also expose APIs to script that
+are known as the CSS Object Model, or CSSOM.
+
+The style sheets that apply to a document are managed by a class called
+the [style
+set](https://dxr.mozilla.org/mozilla-central/source/layout/style/nsStyleSet.h).
+The style set interacts with the different types of style sheets
+(representing CSS style sheets, presentational attributes, and \'style\'
+attributes) through two interfaces:
+[nsIStyleSheet](http://dxr.mozilla.org/mozilla-central/source/layout/style/nsIStyleSheet.h)
+for basic management of style sheets and
+[nsIStyleRuleProcessor](http://dxr.mozilla.org/mozilla-central/source/layout/style/nsIStyleRuleProcessor.h)
+for getting the style data out of them. Usually the same object
+implements both interfaces, except in the most important case, CSS style
+sheets, where there is a single rule processor for all of the CSS style
+sheets in each origin (user/UA/author) of the CSS cascade.
+
+The computed style data for an element/frame are exposed to the rest of
+Gecko through the class mozilla::ComputedStyle (previously called
+nsStyleContext). Rather than having a member variable for each CSS
+property, it breaks up the properties into groups of related properties
+called style structs. These style structs obey the rule that all of the
+properties in a single struct either inherit by default (what the CSS
+specifications call \"Inherited: yes\" in the definition of properties;
+we call these inherited structs) or all are not inherited by default (we
+call these reset structs). Separating the properties in this way
+improves the ability to share the structs between similar ComputedStyle
+objects and reduce the amount of memory needed to store the style data.
+The ComputedStyle API exposes a method for getting each struct, so
+you\'ll see code like `sc->GetStyleText()->mTextAlign` for getting the
+value of the text-align CSS property. (Frames (see the Layout section
+below) also have the same GetStyle\* methods, which just forward the
+call to the frame\'s ComputedStyle.)
+
+The ComputedStyles form a tree structure, in a shape somewhat like the
+content tree (except that we coalesce identical sibling ComputedStyles
+rather than keeping two of them around; if the parents have been
+coalesced then this can apply recursively and coalasce cousins, etc.; we
+do not coalesce parent/child ComputedStyles). The parent of a
+ComputedStyle has the style data that the ComputedStyle inherits from
+when CSS inheritance occurs. This means that the parent of the
+ComputedStyle for a DOM element is generally the ComputedStyle for that
+DOM element\'s parent, since that\'s how CSS says inheritance works.
+
+The process of turning the style sheets into computed style data goes
+through three main steps, the first two of which closely relate to the
+[nsIStyleRule](http://dxr.mozilla.org/mozilla-central/source/layout/style/nsIStyleRule.h)
+interface, which represents an immutable source of style data,
+conceptually representing (and for CSS style rules, directly storing) a
+set of property:value pairs. (It is similar to the idea of a CSS style
+rule, except that it is immutable; this immutability allows for
+significant optimization. When a CSS style rule is changed through
+script, we create a new style rule.)
+
+The first step of going from style sheets to computed style data is
+finding the ordered sequence of style rules that apply to an element.
+The order represents which rules override which other rules: if two
+rules have a value for the same property, the higher ranking one wins.
+(Note that there\'s another difference from CSS style rules:
+declarations with !important are represented using a separate style
+rule.) This is done by calling one of the
+nsIStyleRuleProcessor::RulesMatching methods. The ordered sequence is
+stored in a [trie](http://en.wikipedia.org/wiki/Trie) called the rule
+tree: the path from the root of the rule tree to any (leaf or non-leaf)
+node in the rule tree represents a sequence of rules, with the highest
+ranking farthest from the root. Each rule node (except for the root) has
+a pointer to a rule, but since a rule may appear in many sequences,
+there are sometimes many rule nodes pointing to the same rule. Once we
+have this list we create a ComputedStyle (or find an appropriate
+existing sibling) with the correct parent pointer (for inheritance) and
+rule node pointer (for the list of rules), and a few other pieces of
+information (like the pseudo-element).
+
+The second step of going from style sheets to computed style data is
+getting the winning property:value pairs from the rules. (This only
+provides property:value pairs for some of the properties; the remaining
+properties will fall back to inheritance or to their initial values
+depending on whether the property is inherited by default.) We do this
+step (and the third) for each style struct, the first time it is needed.
+This is done in nsRuleNode::WalkRuleTree, where we ask each style rule
+to fill in its property:value pairs by calling its MapRuleInfoInto
+function. When called, the rule fills in only those pairs that haven\'t
+been filled in already, since we\'re calling from the highest priority
+rule to the lowest (since in many cases this allows us to stop before
+going through the whole list, or to do partial computation that just
+adds to data cached higher in the rule tree).
+
+The third step of going from style sheets to computed style data (which
+various caching optimizations allow us to skip in many cases) is
+actually doing the computation; this generally means we transform the
+style data into the data type described in the \"Computed Value\" line
+in the property\'s definition in the CSS specifications. This
+transformation happens in functions called nsRuleNode::Compute\*Data,
+where the \* in the middle represents the name of the style struct. This
+is where the transformation from the style sheet value storage format to
+the computed value storage format happens.
+
+Once we have the computed style data, we then store it: if a style
+struct in the computed style data doesn\'t depend on inherited values or
+on data from other style structs, then we can cache it in the rule tree
+(and then reuse it, without recomputing it, for any ComputedStyles
+pointing to that rule node). Otherwise, we store it on the ComputedStyle
+(in which case it may be shared with the ComputedStyle\'s descendant
+ComputedStyles). This is where keeping inherited and non-inherited
+properties separate is useful: in the common case of relatively few
+properties being specified, we can generally cache the non-inherited
+structs in the rule tree, and we can generally share the inherited
+structs up and down the ComputedStyle tree.
+
+The ownership models in style sheet structures are a mix of reference
+counted structures (for things accessible from script) and directly
+owned structures. ComputedStyles are reference counted, and own their
+parents (from which they inherit), and rule nodes are garbage collected
+with a simple mark and sweep collector (which often never needs to run).
+
+- code:
+ [layout/style/](http://dxr.mozilla.org/mozilla-central/source/layout/style/),
+ where most files have useful one line descriptions at the top that
+ show up in DXR
+- Bugzilla: Style System (CSS)
+- specifications
+ - [CSS 2.1](http://www.w3.org/TR/CSS21/)
+ - [CSS 2010, listing stable css3
+ modules](http://www.w3.org/TR/css-2010/)
+ - [CSS WG editors drafts](http://dev.w3.org/csswg/) (often more
+ current, but sometimes more unstable than the drafts on the
+ technical reports page)
+ - [Preventing attacks on a user\'s history through CSS :visited
+ selectors](http://dbaron.org/mozilla/visited-privacy)
+- documentation
+ - [style system
+ documentation](http://www-archive.mozilla.org/newlayout/doc/style-system.html)
+ (somewhat out of date)
diff --git a/layout/docs/index.rst b/layout/docs/index.rst
index 16d9df8b05..39455a1075 100644
--- a/layout/docs/index.rst
+++ b/layout/docs/index.rst
@@ -1,8 +1,9 @@
-Layout & CSS
-============
+Style system (CSS) & Layout
+===========================
-Here contains design documents for the Gecko's style system and layout engine.
-They live in the mozilla-central repository under layout/docs directory.
+Here contains the overview and design documents for Firefox's layout engine and
+style system. They live in the mozilla-central repository under `layout/docs
+<https://searchfox.org/mozilla-central/source/layout/docs>`__ directory.
`Layout page <https://wiki.mozilla.org/Platform/Layout>`__ on mozilla wiki
contains general information about layout and the layout team at Mozilla.
@@ -10,6 +11,9 @@ contains general information about layout and the layout team at Mozilla.
.. toctree::
:maxdepth: 1
- AccessibleCaret
+ StyleSystemOverview
+ LayoutOverview
+ DynamicChangeHandling
Reftest
LayoutDebugger
+ AccessibleCaret