blob: 77769795943a61dccd41e97c028974499520fa90 [file] [log] [blame]
/*
* 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