blob: 1d47beba58d7e5504ef093741da160f1daf3e209 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/animation/css_font_size_interpolation_type.h"
#include <memory>
#include <utility>
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/animation/interpolable_length.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
namespace blink {
namespace {
class IsMonospaceChecker : public CSSInterpolationType::CSSConversionChecker {
public:
IsMonospaceChecker(bool is_monospace) : is_monospace_(is_monospace) {}
private:
bool IsValid(const StyleResolverState& state,
const InterpolationValue&) const final {
return is_monospace_ == state.Style()->GetFontDescription().IsMonospace();
}
const bool is_monospace_;
};
class InheritedFontSizeChecker
: public CSSInterpolationType::CSSConversionChecker {
public:
InheritedFontSizeChecker(const FontDescription::Size& inherited_font_size)
: inherited_font_size_(inherited_font_size.value) {}
private:
bool IsValid(const StyleResolverState& state,
const InterpolationValue&) const final {
return inherited_font_size_ ==
state.ParentFontDescription().GetSize().value;
}
const float inherited_font_size_;
};
InterpolationValue ConvertFontSize(float size) {
return InterpolationValue(InterpolableLength::CreatePixels(size));
}
InterpolationValue MaybeConvertKeyword(
CSSValueID value_id,
const StyleResolverState& state,
InterpolationType::ConversionCheckers& conversion_checkers) {
if (FontSizeFunctions::IsValidValueID(value_id)) {
bool is_monospace = state.Style()->GetFontDescription().IsMonospace();
conversion_checkers.push_back(
std::make_unique<IsMonospaceChecker>(is_monospace));
return ConvertFontSize(state.GetFontBuilder().FontSizeForKeyword(
FontSizeFunctions::KeywordSize(value_id), is_monospace));
}
if (value_id != CSSValueID::kSmaller && value_id != CSSValueID::kLarger)
return nullptr;
const FontDescription::Size& inherited_font_size =
state.ParentFontDescription().GetSize();
conversion_checkers.push_back(
std::make_unique<InheritedFontSizeChecker>(inherited_font_size));
if (value_id == CSSValueID::kSmaller)
return ConvertFontSize(
FontDescription::SmallerSize(inherited_font_size).value);
return ConvertFontSize(
FontDescription::LargerSize(inherited_font_size).value);
}
} // namespace
InterpolationValue CSSFontSizeInterpolationType::MaybeConvertNeutral(
const InterpolationValue&,
ConversionCheckers&) const {
return InterpolationValue(InterpolableLength::CreateNeutral());
}
InterpolationValue CSSFontSizeInterpolationType::MaybeConvertInitial(
const StyleResolverState& state,
ConversionCheckers& conversion_checkers) const {
return MaybeConvertKeyword(FontSizeFunctions::InitialValueID(), state,
conversion_checkers);
}
InterpolationValue CSSFontSizeInterpolationType::MaybeConvertInherit(
const StyleResolverState& state,
ConversionCheckers& conversion_checkers) const {
const FontDescription::Size& inherited_font_size =
state.ParentFontDescription().GetSize();
conversion_checkers.push_back(
std::make_unique<InheritedFontSizeChecker>(inherited_font_size));
return ConvertFontSize(inherited_font_size.value);
}
InterpolationValue CSSFontSizeInterpolationType::MaybeConvertValue(
const CSSValue& value,
const StyleResolverState* state,
ConversionCheckers& conversion_checkers) const {
std::unique_ptr<InterpolableValue> result =
InterpolableLength::MaybeConvertCSSValue(value);
if (result)
return InterpolationValue(std::move(result));
auto* identifier_value = DynamicTo<CSSIdentifierValue>(value);
if (!identifier_value)
return nullptr;
DCHECK(state);
return MaybeConvertKeyword(identifier_value->GetValueID(), *state,
conversion_checkers);
}
InterpolationValue
CSSFontSizeInterpolationType::MaybeConvertStandardPropertyUnderlyingValue(
const ComputedStyle& style) const {
return ConvertFontSize(style.SpecifiedFontSize());
}
void CSSFontSizeInterpolationType::ApplyStandardPropertyValue(
const InterpolableValue& interpolable_value,
const NonInterpolableValue*,
StyleResolverState& state) const {
const FontDescription& parent_font = state.ParentFontDescription();
Length font_size_length =
To<InterpolableLength>(interpolable_value)
.CreateLength(state.FontSizeConversionData(), kValueRangeNonNegative);
float font_size =
FloatValueForLength(font_size_length, parent_font.GetSize().value);
state.GetFontBuilder().SetSize(FontDescription::Size(
0, font_size,
!font_size_length.IsPercentOrCalc() || parent_font.IsAbsoluteSize()));
}
} // namespace blink