diff --git a/bindings/python/openshot.i b/bindings/python/openshot.i index 7197f7dd..a129280d 100644 --- a/bindings/python/openshot.i +++ b/bindings/python/openshot.i @@ -127,12 +127,19 @@ /* Instantiate the required template specializations */ %template() std::map; +%template() std::pair; +%template() std::vector; +%template() std::pair; +%template() std::pair; /* Make openshot.Fraction more Pythonic */ %extend openshot::Fraction { %{ #include #include + + static std::vector _keys{"num", "den"}; + static int fracError = 0; %} double __float__() { return $self->ToDouble(); @@ -140,17 +147,70 @@ int __int__() { return $self->ToInt(); } + /* Dictionary-type methods */ + int __len__() { + return _keys.size(); + } + %exception __getitem__ { + $action + if (fracError == 1) { + fracError = 0; // Clear flag for reuse + PyErr_SetString(PyExc_KeyError, "Key not found"); + SWIG_fail; + } + } + const std::string __getitem__(int index) { + if (index < _keys.size()) { + return _keys[index]; + } + /* Otherwise, raise an exception */ + fracError = 1; + return ""; + } + int __getitem__(const std::string& key) { + if (key == "num") { + return $self->num; + } else if (key == "den") { + return $self->den; + } + /* Otherwise, raise an exception */ + fracError = 1; + return 0; + } + bool __contains__(const std::string& key) { + return bool(std::find(_keys.begin(), _keys.end(), key) != _keys.end()); + } std::map GetMap() { std::map map1; map1.insert({"num", $self->num}); map1.insert({"den", $self->den}); return map1; } - std::string __repr__() { + /* Display methods */ + const std::string __string__() { std::ostringstream result; result << $self->num << ":" << $self->den; return result.str(); + } + const std::string __repr__() { + std::ostringstream result; + result << "Fraction(" << $self->num << ", " << $self->den << ")"; + return result.str(); } + /* Implement dict methods in Python */ + %pythoncode %{ + def __iter__(self): + return iter(self.GetMap()) + def keys(self): + _items = self.GetMap() + return _items.keys() + def items(self): + _items = self.GetMap() + return _items.items() + def values(self): + _items = self.GetMap() + return _items.values() + %} } %extend openshot::OpenShotVersion { diff --git a/bindings/ruby/openshot.i b/bindings/ruby/openshot.i index fe47f1bc..3e64af26 100644 --- a/bindings/ruby/openshot.i +++ b/bindings/ruby/openshot.i @@ -57,6 +57,13 @@ %shared_ptr(juce::AudioSampleBuffer) %shared_ptr(openshot::Frame) +/* Template specializations */ +%template() std::map; +%template() std::pair; +%template() std::vector; +%template() std::pair; +%template() std::pair; + %{ /* Ruby and FFmpeg define competing RSHIFT macros, * so we move Ruby's out of the way for now. We'll diff --git a/src/Clip.h b/src/Clip.h index aae93c27..e8b75c79 100644 --- a/src/Clip.h +++ b/src/Clip.h @@ -41,7 +41,6 @@ #include "EffectBase.h" #include "Effects.h" #include "EffectInfo.h" -#include "Fraction.h" #include "Frame.h" #include "KeyFrame.h" #include "ReaderBase.h" diff --git a/src/Coordinate.cpp b/src/Coordinate.cpp index 1aae2c01..6a4abb21 100644 --- a/src/Coordinate.cpp +++ b/src/Coordinate.cpp @@ -31,19 +31,17 @@ #include "Coordinate.h" #include "Exceptions.h" -using namespace std; using namespace openshot; -// Default constructor for a coordinate, which defaults the X and Y to zero (0,0) -Coordinate::Coordinate() : - X(0), Y(0) { -} +// Default constructor for a coordinate, delegating to the full signature +Coordinate::Coordinate() : Coordinate::Coordinate(0, 0) {}; // Constructor which also allows the user to set the X and Y -Coordinate::Coordinate(double x, double y) : - X(x), Y(y) { -} +Coordinate::Coordinate(double x, double y) : X(x), Y(y) {}; +// Constructor which accepts a std::pair for (X, Y) +Coordinate::Coordinate(const std::pair& co) + : X(co.first), Y(co.second) {}; // Generate JSON string of this object std::string Coordinate::Json() const { diff --git a/src/Coordinate.h b/src/Coordinate.h index 9437d8e4..35fa966a 100644 --- a/src/Coordinate.h +++ b/src/Coordinate.h @@ -64,6 +64,10 @@ namespace openshot { /// @param y The Y coordinate (usually representing the value of the property being animated) Coordinate(double x, double y); + /// @brief Constructor which accepts a std::pair tuple for {X, Y} + /// @param co A std::pair tuple containing (X, Y) + Coordinate(const std::pair& co); + /// Get and Set JSON methods std::string Json() const; ///< Generate JSON string of this object Json::Value JsonValue() const; ///< Generate Json::Value for this object diff --git a/src/Fraction.cpp b/src/Fraction.cpp index 869ef35f..86671e11 100644 --- a/src/Fraction.cpp +++ b/src/Fraction.cpp @@ -29,13 +29,23 @@ */ #include "Fraction.h" +#include using namespace openshot; -// Constructor -Fraction::Fraction() : - num(1), den(1) { -} +// Delegating constructors +Fraction::Fraction() : Fraction::Fraction(1, 1) {}; + +Fraction::Fraction(std::pair pair) + : Fraction::Fraction(pair.first, pair.second) {}; + +Fraction::Fraction(std::map mapping) + : Fraction::Fraction(mapping["num"], mapping["den"]) {}; + +Fraction::Fraction(std::vector vector) + : Fraction::Fraction(vector[0], vector[1]) {}; + +// Full constructor Fraction::Fraction(int num, int den) : num(num), den(den) { } diff --git a/src/Fraction.h b/src/Fraction.h index 88c16fbc..ffb0640b 100644 --- a/src/Fraction.h +++ b/src/Fraction.h @@ -31,7 +31,10 @@ #ifndef OPENSHOT_FRACTION_H #define OPENSHOT_FRACTION_H -#include +#include // for std::string +#include // for std::pair +#include // for std::map +#include // for std::vector namespace openshot { @@ -49,9 +52,19 @@ namespace openshot { /// Default Constructor Fraction(); + /// Constructor with numerator and denominator Fraction(int num, int den); + /// Constructor that accepts a (num, den) pair + Fraction(std::pair pair); + + /// Constructor that takes a vector of length 2 (containing {num, den}) + Fraction(std::vector vector); + + /// Constructor that takes a key-value mapping (keys: 'num'. 'den') + Fraction(std::map mapping); + /// Calculate the greatest common denominator int GreatestCommonDenominator(); diff --git a/src/ImageWriter.h b/src/ImageWriter.h index 89754187..be12e5d1 100644 --- a/src/ImageWriter.h +++ b/src/ImageWriter.h @@ -43,12 +43,11 @@ #include "ReaderBase.h" #include "WriterBase.h" -#include -#include -#include -#include -#include +#include +#include #include "CacheMemory.h" +#include "Exceptions.h" +#include "Fraction.h" #include "OpenMPUtilities.h" #include "MagickUtilities.h" diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp index 96c8dca9..eaafcb1f 100644 --- a/src/KeyFrame.cpp +++ b/src/KeyFrame.cpp @@ -30,6 +30,10 @@ #include "KeyFrame.h" #include "Exceptions.h" + +#include // For assert() +#include // For std::cout +#include // For std::setprecision #include #include #include @@ -121,6 +125,16 @@ Keyframe::Keyframe(double value) { AddPoint(Point(value)); } +// Constructor which takes a vector of Points +Keyframe::Keyframe(const std::vector& points) : Points(points) {}; + +// Constructor which takes a vector of std::pair tuples (and adds them all) +Keyframe::Keyframe(const std::vector& coordinates) { + for (const auto& co : coordinates) { + AddPoint(Point(co)); + } +} + // Add a new point on the key-frame. Each point has a primary coordinate, // a left handle, and a right handle. void Keyframe::AddPoint(Point p) { @@ -147,17 +161,7 @@ void Keyframe::AddPoint(Point p) { } } -// Add a new point on the key-frame, with some defaults set (BEZIER) -void Keyframe::AddPoint(double x, double y) -{ - // Create a point - Point new_point(x, y, BEZIER); - - // Add the point - AddPoint(new_point); -} - -// Add a new point on the key-frame, with a specific interpolation type +// Add a new point on the key-frame, interpolate is optional (default: BEZIER) void Keyframe::AddPoint(double x, double y, InterpolationType interpolate) { // Create a point diff --git a/src/KeyFrame.h b/src/KeyFrame.h index f19165a2..7e912f6c 100644 --- a/src/KeyFrame.h +++ b/src/KeyFrame.h @@ -31,14 +31,10 @@ #ifndef OPENSHOT_KEYFRAME_H #define OPENSHOT_KEYFRAME_H -#include -#include #include -#include #include #include "Fraction.h" -#include "Coordinate.h" #include "Point.h" #include "Json.h" @@ -66,6 +62,8 @@ namespace openshot { std::vector Points; ///< Vector of all Points public: + using CoordinateVector = std::vector; + using PointsVector = std::vector; /// Default constructor for the Keyframe class Keyframe() = default; @@ -73,14 +71,17 @@ namespace openshot { /// Constructor which sets the default point & coordinate at X=1 Keyframe(double value); + /// Constructor which adds a supplied vector of Points + Keyframe(const PointsVector& points); + + /// Constructor which takes a vector of std::pair tuples + Keyframe(const CoordinateVector& coordinates); + /// Add a new point on the key-frame. Each point has a primary coordinate, a left handle, and a right handle. void AddPoint(Point p); - /// Add a new point on the key-frame, with some defaults set (BEZIER) - void AddPoint(double x, double y); - - /// Add a new point on the key-frame, with a specific interpolation type - void AddPoint(double x, double y, InterpolationType interpolate); + /// Add a new point on the key-frame, with optional interpolation type + void AddPoint(double x, double y, InterpolationType interpolate=BEZIER); /// Does this keyframe contain a specific point bool Contains(Point p) const; diff --git a/src/Point.cpp b/src/Point.cpp index 0e62d3b4..44b6883f 100644 --- a/src/Point.cpp +++ b/src/Point.cpp @@ -34,58 +34,27 @@ using namespace std; using namespace openshot; -// Default constructor (defaults to 1,0) -Point::Point() : interpolation(BEZIER), handle_type(AUTO) -{ - // set new coorinate - co = Coordinate(1, 0); - - // set handles - Initialize_Handles(); -} +// Default constructor +Point::Point() : Point::Point(Coordinate(1, 0), BEZIER, AUTO) {}; // Constructor which creates a single coordinate at X=1 -Point::Point(float y) : - interpolation(CONSTANT), handle_type(AUTO) { - // set new coorinate - co = Coordinate(1, y); +Point::Point(float y) : Point::Point(Coordinate(1, y), CONSTANT, AUTO) {}; - // set handles - Initialize_Handles(); -} +// Constructor which creates a Bezier curve with point at (x, y) +Point::Point(float x, float y) : Point::Point(Coordinate(x, y), BEZIER, AUTO) {}; -Point::Point(float x, float y) : - interpolation(BEZIER), handle_type(AUTO) { - // set new coorinate - co = Coordinate(x, y); +// Constructor which also creates a Point, setting X,Y, and interpolation. +Point::Point(float x, float y, InterpolationType interpolation) + : Point::Point(Coordinate(x, y), interpolation, AUTO) {}; - // set handles - Initialize_Handles(); -} -// Constructor which also creates a Point and sets the X,Y, and interpolation of the Point. -Point::Point(float x, float y, InterpolationType interpolation) : - handle_type(AUTO), interpolation(interpolation) { - // set new coorinate - co = Coordinate(x, y); +// Direct Coordinate-accepting constructors +Point::Point(const Coordinate& co) : Point::Point(co, BEZIER, AUTO) {}; - // set handles - Initialize_Handles(); -} +Point::Point(const Coordinate& co, InterpolationType interpolation) + : Point::Point(co, interpolation, AUTO) {}; -Point::Point(Coordinate co) : - co(co), interpolation(BEZIER), handle_type(AUTO) { - // set handles - Initialize_Handles(); -} - -Point::Point(Coordinate co, InterpolationType interpolation) : - co(co), interpolation(interpolation), handle_type(AUTO) { - // set handles - Initialize_Handles(); -} - -Point::Point(Coordinate co, InterpolationType interpolation, HandleType handle_type) : +Point::Point(const Coordinate& co, InterpolationType interpolation, HandleType handle_type) : co(co), interpolation(interpolation), handle_type(handle_type) { // set handles Initialize_Handles(); diff --git a/src/Point.h b/src/Point.h index 8b966416..8df34aa9 100644 --- a/src/Point.h +++ b/src/Point.h @@ -100,13 +100,13 @@ namespace openshot Point(float x, float y, InterpolationType interpolation); /// Constructor which takes a coordinate - Point(Coordinate co); + Point(const Coordinate& co); /// Constructor which takes a coordinate and interpolation mode - Point(Coordinate co, InterpolationType interpolation); + Point(const Coordinate& co, InterpolationType interpolation); /// Constructor which takes a coordinate, interpolation mode, and handle type - Point(Coordinate co, InterpolationType interpolation, HandleType handle_type); + Point(const Coordinate& co, InterpolationType interpolation, HandleType handle_type); /// Set the left and right handles to a percent of the primary coordinate (0 to 1) /// Defaults to a smooth curve (Ease in and out) diff --git a/src/effects/Caption.cpp b/src/effects/Caption.cpp index 6452613f..73c53cc2 100644 --- a/src/effects/Caption.cpp +++ b/src/effects/Caption.cpp @@ -33,6 +33,12 @@ #include "../Clip.h" #include "../Timeline.h" +#include +#include +#include +#include +#include + using namespace openshot; /// Blank constructor, useful when using Json to load the effect properties diff --git a/src/effects/Caption.h b/src/effects/Caption.h index 9678d520..61897740 100644 --- a/src/effects/Caption.h +++ b/src/effects/Caption.h @@ -31,13 +31,14 @@ #ifndef OPENSHOT_CAPTION_EFFECT_H #define OPENSHOT_CAPTION_EFFECT_H -#include -#include #include -#include +#include +#include +#include +#include +#include #include "../Color.h" #include "../EffectBase.h" -#include "../Fraction.h" #include "../Json.h" #include "../KeyFrame.h" @@ -46,87 +47,87 @@ namespace openshot { - /** - * @brief This class adds captions/text over a video, based on timestamps. You can also animate some limited - * aspects, such as words appearing/disappearing. - * - * Adding captions can be an easy way to generate text overlays through-out a long clip. - */ - class Caption : public EffectBase - { - private: - std::vector matchedCaptions; ///< RegEx to capture cues and text - std::string caption_text; ///< Text of caption - QFontMetrics* metrics; ///< Font metrics object - QFont* font; ///< QFont object - bool is_dirty; +/** + * @brief This class adds captions/text over a video, based on timestamps. You can also animate some limited + * aspects, such as words appearing/disappearing. + * + * Adding captions can be an easy way to generate text overlays through-out a long clip. + */ +class Caption : public EffectBase +{ +private: + std::vector matchedCaptions; ///< RegEx to capture cues and text + std::string caption_text; ///< Text of caption + QFontMetrics* metrics; ///< Font metrics object + QFont* font; ///< QFont object + bool is_dirty; - /// Init effect settings - void init_effect_details(); + /// Init effect settings + void init_effect_details(); - /// Process regex capture - void process_regex(); + /// Process regex capture + void process_regex(); - public: - Color color; ///< Color of caption text - Color stroke; ///< Color of text border / stroke - Color background; ///< Color of caption area background - Keyframe background_alpha; ///< Background color alpha - Keyframe background_corner; ///< Background cornder radius - Keyframe background_padding; ///< Background padding - Keyframe stroke_width; ///< Width of text border / stroke - Keyframe font_size; ///< Font size in points - Keyframe font_alpha; ///< Font color alpha - Keyframe left; ///< Size of left bar - Keyframe top; ///< Size of top bar - Keyframe right; ///< Size of right bar - Keyframe fade_in; ///< Fade in per caption (# of seconds) - Keyframe fade_out; ///< Fade in per caption (# of seconds) - std::string font_name; ///< Font string +public: + Color color; ///< Color of caption text + Color stroke; ///< Color of text border / stroke + Color background; ///< Color of caption area background + Keyframe background_alpha; ///< Background color alpha + Keyframe background_corner; ///< Background cornder radius + Keyframe background_padding; ///< Background padding + Keyframe stroke_width; ///< Width of text border / stroke + Keyframe font_size; ///< Font size in points + Keyframe font_alpha; ///< Font color alpha + Keyframe left; ///< Size of left bar + Keyframe top; ///< Size of top bar + Keyframe right; ///< Size of right bar + Keyframe fade_in; ///< Fade in per caption (# of seconds) + Keyframe fade_out; ///< Fade in per caption (# of seconds) + std::string font_name; ///< Font string - /// Blank constructor, useful when using Json to load the effect properties - Caption(); + /// Blank constructor, useful when using Json to load the effect properties + Caption(); - /// Default constructor, which takes a string of VTT/Subrip formatted caption data, and displays them over time. - /// - /// @param captions A string with VTT/Subrip format text captions - Caption(std::string captions); + /// Default constructor, which takes a string of VTT/Subrip formatted caption data, and displays them over time. + /// + /// @param captions A string with VTT/Subrip format text captions + Caption(std::string captions); - /// @brief This method is required for all derived classes of ClipBase, and returns a - /// new openshot::Frame object. All Clip keyframes and effects are resolved into - /// pixels. - /// - /// @returns A new openshot::Frame object - /// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline. - std::shared_ptr GetFrame(int64_t frame_number) override { return GetFrame(std::make_shared(), frame_number); } + /// @brief This method is required for all derived classes of ClipBase, and returns a + /// new openshot::Frame object. All Clip keyframes and effects are resolved into + /// pixels. + /// + /// @returns A new openshot::Frame object + /// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline. + std::shared_ptr GetFrame(int64_t frame_number) override { return GetFrame(std::make_shared(), frame_number); } - /// @brief This method is required for all derived classes of ClipBase, and returns a - /// modified openshot::Frame object - /// - /// The frame object is passed into this method and used as a starting point (pixels and audio). - /// All Clip keyframes and effects are resolved into pixels. - /// - /// @returns The modified openshot::Frame object - /// @param frame The frame object that needs the clip or effect applied to it - /// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; + /// @brief This method is required for all derived classes of ClipBase, and returns a + /// modified openshot::Frame object + /// + /// The frame object is passed into this method and used as a starting point (pixels and audio). + /// All Clip keyframes and effects are resolved into pixels. + /// + /// @returns The modified openshot::Frame object + /// @param frame The frame object that needs the clip or effect applied to it + /// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline. + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; - // Get and Set caption data - std::string CaptionText(); ///< Set the caption string to use (see VTT format) - void CaptionText(std::string new_caption_text); ///< Get the caption string + // Get and Set caption data + std::string CaptionText(); ///< Set the caption string to use (see VTT format) + void CaptionText(std::string new_caption_text); ///< Get the caption string - /// Get and Set JSON methods - std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value) override; ///< Load JSON string into this object - Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object + /// Get and Set JSON methods + std::string Json() const override; ///< Generate JSON string of this object + void SetJson(const std::string value) override; ///< Load JSON string into this object + Json::Value JsonValue() const override; ///< Generate Json::Value for this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object - /// Get all properties for a specific frame (perfect for a UI to display the current state - /// of all properties at any time) - std::string PropertiesJSON(int64_t requested_frame) const override; - }; + /// Get all properties for a specific frame (perfect for a UI to display the current state + /// of all properties at any time) + std::string PropertiesJSON(int64_t requested_frame) const override; +}; -} +} // namespace openshot -#endif +#endif // OPENSHOT_CAPTION_EFFECT_H diff --git a/tests/Coordinate_Tests.cpp b/tests/Coordinate_Tests.cpp index 0ed4a46a..7dd5886c 100644 --- a/tests/Coordinate_Tests.cpp +++ b/tests/Coordinate_Tests.cpp @@ -32,10 +32,14 @@ // Prevent name clashes with juce::UnitTest #define DONT_SET_USING_JUCE_NAMESPACE 1 #include "Coordinate.h" +#include "Exceptions.h" using namespace openshot; -TEST(Coordinate_Default_Constructor) +SUITE(Coordinate) +{ + +TEST(Default_Constructor) { // Create an empty coordinate Coordinate c1; @@ -44,7 +48,7 @@ TEST(Coordinate_Default_Constructor) CHECK_CLOSE(0.0f, c1.Y, 0.00001); } -TEST(Coordinate_X_Y_Constructor) +TEST(X_Y_Constructor) { // Create an empty coordinate Coordinate c1(2,8); @@ -52,3 +56,44 @@ TEST(Coordinate_X_Y_Constructor) CHECK_CLOSE(2.0f, c1.X, 0.00001); CHECK_CLOSE(8.0f, c1.Y, 0.00001); } + +TEST(Pair_Constructor) +{ + Coordinate c1(std::pair(12, 10)); + CHECK_CLOSE(12.0f, c1.X, 0.00001); + CHECK_CLOSE(10.0f, c1.Y, 0.00001); +} + +TEST(Json) +{ + openshot::Coordinate c(100, 200); + openshot::Coordinate c1; + c1.X = 100; + c1.Y = 200; + // Check that JSON produced is identical + auto j = c.Json(); + auto j1 = c1.Json(); + CHECK_EQUAL(j, j1); + // Check Json::Value representation + auto jv = c.JsonValue(); + auto jv_string = jv.toStyledString(); + CHECK_EQUAL(jv_string, j1); +} + +TEST(SetJson) { + // Construct our input Json representation + const std::string json_input = R"json( + { + "X": 100.0, + "Y": 50.0 + } + )json"; + openshot::Coordinate c; + CHECK_THROW(c.SetJson("}{"), openshot::InvalidJSON); + // Check that values set via SetJson() are correct + c.SetJson(json_input); + CHECK_CLOSE(100.0, c.X, 0.01); + CHECK_CLOSE(50.0, c.Y, 0.01); +} + +} // SUITE diff --git a/tests/Fraction_Tests.cpp b/tests/Fraction_Tests.cpp index d2ef24ad..760a8380 100644 --- a/tests/Fraction_Tests.cpp +++ b/tests/Fraction_Tests.cpp @@ -36,7 +36,10 @@ using namespace std; using namespace openshot; -TEST(Fraction_Default_Constructor) +SUITE(Fraction) +{ + +TEST(Constructors) { // Create a default fraction (should be 1/1) Fraction f1; @@ -57,7 +60,31 @@ TEST(Fraction_Default_Constructor) CHECK_CLOSE(1.0f, f1.ToDouble(), 0.00001); } -TEST(Fraction_640_480) +TEST(Alt_Constructors) +{ + // Use the delegating constructor for std::pair + std::pair args{24, 1}; + Fraction f1(args); + CHECK_EQUAL(24, f1.num); + CHECK_EQUAL(1, f1.den); + CHECK_CLOSE(24.0f, f1.ToFloat(), 0.00001); + + // Use the delegating constructor for std::vector + std::vector v{30000, 1001}; + Fraction f2(v); + CHECK_CLOSE(30000.0/1001.0, f2.ToFloat(), 0.00001); + + // Use the delegating constructor for std::map + std::map dict; + dict.insert({"num", 24000}); + dict.insert({"den", 1001}); + Fraction f3(dict); + CHECK_EQUAL(1001, f3.den); + CHECK_EQUAL(24000, f3.num); + CHECK_CLOSE(1001.0/24000.0, f3.Reciprocal().ToFloat(), 0.00001); +} + +TEST(WxH_640_480) { // Create fraction Fraction f1(640, 480); @@ -78,7 +105,7 @@ TEST(Fraction_640_480) CHECK_CLOSE(1.33333f, f1.ToDouble(), 0.00001); } -TEST(Fraction_1280_720) +TEST(WxH_1280_720) { // Create fraction Fraction f1(1280, 720); @@ -99,7 +126,7 @@ TEST(Fraction_1280_720) CHECK_CLOSE(1.77777f, f1.ToDouble(), 0.00001); } -TEST(Fraction_reciprocal) +TEST(Reciprocal) { // Create fraction Fraction f1(1280, 720); @@ -125,3 +152,5 @@ TEST(Fraction_reciprocal) CHECK_CLOSE(1.77777f, f1.ToFloat(), 0.00001); CHECK_CLOSE(1.77777f, f1.ToDouble(), 0.00001); } + +} // SUITE diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index 0ffa3f98..e3a1d06a 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -40,7 +40,9 @@ using namespace std; using namespace openshot; -TEST(Keyframe_GetPoint_With_No_Points) +SUITE(Keyframe) { + +TEST(GetPoint_With_No_Points) { // Create an empty keyframe Keyframe k1; @@ -48,7 +50,7 @@ TEST(Keyframe_GetPoint_With_No_Points) CHECK_THROW(k1.GetPoint(0), OutOfBoundsPoint); } -TEST(Keyframe_GetPoint_With_1_Points) +TEST(GetPoint_With_1_Points) { // Create an empty keyframe Keyframe k1; @@ -62,7 +64,7 @@ TEST(Keyframe_GetPoint_With_1_Points) } -TEST(Keyframe_AddPoint_With_1_Point) +TEST(AddPoint_With_1_Point) { // Create an empty keyframe Keyframe k1; @@ -73,7 +75,7 @@ TEST(Keyframe_AddPoint_With_1_Point) CHECK_THROW(k1.GetPoint(1), OutOfBoundsPoint); } -TEST(Keyframe_AddPoint_With_2_Points) +TEST(AddPoint_With_2_Points) { // Create an empty keyframe Keyframe k1; @@ -86,7 +88,7 @@ TEST(Keyframe_AddPoint_With_2_Points) CHECK_THROW(k1.GetPoint(2), OutOfBoundsPoint); } -TEST(Keyframe_GetValue_For_Bezier_Curve_2_Points) +TEST(GetValue_For_Bezier_Curve_2_Points) { // Create a keyframe curve with 2 points Keyframe kf; @@ -105,7 +107,7 @@ TEST(Keyframe_GetValue_For_Bezier_Curve_2_Points) CHECK_EQUAL(51, kf.GetLength()); } -TEST(Keyframe_GetValue_For_Bezier_Curve_5_Points_40_Percent_Handle) +TEST(GetValue_For_Bezier_Curve_5_Points_40_Percent_Handle) { // Create a keyframe curve with 2 points Keyframe kf; @@ -128,7 +130,7 @@ TEST(Keyframe_GetValue_For_Bezier_Curve_5_Points_40_Percent_Handle) CHECK_EQUAL(201, kf.GetLength()); } -TEST(Keyframe_GetValue_For_Bezier_Curve_5_Points_25_Percent_Handle) +TEST(GetValue_For_Bezier_Curve_5_Points_25_Percent_Handle) { // Create a keyframe curve with 2 points Keyframe kf; @@ -151,7 +153,7 @@ TEST(Keyframe_GetValue_For_Bezier_Curve_5_Points_25_Percent_Handle) CHECK_EQUAL(201, kf.GetLength()); } -TEST(Keyframe_GetValue_For_Linear_Curve_3_Points) +TEST(GetValue_For_Linear_Curve_3_Points) { // Create a keyframe curve with 2 points Keyframe kf; @@ -171,7 +173,7 @@ TEST(Keyframe_GetValue_For_Linear_Curve_3_Points) CHECK_EQUAL(51, kf.GetLength()); } -TEST(Keyframe_GetValue_For_Constant_Curve_3_Points) +TEST(GetValue_For_Constant_Curve_3_Points) { // Create a keyframe curve with 2 points Keyframe kf; @@ -192,7 +194,7 @@ TEST(Keyframe_GetValue_For_Constant_Curve_3_Points) CHECK_EQUAL(51, kf.GetLength()); } -TEST(Keyframe_Check_Direction_and_Repeat_Fractions) +TEST(Check_Direction_and_Repeat_Fractions) { // Create a keyframe curve with 2 points Keyframe kf; @@ -227,7 +229,7 @@ TEST(Keyframe_Check_Direction_and_Repeat_Fractions) } -TEST(Keyframe_Get_Closest_Point) +TEST(Get_Closest_Point) { // Create a keyframe curve with 2 points Keyframe kf; @@ -255,7 +257,7 @@ TEST(Keyframe_Get_Closest_Point) } -TEST(Keyframe_Get_Previous_Point) +TEST(Get_Previous_Point) { // Create a keyframe curve with 2 points Keyframe kf; @@ -274,7 +276,7 @@ TEST(Keyframe_Get_Previous_Point) } -TEST(Keyframe_Get_Max_Point) +TEST(Get_Max_Point) { // Create a keyframe curve Keyframe kf; @@ -299,7 +301,7 @@ TEST(Keyframe_Get_Max_Point) CHECK_EQUAL(2.0, kf.GetMaxPoint().co.Y); } -TEST(Keyframe_Scale_Keyframe) +TEST(Scale_Keyframe) { // Create a keyframe curve with 2 points Keyframe kf; @@ -341,7 +343,7 @@ TEST(Keyframe_Scale_Keyframe) } -TEST(Keyframe_Flip_Keyframe) +TEST(Flip_Keyframe) { // Create a keyframe curve with 2 points Keyframe kf; @@ -375,7 +377,7 @@ TEST(Keyframe_Flip_Keyframe) CHECK_CLOSE(10.0f, kf.GetValue(100), 0.01); } -TEST(Keyframe_Remove_Duplicate_Point) +TEST(Remove_Duplicate_Point) { // Create a keyframe curve with 2 points Keyframe kf; @@ -388,7 +390,7 @@ TEST(Keyframe_Remove_Duplicate_Point) CHECK_CLOSE(2.0, kf.GetPoint(0).co.Y, 0.01); } -TEST(Keyframe_Large_Number_Values) +TEST(Large_Number_Values) { // Large value int64_t const large_value = 30 * 60 * 90; @@ -404,7 +406,7 @@ TEST(Keyframe_Large_Number_Values) CHECK_CLOSE(100.0, kf.GetPoint(1).co.Y, 0.01); } -TEST(Keyframe_Remove_Point) +TEST(Remove_Point) { Keyframe kf; kf.AddPoint(openshot::Point(Coordinate(1, 1), CONSTANT)); @@ -417,7 +419,7 @@ TEST(Keyframe_Remove_Point) CHECK_THROW(kf.RemovePoint(100), OutOfBoundsPoint); } -TEST(Keyframe_Constant_Interpolation_First_Segment) +TEST(Constant_Interpolation_First_Segment) { Keyframe kf; kf.AddPoint(Point(Coordinate(1, 1), CONSTANT)); @@ -430,7 +432,7 @@ TEST(Keyframe_Constant_Interpolation_First_Segment) CHECK_EQUAL(100, kf.GetInt(4)); } -TEST(Keyframe_isIncreasing) +TEST(isIncreasing) { // Which cases need to be tested to keep same behaviour as // previously? @@ -461,7 +463,7 @@ TEST(Keyframe_isIncreasing) CHECK_EQUAL(true, kf.IsIncreasing(2)); } -TEST(Keyframe_GetLength) +TEST(GetLength) { Keyframe f; CHECK_EQUAL(0, f.GetLength()); @@ -479,7 +481,7 @@ TEST(Keyframe_GetLength) CHECK_EQUAL(201, g.GetLength()); } -TEST(Keyframe_Use_Interpolation_of_Segment_End_Point) +TEST(Use_Interpolation_of_Segment_End_Point) { Keyframe f; f.AddPoint(1,0, CONSTANT); @@ -487,7 +489,7 @@ TEST(Keyframe_Use_Interpolation_of_Segment_End_Point) CHECK_CLOSE(75.9, f.GetValue(50), 0.1); } -TEST(Keyframe_Handle_Large_Segment) +TEST(Handle_Large_Segment) { Keyframe kf; kf.AddPoint(1, 0, CONSTANT); @@ -498,3 +500,28 @@ TEST(Keyframe_Handle_Large_Segment) Fraction fr = kf.GetRepeatFraction(250000); CHECK_CLOSE(0.5, (double)fr.num / fr.den, 0.01); } + +TEST(Point_Vector_Constructor) +{ + std::vector points{Point(1, 10), Point(5, 20), Point(10, 30)}; + Keyframe k1(points); + + CHECK_EQUAL(11, k1.GetLength()); + CHECK_CLOSE(30.0f, k1.GetValue(10), 0.0001); +} + +TEST(Coordinate_Vector_Constructor) +{ + std::vector coordinates{ + Coordinate(1, 100), Coordinate(10, 500), Coordinate(1000, 80000) + }; + Keyframe k1(coordinates); + + CHECK_EQUAL(1001, k1.GetLength()); + + auto p1 = k1.GetPoint(2); + CHECK_CLOSE(80000.0f, p1.co.Y, 0.00001); +} + + +}; // SUITE diff --git a/tests/Point_Tests.cpp b/tests/Point_Tests.cpp index 6a94dda5..39012845 100644 --- a/tests/Point_Tests.cpp +++ b/tests/Point_Tests.cpp @@ -62,14 +62,24 @@ TEST(XY_Constructor) CHECK_EQUAL(openshot::InterpolationType::BEZIER, p1.interpolation); } +TEST(Pair_Constructor) +{ + // Create a point from a std::pair + std::pair coordinates(22, 5); + openshot::Point p1(coordinates); + + CHECK_CLOSE(22.0f, p1.co.X, 0.00001); + CHECK_CLOSE(5.0f, p1.co.Y, 0.00001); +} + TEST(Constructor_With_Coordinate) { // Create a point with a coordinate openshot::Coordinate c1(3,7); openshot::Point p1(c1); - CHECK_EQUAL(3, p1.co.X); - CHECK_EQUAL(7, p1.co.Y); + CHECK_CLOSE(3.0f, p1.co.X, 0.00001); + CHECK_CLOSE(7.0f, p1.co.Y, 0.00001); CHECK_EQUAL(openshot::InterpolationType::BEZIER, p1.interpolation); }