• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1{% from 'macros.tmpl' import license %}
2{#
3    This file is for property handlers which use the templating engine to
4    reduce (handwritten) code duplication.
5
6    The `properties' dict can be used to access a property's parameters in
7    jinja2 templates (i.e. setter, getter, initial, type_name)
8#}
9#include "config.h"
10#include "StyleBuilderFunctions.h"
11
12#include "CSSValueKeywords.h"
13#include "core/css/BasicShapeFunctions.h"
14#include "core/css/CSSPrimitiveValueMappings.h"
15#include "core/css/Pair.h"
16#include "core/css/resolver/StyleResolverState.h"
17
18{% macro declare_initial_function(property_id) %}
19void StyleBuilderFunctions::applyInitial{{property_id}}(StyleResolverState& state)
20{%- endmacro %}
21{% macro declare_inherit_function(property_id) %}
22void StyleBuilderFunctions::applyInherit{{property_id}}(StyleResolverState& state)
23{%- endmacro %}
24{% macro declare_value_function(property_id) %}
25void StyleBuilderFunctions::applyValue{{property_id}}(StyleResolverState& state, CSSValue* value)
26{%- endmacro %}
27{% macro set_value(property) %}
28{% if property.svg %}
29state.style()->accessSVGStyle().{{property.setter}}
30{%- elif property.font %}
31state.fontBuilder().{{property.setter}}
32{%- else %}
33state.style()->{{property.setter}}
34{%- endif %}
35{% endmacro %}
36{% macro convert_and_set_value(property) %}
37{% if property.converter %}
38{{set_value(property)}}(StyleBuilderConverter::{{property.converter}}(state, value));
39{%- else %}
40{{set_value(property)}}(static_cast<{{property.type_name}}>(*toCSSPrimitiveValue(value)));
41{%- endif %}
42{% endmacro %}
43
44namespace blink {
45
46{% for property_id, property in properties.items() if property.should_declare_functions %}
47{% set apply_type = property.apply_type %}
48{% if not property.custom_initial %}
49{{declare_initial_function(property_id)}}
50{
51    {% if property.svg %}
52    {{set_value(property)}}(SVGRenderStyle::{{property.initial}}());
53    {% elif property.font %}
54    {{set_value(property)}}(FontBuilder::{{property.initial}}());
55    {% else %}
56    {{set_value(property)}}(RenderStyle::{{property.initial}}());
57    {% endif %}
58}
59
60{% endif %}
61{% if not property.custom_inherit %}
62{{declare_inherit_function(property_id)}}
63{
64    {% if property.svg %}
65    {{set_value(property)}}(state.parentStyle()->svgStyle().{{property.getter}}());
66    {% elif property.font %}
67    {{set_value(property)}}(state.parentFontDescription().{{property.getter}}());
68    {% else %}
69    {{set_value(property)}}(state.parentStyle()->{{property.getter}}());
70    {% endif %}
71}
72
73{% endif %}
74{% if not property.custom_value %}
75{{declare_value_function(property_id)}}
76{
77    {{convert_and_set_value(property)}}
78}
79
80{% endif %}
81{% endfor %}
82
83{% macro apply_animation(property_id, attribute, animation) %}
84{% set vector = attribute|lower_first + "List()" %}
85{{declare_initial_function(property_id)}}
86{
87    CSS{{animation}}Data& data = state.style()->access{{animation}}s();
88    data.{{vector}}.clear();
89    data.{{vector}}.append(CSS{{animation}}Data::initial{{attribute}}());
90}
91
92{{declare_inherit_function(property_id)}}
93{
94    const CSS{{animation}}Data* parentData = state.parentStyle()->{{animation|lower}}s();
95    if (!parentData)
96        applyInitial{{property_id}}(state);
97    else
98        state.style()->access{{animation}}s().{{vector}} = parentData->{{vector}};
99}
100
101{{declare_value_function(property_id)}}
102{
103    CSS{{animation}}Data& data = state.style()->access{{animation}}s();
104    data.{{vector}}.clear();
105    for (CSSValueListIterator i = value; i.hasMore(); i.advance())
106        data.{{vector}}.append(state.styleMap().mapAnimation{{attribute}}(i.value()));
107}
108{% endmacro %}
109{{apply_animation('CSSPropertyWebkitAnimationDelay', 'Delay', 'Animation')}}
110{{apply_animation('CSSPropertyWebkitAnimationDirection', 'Direction', 'Animation')}}
111{{apply_animation('CSSPropertyWebkitAnimationDuration', 'Duration', 'Animation')}}
112{{apply_animation('CSSPropertyWebkitAnimationFillMode', 'FillMode', 'Animation')}}
113{{apply_animation('CSSPropertyWebkitAnimationIterationCount', 'IterationCount', 'Animation')}}
114{{apply_animation('CSSPropertyWebkitAnimationName', 'Name', 'Animation')}}
115{{apply_animation('CSSPropertyWebkitAnimationPlayState', 'PlayState', 'Animation')}}
116{{apply_animation('CSSPropertyWebkitAnimationTimingFunction', 'TimingFunction', 'Animation')}}
117{{apply_animation('CSSPropertyWebkitTransitionDelay', 'Delay', 'Transition')}}
118{{apply_animation('CSSPropertyWebkitTransitionDuration', 'Duration', 'Transition')}}
119{{apply_animation('CSSPropertyWebkitTransitionProperty', 'Property', 'Transition')}}
120{{apply_animation('CSSPropertyWebkitTransitionTimingFunction', 'TimingFunction', 'Transition')}}
121
122{% macro apply_auto(property_id, auto_getter=none, auto_setter=none, auto_identity='CSSValueAuto') %}
123{% set property = properties[property_id] %}
124{% set auto_getter = auto_getter or 'hasAuto' + property.name_for_methods %}
125{% set auto_setter = auto_setter or 'setHasAuto' + property.name_for_methods %}
126{{declare_initial_function(property_id)}}
127{
128    state.style()->{{auto_setter}}();
129}
130
131{{declare_inherit_function(property_id)}}
132{
133    if (state.parentStyle()->{{auto_getter}}())
134        state.style()->{{auto_setter}}();
135    else
136        {{set_value(property)}}(state.parentStyle()->{{property.getter}}());
137}
138
139{{declare_value_function(property_id)}}
140{
141    if (!value->isPrimitiveValue())
142        return;
143
144    CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
145    if (primitiveValue->getValueID() == {{auto_identity}})
146        state.style()->{{auto_setter}}();
147    else
148        {{convert_and_set_value(property)}}
149}
150{% endmacro %}
151{{apply_auto('CSSPropertyClip')}}
152{{apply_auto('CSSPropertyOrphans')}}
153{{apply_auto('CSSPropertyWebkitColumnCount')}}
154{{apply_auto('CSSPropertyWebkitColumnGap', auto_getter='hasNormalColumnGap', auto_setter='setHasNormalColumnGap', auto_identity='CSSValueNormal')}}
155{{apply_auto('CSSPropertyWebkitColumnWidth')}}
156{{apply_auto('CSSPropertyWidows')}}
157{{apply_auto('CSSPropertyZIndex')}}
158
159static bool lengthTypeAndValueMatch(const Length& length, LengthType type, float value)
160{
161    return length.type() == type && length.value() == value;
162}
163
164static bool lengthTypeAndValueMatch(const LengthBox& lengthBox, LengthType type, float value)
165{
166    return (lengthTypeAndValueMatch(lengthBox.left(), type, value)
167        && lengthTypeAndValueMatch(lengthBox.right(), type, value)
168        && lengthTypeAndValueMatch(lengthBox.top(), type, value)
169        && lengthTypeAndValueMatch(lengthBox.bottom(), type, value));
170}
171
172static bool lengthTypeAndValueMatch(const BorderImageLength& borderImageLength, LengthType type, float value)
173{
174    return borderImageLength.isLength() && lengthTypeAndValueMatch(borderImageLength.length(), type, value);
175}
176
177static bool lengthTypeAndValueMatch(const BorderImageLengthBox& borderImageLengthBox, LengthType type, float value)
178{
179    return (lengthTypeAndValueMatch(borderImageLengthBox.left(), type, value)
180        && lengthTypeAndValueMatch(borderImageLengthBox.right(), type, value)
181        && lengthTypeAndValueMatch(borderImageLengthBox.top(), type, value)
182        && lengthTypeAndValueMatch(borderImageLengthBox.bottom(), type, value));
183}
184
185{% macro apply_border_image_modifier(property_id, modifier_type) %}
186{% set is_mask_box = 'MaskBox' in property_id %}
187{% set getter = 'maskBoxImage' if is_mask_box else 'borderImage' %}
188{% set setter = 'setMaskBoxImage' if is_mask_box else 'setBorderImage' %}
189{{ declare_initial_function(property_id) }}
190{
191    const NinePieceImage& currentImage = state.style()->{{getter}}();
192    {# Check for equality in case we can bail out before creating a new NinePieceImage. #}
193    {% if modifier_type == 'Outset' %}
194    if (lengthTypeAndValueMatch(currentImage.outset(), Fixed, 0))
195        return;
196    {% elif modifier_type == 'Repeat' %}
197    if (currentImage.horizontalRule() == StretchImageRule && currentImage.verticalRule() == StretchImageRule)
198        return;
199    {% elif modifier_type == 'Slice' and is_mask_box %}
200    // Masks have a different initial value for slices. Preserve the value of 0 for backwards compatibility.
201    if (currentImage.fill() == true && lengthTypeAndValueMatch(currentImage.imageSlices(), Fixed, 0))
202        return;
203    {% elif modifier_type == 'Slice' and not is_mask_box %}
204    if (currentImage.fill() == false && lengthTypeAndValueMatch(currentImage.imageSlices(), Percent, 100))
205        return;
206    {% elif modifier_type == 'Width' and is_mask_box %}
207    // Masks have a different initial value for widths. Preserve the value of 'auto' for backwards compatibility.
208    if (lengthTypeAndValueMatch(currentImage.borderSlices(), Auto, 0))
209        return;
210    {% elif modifier_type == 'Width' and not is_mask_box %}
211    if (lengthTypeAndValueMatch(currentImage.borderSlices(), Fixed, 1))
212        return;
213    {% endif %}
214
215    NinePieceImage image(currentImage);
216    {% if modifier_type == 'Outset' %}
217    image.setOutset(Length(0, Fixed));
218    {% elif modifier_type == 'Repeat' %}
219    image.setHorizontalRule(StretchImageRule);
220    image.setVerticalRule(StretchImageRule);
221    {% elif modifier_type == 'Slice' and is_mask_box %}
222    image.setImageSlices(LengthBox({{ (['Length(0, Fixed)']*4) | join(', ') }}));
223    image.setFill(true);
224    {% elif modifier_type == 'Slice' and not is_mask_box %}
225    image.setImageSlices(LengthBox({{ (['Length(100, Percent)']*4) | join(', ') }}));
226    image.setFill(false);
227    {% elif modifier_type == 'Width' %}
228    image.setBorderSlices({{ 'Length(Auto)' if is_mask_box else '1.0' }});
229    {% endif %}
230    state.style()->{{setter}}(image);
231}
232
233{{declare_inherit_function(property_id)}}
234{
235    NinePieceImage image(state.style()->{{getter}}());
236    {% if modifier_type == 'Outset' %}
237    image.copyOutsetFrom(state.parentStyle()->{{getter}}());
238    {% elif modifier_type == 'Repeat' %}
239    image.copyRepeatFrom(state.parentStyle()->{{getter}}());
240    {% elif modifier_type == 'Slice' %}
241    image.copyImageSlicesFrom(state.parentStyle()->{{getter}}());
242    {% elif modifier_type == 'Width' %}
243    image.copyBorderSlicesFrom(state.parentStyle()->{{getter}}());
244    {% endif %}
245    state.style()->{{setter}}(image);
246}
247
248{{declare_value_function(property_id)}}
249{
250    NinePieceImage image(state.style()->{{getter}}());
251    {% if modifier_type == 'Outset' %}
252    image.setOutset(state.styleMap().mapNinePieceImageQuad(value));
253    {% elif modifier_type == 'Repeat' %}
254    state.styleMap().mapNinePieceImageRepeat(value, image);
255    {% elif modifier_type == 'Slice' %}
256    state.styleMap().mapNinePieceImageSlice(value, image);
257    {% elif modifier_type == 'Width' %}
258    image.setBorderSlices(state.styleMap().mapNinePieceImageQuad(value));
259    {% endif %}
260    state.style()->{{setter}}(image);
261}
262{% endmacro %}
263{{apply_border_image_modifier('CSSPropertyBorderImageOutset', 'Outset')}}
264{{apply_border_image_modifier('CSSPropertyBorderImageRepeat', 'Repeat')}}
265{{apply_border_image_modifier('CSSPropertyBorderImageSlice', 'Slice')}}
266{{apply_border_image_modifier('CSSPropertyBorderImageWidth', 'Width')}}
267{{apply_border_image_modifier('CSSPropertyWebkitMaskBoxImageOutset', 'Outset')}}
268{{apply_border_image_modifier('CSSPropertyWebkitMaskBoxImageRepeat', 'Repeat')}}
269{{apply_border_image_modifier('CSSPropertyWebkitMaskBoxImageSlice', 'Slice')}}
270{{apply_border_image_modifier('CSSPropertyWebkitMaskBoxImageWidth', 'Width')}}
271
272{% macro apply_value_border_image_source(property_id) %}
273{{declare_value_function(property_id)}}
274{
275    {% set property = properties[property_id] %}
276    {{set_value(property)}}(state.styleImage({{property_id}}, value));
277}
278{% endmacro %}
279{{apply_value_border_image_source('CSSPropertyBorderImageSource')}}
280{{apply_value_border_image_source('CSSPropertyWebkitMaskBoxImageSource')}}
281
282{% macro apply_color(property_id, initial_color='StyleColor::currentColor') %}
283{% set property = properties[property_id] %}
284{% set visited_link_setter = 'setVisitedLink' + property.name_for_methods %}
285{{declare_initial_function(property_id)}}
286{
287    StyleColor color = {{initial_color}}();
288    if (state.applyPropertyToRegularStyle())
289        {{set_value(property)}}(color);
290    if (state.applyPropertyToVisitedLinkStyle())
291        state.style()->{{visited_link_setter}}(color);
292}
293
294{{declare_inherit_function(property_id)}}
295{
296    // Visited link style can never explicitly inherit from parent visited link style so no separate getters are needed.
297    StyleColor color = state.parentStyle()->{{property.getter}}();
298    Color resolvedColor = color.resolve(state.parentStyle()->color());
299    if (state.applyPropertyToRegularStyle())
300        {{set_value(property)}}(resolvedColor);
301    if (state.applyPropertyToVisitedLinkStyle())
302        state.style()->{{visited_link_setter}}(resolvedColor);
303}
304
305{{declare_value_function(property_id)}}
306{
307    if (state.applyPropertyToRegularStyle())
308        {{set_value(property)}}(StyleBuilderConverter::convertStyleColor(state, value));
309    if (state.applyPropertyToVisitedLinkStyle())
310        state.style()->{{visited_link_setter}}(StyleBuilderConverter::convertStyleColor(state, value, true));
311}
312{% endmacro %}
313{{apply_color('CSSPropertyBackgroundColor', initial_color='RenderStyle::initialBackgroundColor') }}
314{{apply_color('CSSPropertyBorderBottomColor')}}
315{{apply_color('CSSPropertyBorderLeftColor')}}
316{{apply_color('CSSPropertyBorderRightColor')}}
317{{apply_color('CSSPropertyBorderTopColor')}}
318{{apply_color('CSSPropertyOutlineColor')}}
319{{apply_color('CSSPropertyTextDecorationColor')}}
320{{apply_color('CSSPropertyWebkitColumnRuleColor')}}
321{{apply_color('CSSPropertyWebkitTextEmphasisColor')}}
322{{apply_color('CSSPropertyWebkitTextFillColor')}}
323{{apply_color('CSSPropertyWebkitTextStrokeColor')}}
324
325{% macro apply_counter(property_id, action) %}
326{% set property = properties[property_id] %}
327{{declare_initial_function(property_id)}} { }
328
329{{declare_inherit_function(property_id)}}
330{
331    CounterDirectiveMap& map = state.style()->accessCounterDirectives();
332    CounterDirectiveMap& parentMap = state.parentStyle()->accessCounterDirectives();
333
334    typedef CounterDirectiveMap::iterator Iterator;
335    Iterator end = parentMap.end();
336    for (Iterator it = parentMap.begin(); it != end; ++it) {
337        CounterDirectives& directives = map.add(it->key, CounterDirectives()).storedValue->value;
338        directives.inherit{{action}}(it->value);
339    }
340}
341
342{{declare_value_function(property_id)}}
343{
344    CounterDirectiveMap& map = state.style()->accessCounterDirectives();
345    typedef CounterDirectiveMap::iterator Iterator;
346
347    Iterator end = map.end();
348    for (Iterator it = map.begin(); it != end; ++it)
349        it->value.clear{{action}}();
350
351    if (!value->isValueList()) {
352        ASSERT(value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueNone);
353        return;
354    }
355
356    CSSValueList* list = toCSSValueList(value);
357
358    int length = list ? list->length() : 0;
359    for (int i = 0; i < length; ++i) {
360        CSSValue* currValue = list->item(i);
361        if (!currValue->isPrimitiveValue())
362            continue;
363
364        Pair* pair = toCSSPrimitiveValue(currValue)->getPairValue();
365        if (!pair || !pair->first() || !pair->second())
366            continue;
367
368        AtomicString identifier(pair->first()->getStringValue());
369        int value = pair->second()->getIntValue();
370        CounterDirectives& directives = map.add(identifier, CounterDirectives()).storedValue->value;
371        {% if action == 'Reset' %}
372        directives.setResetValue(value);
373        {% else %}
374        directives.addIncrementValue(value);
375        {% endif %}
376    }
377}
378{% endmacro %}
379{{apply_counter('CSSPropertyCounterIncrement', 'Increment')}}
380{{apply_counter('CSSPropertyCounterReset', 'Reset')}}
381
382{% macro apply_fill_layer(property_id, fill_type) %}
383{% set layer_type = 'Background' if 'Background' in property_id else 'Mask' %}
384{% set fill_layer_type = layer_type + 'FillLayer' %}
385{% set access_layers = 'access' + layer_type + 'Layers' %}
386{% set map_fill = 'mapFill' + fill_type %}
387{{declare_initial_function(property_id)}}
388{
389    FillLayer* currChild = &state.style()->{{access_layers}}();
390    currChild->set{{fill_type}}(FillLayer::initialFill{{fill_type}}({{fill_layer_type}}));
391    for (currChild = currChild->next(); currChild; currChild = currChild->next())
392        currChild->clear{{fill_type}}();
393}
394
395{{declare_inherit_function(property_id)}}
396{
397    FillLayer* currChild = &state.style()->{{access_layers}}();
398    FillLayer* prevChild = 0;
399    const FillLayer* currParent = &state.parentStyle()->{{layer_type|lower}}Layers();
400    while (currParent && currParent->is{{fill_type}}Set()) {
401        if (!currChild)
402            currChild = prevChild->ensureNext();
403        currChild->set{{fill_type}}(currParent->{{fill_type|lower_first}}());
404        prevChild = currChild;
405        currChild = prevChild->next();
406        currParent = currParent->next();
407    }
408
409    while (currChild) {
410        /* Reset any remaining layers to not have the property set. */
411        currChild->clear{{fill_type}}();
412        currChild = currChild->next();
413    }
414}
415
416{{declare_value_function(property_id)}}
417{
418    FillLayer* currChild = &state.style()->{{access_layers}}();
419    FillLayer* prevChild = 0;
420    if (value->isValueList() && !value->isImageSetValue()) {
421        /* Walk each value and put it into a layer, creating new layers as needed. */
422        CSSValueList* valueList = toCSSValueList(value);
423        for (unsigned int i = 0; i < valueList->length(); i++) {
424            if (!currChild)
425                currChild = prevChild->ensureNext();
426            state.styleMap().{{map_fill}}(currChild, valueList->item(i));
427            prevChild = currChild;
428            currChild = currChild->next();
429        }
430    } else {
431        state.styleMap().{{map_fill}}(currChild, value);
432        currChild = currChild->next();
433    }
434    while (currChild) {
435        /* Reset all remaining layers to not have the property set. */
436        currChild->clear{{fill_type}}();
437        currChild = currChild->next();
438    }
439}
440{% endmacro %}
441{{apply_fill_layer('CSSPropertyBackgroundAttachment', 'Attachment')}}
442{{apply_fill_layer('CSSPropertyBackgroundBlendMode', 'BlendMode')}}
443{{apply_fill_layer('CSSPropertyBackgroundClip', 'Clip')}}
444{{apply_fill_layer('CSSPropertyBackgroundImage', 'Image')}}
445{{apply_fill_layer('CSSPropertyBackgroundOrigin', 'Origin')}}
446{{apply_fill_layer('CSSPropertyBackgroundPositionX', 'XPosition')}}
447{{apply_fill_layer('CSSPropertyBackgroundPositionY', 'YPosition')}}
448{{apply_fill_layer('CSSPropertyBackgroundRepeatX', 'RepeatX')}}
449{{apply_fill_layer('CSSPropertyBackgroundRepeatY', 'RepeatY')}}
450{{apply_fill_layer('CSSPropertyBackgroundSize', 'Size')}}
451{{apply_fill_layer('CSSPropertyMaskSourceType', 'MaskSourceType')}}
452{{apply_fill_layer('CSSPropertyWebkitBackgroundComposite', 'Composite')}}
453{{apply_fill_layer('CSSPropertyWebkitMaskClip', 'Clip')}}
454{{apply_fill_layer('CSSPropertyWebkitMaskComposite', 'Composite')}}
455{{apply_fill_layer('CSSPropertyWebkitMaskImage', 'Image')}}
456{{apply_fill_layer('CSSPropertyWebkitMaskOrigin', 'Origin')}}
457{{apply_fill_layer('CSSPropertyWebkitMaskPositionX', 'XPosition')}}
458{{apply_fill_layer('CSSPropertyWebkitMaskPositionY', 'YPosition')}}
459{{apply_fill_layer('CSSPropertyWebkitMaskRepeatX', 'RepeatX')}}
460{{apply_fill_layer('CSSPropertyWebkitMaskRepeatY', 'RepeatY')}}
461{{apply_fill_layer('CSSPropertyWebkitMaskSize', 'Size')}}
462
463{% macro apply_grid_template(property_id, type) %}
464{{declare_initial_function(property_id)}}
465{
466    state.style()->setGridTemplate{{type}}s(RenderStyle::initialGridTemplate{{type}}s());
467    state.style()->setNamedGrid{{type}}Lines(RenderStyle::initialNamedGrid{{type}}Lines());
468    state.style()->setOrderedNamedGrid{{type}}Lines(RenderStyle::initialOrderedNamedGrid{{type}}Lines());
469}
470
471{{declare_inherit_function(property_id)}}
472{
473    state.style()->setGridTemplate{{type}}s(state.parentStyle()->gridTemplate{{type}}s());
474    state.style()->setNamedGrid{{type}}Lines(state.parentStyle()->namedGrid{{type}}Lines());
475    state.style()->setOrderedNamedGrid{{type}}Lines(state.parentStyle()->orderedNamedGrid{{type}}Lines());
476}
477
478{{declare_value_function(property_id)}}
479{
480    Vector<GridTrackSize> trackSizes;
481    NamedGridLinesMap namedGridLines;
482    OrderedNamedGridLines orderedNamedGridLines;
483    if (!StyleBuilderConverter::convertGridTrackList(value, trackSizes, namedGridLines, orderedNamedGridLines, state))
484        return;
485    const NamedGridAreaMap& namedGridAreas = state.style()->namedGridArea();
486    if (!namedGridAreas.isEmpty())
487        StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(namedGridAreas, namedGridLines, For{{type}}s);
488    state.style()->setGridTemplate{{type}}s(trackSizes);
489    state.style()->setNamedGrid{{type}}Lines(namedGridLines);
490    state.style()->setOrderedNamedGrid{{type}}Lines(orderedNamedGridLines);
491}
492{% endmacro %}
493{{apply_grid_template('CSSPropertyGridTemplateColumns', 'Column')}}
494{{apply_grid_template('CSSPropertyGridTemplateRows', 'Row')}}
495
496{% macro apply_value_number(property_id, id_for_minus_one) %}
497{{declare_value_function(property_id)}}
498{
499    {% set property = properties[property_id] %}
500    if (!value->isPrimitiveValue())
501        return;
502
503    CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
504    if (primitiveValue->getValueID() == {{id_for_minus_one}})
505        {{set_value(property)}}(-1);
506    else
507        {{set_value(property)}}(primitiveValue->getValue<{{property.type_name}}>(CSSPrimitiveValue::CSS_NUMBER));
508}
509{% endmacro %}
510{{apply_value_number('CSSPropertyInternalMarqueeRepetition', 'CSSValueInfinite')}}
511
512{% macro apply_value_shape(property_id) %}
513{{declare_value_function(property_id)}}
514{
515    {% set property = properties[property_id] %}
516    if (value->isPrimitiveValue()) {
517        CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
518        if (primitiveValue->getValueID() == CSSValueNone)
519            {{set_value(property)}}(nullptr);
520    } else if (value->isImageValue() || value->isImageGeneratorValue() || value->isImageSetValue()) {
521        {{set_value(property)}}(ShapeValue::createImageValue(state.styleImage({{property_id}}, value)));
522    } else if (value->isValueList()) {
523        RefPtr<BasicShape> shape;
524        CSSBoxType cssBox = BoxMissing;
525        CSSValueList* valueList = toCSSValueList(value);
526        for (unsigned i = 0; i < valueList->length(); ++i) {
527            CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(valueList->item(i));
528            if (primitiveValue->isShape())
529                shape = basicShapeForValue(state, primitiveValue->getShapeValue());
530            else if (primitiveValue->getValueID() == CSSValueContentBox
531                || primitiveValue->getValueID() == CSSValueBorderBox
532                || primitiveValue->getValueID() == CSSValuePaddingBox
533                || primitiveValue->getValueID() == CSSValueMarginBox)
534                cssBox = CSSBoxType(*primitiveValue);
535            else
536                return;
537        }
538
539        if (shape)
540            {{set_value(property)}}(ShapeValue::createShapeValue(shape.release(), cssBox));
541        else if (cssBox != BoxMissing)
542            {{set_value(property)}}(ShapeValue::createBoxShapeValue(cssBox));
543    }
544}
545{% endmacro %}
546{{apply_value_shape('CSSPropertyShapeOutside')}}
547
548{% macro apply_alignment(property_id, alignment_type) %}
549{% set property = properties[property_id] %}
550{{declare_initial_function(property_id)}}
551{
552    state.style()->set{{alignment_type}}(RenderStyle::initial{{alignment_type}}());
553    state.style()->set{{alignment_type}}OverflowAlignment(RenderStyle::initial{{alignment_type}}OverflowAlignment());
554}
555
556{{declare_inherit_function(property_id)}}
557{
558    state.style()->set{{alignment_type}}(state.parentStyle()->{{property.getter}}());
559    state.style()->set{{alignment_type}}OverflowAlignment(state.parentStyle()->{{property.getter}}OverflowAlignment());
560}
561
562{{declare_value_function(property_id)}}
563{
564    CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
565    if (Pair* pairValue = primitiveValue->getPairValue()) {
566        state.style()->set{{alignment_type}}(*pairValue->first());
567        state.style()->set{{alignment_type}}OverflowAlignment(*pairValue->second());
568    } else {
569        state.style()->set{{alignment_type}}(*primitiveValue);
570    }
571}
572{% endmacro %}
573{{apply_alignment('CSSPropertyJustifySelf', 'JustifySelf')}}
574{{apply_alignment('CSSPropertyAlignItems', 'AlignItems')}}
575{{apply_alignment('CSSPropertyAlignSelf', 'AlignSelf')}}
576
577{% macro apply_svg_paint(property_id, paint_type) %}
578{% set property = properties[property_id] %}
579{{declare_initial_function(property_id)}}
580{
581    {{set_value(property)}}(
582        SVGRenderStyle::initial{{paint_type}}Type(),
583        SVGRenderStyle::initial{{paint_type}}Color(),
584        SVGRenderStyle::initial{{paint_type}}Uri(),
585        state.applyPropertyToRegularStyle(),
586        state.applyPropertyToVisitedLinkStyle());
587}
588
589{{declare_inherit_function(property_id)}}
590{
591    const SVGRenderStyle& svgParentStyle = state.parentStyle()->svgStyle();
592    {{set_value(property)}}(
593        svgParentStyle.{{paint_type|lower_first}}Type(),
594        svgParentStyle.{{paint_type|lower_first}}Color(),
595        svgParentStyle.{{paint_type|lower_first}}Uri(),
596        state.applyPropertyToRegularStyle(),
597        state.applyPropertyToVisitedLinkStyle());
598}
599
600{{declare_value_function(property_id)}}
601{
602    String url;
603    if (value->isValueList()) {
604        CSSValueList* list = toCSSValueList(value);
605        ASSERT(list->length() > 1);
606
607        if (!list->item(0)->isPrimitiveValue())
608            return;
609
610        CSSPrimitiveValue* pValue = toCSSPrimitiveValue(list->item(0));
611        if (!pValue->isURI())
612            return;
613
614        url = pValue->getStringValue();
615        value = list->item(1);
616    }
617    if (value->isPrimitiveValue()) {
618        CSSPrimitiveValue* pValue = toCSSPrimitiveValue(value);
619        Color c;
620        SVGPaintType ptype = SVG_PAINTTYPE_RGBCOLOR;
621        if (pValue->isRGBColor()) {
622            c = pValue->getRGBA32Value();
623            ptype = url.isEmpty() ? SVG_PAINTTYPE_RGBCOLOR : SVG_PAINTTYPE_URI_RGBCOLOR;
624        } else if (pValue->getValueID() == CSSValueCurrentcolor) {
625            c = state.style()->color();
626            ptype = url.isEmpty() ? SVG_PAINTTYPE_CURRENTCOLOR : SVG_PAINTTYPE_URI_CURRENTCOLOR;
627        } else if (pValue->getValueID() == CSSValueNone) {
628            ptype = url.isEmpty() ? SVG_PAINTTYPE_NONE : SVG_PAINTTYPE_URI_NONE;
629        } else if (pValue->isURI()) {
630            ptype = SVG_PAINTTYPE_URI;
631            url = pValue->getStringValue();
632        } else {
633            return;
634        }
635        {{set_value(property)}}(ptype, c, url,
636            state.applyPropertyToRegularStyle(),
637            state.applyPropertyToVisitedLinkStyle());
638    }
639}
640{% endmacro %}
641{{apply_svg_paint('CSSPropertyFill', 'FillPaint')}}
642{{apply_svg_paint('CSSPropertyStroke', 'StrokePaint')}}
643} // namespace blink
644