From: start1a Date: Sat, 26 Sep 2020 04:43:11 +0000 (+0900) Subject: add rlottiePlayer Project X-Git-Tag: accepted/tizen/unified/20201102.124239~14 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=845a2265d94c992b8a13c1acf117548e2c67652a;p=platform%2Fcore%2Fuifw%2Flottie-player.git add rlottiePlayer Project --- diff --git a/example/rlottiePlayer/Source.cpp b/example/rlottiePlayer/Source.cpp new file mode 100644 index 0000000..9f112cb --- /dev/null +++ b/example/rlottiePlayer/Source.cpp @@ -0,0 +1,50 @@ +#include "rlottie.h" +using namespace rlottie; + +std::unique_ptr anim; +uint32_t *buffer; +size_t width, height; +size_t bytesPerLine; +uint32_t curColor = UINT32_MAX; + +void initAnimation(size_t w, size_t h) +{ + width = w; + height = h; + bytesPerLine = width * sizeof(uint32_t); + buffer = (uint32_t*)calloc(bytesPerLine * height, sizeof(uint32_t)); +} + +void setAnimation(char* path, size_t w, size_t h) +{ + anim = Animation::loadFromFile(path); +} + +uint32_t* renderRLottieAnimation(uint32_t frameNum) +{ + static Surface surface = Surface(buffer, width, height, bytesPerLine); + anim->renderSync(frameNum, surface); + // background color + for (int i = 0; i < height; i++) + for (int j = 0; j < width; ++j) + { + uint32_t* v = buffer + i * width + j; + if (*v == 0) *v = curColor; + } + return buffer; +} + +void setAnimationColor(int r, int g, int b) +{ + curColor = ((255 << 16) * r) + ((255 << 8) * g) + 255 * b; +} + +size_t getTotalFrame() +{ + return anim->totalFrame(); +} + +bool isAnimNULL() +{ + return anim == NULL; +} \ No newline at end of file diff --git a/example/rlottiePlayer/framework.h b/example/rlottiePlayer/framework.h new file mode 100644 index 0000000..33a6be6 --- /dev/null +++ b/example/rlottiePlayer/framework.h @@ -0,0 +1,15 @@ +// header.h : include file for standard system include files, +// or project specific include files +// + +#pragma once + +#include "targetver.h" +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files +#include +// C RunTime Header Files +#include +#include +#include +#include diff --git a/example/rlottiePlayer/resource.h b/example/rlottiePlayer/resource.h new file mode 100644 index 0000000..7674dde --- /dev/null +++ b/example/rlottiePlayer/resource.h @@ -0,0 +1,40 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++¿¡¼­ »ý¼ºÇÑ Æ÷ÇÔ ÆÄÀÏÀÔ´Ï´Ù. +// rlottiePlayer.rc¿¡¼­ »ç¿ëµÇ°í ÀÖ½À´Ï´Ù. +// +#define IDC_MYICON 2 +#define IDD_RLOTTIEPLAYER_DIALOG 102 +#define IDS_APP_TITLE 103 +#define IDD_ABOUTBOX 103 +#define IDM_ABOUT 104 +#define IDM_EXIT 105 +#define IDI_RLOTTIEPLAYER 107 +#define IDI_SMALL 108 +#define IDC_RLOTTIEPLAYER 109 +#define IDR_MAINFRAME 128 +#define MAIN_WINDOW 130 +#define BTN_BROWSE 1004 +#define BTN_WHITE 1005 +#define BTN_BLACK 1006 +#define BTN_RED 1007 +#define BTN_GREEN 1008 +#define BTN_BLUE 1009 +#define SLIDER_CANVAS_RESIZE 1010 +#define BTN_PLAY 1011 +#define SLIDER_PLAY 1012 +#define TEXT_FILENAME 1013 +#define PICCTRL_RLOTTIE 1014 +#define TIMER_PLAY_ANIM 1015 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 131 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1017 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/example/rlottiePlayer/rlottie.dll b/example/rlottiePlayer/rlottie.dll new file mode 100644 index 0000000..296f70a Binary files /dev/null and b/example/rlottiePlayer/rlottie.dll differ diff --git a/example/rlottiePlayer/rlottie.h b/example/rlottiePlayer/rlottie.h new file mode 100644 index 0000000..12c413b --- /dev/null +++ b/example/rlottiePlayer/rlottie.h @@ -0,0 +1,525 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _RLOTTIE_H_ +#define _RLOTTIE_H_ + +#include +#include +#include + +#if defined _WIN32 || defined __CYGWIN__ + #ifdef RLOTTIE_BUILD + #define RLOTTIE_API __declspec(dllexport) + #else + #define RLOTTIE_API __declspec(dllimport) + #endif +#else + #ifdef RLOTTIE_BUILD + #define RLOTTIE_API __attribute__ ((visibility ("default"))) + #else + #define RLOTTIE_API + #endif +#endif + +class AnimationImpl; +struct LOTNode; +struct LOTLayerNode; + +namespace rlottie { + +/** + * @brief Configures rlottie model cache policy. + * + * Provides Library level control to configure model cache + * policy. Setting it to 0 will disable + * the cache as well as flush all the previously cached content. + * + * @param[in] cacheSize Maximum Model Cache size. + * + * @note to disable Caching configure with 0 size. + * @note to flush the current Cache content configure it with 0 and + * then reconfigure with the new size. + * + * @internal + */ +RLOTTIE_API void configureModelCacheSize(size_t cacheSize); + +struct Color { + Color() = default; + Color(float r, float g , float b):_r(r), _g(g), _b(b){} + float r() const {return _r;} + float g() const {return _g;} + float b() const {return _b;} +private: + float _r{0}; + float _g{0}; + float _b{0}; +}; + +struct Size { + Size() = default; + Size(float w, float h):_w(w), _h(h){} + float w() const {return _w;} + float h() const {return _h;} +private: + float _w{0}; + float _h{0}; +}; + +struct Point { + Point() = default; + Point(float x, float y):_x(x), _y(y){} + float x() const {return _x;} + float y() const {return _y;} +private: + float _x{0}; + float _y{0}; +}; + +struct FrameInfo { + explicit FrameInfo(uint32_t frame): _frameNo(frame){} + uint32_t curFrame() const {return _frameNo;} +private: + uint32_t _frameNo; +}; + +enum class Property { + FillColor, /*!< Color property of Fill object , value type is rlottie::Color */ + FillOpacity, /*!< Opacity property of Fill object , value type is float [ 0 .. 100] */ + StrokeColor, /*!< Color property of Stroke object , value type is rlottie::Color */ + StrokeOpacity, /*!< Opacity property of Stroke object , value type is float [ 0 .. 100] */ + StrokeWidth, /*!< stroke with property of Stroke object , value type is float */ + TrAnchor, /*!< Transform Anchor property of Layer and Group object , value type is rlottie::Point */ + TrPosition, /*!< Transform Position property of Layer and Group object , value type is rlottie::Point */ + TrScale, /*!< Transform Scale property of Layer and Group object , value type is rlottie::Size. range[0 ..100] */ + TrRotation, /*!< Transform Scale property of Layer and Group object , value type is float. range[0 .. 360] in degrees*/ + TrOpacity /*!< Transform Opacity property of Layer and Group object , value type is float [ 0 .. 100] */ +}; + +struct Color_Type{}; +struct Point_Type{}; +struct Size_Type{}; +struct Float_Type{}; +template struct MapType; + +class RLOTTIE_API Surface { +public: + /** + * @brief Surface object constructor. + * + * @param[in] buffer surface buffer. + * @param[in] width surface width. + * @param[in] height surface height. + * @param[in] bytesPerLine number of bytes in a surface scanline. + * + * @note Default surface format is ARGB32_Premultiplied. + * + * @internal + */ + Surface(uint32_t *buffer, size_t width, size_t height, size_t bytesPerLine); + + /** + * @brief Sets the Draw Area available on the Surface. + * + * Lottie will use the draw region size to generate frame image + * and will update only the draw rgion of the surface. + * + * @param[in] x region area x position. + * @param[in] y region area y position. + * @param[in] width region area width. + * @param[in] height region area height. + * + * @note Default surface format is ARGB32_Premultiplied. + * @note Default draw region area is [ 0 , 0, surface width , surface height] + * + * @internal + */ + void setDrawRegion(size_t x, size_t y, size_t width, size_t height); + + /** + * @brief Returns width of the surface. + * + * @return surface width + * + * @internal + * + */ + size_t width() const {return mWidth;} + + /** + * @brief Returns height of the surface. + * + * @return surface height + * + * @internal + */ + size_t height() const {return mHeight;} + + /** + * @brief Returns number of bytes in the surface scanline. + * + * @return number of bytes in scanline. + * + * @internal + */ + size_t bytesPerLine() const {return mBytesPerLine;} + + /** + * @brief Returns buffer attached tp the surface. + * + * @return buffer attaced to the Surface. + * + * @internal + */ + uint32_t *buffer() const {return mBuffer;} + + /** + * @brief Returns drawable area width of the surface. + * + * @return drawable area width + * + * @note Default value is width() of the surface + * + * @internal + * + */ + size_t drawRegionWidth() const {return mDrawArea.w;} + + /** + * @brief Returns drawable area height of the surface. + * + * @return drawable area height + * + * @note Default value is height() of the surface + * + * @internal + */ + size_t drawRegionHeight() const {return mDrawArea.h;} + + /** + * @brief Returns drawable area's x position of the surface. + * + * @return drawable area's x potition. + * + * @note Default value is 0 + * + * @internal + */ + size_t drawRegionPosX() const {return mDrawArea.x;} + + /** + * @brief Returns drawable area's y position of the surface. + * + * @return drawable area's y potition. + * + * @note Default value is 0 + * + * @internal + */ + size_t drawRegionPosY() const {return mDrawArea.y;} + + /** + * @brief Default constructor. + */ + Surface() = default; +private: + uint32_t *mBuffer{nullptr}; + size_t mWidth{0}; + size_t mHeight{0}; + size_t mBytesPerLine{0}; + struct { + size_t x{0}; + size_t y{0}; + size_t w{0}; + size_t h{0}; + }mDrawArea; +}; + +using MarkerList = std::vector>; +/** + * @brief https://helpx.adobe.com/after-effects/using/layer-markers-composition-markers.html + * Markers exported form AE are used to describe a segmnet of an animation {comment/tag , startFrame, endFrame} + * Marker can be use to devide a resource in to separate animations by tagging the segment with comment string , + * start frame and duration of that segment. + */ + +using LayerInfoList = std::vector>; + + +using ColorFilter = std::function; + +class RLOTTIE_API Animation { +public: + + /** + * @brief Constructs an animation object from file path. + * + * @param[in] path Lottie resource file path + * @param[in] cachePolicy whether to cache or not the model data. + * use only when need to explicit disabl caching for a + * particular resource. To disable caching at library level + * use @see configureModelCacheSize() instead. + * + * @return Animation object that can render the contents of the + * Lottie resource represented by file path. + * + * @internal + */ + static std::unique_ptr + loadFromFile(const std::string &path, bool cachePolicy=true); + + /** + * @brief Constructs an animation object from JSON string data. + * + * @param[in] jsonData The JSON string data. + * @param[in] key the string that will be used to cache the JSON string data. + * @param[in] resourcePath the path will be used to search for external resource. + * @param[in] cachePolicy whether to cache or not the model data. + * use only when need to explicit disabl caching for a + * particular resource. To disable caching at library level + * use @see configureModelCacheSize() instead. + * + * @return Animation object that can render the contents of the + * Lottie resource represented by JSON string data. + * + * @internal + */ + static std::unique_ptr + loadFromData(std::string jsonData, const std::string &key, + const std::string &resourcePath="", bool cachePolicy=true); + + /** + * @brief Constructs an animation object from JSON string data and update. + * the color properties using ColorFilter. + + * @param[in] jsonData The JSON string data. + * @param[in] resourcePath the path will be used to search for external resource. + * @param[in] filter The color filter that will be applied for each color property + * found during parsing. + + * @return Animation object that can render the contents of the + * Lottie resource represented by JSON string data. + * + * @internal + */ + static std::unique_ptr + loadFromData(std::string jsonData, std::string resourcePath, ColorFilter filter); + + /** + * @brief Returns default framerate of the Lottie resource. + * + * @return framerate of the Lottie resource + * + * @internal + * + */ + double frameRate() const; + + /** + * @brief Returns total number of frames present in the Lottie resource. + * + * @return frame count of the Lottie resource. + * + * @note frame number starts with 0. + * + * @internal + */ + size_t totalFrame() const; + + /** + * @brief Returns default viewport size of the Lottie resource. + * + * @param[out] width default width of the viewport. + * @param[out] height default height of the viewport. + * + * @internal + * + */ + void size(size_t &width, size_t &height) const; + + /** + * @brief Returns total animation duration of Lottie resource in second. + * it uses totalFrame() and frameRate() to calculate the duration. + * duration = totalFrame() / frameRate(). + * + * @return total animation duration in second. + * @retval 0 if the Lottie resource has no animation. + * + * @see totalFrame() + * @see frameRate() + * + * @internal + */ + double duration() const; + + /** + * @brief Returns frame number for a given position. + * this function helps to map the position value retuned + * by the animator to a frame number in side the Lottie resource. + * frame_number = lerp(start_frame, endframe, pos); + * + * @param[in] pos normalized position value [0 ... 1] + * + * @return frame numer maps to the position value [startFrame .... endFrame] + * + * @internal + */ + size_t frameAtPos(double pos); + + /** + * @brief Renders the content to surface Asynchronously. + * it gives a future in return to get the result of the + * rendering at a future point. + * To get best performance user has to start rendering as soon as + * it finds that content at {frameNo} has to be rendered and get the + * result from the future at the last moment when the surface is needed + * to draw into the screen. + * + * + * @param[in] frameNo Content corresponds to the @p frameNo needs to be drawn + * @param[in] surface Surface in which content will be drawn + * @param[in] keepAspectRatio whether to keep the aspect ratio while scaling the content. + * + * @return future that will hold the result when rendering finished. + * + * for Synchronus rendering @see renderSync + * + * @see Surface + * @internal + */ + std::future render(size_t frameNo, Surface surface, bool keepAspectRatio=true); + + /** + * @brief Renders the content to surface synchronously. + * for performance use the async rendering @see render + * + * @param[in] frameNo Content corresponds to the @p frameNo needs to be drawn + * @param[in] surface Surface in which content will be drawn + * @param[in] keepAspectRatio whether to keep the aspect ratio while scaling the content. + * + * @internal + */ + void renderSync(size_t frameNo, Surface surface, bool keepAspectRatio=true); + + /** + * @brief Returns root layer of the composition updated with + * content of the Lottie resource at frame number @p frameNo. + * + * @param[in] frameNo Content corresponds to the @p frameNo needs to be extracted. + * @param[in] width content viewbox width + * @param[in] height content viewbox height + * + * @return Root layer node. + * + * @internal + */ + const LOTLayerNode * renderTree(size_t frameNo, size_t width, size_t height) const; + + /** + * @brief Returns Composition Markers. + * + * + * @return returns MarkerList of the Composition. + * + * @see MarkerList + * @internal + */ + const MarkerList& markers() const; + + /** + * @brief Returns Layer information{name, inFrame, outFrame} of all the child layers of the composition. + * + * + * @return List of Layer Information of the Composition. + * + * @see LayerInfoList + * @internal + */ + const LayerInfoList& layers() const; + + /** + * @brief Sets property value for the specified {@link KeyPath}. This {@link KeyPath} can resolve + * to multiple contents. In that case, the callback's value will apply to all of them. + * + * Keypath should conatin object names separated by (.) and can handle globe(**) or wildchar(*). + * + * @usage + * To change fillcolor property of fill1 object in the layer1->group1->fill1 hirarchy to RED color + * + * player->setValue("layer1.group1.fill1", rlottie::Color(1, 0, 0); + * + * if all the color property inside group1 needs to be changed to GREEN color + * + * player->setValue("**.group1.**", rlottie::Color(0, 1, 0); + * + * @internal + */ + template + void setValue(const std::string &keypath, AnyValue value) + { + setValue(MapType>{}, prop, keypath, value); + } + + /** + * @brief default destructor + * + * @internal + */ + ~Animation(); + +private: + void setValue(Color_Type, Property, const std::string &, Color); + void setValue(Float_Type, Property, const std::string &, float); + void setValue(Size_Type, Property, const std::string &, Size); + void setValue(Point_Type, Property, const std::string &, Point); + + void setValue(Color_Type, Property, const std::string &, std::function &&); + void setValue(Float_Type, Property, const std::string &, std::function &&); + void setValue(Size_Type, Property, const std::string &, std::function &&); + void setValue(Point_Type, Property, const std::string &, std::function &&); + /** + * @brief default constructor + * + * @internal + */ + Animation(); + + std::unique_ptr d; +}; + +//Map Property to Value type +template<> struct MapType>: Color_Type{}; +template<> struct MapType>: Color_Type{}; +template<> struct MapType>: Float_Type{}; +template<> struct MapType>: Float_Type{}; +template<> struct MapType>: Float_Type{}; +template<> struct MapType>: Float_Type{}; +template<> struct MapType>: Float_Type{}; +template<> struct MapType>: Point_Type{}; +template<> struct MapType>: Point_Type{}; +template<> struct MapType>: Size_Type{}; + + +} // namespace lotplayer + +#endif // _RLOTTIE_H_ diff --git a/example/rlottiePlayer/rlottie.lib b/example/rlottiePlayer/rlottie.lib new file mode 100644 index 0000000..2625916 Binary files /dev/null and b/example/rlottiePlayer/rlottie.lib differ diff --git a/example/rlottiePlayer/rlottiePlayer.cpp b/example/rlottiePlayer/rlottiePlayer.cpp new file mode 100644 index 0000000..db2c9bf --- /dev/null +++ b/example/rlottiePlayer/rlottiePlayer.cpp @@ -0,0 +1,517 @@ +// rlottiePlayer.cpp : Defines the entry point for the application. +// + + +#include "framework.h" +#include "rlottiePlayer.h" +using namespace Gdiplus; + +#define MAX_LOADSTRING 100 + +// Global Variables: +HINSTANCE hInst; // current instance +WCHAR szTitle[MAX_LOADSTRING]; // The title bar text +WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name +HWND mainWindow; // Main Window Instance +HWND hTextFileToBeOpened; // openDialog file path +HWND hBtnPlay; +HWND hSliderPlay, hSliderCanvasResize; +UINT curFrame = 0; +RlottieBitmap anim; // rendered Animation Bitmap +RECT animRect, backRect; +Gdiplus::Color backColor(255, 255, 255, 255); +Gdiplus::Color borderColor(255, 0, 0, 0); +bool isBackgroundChanged = false; + +// Forward declarations of functions included in this code module: +ATOM MyRegisterClass(HINSTANCE hInstance); +BOOL InitInstance(HINSTANCE, int); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); +void openJSONFileDialog(HWND); +void initUIControl(HWND); +void dlgUICommand(HWND, WPARAM); +void resizeCanvas(HWND, int); +void changeBackgroundColor(int r, int g, int b); + +// Animation Rendering Functions +void draw(HDC); +Bitmap* CreateBitmap(void* data, unsigned int width, unsigned int height); +void renderAnimation(UINT); + +int APIENTRY wWinMain(_In_ HINSTANCE hInstance, + _In_opt_ HINSTANCE hPrevInstance, + _In_ LPWSTR lpCmdLine, + _In_ int nCmdShow) +{ + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + // initialize Gdiplus + Gdiplus::GdiplusStartupInput gdiplusStartUpInput; + ULONG_PTR gdiplustoken; + Gdiplus::GdiplusStartup(&gdiplustoken, &gdiplusStartUpInput, nullptr); + + // Initialize global strings + LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + LoadStringW(hInstance, IDC_RLOTTIEPLAYER, szWindowClass, MAX_LOADSTRING); + MyRegisterClass(hInstance); + + // Perform application initialization: + if (!InitInstance(hInstance, nCmdShow)) + { + return FALSE; + } + + HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_RLOTTIEPLAYER)); + + MSG msg; + + // Main message loop: + while (GetMessage(&msg, nullptr, 0, 0)) + { + if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + Gdiplus::GdiplusShutdown(gdiplustoken); + return (int)msg.wParam; +} + + + +// +// FUNCTION: MyRegisterClass() +// +// PURPOSE: Registers the window class. +// +ATOM MyRegisterClass(HINSTANCE hInstance) +{ + WNDCLASSEXW wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_RLOTTIEPLAYER)); + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_RLOTTIEPLAYER); + wcex.lpszClassName = szWindowClass; + wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); + + return RegisterClassExW(&wcex); +} + +// +// FUNCTION: InitInstance(HINSTANCE, int) +// +// PURPOSE: Saves instance handle and creates main window +// +// COMMENTS: +// +// In this function, we save the instance handle in a global variable and +// create and display the main program window. +// +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + hInst = hInstance; // Store instance handle in our global variable + + DWORD dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; + mainWindow = CreateWindowEx(0, szWindowClass, szTitle, dwStyle, + CW_USEDEFAULT, CW_USEDEFAULT, WND_WIDTH, WND_HEIGHT, nullptr, nullptr, hInstance, nullptr); + + if (!mainWindow) + { + return FALSE; + } + + ShowWindow(mainWindow, nCmdShow); + UpdateWindow(mainWindow); + SetMenu(mainWindow, NULL); + + return TRUE; +} + +// +// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) +// +// PURPOSE: Processes messages for the main window. +// +// WM_COMMAND - process the application menu +// WM_PAINT - Paint the main window +// WM_DESTROY - post a quit message and return +// +// +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static bool isplay = false; + int wmId = LOWORD(wParam); + + switch (message) + { + case WM_CREATE: + { + initUIControl(hWnd); + initAnimation(BMP_MAX_LEN, BMP_MAX_LEN); + break; + } + case WM_TIMER: + { + switch (wmId) + { + case TIMER_PLAY_ANIM: + { + renderAnimation(curFrame + 1); + SendMessage(hSliderPlay, TBM_SETPOS, TRUE, curFrame); + break; + } + default: + break; + } + break; + } + case WM_COMMAND: + { + // Parse the menu selections: + switch (wmId) + { + case IDM_ABOUT: + DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); + break; + + case IDM_EXIT: + DestroyWindow(hWnd); + break; + + case BTN_BROWSE: + openJSONFileDialog(hWnd); + break; + + case BTN_PLAY: + { + LPWSTR textBtnPlay; + USES_CONVERSION; + if (isplay) + { + isplay = false; + textBtnPlay = A2W("Play"); + KillTimer(hWnd, TIMER_PLAY_ANIM); + } + else + { + isplay = true; + textBtnPlay = A2W("Pause"); + SetTimer(hWnd, TIMER_PLAY_ANIM, 10, NULL); + } + SetWindowText(hBtnPlay, textBtnPlay); + break; + } + + case WM_DROPFILES: + break; + case BTN_WHITE: + changeBackgroundColor(1, 1, 1); + break; + case BTN_BLACK: + changeBackgroundColor(0, 0, 0); + break; + case BTN_RED: + changeBackgroundColor(1, 0, 0); + break; + case BTN_GREEN: + changeBackgroundColor(0, 1, 0); + break; + case BTN_BLUE: + changeBackgroundColor(0, 0, 1); + break; + + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + } + break; + + case WM_HSCROLL: + { + if ((lParam != 0) && (reinterpret_cast(lParam) == hSliderPlay)) + { + UINT frameNum = SendDlgItemMessage(hWnd, SLIDER_PLAY, TBM_GETPOS, 0, 0); + renderAnimation(frameNum); + } + else if ((lParam != 0) && (reinterpret_cast(lParam) == hSliderCanvasResize)) + { + static int curSize = anim.width / RESIZE_LENGTH; + int newSize = SendDlgItemMessage(hWnd, SLIDER_CANVAS_RESIZE, TBM_GETPOS, 0, 0); + resizeCanvas(hWnd, (curSize - newSize) * RESIZE_LENGTH); + curSize = newSize; + } + break; + } + + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hWnd, &ps); + draw(hdc); + EndPaint(hWnd, &ps); + } + break; + case WM_CTLCOLORSTATIC: + { + static HBRUSH hBrushEdit = CreateSolidBrush(RGB(255, 255, 255)); + return (LRESULT)hBrushEdit; + } + + case WM_DESTROY: + PostQuitMessage(0); + break; + + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + +// Message handler for about box. +INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + UNREFERENCED_PARAMETER(lParam); + switch (message) + { + case WM_INITDIALOG: + return (INT_PTR)TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) + { + EndDialog(hDlg, LOWORD(wParam)); + return (INT_PTR)TRUE; + } + break; + } + return (INT_PTR)FALSE; +} + +void openJSONFileDialog(HWND hDlg) +{ + OPENFILENAME ofn; // common dialog box structure + TCHAR szFile[260] = { 0 }; // if using TCHAR macros + + // Initialize OPENFILENAME + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hDlg; + ofn.lpstrFile = szFile; + ofn.nMaxFile = sizeof(szFile); + ofn.lpstrFilter = _T("JSON\0*.json\0"); + ofn.nFilterIndex = 1; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; + + if (GetOpenFileName(&ofn)) + { + SetWindowText(hTextFileToBeOpened, ofn.lpstrFile); + // LPWSTR(w_char*) -> LPSTR(char*) + USES_CONVERSION; + LPSTR path = W2A(ofn.lpstrFile); + + setAnimation(path, BMP_MAX_LEN, BMP_MAX_LEN); + // init play slider + SendMessage(hSliderPlay, TBM_SETRANGE, FALSE, MAKELPARAM(0, getTotalFrame())); + SendMessage(hSliderPlay, TBM_SETPOS, TRUE, 0); + renderAnimation(0); + } +} + +void draw(HDC hdc) +{ + Graphics gf(hdc); + int half_interval = UI_INTERVAL / 2; + + // background + SolidBrush brush(backColor); + int back_y = half_interval + BTN_HEIGHT; + int back_height = back_y + BMP_MAX_LEN + UI_INTERVAL; + if (isBackgroundChanged) + { + isBackgroundChanged = false; + gf.FillRectangle(&brush, 0, back_y, WND_WIDTH, back_height); + } + + // image borderline + Pen pen(borderColor); + gf.DrawRectangle(&pen, anim.x - half_interval, anim.y - half_interval, anim.width + half_interval * 2, anim.height + half_interval * 2); + + // image + if (anim.image != NULL) + { + gf.DrawImage(anim.image, anim.x, anim.y, anim.width, anim.height); + } +} + +Bitmap* CreateBitmap(void* data, unsigned int width, unsigned int height) +{ + BITMAPINFO Info; + memset(&Info, 0, sizeof(Info)); + + Info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + Info.bmiHeader.biWidth = 500; + Info.bmiHeader.biHeight = 500; + Info.bmiHeader.biPlanes = 1; + Info.bmiHeader.biBitCount = 32; + Info.bmiHeader.biCompression = BI_RGB; + Info.bmiHeader.biSizeImage = 0; //(((32 * width + 31) & ~31) / 8) * height; + + return new Gdiplus::Bitmap(&Info, data); +} + +void renderAnimation(UINT frameNum) +{ + if (isAnimNULL()) return; + if (anim.image != NULL) delete anim.image; + + curFrame = frameNum % getTotalFrame(); + + // render + UINT* resRender = renderRLottieAnimation(curFrame); + anim.image = CreateBitmap(resRender, BMP_MAX_LEN, BMP_MAX_LEN); + anim.image->RotateFlip(RotateNoneFlipY); + // call WM_PAINT message + InvalidateRect(mainWindow, &animRect, FALSE); +} + +void initUIControl(HWND hWnd) +{ + int half_ui_interval = UI_INTERVAL / 2; + + // button browse + int browse_x = UI_INTERVAL; + int browse_y = half_ui_interval; + CreateWindow(L"button", L"Browse", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + browse_x, browse_y, BTN_WIDTH, BTN_HEIGHT, hWnd, (HMENU)BTN_BROWSE, hInst, NULL); + + // textbox FilePath + int textFile_x = browse_x + BTN_WIDTH + UI_INTERVAL; + int textFile_y = browse_y; + hTextFileToBeOpened = CreateWindowEx(0, L"static", L"No file selected.", WS_CHILD | WS_VISIBLE | ES_LEFT, + textFile_x, textFile_y, WND_WIDTH * 0.6, TEXT_HEIGHT, hWnd, (HMENU)TEXT_FILENAME, hInst, 0); + + // image + anim.x = WND_WIDTH / 4; + anim.y = browse_y + BTN_HEIGHT + UI_INTERVAL * 2; + anim.width = BMP_MAX_LEN; + anim.height = anim.width; + + // animating range + SetRect(&animRect, + anim.x - UI_INTERVAL, + anim.y - UI_INTERVAL, + anim.x + anim.width + UI_INTERVAL * 2, + anim.y + anim.height + UI_INTERVAL * 2 + ); + + // background range + SetRect(&backRect, + 0, + anim.y - UI_INTERVAL, + WND_WIDTH, + anim.y + anim.height + UI_INTERVAL * 2); + + // text Background Color + int textBC_x = WND_WIDTH / 20; + int textBC_y = anim.y + anim.height + UI_INTERVAL * 2; + CreateWindowEx(0, L"static", L"Background Color", WS_CHILD | WS_VISIBLE | ES_LEFT, + textBC_x, textBC_y, 120, TEXT_HEIGHT, hWnd, (HMENU)TEXT_FILENAME, hInst, 0); + + // radio button + // white + int white_x = WND_WIDTH / 20; + int white_y = textBC_y + TEXT_HEIGHT + half_ui_interval; + CreateWindowEx(0, L"button", L"White", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON, + white_x, white_y, RDOBTN_WIDTH, RDOBTN_HEIGHT, hWnd, (HMENU)BTN_WHITE, hInst, NULL); + + // black + int black_x = white_x + RDOBTN_WIDTH + half_ui_interval; + int black_y = white_y; + CreateWindowEx(0, L"button", L"Black", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON, + black_x, black_y, RDOBTN_WIDTH, RDOBTN_HEIGHT, hWnd, (HMENU)BTN_BLACK, hInst, NULL); + + // red + int red_x = black_x + RDOBTN_WIDTH + half_ui_interval; + int red_y = white_y; + CreateWindowEx(0, L"button", L"Red", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON, + red_x, red_y, RDOBTN_WIDTH, RDOBTN_HEIGHT, hWnd, (HMENU)BTN_RED, hInst, NULL); + + // green + int green_x = red_x + RDOBTN_WIDTH + half_ui_interval; + int green_y = white_y; + CreateWindowEx(0, L"button", L"Green", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON, + green_x, green_y, RDOBTN_WIDTH, RDOBTN_HEIGHT, hWnd, (HMENU)BTN_GREEN, hInst, NULL); + + // blue + int blue_x = green_x + RDOBTN_WIDTH + half_ui_interval; + int blue_y = white_y; + CreateWindowEx(0, L"button", L"Blue", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON, + blue_x, blue_y, RDOBTN_WIDTH, RDOBTN_HEIGHT, hWnd, (HMENU)BTN_BLUE, hInst, NULL); + + CheckRadioButton(hWnd, BTN_WHITE, BTN_BLUE, BTN_WHITE); + + // text Canvas Resize + int textCR_x = WND_WIDTH / 2; + int textCR_y = textBC_y; + CreateWindowEx(0, L"static", L"Canvas Resize", WS_CHILD | WS_VISIBLE | ES_LEFT, + textCR_x, textCR_y, 120, TEXT_HEIGHT, hWnd, (HMENU)TEXT_FILENAME, hInst, 0); + + // slider Canvas Resize + int sliderCR_x = textCR_x; + int sliderCR_y = textCR_y + TEXT_HEIGHT + half_ui_interval; + hSliderCanvasResize = CreateWindowExW(0, TRACKBAR_CLASSW, NULL, WS_CHILD | WS_VISIBLE | TBS_FIXEDLENGTH | TBS_NOTICKS, + sliderCR_x, sliderCR_y, WND_WIDTH * 0.2, SLIDER_HEIGHT, hWnd, (HMENU)SLIDER_CANVAS_RESIZE, hInst, NULL); + + // init resize slider + UINT sizeSlider = anim.width / RESIZE_LENGTH; + SendMessage(hSliderCanvasResize, TBM_SETRANGE, FALSE, MAKELPARAM(0, sizeSlider)); + SendMessage(hSliderCanvasResize, TBM_SETPOS, TRUE, sizeSlider); + + // button play + int btnPlay_x = WND_WIDTH / 10; + int btnPlay_y = red_y + RDOBTN_HEIGHT + UI_INTERVAL * 2; + hBtnPlay = CreateWindow(L"button", L"Play", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + btnPlay_x, btnPlay_y, BTN_WIDTH, BTN_HEIGHT, hWnd, (HMENU)BTN_PLAY, hInst, NULL); + + // slider play + int sliderPlay_x = btnPlay_x + BTN_WIDTH + UI_INTERVAL; + int sliderPlay_y = btnPlay_y; + hSliderPlay = CreateWindowExW(0, TRACKBAR_CLASSW, NULL, WS_CHILD | WS_VISIBLE | TBS_FIXEDLENGTH | TBS_NOTICKS, + sliderPlay_x, sliderPlay_y, WND_WIDTH * 0.6, SLIDER_HEIGHT, hWnd, (HMENU)SLIDER_PLAY, hInst, NULL); +} + +void resizeCanvas(HWND hWnd, int resizeValue) +{ + isBackgroundChanged = true; + anim.x += resizeValue / 2; + anim.y += resizeValue / 2; + anim.width -= resizeValue; + anim.height -= resizeValue; + InvalidateRect(hWnd, &animRect, TRUE); +} + +void changeBackgroundColor(int r, int g, int b) +{ + isBackgroundChanged = true; + backColor = Gdiplus::Color(r * 255, g * 255, b * 255); + if (r + g + b == 0) borderColor = Gdiplus::Color(255, 255, 255); + else borderColor = Gdiplus::Color(0, 0, 0); + setAnimationColor(r, g, b); + renderAnimation(curFrame); + InvalidateRect(mainWindow, &backRect, FALSE); +} \ No newline at end of file diff --git a/example/rlottiePlayer/rlottiePlayer.h b/example/rlottiePlayer/rlottiePlayer.h new file mode 100644 index 0000000..4200862 --- /dev/null +++ b/example/rlottiePlayer/rlottiePlayer.h @@ -0,0 +1,39 @@ +#pragma once + +#include "resource.h" +#include // OPENFILENAME +#include "atlconv.h" // String cast. ex) LPWSTR <-> LPSTR +#include +#include // slider handle +#include + +// interval +#define UI_INTERVAL 20 + +// length +#define WND_WIDTH 1000 +#define WND_HEIGHT 800 +#define BMP_MAX_LEN 500 +#define BTN_WIDTH 100 +#define BTN_HEIGHT 30 +#define TEXT_HEIGHT 20 +#define SLIDER_HEIGHT 25 +#define RDOBTN_WIDTH 60 +#define RDOBTN_HEIGHT 20 +#define RESIZE_LENGTH 10 + +void setAnimation(char* path, size_t w, size_t h); +void initAnimation(size_t w, size_t h); +uint32_t* renderRLottieAnimation(uint32_t frameNum); +size_t getTotalFrame(); +bool isAnimNULL(); +void setAnimationColor(int r, int g, int b); + +typedef struct RlottieBitmap +{ + Gdiplus::Bitmap* image = NULL; + int x = 0; + int y = 0; + unsigned int width = 0; + unsigned int height = 0; +}RlottieBitmap; \ No newline at end of file diff --git a/example/rlottiePlayer/rlottiePlayer.ico b/example/rlottiePlayer/rlottiePlayer.ico new file mode 100644 index 0000000..b3ec03b Binary files /dev/null and b/example/rlottiePlayer/rlottiePlayer.ico differ diff --git a/example/rlottiePlayer/rlottiePlayer.rc b/example/rlottiePlayer/rlottiePlayer.rc new file mode 100644 index 0000000..0c7935f Binary files /dev/null and b/example/rlottiePlayer/rlottiePlayer.rc differ diff --git a/example/rlottiePlayer/rlottiePlayer.sln b/example/rlottiePlayer/rlottiePlayer.sln new file mode 100644 index 0000000..d1c8f0d --- /dev/null +++ b/example/rlottiePlayer/rlottiePlayer.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30503.244 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rlottiePlayer", "rlottiePlayer.vcxproj", "{CC7AD634-4D29-4D8E-997D-9727DABB44EE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CC7AD634-4D29-4D8E-997D-9727DABB44EE}.Debug|x64.ActiveCfg = Debug|x64 + {CC7AD634-4D29-4D8E-997D-9727DABB44EE}.Debug|x64.Build.0 = Debug|x64 + {CC7AD634-4D29-4D8E-997D-9727DABB44EE}.Debug|x86.ActiveCfg = Debug|Win32 + {CC7AD634-4D29-4D8E-997D-9727DABB44EE}.Debug|x86.Build.0 = Debug|Win32 + {CC7AD634-4D29-4D8E-997D-9727DABB44EE}.Release|x64.ActiveCfg = Release|x64 + {CC7AD634-4D29-4D8E-997D-9727DABB44EE}.Release|x64.Build.0 = Release|x64 + {CC7AD634-4D29-4D8E-997D-9727DABB44EE}.Release|x86.ActiveCfg = Release|Win32 + {CC7AD634-4D29-4D8E-997D-9727DABB44EE}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {57EEA15F-28FB-4C19-96B4-7B62BFA0CFE5} + EndGlobalSection +EndGlobal diff --git a/example/rlottiePlayer/rlottiePlayer.vcxproj b/example/rlottiePlayer/rlottiePlayer.vcxproj new file mode 100644 index 0000000..1e6eeb2 --- /dev/null +++ b/example/rlottiePlayer/rlottiePlayer.vcxproj @@ -0,0 +1,162 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {cc7ad634-4d29-4d8e-997d-9727dabb44ee} + rlottiePlayer + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + Level3 + true + _DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;rlottie.lib;gdiplus.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/example/rlottiePlayer/rlottiePlayer.vcxproj.filters b/example/rlottiePlayer/rlottiePlayer.vcxproj.filters new file mode 100644 index 0000000..5c0486e --- /dev/null +++ b/example/rlottiePlayer/rlottiePlayer.vcxproj.filters @@ -0,0 +1,52 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + + + Resource Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/example/rlottiePlayer/rlottie_capi.h b/example/rlottiePlayer/rlottie_capi.h new file mode 100644 index 0000000..9bdf336 --- /dev/null +++ b/example/rlottiePlayer/rlottie_capi.h @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _RLOTTIE_CAPI_H_ +#define _RLOTTIE_CAPI_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + LOTTIE_ANIMATION_PROPERTY_FILLCOLOR, /*!< Color property of Fill object , value type is float [0 ... 1] */ + LOTTIE_ANIMATION_PROPERTY_FILLOPACITY, /*!< Opacity property of Fill object , value type is float [ 0 .. 100] */ + LOTTIE_ANIMATION_PROPERTY_STROKECOLOR, /*!< Color property of Stroke object , value type is float [0 ... 1] */ + LOTTIE_ANIMATION_PROPERTY_STROKEOPACITY, /*!< Opacity property of Stroke object , value type is float [ 0 .. 100] */ + LOTTIE_ANIMATION_PROPERTY_STROKEWIDTH, /*!< stroke with property of Stroke object , value type is float */ + LOTTIE_ANIMATION_PROPERTY_TR_ANCHOR, /*!< Transform Anchor property of Layer and Group object , value type is int */ + LOTTIE_ANIMATION_PROPERTY_TR_POSITION, /*!< Transform Position property of Layer and Group object , value type is int */ + LOTTIE_ANIMATION_PROPERTY_TR_SCALE, /*!< Transform Scale property of Layer and Group object , value type is float range[0 ..100] */ + LOTTIE_ANIMATION_PROPERTY_TR_ROTATION, /*!< Transform Scale property of Layer and Group object , value type is float. range[0 .. 360] in degrees*/ + LOTTIE_ANIMATION_PROPERTY_TR_OPACITY /*!< Transform Opacity property of Layer and Group object , value type is float [ 0 .. 100] */ +}Lottie_Animation_Property; + +typedef struct Lottie_Animation_S Lottie_Animation; + +/** + * @brief Constructs an animation object from file path. + * + * @param[in] path Lottie resource file path + * + * @return Animation object that can build the contents of the + * Lottie resource represented by file path. + * + * @see lottie_animation_destroy() + * + * @ingroup Lottie_Animation + * @internal + */ +RLOTTIE_API Lottie_Animation *lottie_animation_from_file(const char *path); + +/** + * @brief Constructs an animation object from JSON string data. + * + * @param[in] data The JSON string data. + * @param[in] key the string that will be used to cache the JSON string data. + * @param[in] resource_path the path that will be used to load external resource needed by the JSON data. + * + * @return Animation object that can build the contents of the + * Lottie resource represented by JSON string data. + * + * @ingroup Lottie_Animation + * @internal + */ +RLOTTIE_API Lottie_Animation *lottie_animation_from_data(const char *data, const char *key, const char *resource_path); + +/** + * @brief Free given Animation object resource. + * + * @param[in] animation Animation object to free. + * + * @see lottie_animation_from_file() + * @see lottie_animation_from_data() + * + * @ingroup Lottie_Animation + * @internal + */ +RLOTTIE_API void lottie_animation_destroy(Lottie_Animation *animation); + +/** + * @brief Returns default viewport size of the Lottie resource. + * + * @param[in] animation Animation object. + * @param[out] w default width of the viewport. + * @param[out] h default height of the viewport. + * + * @ingroup Lottie_Animation + * @internal + */ +RLOTTIE_API void lottie_animation_get_size(const Lottie_Animation *animation, size_t *width, size_t *height); + +/** + * @brief Returns total animation duration of Lottie resource in second. + * it uses totalFrame() and frameRate() to calculate the duration. + * duration = totalFrame() / frameRate(). + * + * @param[in] animation Animation object. + * + * @return total animation duration in second. + * @c 0 if the Lottie resource has no animation. + * + * @see lottie_animation_get_totalframe() + * @see lottie_animation_get_framerate() + * + * @ingroup Lottie_Animation + * @internal + */ +RLOTTIE_API double lottie_animation_get_duration(const Lottie_Animation *animation); + +/** + * @brief Returns total number of frames present in the Lottie resource. + * + * @param[in] animation Animation object. + * + * @return frame count of the Lottie resource.* + * + * @note frame number starts with 0. + * + * @see lottie_animation_get_duration() + * @see lottie_animation_get_framerate() + * + * @ingroup Lottie_Animation + * @internal + */ +RLOTTIE_API size_t lottie_animation_get_totalframe(const Lottie_Animation *animation); + +/** + * @brief Returns default framerate of the Lottie resource. + * + * @param[in] animation Animation object. + * + * @return framerate of the Lottie resource + * + * @ingroup Lottie_Animation + * @internal + * + */ +RLOTTIE_API double lottie_animation_get_framerate(const Lottie_Animation *animation); + +/** + * @brief Get the render tree which contains the snapshot of the animation object + * at frame = @c frame_num, the content of the animation in that frame number. + * + * @param[in] animation Animation object. + * @param[in] frame_num Content corresponds to the @p frame_num needs to be drawn + * @param[in] width requested snapshot viewport width. + * @param[in] height requested snapshot viewport height. + * + * @return Animation snapshot tree. + * + * @note: User has to traverse the tree for rendering. + * + * @see LOTLayerNode + * @see LOTNode + * + * @ingroup Lottie_Animation + * @internal + */ +RLOTTIE_API const LOTLayerNode *lottie_animation_render_tree(Lottie_Animation *animation, size_t frame_num, size_t width, size_t height); + +/** + * @brief Maps position to frame number and returns it. + * + * @param[in] animation Animation object. + * @param[in] pos position in the range [ 0.0 .. 1.0 ]. + * + * @return mapped frame numbe in the range [ start_frame .. end_frame ]. + * @c 0 if the Lottie resource has no animation. + * + * + * @ingroup Lottie_Animation + * @internal + */ +RLOTTIE_API size_t lottie_animation_get_frame_at_pos(const Lottie_Animation *animation, float pos); + +/** + * @brief Request to render the content of the frame @p frame_num to buffer @p buffer. + * + * @param[in] animation Animation object. + * @param[in] frame_num the frame number needs to be rendered. + * @param[in] buffer surface buffer use for rendering. + * @param[in] width width of the surface + * @param[in] height height of the surface + * @param[in] bytes_per_line stride of the surface in bytes. + * + * + * @ingroup Lottie_Animation + * @internal + */ +RLOTTIE_API void lottie_animation_render(Lottie_Animation *animation, size_t frame_num, uint32_t *buffer, size_t width, size_t height, size_t bytes_per_line); + +/** + * @brief Request to render the content of the frame @p frame_num to buffer @p buffer asynchronously. + * + * @param[in] animation Animation object. + * @param[in] frame_num the frame number needs to be rendered. + * @param[in] buffer surface buffer use for rendering. + * @param[in] width width of the surface + * @param[in] height height of the surface + * @param[in] bytes_per_line stride of the surface in bytes. + * + * @note user must call lottie_animation_render_flush() to make sure render is finished. + * + * @ingroup Lottie_Animation + * @internal + */ +RLOTTIE_API void lottie_animation_render_async(Lottie_Animation *animation, size_t frame_num, uint32_t *buffer, size_t width, size_t height, size_t bytes_per_line); + +/** + * @brief Request to finish the current async renderer job for this animation object. + * If render is finished then this call returns immidiately. + * If not, it waits till render job finish and then return. + * + * @param[in] animation Animation object. + * + * @warning User must call lottie_animation_render_async() and lottie_animation_render_flush() + * in pair to get the benefit of async rendering. + * + * @return the pixel buffer it finished rendering. + * + * @ingroup Lottie_Animation + * @internal + */ +RLOTTIE_API uint32_t *lottie_animation_render_flush(Lottie_Animation *animation); + + +/** + * @brief Request to change the properties of this animation object. + * Keypath should conatin object names separated by (.) and can handle globe(**) or wildchar(*) + * + * @usage + * To change fillcolor property of fill1 object in the layer1->group1->fill1 hirarchy to RED color + * + * lottie_animation_property_override(animation, LOTTIE_ANIMATION_PROPERTY_FILLCOLOR, "layer1.group1.fill1", 1.0, 0.0, 0.0); + * + * if all the color property inside group1 needs to be changed to GREEN color + * + * lottie_animation_property_override(animation, LOTTIE_ANIMATION_PROPERTY_FILLCOLOR, "**.group1.**", 1.0, 0.0, 0.0); + * + * @param[in] animation Animation object. + * @param[in] type Property type. (@p Lottie_Animation_Property) + * @param[in] keypath Specific content of target. + * @param[in] ... Property values. + * + * @ingroup Lottie_Animation + * @internal + * */ +RLOTTIE_API void lottie_animation_property_override(Lottie_Animation *animation, const Lottie_Animation_Property type, const char *keypath, ...); + + +/** + * @brief Returns list of markers in the Lottie resource + * @p LOTMarkerList has a @p LOTMarker list and size of list + * @p LOTMarker has the marker's name, start frame, and end frame. + * + * @param[in] animation Animation object. + * + * @return The list of marker. If there is no marker, return null. + * + * @ingroup Lottie_Animation + * @internal + * */ +RLOTTIE_API const LOTMarkerList* lottie_animation_get_markerlist(Lottie_Animation *animation); + +#ifdef __cplusplus +} +#endif + +#endif //_RLOTTIE_CAPI_H_ + diff --git a/example/rlottiePlayer/rlottiecommon.h b/example/rlottiePlayer/rlottiecommon.h new file mode 100644 index 0000000..784fbe2 --- /dev/null +++ b/example/rlottiePlayer/rlottiecommon.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _RLOTTIE_COMMON_H_ +#define _RLOTTIE_COMMON_H_ + +#if defined _WIN32 || defined __CYGWIN__ + #ifdef RLOTTIE_BUILD + #define RLOTTIE_API __declspec(dllexport) + #else + #define RLOTTIE_API __declspec(dllimport) + #endif +#else + #ifdef RLOTTIE_BUILD + #define RLOTTIE_API __attribute__ ((visibility ("default"))) + #else + #define RLOTTIE_API + #endif +#endif + + +/** + * @defgroup Lottie_Animation Lottie_Animation + * + * Lottie Animation is a modern style vector based animation design. Its animation + * resource(within json format) could be generated by Adobe After Effect using + * bodymovin plugin. You can find a good examples in Lottie Community which + * shares many free resources(see: www.lottiefiles.com). + * + * This Lottie_Animation is a common engine to manipulate, control Lottie + * Animation from the Lottie resource - json file. It provides a scene-graph + * node tree per frames by user demand as well as rasterized frame images. + * + */ + +/** + * @ingroup Lottie_Animation + */ + +typedef enum +{ + BrushSolid = 0, + BrushGradient +} LOTBrushType; + +typedef enum +{ + FillEvenOdd = 0, + FillWinding +} LOTFillRule; + +typedef enum +{ + JoinMiter = 0, + JoinBevel, + JoinRound +} LOTJoinStyle; + +typedef enum +{ + CapFlat = 0, + CapSquare, + CapRound +} LOTCapStyle; + +typedef enum +{ + GradientLinear = 0, + GradientRadial +} LOTGradientType; + +typedef struct LOTGradientStop +{ + float pos; + unsigned char r, g, b, a; +} LOTGradientStop; + +typedef enum +{ + MaskAdd = 0, + MaskSubstract, + MaskIntersect, + MaskDifference +} LOTMaskType; + +typedef struct LOTMask { + struct { + const float *ptPtr; + size_t ptCount; + const char* elmPtr; + size_t elmCount; + } mPath; + LOTMaskType mMode; + unsigned char mAlpha; +}LOTMask; + +typedef enum +{ + MatteNone = 0, + MatteAlpha, + MatteAlphaInv, + MatteLuma, + MatteLumaInv +} LOTMatteType; + +typedef struct LOTMarker { + char *name; + size_t startframe; + size_t endframe; +} LOTMarker; + +typedef struct LOTMarkerList { + LOTMarker *ptr; + size_t size; +} LOTMarkerList; + +typedef struct LOTNode { + +#define ChangeFlagNone 0x0000 +#define ChangeFlagPath 0x0001 +#define ChangeFlagPaint 0x0010 +#define ChangeFlagAll (ChangeFlagPath & ChangeFlagPaint) + + struct { + const float *ptPtr; + size_t ptCount; + const char *elmPtr; + size_t elmCount; + } mPath; + + struct { + unsigned char r, g, b, a; + } mColor; + + struct { + unsigned char enable; + float width; + LOTCapStyle cap; + LOTJoinStyle join; + float miterLimit; + float *dashArray; + int dashArraySize; + } mStroke; + + struct { + LOTGradientType type; + LOTGradientStop *stopPtr; + size_t stopCount; + struct { + float x, y; + } start, end, center, focal; + float cradius; + float fradius; + } mGradient; + + struct { + unsigned char *data; + size_t width; + size_t height; + unsigned char mAlpha; + struct { + float m11; float m12; float m13; + float m21; float m22; float m23; + float m31; float m32; float m33; + } mMatrix; + } mImageInfo; + + int mFlag; + LOTBrushType mBrushType; + LOTFillRule mFillRule; + + const char *keypath; +} LOTNode; + + + +typedef struct LOTLayerNode { + + struct { + LOTMask *ptr; + size_t size; + } mMaskList; + + struct { + const float *ptPtr; + size_t ptCount; + const char *elmPtr; + size_t elmCount; + } mClipPath; + + struct { + struct LOTLayerNode **ptr; + size_t size; + } mLayerList; + + struct { + LOTNode **ptr; + size_t size; + } mNodeList; + + LOTMatteType mMatte; + int mVisible; + unsigned char mAlpha; + const char *keypath; + +} LOTLayerNode; + +/** + * @} + */ + +#endif // _RLOTTIE_COMMON_H_ diff --git a/example/rlottiePlayer/small.ico b/example/rlottiePlayer/small.ico new file mode 100644 index 0000000..b3ec03b Binary files /dev/null and b/example/rlottiePlayer/small.ico differ diff --git a/example/rlottiePlayer/targetver.h b/example/rlottiePlayer/targetver.h new file mode 100644 index 0000000..bf75e08 --- /dev/null +++ b/example/rlottiePlayer/targetver.h @@ -0,0 +1,6 @@ +#pragma once + +// // Including SDKDDKVer.h defines the highest available Windows platform. +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. +#include