| // Copyright 2014 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "cobalt/cssom/cascaded_style.h" |
| |
| #include <vector> |
| |
| #include "base/optional.h" |
| #include "cobalt/cssom/css_computed_style_data.h" |
| #include "cobalt/cssom/css_declared_style_data.h" |
| #include "cobalt/cssom/css_rule_style_declaration.h" |
| #include "cobalt/cssom/css_style_sheet.h" |
| |
| namespace cobalt { |
| namespace cssom { |
| |
| namespace { |
| |
| void SetPropertyValuesOfHigherPrecedence( |
| const scoped_refptr<const CSSDeclaredStyleData>& style, |
| const CascadePrecedence& precedence_normal, |
| const CascadePrecedence& precedence_important, |
| base::optional<CascadePrecedence>* cascade_precedences, |
| scoped_refptr<CSSComputedStyleData>* cascaded_style, |
| bool* background_image_refreshed) { |
| const CSSDeclaredStyleData::PropertyValues& property_values = |
| style->declared_property_values(); |
| for (CSSDeclaredStyleData::PropertyValues::const_iterator |
| property_value_iterator = property_values.begin(); |
| property_value_iterator != property_values.end(); |
| ++property_value_iterator) { |
| const PropertyKey& key = property_value_iterator->first; |
| DCHECK_GT(key, kNoneProperty); |
| DCHECK_LE(key, kMaxLonghandPropertyKey); |
| |
| const CascadePrecedence& precedence = |
| style->IsDeclaredPropertyImportant(key) ? precedence_important |
| : precedence_normal; |
| if (!(cascade_precedences[key]) || |
| *(cascade_precedences[key]) < precedence) { |
| cascade_precedences[key] = precedence; |
| (*cascaded_style)->SetPropertyValue(key, property_value_iterator->second); |
| if (kBackgroundImageProperty == key) { |
| *background_image_refreshed = true; |
| } |
| } |
| } |
| } |
| |
| } // namespace |
| |
| scoped_refptr<CSSComputedStyleData> PromoteToCascadedStyle( |
| const scoped_refptr<const CSSDeclaredStyleData>& inline_style, |
| RulesWithCascadePrecedence* matching_rules, |
| GURLMap* property_key_to_base_url_map) { |
| scoped_refptr<CSSComputedStyleData> cascaded_style( |
| new CSSComputedStyleData()); |
| |
| // A sparse vector of CascadePrecedence values for all possible property |
| // values. |
| base::optional<CascadePrecedence> |
| cascade_precedences[static_cast<size_t>(kNumLonghandProperties)]; |
| |
| if (inline_style) { |
| const CascadePrecedence precedence_normal = |
| CascadePrecedence(kImportantMin); |
| const CascadePrecedence precedence_important = |
| CascadePrecedence(kImportantMax); |
| bool background_image_refreshed = false; |
| SetPropertyValuesOfHigherPrecedence( |
| inline_style, precedence_normal, precedence_important, |
| cascade_precedences, &cascaded_style, &background_image_refreshed); |
| } |
| |
| if (!matching_rules->empty()) { |
| for (RulesWithCascadePrecedence::const_iterator rule_iterator = |
| matching_rules->begin(); |
| rule_iterator != matching_rules->end(); ++rule_iterator) { |
| const scoped_refptr<const CSSDeclaredStyleData>& declared_style = |
| rule_iterator->first->declared_style_data(); |
| if (declared_style) { |
| const CascadePrecedence& precedence_normal = rule_iterator->second; |
| CascadePrecedence precedence_important = rule_iterator->second; |
| precedence_important.SetImportant(); |
| bool background_image_refreshed = false; |
| SetPropertyValuesOfHigherPrecedence( |
| declared_style, precedence_normal, precedence_important, |
| cascade_precedences, &cascaded_style, &background_image_refreshed); |
| |
| if (background_image_refreshed) { |
| const scoped_refptr<CSSStyleSheet>& parent_style_sheet = |
| rule_iterator->first->parent_style_sheet(); |
| if (parent_style_sheet && |
| parent_style_sheet->LocationUrl().is_valid()) { |
| DCHECK(property_key_to_base_url_map); |
| (*property_key_to_base_url_map)[kBackgroundImageProperty] = |
| parent_style_sheet->LocationUrl(); |
| } |
| } |
| } |
| } |
| } |
| return cascaded_style; |
| } |
| |
| } // namespace cssom |
| } // namespace cobalt |