This also fixes the C++ side to give the right baseline information. Previously it was giving the baseline distance for the font, but not for the actual laid-out text. I considered also providing a "defaultBaseline" accessor that returns the distance for the actual dominant baseline, but it turns out right now we never decide the baseline is ideographic. We always use the alphabetic baseline. We should probably fix that... R=eseidel@chromium.org Review URL: https://codereview.chromium.org/1200233002.
Sky Rendering
The Sky render tree is a low-level layout and painting system based on a
retained tree of objects that inherit from RenderObject. Most
developers using Sky will not need to interact directly with the rendering tree.
Instead, most developers should use Sky widgets, which
are built using the render tree.
Overview
Base Model
The base class for every node in the render tree is
RenderObject, which defines the base layout model. The base
layout mode is extremely general and can accomodate a large number of more
concrete layout models that can co-exist in the same tree. For example, the base
model does not commit to a fixed number of dimensions or even a cartesian
coordinate system. In this way, a single render tree can contain render objects
operating in three-dimensional space together with other render objects
operating in two-dimensional space, e.g., on the face of a cube in the three-
dimensional space. Moreover, the two-dimensional layout might be partially
computed in cartesian coordinates and partially computed in polar coordinates.
These distinct models can interact during layout, for example determining the
size of the cube by the height of a block of text on the cube's face.
Not entirely free-wheeling, the base model does impose some structure on the render tree:
-
Subclasses of
RenderObjectmust implement aperformLayoutfunction that takes as input aconstraintsobject provided by its parent.RenderObjecthas no opinion about the structure of this object and different layout models use different types of constraints. However, whatever type they choose must implementoperator==in such a way thatperformLayoutproduces the same output for twoconstraintsobjects that areoperator==. -
Implementations of
performLayoutare expected to calllayouton their children. When callinglayout, aRenderObjectmust use theparentUsesSizeparameter to declare whether itsperformLayoutfunction depends on information read from the child. If the parent doesn't declare that it uses the child's size, the edge from the parent to the child becomes a relayout boundary, which means the child (and its subtree) might undergo layout without the parent undergoing layout. -
Subclasses of
RenderObjectmust implement apaintfunction that draws a visual representation of the object onto aRenderCanvas. If theRenderObjecthas children, theRenderObjectis responsible for painting its children using thepaintChildfunction on theRenderCanvas. -
Subclasses of
RenderObjectmust calladoptChildwhenever they add a child. Similarly, they must calldropChildwhenever they remove a child. -
Most subclasses of
RenderObjectwill implement ahitTestfunction that lets clients query the render tree for objects that intersect with a given user input location.RenderObjectitself does not impose a particular type signature onhitTest, but most implementations will take an argument of typeHitTestResult(or, more likely, a model-specific subclass ofHitTestResult) as well as an object that describes the location at which the user provided input (e.g., aPointfor a two-dimensional cartesian model). -
Finally, subclasses of
RenderObjectcan override the default, do-nothing implemenations ofhandleEventandrotateto respond to user input and screen rotation, respectively.
The base model also provides two mixins for common child models:
-
RenderObjectWithChildMixinis useful for subclasses ofRenderObjectthat have a unique child. -
ContainerRenderObjectMixinis useful for subclasses ofRenderObjectthat have a child list.
Subclasses of RenderObject are not required to use either of these child
models and are free to invent novel child models for their specific use cases.
Parent Data
Box Model
EdgeDims
BoxConstraints
Bespoke Models
Using the provided subclasses
render_box.dart
RenderConstrainedBox
RenderShrinkWrapWidth
RenderOpacity
RenderColorFilter
RenderClipRect
RenderClipOval
RenderPadding
RenderPositionedBox
RenderImage
RenderDecoratedBox
RenderTransform
RenderSizeObserver
RenderCustomPaint
RenderBlock (render_block.dart)
RenderFlex (render_flex.dart)
RenderParagraph (render_paragraph.dart)
RenderStack (render_stack.dart)
Writing new subclasses
The RenderObject contract
The ParentData contract
Using RenderObjectWithChildMixin
Using ContainerParentDataMixin and ContainerRenderObjectMixin
The RenderBox contract
Using RenderProxyBox
The Hit Testing contract
Performance rules of thumb
-
Avoid using transforms where mere maths would be sufficient (e.g. draw your rectangle at x,y rather than translating by x,y and drawing it at 0,0).
-
Avoid using save/restore on canvases.