Exemple #1
0
	bignum lowestCommonMultiple(const bignum &bn1, const bignum &bn2)
	{
		if (bn1.isNegative() != bn2.isNegative())
			return lowestCommonMultiple(bn1.absolute(), bn2.absolute());

		if (bn1.getDecimalCount() > 0 || bn2.getDecimalCount() > 0)
			throw error_handler(__FILE__, __LINE__, "Lowest common multiple can only be found with two integers");

		if (bn1 == bn2)
			return bn1;

		bignum lowest = bn1 < bn2 ? bn1 : bn2;
		bignum highest = bn1 > bn2 ? bn1 : bn2;

		if (highest % lowest == 0)
			return highest;

		for (int i = 1; lowest >= i; i++)
		{
			bignum product_check(highest * i);
			if (product_check % lowest == 0)
				return product_check;
		}

		throw error_handler(__FILE__, __LINE__, "An error has occurred");
	}
PairwiseInterpolationValue ListInterpolationFunctions::mergeSingleConversions(InterpolationValue& start, InterpolationValue& end, MergeSingleItemConversionsCallback mergeSingleItemConversions)
{
    size_t startLength = toInterpolableList(*start.interpolableValue).length();
    size_t endLength = toInterpolableList(*end.interpolableValue).length();

    if (startLength == 0 && endLength == 0) {
        return PairwiseInterpolationValue(
            start.interpolableValue.release(),
            end.interpolableValue.release(),
            nullptr);
    }

    if (startLength == 0) {
        OwnPtr<InterpolableValue> startInterpolableValue = end.interpolableValue->cloneAndZero();
        return PairwiseInterpolationValue(
            startInterpolableValue.release(),
            end.interpolableValue.release(),
            end.nonInterpolableValue.release());
    }

    if (endLength == 0) {
        OwnPtr<InterpolableValue> endInterpolableValue = start.interpolableValue->cloneAndZero();
        return PairwiseInterpolationValue(
            start.interpolableValue.release(),
            endInterpolableValue.release(),
            start.nonInterpolableValue.release());
    }

    size_t finalLength = lowestCommonMultiple(startLength, endLength);
    OwnPtr<InterpolableList> resultStartInterpolableList = InterpolableList::create(finalLength);
    OwnPtr<InterpolableList> resultEndInterpolableList = InterpolableList::create(finalLength);
    Vector<RefPtr<NonInterpolableValue>> resultNonInterpolableValues(finalLength);

    InterpolableList& startInterpolableList = toInterpolableList(*start.interpolableValue);
    InterpolableList& endInterpolableList = toInterpolableList(*end.interpolableValue);
    NonInterpolableList& startNonInterpolableList = toNonInterpolableList(*start.nonInterpolableValue);
    NonInterpolableList& endNonInterpolableList = toNonInterpolableList(*end.nonInterpolableValue);

    for (size_t i = 0; i < finalLength; i++) {
        InterpolationValue start(startInterpolableList.get(i % startLength)->clone(), startNonInterpolableList.get(i % startLength));
        InterpolationValue end(endInterpolableList.get(i % endLength)->clone(), endNonInterpolableList.get(i % endLength));
        PairwiseInterpolationValue result = mergeSingleItemConversions(start, end);
        if (!result)
            return nullptr;
        resultStartInterpolableList->set(i, result.startInterpolableValue.release());
        resultEndInterpolableList->set(i, result.endInterpolableValue.release());
        resultNonInterpolableValues[i] = result.nonInterpolableValue.release();
    }

    return PairwiseInterpolationValue(
        resultStartInterpolableList.release(),
        resultEndInterpolableList.release(),
        NonInterpolableList::create(resultNonInterpolableValues));
}
bool AnimatableRepeatable::usesDefaultInterpolationWith(const AnimatableValue* value) const
{
    const WillBeHeapVector<RefPtrWillBeMember<AnimatableValue>>& fromValues = m_values;
    const WillBeHeapVector<RefPtrWillBeMember<AnimatableValue>>& toValues = toAnimatableRepeatable(value)->m_values;
    ASSERT(!fromValues.isEmpty() && !toValues.isEmpty());
    size_t size = lowestCommonMultiple(fromValues.size(), toValues.size());
    ASSERT(size > 0);
    for (size_t i = 0; i < size; ++i) {
        const AnimatableValue* from = fromValues[i % fromValues.size()].get();
        const AnimatableValue* to = toValues[i % toValues.size()].get();
        // Spec: If a pair of values cannot be interpolated, then the lists are not interpolable.
        if (AnimatableValue::usesDefaultInterpolation(from, to))
            return true;
    }
    return false;
}
bool AnimatableRepeatable::interpolateLists(const WillBeHeapVector<RefPtrWillBeMember<AnimatableValue>>& fromValues, const WillBeHeapVector<RefPtrWillBeMember<AnimatableValue>>& toValues, double fraction, WillBeHeapVector<RefPtrWillBeMember<AnimatableValue>>& interpolatedValues)
{
    // Interpolation behaviour spec: http://www.w3.org/TR/css3-transitions/#animtype-repeatable-list
    ASSERT(interpolatedValues.isEmpty());
    ASSERT(!fromValues.isEmpty() && !toValues.isEmpty());
    size_t size = lowestCommonMultiple(fromValues.size(), toValues.size());
    ASSERT(size > 0);
    for (size_t i = 0; i < size; ++i) {
        const AnimatableValue* from = fromValues[i % fromValues.size()].get();
        const AnimatableValue* to = toValues[i % toValues.size()].get();
        // Spec: If a pair of values cannot be interpolated, then the lists are not interpolable.
        if (AnimatableValue::usesDefaultInterpolation(from, to))
            return false;
        interpolatedValues.append(interpolate(from, to, fraction));
    }
    return true;
}
String StylePropertySerializer::backgroundRepeatPropertyValue() const
{
    RefPtr<CSSValue> repeatX = m_propertySet.getPropertyCSSValue(CSSPropertyBackgroundRepeatX);
    RefPtr<CSSValue> repeatY = m_propertySet.getPropertyCSSValue(CSSPropertyBackgroundRepeatY);
    if (!repeatX || !repeatY)
        return String();
    if (repeatX->cssValueType() == repeatY->cssValueType()
        && (repeatX->cssValueType() == CSSValue::CSS_INITIAL || repeatX->cssValueType() == CSSValue::CSS_INHERIT)) {
        return repeatX->cssText();
    }

    RefPtr<CSSValueList> repeatXList;
    if (repeatX->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) {
        repeatXList = CSSValueList::createCommaSeparated();
        repeatXList->append(repeatX);
    } else if (repeatX->cssValueType() == CSSValue::CSS_VALUE_LIST) {
        repeatXList = toCSSValueList(repeatX.get());
    } else {
        return String();
    }

    RefPtr<CSSValueList> repeatYList;
    if (repeatY->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) {
        repeatYList = CSSValueList::createCommaSeparated();
        repeatYList->append(repeatY);
    } else if (repeatY->cssValueType() == CSSValue::CSS_VALUE_LIST) {
        repeatYList = toCSSValueList(repeatY.get());
    } else {
        return String();
    }

    size_t shorthandLength = lowestCommonMultiple(repeatXList->length(), repeatYList->length());
    StringBuilder builder;
    for (size_t i = 0; i < shorthandLength; ++i) {
        if (i)
            builder.appendLiteral(", ");
        appendBackgroundRepeatValue(builder,
            *repeatXList->item(i % repeatXList->length()),
            *repeatYList->item(i % repeatYList->length()));
    }
    return builder.toString();
}
void ListInterpolationFunctions::composite(UnderlyingValueOwner& underlyingValueOwner, double underlyingFraction, const InterpolationType& type, const InterpolationValue& value, NonInterpolableValuesAreCompatibleCallback nonInterpolableValuesAreCompatible, CompositeItemCallback compositeItem)
{
    size_t underlyingLength = toInterpolableList(*underlyingValueOwner.value().interpolableValue).length();
    if (underlyingLength == 0) {
        ASSERT(!underlyingValueOwner.value().nonInterpolableValue);
        underlyingValueOwner.set(type, value);
        return;
    }

    const InterpolableList& interpolableList = toInterpolableList(*value.interpolableValue);
    size_t valueLength = interpolableList.length();
    if (valueLength == 0) {
        ASSERT(!value.nonInterpolableValue);
        underlyingValueOwner.mutableValue().interpolableValue->scale(underlyingFraction);
        return;
    }

    const NonInterpolableList& nonInterpolableList = toNonInterpolableList(*value.nonInterpolableValue);
    size_t newLength = lowestCommonMultiple(underlyingLength, valueLength);
    if (!nonInterpolableListsAreCompatible(toNonInterpolableList(*underlyingValueOwner.value().nonInterpolableValue), nonInterpolableList, newLength, nonInterpolableValuesAreCompatible)) {
        underlyingValueOwner.set(type, value);
        return;
    }

    InterpolationValue& underlyingValue = underlyingValueOwner.mutableValue();
    if (underlyingLength < newLength)
        repeatToLength(underlyingValue, newLength);

    InterpolableList& underlyingInterpolableList = toInterpolableList(*underlyingValue.interpolableValue);
    NonInterpolableList& underlyingNonInterpolableList = toNonInterpolableList(*underlyingValue.nonInterpolableValue);
    for (size_t i = 0; i < newLength; i++) {
        compositeItem(
            underlyingInterpolableList.getMutable(i),
            underlyingNonInterpolableList.getMutable(i),
            underlyingFraction,
            *interpolableList.get(i % valueLength),
            nonInterpolableList.get(i % valueLength));
    }
}