mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-25 18:07:31 +09:00
Issue #1826 - Add typed calc() arithmetic for media queries
This commit is contained in:
parent
8af3f489da
commit
79800a9113
4 changed files with 134 additions and 17 deletions
|
|
@ -318,11 +318,7 @@ SerializeCalcInternal(const typename CalcOps::input_type& aValue, CalcOps &aOps)
|
||||||
if (needParens) {
|
if (needParens) {
|
||||||
aOps.Append("(");
|
aOps.Append("(");
|
||||||
}
|
}
|
||||||
if (unit == eCSSUnit_Calc_Times_L) {
|
|
||||||
aOps.AppendNumber(array->Item(0));
|
|
||||||
} else {
|
|
||||||
SerializeCalcInternal(array->Item(0), aOps);
|
SerializeCalcInternal(array->Item(0), aOps);
|
||||||
}
|
|
||||||
if (needParens) {
|
if (needParens) {
|
||||||
aOps.Append(")");
|
aOps.Append(")");
|
||||||
}
|
}
|
||||||
|
|
@ -340,11 +336,7 @@ SerializeCalcInternal(const typename CalcOps::input_type& aValue, CalcOps &aOps)
|
||||||
if (needParens) {
|
if (needParens) {
|
||||||
aOps.Append("(");
|
aOps.Append("(");
|
||||||
}
|
}
|
||||||
if (unit == eCSSUnit_Calc_Times_L) {
|
|
||||||
SerializeCalcInternal(array->Item(1), aOps);
|
SerializeCalcInternal(array->Item(1), aOps);
|
||||||
} else {
|
|
||||||
aOps.AppendNumber(array->Item(1));
|
|
||||||
}
|
|
||||||
if (needParens) {
|
if (needParens) {
|
||||||
aOps.Append(")");
|
aOps.Append(")");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -314,8 +314,11 @@ nsMediaExpression::Matches(nsPresContext *aPresContext,
|
||||||
"bad required value");
|
"bad required value");
|
||||||
nscoord actualCoord = nsRuleNode::CalcLengthWithInitialFont(
|
nscoord actualCoord = nsRuleNode::CalcLengthWithInitialFont(
|
||||||
aPresContext, actual);
|
aPresContext, actual);
|
||||||
nscoord requiredCoord = nsRuleNode::CalcLengthWithInitialFont(
|
nscoord requiredCoord;
|
||||||
aPresContext, required);
|
if (!ComputeMediaQueryTypedCalcLength(aPresContext, required,
|
||||||
|
requiredCoord)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
cmp = DoCompare(actualCoord, requiredCoord);
|
cmp = DoCompare(actualCoord, requiredCoord);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -262,6 +262,65 @@ RoundFloatToCSSInteger(float aValue)
|
||||||
return int32_t(rounded);
|
return int32_t(rounded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
GetCalcLengthTypedArithmeticExponent(const nsCSSValue& aValue,
|
||||||
|
int32_t& aExponent)
|
||||||
|
{
|
||||||
|
switch (aValue.GetUnit()) {
|
||||||
|
case eCSSUnit_Calc: {
|
||||||
|
nsCSSValue::Array* array = aValue.GetArrayValue();
|
||||||
|
MOZ_ASSERT(array->Count() == 1, "unexpected length");
|
||||||
|
return GetCalcLengthTypedArithmeticExponent(array->Item(0), aExponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
case eCSSUnit_Calc_Plus:
|
||||||
|
case eCSSUnit_Calc_Minus: {
|
||||||
|
nsCSSValue::Array* array = aValue.GetArrayValue();
|
||||||
|
MOZ_ASSERT(array->Count() == 2, "unexpected length");
|
||||||
|
int32_t lhsExponent;
|
||||||
|
int32_t rhsExponent;
|
||||||
|
if (!GetCalcLengthTypedArithmeticExponent(array->Item(0), lhsExponent) ||
|
||||||
|
!GetCalcLengthTypedArithmeticExponent(array->Item(1), rhsExponent) ||
|
||||||
|
lhsExponent != rhsExponent) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
aExponent = lhsExponent;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case eCSSUnit_Calc_Times_L:
|
||||||
|
case eCSSUnit_Calc_Times_R:
|
||||||
|
case eCSSUnit_Calc_Divided: {
|
||||||
|
nsCSSValue::Array* array = aValue.GetArrayValue();
|
||||||
|
MOZ_ASSERT(array->Count() == 2, "unexpected length");
|
||||||
|
int32_t lhsExponent;
|
||||||
|
int32_t rhsExponent;
|
||||||
|
if (!GetCalcLengthTypedArithmeticExponent(array->Item(0), lhsExponent) ||
|
||||||
|
!GetCalcLengthTypedArithmeticExponent(array->Item(1), rhsExponent)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
aExponent = aValue.GetUnit() == eCSSUnit_Calc_Divided
|
||||||
|
? lhsExponent - rhsExponent
|
||||||
|
: lhsExponent + rhsExponent;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case eCSSUnit_Number:
|
||||||
|
aExponent = 0;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aValue.IsLengthUnit()) {
|
||||||
|
aExponent = 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
NormalizeCalcForVariant(nsCSSValue& aValue,
|
NormalizeCalcForVariant(nsCSSValue& aValue,
|
||||||
uint32_t aPropertyVariantMask,
|
uint32_t aPropertyVariantMask,
|
||||||
|
|
@ -1727,6 +1786,7 @@ protected:
|
||||||
// not be set to false if any nsCSSValues created during parsing can escape
|
// not be set to false if any nsCSSValues created during parsing can escape
|
||||||
// out of the parser.
|
// out of the parser.
|
||||||
bool mSheetPrincipalRequired;
|
bool mSheetPrincipalRequired;
|
||||||
|
bool mCalcAllowsTypedArithmetic;
|
||||||
|
|
||||||
// This enum helps us track whether we've unprefixed "display: -webkit-box"
|
// This enum helps us track whether we've unprefixed "display: -webkit-box"
|
||||||
// (treating it as "display: flex") in an earlier declaration within a series
|
// (treating it as "display: flex") in an earlier declaration within a series
|
||||||
|
|
@ -1831,6 +1891,7 @@ CSSParserImpl::CSSParserImpl()
|
||||||
mInFailingSupportsRule(false),
|
mInFailingSupportsRule(false),
|
||||||
mSuppressErrors(false),
|
mSuppressErrors(false),
|
||||||
mSheetPrincipalRequired(true),
|
mSheetPrincipalRequired(true),
|
||||||
|
mCalcAllowsTypedArithmetic(false),
|
||||||
mWebkitBoxUnprefixState(eNotParsingDecls),
|
mWebkitBoxUnprefixState(eNotParsingDecls),
|
||||||
mNextFree(nullptr)
|
mNextFree(nullptr)
|
||||||
{
|
{
|
||||||
|
|
@ -3998,8 +4059,12 @@ CSSParserImpl::ParseMediaQueryExpression(nsMediaQuery* aQuery)
|
||||||
bool rv = false;
|
bool rv = false;
|
||||||
switch (feature->mValueType) {
|
switch (feature->mValueType) {
|
||||||
case nsMediaFeature::eLength:
|
case nsMediaFeature::eLength:
|
||||||
|
{
|
||||||
|
AutoRestore<bool> autoRestore(mCalcAllowsTypedArithmetic);
|
||||||
|
mCalcAllowsTypedArithmetic = true;
|
||||||
rv = ParseSingleTokenNonNegativeVariant(expr->mValue, VARIANT_LCALC,
|
rv = ParseSingleTokenNonNegativeVariant(expr->mValue, VARIANT_LCALC,
|
||||||
nullptr);
|
nullptr);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case nsMediaFeature::eInteger:
|
case nsMediaFeature::eInteger:
|
||||||
case nsMediaFeature::eBoolInteger:
|
case nsMediaFeature::eBoolInteger:
|
||||||
|
|
@ -14848,6 +14913,25 @@ CSSParserImpl::ParseCalc(nsCSSValue& aValue, uint32_t aVariantMask,
|
||||||
if (!ParseCalcAdditiveExpression(arr->Item(0), resultVariantMask))
|
if (!ParseCalcAdditiveExpression(arr->Item(0), resultVariantMask))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (mCalcAllowsTypedArithmetic) {
|
||||||
|
int32_t exponent;
|
||||||
|
if (!GetCalcLengthTypedArithmeticExponent(arr->Item(0), exponent)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aVariantMask & VARIANT_NUMBER) {
|
||||||
|
if (exponent == 0) {
|
||||||
|
resultVariantMask = VARIANT_NUMBER;
|
||||||
|
} else if (exponent == 1) {
|
||||||
|
resultVariantMask &= ~int32_t(VARIANT_NUMBER);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (exponent != 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!ExpectSymbol(')', true))
|
if (!ExpectSymbol(')', true))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -14928,13 +15012,16 @@ CSSParserImpl::ParseCalcMultiplicativeExpression(nsCSSValue& aValue,
|
||||||
bool *aHadFinalWS)
|
bool *aHadFinalWS)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aVariantMask != 0, "unexpected variant mask");
|
MOZ_ASSERT(aVariantMask != 0, "unexpected variant mask");
|
||||||
|
bool allowTypedArithmetic = mCalcAllowsTypedArithmetic;
|
||||||
bool gotValue = false; // already got the part with the unit
|
bool gotValue = false; // already got the part with the unit
|
||||||
bool afterDivision = false;
|
bool afterDivision = false;
|
||||||
|
|
||||||
nsCSSValue *storage = &aValue;
|
nsCSSValue *storage = &aValue;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint32_t variantMask;
|
uint32_t variantMask;
|
||||||
if (afterDivision || gotValue) {
|
if (allowTypedArithmetic) {
|
||||||
|
variantMask = aVariantMask | VARIANT_NUMBER;
|
||||||
|
} else if (afterDivision || gotValue) {
|
||||||
variantMask = VARIANT_NUMBER;
|
variantMask = VARIANT_NUMBER;
|
||||||
} else {
|
} else {
|
||||||
variantMask = aVariantMask | VARIANT_NUMBER;
|
variantMask = aVariantMask | VARIANT_NUMBER;
|
||||||
|
|
@ -14955,7 +15042,7 @@ CSSParserImpl::ParseCalcMultiplicativeExpression(nsCSSValue& aValue,
|
||||||
if (number == 0.0 && afterDivision)
|
if (number == 0.0 && afterDivision)
|
||||||
return false;
|
return false;
|
||||||
storage->SetFloatValue(number, eCSSUnit_Number);
|
storage->SetFloatValue(number, eCSSUnit_Number);
|
||||||
} else {
|
} else if (!allowTypedArithmetic) {
|
||||||
gotValue = true;
|
gotValue = true;
|
||||||
|
|
||||||
if (storage != &aValue) {
|
if (storage != &aValue) {
|
||||||
|
|
@ -14977,7 +15064,10 @@ CSSParserImpl::ParseCalcMultiplicativeExpression(nsCSSValue& aValue,
|
||||||
}
|
}
|
||||||
nsCSSUnit unit;
|
nsCSSUnit unit;
|
||||||
if (mToken.IsSymbol('*')) {
|
if (mToken.IsSymbol('*')) {
|
||||||
unit = gotValue ? eCSSUnit_Calc_Times_R : eCSSUnit_Calc_Times_L;
|
unit = allowTypedArithmetic
|
||||||
|
? eCSSUnit_Calc_Times_R
|
||||||
|
: (gotValue ? eCSSUnit_Calc_Times_R
|
||||||
|
: eCSSUnit_Calc_Times_L);
|
||||||
afterDivision = false;
|
afterDivision = false;
|
||||||
} else if (mToken.IsSymbol('/')) {
|
} else if (mToken.IsSymbol('/')) {
|
||||||
unit = eCSSUnit_Calc_Divided;
|
unit = eCSSUnit_Calc_Divided;
|
||||||
|
|
@ -14996,6 +15086,23 @@ CSSParserImpl::ParseCalcMultiplicativeExpression(nsCSSValue& aValue,
|
||||||
|
|
||||||
// Adjust aVariantMask (see comments above function) to reflect which
|
// Adjust aVariantMask (see comments above function) to reflect which
|
||||||
// option we took.
|
// option we took.
|
||||||
|
if (allowTypedArithmetic) {
|
||||||
|
int32_t exponent;
|
||||||
|
if (!GetCalcLengthTypedArithmeticExponent(aValue, exponent)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aVariantMask & VARIANT_NUMBER) {
|
||||||
|
if (exponent == 0) {
|
||||||
|
aVariantMask = VARIANT_NUMBER;
|
||||||
|
} else {
|
||||||
|
aVariantMask &= ~int32_t(VARIANT_NUMBER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (aVariantMask & VARIANT_NUMBER) {
|
if (aVariantMask & VARIANT_NUMBER) {
|
||||||
if (gotValue) {
|
if (gotValue) {
|
||||||
aVariantMask &= ~int32_t(VARIANT_NUMBER);
|
aVariantMask &= ~int32_t(VARIANT_NUMBER);
|
||||||
|
|
|
||||||
|
|
@ -321,6 +321,21 @@ function run() {
|
||||||
(Math.floor(value/em_size) - 1) + "rem)");
|
(Math.floor(value/em_size) - 1) + "rem)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
change_state(function() {
|
||||||
|
iframe_style.width = "100px";
|
||||||
|
iframe_style.height = "10px";
|
||||||
|
});
|
||||||
|
should_apply("all and (width: calc(100px / 1em * 1em))");
|
||||||
|
should_apply("all and (width: calc((50vh * 5em) / 4px))");
|
||||||
|
should_apply("all and (width: calc(10vw / 10px * 1000vh))");
|
||||||
|
should_apply("all and (width: calc(8000vh * 1vw / 1em * 8px / 40vh))");
|
||||||
|
should_not_apply("all and (width: calc(100px / 1em * 2em))");
|
||||||
|
|
||||||
|
change_state(function() {
|
||||||
|
iframe_style.width = width_val + "px";
|
||||||
|
iframe_style.height = height_val + "px";
|
||||||
|
});
|
||||||
|
|
||||||
change_state(function() {
|
change_state(function() {
|
||||||
iframe_style.width = "0";
|
iframe_style.width = "0";
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue