// https://drafts.csswg.org/css-transitions/#transition-shorthand-property // [ none | <single-transition-property> ] || <time> || <easing-function> || <time> private static void CompileTransition(StylePropertyReader reader, out List <TimeValue> outDelay, out List <TimeValue> outDuration, out List <StylePropertyName> outProperty, out List <EasingFunction> outTimingFunction) { s_TransitionDelayList.Clear(); s_TransitionDurationList.Clear(); s_TransitionPropertyList.Clear(); s_TransitionTimingFunctionList.Clear(); bool isValid = true; bool noneFound = false; var valueCount = reader.valueCount; int transitionCount = 0; int i = 0; do { // If none is present and there are more transitions the shorthand is considered invalid if (noneFound) { isValid = false; break; } var transitionProperty = InitialStyle.transitionProperty[0]; var transitionDuration = InitialStyle.transitionDuration[0]; var transitionDelay = InitialStyle.transitionDelay[0]; var transitionTimingFunction = InitialStyle.transitionTimingFunction[0]; bool durationFound = false; bool delayFound = false; bool propertyFound = false; bool timingFunctionFound = false; bool commaFound = false; for (; i < valueCount && !commaFound; ++i) { var valueType = reader.GetValueType(i); switch (valueType) { case StyleValueType.Keyword: if (reader.IsKeyword(i, StyleValueKeyword.None) && transitionCount == 0) { noneFound = true; propertyFound = true; transitionProperty = new StylePropertyName("none"); } else { isValid = false; } break; case StyleValueType.Dimension: var time = reader.ReadTimeValue(i); if (!durationFound) { // transition-duration durationFound = true; transitionDuration = time; } else if (!delayFound) { // transition-delay delayFound = true; transitionDelay = time; } else { isValid = false; } break; case StyleValueType.Enum: var str = reader.ReadAsString(i); if (!timingFunctionFound && StylePropertyUtil.TryGetEnumIntValue(StyleEnumType.EasingMode, str, out var intValue)) { // transition-timing-function timingFunctionFound = true; transitionTimingFunction = (EasingMode)intValue; } else if (!propertyFound) { // transition-property propertyFound = true; transitionProperty = new StylePropertyName(str); } else { isValid = false; } break; case StyleValueType.CommaSeparator: commaFound = true; ++transitionCount; break; default: isValid = false; break; } } s_TransitionDelayList.Add(transitionDelay); s_TransitionDurationList.Add(transitionDuration); s_TransitionPropertyList.Add(transitionProperty); s_TransitionTimingFunctionList.Add(transitionTimingFunction); }while (i < valueCount && isValid); if (isValid) { outProperty = s_TransitionPropertyList; outDelay = s_TransitionDelayList; outDuration = s_TransitionDurationList; outTimingFunction = s_TransitionTimingFunctionList; } else { outProperty = InitialStyle.transitionProperty; outDelay = InitialStyle.transitionDelay; outDuration = InitialStyle.transitionDuration; outTimingFunction = InitialStyle.transitionTimingFunction; } }