Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Unified Diff: sky/specs/style.md

Issue 835973003: Specs: Move the LayoutManager and RenderNode logic from Element to (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sky/specs/runloop.md ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sky/specs/style.md
diff --git a/sky/specs/style.md b/sky/specs/style.md
index 5b4a9981321d0413caddbeb32a665daf5d8ad8c7..a710b9d166fe8c72f9597e0c859a9a1f60bd7e68 100644
--- a/sky/specs/style.md
+++ b/sky/specs/style.md
@@ -276,12 +276,25 @@ abstract class StyleNode {
abstract void markDirty();
}
+dictionary StyleValueResolverSettingsSettings {
+ Boolean firstTime = false;
+ any state = null;
+}
+
class StyleValueResolverSettings {
// this is used as an "out" parameter for 'resolve()' below
- constructor();
- void reset(); // resets values to defaults so that object can be reused
+ constructor(StyleValueResolverSettingsSettings initial);
+ void reset(StyleValueResolverSettingsSettings initial);
+ // sets firstTime and state to given values
+ // sets layoutDependent to false
+ // sets dependencies to empty set
+
+ readonly attribute Boolean firstTime;
+ // true if this is the first time this property is being resolved for this element,
+ // or if the last time it was resolved, the value was a different object
+
attribute Boolean layoutDependent; // default to false
- // set this if the value should be recomputed each time the ownerLayoutManager's dimensions change, rather than being precomputed
+ // set this if the value should be recomputed each time the ownerLayoutManager's dimensions change, rather than being cached
// attribute "BitField" dependencies; // defaults to no bits set
void dependsOn(PropertyHandle property);
@@ -289,6 +302,19 @@ class StyleValueResolverSettings {
// - assign the next bit to the property
// - if there's no bits left, throw
// set the bit on this StyleValueResolverSettings's dependencies bitfield
+ Array<PropertyHandle> getDependencies();
+ // returns an array of the PropertyHandle values for the bits that are set in dependencies
+
+ attribute any state; // initially null, can be set to store value for this RenderNode/property pair
+ // for example, TransitioningColorStyleValue would store
+ // {
+ // initial: /* color at time of transition */,
+ // target: /* color at end of transition */,
+ // start: /* time at start of transition */,
+ // }
+ // ...which would enable it to update appropriately, and would also
+ // let other transitions that come later know that you were half-way
+ // through a transition so they can shorten their time accordingly
}
class Property : StyleNode {
@@ -309,8 +335,8 @@ class Property : StyleNode {
}
abstract class AbstractStyleValue : StyleNode {
- abstract constructor(StyleNode parentNode);
- readonly attribute StyleNode parentNode;
+ abstract constructor(StyleNode? parentNode = null);
+ attribute StyleNode? parentNode;
void markDirty();
// call this.parentNode.markDirty()
@@ -323,33 +349,36 @@ abstract class LengthStyleValue : AbstractStyleValue {
}
class PixelLengthStyleValue : LengthStyleValue {
- constructor(StyleNode parentNode, Float number);
- readonly attribute Float value;
+ constructor(Float number, StyleNode? parentNode = null);
+ attribute Float value;
+ // on setting, calls markDirty();
Float resolve(PropertyHandle property, RenderNode node, StyleValueResolverSettings? settings = null);
+ // return value
}
typedef RawColor Float; // TODO(ianh): figure out what Color should be
class ColorStyleValue : LengthStyleValue {
- constructor(StyleNode parentNode, Float red, Float green, Float blue, Float alpha);
+ constructor(Float red, Float green, Float blue, Float alpha, StyleNode? parentNode = null);
// ... color API ...
RawColor resolve(PropertyHandle property, RenderNode node, StyleValueResolverSettings? settings = null);
}
class AbstractOpaqueStyleValue : AbstractStyleValue {
- abstract constructor(StyleNode parentNode, any value);
- readonly attribute any value;
+ abstract constructor(any value, StyleNode? parentNode = null);
+ attribute any value;
+ // on setting, calls markDirty();
any resolve(PropertyHandle property, RenderNode node, StyleValueResolverSettings? settings = null);
// returns value
}
class IdentifierStyleValue : AbstractOpaqueStyleValue {
- constructor(StyleNode parentNode, String value);
+ constructor(String value, StyleNode? parentNode = null);
// calls superclass constructor
}
/*
class AnimatableIdentifierStyleValue : AbstractOpaqueStyleValue {
- constructor(StyleNode parentNode, String value, String newValue, AnimationFunction player);
+ constructor(String value, String newValue, AnimationFunction player, StyleNode? parentNode = null);
readonly attribute String newValue;
readonly attribute AnimationFunction player;
any resolve(PropertyHandle property, RenderNode node, StyleValueResolverSettings? settings = null);
@@ -357,13 +386,13 @@ class AnimatableIdentifierStyleValue : AbstractOpaqueStyleValue {
*/
class ObjectStyleValue : AbstractOpaqueStyleValue {
- constructor(StyleNode parentNode, any value);
+ constructor(any value, StyleNode? parentNode = null);
// calls superclass constructor
}
dictionary PropertySettings {
String? name = null; // null if the property can't be set from a <style> block
- StyleGrammar? grammar = null; // msut be non-null if name is non-null; must be null otherwise
+ StyleGrammar? grammar = null; // must be non-null if name is non-null; must be null otherwise
Boolean inherited = false;
any initialValue = null;
Boolean needsManager = false;
@@ -391,9 +420,9 @@ Inline Styles
```javascript
abstract class AbstractStyleDeclarationList {
- void addStyles(StyleDeclaration styles, String? pseudoElement = null); // O(1)
- void removeStyles(StyleDeclaration styles, String? pseudoElement = null); // O(N) in number of declarations
- Array<StyleDeclaration> getDeclarations(String? pseudoElement = null); // O(N) in number of declarations
+ void addStyles(StyleDeclaration styles, String pseudoElement = ''); // O(1)
+ void removeStyles(StyleDeclaration styles, String pseudoElement = ''); // O(N) in number of declarations
+ Array<StyleDeclaration> getDeclarations(String pseudoElement = ''); // O(N) in number of declarations
}
class ElementStyleDeclarationList : AbstractStyleDeclarationList {
@@ -406,7 +435,7 @@ class ElementStyleDeclarationList : AbstractStyleDeclarationList {
// <style> blocks get added back in, followed by all the animation-
// derived rules; scripts can also add styles themselves, but they are
// dropped after the next frame
- void addFrameStyles(StyleDeclaration styles, String? pseudoElement = null); // O(1)
+ void addFrameStyles(StyleDeclaration styles, String pseudoElement = ''); // O(1)
void clearFrameStyles();
// the second batch is the persistent styles, which remain until removed;
@@ -416,7 +445,7 @@ class ElementStyleDeclarationList : AbstractStyleDeclarationList {
// calls register(element) and unregister(element) respectively on those
// StyleDeclaration objects, where element is the element that was passed
// to the constructor, if not null
- // then, it calls element.renderNode.cascadedValueAdded/cascadedValueRemoved
+ // then, it calls element.renderNode.cascadedValueChanged
// for each property on the object
// the inherited getDeclarations() method returns all the frame
@@ -430,7 +459,7 @@ class RenderNodeStyleDeclarationList : AbstractStyleDeclarationList {
// calls register(renderNode) and unregister(renderNode) respectively on those
// StyleDeclaration objects, where renderNode is the RenderNode that was passed
// to the constructor, if not null
- // then, it calls renderNode.cascadedValueAdded/cascadedValueRemoved
+ // then, it calls renderNode.cascadedValueChanged
// for each property on the object
}
@@ -444,8 +473,8 @@ class StyleDeclaration {
// invoke element.renderNode.cascadedValueDirty(property, pseudoElement); for each
// currently registered consumer element/pseudoElement pair
- void register((Element or RenderNode) consumer, String? pseudoElement = null); // O(1)
- void unregister((Element or RenderNode) consumer, String? pseudoElement = null); // O(N)
+ void register((Element or RenderNode) consumer, String pseudoElement = ''); // O(1)
+ void unregister((Element or RenderNode) consumer, String pseudoElement = ''); // O(N)
// registers an element/pseudoElement or renderNode/pseudoElement pair with
// this StyleDeclaration so that a property/value on the style declaration
// is marked dirty, the relevant render node is informed and can then update
@@ -456,18 +485,16 @@ class StyleDeclaration {
// null if property is missing
setter void (PropertyHandle property, AbstractStyleValue value);
+ // verify that value.parentNode is null
// if there is no Property object for /property/, creates one
// else calls its update() method to change the value
- // if the value changed:
+ // update value's parentNode
// invoke consumer.renderNode.cascadedValueChanged(property); for each
// currently registered consumer
- // if the value is new:
- // invoke consumer.renderNode.cascadedValueAdded(property); for each
- // currently registered consumer
void remove(PropertyHandle property);
// drops the Property object for /property/ from this StyleDeclaration object
- // invoke consumer.renderNode.cascadedValueRemoved(property); for each
+ // invoke consumer.renderNode.cascadedValueChanged(property); for each
// currently registered consumer
}
```
@@ -479,7 +506,7 @@ Rule Matching
class Rule {
constructor ();
attribute SelectorQuery selector; // O(1)
- attribute String? pseudoElement; // O(1)
+ attribute String pseudoElement; // O(1)
attribute StyleDeclaration styles; // O(1)
}
```
@@ -537,7 +564,24 @@ RenderNode's LayoutManager's childRemoved() callback.
```javascript
-callback any ValueResolver (any value, String propertyName, RenderNode node, Float containerWidth, Float containerHeight);
+dictionary PropertySettings {
+ String? name = null; // null if the property can't be set from a <style> block
+ StyleGrammar? grammar = null; // must be non-null if name is non-null; must be null otherwise
+ Boolean inherited = false;
+ any initialValue = null;
+ Boolean needsManager = false;
+ Boolean needsLayout = false;
+ Boolean needsPaint = false;
+ // PropertyHandle propertyHandle; // assigned by registerProperty
+ // Integer dependencyBit; // assigned by StyleValueResolverSettings.dependsOn()
+}
+
+dictionary GetPropertySettings {
+ String pseudoElement = '';
+ Boolean forceCache = false;
+ // if set to true, will return the cached value if any, or null otherwise
+ // this is used by transitions to figure out what to transition from
+}
class RenderNode { // implemented in C++ with no virtual tables
// this is generated before layout
@@ -546,43 +590,70 @@ class RenderNode { // implemented in C++ with no virtual tables
readonly attribute Node? firstChild;
readonly attribute Node? nextSibling;
- any getProperty(PropertyHandle property, String? pseudoElement = null);
+ // internal state:
+ // - back pointer to backing Node, if we're not a ghost
+ // - cache of resolved property values, mapping as follows:
+ // - pseudoElement, property => StyleValue object, resolved value, StyleValueResolverSettings, cascade dirty bit, value dirty bit
+ // - property state map (initially empty), as follows:
+ // - pseudoElement, property => object
+
+ any getProperty(PropertyHandle property, GetPropertySettings? settings = null);
// looking at the cached data for the given pseudoElement:
- // if there's a cached value, return it
- // otherwise, figure out which StyleValue we're going to be using, in this order:
- // - look out our override declarations (first with the pseudo, if any, then without)
- // - if there's an element:
- // - look at this element's StyleDeclarations (first with the pseudo, if any, then without)
- // - if it's an inherited property and there's a parent:
- // - call getProperty() on the parent (without the pseudo)
- // - use the default value
- // resolve the StyleValue giving it the property and node in question
- // cache the value, along with the StyleValueResolverSettings
+ // if there's a cached value:
+ // if settings.forceCache is true, return the value
+ // if neither dirty bit is set, return the cached resolved value
+ // if the cascade dirty bit is not set (value dirty is set) then
+ // resolve the value using the same StyleValue object
+ // - with firstTime=false on the resolver settings
+ // - with the cached state object if any
+ // if settings.forceCache is true, return null
+ // - if there's an override declaration with the property (with
+ // the pseudo or without), then get the value object from there and
+ // jump to "resolve" below.
+ // - if there's an element and it has a style declaration with the property
+ // (with the pseudo or without), then get the value object from there
+ // and jump to "resolve" below.
+ // - if it's not an inherited property, or if there's no parent, then get the
+ // default value and jump to "resolve" below.
+ // - call the parent render node's getProperty() with the same property
+ // but no settings, then cache that value as the value for this element
+ // with the given pseudoElement, with no StyleValue object, no resolver
+ // settings, and set the state to null.
+ // resolve:
+ // - get a new resolver settings object
+ // - if the obtained StyleValue object is different than the
+ // cached StyleValue object, or if there is no cached object, then set
+ // the resolver settings to firstTime=true, otherwise it's the same object
+ // and set firstTime=false.
+ // - set the resolver settings' state to the current state for this
+ // pseudoElement/property combination
+ // - using the obtained StyleValue object, call resolve(),
+ // passing it this node and the resolver settings object.
+ // - update the cache with the obtained value and resolver settings,
+ // resetting the dirty bits; update the state similarly
readonly attribute RenderNodeStyleDeclarationList overrideStyles;
// mutable; initially empty
// this is used when isGhost is true, and can also be used more generally to
// override styles from the layout manager (e.g. to animate a new node into view)
- private void cascadedValueAdded(PropertyHandle property, String? pseudoElement = null);
- private void cascadedValueRemoved(PropertyHandle property, String? pseudoElement = null);
- private void cascadedValueChanged(PropertyHandle property, String? pseudoElement = null);
- private void cascadedValueDirty(PropertyHandle property, String? pseudoElement = null);
- // - clear the cached data for this property/pseudoElement pair
+ private void cascadedValueChanged(PropertyHandle property, String pseudoElement = '');
+ private void cascadedValueDirty(PropertyHandle property, String pseudoElement = '');
+ // - set the appropriate dirty bit on the cached data for this property/pseudoElement pair
+ // - cascade dirty for cascadedValueChanged
+ // - value dirty for cascadedValueDirty
// - if the property is needsManager, set needsManager to true
- // - if the property is needsLayout, set needsLayout to true and walk
- // up the tree setting descendantNeedsLayout
+ // - if the property is needsLayout, set needsLayout to true and walk up the
+ // tree setting descendantNeedsLayout
// - if the property is needsPaint, add the node to the list of nodes that need painting
// - if the property has a dependencyBit defined, then check the cache of all the
// properties on this RenderNode, and the cache for the property in all the child
- // nodes and (if pseudoElement is null) or the pseudoElements
- // and if any of them have the relevant dependency bit set then call
+ // nodes and, if pseudoElement is '', the pseudoElements of this node, and,
+ // if any of them have the relevant dependency bit set, then call
// thatRenderNode.cascadedValueDirty(thatProperty, thatPseudoElement)
- // - if the property is inherited:
- // - call this.cascadedValueDirty(property, eachPseudoElement)
- // - call eachChildRenderNode.cascadedValueDirty(property, null)
- // (these four methods all do the same thing; they might get merged into one. For now
- // they're separate in case we want to make them cleverer later.)
+ // - if the property is inherited, then for each child node, and, if pseudoElement
+ // is '', the pseudoElements of this node, if the cached value for this property
+ // is present but has no StyleValue, call thatNode.cascadedValueChanged(property, thatPseudoElement)
readonly attribute Boolean needsManager;
// means that a property with needsManager:true has changed on this node
@@ -669,9 +740,10 @@ class LayoutManager : EventTarget {
// }
// return result;
- void setProperty(RenderNode node, PropertyHandle property, any value, String? pseudoElement = null); // O(1)
+ void setProperty(RenderNode node, PropertyHandle property, any value, String pseudoElement = ''); // O(1)
// if called from an adjustProperties() method during the property adjustment phase,
// replaces the value that getProperty() would return on that node with /value/
+ // this also clears the dependency bits and sets the property state to null
void take(RenderNode victim); // sets victim.ownerLayoutManager = this;
// assert: victim hasn't been take()n yet during this layout
« no previous file with comments | « sky/specs/runloop.md ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698