diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index c75b21f739cd5..9270901bcacdd 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -503,6 +503,7 @@ cc_defaults { "RenderProperties.cpp", "RootRenderNode.cpp", "SkiaCanvas.cpp", + "SkiaInterpolator.cpp", "VectorDrawable.cpp", ], diff --git a/libs/hwui/SkiaInterpolator.cpp b/libs/hwui/SkiaInterpolator.cpp new file mode 100644 index 0000000000000..0695dd1ab2188 --- /dev/null +++ b/libs/hwui/SkiaInterpolator.cpp @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SkiaInterpolator.h" + +#include "include/core/SkMath.h" +#include "include/private/SkFixed.h" +#include "include/private/SkMalloc.h" +#include "include/private/SkTo.h" +#include "src/core/SkTSearch.h" + +typedef int Dot14; +#define Dot14_ONE (1 << 14) +#define Dot14_HALF (1 << 13) + +#define Dot14ToFloat(x) ((x) / 16384.f) + +static inline Dot14 Dot14Mul(Dot14 a, Dot14 b) { + return (a * b + Dot14_HALF) >> 14; +} + +static inline Dot14 eval_cubic(Dot14 t, Dot14 A, Dot14 B, Dot14 C) { + return Dot14Mul(Dot14Mul(Dot14Mul(C, t) + B, t) + A, t); +} + +static inline Dot14 pin_and_convert(float x) { + if (x <= 0) { + return 0; + } + if (x >= SK_Scalar1) { + return Dot14_ONE; + } + return SkScalarToFixed(x) >> 2; +} + +static float SkUnitCubicInterp(float value, float bx, float by, float cx, float cy) { + // pin to the unit-square, and convert to 2.14 + Dot14 x = pin_and_convert(value); + + if (x == 0) return 0; + if (x == Dot14_ONE) return SK_Scalar1; + + Dot14 b = pin_and_convert(bx); + Dot14 c = pin_and_convert(cx); + + // Now compute our coefficients from the control points + // t -> 3b + // t^2 -> 3c - 6b + // t^3 -> 3b - 3c + 1 + Dot14 A = 3 * b; + Dot14 B = 3 * (c - 2 * b); + Dot14 C = 3 * (b - c) + Dot14_ONE; + + // Now search for a t value given x + Dot14 t = Dot14_HALF; + Dot14 dt = Dot14_HALF; + for (int i = 0; i < 13; i++) { + dt >>= 1; + Dot14 guess = eval_cubic(t, A, B, C); + if (x < guess) { + t -= dt; + } else { + t += dt; + } + } + + // Now we have t, so compute the coeff for Y and evaluate + b = pin_and_convert(by); + c = pin_and_convert(cy); + A = 3 * b; + B = 3 * (c - 2 * b); + C = 3 * (b - c) + Dot14_ONE; + return SkFixedToScalar(eval_cubic(t, A, B, C) << 2); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +SkiaInterpolatorBase::SkiaInterpolatorBase() { + fStorage = nullptr; + fTimes = nullptr; + SkDEBUGCODE(fTimesArray = nullptr;) +} + +SkiaInterpolatorBase::~SkiaInterpolatorBase() { + if (fStorage) { + sk_free(fStorage); + } +} + +void SkiaInterpolatorBase::reset(int elemCount, int frameCount) { + fFlags = 0; + fElemCount = SkToU8(elemCount); + fFrameCount = SkToS16(frameCount); + fRepeat = SK_Scalar1; + if (fStorage) { + sk_free(fStorage); + fStorage = nullptr; + fTimes = nullptr; + SkDEBUGCODE(fTimesArray = nullptr); + } +} + +/* Each value[] run is formatted as: +