flutter_flutter/engine/build/scripts/templates/StyleBuilderFunctions.cpp.tmpl
Ojan Vafai ed0c01cdca Remove CSS Grid Layout and grid media queries.
The two are unrelated, but it was easier to just grep for grid
and remove them all. Aside from the media query change, there
isn't any change in behavior since grid was behind a flag.

R=esprehn@chromium.org

Review URL: https://codereview.chromium.org/689853003
2014-10-31 16:40:03 -07:00

520 lines
21 KiB
Cheetah

{% from 'macros.tmpl' import license %}
{#
This file is for property handlers which use the templating engine to
reduce (handwritten) code duplication.
The `properties' dict can be used to access a property's parameters in
jinja2 templates (i.e. setter, getter, initial, type_name)
#}
#include "config.h"
#include "StyleBuilderFunctions.h"
#include "CSSValueKeywords.h"
#include "core/css/BasicShapeFunctions.h"
#include "core/css/CSSPrimitiveValueMappings.h"
#include "core/css/Pair.h"
#include "core/css/resolver/StyleResolverState.h"
{% macro declare_initial_function(property_id) %}
void StyleBuilderFunctions::applyInitial{{property_id}}(StyleResolverState& state)
{%- endmacro %}
{% macro declare_inherit_function(property_id) %}
void StyleBuilderFunctions::applyInherit{{property_id}}(StyleResolverState& state)
{%- endmacro %}
{% macro declare_value_function(property_id) %}
void StyleBuilderFunctions::applyValue{{property_id}}(StyleResolverState& state, CSSValue* value)
{%- endmacro %}
{% macro set_value(property) %}
{%- if property.font %}
state.fontBuilder().{{property.setter}}
{%- else %}
state.style()->{{property.setter}}
{%- endif %}
{% endmacro %}
{% macro convert_and_set_value(property) %}
{% if property.converter %}
{{set_value(property)}}(StyleBuilderConverter::{{property.converter}}(state, value));
{%- else %}
{{set_value(property)}}(static_cast<{{property.type_name}}>(*toCSSPrimitiveValue(value)));
{%- endif %}
{% endmacro %}
namespace blink {
{% for property_id, property in properties.items() if property.should_declare_functions %}
{% set apply_type = property.apply_type %}
{% if not property.custom_initial %}
{{declare_initial_function(property_id)}}
{
{% if property.font %}
{{set_value(property)}}(FontBuilder::{{property.initial}}());
{% else %}
{{set_value(property)}}(RenderStyle::{{property.initial}}());
{% endif %}
}
{% endif %}
{% if not property.custom_inherit %}
{{declare_inherit_function(property_id)}}
{
{% if property.font %}
{{set_value(property)}}(state.parentFontDescription().{{property.getter}}());
{% else %}
{{set_value(property)}}(state.parentStyle()->{{property.getter}}());
{% endif %}
}
{% endif %}
{% if not property.custom_value %}
{{declare_value_function(property_id)}}
{
{{convert_and_set_value(property)}}
}
{% endif %}
{% endfor %}
{% macro apply_animation(property_id, attribute, animation) %}
{% set vector = attribute|lower_first + "List()" %}
{{declare_initial_function(property_id)}}
{
CSS{{animation}}Data& data = state.style()->access{{animation}}s();
data.{{vector}}.clear();
data.{{vector}}.append(CSS{{animation}}Data::initial{{attribute}}());
}
{{declare_inherit_function(property_id)}}
{
const CSS{{animation}}Data* parentData = state.parentStyle()->{{animation|lower}}s();
if (!parentData)
applyInitial{{property_id}}(state);
else
state.style()->access{{animation}}s().{{vector}} = parentData->{{vector}};
}
{{declare_value_function(property_id)}}
{
CSS{{animation}}Data& data = state.style()->access{{animation}}s();
data.{{vector}}.clear();
for (CSSValueListIterator i = value; i.hasMore(); i.advance())
data.{{vector}}.append(state.styleMap().mapAnimation{{attribute}}(i.value()));
}
{% endmacro %}
{{apply_animation('CSSPropertyWebkitAnimationDelay', 'Delay', 'Animation')}}
{{apply_animation('CSSPropertyWebkitAnimationDirection', 'Direction', 'Animation')}}
{{apply_animation('CSSPropertyWebkitAnimationDuration', 'Duration', 'Animation')}}
{{apply_animation('CSSPropertyWebkitAnimationFillMode', 'FillMode', 'Animation')}}
{{apply_animation('CSSPropertyWebkitAnimationIterationCount', 'IterationCount', 'Animation')}}
{{apply_animation('CSSPropertyWebkitAnimationName', 'Name', 'Animation')}}
{{apply_animation('CSSPropertyWebkitAnimationPlayState', 'PlayState', 'Animation')}}
{{apply_animation('CSSPropertyWebkitAnimationTimingFunction', 'TimingFunction', 'Animation')}}
{{apply_animation('CSSPropertyWebkitTransitionDelay', 'Delay', 'Transition')}}
{{apply_animation('CSSPropertyWebkitTransitionDuration', 'Duration', 'Transition')}}
{{apply_animation('CSSPropertyWebkitTransitionProperty', 'Property', 'Transition')}}
{{apply_animation('CSSPropertyWebkitTransitionTimingFunction', 'TimingFunction', 'Transition')}}
{% macro apply_auto(property_id, auto_getter=none, auto_setter=none, auto_identity='CSSValueAuto') %}
{% set property = properties[property_id] %}
{% set auto_getter = auto_getter or 'hasAuto' + property.name_for_methods %}
{% set auto_setter = auto_setter or 'setHasAuto' + property.name_for_methods %}
{{declare_initial_function(property_id)}}
{
state.style()->{{auto_setter}}();
}
{{declare_inherit_function(property_id)}}
{
if (state.parentStyle()->{{auto_getter}}())
state.style()->{{auto_setter}}();
else
{{set_value(property)}}(state.parentStyle()->{{property.getter}}());
}
{{declare_value_function(property_id)}}
{
if (!value->isPrimitiveValue())
return;
CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
if (primitiveValue->getValueID() == {{auto_identity}})
state.style()->{{auto_setter}}();
else
{{convert_and_set_value(property)}}
}
{% endmacro %}
{{apply_auto('CSSPropertyClip')}}
{{apply_auto('CSSPropertyOrphans')}}
{{apply_auto('CSSPropertyWidows')}}
{{apply_auto('CSSPropertyZIndex')}}
static bool lengthTypeAndValueMatch(const Length& length, LengthType type, float value)
{
return length.type() == type && length.value() == value;
}
static bool lengthTypeAndValueMatch(const LengthBox& lengthBox, LengthType type, float value)
{
return (lengthTypeAndValueMatch(lengthBox.left(), type, value)
&& lengthTypeAndValueMatch(lengthBox.right(), type, value)
&& lengthTypeAndValueMatch(lengthBox.top(), type, value)
&& lengthTypeAndValueMatch(lengthBox.bottom(), type, value));
}
static bool lengthTypeAndValueMatch(const BorderImageLength& borderImageLength, LengthType type, float value)
{
return borderImageLength.isLength() && lengthTypeAndValueMatch(borderImageLength.length(), type, value);
}
static bool lengthTypeAndValueMatch(const BorderImageLengthBox& borderImageLengthBox, LengthType type, float value)
{
return (lengthTypeAndValueMatch(borderImageLengthBox.left(), type, value)
&& lengthTypeAndValueMatch(borderImageLengthBox.right(), type, value)
&& lengthTypeAndValueMatch(borderImageLengthBox.top(), type, value)
&& lengthTypeAndValueMatch(borderImageLengthBox.bottom(), type, value));
}
{% macro apply_border_image_modifier(property_id, modifier_type) %}
{% set is_mask_box = 'MaskBox' in property_id %}
{% set getter = 'maskBoxImage' if is_mask_box else 'borderImage' %}
{% set setter = 'setMaskBoxImage' if is_mask_box else 'setBorderImage' %}
{{ declare_initial_function(property_id) }}
{
const NinePieceImage& currentImage = state.style()->{{getter}}();
{# Check for equality in case we can bail out before creating a new NinePieceImage. #}
{% if modifier_type == 'Outset' %}
if (lengthTypeAndValueMatch(currentImage.outset(), Fixed, 0))
return;
{% elif modifier_type == 'Repeat' %}
if (currentImage.horizontalRule() == StretchImageRule && currentImage.verticalRule() == StretchImageRule)
return;
{% elif modifier_type == 'Slice' and is_mask_box %}
// Masks have a different initial value for slices. Preserve the value of 0 for backwards compatibility.
if (currentImage.fill() == true && lengthTypeAndValueMatch(currentImage.imageSlices(), Fixed, 0))
return;
{% elif modifier_type == 'Slice' and not is_mask_box %}
if (currentImage.fill() == false && lengthTypeAndValueMatch(currentImage.imageSlices(), Percent, 100))
return;
{% elif modifier_type == 'Width' and is_mask_box %}
// Masks have a different initial value for widths. Preserve the value of 'auto' for backwards compatibility.
if (lengthTypeAndValueMatch(currentImage.borderSlices(), Auto, 0))
return;
{% elif modifier_type == 'Width' and not is_mask_box %}
if (lengthTypeAndValueMatch(currentImage.borderSlices(), Fixed, 1))
return;
{% endif %}
NinePieceImage image(currentImage);
{% if modifier_type == 'Outset' %}
image.setOutset(Length(0, Fixed));
{% elif modifier_type == 'Repeat' %}
image.setHorizontalRule(StretchImageRule);
image.setVerticalRule(StretchImageRule);
{% elif modifier_type == 'Slice' and is_mask_box %}
image.setImageSlices(LengthBox({{ (['Length(0, Fixed)']*4) | join(', ') }}));
image.setFill(true);
{% elif modifier_type == 'Slice' and not is_mask_box %}
image.setImageSlices(LengthBox({{ (['Length(100, Percent)']*4) | join(', ') }}));
image.setFill(false);
{% elif modifier_type == 'Width' %}
image.setBorderSlices({{ 'Length(Auto)' if is_mask_box else '1.0' }});
{% endif %}
state.style()->{{setter}}(image);
}
{{declare_inherit_function(property_id)}}
{
NinePieceImage image(state.style()->{{getter}}());
{% if modifier_type == 'Outset' %}
image.copyOutsetFrom(state.parentStyle()->{{getter}}());
{% elif modifier_type == 'Repeat' %}
image.copyRepeatFrom(state.parentStyle()->{{getter}}());
{% elif modifier_type == 'Slice' %}
image.copyImageSlicesFrom(state.parentStyle()->{{getter}}());
{% elif modifier_type == 'Width' %}
image.copyBorderSlicesFrom(state.parentStyle()->{{getter}}());
{% endif %}
state.style()->{{setter}}(image);
}
{{declare_value_function(property_id)}}
{
NinePieceImage image(state.style()->{{getter}}());
{% if modifier_type == 'Outset' %}
image.setOutset(state.styleMap().mapNinePieceImageQuad(value));
{% elif modifier_type == 'Repeat' %}
state.styleMap().mapNinePieceImageRepeat(value, image);
{% elif modifier_type == 'Slice' %}
state.styleMap().mapNinePieceImageSlice(value, image);
{% elif modifier_type == 'Width' %}
image.setBorderSlices(state.styleMap().mapNinePieceImageQuad(value));
{% endif %}
state.style()->{{setter}}(image);
}
{% endmacro %}
{{apply_border_image_modifier('CSSPropertyBorderImageOutset', 'Outset')}}
{{apply_border_image_modifier('CSSPropertyBorderImageRepeat', 'Repeat')}}
{{apply_border_image_modifier('CSSPropertyBorderImageSlice', 'Slice')}}
{{apply_border_image_modifier('CSSPropertyBorderImageWidth', 'Width')}}
{{apply_border_image_modifier('CSSPropertyWebkitMaskBoxImageOutset', 'Outset')}}
{{apply_border_image_modifier('CSSPropertyWebkitMaskBoxImageRepeat', 'Repeat')}}
{{apply_border_image_modifier('CSSPropertyWebkitMaskBoxImageSlice', 'Slice')}}
{{apply_border_image_modifier('CSSPropertyWebkitMaskBoxImageWidth', 'Width')}}
{% macro apply_value_border_image_source(property_id) %}
{{declare_value_function(property_id)}}
{
{% set property = properties[property_id] %}
{{set_value(property)}}(state.styleImage({{property_id}}, value));
}
{% endmacro %}
{{apply_value_border_image_source('CSSPropertyBorderImageSource')}}
{{apply_value_border_image_source('CSSPropertyWebkitMaskBoxImageSource')}}
{% macro apply_color(property_id, initial_color='StyleColor::currentColor') %}
{% set property = properties[property_id] %}
{{declare_initial_function(property_id)}}
{
StyleColor color = {{initial_color}}();
{{set_value(property)}}(color);
}
{{declare_inherit_function(property_id)}}
{
StyleColor color = state.parentStyle()->{{property.getter}}();
Color resolvedColor = color.resolve(state.parentStyle()->color());
{{set_value(property)}}(resolvedColor);
}
{{declare_value_function(property_id)}}
{
{{set_value(property)}}(StyleBuilderConverter::convertColor(state, value));
}
{% endmacro %}
{{apply_color('CSSPropertyBackgroundColor', initial_color='RenderStyle::initialBackgroundColor') }}
{{apply_color('CSSPropertyBorderBottomColor')}}
{{apply_color('CSSPropertyBorderLeftColor')}}
{{apply_color('CSSPropertyBorderRightColor')}}
{{apply_color('CSSPropertyBorderTopColor')}}
{{apply_color('CSSPropertyOutlineColor')}}
{{apply_color('CSSPropertyTextDecorationColor')}}
{{apply_color('CSSPropertyWebkitTextEmphasisColor')}}
{{apply_color('CSSPropertyWebkitTextFillColor')}}
{{apply_color('CSSPropertyWebkitTextStrokeColor')}}
{% macro apply_counter(property_id, action) %}
{% set property = properties[property_id] %}
{{declare_initial_function(property_id)}} { }
{{declare_inherit_function(property_id)}}
{
CounterDirectiveMap& map = state.style()->accessCounterDirectives();
CounterDirectiveMap& parentMap = state.parentStyle()->accessCounterDirectives();
typedef CounterDirectiveMap::iterator Iterator;
Iterator end = parentMap.end();
for (Iterator it = parentMap.begin(); it != end; ++it) {
CounterDirectives& directives = map.add(it->key, CounterDirectives()).storedValue->value;
directives.inherit{{action}}(it->value);
}
}
{{declare_value_function(property_id)}}
{
CounterDirectiveMap& map = state.style()->accessCounterDirectives();
typedef CounterDirectiveMap::iterator Iterator;
Iterator end = map.end();
for (Iterator it = map.begin(); it != end; ++it)
it->value.clear{{action}}();
if (!value->isValueList()) {
ASSERT(value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueNone);
return;
}
CSSValueList* list = toCSSValueList(value);
int length = list ? list->length() : 0;
for (int i = 0; i < length; ++i) {
CSSValue* currValue = list->item(i);
if (!currValue->isPrimitiveValue())
continue;
Pair* pair = toCSSPrimitiveValue(currValue)->getPairValue();
if (!pair || !pair->first() || !pair->second())
continue;
AtomicString identifier(pair->first()->getStringValue());
int value = pair->second()->getIntValue();
CounterDirectives& directives = map.add(identifier, CounterDirectives()).storedValue->value;
{% if action == 'Reset' %}
directives.setResetValue(value);
{% else %}
directives.addIncrementValue(value);
{% endif %}
}
}
{% endmacro %}
{% macro apply_fill_layer(property_id, fill_type) %}
{% set layer_type = 'Background' if 'Background' in property_id else 'Mask' %}
{% set fill_layer_type = layer_type + 'FillLayer' %}
{% set access_layers = 'access' + layer_type + 'Layers' %}
{% set map_fill = 'mapFill' + fill_type %}
{{declare_initial_function(property_id)}}
{
FillLayer* currChild = &state.style()->{{access_layers}}();
currChild->set{{fill_type}}(FillLayer::initialFill{{fill_type}}({{fill_layer_type}}));
for (currChild = currChild->next(); currChild; currChild = currChild->next())
currChild->clear{{fill_type}}();
}
{{declare_inherit_function(property_id)}}
{
FillLayer* currChild = &state.style()->{{access_layers}}();
FillLayer* prevChild = 0;
const FillLayer* currParent = &state.parentStyle()->{{layer_type|lower}}Layers();
while (currParent && currParent->is{{fill_type}}Set()) {
if (!currChild)
currChild = prevChild->ensureNext();
currChild->set{{fill_type}}(currParent->{{fill_type|lower_first}}());
prevChild = currChild;
currChild = prevChild->next();
currParent = currParent->next();
}
while (currChild) {
/* Reset any remaining layers to not have the property set. */
currChild->clear{{fill_type}}();
currChild = currChild->next();
}
}
{{declare_value_function(property_id)}}
{
FillLayer* currChild = &state.style()->{{access_layers}}();
FillLayer* prevChild = 0;
if (value->isValueList() && !value->isImageSetValue()) {
/* Walk each value and put it into a layer, creating new layers as needed. */
CSSValueList* valueList = toCSSValueList(value);
for (unsigned int i = 0; i < valueList->length(); i++) {
if (!currChild)
currChild = prevChild->ensureNext();
state.styleMap().{{map_fill}}(currChild, valueList->item(i));
prevChild = currChild;
currChild = currChild->next();
}
} else {
state.styleMap().{{map_fill}}(currChild, value);
currChild = currChild->next();
}
while (currChild) {
/* Reset all remaining layers to not have the property set. */
currChild->clear{{fill_type}}();
currChild = currChild->next();
}
}
{% endmacro %}
{{apply_fill_layer('CSSPropertyBackgroundAttachment', 'Attachment')}}
{{apply_fill_layer('CSSPropertyBackgroundBlendMode', 'BlendMode')}}
{{apply_fill_layer('CSSPropertyBackgroundClip', 'Clip')}}
{{apply_fill_layer('CSSPropertyBackgroundImage', 'Image')}}
{{apply_fill_layer('CSSPropertyBackgroundOrigin', 'Origin')}}
{{apply_fill_layer('CSSPropertyBackgroundPositionX', 'XPosition')}}
{{apply_fill_layer('CSSPropertyBackgroundPositionY', 'YPosition')}}
{{apply_fill_layer('CSSPropertyBackgroundRepeatX', 'RepeatX')}}
{{apply_fill_layer('CSSPropertyBackgroundRepeatY', 'RepeatY')}}
{{apply_fill_layer('CSSPropertyBackgroundSize', 'Size')}}
{{apply_fill_layer('CSSPropertyMaskSourceType', 'MaskSourceType')}}
{{apply_fill_layer('CSSPropertyWebkitBackgroundComposite', 'Composite')}}
{{apply_fill_layer('CSSPropertyWebkitMaskClip', 'Clip')}}
{{apply_fill_layer('CSSPropertyWebkitMaskComposite', 'Composite')}}
{{apply_fill_layer('CSSPropertyWebkitMaskImage', 'Image')}}
{{apply_fill_layer('CSSPropertyWebkitMaskOrigin', 'Origin')}}
{{apply_fill_layer('CSSPropertyWebkitMaskPositionX', 'XPosition')}}
{{apply_fill_layer('CSSPropertyWebkitMaskPositionY', 'YPosition')}}
{{apply_fill_layer('CSSPropertyWebkitMaskRepeatX', 'RepeatX')}}
{{apply_fill_layer('CSSPropertyWebkitMaskRepeatY', 'RepeatY')}}
{{apply_fill_layer('CSSPropertyWebkitMaskSize', 'Size')}}
{% macro apply_value_number(property_id, id_for_minus_one) %}
{{declare_value_function(property_id)}}
{
{% set property = properties[property_id] %}
if (!value->isPrimitiveValue())
return;
CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
if (primitiveValue->getValueID() == {{id_for_minus_one}})
{{set_value(property)}}(-1);
else
{{set_value(property)}}(primitiveValue->getValue<{{property.type_name}}>(CSSPrimitiveValue::CSS_NUMBER));
}
{% endmacro %}
{% macro apply_value_shape(property_id) %}
{{declare_value_function(property_id)}}
{
{% set property = properties[property_id] %}
if (value->isPrimitiveValue()) {
CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
if (primitiveValue->getValueID() == CSSValueNone)
{{set_value(property)}}(nullptr);
} else if (value->isImageValue() || value->isImageGeneratorValue() || value->isImageSetValue()) {
{{set_value(property)}}(ShapeValue::createImageValue(state.styleImage({{property_id}}, value)));
} else if (value->isValueList()) {
RefPtr<BasicShape> shape;
CSSBoxType cssBox = BoxMissing;
CSSValueList* valueList = toCSSValueList(value);
for (unsigned i = 0; i < valueList->length(); ++i) {
CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(valueList->item(i));
if (primitiveValue->isShape())
shape = basicShapeForValue(state, primitiveValue->getShapeValue());
else if (primitiveValue->getValueID() == CSSValueContentBox
|| primitiveValue->getValueID() == CSSValueBorderBox
|| primitiveValue->getValueID() == CSSValuePaddingBox
|| primitiveValue->getValueID() == CSSValueMarginBox)
cssBox = CSSBoxType(*primitiveValue);
else
return;
}
if (shape)
{{set_value(property)}}(ShapeValue::createShapeValue(shape.release(), cssBox));
else if (cssBox != BoxMissing)
{{set_value(property)}}(ShapeValue::createBoxShapeValue(cssBox));
}
}
{% endmacro %}
{{apply_value_shape('CSSPropertyShapeOutside')}}
{% macro apply_alignment(property_id, alignment_type) %}
{% set property = properties[property_id] %}
{{declare_initial_function(property_id)}}
{
state.style()->set{{alignment_type}}(RenderStyle::initial{{alignment_type}}());
state.style()->set{{alignment_type}}OverflowAlignment(RenderStyle::initial{{alignment_type}}OverflowAlignment());
}
{{declare_inherit_function(property_id)}}
{
state.style()->set{{alignment_type}}(state.parentStyle()->{{property.getter}}());
state.style()->set{{alignment_type}}OverflowAlignment(state.parentStyle()->{{property.getter}}OverflowAlignment());
}
{{declare_value_function(property_id)}}
{
CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
if (Pair* pairValue = primitiveValue->getPairValue()) {
state.style()->set{{alignment_type}}(*pairValue->first());
state.style()->set{{alignment_type}}OverflowAlignment(*pairValue->second());
} else {
state.style()->set{{alignment_type}}(*primitiveValue);
}
}
{% endmacro %}
{{apply_alignment('CSSPropertyAlignItems', 'AlignItems')}}
{{apply_alignment('CSSPropertyAlignSelf', 'AlignSelf')}}
} // namespace blink