mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-25 18:07:31 +09:00
Issue #1826 - Implement broader CSS calc() parsing
This commit is contained in:
parent
7e0818c9ec
commit
41cd9dbe88
4 changed files with 284 additions and 16 deletions
|
|
@ -170,6 +170,153 @@ struct ReducePercentageCalcOps : ReduceNumberCalcOps
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ReduceDimensionCalcOps : public mozilla::css::BasicFloatCalcOps,
|
||||||
|
public mozilla::css::CSSValueInputCalcOps,
|
||||||
|
public mozilla::css::NumbersAlreadyNormalizedOps
|
||||||
|
{
|
||||||
|
enum class DimensionType {
|
||||||
|
Angle,
|
||||||
|
Time,
|
||||||
|
Frequency,
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit ReduceDimensionCalcOps(DimensionType aDimensionType)
|
||||||
|
: mDimensionType(aDimensionType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type ComputeLeafValue(const nsCSSValue& aValue)
|
||||||
|
{
|
||||||
|
switch (mDimensionType) {
|
||||||
|
case DimensionType::Angle:
|
||||||
|
MOZ_ASSERT(aValue.IsAngularUnit(), "unexpected unit");
|
||||||
|
return aValue.GetAngleValueInDegrees();
|
||||||
|
|
||||||
|
case DimensionType::Time:
|
||||||
|
MOZ_ASSERT(aValue.IsTimeUnit(), "unexpected unit");
|
||||||
|
return aValue.GetUnit() == eCSSUnit_Seconds
|
||||||
|
? aValue.GetFloatValue()
|
||||||
|
: aValue.GetFloatValue() / float(PR_MSEC_PER_SEC);
|
||||||
|
|
||||||
|
case DimensionType::Frequency:
|
||||||
|
MOZ_ASSERT(aValue.IsFrequencyUnit(), "unexpected unit");
|
||||||
|
return aValue.GetUnit() == eCSSUnit_Kilohertz
|
||||||
|
? aValue.GetFloatValue() * 1000.0f
|
||||||
|
: aValue.GetFloatValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT_UNREACHABLE("unexpected dimension type");
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
DimensionType mDimensionType;
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
GetCalcParseVariantMask(uint32_t aVariantMask)
|
||||||
|
{
|
||||||
|
uint32_t calcVariantMask = 0;
|
||||||
|
|
||||||
|
if (aVariantMask & VARIANT_LENGTH) {
|
||||||
|
calcVariantMask |= VARIANT_LENGTH | (aVariantMask & VARIANT_ABSOLUTE_DIMENSION);
|
||||||
|
}
|
||||||
|
if (aVariantMask & VARIANT_PERCENT) {
|
||||||
|
calcVariantMask |= VARIANT_PERCENT;
|
||||||
|
}
|
||||||
|
if (aVariantMask & VARIANT_ANGLE) {
|
||||||
|
calcVariantMask |= VARIANT_ANGLE;
|
||||||
|
}
|
||||||
|
if (aVariantMask & VARIANT_TIME) {
|
||||||
|
calcVariantMask |= VARIANT_TIME;
|
||||||
|
}
|
||||||
|
if (aVariantMask & VARIANT_FREQUENCY) {
|
||||||
|
calcVariantMask |= VARIANT_FREQUENCY;
|
||||||
|
}
|
||||||
|
if (aVariantMask & (VARIANT_NUMBER | VARIANT_INTEGER)) {
|
||||||
|
calcVariantMask |= VARIANT_NUMBER;
|
||||||
|
}
|
||||||
|
if (aVariantMask & VARIANT_OPACITY) {
|
||||||
|
calcVariantMask |= VARIANT_PN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return calcVariantMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ShouldPreserveCalcValue(uint32_t aVariantMask)
|
||||||
|
{
|
||||||
|
return (aVariantMask & VARIANT_LENGTH) != 0 ||
|
||||||
|
((aVariantMask & VARIANT_PERCENT) != 0 &&
|
||||||
|
(aVariantMask & (VARIANT_NUMBER | VARIANT_INTEGER |
|
||||||
|
VARIANT_OPACITY)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t
|
||||||
|
RoundFloatToCSSInteger(float aValue)
|
||||||
|
{
|
||||||
|
double rounded = std::floor(double(aValue) + 0.5);
|
||||||
|
rounded = mozilla::clamped(
|
||||||
|
rounded,
|
||||||
|
double(std::numeric_limits<int32_t>::min()),
|
||||||
|
double(std::numeric_limits<int32_t>::max()));
|
||||||
|
return int32_t(rounded);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
NormalizeCalcForVariant(nsCSSValue& aValue,
|
||||||
|
uint32_t aPropertyVariantMask,
|
||||||
|
uint32_t aResultVariantMask)
|
||||||
|
{
|
||||||
|
if (ShouldPreserveCalcValue(aPropertyVariantMask)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aResultVariantMask == VARIANT_NUMBER) {
|
||||||
|
ReduceNumberCalcOps ops;
|
||||||
|
float value = mozilla::css::ComputeCalc(aValue, ops);
|
||||||
|
|
||||||
|
if (aPropertyVariantMask & VARIANT_INTEGER) {
|
||||||
|
aValue.SetIntValue(RoundFloatToCSSInteger(value), eCSSUnit_Integer);
|
||||||
|
} else {
|
||||||
|
aValue.SetFloatValue(value, eCSSUnit_Number);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aResultVariantMask & VARIANT_PERCENT) {
|
||||||
|
ReducePercentageCalcOps ops;
|
||||||
|
float value = mozilla::css::ComputeCalc(aValue, ops);
|
||||||
|
|
||||||
|
if (aPropertyVariantMask & VARIANT_OPACITY) {
|
||||||
|
aValue.SetFloatValue(value, eCSSUnit_Number);
|
||||||
|
} else {
|
||||||
|
aValue.SetPercentValue(value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aResultVariantMask & VARIANT_ANGLE) {
|
||||||
|
ReduceDimensionCalcOps ops(ReduceDimensionCalcOps::DimensionType::Angle);
|
||||||
|
aValue.SetFloatValue(mozilla::css::ComputeCalc(aValue, ops), eCSSUnit_Degree);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aResultVariantMask & VARIANT_TIME) {
|
||||||
|
ReduceDimensionCalcOps ops(ReduceDimensionCalcOps::DimensionType::Time);
|
||||||
|
aValue.SetFloatValue(mozilla::css::ComputeCalc(aValue, ops), eCSSUnit_Seconds);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aResultVariantMask & VARIANT_FREQUENCY) {
|
||||||
|
ReduceDimensionCalcOps ops(ReduceDimensionCalcOps::DimensionType::Frequency);
|
||||||
|
aValue.SetFloatValue(mozilla::css::ComputeCalc(aValue, ops), eCSSUnit_Hertz);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT_UNREACHABLE("unsupported calc result type");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static_assert(css::eAuthorSheetFeatures == 0 &&
|
static_assert(css::eAuthorSheetFeatures == 0 &&
|
||||||
css::eUserSheetFeatures == 1 &&
|
css::eUserSheetFeatures == 1 &&
|
||||||
css::eAgentSheetFeatures == 2,
|
css::eAgentSheetFeatures == 2,
|
||||||
|
|
@ -980,7 +1127,8 @@ protected:
|
||||||
bool ParseBorderStyle();
|
bool ParseBorderStyle();
|
||||||
bool ParseBorderWidth();
|
bool ParseBorderWidth();
|
||||||
|
|
||||||
bool ParseCalc(nsCSSValue &aValue, uint32_t aVariantMask);
|
bool ParseCalc(nsCSSValue& aValue, uint32_t aVariantMask,
|
||||||
|
uint32_t* aResultVariantMask = nullptr);
|
||||||
bool ParseCalcAdditiveExpression(nsCSSValue& aValue,
|
bool ParseCalcAdditiveExpression(nsCSSValue& aValue,
|
||||||
uint32_t& aVariantMask);
|
uint32_t& aVariantMask);
|
||||||
bool ParseCalcMultiplicativeExpression(nsCSSValue& aValue,
|
bool ParseCalcMultiplicativeExpression(nsCSSValue& aValue,
|
||||||
|
|
@ -8598,14 +8746,18 @@ CSSParserImpl::ParseNonNegativeVariant(nsCSSValue& aValue,
|
||||||
VARIANT_NUMBER |
|
VARIANT_NUMBER |
|
||||||
VARIANT_LENGTH |
|
VARIANT_LENGTH |
|
||||||
VARIANT_PERCENT |
|
VARIANT_PERCENT |
|
||||||
|
VARIANT_FREQUENCY |
|
||||||
VARIANT_OPACITY |
|
VARIANT_OPACITY |
|
||||||
|
VARIANT_TIME |
|
||||||
VARIANT_INTEGER)) == 0,
|
VARIANT_INTEGER)) == 0,
|
||||||
"need to update code below to handle additional variants");
|
"need to update code below to handle additional variants");
|
||||||
|
|
||||||
CSSParseResult result = ParseVariant(aValue, aVariantMask, aKeywordTable);
|
CSSParseResult result = ParseVariant(aValue, aVariantMask, aKeywordTable);
|
||||||
if (result == CSSParseResult::Ok) {
|
if (result == CSSParseResult::Ok) {
|
||||||
if (eCSSUnit_Number == aValue.GetUnit() ||
|
if (eCSSUnit_Number == aValue.GetUnit() ||
|
||||||
aValue.IsLengthUnit()){
|
aValue.IsLengthUnit() ||
|
||||||
|
aValue.IsFrequencyUnit() ||
|
||||||
|
aValue.IsTimeUnit()) {
|
||||||
if (aValue.GetFloatValue() < 0) {
|
if (aValue.GetFloatValue() < 0) {
|
||||||
UngetToken();
|
UngetToken();
|
||||||
return CSSParseResult::NotFound;
|
return CSSParseResult::NotFound;
|
||||||
|
|
@ -8967,12 +9119,14 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue,
|
||||||
return CSSParseResult::Ok;
|
return CSSParseResult::Ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((aVariantMask & VARIANT_CALC) &&
|
uint32_t calcVariantMask = GetCalcParseVariantMask(aVariantMask);
|
||||||
|
if (calcVariantMask &&
|
||||||
|
(((aVariantMask & VARIANT_CALC) != 0) ||
|
||||||
|
!ShouldPreserveCalcValue(calcVariantMask)) &&
|
||||||
IsCalcFunctionToken(*tk)) {
|
IsCalcFunctionToken(*tk)) {
|
||||||
// calc() currently allows only lengths and percents and number inside it.
|
uint32_t calcResultVariantMask = calcVariantMask;
|
||||||
// And note that in current implementation, number cannot be mixed with
|
if (!ParseCalc(aValue, calcVariantMask, &calcResultVariantMask) ||
|
||||||
// length and percent.
|
!NormalizeCalcForVariant(aValue, aVariantMask, calcResultVariantMask)) {
|
||||||
if (!ParseCalc(aValue, aVariantMask & VARIANT_LPN)) {
|
|
||||||
return CSSParseResult::Error;
|
return CSSParseResult::Error;
|
||||||
}
|
}
|
||||||
return CSSParseResult::Ok;
|
return CSSParseResult::Ok;
|
||||||
|
|
@ -14673,7 +14827,8 @@ CSSParserImpl::ParseBorderColors(nsCSSPropertyID aProperty)
|
||||||
|
|
||||||
// Parse the top level of a calc() expression.
|
// Parse the top level of a calc() expression.
|
||||||
bool
|
bool
|
||||||
CSSParserImpl::ParseCalc(nsCSSValue &aValue, uint32_t aVariantMask)
|
CSSParserImpl::ParseCalc(nsCSSValue& aValue, uint32_t aVariantMask,
|
||||||
|
uint32_t* aResultVariantMask)
|
||||||
{
|
{
|
||||||
// Parsing calc expressions requires, in a number of cases, looking
|
// Parsing calc expressions requires, in a number of cases, looking
|
||||||
// for a token that is *either* a value of the property or a number.
|
// for a token that is *either* a value of the property or a number.
|
||||||
|
|
@ -14688,14 +14843,18 @@ CSSParserImpl::ParseCalc(nsCSSValue &aValue, uint32_t aVariantMask)
|
||||||
do {
|
do {
|
||||||
// The toplevel of a calc() is always an nsCSSValue::Array of length 1.
|
// The toplevel of a calc() is always an nsCSSValue::Array of length 1.
|
||||||
RefPtr<nsCSSValue::Array> arr = nsCSSValue::Array::Create(1);
|
RefPtr<nsCSSValue::Array> arr = nsCSSValue::Array::Create(1);
|
||||||
|
uint32_t resultVariantMask = aVariantMask;
|
||||||
|
|
||||||
if (!ParseCalcAdditiveExpression(arr->Item(0), aVariantMask))
|
if (!ParseCalcAdditiveExpression(arr->Item(0), resultVariantMask))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!ExpectSymbol(')', true))
|
if (!ExpectSymbol(')', true))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
aValue.SetArrayValue(arr, eCSSUnit_Calc);
|
aValue.SetArrayValue(arr, eCSSUnit_Calc);
|
||||||
|
if (aResultVariantMask) {
|
||||||
|
*aResultVariantMask = resultVariantMask;
|
||||||
|
}
|
||||||
mUnitlessLengthQuirk = oldUnitlessLengthQuirk;
|
mUnitlessLengthQuirk = oldUnitlessLengthQuirk;
|
||||||
return true;
|
return true;
|
||||||
} while (false);
|
} while (false);
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,8 @@ support-files = file_bug1089417_iframe.html
|
||||||
[test_clip-path_polygon.html]
|
[test_clip-path_polygon.html]
|
||||||
[test_compute_data_with_start_struct.html]
|
[test_compute_data_with_start_struct.html]
|
||||||
[test_computed_style.html]
|
[test_computed_style.html]
|
||||||
|
[test_calc_numeric_types.html]
|
||||||
|
prefs = layout.css.filters.enabled=true
|
||||||
[test_computed_style_min_size_auto.html]
|
[test_computed_style_min_size_auto.html]
|
||||||
[test_computed_style_no_pseudo.html]
|
[test_computed_style_no_pseudo.html]
|
||||||
[test_computed_style_prefs.html]
|
[test_computed_style_prefs.html]
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,8 @@ var validGradientAndElementValues = [
|
||||||
"linear-gradient(10deg, red, blue)",
|
"linear-gradient(10deg, red, blue)",
|
||||||
"linear-gradient(1turn, red, blue)",
|
"linear-gradient(1turn, red, blue)",
|
||||||
"linear-gradient(.414rad, red, blue)",
|
"linear-gradient(.414rad, red, blue)",
|
||||||
|
"linear-gradient(calc(90deg / 2), red, blue)",
|
||||||
|
"linear-gradient(calc(calc(0.25turn) + 45deg), red, blue)",
|
||||||
"linear-gradient(90deg in srgb, yellow, purple)",
|
"linear-gradient(90deg in srgb, yellow, purple)",
|
||||||
"linear-gradient(90deg in hsl, yellow, purple)",
|
"linear-gradient(90deg in hsl, yellow, purple)",
|
||||||
"linear-gradient(90deg in lch, yellow, purple)",
|
"linear-gradient(90deg in lch, yellow, purple)",
|
||||||
|
|
@ -1005,7 +1007,8 @@ var gCSSProperties = {
|
||||||
inherited: false,
|
inherited: false,
|
||||||
type: CSS_TYPE_LONGHAND,
|
type: CSS_TYPE_LONGHAND,
|
||||||
initial_values: ["0s", "0ms"],
|
initial_values: ["0s", "0ms"],
|
||||||
other_values: ["1s", "250ms", "-100ms", "-1s", "1s, 250ms, 2.3s"],
|
other_values: ["1s", "250ms", "-100ms", "-1s", "1s, 250ms, 2.3s",
|
||||||
|
"calc(250ms - 0.5s)", "calc(calc(500ms) - 250ms)"],
|
||||||
invalid_values: ["0", "0px"],
|
invalid_values: ["0", "0px"],
|
||||||
},
|
},
|
||||||
"animation-direction": {
|
"animation-direction": {
|
||||||
|
|
@ -1030,7 +1033,8 @@ var gCSSProperties = {
|
||||||
inherited: false,
|
inherited: false,
|
||||||
type: CSS_TYPE_LONGHAND,
|
type: CSS_TYPE_LONGHAND,
|
||||||
initial_values: ["0s", "0ms"],
|
initial_values: ["0s", "0ms"],
|
||||||
other_values: ["1s", "250ms", "1s, 250ms, 2.3s"],
|
other_values: ["1s", "250ms", "1s, 250ms, 2.3s",
|
||||||
|
"calc(calc(0.25s) + 250ms)"],
|
||||||
invalid_values: ["0", "0px", "-1ms", "-2s"],
|
invalid_values: ["0", "0px", "-1ms", "-2s"],
|
||||||
},
|
},
|
||||||
"animation-fill-mode": {
|
"animation-fill-mode": {
|
||||||
|
|
@ -2862,6 +2866,9 @@ var gCSSProperties = {
|
||||||
"translate(calc(5px - 10% * 3))",
|
"translate(calc(5px - 10% * 3))",
|
||||||
"translate(calc(5px - 3 * 10%), 50px)",
|
"translate(calc(5px - 3 * 10%), 50px)",
|
||||||
"translate(-50px, calc(5px - 10% * 3))",
|
"translate(-50px, calc(5px - 10% * 3))",
|
||||||
|
"rotate(calc(45deg + 45deg))",
|
||||||
|
"rotate(calc(calc(0.125turn) + 45deg))",
|
||||||
|
"scale(calc(1 + 0.5))",
|
||||||
"translatez(1px)",
|
"translatez(1px)",
|
||||||
"translatez(4em)",
|
"translatez(4em)",
|
||||||
"translatez(-4px)",
|
"translatez(-4px)",
|
||||||
|
|
@ -5584,7 +5591,8 @@ var gCSSProperties = {
|
||||||
"3e+0",
|
"3e+0",
|
||||||
"3e-0",
|
"3e-0",
|
||||||
],
|
],
|
||||||
other_values: ["0", "0.4", "0.0000", "-3", "3e-1", "-100%", "50%"],
|
other_values: ["0", "0.4", "0.0000", "-3", "3e-1", "-100%", "50%",
|
||||||
|
"calc(25% * 2)", "calc(calc(0.25) + 0.25)"],
|
||||||
invalid_values: ["0px", "1px"],
|
invalid_values: ["0px", "1px"],
|
||||||
},
|
},
|
||||||
"-moz-orient": {
|
"-moz-orient": {
|
||||||
|
|
@ -6413,7 +6421,8 @@ var gCSSProperties = {
|
||||||
inherited: false,
|
inherited: false,
|
||||||
type: CSS_TYPE_LONGHAND,
|
type: CSS_TYPE_LONGHAND,
|
||||||
initial_values: ["0s", "0ms"],
|
initial_values: ["0s", "0ms"],
|
||||||
other_values: ["1s", "250ms", "-100ms", "-1s", "1s, 250ms, 2.3s"],
|
other_values: ["1s", "250ms", "-100ms", "-1s", "1s, 250ms, 2.3s",
|
||||||
|
"calc(250ms - 0.5s)", "calc(calc(500ms) - 250ms)"],
|
||||||
invalid_values: ["0", "0px"],
|
invalid_values: ["0", "0px"],
|
||||||
},
|
},
|
||||||
"transition-duration": {
|
"transition-duration": {
|
||||||
|
|
@ -6421,7 +6430,8 @@ var gCSSProperties = {
|
||||||
inherited: false,
|
inherited: false,
|
||||||
type: CSS_TYPE_LONGHAND,
|
type: CSS_TYPE_LONGHAND,
|
||||||
initial_values: ["0s", "0ms"],
|
initial_values: ["0s", "0ms"],
|
||||||
other_values: ["1s", "250ms", "1s, 250ms, 2.3s"],
|
other_values: ["1s", "250ms", "1s, 250ms, 2.3s",
|
||||||
|
"calc(calc(0.25s) + 250ms)"],
|
||||||
invalid_values: ["0", "0px", "-1ms", "-2s"],
|
invalid_values: ["0", "0px", "-1ms", "-2s"],
|
||||||
},
|
},
|
||||||
"transition-property": {
|
"transition-property": {
|
||||||
|
|
@ -6785,7 +6795,7 @@ var gCSSProperties = {
|
||||||
type: CSS_TYPE_LONGHAND,
|
type: CSS_TYPE_LONGHAND,
|
||||||
/* XXX requires position */
|
/* XXX requires position */
|
||||||
initial_values: ["auto"],
|
initial_values: ["auto"],
|
||||||
other_values: ["0", "3", "-7000", "12000"],
|
other_values: ["0", "3", "-7000", "12000", "calc(2.5)"],
|
||||||
invalid_values: ["3.0", "17.5", "3e1"],
|
invalid_values: ["3.0", "17.5", "3e1"],
|
||||||
},
|
},
|
||||||
"clip-path": {
|
"clip-path": {
|
||||||
|
|
@ -7645,7 +7655,8 @@ var gCSSProperties = {
|
||||||
inherited: false,
|
inherited: false,
|
||||||
type: CSS_TYPE_LONGHAND,
|
type: CSS_TYPE_LONGHAND,
|
||||||
initial_values: ["0"],
|
initial_values: ["0"],
|
||||||
other_values: ["1", "99999", "-1", "-50"],
|
other_values: ["1", "99999", "-1", "-50", "calc(1.5)",
|
||||||
|
"calc(calc(-2) + 1)"],
|
||||||
invalid_values: ["0px", "1.0", "1.", "1%", "0.2", "3em", "stretch"],
|
invalid_values: ["0px", "1.0", "1.", "1%", "0.2", "3em", "stretch"],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -9305,6 +9316,8 @@ if (IsCSSPropertyPrefEnabled("layout.css.filters.enabled")) {
|
||||||
"brightness(2)",
|
"brightness(2)",
|
||||||
"brightness(350%)",
|
"brightness(350%)",
|
||||||
"brightness(4.567)",
|
"brightness(4.567)",
|
||||||
|
"brightness(calc(25% * 2))",
|
||||||
|
"brightness(calc(calc(0.25) + 0.25))",
|
||||||
|
|
||||||
"contrast(0)",
|
"contrast(0)",
|
||||||
"contrast(50%)",
|
"contrast(50%)",
|
||||||
|
|
@ -9349,6 +9362,7 @@ if (IsCSSPropertyPrefEnabled("layout.css.filters.enabled")) {
|
||||||
"hue-rotate(-1.6rad)",
|
"hue-rotate(-1.6rad)",
|
||||||
"hue-rotate(0.5turn)",
|
"hue-rotate(0.5turn)",
|
||||||
"hue-rotate(-2turn)",
|
"hue-rotate(-2turn)",
|
||||||
|
"hue-rotate(calc(90deg + 0.125turn))",
|
||||||
|
|
||||||
"invert(0)",
|
"invert(0)",
|
||||||
"invert(50%)",
|
"invert(50%)",
|
||||||
|
|
|
||||||
93
layout/style/test/test_calc_numeric_types.html
Normal file
93
layout/style/test/test_calc_numeric_types.html
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test calc() numeric type support</title>
|
||||||
|
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="display"></div>
|
||||||
|
<pre id="test">
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function appendTestNode(tag = "div") {
|
||||||
|
const node = document.createElement(tag);
|
||||||
|
document.getElementById("display").appendChild(node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse2dMatrix(transformValue) {
|
||||||
|
const match = /^matrix\(([^)]+)\)$/.exec(transformValue);
|
||||||
|
ok(match, `expected a 2d matrix, got "${transformValue}"`);
|
||||||
|
return match[1].split(",").map(value => parseFloat(value.trim()));
|
||||||
|
}
|
||||||
|
|
||||||
|
(function testNestedCalcLengthPercentage() {
|
||||||
|
const container = appendTestNode();
|
||||||
|
container.style.width = "200px";
|
||||||
|
container.style.position = "absolute";
|
||||||
|
|
||||||
|
const child = document.createElement("div");
|
||||||
|
child.style.width = "calc(calc(50% + 10px) - calc(5px + 10%))";
|
||||||
|
container.appendChild(child);
|
||||||
|
|
||||||
|
is(getComputedStyle(child).width, "85px",
|
||||||
|
"nested calc() should resolve length-percentage expressions correctly");
|
||||||
|
|
||||||
|
container.remove();
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function testTimeCalc() {
|
||||||
|
const div = appendTestNode();
|
||||||
|
div.style.transitionDuration = "calc(calc(0.25s) + 250ms)";
|
||||||
|
div.style.animationDelay = "calc(250ms - 0.5s)";
|
||||||
|
|
||||||
|
is(getComputedStyle(div).transitionDuration, "0.5s",
|
||||||
|
"transition-duration should accept calc() time values");
|
||||||
|
is(getComputedStyle(div).animationDelay, "-0.25s",
|
||||||
|
"animation-delay should accept calc() time values");
|
||||||
|
|
||||||
|
div.remove();
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function testNumericAndIntegerCalc() {
|
||||||
|
const div = appendTestNode();
|
||||||
|
div.style.opacity = "calc(25% * 2)";
|
||||||
|
div.style.order = "calc(1.5)";
|
||||||
|
div.style.zIndex = "calc(2.5)";
|
||||||
|
|
||||||
|
is(getComputedStyle(div).opacity, "0.5",
|
||||||
|
"opacity should accept calc() number/percent values");
|
||||||
|
is(getComputedStyle(div).order, "2",
|
||||||
|
"order should round calc() results to the nearest integer");
|
||||||
|
is(getComputedStyle(div).zIndex, "3",
|
||||||
|
"z-index should round calc() results to the nearest integer");
|
||||||
|
|
||||||
|
div.remove();
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function testAngleAndNumberCalcInFunctions() {
|
||||||
|
const div = appendTestNode();
|
||||||
|
div.style.transform = "rotate(calc(45deg + 45deg)) scale(calc(1 + 0.5))";
|
||||||
|
div.style.filter = "hue-rotate(calc(90deg + 0.125turn)) brightness(calc(0.25 + 0.25))";
|
||||||
|
div.style.backgroundImage = "linear-gradient(calc(90deg / 2), red, blue)";
|
||||||
|
|
||||||
|
ok(div.style.filter !== "",
|
||||||
|
"filter should accept calc() in angle and number function arguments");
|
||||||
|
ok(div.style.backgroundImage !== "",
|
||||||
|
"gradients should accept calc() in angle arguments");
|
||||||
|
|
||||||
|
const matrix = parse2dMatrix(getComputedStyle(div).transform);
|
||||||
|
ok(Math.abs(matrix[0]) < 1e-6, "rotate(calc()) should zero out the xx entry");
|
||||||
|
ok(Math.abs(matrix[1] - 1.5) < 1e-6, "scale(calc()) should affect the xy entry");
|
||||||
|
ok(Math.abs(matrix[2] + 1.5) < 1e-6, "scale(calc()) should affect the yx entry");
|
||||||
|
ok(Math.abs(matrix[3]) < 1e-6, "rotate(calc()) should zero out the yy entry");
|
||||||
|
|
||||||
|
div.remove();
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue