blob: f78bc93798285c8a67c484ab7ca552608644a86e [file] [log] [blame]
{% from "macros.tmpl" import lower_first, wrap_with_condition -%}
{#
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, condition)
-#}
#include "config.h"
#include "StyleBuilderFunctions.h"
#include "CSSValueKeywords.h"
#include "core/css/CSSPrimitiveValueMappings.h"
#include "core/css/resolver/StyleResolver.h"
{%- macro apply_initial(property_id) -%}
void StyleBuilderFunctions::applyInitial{{property_id}}(StyleResolver* styleResolver)
{%- endmacro %}
{%- macro apply_inherit(property_id) -%}
void StyleBuilderFunctions::applyInherit{{property_id}}(StyleResolver* styleResolver)
{%- endmacro %}
{%- macro apply_value(property_id) -%}
void StyleBuilderFunctions::applyValue{{property_id}}(StyleResolver* styleResolver, CSSValue* value)
{%- endmacro %}
{%- macro set_value(property) -%}
styleResolver->style()->{{property.setter}}
{%- endmacro %}
namespace WebCore {
{%- macro apply_animation(property_id, attribute, animation) %}
{{ apply_initial(property_id) }}
{
CSSAnimationDataList* list = styleResolver->style()->access{{animation}}();
if (list->isEmpty())
list->append(CSSAnimationData::create());
list->animation(0)->set{{attribute}}(CSSAnimationData::initialAnimation{{attribute}}());
{%- if property_id == "CSSPropertyWebkitTransitionProperty" %}
list->animation(0)->setAnimationMode(CSSAnimationData::AnimateAll);
{%- endif %}
for (size_t i = 1; i < list->size(); ++i)
list->animation(i)->clear{{attribute}}();
}
{{ apply_inherit(property_id) }}
{
CSSAnimationDataList* list = styleResolver->style()->access{{animation}}();
const CSSAnimationDataList* parentList = styleResolver->parentStyle()->{{animation|lower}}();
size_t i = 0, parentSize = parentList ? parentList->size() : 0;
for ( ; i < parentSize && parentList->animation(i)->is{{attribute}}Set(); ++i) {
if (list->size() <= i)
list->append(CSSAnimationData::create());
list->animation(i)->set{{attribute}}(parentList->animation(i)->{{lower_first(attribute)}}());
list->animation(i)->setAnimationMode(parentList->animation(i)->animationMode());
}
// Reset any remaining animations to not have the property set.
for ( ; i < list->size(); ++i)
list->animation(i)->clear{{attribute}}();
}
{{ apply_value(property_id) }}
{
CSSAnimationDataList* list = styleResolver->style()->access{{animation}}();
size_t childIndex = 0;
if (value->isValueList()) {
// Walk each value and put it into an animation, creating new animations as needed.
for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
if (childIndex <= list->size())
list->append(CSSAnimationData::create());
styleResolver->styleMap()->mapAnimation{{attribute}}(list->animation(childIndex), i.value());
++childIndex;
}
} else {
if (list->isEmpty())
list->append(CSSAnimationData::create());
styleResolver->styleMap()->mapAnimation{{attribute}}(list->animation(childIndex), value);
childIndex = 1;
}
for ( ; childIndex < list->size(); ++childIndex) {
// Reset all remaining animations to not have the property set.
list->animation(childIndex)->clear{{attribute}}();
}
}
{%- endmacro %}
{{ apply_animation("CSSPropertyWebkitAnimationDelay", "Delay", "Animations") }}
{{ apply_animation("CSSPropertyWebkitAnimationDirection", "Direction", "Animations") }}
{{ apply_animation("CSSPropertyWebkitAnimationDuration", "Duration", "Animations") }}
{{ apply_animation("CSSPropertyWebkitAnimationFillMode", "FillMode", "Animations") }}
{{ apply_animation("CSSPropertyWebkitAnimationIterationCount", "IterationCount", "Animations") }}
{{ apply_animation("CSSPropertyWebkitAnimationName", "Name", "Animations") }}
{{ apply_animation("CSSPropertyWebkitAnimationPlayState", "PlayState", "Animations") }}
{{ apply_animation("CSSPropertyWebkitAnimationTimingFunction", "TimingFunction", "Animations") }}
{{ apply_animation("CSSPropertyWebkitTransitionDelay", "Delay", "Transitions") }}
{{ apply_animation("CSSPropertyWebkitTransitionDuration", "Duration", "Transitions") }}
{{ apply_animation("CSSPropertyWebkitTransitionProperty", "Property", "Transitions") }}
{{ apply_animation("CSSPropertyWebkitTransitionTimingFunction", "TimingFunction", "Transitions") }}
{%- macro apply_auto(property_id, auto_getter=none, auto_setter=none, auto_identity="CSSValueAuto", compute_length=false) %}
{%- set property = properties[property_id] %}
{%- set auto_getter = auto_getter or "hasAuto" + property.camel_case_name %}
{%- set auto_setter = auto_setter or "setHasAuto" + property.camel_case_name %}
{{ apply_initial(property_id) }}
{
styleResolver->style()->{{auto_setter}}();
}
{{ apply_inherit(property_id) }}
{
if (styleResolver->parentStyle()->{{auto_getter}}())
styleResolver->style()->{{auto_setter}}();
else
{{ set_value(property) }}(styleResolver->parentStyle()->{{property.getter}}());
}
{{ apply_value(property_id) }}
{
if (!value->isPrimitiveValue())
return;
CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
if (primitiveValue->getValueID() == {{auto_identity}})
styleResolver->style()->{{auto_setter}}();
else
{%- if compute_length %}
{{ set_value(property) }}(primitiveValue->computeLength<{{property.type_name}}>(styleResolver->style(), styleResolver->rootElementStyle(), styleResolver->style()->effectiveZoom()));
{%- else %}
{{ set_value(property) }}(*primitiveValue);
{%- endif %}
}
{%- endmacro %}
{{ apply_auto("CSSPropertyOrphans") }}
{{ apply_auto("CSSPropertyWebkitColumnCount") }}
{{ apply_auto("CSSPropertyWebkitColumnGap", auto_getter="hasNormalColumnGap", auto_setter="setHasNormalColumnGap", auto_identity="CSSValueNormal", compute_length=true) }}
{{ apply_auto("CSSPropertyWebkitColumnWidth", compute_length=true) }}
{{ apply_auto("CSSPropertyWidows") }}
{{ apply_auto("CSSPropertyZIndex") }}
{%- macro apply_value_border_image(property_id) %}
{{ apply_value(property_id) }}
{
{%- set property = properties[property_id] %}
NinePieceImage image;
{%- if property_id == "CSSPropertyWebkitMaskBoxImage" %}
image.setMaskDefaults();
{%- endif %}
styleResolver->styleMap()->mapNinePieceImage({{property_id}}, value, image);
{{ set_value(property) }}(image);
}
{%- endmacro %}
{{ apply_value_border_image("CSSPropertyWebkitBorderImage") }}
{{ apply_value_border_image("CSSPropertyWebkitMaskBoxImage") }}
{%- macro apply_color(property_id, default_getter="color", initial_color=none, inherit_color=false) %}
{%- set property = properties[property_id] %}
{%- call wrap_with_condition(property.condition) %}
{%- set visited_link_setter = "setVisitedLink" + property.camel_case_name %}
{{ apply_initial(property_id) }}
{
Color color = {{ initial_color or "Color" -}}();
if (styleResolver->applyPropertyToRegularStyle())
{{ set_value(property) }}(color);
if (styleResolver->applyPropertyToVisitedLinkStyle())
styleResolver->style()->{{visited_link_setter}}(color);
}
{{ apply_inherit(property_id) }}
{
// Visited link style can never explicitly inherit from parent visited link style so no separate getters are needed.
Color color = styleResolver->parentStyle()->{{property.getter}}();
if (!color.isValid())
color = styleResolver->parentStyle()->{{default_getter}}();
if (styleResolver->applyPropertyToRegularStyle())
{{ set_value(property) }}(color);
if (styleResolver->applyPropertyToVisitedLinkStyle())
styleResolver->style()->{{visited_link_setter}}(color);
}
{{ apply_value(property_id) }}
{
if (!value->isPrimitiveValue())
return;
CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
{%- if inherit_color %}
if (primitiveValue->getValueID() == CSSValueCurrentcolor) {
applyInherit{{property_id}}(styleResolver);
return;
}
{%- endif %}
if (styleResolver->applyPropertyToRegularStyle())
{{ set_value(property) }}(styleResolver->resolveColorFromPrimitiveValue(primitiveValue));
if (styleResolver->applyPropertyToVisitedLinkStyle())
styleResolver->style()->{{visited_link_setter}}(styleResolver->resolveColorFromPrimitiveValue(primitiveValue, /* forVisitedLink */ true));
}
{%- endcall %}
{%- endmacro %}
{{ apply_color("CSSPropertyBackgroundColor", default_getter="invalidColor") }}
{{ apply_color("CSSPropertyBorderBottomColor") }}
{{ apply_color("CSSPropertyBorderLeftColor") }}
{{ apply_color("CSSPropertyBorderRightColor") }}
{{ apply_color("CSSPropertyBorderTopColor") }}
{{ apply_color("CSSPropertyColor", inherit_color=true, default_getter="invalidColor", initial_color="RenderStyle::initialColor") }}
{{ apply_color("CSSPropertyOutlineColor") }}
{{ apply_color("CSSPropertyTextDecorationColor") }}
{{ apply_color("CSSPropertyWebkitColumnRuleColor") }}
{{ apply_color("CSSPropertyWebkitTextEmphasisColor") }}
{{ apply_color("CSSPropertyWebkitTextFillColor") }}
{{ apply_color("CSSPropertyWebkitTextStrokeColor") }}
{%- 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 %}
{{ apply_initial(property_id) }}
{
FillLayer* currChild = styleResolver->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}}();
}
{{ apply_inherit(property_id) }}
{
FillLayer* currChild = styleResolver->style()->{{access_layers}}();
FillLayer* prevChild = 0;
const FillLayer* currParent = styleResolver->parentStyle()->{{layer_type|lower}}Layers();
while (currParent && currParent->is{{fill_type}}Set()) {
if (!currChild) {
/* Need to make a new layer.*/
currChild = new FillLayer({{fill_layer_type}});
prevChild->setNext(currChild);
}
currChild->set{{fill_type}}(currParent->{{lower_first(fill_type)}}());
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();
}
}
{{ apply_value(property_id) }}
{
FillLayer* currChild = styleResolver->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) {
/* Need to make a new layer to hold this value */
currChild = new FillLayer({{fill_layer_type}});
prevChild->setNext(currChild);
}
styleResolver->styleMap()->{{map_fill}}({{property_id}}, currChild, valueList->itemWithoutBoundsCheck(i));
prevChild = currChild;
currChild = currChild->next();
}
} else {
styleResolver->styleMap()->{{map_fill}}({{property_id}}, 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("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) %}
{{ apply_value(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 %}
{{ apply_value_number("CSSPropertyWebkitHyphenateLimitAfter", "CSSValueAuto") }}
{{ apply_value_number("CSSPropertyWebkitHyphenateLimitBefore", "CSSValueAuto") }}
{{ apply_value_number("CSSPropertyWebkitHyphenateLimitLines", "CSSValueNoLimit") }}
{{ apply_value_number("CSSPropertyWebkitMarqueeRepetition", "CSSValueInfinite") }}
{%- macro apply_value_string(property_id, id_for_none) %}
{{ apply_value(property_id) }}
{
{%- set property = properties[property_id] %}
if (!value->isPrimitiveValue())
return;
CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
if (primitiveValue->getValueID() == {{id_for_none}})
{{ set_value(property) }}(nullAtom);
else
{{ set_value(property) }}(primitiveValue->getStringValue());
}
{%- endmacro %}
{{ apply_value_string("CSSPropertyWebkitHighlight", "CSSValueNone") }}
{{ apply_value_string("CSSPropertyWebkitHyphenateCharacter", "CSSValueAuto") }}
{{ apply_value_string("CSSPropertyWebkitLineGrid", "CSSValueNone") }}
{{ apply_value_string("CSSPropertyWebkitFlowFrom", "CSSValueNone") }}
{{ apply_value_string("CSSPropertyWebkitFlowInto", "CSSValueNone") }}
{{ apply_value("CSSPropertyWebkitMarqueeIncrement") }}
{
if (!value->isPrimitiveValue())
return;
CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
if (primitiveValue->getValueID()) {
switch (primitiveValue->getValueID()) {
case CSSValueSmall:
styleResolver->style()->setMarqueeIncrement(Length(1, Fixed)); // 1px.
break;
case CSSValueNormal:
styleResolver->style()->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
break;
case CSSValueLarge:
styleResolver->style()->setMarqueeIncrement(Length(36, Fixed)); // 36px.
break;
default:
break;
}
} else {
Length marqueeLength = styleResolver->convertToIntLength(primitiveValue, styleResolver->style(), styleResolver->rootElementStyle());
if (!marqueeLength.isUndefined())
styleResolver->style()->setMarqueeIncrement(marqueeLength);
}
}
} // namespace WebCore