Bug 1354947 - Fill in missing keyframe values. r=birtles

This is mostly a mimic of what we do in
GeckoCSSAnimationBuilder::FillInMissingKeyframeValues().

In Gecko we iterate over the properties just once because we can take the
index for both the synthesized start and end keyframe and easily look them up
as needed. However, in this patch we synthesize the start and end keyframes
separately and iterate over the properties twice because that's easier than
getting two indices and then later calling another FFI to dereference each of
them, and neater than getting back two pointers

MozReview-Commit-ID: 1e0R9AKzgaG

--HG--
extra : rebase_source : a37c406480c2d0ce2b8c4d4ad804622cac2083fa
This commit is contained in:
Hiroyuki Ikezoe 2017-05-13 16:34:38 +09:00
Родитель 8fd511dac1
Коммит c115978360
3 изменённых файлов: 99 добавлений и 14 удалений

Просмотреть файл

@ -194,6 +194,8 @@ function treatAsSafeArgument(entry, varName, csuName)
[/Gecko_EnsureStyle.*?ArrayLength/, "aArray", null],
["Gecko_AnimationAppendKeyframe", "aKeyframes", null],
["Gecko_GetOrCreateKeyframeAtStart", "aKeyframes", null],
["Gecko_GetOrCreateInitialKeyframe", "aKeyframes", null],
["Gecko_GetOrCreateFinalKeyframe", "aKeyframes", null],
["Gecko_SetStyleCoordCalcValue", null, null],
["Gecko_StyleClipPath_SetURLValue", "aClip", null],
["Gecko_nsStyleFilter_SetURLValue", "aEffects", null],
@ -376,6 +378,8 @@ function ignoreContents(entry)
// being initialized here.
"Gecko_AnimationAppendKeyframe",
"Gecko_GetOrCreateKeyframeAtStart",
"Gecko_GetOrCreateInitialKeyframe",
"Gecko_GetOrCreateFinalKeyframe",
"Gecko_NewStyleQuoteValues",
"Gecko_NewCSSValueSharedList",
"Gecko_NewGridTemplateAreasValue",

Просмотреть файл

@ -1468,29 +1468,54 @@ Gecko_AnimationAppendKeyframe(RawGeckoKeyframeListBorrowedMut aKeyframes,
return keyframe;
}
Keyframe*
Gecko_GetOrCreateKeyframeAtStart(nsTArray<Keyframe>* aKeyframes,
float aOffset,
const nsTimingFunction* aTimingFunction)
enum class KeyframeSearchDirection {
Forwards,
Backwards,
};
enum class KeyframeInsertPosition {
Prepend,
LastForOffset,
};
static Keyframe*
GetOrCreateKeyframe(nsTArray<Keyframe>* aKeyframes,
float aOffset,
const nsTimingFunction* aTimingFunction,
KeyframeSearchDirection aSearchDirection,
KeyframeInsertPosition aInsertPosition)
{
MOZ_ASSERT(aKeyframes, "The keyframe array should be valid");
MOZ_ASSERT(aTimingFunction, "The timing function should be valid");
MOZ_ASSERT(aOffset >= 0. && aOffset <= 1.,
"The offset should be in the range of [0.0, 1.0]");
MOZ_ASSERT(aKeyframes->IsEmpty() ||
aKeyframes->ElementAt(0).mOffset.value() >= aOffset,
"The offset should be less than or equal to the first keyframe's "
"offset if there are exisiting keyframes");
size_t keyframeIndex;
if (nsAnimationManager::FindMatchingKeyframe(*aKeyframes,
aOffset,
*aTimingFunction,
keyframeIndex)) {
return &(*aKeyframes)[keyframeIndex];
switch (aSearchDirection) {
case KeyframeSearchDirection::Forwards:
if (nsAnimationManager::FindMatchingKeyframe(*aKeyframes,
aOffset,
*aTimingFunction,
keyframeIndex)) {
return &(*aKeyframes)[keyframeIndex];
}
break;
case KeyframeSearchDirection::Backwards:
if (nsAnimationManager::FindMatchingKeyframe(Reversed(*aKeyframes),
aOffset,
*aTimingFunction,
keyframeIndex)) {
return &(*aKeyframes)[aKeyframes->Length() - 1 - keyframeIndex];
}
keyframeIndex = aKeyframes->Length() - 1;
break;
}
Keyframe* keyframe = aKeyframes->InsertElementAt(0);
Keyframe* keyframe =
aKeyframes->InsertElementAt(
aInsertPosition == KeyframeInsertPosition::Prepend
? 0
: keyframeIndex);
keyframe->mOffset.emplace(aOffset);
if (aTimingFunction->mType != nsTimingFunction::Type::Linear) {
keyframe->mTimingFunction.emplace();
@ -1500,6 +1525,45 @@ Gecko_GetOrCreateKeyframeAtStart(nsTArray<Keyframe>* aKeyframes,
return keyframe;
}
Keyframe*
Gecko_GetOrCreateKeyframeAtStart(nsTArray<Keyframe>* aKeyframes,
float aOffset,
const nsTimingFunction* aTimingFunction)
{
MOZ_ASSERT(aKeyframes->IsEmpty() ||
aKeyframes->ElementAt(0).mOffset.value() >= aOffset,
"The offset should be less than or equal to the first keyframe's "
"offset if there are exisiting keyframes");
return GetOrCreateKeyframe(aKeyframes,
aOffset,
aTimingFunction,
KeyframeSearchDirection::Forwards,
KeyframeInsertPosition::Prepend);
}
Keyframe*
Gecko_GetOrCreateInitialKeyframe(nsTArray<Keyframe>* aKeyframes,
const nsTimingFunction* aTimingFunction)
{
return GetOrCreateKeyframe(aKeyframes,
0.,
aTimingFunction,
KeyframeSearchDirection::Forwards,
KeyframeInsertPosition::LastForOffset);
}
Keyframe*
Gecko_GetOrCreateFinalKeyframe(nsTArray<Keyframe>* aKeyframes,
const nsTimingFunction* aTimingFunction)
{
return GetOrCreateKeyframe(aKeyframes,
1.,
aTimingFunction,
KeyframeSearchDirection::Backwards,
KeyframeInsertPosition::LastForOffset);
}
void
Gecko_ResetStyleCoord(nsStyleUnit* aUnit, nsStyleUnion* aValue)
{

Просмотреть файл

@ -392,6 +392,23 @@ mozilla::Keyframe* Gecko_GetOrCreateKeyframeAtStart(
float offset,
const nsTimingFunction* timingFunction);
// As with Gecko_GetOrCreateKeyframeAtStart except that this method will search
// from the beginning of |keyframes| for a Keyframe with matching timing
// function and an offset of 0.0.
// Furthermore, if a matching Keyframe is not found, a new Keyframe will be
// inserted after the *last* Keyframe in |keyframes| with offset 0.0.
mozilla::Keyframe* Gecko_GetOrCreateInitialKeyframe(
RawGeckoKeyframeListBorrowedMut keyframes,
const nsTimingFunction* timingFunction);
// As with Gecko_GetOrCreateKeyframeAtStart except that this method will search
// from the *end* of |keyframes| for a Keyframe with matching timing function
// and an offset of 1.0. If a matching Keyframe is not found, a new Keyframe
// will be appended to the end of |keyframes|.
mozilla::Keyframe* Gecko_GetOrCreateFinalKeyframe(
RawGeckoKeyframeListBorrowedMut keyframes,
const nsTimingFunction* timingFunction);
// Clean up pointer-based coordinates
void Gecko_ResetStyleCoord(nsStyleUnit* unit, nsStyleUnion* value);