You've already forked libopenshot
mirror of
https://github.com/OpenShot/libopenshot.git
synced 2026-03-02 08:53:52 -08:00
Merge branch 'move-feature-summary' into coverage-build
This commit is contained in:
@@ -66,6 +66,15 @@ Generating build files for OpenShot with CMake ${CMAKE_VERSION}
|
||||
# in order to properly configure CMAKE_INSTALL_LIBDIR path
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Collect and display summary of options/dependencies
|
||||
include(FeatureSummary)
|
||||
|
||||
################ OPTIONS ##################
|
||||
# Optional build settings for libopenshot
|
||||
option(USE_SYSTEM_JSONCPP "Use system installed JsonCpp, if found" ON)
|
||||
option(DISABLE_BUNDLED_JSONCPP "Don't fall back to bundled JsonCpp" OFF)
|
||||
option(ENABLE_IWYU "Enable 'Include What You Use' scanner (CMake 3.3+)" OFF)
|
||||
|
||||
########## Configure Version.h header ##############
|
||||
configure_file(include/OpenShotVersion.h.in include/OpenShotVersion.h @ONLY)
|
||||
# We'll want that installed later
|
||||
@@ -106,17 +115,23 @@ if (TARGET doc)
|
||||
message(STATUS "Doxygen found, documentation target enabled")
|
||||
message("\nTo compile documentation in doc/html, run: 'make doc'")
|
||||
|
||||
# Install docs, if the user builds them with `make doc`
|
||||
install(CODE "MESSAGE(\"Checking for documentation files to install...\")")
|
||||
install(CODE "MESSAGE(\"(Compile with 'make doc' command, requires Doxygen)\")")
|
||||
# Install docs, if the user builds them with `make doc`
|
||||
install(CODE "MESSAGE(\"Checking for documentation files to install...\")")
|
||||
install(CODE "MESSAGE(\"(Compile with 'make doc' command, requires Doxygen)\")")
|
||||
|
||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/html/
|
||||
DESTINATION ${CMAKE_INSTALL_DOCDIR}/API
|
||||
MESSAGE_NEVER # Don't spew about file copies
|
||||
OPTIONAL ) # No error if the docs aren't found
|
||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/html/
|
||||
DESTINATION ${CMAKE_INSTALL_DOCDIR}/API
|
||||
MESSAGE_NEVER # Don't spew about file copies
|
||||
OPTIONAL ) # No error if the docs aren't found
|
||||
endif()
|
||||
|
||||
############# PROCESS tests/ DIRECTORY ##############
|
||||
if(NOT DISABLE_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
########### PRINT FEATURE SUMMARY ##############
|
||||
feature_summary(WHAT ALL
|
||||
INCLUDE_QUIET_PACKAGES
|
||||
FATAL_ON_MISSING_REQUIRED_PACKAGES
|
||||
DESCRIPTION "Displaying feature summary\n\nBuild configuration:")
|
||||
|
||||
@@ -340,7 +340,7 @@ AUTOLINK_SUPPORT = YES
|
||||
# diagrams that involve STL classes more complete and accurate.
|
||||
# The default value is: NO.
|
||||
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
BUILTIN_STL_SUPPORT = YES
|
||||
|
||||
# If you use Microsoft's C++/CLI language, you should set this option to YES to
|
||||
# enable parsing support.
|
||||
@@ -2096,7 +2096,7 @@ INCLUDE_FILE_PATTERNS =
|
||||
# recursively expanded use the := operator instead of the = operator.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
PREDEFINED =
|
||||
PREDEFINED = USE_BLACKMAGIC USE_IMAGEMAGICK
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||
# tag can be used to specify a list of macro names that should be expanded. The
|
||||
|
||||
@@ -63,37 +63,12 @@ namespace openshot {
|
||||
*/
|
||||
class Keyframe {
|
||||
private:
|
||||
bool needs_update;
|
||||
double FactorialLookup[4];
|
||||
|
||||
/*
|
||||
* Because points can be added in any order, we need to reorder them
|
||||
* in ascending order based on the point.co.X value. This simplifies
|
||||
* processing the curve, due to all the points going from left to right.
|
||||
*/
|
||||
void ReorderPoints();
|
||||
|
||||
// Process an individual segment
|
||||
void ProcessSegment(int Segment, Point p1, Point p2);
|
||||
|
||||
// create lookup table for fast factorial calculation
|
||||
void CreateFactorialTable();
|
||||
|
||||
// Get a factorial for a coordinate
|
||||
double Factorial(int64_t n);
|
||||
|
||||
// Calculate the factorial function for Bernstein basis
|
||||
double Ni(int64_t n, int64_t i);
|
||||
|
||||
// Calculate Bernstein Basis
|
||||
double Bernstein(int64_t n, int64_t i, double t);
|
||||
std::vector<Point> Points; ///< Vector of all Points
|
||||
|
||||
public:
|
||||
std::vector<Point> Points; ///< Vector of all Points
|
||||
std::vector<Coordinate> Values; ///< Vector of all Values (i.e. the processed coordinates from the curve)
|
||||
|
||||
/// Default constructor for the Keyframe class
|
||||
Keyframe();
|
||||
Keyframe() = default;
|
||||
|
||||
/// Constructor which sets the default point & coordinate at X=1
|
||||
Keyframe(double value);
|
||||
@@ -108,68 +83,60 @@ namespace openshot {
|
||||
void AddPoint(double x, double y, InterpolationType interpolate);
|
||||
|
||||
/// Does this keyframe contain a specific point
|
||||
bool Contains(Point p);
|
||||
bool Contains(Point p) const;
|
||||
|
||||
/// Flip all the points in this openshot::Keyframe (useful for reversing an effect or transition, etc...)
|
||||
void FlipPoints();
|
||||
|
||||
/// Get the index of a point by matching a coordinate
|
||||
int64_t FindIndex(Point p);
|
||||
int64_t FindIndex(Point p) const;
|
||||
|
||||
/// Get the value at a specific index
|
||||
double GetValue(int64_t index);
|
||||
double GetValue(int64_t index) const;
|
||||
|
||||
/// Get the rounded INT value at a specific index
|
||||
int GetInt(int64_t index);
|
||||
int GetInt(int64_t index) const;
|
||||
|
||||
/// Get the rounded LONG value at a specific index
|
||||
int64_t GetLong(int64_t index);
|
||||
int64_t GetLong(int64_t index) const;
|
||||
|
||||
/// Get the fraction that represents how many times this value is repeated in the curve
|
||||
Fraction GetRepeatFraction(int64_t index);
|
||||
Fraction GetRepeatFraction(int64_t index) const;
|
||||
|
||||
/// Get the change in Y value (from the previous Y value)
|
||||
double GetDelta(int64_t index);
|
||||
double GetDelta(int64_t index) const;
|
||||
|
||||
/// Get a point at a specific index
|
||||
Point& GetPoint(int64_t index);
|
||||
Point const & GetPoint(int64_t index) const;
|
||||
|
||||
/// Get current point (or closest point to the right) from the X coordinate (i.e. the frame number)
|
||||
Point GetClosestPoint(Point p);
|
||||
Point GetClosestPoint(Point p) const;
|
||||
|
||||
/// Get current point (or closest point) from the X coordinate (i.e. the frame number)
|
||||
/// Either use the closest left point, or right point
|
||||
Point GetClosestPoint(Point p, bool useLeft);
|
||||
Point GetClosestPoint(Point p, bool useLeft) const;
|
||||
|
||||
/// Get previous point (
|
||||
Point GetPreviousPoint(Point p);
|
||||
Point GetPreviousPoint(Point p) const;
|
||||
|
||||
/// Get max point (by Y coordinate)
|
||||
Point GetMaxPoint();
|
||||
Point GetMaxPoint() const;
|
||||
|
||||
// Get the number of values (i.e. coordinates on the X axis)
|
||||
int64_t GetLength();
|
||||
int64_t GetLength() const;
|
||||
|
||||
/// Get the number of points (i.e. # of points)
|
||||
int64_t GetCount();
|
||||
int64_t GetCount() const;
|
||||
|
||||
/// Get the direction of the curve at a specific index (increasing or decreasing)
|
||||
bool IsIncreasing(int index);
|
||||
bool IsIncreasing(int index) const;
|
||||
|
||||
/// Get and Set JSON methods
|
||||
std::string Json(); ///< Generate JSON string of this object
|
||||
Json::Value JsonValue(); ///< Generate Json::JsonValue for this object
|
||||
std::string Json() const; ///< Generate JSON string of this object
|
||||
Json::Value JsonValue() const; ///< Generate Json::JsonValue for this object
|
||||
void SetJson(std::string value); ///< Load JSON string into this object
|
||||
void SetJsonValue(Json::Value root); ///< Load Json::JsonValue into this object
|
||||
|
||||
/**
|
||||
* @brief Calculate all of the values for this keyframe.
|
||||
*
|
||||
* This clears any existing data in the "values" vector. This method is automatically called
|
||||
* by AddPoint(), so you don't typically need to call this method.
|
||||
*/
|
||||
void Process();
|
||||
|
||||
/// Remove a point by matching a coordinate
|
||||
void RemovePoint(Point p);
|
||||
|
||||
@@ -184,10 +151,10 @@ namespace openshot {
|
||||
void UpdatePoint(int64_t index, Point p);
|
||||
|
||||
/// Print a list of points
|
||||
void PrintPoints();
|
||||
void PrintPoints() const;
|
||||
|
||||
/// Print just the Y value of the point's primary coordinate
|
||||
void PrintValues();
|
||||
void PrintValues() const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -27,12 +27,6 @@
|
||||
# Collect and display summary of options/dependencies
|
||||
include(FeatureSummary)
|
||||
|
||||
################ OPTIONS ##################
|
||||
# Optional build settings for libopenshot
|
||||
option(USE_SYSTEM_JSONCPP "Use system installed JsonCpp, if found" ON)
|
||||
option(DISABLE_BUNDLED_JSONCPP "Don't fall back to bundled JsonCpp" OFF)
|
||||
option(ENABLE_IWYU "Enable 'Include What You Use' scanner (CMake 3.3+)" OFF)
|
||||
|
||||
# Automatically process Qt classes with meta-object compiler
|
||||
set(CMAKE_AUTOMOC True)
|
||||
|
||||
@@ -426,12 +420,6 @@ ENDIF (BLACKMAGIC_FOUND)
|
||||
############### INCLUDE SWIG BINDINGS ################
|
||||
add_subdirectory(bindings)
|
||||
|
||||
########### PRINT FEATURE SUMMARY ##############
|
||||
feature_summary(WHAT ALL
|
||||
INCLUDE_QUIET_PACKAGES
|
||||
FATAL_ON_MISSING_REQUIRED_PACKAGES
|
||||
DESCRIPTION "Displaying feature summary\n\nBuild configuration:")
|
||||
|
||||
############### INSTALL HEADERS & LIBRARY ################
|
||||
set(LIB_INSTALL_DIR lib${LIB_SUFFIX}) # determine correct lib folder
|
||||
|
||||
|
||||
14
src/Clip.cpp
14
src/Clip.cpp
@@ -109,10 +109,10 @@ void Clip::init_settings()
|
||||
// Init reader's rotation (if any)
|
||||
void Clip::init_reader_rotation() {
|
||||
// Only init rotation from reader when needed
|
||||
if (rotation.Points.size() > 1)
|
||||
if (rotation.GetCount() > 1)
|
||||
// Do nothing if more than 1 rotation Point
|
||||
return;
|
||||
else if (rotation.Points.size() == 1 && rotation.GetValue(1) != 0.0)
|
||||
else if (rotation.GetCount() == 1 && rotation.GetValue(1) != 0.0)
|
||||
// Do nothing if 1 Point, and it's not the default value
|
||||
return;
|
||||
|
||||
@@ -273,7 +273,7 @@ void Clip::Close()
|
||||
float Clip::End()
|
||||
{
|
||||
// if a time curve is present, use its length
|
||||
if (time.Points.size() > 1)
|
||||
if (time.GetCount() > 1)
|
||||
{
|
||||
// Determine the FPS fo this clip
|
||||
float fps = 24.0;
|
||||
@@ -314,8 +314,8 @@ std::shared_ptr<Frame> Clip::GetFrame(int64_t requested_frame)
|
||||
// Is a time map detected
|
||||
int64_t new_frame_number = requested_frame;
|
||||
int64_t time_mapped_number = adjust_frame_number_minimum(time.GetLong(requested_frame));
|
||||
if (time.Values.size() > 1)
|
||||
new_frame_number = time_mapped_number;
|
||||
if (time.GetLength() > 1)
|
||||
new_frame_number = time_mapped_number;
|
||||
|
||||
// Now that we have re-mapped what frame number is needed, go and get the frame pointer
|
||||
std::shared_ptr<Frame> original_frame;
|
||||
@@ -397,7 +397,7 @@ void Clip::get_time_mapped_frame(std::shared_ptr<Frame> frame, int64_t frame_num
|
||||
throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method.");
|
||||
|
||||
// Check for a valid time map curve
|
||||
if (time.Values.size() > 1)
|
||||
if (time.GetLength() > 1)
|
||||
{
|
||||
const GenericScopedLock<juce::CriticalSection> lock(getFrameCriticalSection);
|
||||
|
||||
@@ -914,7 +914,7 @@ void Clip::SetJsonValue(Json::Value root) {
|
||||
|
||||
if (!existing_effect["type"].isNull()) {
|
||||
// Create instance of effect
|
||||
if (e = EffectInfo().CreateEffect(existing_effect["type"].asString())) {
|
||||
if ( (e = EffectInfo().CreateEffect(existing_effect["type"].asString())) ) {
|
||||
|
||||
// Load Json into Effect
|
||||
e->SetJsonValue(existing_effect);
|
||||
|
||||
@@ -341,7 +341,7 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va
|
||||
// Was option found?
|
||||
if (option || (name == "g" || name == "qmin" || name == "qmax" || name == "max_b_frames" || name == "mb_decision" ||
|
||||
name == "level" || name == "profile" || name == "slices" || name == "rc_min_rate" || name == "rc_max_rate" ||
|
||||
name == "crf" || name == "cqp")) {
|
||||
name == "rc_buffer_size" || name == "crf" || name == "cqp")) {
|
||||
// Check for specific named options
|
||||
if (name == "g")
|
||||
// Set gop_size
|
||||
|
||||
@@ -280,7 +280,7 @@ const unsigned char* Frame::GetWaveformPixels(int width, int height, int Red, in
|
||||
wave_image = GetWaveform(width, height, Red, Green, Blue, Alpha);
|
||||
|
||||
// Return array of pixel packets
|
||||
return wave_image->bits();
|
||||
return wave_image->constBits();
|
||||
}
|
||||
|
||||
// Display the wave form
|
||||
@@ -473,14 +473,14 @@ const unsigned char* Frame::GetPixels()
|
||||
AddColor(width, height, color);
|
||||
|
||||
// Return array of pixel packets
|
||||
return image->bits();
|
||||
return image->constBits();
|
||||
}
|
||||
|
||||
// Get pixel data (for only a single scan-line)
|
||||
const unsigned char* Frame::GetPixels(int row)
|
||||
{
|
||||
// Return array of pixel packets
|
||||
return image->scanLine(row);
|
||||
return image->constScanLine(row);
|
||||
}
|
||||
|
||||
// Check a specific pixel color value (returns True/False)
|
||||
@@ -692,7 +692,7 @@ void Frame::Thumbnail(std::string path, int new_width, int new_height, std::stri
|
||||
|
||||
// Get pixels
|
||||
unsigned char *pixels = (unsigned char *) thumbnail->bits();
|
||||
unsigned char *mask_pixels = (unsigned char *) mask->bits();
|
||||
const unsigned char *mask_pixels = (const unsigned char *) mask->constBits();
|
||||
|
||||
// Convert the mask image to grayscale
|
||||
// Loop through pixels
|
||||
@@ -826,8 +826,8 @@ void Frame::AddImage(std::shared_ptr<QImage> new_image, bool only_odd_lines)
|
||||
const GenericScopedLock<juce::CriticalSection> lock(addingImageSection);
|
||||
#pragma omp critical (AddImage)
|
||||
{
|
||||
const unsigned char *pixels = image->bits();
|
||||
const unsigned char *new_pixels = new_image->bits();
|
||||
const unsigned char *pixels = image->constBits();
|
||||
const unsigned char *new_pixels = new_image->constBits();
|
||||
|
||||
// Loop through the scanlines of the image (even or odd)
|
||||
int start = 0;
|
||||
@@ -922,7 +922,7 @@ std::shared_ptr<Magick::Image> Frame::GetMagickImage()
|
||||
AddColor(width, height, "#000000");
|
||||
|
||||
// Get the pixels from the frame image
|
||||
QRgb const *tmpBits = (const QRgb*)image->bits();
|
||||
const QRgb *tmpBits = (const QRgb*)image->constBits();
|
||||
|
||||
// Create new image object, and fill with pixel data
|
||||
std::shared_ptr<Magick::Image> magick_image = std::shared_ptr<Magick::Image>(new Magick::Image(image->width(), image->height(),"RGBA", Magick::CharPixel, tmpBits));
|
||||
|
||||
913
src/KeyFrame.cpp
913
src/KeyFrame.cpp
File diff suppressed because it is too large
Load Diff
@@ -824,7 +824,7 @@ std::shared_ptr<Frame> Timeline::GetFrame(int64_t requested_frame)
|
||||
ZmqLogger::Instance()->AppendDebugMethod("Timeline::GetFrame (Adding solid color)", "frame_number", frame_number, "info.width", info.width, "info.height", info.height);
|
||||
|
||||
// Add Background Color to 1st layer (if animated or not black)
|
||||
if ((color.red.Points.size() > 1 || color.green.Points.size() > 1 || color.blue.Points.size() > 1) ||
|
||||
if ((color.red.GetCount() > 1 || color.green.GetCount() > 1 || color.blue.GetCount() > 1) ||
|
||||
(color.red.GetValue(frame_number) != 0.0 || color.green.GetValue(frame_number) != 0.0 || color.blue.GetValue(frame_number) != 0.0))
|
||||
new_frame->AddColor(Settings::Instance()->MAX_WIDTH, Settings::Instance()->MAX_HEIGHT, color.GetColorHex(frame_number));
|
||||
|
||||
@@ -1098,7 +1098,7 @@ void Timeline::SetJsonValue(Json::Value root) {
|
||||
|
||||
if (!existing_effect["type"].isNull()) {
|
||||
// Create instance of effect
|
||||
if (e = EffectInfo().CreateEffect(existing_effect["type"].asString())) {
|
||||
if ( (e = EffectInfo().CreateEffect(existing_effect["type"].asString())) ) {
|
||||
|
||||
// Load Json into Effect
|
||||
e->SetJsonValue(existing_effect);
|
||||
@@ -1364,7 +1364,7 @@ void Timeline::apply_json_to_effects(Json::Value change, EffectBase* existing_ef
|
||||
EffectBase *e = NULL;
|
||||
|
||||
// Init the matching effect object
|
||||
if (e = EffectInfo().CreateEffect(effect_type)) {
|
||||
if ( (e = EffectInfo().CreateEffect(effect_type)) ) {
|
||||
|
||||
// Load Json into Effect
|
||||
e->SetJsonValue(change["value"]);
|
||||
|
||||
@@ -153,10 +153,16 @@
|
||||
}
|
||||
|
||||
%extend openshot::OpenShotVersion {
|
||||
// Give the struct a string representation
|
||||
// Give the struct a string representation
|
||||
const std::string __str__() {
|
||||
return std::string(OPENSHOT_VERSION_FULL);
|
||||
}
|
||||
// And a repr for interactive use
|
||||
const std::string __repr__() {
|
||||
std::ostringstream result;
|
||||
result << "OpenShotVersion('" << OPENSHOT_VERSION_FULL << "')";
|
||||
return result.str();
|
||||
}
|
||||
}
|
||||
|
||||
%include "OpenShotVersion.h"
|
||||
|
||||
@@ -79,7 +79,7 @@ TEST(Color_HEX_Value)
|
||||
c.blue.AddPoint(100, 255);
|
||||
|
||||
CHECK_EQUAL("#000000", c.GetColorHex(1));
|
||||
CHECK_EQUAL("#7f7f7f", c.GetColorHex(50));
|
||||
CHECK_EQUAL("#7d7d7d", c.GetColorHex(50));
|
||||
CHECK_EQUAL("#ffffff", c.GetColorHex(100));
|
||||
|
||||
}
|
||||
@@ -93,7 +93,7 @@ TEST(Color_HEX_Constructor)
|
||||
c.blue.AddPoint(100, 255);
|
||||
|
||||
CHECK_EQUAL("#4586db", c.GetColorHex(1));
|
||||
CHECK_EQUAL("#a2c2ed", c.GetColorHex(50));
|
||||
CHECK_EQUAL("#a0c1ed", c.GetColorHex(50));
|
||||
CHECK_EQUAL("#ffffff", c.GetColorHex(100));
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ TEST(Color_RGBA_Constructor)
|
||||
c.blue.AddPoint(100, 255);
|
||||
|
||||
CHECK_EQUAL("#4586db", c.GetColorHex(1));
|
||||
CHECK_EQUAL("#a2c2ed", c.GetColorHex(50));
|
||||
CHECK_EQUAL("#a0c1ed", c.GetColorHex(50));
|
||||
CHECK_EQUAL("#ffffff", c.GetColorHex(100));
|
||||
|
||||
// Color with alpha
|
||||
|
||||
@@ -51,7 +51,7 @@ TEST(Keyframe_GetPoint_With_1_Points)
|
||||
k1.AddPoint(openshot::Point(2,3));
|
||||
|
||||
CHECK_THROW(k1.GetPoint(-1), OutOfBoundsPoint);
|
||||
CHECK_EQUAL(1, k1.Points.size());
|
||||
CHECK_EQUAL(1, k1.GetCount());
|
||||
CHECK_CLOSE(2.0f, k1.GetPoint(0).co.X, 0.00001);
|
||||
CHECK_CLOSE(3.0f, k1.GetPoint(0).co.Y, 0.00001);
|
||||
CHECK_THROW(k1.GetPoint(1), OutOfBoundsPoint);
|
||||
@@ -92,13 +92,13 @@ TEST(Keyframe_GetValue_For_Bezier_Curve_2_Points)
|
||||
// Spot check values from the curve
|
||||
CHECK_CLOSE(1.0f, kf.GetValue(-1), 0.0001);
|
||||
CHECK_CLOSE(1.0f, kf.GetValue(0), 0.0001);
|
||||
CHECK_CLOSE(1.00023f, kf.GetValue(1), 0.0001);
|
||||
CHECK_CLOSE(1.14025f, kf.GetValue(9), 0.0001);
|
||||
CHECK_CLOSE(1.91492f, kf.GetValue(20), 0.0001);
|
||||
CHECK_CLOSE(3.81602f, kf.GetValue(40), 0.0001);
|
||||
CHECK_CLOSE(1.0f, kf.GetValue(1), 0.0001);
|
||||
CHECK_CLOSE(1.12414f, kf.GetValue(9), 0.0001);
|
||||
CHECK_CLOSE(1.86370f, kf.GetValue(20), 0.0001);
|
||||
CHECK_CLOSE(3.79733f, kf.GetValue(40), 0.0001);
|
||||
CHECK_CLOSE(4.0f, kf.GetValue(50), 0.0001);
|
||||
// Check the expected number of values
|
||||
CHECK_EQUAL(kf.Values.size(), 51);
|
||||
CHECK_EQUAL(51, kf.GetLength());
|
||||
}
|
||||
|
||||
TEST(Keyframe_GetValue_For_Bezier_Curve_5_Points_40_Percent_Handle)
|
||||
@@ -114,14 +114,14 @@ TEST(Keyframe_GetValue_For_Bezier_Curve_5_Points_40_Percent_Handle)
|
||||
// Spot check values from the curve
|
||||
CHECK_CLOSE(kf.GetValue(-1), 1.0f, 0.0001);
|
||||
CHECK_CLOSE(1.0f, kf.GetValue(0), 0.0001);
|
||||
CHECK_CLOSE(1.00023f, kf.GetValue(1), 0.0001);
|
||||
CHECK_CLOSE(2.73656f, kf.GetValue(27), 0.0001);
|
||||
CHECK_CLOSE(7.55139f, kf.GetValue(77), 0.0001);
|
||||
CHECK_CLOSE(4.08102f, kf.GetValue(127), 0.0001);
|
||||
CHECK_CLOSE(1.77569f, kf.GetValue(177), 0.0001);
|
||||
CHECK_CLOSE(1.0f, kf.GetValue(1), 0.0001);
|
||||
CHECK_CLOSE(2.68197f, kf.GetValue(27), 0.0001);
|
||||
CHECK_CLOSE(7.47719f, kf.GetValue(77), 0.0001);
|
||||
CHECK_CLOSE(4.20468f, kf.GetValue(127), 0.0001);
|
||||
CHECK_CLOSE(1.73860f, kf.GetValue(177), 0.0001);
|
||||
CHECK_CLOSE(3.0f, kf.GetValue(200), 0.0001);
|
||||
// Check the expected number of values
|
||||
CHECK_EQUAL(kf.Values.size(), 201);
|
||||
CHECK_EQUAL(201, kf.GetLength());
|
||||
}
|
||||
|
||||
TEST(Keyframe_GetValue_For_Bezier_Curve_5_Points_25_Percent_Handle)
|
||||
@@ -137,14 +137,14 @@ TEST(Keyframe_GetValue_For_Bezier_Curve_5_Points_25_Percent_Handle)
|
||||
// Spot check values from the curve
|
||||
CHECK_CLOSE(1.0f, kf.GetValue(-1), 0.0001);
|
||||
CHECK_CLOSE(1.0f, kf.GetValue(0), 0.0001);
|
||||
CHECK_CLOSE(1.00023f, kf.GetValue(1), 0.0001);
|
||||
CHECK_CLOSE(2.73656f, kf.GetValue(27), 0.0001);
|
||||
CHECK_CLOSE(7.55139f, kf.GetValue(77), 0.0001);
|
||||
CHECK_CLOSE(4.08102f, kf.GetValue(127), 0.0001);
|
||||
CHECK_CLOSE(1.77569f, kf.GetValue(177), 0.0001);
|
||||
CHECK_CLOSE(1.0f, kf.GetValue(1), 0.0001);
|
||||
CHECK_CLOSE(2.68197f, kf.GetValue(27), 0.0001);
|
||||
CHECK_CLOSE(7.47719f, kf.GetValue(77), 0.0001);
|
||||
CHECK_CLOSE(4.20468f, kf.GetValue(127), 0.0001);
|
||||
CHECK_CLOSE(1.73860f, kf.GetValue(177), 0.0001);
|
||||
CHECK_CLOSE(3.0f, kf.GetValue(200), 0.0001);
|
||||
// Check the expected number of values
|
||||
CHECK_EQUAL(kf.Values.size(), 201);
|
||||
CHECK_EQUAL(201, kf.GetLength());
|
||||
}
|
||||
|
||||
TEST(Keyframe_GetValue_For_Linear_Curve_3_Points)
|
||||
@@ -164,7 +164,7 @@ TEST(Keyframe_GetValue_For_Linear_Curve_3_Points)
|
||||
CHECK_CLOSE(4.4f, kf.GetValue(40), 0.0001);
|
||||
CHECK_CLOSE(2.0f, kf.GetValue(50), 0.0001);
|
||||
// Check the expected number of values
|
||||
CHECK_EQUAL(kf.Values.size(), 51);
|
||||
CHECK_EQUAL(51, kf.GetLength());
|
||||
}
|
||||
|
||||
TEST(Keyframe_GetValue_For_Constant_Curve_3_Points)
|
||||
@@ -185,7 +185,7 @@ TEST(Keyframe_GetValue_For_Constant_Curve_3_Points)
|
||||
CHECK_CLOSE(8.0f, kf.GetValue(49), 0.0001);
|
||||
CHECK_CLOSE(2.0f, kf.GetValue(50), 0.0001);
|
||||
// Check the expected number of values
|
||||
CHECK_EQUAL(kf.Values.size(), 51);
|
||||
CHECK_EQUAL(51, kf.GetLength());
|
||||
}
|
||||
|
||||
TEST(Keyframe_Check_Direction_and_Repeat_Fractions)
|
||||
@@ -197,29 +197,29 @@ TEST(Keyframe_Check_Direction_and_Repeat_Fractions)
|
||||
kf.AddPoint(500, 500);
|
||||
|
||||
// Spot check values from the curve
|
||||
CHECK_EQUAL(kf.GetInt(1), 500);
|
||||
CHECK_EQUAL(kf.IsIncreasing(1), false);
|
||||
CHECK_EQUAL(kf.GetRepeatFraction(1).num, 1);
|
||||
CHECK_EQUAL(kf.GetRepeatFraction(1).den, 12);
|
||||
CHECK_EQUAL(kf.GetDelta(1), 500);
|
||||
CHECK_EQUAL(500, kf.GetInt(1));
|
||||
CHECK_EQUAL(false, kf.IsIncreasing(1));
|
||||
CHECK_EQUAL(1, kf.GetRepeatFraction(1).num);
|
||||
CHECK_EQUAL(13, kf.GetRepeatFraction(1).den);
|
||||
CHECK_EQUAL(500, kf.GetDelta(1));
|
||||
|
||||
CHECK_EQUAL(kf.GetInt(24), 498);
|
||||
CHECK_EQUAL(kf.IsIncreasing(24), false);
|
||||
CHECK_EQUAL(kf.GetRepeatFraction(24).num, 3);
|
||||
CHECK_EQUAL(kf.GetRepeatFraction(24).den, 6);
|
||||
CHECK_EQUAL(kf.GetDelta(24), 0);
|
||||
CHECK_EQUAL(498, kf.GetInt(24));
|
||||
CHECK_EQUAL(false, kf.IsIncreasing(24));
|
||||
CHECK_EQUAL(3, kf.GetRepeatFraction(24).num);
|
||||
CHECK_EQUAL(6, kf.GetRepeatFraction(24).den);
|
||||
CHECK_EQUAL(0, kf.GetDelta(24));
|
||||
|
||||
CHECK_EQUAL(kf.GetLong(390), 100);
|
||||
CHECK_EQUAL(kf.IsIncreasing(390), true);
|
||||
CHECK_EQUAL(kf.GetRepeatFraction(390).num, 3);
|
||||
CHECK_EQUAL(kf.GetRepeatFraction(390).den, 15);
|
||||
CHECK_EQUAL(kf.GetDelta(390), 0);
|
||||
CHECK_EQUAL(100, kf.GetLong(390));
|
||||
CHECK_EQUAL(true, kf.IsIncreasing(390));
|
||||
CHECK_EQUAL(3, kf.GetRepeatFraction(390).num);
|
||||
CHECK_EQUAL(16, kf.GetRepeatFraction(390).den);
|
||||
CHECK_EQUAL(0, kf.GetDelta(390));
|
||||
|
||||
CHECK_EQUAL(kf.GetLong(391), 100);
|
||||
CHECK_EQUAL(kf.IsIncreasing(391), true);
|
||||
CHECK_EQUAL(kf.GetRepeatFraction(391).num, 4);
|
||||
CHECK_EQUAL(kf.GetRepeatFraction(391).den, 15);
|
||||
CHECK_EQUAL(kf.GetDelta(388), -1);
|
||||
CHECK_EQUAL(100, kf.GetLong(391));
|
||||
CHECK_EQUAL(true, kf.IsIncreasing(391));
|
||||
CHECK_EQUAL(4, kf.GetRepeatFraction(391).num);
|
||||
CHECK_EQUAL(16, kf.GetRepeatFraction(391).den);
|
||||
CHECK_EQUAL(-1, kf.GetDelta(388));
|
||||
}
|
||||
|
||||
|
||||
@@ -232,22 +232,22 @@ TEST(Keyframe_Get_Closest_Point)
|
||||
kf.AddPoint(2500, 0.0);
|
||||
|
||||
// Spot check values from the curve (to the right)
|
||||
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(900, 900)).co.X, 1000);
|
||||
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(1, 1)).co.X, 1);
|
||||
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(5, 5)).co.X, 1000);
|
||||
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(1000, 1000)).co.X, 1000);
|
||||
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(1001, 1001)).co.X, 2500);
|
||||
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(2500, 2500)).co.X, 2500);
|
||||
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(3000, 3000)).co.X, 2500);
|
||||
CHECK_EQUAL(1000, kf.GetClosestPoint(openshot::Point(900, 900)).co.X);
|
||||
CHECK_EQUAL(1, kf.GetClosestPoint(openshot::Point(1, 1)).co.X);
|
||||
CHECK_EQUAL(1000, kf.GetClosestPoint(openshot::Point(5, 5)).co.X);
|
||||
CHECK_EQUAL(1000, kf.GetClosestPoint(openshot::Point(1000, 1000)).co.X);
|
||||
CHECK_EQUAL(2500, kf.GetClosestPoint(openshot::Point(1001, 1001)).co.X);
|
||||
CHECK_EQUAL(2500, kf.GetClosestPoint(openshot::Point(2500, 2500)).co.X);
|
||||
CHECK_EQUAL(2500, kf.GetClosestPoint(openshot::Point(3000, 3000)).co.X);
|
||||
|
||||
// Spot check values from the curve (to the left)
|
||||
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(900, 900), true).co.X, 1);
|
||||
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(1, 1), true).co.X, 1);
|
||||
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(5, 5), true).co.X, 1);
|
||||
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(1000, 1000), true).co.X, 1);
|
||||
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(1001, 1001), true).co.X, 1000);
|
||||
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(2500, 2500), true).co.X, 1000);
|
||||
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(3000, 3000), true).co.X, 2500);
|
||||
CHECK_EQUAL(1, kf.GetClosestPoint(openshot::Point(900, 900), true).co.X);
|
||||
CHECK_EQUAL(1, kf.GetClosestPoint(openshot::Point(1, 1), true).co.X);
|
||||
CHECK_EQUAL(1, kf.GetClosestPoint(openshot::Point(5, 5), true).co.X);
|
||||
CHECK_EQUAL(1, kf.GetClosestPoint(openshot::Point(1000, 1000), true).co.X);
|
||||
CHECK_EQUAL(1000, kf.GetClosestPoint(openshot::Point(1001, 1001), true).co.X);
|
||||
CHECK_EQUAL(1000, kf.GetClosestPoint(openshot::Point(2500, 2500), true).co.X);
|
||||
CHECK_EQUAL(2500, kf.GetClosestPoint(openshot::Point(3000, 3000), true).co.X);
|
||||
}
|
||||
|
||||
|
||||
@@ -260,13 +260,13 @@ TEST(Keyframe_Get_Previous_Point)
|
||||
kf.AddPoint(2500, 0.0);
|
||||
|
||||
// Spot check values from the curve
|
||||
CHECK_EQUAL(kf.GetPreviousPoint(kf.GetClosestPoint(openshot::Point(900, 900))).co.X, 1);
|
||||
CHECK_EQUAL(kf.GetPreviousPoint(kf.GetClosestPoint(openshot::Point(1, 1))).co.X, 1);
|
||||
CHECK_EQUAL(kf.GetPreviousPoint(kf.GetClosestPoint(openshot::Point(5, 5))).co.X, 1);
|
||||
CHECK_EQUAL(kf.GetPreviousPoint(kf.GetClosestPoint(openshot::Point(1000, 1000))).co.X, 1);
|
||||
CHECK_EQUAL(kf.GetPreviousPoint(kf.GetClosestPoint(openshot::Point(1001, 1001))).co.X, 1000);
|
||||
CHECK_EQUAL(kf.GetPreviousPoint(kf.GetClosestPoint(openshot::Point(2500, 2500))).co.X, 1000);
|
||||
CHECK_EQUAL(kf.GetPreviousPoint(kf.GetClosestPoint(openshot::Point(3000, 3000))).co.X, 1000);
|
||||
CHECK_EQUAL(1, kf.GetPreviousPoint(kf.GetClosestPoint(openshot::Point(900, 900))).co.X);
|
||||
CHECK_EQUAL(1, kf.GetPreviousPoint(kf.GetClosestPoint(openshot::Point(1, 1))).co.X);
|
||||
CHECK_EQUAL(1, kf.GetPreviousPoint(kf.GetClosestPoint(openshot::Point(5, 5))).co.X);
|
||||
CHECK_EQUAL(1, kf.GetPreviousPoint(kf.GetClosestPoint(openshot::Point(1000, 1000))).co.X);
|
||||
CHECK_EQUAL(1000, kf.GetPreviousPoint(kf.GetClosestPoint(openshot::Point(1001, 1001))).co.X);
|
||||
CHECK_EQUAL(1000, kf.GetPreviousPoint(kf.GetClosestPoint(openshot::Point(2500, 2500))).co.X);
|
||||
CHECK_EQUAL(1000, kf.GetPreviousPoint(kf.GetClosestPoint(openshot::Point(3000, 3000))).co.X);
|
||||
|
||||
}
|
||||
|
||||
@@ -277,22 +277,22 @@ TEST(Keyframe_Get_Max_Point)
|
||||
kf.AddPoint(1, 1.0);
|
||||
|
||||
// Spot check values from the curve
|
||||
CHECK_EQUAL(kf.GetMaxPoint().co.Y, 1.0);
|
||||
CHECK_EQUAL(1.0, kf.GetMaxPoint().co.Y);
|
||||
|
||||
kf.AddPoint(2, 0.0);
|
||||
|
||||
// Spot check values from the curve
|
||||
CHECK_EQUAL(kf.GetMaxPoint().co.Y, 1.0);
|
||||
CHECK_EQUAL(1.0, kf.GetMaxPoint().co.Y);
|
||||
|
||||
kf.AddPoint(3, 2.0);
|
||||
|
||||
// Spot check values from the curve
|
||||
CHECK_EQUAL(kf.GetMaxPoint().co.Y, 2.0);
|
||||
CHECK_EQUAL(2.0, kf.GetMaxPoint().co.Y);
|
||||
|
||||
kf.AddPoint(4, 1.0);
|
||||
|
||||
// Spot check values from the curve
|
||||
CHECK_EQUAL(kf.GetMaxPoint().co.Y, 2.0);
|
||||
CHECK_EQUAL(2.0, kf.GetMaxPoint().co.Y);
|
||||
}
|
||||
|
||||
TEST(Keyframe_Scale_Keyframe)
|
||||
@@ -307,8 +307,8 @@ TEST(Keyframe_Scale_Keyframe)
|
||||
CHECK_CLOSE(1.0f, kf.GetValue(1), 0.01);
|
||||
CHECK_CLOSE(7.99f, kf.GetValue(24), 0.01);
|
||||
CHECK_CLOSE(8.0f, kf.GetValue(25), 0.01);
|
||||
CHECK_CLOSE(3.68f, kf.GetValue(40), 0.01);
|
||||
CHECK_CLOSE(2.0f, kf.GetValue(49), 0.01);
|
||||
CHECK_CLOSE(3.85f, kf.GetValue(40), 0.01);
|
||||
CHECK_CLOSE(2.01f, kf.GetValue(49), 0.01);
|
||||
CHECK_CLOSE(2.0f, kf.GetValue(50), 0.01);
|
||||
|
||||
// Resize / Scale the keyframe
|
||||
@@ -316,12 +316,12 @@ TEST(Keyframe_Scale_Keyframe)
|
||||
|
||||
// Spot check values from the curve
|
||||
CHECK_CLOSE(1.0f, kf.GetValue(1), 0.01);
|
||||
CHECK_CLOSE(4.21f, kf.GetValue(24), 0.01);
|
||||
CHECK_CLOSE(4.47f, kf.GetValue(25), 0.01);
|
||||
CHECK_CLOSE(7.57f, kf.GetValue(40), 0.01);
|
||||
CHECK_CLOSE(4.08f, kf.GetValue(24), 0.01);
|
||||
CHECK_CLOSE(4.36f, kf.GetValue(25), 0.01);
|
||||
CHECK_CLOSE(7.53f, kf.GetValue(40), 0.01);
|
||||
CHECK_CLOSE(7.99f, kf.GetValue(49), 0.01);
|
||||
CHECK_CLOSE(8.0f, kf.GetValue(50), 0.01);
|
||||
CHECK_CLOSE(2.35f, kf.GetValue(90), 0.01);
|
||||
CHECK_CLOSE(2.39f, kf.GetValue(90), 0.01);
|
||||
CHECK_CLOSE(2.0f, kf.GetValue(100), 0.01);
|
||||
|
||||
// Resize / Scale the keyframe
|
||||
@@ -331,8 +331,8 @@ TEST(Keyframe_Scale_Keyframe)
|
||||
CHECK_CLOSE(1.0f, kf.GetValue(1), 0.01);
|
||||
CHECK_CLOSE(7.99f, kf.GetValue(24), 0.01);
|
||||
CHECK_CLOSE(8.0f, kf.GetValue(25), 0.01);
|
||||
CHECK_CLOSE(3.68f, kf.GetValue(40), 0.01);
|
||||
CHECK_CLOSE(2.0f, kf.GetValue(49), 0.01);
|
||||
CHECK_CLOSE(3.85f, kf.GetValue(40), 0.01);
|
||||
CHECK_CLOSE(2.01f, kf.GetValue(49), 0.01);
|
||||
CHECK_CLOSE(2.0f, kf.GetValue(50), 0.01);
|
||||
|
||||
}
|
||||
@@ -380,14 +380,14 @@ TEST(Keyframe_Remove_Duplicate_Point)
|
||||
kf.AddPoint(1, 2.0);
|
||||
|
||||
// Spot check values from the curve
|
||||
CHECK_EQUAL(kf.GetLength(), 1);
|
||||
CHECK_CLOSE(kf.GetPoint(0).co.Y, 2.0, 0.01);
|
||||
CHECK_EQUAL(1, kf.GetLength());
|
||||
CHECK_CLOSE(2.0, kf.GetPoint(0).co.Y, 0.01);
|
||||
}
|
||||
|
||||
TEST(Keyframe_Large_Number_Values)
|
||||
{
|
||||
// Large value
|
||||
int64_t large_value = 30 * 60 * 90;
|
||||
int64_t const large_value = 30 * 60 * 90;
|
||||
|
||||
// Create a keyframe curve with 2 points
|
||||
Keyframe kf;
|
||||
@@ -395,7 +395,102 @@ TEST(Keyframe_Large_Number_Values)
|
||||
kf.AddPoint(large_value, 100.0); // 90 minutes long
|
||||
|
||||
// Spot check values from the curve
|
||||
CHECK_EQUAL(kf.GetLength(), large_value + 1);
|
||||
CHECK_CLOSE(kf.GetPoint(0).co.Y, 1.0, 0.01);
|
||||
CHECK_CLOSE(kf.GetPoint(1).co.Y, 100.0, 0.01);
|
||||
CHECK_EQUAL(large_value + 1, kf.GetLength());
|
||||
CHECK_CLOSE(1.0, kf.GetPoint(0).co.Y, 0.01);
|
||||
CHECK_CLOSE(100.0, kf.GetPoint(1).co.Y, 0.01);
|
||||
}
|
||||
|
||||
TEST(Keyframe_Remove_Point)
|
||||
{
|
||||
Keyframe kf;
|
||||
kf.AddPoint(openshot::Point(Coordinate(1, 1), CONSTANT));
|
||||
kf.AddPoint(openshot::Point(Coordinate(3, 100), CONSTANT));
|
||||
CHECK_EQUAL(1, kf.GetInt(2));
|
||||
kf.AddPoint(openshot::Point(Coordinate(2, 50), CONSTANT));
|
||||
CHECK_EQUAL(50, kf.GetInt(2));
|
||||
kf.RemovePoint(1); // This is the index of point with X == 2
|
||||
CHECK_EQUAL(1, kf.GetInt(2));
|
||||
CHECK_THROW(kf.RemovePoint(100), OutOfBoundsPoint);
|
||||
}
|
||||
|
||||
TEST(Keyframe_Constant_Interpolation_First_Segment)
|
||||
{
|
||||
Keyframe kf;
|
||||
kf.AddPoint(Point(Coordinate(1, 1), CONSTANT));
|
||||
kf.AddPoint(Point(Coordinate(2, 50), CONSTANT));
|
||||
kf.AddPoint(Point(Coordinate(3, 100), CONSTANT));
|
||||
CHECK_EQUAL(1, kf.GetInt(0));
|
||||
CHECK_EQUAL(1, kf.GetInt(1));
|
||||
CHECK_EQUAL(50, kf.GetInt(2));
|
||||
CHECK_EQUAL(100, kf.GetInt(3));
|
||||
CHECK_EQUAL(100, kf.GetInt(4));
|
||||
}
|
||||
|
||||
TEST(Keyframe_isIncreasing)
|
||||
{
|
||||
// Which cases need to be tested to keep same behaviour as
|
||||
// previously?
|
||||
//
|
||||
// - "invalid point" => true
|
||||
// - point where all next values are equal => false
|
||||
// - point where first non-eq next value is smaller => false
|
||||
// - point where first non-eq next value is larger => true
|
||||
Keyframe kf;
|
||||
kf.AddPoint(1, 1, LINEAR); // testing with linear
|
||||
kf.AddPoint(3, 5, BEZIER); // testing with bezier
|
||||
kf.AddPoint(6, 10, CONSTANT); // first non-eq is smaller
|
||||
kf.AddPoint(8, 8, CONSTANT); // first non-eq is larger
|
||||
kf.AddPoint(10, 10, CONSTANT); // all next values are equal
|
||||
kf.AddPoint(15, 10, CONSTANT);
|
||||
|
||||
// "invalid points"
|
||||
CHECK_EQUAL(true, kf.IsIncreasing(0));
|
||||
CHECK_EQUAL(true, kf.IsIncreasing(15));
|
||||
// all next equal
|
||||
CHECK_EQUAL(false, kf.IsIncreasing(12));
|
||||
// first non-eq is larger
|
||||
CHECK_EQUAL(true, kf.IsIncreasing(8));
|
||||
// first non-eq is smaller
|
||||
CHECK_EQUAL(false, kf.IsIncreasing(6));
|
||||
// bezier and linear
|
||||
CHECK_EQUAL(true, kf.IsIncreasing(4));
|
||||
CHECK_EQUAL(true, kf.IsIncreasing(2));
|
||||
}
|
||||
|
||||
TEST(Keyframe_GetLength)
|
||||
{
|
||||
Keyframe f;
|
||||
CHECK_EQUAL(0, f.GetLength());
|
||||
f.AddPoint(1, 1);
|
||||
CHECK_EQUAL(1, f.GetLength());
|
||||
f.AddPoint(2, 1);
|
||||
CHECK_EQUAL(3, f.GetLength());
|
||||
f.AddPoint(200, 1);
|
||||
CHECK_EQUAL(201, f.GetLength());
|
||||
|
||||
Keyframe g;
|
||||
g.AddPoint(200, 1);
|
||||
CHECK_EQUAL(1, g.GetLength());
|
||||
g.AddPoint(1,1);
|
||||
CHECK_EQUAL(201, g.GetLength());
|
||||
}
|
||||
|
||||
TEST(Keyframe_Use_Interpolation_of_Segment_End_Point)
|
||||
{
|
||||
Keyframe f;
|
||||
f.AddPoint(1,0, CONSTANT);
|
||||
f.AddPoint(100,155, BEZIER);
|
||||
CHECK_CLOSE(75.9, f.GetValue(50), 0.1);
|
||||
}
|
||||
|
||||
TEST(Keyframe_Handle_Large_Segment)
|
||||
{
|
||||
Keyframe kf;
|
||||
kf.AddPoint(1, 0, CONSTANT);
|
||||
kf.AddPoint(1000000, 1, LINEAR);
|
||||
UNITTEST_TIME_CONSTRAINT(10); // 10 milliseconds would still be relatively slow, but need to think about slower build machines!
|
||||
CHECK_CLOSE(0.5, kf.GetValue(500000), 0.01);
|
||||
CHECK_EQUAL(true, kf.IsIncreasing(10));
|
||||
Fraction fr = kf.GetRepeatFraction(250000);
|
||||
CHECK_CLOSE(0.5, (double)fr.num / fr.den, 0.01);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user