Bug 51684 suggests a number of fundamental items to evaluate prior
freezing nsIFrame for Mozilla 1.0. One such suggestion is the switch
from 'nsRect mRect' to 'nsArea mArea' in the geometric frame model.
The pros and cons of this are detailed in bug 51684. Here is a summary of
the motivations. Since the basic rectangular metrics (nsRect mRect) stored
in the frames are too limited for layout purposes, the suggestion is to
switch from nsRect mRect (defined as: struct nsRect { x, y, width, height})
to a nsArea mArea (defined as: struct nsArea { x, y, width [, height],
ascent, descent }).
Or to put literally, let the frame store its 'ascent' and 'descent' together
with its other dimensions.
(Although height = ascent + descent, the 'height' may be kept in nsArea
for convenience. Indeed, as we shall we see below, storing the extra ascent,
descent information can bring savings to the overall system. However, the
'height' could well be removed later to get additional savings).
The fact that the ascent and descent are not stored in the base frame class
has been the source of undue complications. Indeed, nearly all frame owners
have come to the realization that they need to keep track of the
ascent and descent of their frames. As a result, people cache their
aDesiredSize.ascent and/or aDesiredSize.descent from reflow, and this
means that separate getter/setter methods are needed for them.
Since (with hindsight) we now see that nearly all frames (XUL/CSS/Table/MathML)
need their ascent/descent information long after the life time of aDesiredSize
from reflow, nsArea will provide a unified way to store/retrieve the information,
thus leading to leaner/cleaner code, and saving time to developers who would
not need to devise work-around to the problem. Moreover, nsArea coincides
with the metrics used in the box model of the XSL-FO spec, and so nsArea
can be seen as a necessary building block with which to consolidate nsIFrame
to later support XSL-FO.
I have taken a first step in the switching direction by setting up
nsArea.h/nsArea.cpp (like nsRect.h/nsRect.cpp). Then, using an
'#ifdef MOZ_USE_NSAREA', I have added GetArea/SetArea in nsIFrame.h,
and made the following change in nsFrame.h :
class nsFrame : public nsIFrame
{
[...]
#ifndef MOZ_USE_NSAREA
nsRect mRect;
#else
nsArea mRect;
#endif
[...]
}
Then with related changes in nsFrame.cpp for consistency (see attachments
on bug 64763), I was able to rebuild and run the application without problems.
This worked straightaway because nsRect is a proper subset of nsArea (descent=0),
and so a direct mapping to the present code is possible. However, if the switch
has to be carried out properly, it will be necessary to rename mRect to mArea to
avoid confusions. It will also be necessary to remove the various codes that
permeate layout just because the ascent/descent are not stored in the base
frame class. The later represent where the benefits will come from.
Like string changes that have been made, this switch will require gradual
passes over the tree. Supporting both GetRect/SetRect and GetArea/SetArea
in layout, and removing the rect variants (and related work-around) when
the changes are over.
Bug 64763 has been opened to track the switch.
If folks object to the switch, could they voice their concerns so that I
don't waste further precious cycles on something that is doomed.
---
RBS