Gecko:Reflow Refactoring: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
Line 25: Line 25:
   cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot checkout <b>-r REFLOW_20050804_BRANCH</b> mozilla/client.mk
   cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot checkout <b>-r REFLOW_20050804_BRANCH</b> mozilla/client.mk


Using <code>client.mk</code> is essential because only layout is branched; the rest of the tree is pulled by date.
Using <code>client.mk</code> to pull the rest of the tree is essential because only layout is branched; the rest of the tree is pulled by date.


== Rationale ==
== Rationale ==

Revision as of 21:05, 5 October 2005

Summary

Reflow refactoring is the name for two related changes currently being worked on mainly by dbaron:

  • Change intrinsic width computation so that it happens in separate methods on nsIFrame. (Currently preferred with calculation using the nsIFrame API can happen in two different ways as well: having only one codepath reduces incremental layout ("{inc}") bugs.)
  • Change the way we handle incremental layout to use dirty bits on the frames rather than the reflow tree (which is essentially out-of-line dirty bits) and a complicated system of reflow reasons that often leads to weird incremental layout ("{inc}") bugs.

The goals of these changes are:

  • simplification of code
  • fixing incremental reflow ("{inc}") bugs
  • fixing intrinsic sizing bugs
  • allowing better integration of nsIBox and nsIFrame layout
  • allowing easier implementation of new features like 'inline-block'

Quick Links

Build Instructions

Follow the normal build instructions and get the source from CVS, except when checking out client.mk, use

 cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot checkout -r REFLOW_20050804_BRANCH mozilla/client.mk

Using client.mk to pull the rest of the tree is essential because only layout is branched; the rest of the tree is pulled by date.

Rationale

The goal of the branch is to change the design in two areas of layout that have given us the most problems due to their complexity. It will also help make the nsIFrame and nsIBox layout methods a little more similar.

nsIFrame and nsIBox layout

Understanding the current situation with Mozilla's rendering objects requires understanding a bit of history, since it's currently in a state that nobody really intended.

CSS sort of has a notion of a rendering tree: a tree structure that's similar to the content tree but also contains pseudo-elements and does not contain objects that are display:none. In the original Gecko codebase, the objects in the rendering tree were intended to be implementations of nsIFrame. Different implementations would be used for different types of rendering objects: for example, objects with CSS display:block (nsBlockFrame), objects with CSS display:inline (nsInlineFrame), HTML <input type="text"> or <textarea> (nsTextControlFrame), or images resulting from <img> or <object> (nsImageFrame).

When the XUL layout model was implemented, nsIFrame was found not to be suitable for the flexible box model needed for XUL. So, for better or for worse, a second interface for rendering objects came into existence: nsIBox. XUL layout objects also delegate to singleton nsIBoxLayout objects for a number of the things that differentiate different types of rendering objects.

In an effort to reduce the size of box rendering objects (which had to implement nsIFrame and nsIBox), the two rendering object interfaces have been merged into nsIFrame and the merged list of methods is on track to be gradually consolidated. Base implementations of the separate methods are still split between nsBox and nsFrame, although the latter inherits from the former. The method nsIFrame::IsBoxFrame is the way the two types of objects can currently be distinguished.

The handling of the boundary between box and non-box rendering objects is currently handled in two places: the code in nsBoxFrame and nsLeafBoxFrame handles a box inside a non-box. The box methods on nsFrame handle a non-box being inside a box (although these used to be on a separate class called nsBoxToBlockAdaptor).

Intrinsic sizing changes

Incremental layout Changes

Design

Status

Currently a lot of the design is done but subject to change. CSS block/inline layout code and XUL box layout code have been converted to the new design and work well enough that the Firefox UI basically works (although with some glitches). However, form controls and tables have not yet been converted to the new design, and are disabled on the branch.

Future Development Tasks

  • fix intrinsic sizing bug in default browser prompt (dbaron priority #1)
  • convert table code (dbaron priority #2)
  • convert form control code
    • figure out whether to refactor nsLeafFrame::GetDesiredSize and implement nsLeafFrame::GetMinWidth and nsLeafFrame::GetPrefWidth in terms of it or whether to implement GetMinWidth and GetPrefWidth separately for all the subclasses of nsLeafFrame that use GetDesiredSize
  • Figure out whether the inline min/pref width interfaces currently on the branch (nsIFrame::GetInlineMinWidth and GetInlinePrefWidth) are sufficient or whether we need to make additional architectural changes related to continuations (particularly making various special things use the existing next-in-flow model)

Future Testing Tasks

  • Make sure dbaron's existing testcases work
  • Develop testcases that test box-block boundaries better
  • Extend intrinsic sizing testcases to check that padding, border, and margin are counted correctly, especially around box-block boundaries
  • Test XUL user interfaces
  • Test Web pages