{% 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 "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_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('CSSPropertyZIndex')}} {% 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 access_layers = 'accessBackgroundLayers' %} {% 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}}(BackgroundFillLayer)); 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()->backgroundLayers(); 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()) { /* 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('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('CSSPropertyWebkitBackgroundComposite', 'Composite')}} {% 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_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