37         double const diff_Y = right.
co.
Y - left.
co.
Y;
 
   38         double const diff_X = right.
co.
X - left.
co.
X;
 
   39         double const slope = diff_Y / diff_X;
 
   40         return left.
co.
Y + slope * (target - left.
co.
X);
 
   45         double const X_diff = right.
co.
X - left.
co.
X;
 
   46         double const Y_diff = right.
co.
Y - left.
co.
Y;
 
   56             double B[4] = {1, 3, 3, 1};
 
   57             double oneMinTExp = 1;
 
   59             for (
int i = 0; i < 4; ++i, tExp *= t) {
 
   62             for (
int i = 0; i < 4; ++i, oneMinTExp *= 1 - t) {
 
   63                 B[4 - i - 1] *= oneMinTExp;
 
   65             double const x = p0.
X * B[0] + p1.
X * B[1] + p2.
X * B[2] + p3.
X * B[3];
 
   66             double const y = p0.
Y * B[0] + p1.
Y * B[1] + p2.
Y * B[2] + p3.
Y * B[3];
 
   67             if (fabs(target - x) < allowed_error) {
 
   83         if(left.
co.
X > target){
 
   86         if(target > right.
co.
X){
 
   98 template<
typename Check>
 
  100     int64_t start = left.
co.
X;
 
  101     int64_t stop = right.
co.
X;
 
  102     while (start < stop) {
 
  103         int64_t 
const mid = (start + stop + 1) / 2;
 
  105         if (check(round(value), current)) {
 
  115 Keyframe::Keyframe(
double value) {
 
  117     AddPoint(
Point(1, value));
 
  121 Keyframe::Keyframe(
const std::vector<openshot::Point>& points) : Points(points) {};
 
  126     Points.shrink_to_fit();
 
  134     std::vector<Point>::iterator candidate =
 
  136     if (candidate == end(Points)) {
 
  140     } 
else if ((*candidate).co.X == p.
co.
X) {
 
  148         size_t const candidate_index = candidate - begin(Points);
 
  150         std::move_backward(begin(Points) + candidate_index, end(Points) - 1, end(Points));
 
  151         Points[candidate_index] = p;
 
  159     Point new_point(x, y, interpolate);
 
  168     for (std::vector<Point>::size_type x = 0; x < Points.size(); x++) {
 
  170         Point existing_point = Points[x];
 
  173         if (p.
co.
X == existing_point.
co.
X && p.
co.
Y == existing_point.
co.
Y) {
 
  185     std::vector<Point>::const_iterator i =
 
  187     return i != end(Points) && i->co.X == p.
co.
X;
 
  192     if (Points.size() == 0) {
 
  193         return Point(-1, -1);
 
  198     std::vector<Point>::const_iterator candidate =
 
  201     if (candidate == end(Points)) {
 
  205         return Points.back();
 
  207     if (candidate == begin(Points)) {
 
  211         return Points.front();
 
  214         return *(candidate - 1);
 
  234             return Points[index - 1];
 
  240         return Point(-1, -1);
 
  246     Point maxPoint(-1, -1);
 
  248     for (
Point const & existing_point: Points) {
 
  249         if (existing_point.co.Y >= maxPoint.
co.
Y) {
 
  250             maxPoint = existing_point;
 
  259     if (Points.empty()) {
 
  262     std::vector<Point>::const_iterator candidate =
 
  263         std::lower_bound(begin(Points), end(Points), 
static_cast<double>(index), 
IsPointBeforeX);
 
  265     if (candidate == end(Points)) {
 
  267         return Points.back().co.Y;
 
  269     if (candidate == begin(Points)) {
 
  271         return Points.front().co.Y;
 
  273     if (candidate->co.X == index) {
 
  275         return candidate->co.Y;
 
  277     std::vector<Point>::const_iterator predecessor = candidate - 1;
 
  288     return long(round(
GetValue(index)));
 
  303     const double current_value = 
GetValue(index);
 
  307     while (attempts < 600 && index + attempts <= 
GetLength()) {
 
  309         const double next_value = 
GetValue(index + attempts);
 
  312         const double diff = next_value - current_value;
 
  313         if (fabs(diff) > 0.0001) {
 
  343     root[
"Points"] = Json::Value(Json::arrayValue);
 
  346     for (
const auto existing_point : Points) {
 
  347         root[
"Points"].append(existing_point.JsonValue());
 
  364     catch (
const std::exception& e)
 
  367         throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
 
  375     Points.shrink_to_fit();
 
  377     if (root.isObject() && !root[
"Points"].isNull()) {
 
  379         for (
const auto existing_point : root[
"Points"]) {
 
  389     } 
else if (root.isNumeric()) {
 
  391         Point p(root.asFloat());
 
  400     if (index < 1) 
return 0.0;
 
  401     if (index == 1 && !Points.empty()) 
return Points[0].co.Y;
 
  409     if (index >= 0 && index < (int64_t)Points.size())
 
  410         return Points[index];
 
  418     if (Points.empty()) 
return 0;
 
  419     if (Points.size() == 1) 
return 1;
 
  420     return round(Points.back().co.X);
 
  426     return Points.size();
 
  432     for (std::vector<Point>::size_type x = 0; x < Points.size(); x++) {
 
  434         Point existing_point = Points[x];
 
  437         if (p.
co.
X == existing_point.
co.
X && p.
co.
Y == existing_point.
co.
Y) {
 
  439             Points.erase(Points.begin() + x);
 
  451     if (index >= 0 && index < (int64_t)Points.size())
 
  454         Points.erase(Points.begin() + index);
 
  471     *out << std::right << std::setprecision(4) << std::setfill(
' ');
 
  472     for (
const auto& p : Points) {
 
  473         *out << std::defaultfloat
 
  474              << std::setw(6) << p.co.X
 
  475              << std::setw(14) << std::fixed << p.co.Y
 
  483     std::vector<int> w{10, 12, 8, 11, 19};
 
  485     *out << std::right << std::setfill(
' ') << std::setprecision(4);
 
  488          << std::setw(w[0]) << 
"Frame# (X)" << 
" │" 
  489          << std::setw(w[1]) << 
"Y Value" << 
" │" 
  490          << std::setw(w[2]) << 
"Delta Y" << 
" │ " 
  491          << std::setw(w[3]) << 
"Increasing?" << std::right
 
  494     *out << 
"├───────────" 
  497          << 
"┼────────────┤\n";
 
  499     for (int64_t i = 1; i <= 
GetLength(); ++i) {
 
  501              << std::setw(w[0]-2) << std::defaultfloat << i
 
  503              << std::setw(w[1]) << std::fixed << 
GetValue(i) << 
" │" 
  504              << std::setw(w[2]) << std::defaultfloat << std::showpos
 
  505                                 << 
GetDelta(i) << 
" │ " << std::noshowpos
 
  507              << (
IsIncreasing(i) ? 
"true" : 
"false") << std::right << 
"│\n";
 
  509     *out << 
" * = Keyframe point (non-interpolated)\n";
 
  523     for (std::vector<Point>::size_type point_index = 1; point_index < Points.size(); point_index++) {
 
  525         Points[point_index].co.X = round(Points[point_index].co.X * scale);
 
  531     for (std::vector<Point>::size_type point_index = 0, reverse_index = Points.size() - 1; point_index < reverse_index; point_index++, reverse_index--) {
 
  534         swap(Points[point_index].co.Y, Points[reverse_index].co.Y);