diff --git a/CMakeLists.txt b/CMakeLists.txt index 26023963e23..72c45ccce71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ option(PAG_USE_SWIFTSHADER "allow build with SwiftShader library" OFF) option(PAG_USE_QT "allow build with QT frameworks" OFF) option(PAG_USE_RTTR "enable RTTR support" OFF) option(PAG_USE_HARFBUZZ "enable HarfBuzz support" OFF) +option(PAG_USE_C "enable c API" OFF) if (NOT APPLE AND NOT WEB) option(PAG_USE_FREETYPE "Allow use of embedded freetype library" ON) @@ -98,6 +99,7 @@ message("PAG_USE_RTTR: ${PAG_USE_RTTR}") message("PAG_USE_HARFBUZZ: ${PAG_USE_HARFBUZZ}") message("PAG_BUILD_SHARED: ${PAG_BUILD_SHARED}") message("PAG_BUILD_TESTS: ${PAG_BUILD_TESTS}") +message("PAG_USE_C: ${PAG_USE_C}") set(TGFX_USE_OPENGL ${PAG_USE_OPENGL}) set(TGFX_USE_QT ${PAG_USE_QT}) @@ -114,6 +116,11 @@ set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) add_subdirectory(tgfx/ EXCLUDE_FROM_ALL) list(APPEND PAG_INCLUDES tgfx/include) +if (PAG_USE_C) + file(GLOB_RECURSE PAG_C_FILES src/c/*.*) + list(APPEND PAG_FILES ${PAG_C_FILES}) +endif() + if (PAG_USE_LIBAVC) add_definitions(-DPAG_USE_LIBAVC) list(APPEND PAG_STATIC_VENDORS libavc) diff --git a/include/pag/c/pag.h b/include/pag/c/pag.h new file mode 100644 index 00000000000..232fa94029e --- /dev/null +++ b/include/pag/c/pag.h @@ -0,0 +1,36 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_animator.h" +#include "pag_backend_semaphore.h" +#include "pag_backend_texture.h" +#include "pag_byte_data.h" +#include "pag_composition.h" +#include "pag_decoder.h" +#include "pag_disk_cache.h" +#include "pag_file.h" +#include "pag_font.h" +#include "pag_image.h" +#include "pag_image_layer.h" +#include "pag_layer.h" +#include "pag_player.h" +#include "pag_solid_layer.h" +#include "pag_surface.h" +#include "pag_text_document.h" diff --git a/include/pag/c/pag_animator.h b/include/pag/c/pag_animator.h new file mode 100644 index 00000000000..4a3e84f8915 --- /dev/null +++ b/include/pag/c/pag_animator.h @@ -0,0 +1,54 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +/** + * Creates a new pag_animator with the specified listener. Release it by pag_release. + */ +PAG_API pag_animator* pag_animator_create(pag_animator_listener* listener, void* user); + +PAG_API bool pag_animator_is_sync(pag_animator* animator); + +PAG_API void pag_animator_set_sync(pag_animator* animator, bool sync); + +PAG_API int64_t pag_animator_get_duration(pag_animator* animator); + +PAG_API void pag_animator_set_duration(pag_animator* animator, int64_t duration); + +PAG_API int pag_animator_get_repeat_count(pag_animator* animator); + +PAG_API void pag_animator_set_repeat_count(pag_animator* animator, int repeatCount); + +PAG_API double pag_animator_get_progress(pag_animator* animator); + +PAG_API void pag_animator_set_progress(pag_animator* animator, double progress); + +PAG_API bool pag_animator_is_running(pag_animator* animator); + +PAG_API void pag_animator_start(pag_animator* animator); + +PAG_API void pag_animator_cancel(pag_animator* animator); + +PAG_API void pag_animator_update(pag_animator* animator); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_backend_semaphore.h b/include/pag/c/pag_backend_semaphore.h new file mode 100644 index 00000000000..450647552d0 --- /dev/null +++ b/include/pag/c/pag_backend_semaphore.h @@ -0,0 +1,36 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +/** + * Creates a new pag_backend_semaphore. Release it by pag_release. + */ +PAG_API pag_backend_semaphore* pag_backend_semaphore_create(); + +PAG_API bool pag_backend_semaphore_is_initialized(pag_backend_semaphore* semaphore); + +PAG_API void pag_backend_semaphore_init_gl(pag_backend_semaphore* semaphore, void* glSync); + +PAG_API void* pag_backend_semaphore_get_gl_sync(pag_backend_semaphore* semaphore); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_backend_texture.h b/include/pag/c/pag_backend_texture.h new file mode 100644 index 00000000000..8f90828ff62 --- /dev/null +++ b/include/pag/c/pag_backend_texture.h @@ -0,0 +1,41 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +/** + * Creates a new pag_backend_texture with texture info, width and height. + * Release it by pag_release. + */ +PAG_API pag_backend_texture* pag_backend_texture_create_from_gl_texture_info( + pag_gl_texture_info textureInfo, int width, int height); + +PAG_API bool pag_backend_texture_get_gl_texture_info(pag_backend_texture* texture, + pag_gl_texture_info* textureInfo); + +PAG_API bool pag_backend_texture_get_vk_image_info(pag_backend_texture* texture, + pag_vk_image_info* imageInfo); + +PAG_API bool pag_backend_texture_get_mtl_texture_info(pag_backend_texture* texture, + pag_mtl_texture_info* mtl_texture_info); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_byte_data.h b/include/pag/c/pag_byte_data.h new file mode 100644 index 00000000000..6c34cf66e31 --- /dev/null +++ b/include/pag/c/pag_byte_data.h @@ -0,0 +1,30 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +/** + * Creates a new pag_byte_data and copy the bytes and length. Release it by pag_release. + */ +PAG_API pag_byte_data* pag_byte_data_copy(const void* bytes, size_t length); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_composition.h b/include/pag/c/pag_composition.h new file mode 100644 index 00000000000..47a6e535356 --- /dev/null +++ b/include/pag/c/pag_composition.h @@ -0,0 +1,41 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +PAG_API int pag_composition_get_width(pag_composition* composition); + +PAG_API int pag_composition_get_height(pag_composition* composition); + +/** + * Returns an array of layers that match the specified layer name. Release it by pag_release. + */ +PAG_API pag_layer** pag_composition_get_layers_by_name(pag_composition* composition, + const char* layerName, size_t* count); + +/** + * Returns an array of layers that match the specified layer type. Release it by pag_release. + */ +PAG_API pag_layer** pag_composition_get_layers_by_type(pag_composition* composition, + pag_layer_type layerType, size_t* count); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_decoder.h b/include/pag/c/pag_decoder.h new file mode 100644 index 00000000000..3e39249b920 --- /dev/null +++ b/include/pag/c/pag_decoder.h @@ -0,0 +1,48 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +/** + * Creates a new pag_decoder with a pag_composition, a frame rate limit, and a scale factor for the + * decoded image size. Release it by pag_release. + */ +PAG_API pag_decoder* pag_decoder_create(pag_composition* composition, float maxFrameRate, + float scale); + +PAG_API int pag_decoder_get_width(pag_decoder* decoder); + +PAG_API int pag_decoder_get_height(pag_decoder* decoder); + +PAG_API int pag_decoder_get_num_frames(pag_decoder* decoder); + +PAG_API float pag_decoder_get_frame_rate(pag_decoder* decoder); + +PAG_API bool pag_decoder_check_frame_changed(pag_decoder* decoder, int index); + +PAG_API bool pag_decoder_read_frame(pag_decoder* decoder, int index, void* pixels, size_t rowBytes, + pag_color_type colorType, pag_alpha_type alphaType); + +PAG_API bool pag_decoder_read_frame_to_hardware_buffer(pag_decoder* decoder, int index, + void* buffer); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_disk_cache.h b/include/pag/c/pag_disk_cache.h new file mode 100644 index 00000000000..3341bcea829 --- /dev/null +++ b/include/pag/c/pag_disk_cache.h @@ -0,0 +1,31 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +PAG_API size_t pag_disk_cache_get_max_disk_size(); + +PAG_API void pag_disk_cache_set_max_disk_size(size_t maxDiskSize); + +PAG_API void pag_disk_cache_remove_all(); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_file.h b/include/pag/c/pag_file.h new file mode 100644 index 00000000000..82b4979547d --- /dev/null +++ b/include/pag/c/pag_file.h @@ -0,0 +1,66 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +/** + * Load a pag file from byte data, return null if the bytes is empty, or it's not a valid pag + * file. Release it by pag_release. + */ +PAG_API pag_file* pag_file_load(const void* bytes, size_t length, const char* filePath, + const char* password); + +PAG_API void pag_file_set_duration(pag_file* file, int64_t duration); + +PAG_API int pag_file_get_num_texts(pag_file* file); + +PAG_API int pag_file_get_num_images(pag_file* file); + +PAG_API int pag_file_get_num_videos(pag_file* file); + +PAG_API pag_time_stretch_mode pag_file_get_time_stretch_mode(pag_file* file); + +PAG_API void pag_file_set_time_stretch_mode(pag_file* file, pag_time_stretch_mode mode); + +/** + * Get a text data of the specified index. The index ranges from 0 to numTexts - 1. Release it by + * pag_release. + * Note: It always returns the default text data. + */ +PAG_API pag_text_document* pag_file_get_text_data(pag_file* file, int editableTextIndex); + +PAG_API void pag_file_replace_text(pag_file* file, int editableTextIndex, pag_text_document* text); + +PAG_API void pag_file_replace_image(pag_file* file, int editableImageIndex, pag_image* image); + +/** + * Return an array of layers by specified editable index and layer type. + * Release them by pag_release. + */ +PAG_API pag_layer** pag_file_get_layers_by_editable_index(pag_file* file, int editableIndex, + pag_layer_type layerType, + size_t* numLayers); + +PAG_API int* pag_file_get_editable_indices(pag_file* file, pag_layer_type layerType, + size_t* numIndexes); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_font.h b/include/pag/c/pag_font.h new file mode 100644 index 00000000000..307bf9fe0dd --- /dev/null +++ b/include/pag/c/pag_font.h @@ -0,0 +1,42 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +/** + * Registers a font required by the text layers in pag files, so that they can be rendered as + * designed. Release it by pag_release. + */ +PAG_API pag_font* pag_font_register_from_path(const char* filePath, int ttcIndex, + const char* fontFamily, const char* fontStyle); +/** + * Registers a font required by the text layers in pag files, so that they can be rendered as + * designed. Release it by pag_release. + */ +PAG_API pag_font* pag_font_register_from_data(const void* data, size_t length, int ttcIndex, + const char* fontFamily, const char* fontStyle); + +PAG_API const char* pag_font_get_family(pag_font* font); + +PAG_API const char* pag_font_get_style(pag_font* font); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_image.h b/include/pag/c/pag_image.h new file mode 100644 index 00000000000..9b55f5835b5 --- /dev/null +++ b/include/pag/c/pag_image.h @@ -0,0 +1,44 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +/** + * Creates a pag_image object from an array of pixel data, return null if it's not valid pixels. + * Release it by pag_release. + */ +PAG_API pag_image* pag_image_from_pixels(const void* pixels, int width, int height, size_t rowBytes, + pag_color_type colorType, pag_alpha_type alphaType); +/** + * Creates a pag_image object from a hardware buffer. Release it by pag_release. + */ +PAG_API pag_image* pag_image_from_hardware_buffer(void* buffer); + +/** + * Creates a pag_image object from the specified backend texture, return null if the texture is + * invalid. Release it by pag_release. + */ +PAG_API pag_image* pag_image_from_backend_texture(pag_backend_texture* texture); + +PAG_API void pag_image_set_scale_mode(pag_image* image, pag_scale_mode mode); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_image_layer.h b/include/pag/c/pag_image_layer.h new file mode 100644 index 00000000000..52369fed3f5 --- /dev/null +++ b/include/pag/c/pag_image_layer.h @@ -0,0 +1,28 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +PAG_API uint8_t* pag_image_layer_get_image_rgba_data(pag_layer* imageLayer, size_t* count, + size_t* width, size_t* height); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_layer.h b/include/pag/c/pag_layer.h new file mode 100644 index 00000000000..b471a3202f0 --- /dev/null +++ b/include/pag/c/pag_layer.h @@ -0,0 +1,37 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +PAG_API pag_layer_type pag_layer_get_layer_type(pag_layer* layer); + +PAG_API const char* pag_layer_get_layer_name(pag_layer* layer); + +PAG_API int64_t pag_layer_get_duration(pag_layer* layer); + +PAG_API float pag_layer_get_frame_rate(pag_layer* layer); + +PAG_API float pag_layer_get_alpha(pag_layer* layer); + +PAG_API void pag_layer_set_alpha(pag_layer* layer, float alpha); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_player.h b/include/pag/c/pag_player.h new file mode 100644 index 00000000000..4f728d83ba0 --- /dev/null +++ b/include/pag/c/pag_player.h @@ -0,0 +1,57 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +/** + * Creates a pag_player object. Release it by pag_release. + */ +PAG_API pag_player* pag_player_create(); + +PAG_API void pag_player_set_composition(pag_player* player, pag_composition* composition); + +PAG_API void pag_player_set_surface(pag_player* player, pag_surface* surface); + +PAG_API bool pag_player_get_cache_enable(pag_player* player); + +PAG_API void pag_player_set_cache_enable(pag_player* player, bool cacheEnable); + +PAG_API double pag_player_get_progress(pag_player* player); + +PAG_API void pag_player_set_progress(pag_player* player, double progress); + +PAG_API bool pag_player_wait(pag_player* player, pag_backend_semaphore* semaphore); + +PAG_API bool pag_player_flush(pag_player* player); + +PAG_API bool pag_player_flush_and_signal_semaphore(pag_player* player, + pag_backend_semaphore* semaphore); + +PAG_API pag_scale_mode pag_player_get_scale_mode(pag_player* player); + +PAG_API void pag_player_set_scale_mode(pag_player* player, pag_scale_mode scaleMode); + +PAG_API int64_t pag_player_get_duration(pag_player* player); + +PAG_API int64_t pag_player_get_graphics_memory(pag_player* player); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_solid_layer.h b/include/pag/c/pag_solid_layer.h new file mode 100644 index 00000000000..8f3a1b1b763 --- /dev/null +++ b/include/pag/c/pag_solid_layer.h @@ -0,0 +1,29 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +PAG_API pag_color pag_solid_layer_get_solid_color(pag_solid_layer* layer); + +PAG_API void pag_solid_layer_set_solid_color(pag_solid_layer* layer, pag_color color); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_surface.h b/include/pag/c/pag_surface.h new file mode 100644 index 00000000000..d315f6a58ab --- /dev/null +++ b/include/pag/c/pag_surface.h @@ -0,0 +1,54 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +/** + * Creates a new pag_surface for off-screen rendering with the specified size. + * Release it by pag_release. + */ +PAG_API pag_surface* pag_surface_make_offscreen(int width, int height); + +/** + * Creates a new pag_surface for off-screen rendering with the specified textures. + * Release it by pag_release. + */ +PAG_API pag_surface* pag_surface_make_double_buffered(int width, int height, + pag_backend_texture* frontTexture, + pag_backend_texture* backTexture); + +/** + * Creates a new pag_surface for off-screen rendering with the specified hardware buffers. + * Release it by pag_release. + */ +PAG_API pag_surface* pag_surface_make_double_buffered_with_hardware_buffer(int width, int height, + void* frontBuffer, + void* backBuffer); + +PAG_API bool pag_surface_is_front_buffer(pag_surface* surface, void* buffer); + +PAG_API bool pag_surface_is_front_texture(pag_surface* surface, pag_backend_texture* texture); + +PAG_API bool pag_surface_read_pixels(pag_surface* surface, pag_color_type colorType, + pag_alpha_type alphaType, void* dstPixels, size_t dstRowBytes); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_text_document.h b/include/pag/c/pag_text_document.h new file mode 100644 index 00000000000..173269464d9 --- /dev/null +++ b/include/pag/c/pag_text_document.h @@ -0,0 +1,119 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag_types.h" + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +PAG_API bool pag_text_document_get_apply_fill(pag_text_document* document); + +PAG_API void pag_text_document_set_apply_fill(pag_text_document* document, bool applyFill); + +PAG_API bool pag_text_document_get_apply_stroke(pag_text_document* document); + +PAG_API void pag_text_document_set_apply_stroke(pag_text_document* document, bool applyStroke); + +PAG_API float pag_text_document_get_baseline_shift(pag_text_document* document); + +PAG_API void pag_text_document_set_baseline_shift(pag_text_document* document, float baselineShift); + +PAG_API bool pag_text_document_get_box_text(pag_text_document* document); + +PAG_API void pag_text_document_set_box_text(pag_text_document* document, bool boxText); + +PAG_API pag_point pag_text_document_get_box_text_pos(pag_text_document* document); + +PAG_API void pag_text_document_set_box_text_pos(pag_text_document* document, pag_point boxTextPos); + +PAG_API pag_point pag_text_document_get_box_text_size(pag_text_document* document); + +PAG_API void pag_text_document_set_box_text_size(pag_text_document* document, + pag_point boxTextSize); + +PAG_API float pag_text_document_get_first_baseline(pag_text_document* document); + +PAG_API void pag_text_document_set_first_baseline(pag_text_document* document, float firstBaseline); + +PAG_API bool pag_text_document_get_faux_bold(pag_text_document* document); + +PAG_API void pag_text_document_set_faux_bold(pag_text_document* document, bool fauxBold); + +PAG_API bool pag_text_document_get_faux_italic(pag_text_document* document); + +PAG_API void pag_text_document_set_faux_italic(pag_text_document* document, bool fauxItalic); + +PAG_API pag_color pag_text_document_get_fill_color(pag_text_document* document); + +PAG_API void pag_text_document_set_fill_color(pag_text_document* document, pag_color fillColor); + +PAG_API const char* pag_text_document_get_font_family(pag_text_document* document); + +PAG_API void pag_text_document_set_font_family(pag_text_document* document, const char* fontFamily); + +PAG_API const char* pag_text_document_get_font_style(pag_text_document* document); + +PAG_API void pag_text_document_set_font_style(pag_text_document* document, const char* fontStyle); + +PAG_API float pag_text_document_get_font_size(pag_text_document* document); + +PAG_API void pag_text_document_set_font_size(pag_text_document* document, float fontSize); + +PAG_API pag_color pag_text_document_get_stroke_color(pag_text_document* document); + +PAG_API void pag_text_document_set_stroke_color(pag_text_document* document, pag_color strokeColor); + +PAG_API bool pag_text_document_get_stroke_over_fill(pag_text_document* document); + +PAG_API void pag_text_document_set_stroke_over_fill(pag_text_document* document, + bool strokeOverFill); + +PAG_API float pag_text_document_get_stroke_width(pag_text_document* document); + +PAG_API void pag_text_document_set_stroke_width(pag_text_document* document, float strokeWidth); + +PAG_API const char* pag_text_document_get_text(pag_text_document* document); + +PAG_API void pag_text_document_set_text(pag_text_document* document, const char* text); + +PAG_API pag_paragraph_justification +pag_text_document_get_justification(pag_text_document* document); + +PAG_API void pag_text_document_set_justification(pag_text_document* document, + pag_paragraph_justification justification); + +PAG_API float pag_text_document_get_leading(pag_text_document* document); + +PAG_API void pag_text_document_set_leading(pag_text_document* document, float leading); + +PAG_API float pag_text_document_get_tracking(pag_text_document* document); + +PAG_API void pag_text_document_set_tracking(pag_text_document* document, float tracking); + +PAG_API pag_color pag_text_document_get_background_color(pag_text_document* document); + +PAG_API void pag_text_document_set_background_color(pag_text_document* document, + pag_color backgroundColor); + +PAG_API uint8_t pag_text_document_get_background_alpha(pag_text_document* document); + +PAG_API void pag_text_document_set_background_alpha(pag_text_document* document, + uint8_t backgroundAlpha); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/include/pag/c/pag_types.h b/include/pag/c/pag_types.h new file mode 100644 index 00000000000..67b4b30415f --- /dev/null +++ b/include/pag/c/pag_types.h @@ -0,0 +1,151 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include "pag/defines.h" + +#ifdef __cplusplus +#define PAG_C_PLUS_PLUS_BEGIN_GUARD extern "C" { +#define PAG_C_PLUS_PLUS_END_GUARD } +#else +#define PAG_C_PLUS_PLUS_BEGIN_GUARD +#define PAG_C_PLUS_PLUS_END_GUARD +#endif + +PAG_C_PLUS_PLUS_BEGIN_GUARD + +typedef enum { + pag_time_stretch_mode_none, + pag_time_stretch_mode_scale, + pag_time_stretch_mode_repeat, + pag_time_stretch_mode_repeat_inverted, +} pag_time_stretch_mode; + +typedef enum { + pag_color_type_unknown, + pag_color_type_alpha_8, + pag_color_type_rgba_8888, + pag_color_type_bgra_8888, + pag_color_type_rgb_565, + pag_color_type_gray_8, + pag_color_type_rgba_f16, + pag_color_type_rgba_101012, +} pag_color_type; + +typedef enum { + pag_alpha_type_unknown, + pag_alpha_type_opaque, + pag_alpha_type_premultiplied, + pag_alpha_type_unpremultiplied, +} pag_alpha_type; + +typedef enum { + pag_scale_mode_none, + pag_scale_mode_stretch, + pag_scale_mode_letter_box, + pag_scale_mode_zoom, +} pag_scale_mode; + +typedef enum { + pag_layer_type_unknown, + pag_layer_type_null, + pag_layer_type_solid, + pag_layer_type_text, + pag_layer_type_shape, + pag_layer_type_image, + pag_layer_type_pre_compose, + pag_layer_type_camera, +} pag_layer_type; + +typedef struct pag_gl_texture_info { + unsigned id = 0; + unsigned target = 0x0DE1; // GL_TEXTURE_2D; + unsigned format = 0x8058; // GL_RGBA8; +} pag_gl_texture_info; + +typedef struct pag_vk_image_info { + void* image = nullptr; +} pag_vk_image_info; + +typedef struct pag_mtl_texture_info { + void* texture = nullptr; +} pag_mtl_texture_info; + +typedef struct pag_point { + float x; + float y; +} pag_point; + +typedef struct pag_color { + uint8_t red; + uint8_t green; + uint8_t blue; +} pag_color; + +typedef enum { + pag_paragraph_justification_left_justify, + pag_paragraph_justification_center_justify, + pag_paragraph_justification_right_justify, + pag_paragraph_justification_full_justify_last_line_left, + pag_paragraph_justification_full_justify_last_line_right, + pag_paragraph_justification_full_justify_last_line_center, + pag_paragraph_justification_full_justify_last_line_full, +} pag_paragraph_justification; + +typedef struct pag_display_link_functions { + void* (*create)(void* user, void (*callback)(void* user)); + void (*start)(void* displayLink); + void (*stop)(void* displayLink); + void (*release)(void* displayLink); +} pag_display_link_functions; + +typedef const void* pag_object; +typedef struct pag_byte_data pag_byte_data; +typedef struct pag_text_document pag_text_document; +typedef struct pag_layer pag_layer; +typedef pag_layer pag_solid_layer; +typedef pag_layer pag_composition; +typedef pag_composition pag_file; +typedef struct pag_player pag_player; +typedef struct pag_surface pag_surface; +typedef struct pag_image pag_image; +typedef struct pag_font pag_font; +typedef struct pag_backend_texture pag_backend_texture; +typedef struct pag_backend_semaphore pag_backend_semaphore; +typedef struct pag_decoder PAGDecoder; +typedef struct pag_animator pag_animator; + +typedef struct pag_animator_listener { + void (*on_animation_start)(pag_animator* animator, void* user); + void (*on_animation_end)(pag_animator* animator, void* user); + void (*on_animation_cancel)(pag_animator* animator, void* user); + void (*on_animation_repeat)(pag_animator* animator, void* user); + void (*on_animation_update)(pag_animator* animator, void* user); +} pag_animator_listener; + +/** + * Release a pag_object. + */ +PAG_API void pag_release(pag_object object); + +PAG_API void pag_display_link_set_functions(pag_display_link_functions* functions); + +PAG_C_PLUS_PLUS_END_GUARD diff --git a/libpag.podspec b/libpag.podspec index 5f9bf885d52..337fedb419a 100644 --- a/libpag.podspec +++ b/libpag.podspec @@ -26,6 +26,33 @@ else system("node build_vendor #{vendorNames} -o #{PAG_ROOT}/ios/Pods/pag-vendor -p ios --xcframework") end +iosSourceFiles = ['src/platform/ios/*.{h,cpp,mm,m}', + 'src/platform/ios/private/*.{h,cpp,mm,m}', + 'src/platform/cocoa/**/*.{h,cpp,mm,m}', + 'tgfx/src/opengl/eagl/*.{h,cpp,mm}', + 'tgfx/src/platform/apple/**/*.{h,cpp,mm,m}'] + +if ENV["PAG_USE_QT"] == 'ON' + macSourceFiles = ['src/platform/qt/**/*.{h,cpp,mm,m}', + 'tgfx/src/platform/apple/*.{h,cpp,m,mm}', + 'tgfx/src/opengl/qt/*.{h,cpp,mm}', + 'tgfx/src/opengl/cgl/CGLHardwareTexture.mm', + 'src/platform/mac/private/HardwareDecoder.mm'] +else + macSourceFiles = ['src/platform/mac/**/*.{h,cpp,mm,m}', + 'src/platform/cocoa/**/*.{h,cpp,mm,m}', + 'tgfx/src/opengl/cgl/*.{h,cpp,mm}', + 'tgfx/src/platform/apple/**/*.{h,cpp,mm,m}'] +end + +cSourceFiles = [] +if ENV["PAG_USE_C"] == 'ON' + commonCFlags += ["-DPAG_USE_C"] + cSourceFiles += ["src/c/*.*"] + iosSourceFiles += ["src/c/*.{h,cpp,mm,m}"] + macSourceFiles += ["src/c/*.{h,cpp,mm,m}"] +end + Pod::Spec.new do |s| s.name = 'libpag' s.version = '4.0.0' @@ -63,25 +90,18 @@ Pod::Spec.new do |s| 'tgfx/src/platform/*.{h,cpp}', 'tgfx/src/codecs/webp/**/*.{h,cpp,mm}' - s.source_files = $source_files + $rasterSourceFiles; + s.source_files = $source_files + $rasterSourceFiles + cSourceFiles; s.compiler_flags = '-Wno-documentation' if ENV["PAG_USE_QT"] == 'ON' s.osx.public_header_files = ['src/platform/qt/*.h', 'tgfx/src/opengl/*.h'] - s.osx.source_files = 'src/platform/qt/**/*.{h,cpp,mm,m}', - 'tgfx/src/platform/apple/*.{h,cpp,m,mm}', - 'tgfx/src/opengl/qt/*.{h,cpp,mm}', - 'tgfx/src/opengl/cgl/CGLHardwareTexture.mm', - 'src/platform/mac/private/HardwareDecoder.mm' else s.osx.public_header_files = 'src/platform/mac/*.h', 'src/platform/cocoa/*.h' - s.osx.source_files = 'src/platform/mac/**/*.{h,cpp,mm,m}', - 'src/platform/cocoa/**/*.{h,cpp,mm,m}', - 'tgfx/src/opengl/cgl/*.{h,cpp,mm}', - 'tgfx/src/platform/apple/**/*.{h,cpp,mm,m}' end + + s.osx.source_files = macSourceFiles s.osx.frameworks = ['ApplicationServices', 'AGL', 'OpenGL', 'QuartzCore', 'Cocoa', 'Foundation', 'VideoToolbox', 'CoreMedia'] s.osx.libraries = ["iconv", "c++", "compression"] @@ -89,17 +109,13 @@ Pod::Spec.new do |s| s.ios.public_header_files = 'src/platform/ios/*.h', 'src/platform/cocoa/*.h' - s.ios.source_files = 'src/platform/ios/*.{h,cpp,mm,m}', - 'src/platform/ios/private/*.{h,cpp,mm,m}', - 'src/platform/cocoa/**/*.{h,cpp,mm,m}', - 'tgfx/src/opengl/eagl/*.{h,cpp,mm}', - 'tgfx/src/platform/apple/**/*.{h,cpp,mm,m}' + s.ios.source_files = iosSourceFiles s.ios.frameworks = ['UIKit', 'CoreFoundation', 'QuartzCore', 'CoreGraphics', 'CoreText', 'OpenGLES', 'VideoToolbox', 'CoreMedia'] s.ios.libraries = ["iconv", "compression"] armv7CFlags = commonCFlags + ["-fno-aligned-allocation"] - s.xcconfig = {'CLANG_CXX_LANGUAGE_STANDARD' => 'c++17','CLANG_CXX_LIBRARY' => 'libc++',"HEADER_SEARCH_PATHS" => "#{PAG_ROOT}/src #{PAG_ROOT}/include #{PAG_ROOT}/tgfx/src #{PAG_ROOT}/tgfx/include #{PAG_ROOT}/third_party/pathkit #{PAG_ROOT}/third_party/skcms #{PAG_ROOT}/third_party/freetype/include #{PAG_ROOT}/third_party/libwebp/src #{PAG_ROOT}/third_party/libavc/common #{PAG_ROOT}/third_party/libavc/decoder"} + s.xcconfig = {'CLANG_CXX_LANGUAGE_STANDARD' => 'c++17','CLANG_CXX_LIBRARY' => 'libc++',"HEADER_SEARCH_PATHS" => "#{PAG_ROOT}/src #{PAG_ROOT}/include #{PAG_ROOT}/src/c #{PAG_ROOT}/tgfx/src #{PAG_ROOT}/tgfx/include #{PAG_ROOT}/third_party/pathkit #{PAG_ROOT}/third_party/skcms #{PAG_ROOT}/third_party/freetype/include #{PAG_ROOT}/third_party/libwebp/src #{PAG_ROOT}/third_party/libavc/common #{PAG_ROOT}/third_party/libavc/decoder"} s.ios.xcconfig = {"OTHER_CFLAGS" => commonCFlags.join(" "),"OTHER_CFLAGS[sdk=iphoneos*][arch=armv7]" => armv7CFlags.join(" "),"EXPORTED_SYMBOLS_FILE" => "${PODS_ROOT}/../libpag.lds","OTHER_LDFLAGS" => "-w -ld64","VALIDATE_WORKSPACE_SKIPPED_SDK_FRAMEWORKS" => "OpenGLES"} s.osx.xcconfig = {"OTHER_CFLAGS" => commonCFlags.join(" ")} s.ios.vendored_frameworks = 'ios/Pods/pag-vendor/libpag-vendor.xcframework' diff --git a/src/c/PAGAnimator.cpp b/src/c/PAGAnimator.cpp new file mode 100644 index 00000000000..90f0f13a3b4 --- /dev/null +++ b/src/c/PAGAnimator.cpp @@ -0,0 +1,165 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "rendering/PAGAnimator.h" +#include "PAGTypesPriv.h" +#include "pag/c/pag_animator.h" + +class PAGAnimatorListenerWrapper : public pag::PAGAnimator::Listener { + public: + static std::shared_ptr Make(pag_animator_listener* listener, + void* user) { + if (listener) { + return std::shared_ptr( + new PAGAnimatorListenerWrapper(listener, user)); + } + return nullptr; + } + + void onAnimationStart(pag::PAGAnimator*) override { + listener->on_animation_start(_animator, user); + } + + void onAnimationEnd(pag::PAGAnimator*) override { + listener->on_animation_end(_animator, user); + } + + void onAnimationCancel(pag::PAGAnimator*) override { + listener->on_animation_cancel(_animator, user); + } + + void onAnimationRepeat(pag::PAGAnimator*) override { + listener->on_animation_repeat(_animator, user); + } + + void onAnimationUpdate(pag::PAGAnimator*) override { + listener->on_animation_update(_animator, user); + } + + void setAnimator(pag_animator* animator) { + _animator = animator; + } + + private: + PAGAnimatorListenerWrapper(pag_animator_listener* listener, void* user) + : listener(listener), user(user) { + } + + pag_animator* _animator = nullptr; + pag_animator_listener* listener = nullptr; + void* user = nullptr; +}; + +pag_animator* pag_animator_create(pag_animator_listener* listener, void* user) { + auto wrapper = PAGAnimatorListenerWrapper::Make(listener, user); + if (wrapper == nullptr) { + return nullptr; + } + if (auto animator = pag::PAGAnimator::MakeFrom(wrapper)) { + auto* ret = new pag_animator(); + wrapper->setAnimator(ret); + ret->p = std::move(animator); + ret->listener = std::move(wrapper); + return ret; + } + return nullptr; +} + +bool pag_animator_is_sync(pag_animator* animator) { + if (animator == nullptr) { + return false; + } + return animator->p->isSync(); +} + +void pag_animator_set_sync(pag_animator* animator, bool sync) { + if (animator == nullptr) { + return; + } + animator->p->setSync(sync); +} + +int64_t pag_animator_get_duration(pag_animator* animator) { + if (animator == nullptr) { + return 0; + } + return animator->p->duration(); +} + +void pag_animator_set_duration(pag_animator* animator, int64_t duration) { + if (animator == nullptr) { + return; + } + animator->p->setDuration(duration); +} + +int pag_animator_get_repeat_count(pag_animator* animator) { + if (animator == nullptr) { + return 0; + } + return animator->p->repeatCount(); +} + +void pag_animator_set_repeat_count(pag_animator* animator, int repeatCount) { + if (animator == nullptr) { + return; + } + animator->p->setRepeatCount(repeatCount); +} + +double pag_animator_get_progress(pag_animator* animator) { + if (animator == nullptr) { + return 0; + } + return animator->p->progress(); +} + +void pag_animator_set_progress(pag_animator* animator, double progress) { + if (animator == nullptr) { + return; + } + animator->p->setProgress(progress); +} + +bool pag_animator_is_running(pag_animator* animator) { + if (animator == nullptr) { + return false; + } + return animator->p->isRunning(); +} + +void pag_animator_start(pag_animator* animator) { + if (animator == nullptr) { + return; + } + animator->p->start(); +} + +void pag_animator_cancel(pag_animator* animator) { + if (animator == nullptr) { + return; + } + animator->p->cancel(); +} + +void pag_animator_update(pag_animator* animator) { + if (animator == nullptr) { + return; + } + animator->p->update(); +} diff --git a/src/c/PAGBackendSemaphore.cpp b/src/c/PAGBackendSemaphore.cpp new file mode 100644 index 00000000000..12c73f9fa09 --- /dev/null +++ b/src/c/PAGBackendSemaphore.cpp @@ -0,0 +1,45 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "PAGTypesPriv.h" +#include "pag/c/pag_backend_semaphore.h" + +pag_backend_semaphore* pag_backend_semaphore_create() { + return new pag_backend_semaphore(); +} + +bool pag_backend_semaphore_is_initialized(pag_backend_semaphore* semaphore) { + if (semaphore == nullptr) { + return false; + } + return semaphore->p.isInitialized(); +} + +void pag_backend_semaphore_init_gl(pag_backend_semaphore* semaphore, void* glSync) { + if (semaphore == nullptr) { + return; + } + semaphore->p.initGL(glSync); +} + +void* pag_backend_semaphore_get_gl_sync(pag_backend_semaphore* semaphore) { + if (semaphore == nullptr) { + return nullptr; + } + return semaphore->p.glSync(); +} diff --git a/src/c/PAGBackendTexture.cpp b/src/c/PAGBackendTexture.cpp new file mode 100644 index 00000000000..868615819c1 --- /dev/null +++ b/src/c/PAGBackendTexture.cpp @@ -0,0 +1,73 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "PAGTypesPriv.h" +#include "pag/c/pag_backend_texture.h" + +using namespace pag; + +pag_backend_texture* pag_backend_texture_create_from_gl_texture_info( + pag_gl_texture_info textureInfo, int width, int height) { + pag::GLTextureInfo info; + info.id = textureInfo.id; + info.target = textureInfo.target; + info.format = textureInfo.format; + pag::BackendTexture backendTexture(info, width, height); + return new pag_backend_texture(backendTexture); +} + +bool pag_backend_texture_get_gl_texture_info(pag_backend_texture* texture, + pag_gl_texture_info* textureInfo) { + if (texture == nullptr || textureInfo == nullptr) { + return false; + } + GLTextureInfo info; + if (texture->p.getGLTextureInfo(&info)) { + textureInfo->id = info.id; + textureInfo->target = info.target; + textureInfo->format = info.format; + return true; + } + return false; +} + +bool pag_backend_texture_get_vk_image_info(pag_backend_texture* texture, + pag_vk_image_info* imageInfo) { + if (texture == nullptr || imageInfo == nullptr) { + return false; + } + VkImageInfo info; + if (texture->p.getVkImageInfo(&info)) { + imageInfo->image = info.image; + return true; + } + return false; +} + +bool pag_backend_texture_get_mtl_texture_info(pag_backend_texture* texture, + pag_mtl_texture_info* mtl_texture_info) { + if (texture == nullptr || mtl_texture_info == nullptr) { + return false; + } + MtlTextureInfo info; + if (texture->p.getMtlTextureInfo(&info)) { + mtl_texture_info->texture = info.texture; + return true; + } + return false; +} diff --git a/src/c/PAGByteData.cpp b/src/c/PAGByteData.cpp new file mode 100644 index 00000000000..1d77e912343 --- /dev/null +++ b/src/c/PAGByteData.cpp @@ -0,0 +1,29 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "PAGTypesPriv.h" +#include "pag/c/pag_byte_data.h" + +using namespace pag; + +pag_byte_data* pag_byte_data_copy(const void* bytes, size_t length) { + if (auto data = ByteData::MakeCopy(bytes, length)) { + return new pag_byte_data(std::move(data)); + } + return nullptr; +} diff --git a/src/c/PAGComposition.cpp b/src/c/PAGComposition.cpp new file mode 100644 index 00000000000..532e502e06f --- /dev/null +++ b/src/c/PAGComposition.cpp @@ -0,0 +1,110 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "PAGTypesPriv.h" +#include "pag/c/pag_composition.h" + +PAG_API int pag_composition_get_width(pag_composition* composition) { + auto p = ToPAGComposition(composition); + if (p == nullptr) { + return 0; + } + return p->width(); +} + +PAG_API int pag_composition_get_height(pag_composition* composition) { + auto p = ToPAGComposition(composition); + if (p == nullptr) { + return 0; + } + return p->height(); +} + +pag_layer** pag_composition_get_layers_by_name(pag_composition* composition, const char* layerName, + size_t* count) { + auto p = ToPAGComposition(composition); + if (p == nullptr) { + return nullptr; + } + auto pagLayers = p->getLayersByName(layerName); + if (pagLayers.empty()) { + return nullptr; + } + auto** layers = static_cast(malloc(sizeof(pag_layer*) * pagLayers.size())); + if (layers == nullptr) { + return nullptr; + } + for (size_t i = 0; i < pagLayers.size(); ++i) { + layers[i] = new pag_layer(std::move(pagLayers[i])); + } + *count = pagLayers.size(); + return layers; +} + +static void PAGCompositionFindLayers(const std::function& filterFunc, + std::vector>* result, + std::shared_ptr pagLayer) { + if (filterFunc(pagLayer.get())) { + result->push_back(pagLayer); + } + if (pagLayer->trackMatteLayer()) { + PAGCompositionFindLayers(filterFunc, result, pagLayer->trackMatteLayer()); + } + if (pagLayer->layerType() == pag::LayerType::PreCompose) { + auto* composition = static_cast(pagLayer.get()); + auto count = composition->numChildren(); + for (int i = 0; i < count; ++i) { + auto childLayer = composition->getLayerAt(i); + PAGCompositionFindLayers(filterFunc, result, childLayer); + } + } +} + +static std::vector> PAGCompositionGetLayersBy( + const std::function& filterFunc, + std::shared_ptr pagLayer) { + std::vector> result = {}; + PAGCompositionFindLayers(filterFunc, &result, pagLayer); + return result; +} + +pag_layer** pag_composition_get_layers_by_type(pag_composition* composition, + pag_layer_type layerType, size_t* count) { + auto p = ToPAGComposition(composition); + if (p == nullptr) { + return nullptr; + } + + pag::LayerType pagLayerType; + FromCLayerType(layerType, &pagLayerType); + + auto pagLayers = PAGCompositionGetLayersBy( + [=](pag::PAGLayer* pagLayer) -> bool { return pagLayer->layerType() == pagLayerType; }, p); + if (pagLayers.empty()) { + return nullptr; + } + auto** layers = static_cast(malloc(sizeof(pag_layer*) * pagLayers.size())); + if (layers == nullptr) { + return nullptr; + } + for (size_t i = 0; i < pagLayers.size(); ++i) { + layers[i] = new pag_layer(std::move(pagLayers[i])); + } + *count = pagLayers.size(); + return layers; +} diff --git a/src/c/PAGDecoder.cpp b/src/c/PAGDecoder.cpp new file mode 100644 index 00000000000..0026687482d --- /dev/null +++ b/src/c/PAGDecoder.cpp @@ -0,0 +1,93 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "PAGTypesPriv.h" +#include "pag/c/pag_decoder.h" + +pag_decoder* pag_decoder_create(pag_composition* composition, float maxFrameRate, float scale) { + if (composition == nullptr) { + return nullptr; + } + if (auto pagComposition = ToPAGComposition(composition)) { + if (auto decoder = pag::PAGDecoder::MakeFrom(pagComposition, maxFrameRate, scale)) { + return new pag_decoder(std::move(decoder)); + } + } + return nullptr; +} + +int pag_decoder_get_width(pag_decoder* decoder) { + if (decoder == nullptr) { + return 0; + } + return decoder->p->width(); +} + +int pag_decoder_get_height(pag_decoder* decoder) { + if (decoder == nullptr) { + return 0; + } + return decoder->p->height(); +} + +int pag_decoder_get_num_frames(pag_decoder* decoder) { + if (decoder == nullptr) { + return 0; + } + return decoder->p->numFrames(); +} + +float pag_decoder_get_frame_rate(pag_decoder* decoder) { + if (decoder == nullptr) { + return 0.0f; + } + return decoder->p->frameRate(); +} + +bool pag_decoder_check_frame_changed(pag_decoder* decoder, int index) { + if (decoder == nullptr) { + return false; + } + return decoder->p->checkFrameChanged(index); +} + +bool pag_decoder_read_frame(pag_decoder* decoder, int index, void* pixels, size_t rowBytes, + pag_color_type colorType, pag_alpha_type alphaType) { + if (decoder == nullptr) { + return false; + } + pag::ColorType color; + if (!FromCColorType(colorType, &color)) { + return false; + } + pag::AlphaType alpha; + if (!FromCAlphaType(alphaType, &alpha)) { + return false; + } + return decoder->p->readFrame(index, pixels, rowBytes, color, alpha); +} + +bool pag_decoder_read_frame_to_hardware_buffer(pag_decoder* decoder, int index, void* buffer) { + if (decoder == nullptr) { + return false; + } + if (buffer == nullptr) { + return false; + } + return decoder->p->readFrame(index, static_cast(buffer)); +} diff --git a/src/c/PAGDiskCache.cpp b/src/c/PAGDiskCache.cpp new file mode 100644 index 00000000000..e3276ed6b7d --- /dev/null +++ b/src/c/PAGDiskCache.cpp @@ -0,0 +1,32 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "pag/c/pag_disk_cache.h" +#include "pag/pag.h" + +size_t pag_disk_cache_get_max_disk_size() { + return pag::PAGDiskCache::MaxDiskSize(); +} + +void pag_disk_cache_set_max_disk_size(size_t maxDiskSize) { + pag::PAGDiskCache::SetMaxDiskSize(maxDiskSize); +} + +void pag_disk_cache_remove_all() { + pag::PAGDiskCache::RemoveAll(); +} diff --git a/src/c/PAGFile.cpp b/src/c/PAGFile.cpp new file mode 100644 index 00000000000..b065d63c6c0 --- /dev/null +++ b/src/c/PAGFile.cpp @@ -0,0 +1,170 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "PAGTypesPriv.h" +#include "pag/c/pag_file.h" + +pag_file* pag_file_load(const void* bytes, size_t length, const char* filePath, + const char* password) { + std::string path(filePath); + std::string pwd(password); + if (auto file = pag::PAGFile::Load(bytes, length, path, pwd)) { + return new pag_file(std::move(file)); + } + return nullptr; +} + +void pag_file_set_duration(pag_file* file, int64_t duration) { + auto pagFile = ToPAGFile(file); + if (pagFile == nullptr) { + return; + } + pagFile->setDuration(duration); +} + +int pag_file_get_num_texts(pag_file* file) { + auto pagFile = ToPAGFile(file); + if (pagFile == nullptr) { + return 0; + } + return pagFile->numTexts(); +} + +int pag_file_get_num_images(pag_file* file) { + auto pagFile = ToPAGFile(file); + if (pagFile == nullptr) { + return 0; + } + return pagFile->numImages(); +} + +int pag_file_get_num_videos(pag_file* file) { + auto pagFile = ToPAGFile(file); + if (pagFile == nullptr) { + return 0; + } + return pagFile->numVideos(); +} + +pag_time_stretch_mode pag_file_get_time_stretch_mode(pag_file* file) { + auto pagFile = ToPAGFile(file); + if (pagFile == nullptr) { + return pag_time_stretch_mode_none; + } + pag_time_stretch_mode mode; + if (ToCTimeStretchMode(pagFile->timeStretchMode(), &mode)) { + return mode; + } + return pag_time_stretch_mode_none; +} + +void pag_file_set_time_stretch_mode(pag_file* file, pag_time_stretch_mode mode) { + auto pagFile = ToPAGFile(file); + if (pagFile == nullptr) { + return; + } + pag::Enum pagMode; + if (FromCTimeStretchMode(mode, &pagMode)) { + pagFile->setTimeStretchMode(pagMode); + } +} + +pag_text_document* pag_file_get_text_data(pag_file* file, int editableTextIndex) { + auto pagFile = ToPAGFile(file); + if (pagFile == nullptr) { + return nullptr; + } + if (auto text = pagFile->getTextData(editableTextIndex)) { + return new pag_text_document(std::move(text)); + } + return nullptr; +} + +void pag_file_replace_text(pag_file* file, int editableTextIndex, pag_text_document* text) { + auto pagFile = ToPAGFile(file); + if (pagFile == nullptr) { + return; + } + if (text) { + pagFile->replaceText(editableTextIndex, text->p); + } else { + pagFile->replaceText(editableTextIndex, nullptr); + } +} + +void pag_file_replace_image(pag_file* file, int editableImageIndex, pag_image* image) { + auto pagFile = ToPAGFile(file); + if (pagFile == nullptr) { + return; + } + if (image) { + pagFile->replaceImage(editableImageIndex, image->p); + } else { + pagFile->replaceImage(editableImageIndex, nullptr); + } +} + +pag_layer** pag_file_get_layers_by_editable_index(pag_file* file, int editableIndex, + pag_layer_type layerType, size_t* numLayers) { + auto pagFile = ToPAGFile(file); + if (pagFile == nullptr) { + return nullptr; + } + + pag::LayerType pagLayerType; + FromCLayerType(layerType, &pagLayerType); + + auto pagLayers = pagFile->getLayersByEditableIndex(editableIndex, pagLayerType); + if (pagLayers.empty()) { + return nullptr; + } + auto** layers = static_cast(malloc(sizeof(pag_layer*) * pagLayers.size())); + if (layers == nullptr) { + return nullptr; + } + for (size_t i = 0; i < pagLayers.size(); ++i) { + layers[i] = new pag_layer(std::move(pagLayers[i])); + } + *numLayers = pagLayers.size(); + return layers; +} + +PAG_API int* pag_file_get_editable_indices(pag_file* file, pag_layer_type layerType, + size_t* numIndexes) { + auto pagFile = ToPAGFile(file); + if (pagFile == nullptr) { + return nullptr; + } + + pag::LayerType pagLayerType; + FromCLayerType(layerType, &pagLayerType); + + auto indexes = pagFile->getEditableIndices(pagLayerType); + if (indexes.empty()) { + return nullptr; + } + int* editableIndexes = static_cast(malloc(sizeof(int) * indexes.size())); + if (editableIndexes == nullptr) { + return nullptr; + } + for (size_t i = 0; i < indexes.size(); ++i) { + editableIndexes[i] = indexes[i]; + } + *numIndexes = indexes.size(); + return editableIndexes; +} diff --git a/src/c/PAGFont.cpp b/src/c/PAGFont.cpp new file mode 100644 index 00000000000..643474b6fa6 --- /dev/null +++ b/src/c/PAGFont.cpp @@ -0,0 +1,53 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "PAGTypesPriv.h" +#include "pag/c/pag_font.h" + +pag_font* pag_font_register_from_path(const char* filePath, int ttcIndex, const char* fontFamily, + const char* fontStyle) { + std::string path(filePath); + std::string family(fontFamily); + std::string style(fontStyle); + return new pag_font(pag::PAGFont::RegisterFont(path, ttcIndex, family, style)); +} + +pag_font* pag_font_register_from_data(const void* data, size_t length, int ttcIndex, + const char* fontFamily, const char* fontStyle) { + std::string family(fontFamily); + std::string style(fontStyle); + return new pag_font(pag::PAGFont::RegisterFont(data, length, ttcIndex, family, style)); +} + +const char* pag_font_get_family(pag_font* font) { + if (font == nullptr || font->p.fontFamily.empty()) { + return nullptr; + } + return font->p.fontFamily.c_str(); +} + +const char* pag_font_get_style(pag_font* font) { + if (font == nullptr || font->p.fontStyle.empty()) { + return nullptr; + } + return font->p.fontStyle.c_str(); +} + +void PAGFontRelease(pag_font* font) { + delete font; +} diff --git a/src/c/PAGImage.cpp b/src/c/PAGImage.cpp new file mode 100644 index 00000000000..77cc165c123 --- /dev/null +++ b/src/c/PAGImage.cpp @@ -0,0 +1,66 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "PAGTypesPriv.h" +#include "pag/c/pag_image.h" +#include "rendering/editing/StillImage.h" +#include "tgfx/core/Image.h" + +pag_image* pag_image_from_pixels(const void* pixels, int width, int height, size_t rowBytes, + pag_color_type colorType, pag_alpha_type alphaType) { + pag::ColorType color; + if (!FromCColorType(colorType, &color)) { + return nullptr; + } + pag::AlphaType alpha; + if (!FromCAlphaType(alphaType, &alpha)) { + return nullptr; + } + if (auto image = pag::PAGImage::FromPixels(pixels, width, height, rowBytes, color, alpha)) { + return new pag_image(std::move(image)); + } + return nullptr; +} + +pag_image* pag_image_from_hardware_buffer(void* buffer) { + if (buffer == nullptr) { + return nullptr; + } + if (auto image = pag::StillImage::MakeFrom( + tgfx::Image::MakeFrom(static_cast(buffer)))) { + return new pag_image(std::move(image)); + } + return nullptr; +} + +pag_image* pag_image_from_backend_texture(pag_backend_texture* texture) { + if (texture == nullptr) { + return nullptr; + } + if (auto image = pag::PAGImage::FromTexture(texture->p, pag::ImageOrigin::TopLeft)) { + return new pag_image(std::move(image)); + } + return nullptr; +} + +void pag_image_set_scale_mode(pag_image* image, pag_scale_mode mode) { + if (image == nullptr) { + return; + } + image->p->setScaleMode(static_cast(mode)); +} diff --git a/src/c/PAGImageLayer.cpp b/src/c/PAGImageLayer.cpp new file mode 100644 index 00000000000..262b5768612 --- /dev/null +++ b/src/c/PAGImageLayer.cpp @@ -0,0 +1,50 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "PAGTypesPriv.h" +#include "pag/c/pag_image.h" +#include "pag/c/pag_image_layer.h" +#include "tgfx/core/ImageCodec.h" +#include "tgfx/core/ImageInfo.h" + +uint8_t* pag_image_layer_get_image_rgba_data(pag_layer* imageLayer, size_t* count, size_t* width, + size_t* height) { + if (imageLayer == nullptr) { + return nullptr; + } + std::shared_ptr imgLayer = + std::static_pointer_cast(imageLayer->p); + if (!imgLayer) { + return nullptr; + } + pag::ByteData* imageBytes = imgLayer->imageBytes(); + auto data = tgfx::Data::MakeWithoutCopy(imageBytes->data(), imageBytes->length()); + std::shared_ptr webp = tgfx::ImageCodec::MakeFrom(data); + auto info = tgfx::ImageInfo::Make(webp->width(), webp->height(), tgfx::ColorType::RGBA_8888, + tgfx::AlphaType::Premultiplied); + *count = 4 * webp->width() * webp->height(); + *width = webp->width(); + *height = webp->height(); + auto rgbaData = new uint8_t[*count]; + auto success = webp->readPixels(info, rgbaData); + if (success) { + return rgbaData; + } else { + return nullptr; + } +} diff --git a/src/c/PAGLayer.cpp b/src/c/PAGLayer.cpp new file mode 100644 index 00000000000..3c8ab984331 --- /dev/null +++ b/src/c/PAGLayer.cpp @@ -0,0 +1,71 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "PAGTypesPriv.h" +#include "pag/c/pag_layer.h" + +PAG_API pag_layer_type pag_layer_get_layer_type(pag_layer* layer) { + if (layer == nullptr) { + return pag_layer_type_unknown; + } + pag_layer_type type = pag_layer_type_unknown; + if (TocLayerType(layer->p->layerType(), &type)) { + return type; + } + return pag_layer_type_unknown; +} + +const char* pag_layer_get_layer_name(pag_layer* layer) { + if (layer == nullptr) { + return nullptr; + } + auto layerName = layer->p->layerName(); + auto length = layerName.length(); + auto name = malloc(sizeof(char) * (length + 1)); + memset(name, 0, length + 1); + memcpy(name, layerName.c_str(), length); + return static_cast(name); +} + +int64_t pag_layer_get_duration(pag_layer* layer) { + if (layer == nullptr) { + return 0; + } + return layer->p->duration(); +} + +float pag_layer_get_frame_rate(pag_layer* layer) { + if (layer == nullptr) { + return 0; + } + return layer->p->frameRate(); +} + +float pag_layer_get_alpha(pag_layer* layer) { + if (layer == nullptr) { + return 1.0f; + } + return layer->p->alpha(); +} + +void pag_layer_set_alpha(pag_layer* layer, float alpha) { + if (layer == nullptr) { + return; + } + layer->p->setAlpha(alpha); +} diff --git a/src/c/PAGPlayer.cpp b/src/c/PAGPlayer.cpp new file mode 100644 index 00000000000..f5c105517bf --- /dev/null +++ b/src/c/PAGPlayer.cpp @@ -0,0 +1,137 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "PAGTypesPriv.h" +#include "pag/c/pag_player.h" + +pag_player* pag_player_create() { + return new pag_player(std::make_shared()); +} + +void PAGPlayerRelease(pag_player* player) { + delete player; +} + +void pag_player_set_composition(pag_player* player, pag_composition* composition) { + if (player == nullptr) { + return; + } + if (auto pagComposition = ToPAGComposition(composition)) { + player->p->setComposition(pagComposition); + } else { + player->p->setComposition(nullptr); + } +} + +void pag_player_set_surface(pag_player* player, pag_surface* surface) { + if (player == nullptr) { + return; + } + if (surface) { + player->p->setSurface(surface->p); + } else { + player->p->setSurface(nullptr); + } +} + +bool pag_player_get_cache_enable(pag_player* player) { + if (player == nullptr) { + return false; + } + return player->p->cacheEnabled(); +} + +void pag_player_set_cache_enable(pag_player* player, bool cacheEnable) { + if (player == nullptr) { + return; + } + player->p->setCacheEnabled(cacheEnable); +} + +double pag_player_get_progress(pag_player* player) { + if (player == nullptr) { + return 0.0; + } + return player->p->getProgress(); +} + +void pag_player_set_progress(pag_player* player, double progress) { + if (player == nullptr) { + return; + } + player->p->setProgress(progress); +} + +bool pag_player_wait(pag_player* player, pag_backend_semaphore* semaphore) { + if (player == nullptr || semaphore == nullptr) { + return false; + } + return player->p->wait(semaphore->p); +} + +bool pag_player_flush(pag_player* player) { + if (player == nullptr) { + return false; + } + return player->p->flush(); +} + +bool pag_player_flush_and_signal_semaphore(pag_player* player, pag_backend_semaphore* semaphore) { + if (player == nullptr) { + return false; + } + if (semaphore == nullptr) { + return player->p->flush(); + } + return player->p->flushAndSignalSemaphore(&semaphore->p); +} + +pag_scale_mode pag_player_get_scale_mode(pag_player* player) { + if (player == nullptr) { + return pag_scale_mode_none; + } + pag_scale_mode scaleMode; + if (ToCScaleMode(player->p->scaleMode(), &scaleMode)) { + return scaleMode; + } + return pag_scale_mode_none; +} + +void pag_player_set_scale_mode(pag_player* player, pag_scale_mode scaleMode) { + if (player == nullptr) { + return; + } + pag::Enum pagScaleMode; + if (FromCScaleMode(scaleMode, &pagScaleMode)) { + player->p->setScaleMode(pagScaleMode); + } +} + +int64_t pag_player_get_duration(pag_player* player) { + if (player == nullptr) { + return 0; + } + return player->p->duration(); +} + +int64_t pag_player_get_graphics_memory(pag_player* player) { + if (player == nullptr) { + return 0; + } + return player->p->graphicsMemory(); +} diff --git a/src/c/PAGSolidLayer.cpp b/src/c/PAGSolidLayer.cpp new file mode 100644 index 00000000000..ab768931a9e --- /dev/null +++ b/src/c/PAGSolidLayer.cpp @@ -0,0 +1,36 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "PAGTypesPriv.h" +#include "pag/c/pag_solid_layer.h" + +pag_color pag_solid_layer_get_solid_color(pag_solid_layer* layer) { + if (layer == nullptr) { + return {0, 0, 0}; + } + auto color = std::static_pointer_cast(layer->p)->solidColor(); + return pag_color{color.red, color.green, color.blue}; +} + +void pag_solid_layer_set_solid_color(pag_solid_layer* layer, pag_color color) { + if (layer == nullptr) { + return; + } + auto c = pag::Color{color.red, color.green, color.blue}; + std::static_pointer_cast(layer->p)->setSolidColor(c); +} diff --git a/src/c/PAGSurface.cpp b/src/c/PAGSurface.cpp new file mode 100644 index 00000000000..b14431bff44 --- /dev/null +++ b/src/c/PAGSurface.cpp @@ -0,0 +1,86 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "PAGTypesPriv.h" +#include "pag/c/pag_surface.h" +#include "rendering/drawables/DoubleBufferedDrawable.h" +#include "tgfx/opengl/GLDevice.h" + +pag_surface* pag_surface_make_offscreen(int width, int height) { + if (auto surface = pag::PAGSurface::MakeOffscreen(width, height)) { + return new pag_surface(std::move(surface)); + } + return nullptr; +} + +pag_surface* pag_surface_make_double_buffered(int width, int height, + pag_backend_texture* frontTexture, + pag_backend_texture* backTexture) { + auto device = tgfx::GLDevice::Current(); + if (auto drawable = pag::DoubleBufferedDrawable::Make(width, height, frontTexture->p, + backTexture->p, std::move(device))) { + if (auto surface = pag::PAGSurface::MakeFrom(drawable)) { + return new pag_surface(std::move(surface), std::move(drawable)); + } + } + return nullptr; +} + +pag_surface* pag_surface_make_double_buffered_with_hardware_buffer(int width, int height, + void* frontBuffer, + void* backBuffer) { + auto device = tgfx::GLDevice::Make(); + if (auto drawable = pag::DoubleBufferedDrawable::Make( + width, height, static_cast(frontBuffer), + static_cast(backBuffer), std::move(device))) { + if (auto surface = pag::PAGSurface::MakeFrom(drawable)) { + return new pag_surface(std::move(surface), std::move(drawable)); + } + } + return nullptr; +} + +bool pag_surface_is_front_buffer(pag_surface* surface, void* buffer) { + if (surface == nullptr || buffer == nullptr || surface->drawable == nullptr) { + return false; + } + return surface->drawable->isFront(static_cast(buffer)); +} + +bool pag_surface_is_front_texture(pag_surface* surface, pag_backend_texture* texture) { + if (surface == nullptr || texture == nullptr || surface->drawable == nullptr) { + return false; + } + return surface->drawable->isFront(texture->p); +} + +bool pag_surface_read_pixels(pag_surface* surface, pag_color_type colorType, + pag_alpha_type alphaType, void* dstPixels, size_t dstRowBytes) { + if (surface == nullptr) { + return false; + } + pag::ColorType pagColorType; + if (!FromCColorType(colorType, &pagColorType)) { + return false; + } + pag::AlphaType pagAlphaType; + if (!FromCAlphaType(alphaType, &pagAlphaType)) { + return false; + } + return surface->p->readPixels(pagColorType, pagAlphaType, dstPixels, dstRowBytes); +} diff --git a/src/c/PAGTextDocument.cpp b/src/c/PAGTextDocument.cpp new file mode 100644 index 00000000000..8a8e5000943 --- /dev/null +++ b/src/c/PAGTextDocument.cpp @@ -0,0 +1,350 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "PAGTypesPriv.h" +#include "pag/c/pag_text_document.h" + +bool pag_text_document_get_apply_fill(pag_text_document* document) { + if (document == nullptr) { + return false; + } + return document->p->applyFill; +} + +void pag_text_document_set_apply_fill(pag_text_document* document, bool applyFill) { + if (document == nullptr) { + return; + } + document->p->applyFill = applyFill; +} + +bool pag_text_document_get_apply_stroke(pag_text_document* document) { + if (document == nullptr) { + return false; + } + return document->p->applyStroke; +} + +void pag_text_document_set_apply_stroke(pag_text_document* document, bool applyStroke) { + if (document == nullptr) { + return; + } + document->p->applyStroke = applyStroke; +} + +float pag_text_document_get_baseline_shift(pag_text_document* document) { + if (document == nullptr) { + return 0.0f; + } + return document->p->baselineShift; +} + +void pag_text_document_set_baseline_shift(pag_text_document* document, float baselineShift) { + if (document == nullptr) { + return; + } + document->p->baselineShift = baselineShift; +} + +bool pag_text_document_get_box_text(pag_text_document* document) { + if (document == nullptr) { + return false; + } + return document->p->boxText; +} + +void pag_text_document_set_box_text(pag_text_document* document, bool boxText) { + if (document == nullptr) { + return; + } + document->p->boxText = boxText; +} + +pag_point pag_text_document_get_box_text_pos(pag_text_document* document) { + if (document == nullptr) { + return {0.0f, 0.0f}; + } + auto point = document->p->boxTextPos; + return pag_point{point.x, point.y}; +} + +void pag_text_document_set_box_text_pos(pag_text_document* document, pag_point boxTextPos) { + if (document == nullptr) { + return; + } + document->p->boxTextPos.x = boxTextPos.x; + document->p->boxTextPos.y = boxTextPos.y; +} + +pag_point pag_text_document_get_box_text_size(pag_text_document* document) { + if (document == nullptr) { + return {0.0f, 0.0f}; + } + auto point = document->p->boxTextSize; + return pag_point{point.x, point.y}; +} + +void pag_text_document_set_box_text_size(pag_text_document* document, pag_point boxTextSize) { + if (document == nullptr) { + return; + } + document->p->boxTextSize.x = boxTextSize.x; + document->p->boxTextSize.y = boxTextSize.y; +} + +float pag_text_document_get_first_baseline(pag_text_document* document) { + if (document == nullptr) { + return 0.0f; + } + return document->p->firstBaseLine; +} + +void pag_text_document_set_first_baseline(pag_text_document* document, float firstBaseline) { + if (document == nullptr) { + return; + } + document->p->firstBaseLine = firstBaseline; +} + +bool pag_text_document_get_faux_bold(pag_text_document* document) { + if (document == nullptr) { + return false; + } + return document->p->fauxBold; +} + +void pag_text_document_set_faux_bold(pag_text_document* document, bool fauxBold) { + if (document == nullptr) { + return; + } + document->p->fauxBold = fauxBold; +} + +bool pag_text_document_get_faux_italic(pag_text_document* document) { + if (document == nullptr) { + return false; + } + return document->p->fauxItalic; +} + +void pag_text_document_set_faux_italic(pag_text_document* document, bool fauxItalic) { + if (document == nullptr) { + return; + } + document->p->fauxItalic = fauxItalic; +} + +pag_color pag_text_document_get_fill_color(pag_text_document* document) { + if (document == nullptr) { + return {0, 0, 0}; + } + auto color = document->p->fillColor; + return pag_color{color.red, color.green, color.blue}; +} + +void pag_text_document_set_fill_color(pag_text_document* document, pag_color fillColor) { + if (document == nullptr) { + return; + } + document->p->fillColor.red = fillColor.red; + document->p->fillColor.green = fillColor.green; + document->p->fillColor.blue = fillColor.blue; +} + +const char* pag_text_document_get_font_family(pag_text_document* document) { + if (document == nullptr) { + return nullptr; + } + return document->p->fontFamily.c_str(); +} + +void pag_text_document_set_font_family(pag_text_document* document, const char* fontFamily) { + if (document == nullptr) { + return; + } + document->p->fontFamily = fontFamily; +} + +const char* pag_text_document_get_font_style(pag_text_document* document) { + if (document == nullptr) { + return nullptr; + } + return document->p->fontStyle.c_str(); +} + +void pag_text_document_set_font_style(pag_text_document* document, const char* fontStyle) { + if (document == nullptr) { + return; + } + document->p->fontStyle = fontStyle; +} + +float pag_text_document_get_font_size(pag_text_document* document) { + if (document == nullptr) { + return 0.0f; + } + return document->p->fontSize; +} + +void pag_text_document_set_font_size(pag_text_document* document, float fontSize) { + if (document == nullptr) { + return; + } + document->p->fontSize = fontSize; +} + +pag_color pag_text_document_get_stroke_color(pag_text_document* document) { + if (document == nullptr) { + return {0, 0, 0}; + } + auto color = document->p->strokeColor; + return pag_color{color.red, color.green, color.blue}; +} + +void pag_text_document_set_stroke_color(pag_text_document* document, pag_color strokeColor) { + if (document == nullptr) { + return; + } + document->p->strokeColor.red = strokeColor.red; + document->p->strokeColor.green = strokeColor.green; + document->p->strokeColor.blue = strokeColor.blue; +} + +bool pag_text_document_get_stroke_over_fill(pag_text_document* document) { + if (document == nullptr) { + return false; + } + return document->p->strokeOverFill; +} + +void pag_text_document_set_stroke_over_fill(pag_text_document* document, bool strokeOverFill) { + if (document == nullptr) { + return; + } + document->p->strokeOverFill = strokeOverFill; +} + +float pag_text_document_get_stroke_width(pag_text_document* document) { + if (document == nullptr) { + return 0.0f; + } + return document->p->strokeWidth; +} + +void pag_text_document_set_stroke_width(pag_text_document* document, float strokeWidth) { + if (document == nullptr) { + return; + } + document->p->strokeWidth = strokeWidth; +} + +const char* pag_text_document_get_text(pag_text_document* document) { + if (document == nullptr) { + return nullptr; + } + return document->p->text.c_str(); +} + +void pag_text_document_set_text(pag_text_document* document, const char* text) { + if (document == nullptr) { + return; + } + document->p->text = text; +} + +pag_paragraph_justification pag_text_document_get_justification(pag_text_document* document) { + if (document == nullptr) { + return pag_paragraph_justification_left_justify; + } + pag_paragraph_justification justification; + if (ToCParagraphJustification(document->p->justification, &justification)) { + return justification; + } + return pag_paragraph_justification_left_justify; +} + +void pag_text_document_set_justification(pag_text_document* document, + pag_paragraph_justification justification) { + if (document == nullptr) { + return; + } + pag::Enum pagJustification; + if (FromCParagraphJustification(justification, &pagJustification)) { + document->p->justification = pagJustification; + } +} + +float pag_text_document_get_leading(pag_text_document* document) { + if (document == nullptr) { + return 0.0f; + } + return document->p->leading; +} + +void pag_text_document_set_leading(pag_text_document* document, float leading) { + if (document == nullptr) { + return; + } + document->p->leading = leading; +} + +float pag_text_document_get_tracking(pag_text_document* document) { + if (document == nullptr) { + return 0.0f; + } + return document->p->tracking; +} + +void pag_text_document_set_tracking(pag_text_document* document, float tracking) { + if (document == nullptr) { + return; + } + document->p->tracking = tracking; +} + +pag_color pag_text_document_get_background_color(pag_text_document* document) { + if (document == nullptr) { + return {0, 0, 0}; + } + auto color = document->p->backgroundColor; + return pag_color{color.red, color.green, color.blue}; +} + +void pag_text_document_set_background_color(pag_text_document* document, + pag_color backgroundColor) { + if (document == nullptr) { + return; + } + document->p->backgroundColor.red = backgroundColor.red; + document->p->backgroundColor.green = backgroundColor.green; + document->p->backgroundColor.blue = backgroundColor.blue; +} + +uint8_t pag_text_document_get_background_alpha(pag_text_document* document) { + if (document == nullptr) { + return 0; + } + return document->p->backgroundAlpha; +} + +void pag_text_document_set_background_alpha(pag_text_document* document, uint8_t backgroundAlpha) { + if (document == nullptr) { + return; + } + document->p->backgroundAlpha = backgroundAlpha; +} diff --git a/src/c/PAGTypes.cpp b/src/c/PAGTypes.cpp new file mode 100644 index 00000000000..942664ac7d9 --- /dev/null +++ b/src/c/PAGTypes.cpp @@ -0,0 +1,289 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "PAGTypesPriv.h" + +static void DeletePAGByteData(const void* pointer) { + delete reinterpret_cast(pointer); +} + +static void DeletePAGTextDocument(const void* pointer) { + delete reinterpret_cast(pointer); +} + +static void DeletePAGLayer(const void* pointer) { + delete reinterpret_cast(pointer); +} + +static void DeletePAGPlayer(const void* pointer) { + delete reinterpret_cast(pointer); +} + +static void DeletePAGSurface(const void* pointer) { + delete reinterpret_cast(pointer); +} + +static void DeletePAGImage(const void* pointer) { + delete reinterpret_cast(pointer); +} + +static void DeletePAGFont(const void* pointer) { + delete reinterpret_cast(pointer); +} + +static void DeletePAGBackendTexture(const void* pointer) { + delete reinterpret_cast(pointer); +} + +static void DeletePAGBackendSemaphore(const void* pointer) { + delete reinterpret_cast(pointer); +} + +static void DeletePAGDecoder(const void* pointer) { + delete reinterpret_cast(pointer); +} + +static void DeletePAGAnimator(const void* pointer) { + delete reinterpret_cast(pointer); +} + +static void (*DeleteFunctions[])(const void*) = { + DeletePAGByteData, DeletePAGTextDocument, DeletePAGLayer, DeletePAGPlayer, + DeletePAGSurface, DeletePAGImage, DeletePAGFont, DeletePAGBackendTexture, + DeletePAGBackendSemaphore, DeletePAGDecoder, DeletePAGAnimator}; + +void pag_release(pag_object object) { + if (object == nullptr) { + return; + } + auto type = *reinterpret_cast(object); + if (type == PAGObjectType::Unknown || type >= PAGObjectType::Count) { + return; + } + DeleteFunctions[static_cast(type) - 1](object); +} + +std::shared_ptr ToPAGComposition(pag_composition* composition) { + if (composition == nullptr) { + return nullptr; + } + return std::static_pointer_cast(composition->p); +} + +std::shared_ptr ToPAGFile(pag_file* file) { + if (file == nullptr || !file->p->isPAGFile()) { + return nullptr; + } + return std::static_pointer_cast(file->p); +} +const struct { + pag_time_stretch_mode C; + pag::Enum Pag; +} gTimeStretchPairs[] = { + {pag_time_stretch_mode_none, pag::PAGTimeStretchMode::None}, + {pag_time_stretch_mode_scale, pag::PAGTimeStretchMode::Scale}, + {pag_time_stretch_mode_repeat_inverted, pag::PAGTimeStretchMode::Repeat}, + {pag_time_stretch_mode_repeat_inverted, pag::PAGTimeStretchMode::RepeatInverted}, +}; + +bool FromCTimeStretchMode(pag_time_stretch_mode cTimeStretchMode, pag::Enum* timeStretchMode) { + for (auto& pair : gTimeStretchPairs) { + if (pair.C == cTimeStretchMode) { + *timeStretchMode = pair.Pag; + return true; + } + } + return false; +} + +bool ToCTimeStretchMode(pag::Enum timeStretchMode, pag_time_stretch_mode* cTimeStretchMode) { + for (auto& pair : gTimeStretchPairs) { + if (pair.Pag == timeStretchMode) { + *cTimeStretchMode = pair.C; + return true; + } + } + return false; +} + +const struct { + pag_color_type C; + pag::ColorType Pag; +} gColorTypePairs[] = { + {pag_color_type_unknown, pag::ColorType::Unknown}, + {pag_color_type_alpha_8, pag::ColorType::ALPHA_8}, + {pag_color_type_rgba_8888, pag::ColorType::RGBA_8888}, + {pag_color_type_bgra_8888, pag::ColorType::BGRA_8888}, + {pag_color_type_rgb_565, pag::ColorType::RGB_565}, + {pag_color_type_gray_8, pag::ColorType::Gray_8}, + {pag_color_type_rgba_f16, pag::ColorType::RGBA_F16}, + {pag_color_type_rgba_101012, pag::ColorType::RGBA_1010102}, +}; + +bool FromCColorType(pag_color_type cColorType, pag::ColorType* colorType) { + for (auto& pair : gColorTypePairs) { + if (pair.C == cColorType) { + *colorType = pair.Pag; + return true; + } + } + return false; +} + +bool ToCColorType(pag::ColorType colorType, pag_color_type* cColorType) { + for (auto& pair : gColorTypePairs) { + if (pair.Pag == colorType) { + *cColorType = pair.C; + return true; + } + } + return false; +} + +const struct { + pag_alpha_type C; + pag::AlphaType Pag; +} gAlphaTypePairs[] = { + {pag_alpha_type_unknown, pag::AlphaType::Unknown}, + {pag_alpha_type_opaque, pag::AlphaType::Opaque}, + {pag_alpha_type_premultiplied, pag::AlphaType::Premultiplied}, + {pag_alpha_type_unpremultiplied, pag::AlphaType::Unpremultiplied}, +}; + +bool FromCAlphaType(pag_alpha_type cAlphaType, pag::AlphaType* alphaType) { + for (auto& pair : gAlphaTypePairs) { + if (pair.C == cAlphaType) { + *alphaType = pair.Pag; + return true; + } + } + return false; +} + +bool ToCAlphaType(pag::AlphaType alphaType, pag_alpha_type* cAlphaType) { + for (auto& pair : gAlphaTypePairs) { + if (pair.Pag == alphaType) { + *cAlphaType = pair.C; + return true; + } + } + return false; +} + +const struct { + pag_scale_mode C; + pag::Enum Pag; +} gScaleModePairs[] = { + {pag_scale_mode_none, pag::PAGScaleMode::None}, + {pag_scale_mode_stretch, pag::PAGScaleMode::Stretch}, + {pag_scale_mode_letter_box, pag::PAGScaleMode::LetterBox}, + {pag_scale_mode_zoom, pag::PAGScaleMode::Zoom}, +}; + +bool FromCScaleMode(pag_scale_mode cScaleMode, pag::Enum* scaleMode) { + for (auto& pair : gScaleModePairs) { + if (pair.C == cScaleMode) { + *scaleMode = pair.Pag; + return true; + } + } + return false; +} + +bool ToCScaleMode(pag::Enum scaleMode, pag_scale_mode* cScaleMode) { + for (auto& pair : gScaleModePairs) { + if (pair.Pag == scaleMode) { + *cScaleMode = pair.C; + return true; + } + } + return false; +} + +const struct { + pag_paragraph_justification C; + pag::Enum Pag; +} gParagraphJustificationPairs[] = { + {pag_paragraph_justification_left_justify, pag::ParagraphJustification::LeftJustify}, + {pag_paragraph_justification_center_justify, pag::ParagraphJustification::CenterJustify}, + {pag_paragraph_justification_right_justify, pag::ParagraphJustification::RightJustify}, + {pag_paragraph_justification_full_justify_last_line_left, + pag::ParagraphJustification::FullJustifyLastLineLeft}, + {pag_paragraph_justification_full_justify_last_line_right, + pag::ParagraphJustification::FullJustifyLastLineRight}, + {pag_paragraph_justification_full_justify_last_line_center, + pag::ParagraphJustification::FullJustifyLastLineCenter}, + {pag_paragraph_justification_full_justify_last_line_full, + pag::ParagraphJustification::FullJustifyLastLineFull}, +}; + +bool FromCParagraphJustification(pag_paragraph_justification cParagraphJustification, + pag::Enum* paragraphJustification) { + for (auto& pair : gParagraphJustificationPairs) { + if (pair.C == cParagraphJustification) { + *paragraphJustification = pair.Pag; + return true; + } + } + return false; +} + +bool ToCParagraphJustification(pag::Enum paragraphJustification, + pag_paragraph_justification* cParagraphJustification) { + for (auto& pair : gParagraphJustificationPairs) { + if (pair.Pag == paragraphJustification) { + *cParagraphJustification = pair.C; + return true; + } + } + return false; +} + +const struct { + pag_layer_type C; + pag::LayerType Pag; +} gLayerTypePairs[] = { + {pag_layer_type_unknown, pag::LayerType::Unknown}, + {pag_layer_type_null, pag::LayerType::Null}, + {pag_layer_type_solid, pag::LayerType::Solid}, + {pag_layer_type_text, pag::LayerType::Text}, + {pag_layer_type_shape, pag::LayerType::Shape}, + {pag_layer_type_image, pag::LayerType::Image}, + {pag_layer_type_pre_compose, pag::LayerType::PreCompose}, + {pag_layer_type_camera, pag::LayerType::Camera}, +}; + +bool FromCLayerType(pag_layer_type cLayerType, pag::LayerType* layerType) { + for (auto& pair : gLayerTypePairs) { + if (pair.C == cLayerType) { + *layerType = pair.Pag; + return true; + } + } + return false; +} + +bool TocLayerType(pag::LayerType layerType, pag_layer_type* cLayerType) { + for (auto& pair : gLayerTypePairs) { + if (pair.Pag == layerType) { + *cLayerType = pair.C; + return true; + } + } + return false; +} diff --git a/src/c/PAGTypesPriv.h b/src/c/PAGTypesPriv.h new file mode 100644 index 00000000000..319155ff5ac --- /dev/null +++ b/src/c/PAGTypesPriv.h @@ -0,0 +1,166 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "pag/c/pag_types.h" +#include "pag/pag.h" +#include "rendering/PAGAnimator.h" +#include "rendering/drawables/DoubleBufferedDrawable.h" +#include "tgfx/gpu/Device.h" + +enum class PAGObjectType : uint8_t { + Unknown = 0, + ByteData, + TextDocument, + Layer, + Player, + Surface, + Image, + Font, + BackendTexture, + BackendSemaphore, + Decoder, + PAGAnimator, + + Count, +}; + +struct pag_byte_data { + explicit pag_byte_data(std::unique_ptr byteData) : p(std::move(byteData)) { + } + + PAGObjectType type = PAGObjectType::ByteData; + std::unique_ptr p; +}; + +struct pag_text_document { + explicit pag_text_document(std::shared_ptr textDocument) + : p(std::move(textDocument)) { + } + + PAGObjectType type = PAGObjectType::TextDocument; + std::shared_ptr p; +}; + +struct pag_layer { + explicit pag_layer(std::shared_ptr layer) : p(std::move(layer)) { + } + + PAGObjectType type = PAGObjectType::Layer; + std::shared_ptr p; +}; + +struct pag_player { + explicit pag_player(std::shared_ptr player) : p(std::move(player)) { + } + + PAGObjectType type = PAGObjectType::Player; + std::shared_ptr p; +}; + +struct pag_surface { + explicit pag_surface(std::shared_ptr surface, + std::shared_ptr drawable = nullptr) + : p(std::move(surface)), drawable(std::move(drawable)) { + } + + PAGObjectType type = PAGObjectType::Surface; + std::shared_ptr p; + std::shared_ptr drawable; +}; + +struct pag_image { + explicit pag_image(std::shared_ptr image) : p(std::move(image)) { + } + + PAGObjectType type = PAGObjectType::Image; + std::shared_ptr p; +}; + +struct pag_font { + explicit pag_font(pag::PAGFont font) : p(std::move(font)) { + } + + PAGObjectType type = PAGObjectType::Font; + pag::PAGFont p; +}; + +struct pag_backend_texture { + explicit pag_backend_texture(const pag::BackendTexture& backendTexture) : p(backendTexture) { + } + explicit pag_backend_texture(void* otherBackend) : otherBackend(otherBackend) { + } + + PAGObjectType type = PAGObjectType::BackendTexture; + pag::BackendTexture p; + void* otherBackend = nullptr; +}; + +struct pag_backend_semaphore { + pag_backend_semaphore() = default; + + PAGObjectType type = PAGObjectType::BackendSemaphore; + pag::BackendSemaphore p; +}; + +struct pag_decoder { + explicit pag_decoder(std::shared_ptr decoder) : p(std::move(decoder)) { + } + + PAGObjectType type = PAGObjectType::Decoder; + std::shared_ptr p; +}; + +struct pag_animator { + pag_animator() = default; + + PAGObjectType type = PAGObjectType::PAGAnimator; + std::shared_ptr p; + std::shared_ptr listener; +}; + +std::shared_ptr ToPAGFile(pag_file* file); + +std::shared_ptr ToPAGComposition(pag_composition* composition); + +bool FromCTimeStretchMode(pag_time_stretch_mode cTimeStretchMode, pag::Enum* timeStretchMode); + +bool ToCTimeStretchMode(pag::Enum timeStretchMode, pag_time_stretch_mode* cTimeStretchMode); + +bool FromCColorType(pag_color_type cColorType, pag::ColorType* colorType); + +bool ToCColorType(pag::ColorType colorType, pag_color_type* cColorType); + +bool FromCAlphaType(pag_alpha_type cAlphaType, pag::AlphaType* alphaType); + +bool ToCAlphaType(pag::AlphaType alphaType, pag_alpha_type* cAlphaType); + +bool FromCScaleMode(pag_scale_mode cScaleMode, pag::Enum* scaleMode); + +bool ToCScaleMode(pag::Enum scaleMode, pag_scale_mode* cScaleMode); + +bool FromCParagraphJustification(pag_paragraph_justification cParagraphJustification, + pag::Enum* paragraphJustification); + +bool ToCParagraphJustification(pag::Enum paragraphJustification, + pag_paragraph_justification* cParagraphJustification); + +bool FromCLayerType(pag_layer_type cLayerType, pag::LayerType* layerType); + +bool TocLayerType(pag::LayerType layerType, pag_layer_type* cLayerType); diff --git a/src/platform/Platform.cpp b/src/platform/Platform.cpp index 2bec064c0f4..c4bd114ce31 100644 --- a/src/platform/Platform.cpp +++ b/src/platform/Platform.cpp @@ -52,4 +52,4 @@ std::string Platform::getSandboxPath(std::string filePath) const { std::shared_ptr Platform::createDisplayLink(std::function) const { return nullptr; } -} // namespace pag \ No newline at end of file +} // namespace pag diff --git a/src/platform/qt/GPUDrawable.cpp b/src/platform/qt/GPUDrawable.cpp index cf098049683..3bc0b8b1ed7 100644 --- a/src/platform/qt/GPUDrawable.cpp +++ b/src/platform/qt/GPUDrawable.cpp @@ -31,7 +31,7 @@ std::shared_ptr GPUDrawable::MakeFrom(QQuickItem* quickItem, } GPUDrawable::GPUDrawable(QQuickItem* quickItem, std::shared_ptr window) - : quickItem(quickItem), window(std::move(window)) { + : DoubleBufferedDrawable(std::move(window)), quickItem(quickItem) { GPUDrawable::updateSize(); } @@ -42,26 +42,15 @@ void GPUDrawable::updateSize() { _height = static_cast(ceil(quickItem->height() * pixelRatio)); } -std::shared_ptr GPUDrawable::onCreateDevice() { - if (_width <= 0 || _height <= 0) { - return nullptr; - } - return window->getDevice(); -} - -std::shared_ptr GPUDrawable::onCreateSurface(tgfx::Context* context) { - return window->createSurface(context); -} - -void GPUDrawable::present(tgfx::Context* context) { - window->present(context); +std::shared_ptr GPUDrawable::qGLWindow() const { + return std::static_pointer_cast(window); } void GPUDrawable::moveToThread(QThread* targetThread) { - window->moveToThread(targetThread); + qGLWindow()->moveToThread(targetThread); } QSGTexture* GPUDrawable::getTexture() { - return window->getTexture(); + return qGLWindow()->getTexture(); } } // namespace pag diff --git a/src/platform/qt/GPUDrawable.h b/src/platform/qt/GPUDrawable.h index 66d251e2a21..27e0f4a53a5 100644 --- a/src/platform/qt/GPUDrawable.h +++ b/src/platform/qt/GPUDrawable.h @@ -24,45 +24,29 @@ #include #include #pragma clang diagnostic pop -#include "rendering/drawables/Drawable.h" +#include "rendering/drawables/DoubleBufferedDrawable.h" namespace tgfx { class QGLWindow; } namespace pag { -class GPUDrawable : public Drawable { +class GPUDrawable : public DoubleBufferedDrawable { public: static std::shared_ptr MakeFrom(QQuickItem* quickItem, QOpenGLContext* sharedContext = nullptr); - int width() const override { - return _width; - } - - int height() const override { - return _height; - } - void updateSize() override; - void present(tgfx::Context* context) override; - void moveToThread(QThread* targetThread); QSGTexture* getTexture(); - protected: - std::shared_ptr onCreateDevice() override; - - std::shared_ptr onCreateSurface(tgfx::Context* context) override; - private: - int _width = 0; - int _height = 0; QQuickItem* quickItem = nullptr; - std::shared_ptr window = nullptr; GPUDrawable(QQuickItem* quickItem, std::shared_ptr window); + + std::shared_ptr qGLWindow() const; }; } // namespace pag diff --git a/src/rendering/PAGAnimator.cpp b/src/rendering/PAGAnimator.cpp index b85ed977bb8..7d8a592657c 100644 --- a/src/rendering/PAGAnimator.cpp +++ b/src/rendering/PAGAnimator.cpp @@ -19,6 +19,7 @@ #include "PAGAnimator.h" #include "base/utils/TimeUtil.h" #include "platform/Platform.h" +#include "rendering/utils/DisplayLinkWrapper.h" #include "tgfx/utils/Clock.h" #include "tgfx/utils/Task.h" @@ -35,7 +36,11 @@ class AnimationTicker { } AnimationTicker() { - displayLink = Platform::Current()->createDisplayLink([this] { onFrameAvailable(); }); + auto callback = [this] { onFrameAvailable(); }; + displayLink = DisplayLinkWrapper::Make(callback); + if (displayLink == nullptr) { + displayLink = Platform::Current()->createDisplayLink(callback); + } } bool available() { diff --git a/src/rendering/drawables/DoubleBufferDrawable.cpp b/src/rendering/drawables/DoubleBufferDrawable.cpp new file mode 100644 index 00000000000..0f1fee3123c --- /dev/null +++ b/src/rendering/drawables/DoubleBufferDrawable.cpp @@ -0,0 +1,83 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "DoubleBufferedDrawable.h" +#include "base/utils/TGFXCast.h" +#include "tgfx/platform/HardwareBuffer.h" + +namespace pag { +std::shared_ptr DoubleBufferedDrawable::Make( + int width, int height, const BackendTexture& frontTexture, const BackendTexture& backTexture, + std::shared_ptr device) { + if (!frontTexture.isValid() || !backTexture.isValid() || + frontTexture.backend() != Backend::OPENGL || backTexture.backend() != Backend::OPENGL || + device == nullptr) { + return nullptr; + } + auto window = tgfx::DoubleBufferedWindow::Make(std::move(device), ToTGFX(frontTexture), + ToTGFX(backTexture)); + if (window == nullptr) { + return nullptr; + } + return std::shared_ptr( + new DoubleBufferedDrawable(width, height, std::move(window))); +} + +std::shared_ptr DoubleBufferedDrawable::Make( + int width, int height, HardwareBufferRef frontBuffer, HardwareBufferRef backBuffer, + std::shared_ptr device) { + if (frontBuffer == nullptr || backBuffer == nullptr || device == nullptr) { + return nullptr; + } + auto window = tgfx::DoubleBufferedWindow::Make(std::move(device), frontBuffer, backBuffer); + if (window == nullptr) { + return nullptr; + } + return std::shared_ptr( + new DoubleBufferedDrawable(width, height, std::move(window))); +} + +DoubleBufferedDrawable::DoubleBufferedDrawable(std::shared_ptr window) + : window(std::move(window)) { +} + +DoubleBufferedDrawable::DoubleBufferedDrawable(int width, int height, + std::shared_ptr window) + : _width(width), _height(height), window(std::move(window)) { +} + +bool DoubleBufferedDrawable::isFront(const BackendTexture& texture) const { + return window->isFront(ToTGFX(texture)); +} + +std::shared_ptr DoubleBufferedDrawable::onCreateDevice() { + if (_width <= 0 || _height <= 0) { + return nullptr; + } + return window->getDevice(); +} + +std::shared_ptr DoubleBufferedDrawable::onCreateSurface(tgfx::Context* context) { + return window->createSurface(context); +} + +void DoubleBufferedDrawable::present(tgfx::Context* context) { + window->present(context); + surface = window->getBackSurface(); +} +} // namespace pag diff --git a/src/rendering/drawables/DoubleBufferedDrawable.h b/src/rendering/drawables/DoubleBufferedDrawable.h new file mode 100644 index 00000000000..145bb8b46da --- /dev/null +++ b/src/rendering/drawables/DoubleBufferedDrawable.h @@ -0,0 +1,67 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "rendering/drawables/Drawable.h" +#include "tgfx/gpu/DoubleBufferedWindow.h" + +namespace pag { +class DoubleBufferedDrawable : public Drawable { + public: + static std::shared_ptr Make(int width, int height, + const BackendTexture& frontTexture, + const BackendTexture& backTexture, + std::shared_ptr device); + + static std::shared_ptr Make(int width, int height, + HardwareBufferRef frontBuffer, + HardwareBufferRef backBuffer, + std::shared_ptr device); + + int width() const override { + return _width; + } + + int height() const override { + return _height; + } + + void present(tgfx::Context* context) override; + + bool isFront(HardwareBufferRef buffer) const { + return window->isFront(buffer); + } + + bool isFront(const BackendTexture& texture) const; + + protected: + explicit DoubleBufferedDrawable(std::shared_ptr window); + + int _width = 0; + int _height = 0; + std::shared_ptr window; + + private: + DoubleBufferedDrawable(int width, int height, std::shared_ptr window); + + std::shared_ptr onCreateSurface(tgfx::Context* context) override; + + std::shared_ptr onCreateDevice() override; +}; +} // namespace pag diff --git a/src/rendering/utils/DisplayLinkWrapper.cpp b/src/rendering/utils/DisplayLinkWrapper.cpp new file mode 100644 index 00000000000..88adc7dc08b --- /dev/null +++ b/src/rendering/utils/DisplayLinkWrapper.cpp @@ -0,0 +1,74 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "DisplayLinkWrapper.h" + +static pag_display_link_functions* DisplayLinkFunctions = nullptr; + +void pag_display_link_set_functions(pag_display_link_functions* functions) { + DisplayLinkFunctions = functions; +} + +namespace pag { +static void DisplayLinkWrapperUpdate(void* user) { + if (user == nullptr) { + return; + } + auto* wrapper = static_cast(user); + wrapper->update(); +} + +std::shared_ptr DisplayLinkWrapper::Make(std::function callback) { + if (DisplayLinkFunctions == nullptr || callback == nullptr) { + return nullptr; + } + auto* ret = new DisplayLinkWrapper(); + if (auto* displayLink = DisplayLinkFunctions->create(ret, DisplayLinkWrapperUpdate)) { + ret->displayLink = displayLink; + ret->callback = std::move(callback); + return std::shared_ptr(ret); + } + delete ret; + return nullptr; +} + +DisplayLinkWrapper::~DisplayLinkWrapper() { + DisplayLinkWrapper::stop(); + DisplayLinkFunctions->release(displayLink); +} + +void DisplayLinkWrapper::start() { + if (started) { + return; + } + started = true; + DisplayLinkFunctions->start(displayLink); +} + +void DisplayLinkWrapper::stop() { + if (!started) { + return; + } + started = false; + DisplayLinkFunctions->stop(displayLink); +} + +void DisplayLinkWrapper::update() { + callback(); +} +} // namespace pag diff --git a/src/rendering/utils/DisplayLinkWrapper.h b/src/rendering/utils/DisplayLinkWrapper.h new file mode 100644 index 00000000000..1b367990f70 --- /dev/null +++ b/src/rendering/utils/DisplayLinkWrapper.h @@ -0,0 +1,46 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include "pag/c/pag_types.h" +#include "rendering/utils/DisplayLink.h" + +namespace pag { +class DisplayLinkWrapper : public DisplayLink { + public: + static std::shared_ptr Make(std::function callback); + + ~DisplayLinkWrapper() override; + + void start() override; + + void stop() override; + + void update(); + + private: + DisplayLinkWrapper() = default; + + bool started = false; + void* displayLink = nullptr; + std::function callback; +}; +} // namespace pag diff --git a/tgfx/include/tgfx/gpu/DoubleBufferedWindow.h b/tgfx/include/tgfx/gpu/DoubleBufferedWindow.h new file mode 100644 index 00000000000..c443486fc38 --- /dev/null +++ b/tgfx/include/tgfx/gpu/DoubleBufferedWindow.h @@ -0,0 +1,58 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "tgfx/gpu/Window.h" + +namespace tgfx { +class DoubleBufferedWindow : public Window { + public: + static std::shared_ptr Make(std::shared_ptr device, + const BackendTexture& frontBackendTexture, + const BackendTexture& backBackendTexture); + + static std::shared_ptr Make(std::shared_ptr device, + HardwareBufferRef frontBuffer, + HardwareBufferRef backBuffer); + + std::shared_ptr getBackSurface() const { + return backSurface; + } + + virtual bool isFront(const BackendTexture&) const { + return false; + } + + virtual bool isFront(HardwareBufferRef) const { + return false; + } + + ~DoubleBufferedWindow() override; + + protected: + explicit DoubleBufferedWindow(std::shared_ptr device); + + void onPresent(Context* context, int64_t presentationTime) override; + + virtual void onSwapSurfaces(Context*) = 0; + + std::shared_ptr frontSurface; + std::shared_ptr backSurface; +}; +} // namespace tgfx diff --git a/tgfx/include/tgfx/opengl/qt/QGLWindow.h b/tgfx/include/tgfx/opengl/qt/QGLWindow.h index 5dfa5d2047c..9a04c0156c4 100644 --- a/tgfx/include/tgfx/opengl/qt/QGLWindow.h +++ b/tgfx/include/tgfx/opengl/qt/QGLWindow.h @@ -24,13 +24,13 @@ #include #pragma clang diagnostic pop #include "QGLDevice.h" -#include "tgfx/gpu/Window.h" +#include "tgfx/gpu/DoubleBufferedWindow.h" namespace tgfx { class Texture; class GLRenderTarget; -class QGLWindow : public Window { +class QGLWindow : public DoubleBufferedWindow { public: ~QGLWindow() override; @@ -57,14 +57,13 @@ class QGLWindow : public Window { protected: std::shared_ptr onCreateSurface(Context* context) override; - void onPresent(Context* context, int64_t presentationTime) override; + void onSwapSurfaces(Context*) override; private: std::mutex locker = {}; bool textureInvalid = true; QQuickItem* quickItem = nullptr; QSGTexture* outTexture = nullptr; - std::shared_ptr surface = nullptr; std::shared_ptr frontTexture = nullptr; std::shared_ptr backTexture = nullptr; diff --git a/tgfx/src/gpu/DoubleBufferedWindow.cpp b/tgfx/src/gpu/DoubleBufferedWindow.cpp new file mode 100644 index 00000000000..7e551d75558 --- /dev/null +++ b/tgfx/src/gpu/DoubleBufferedWindow.cpp @@ -0,0 +1,145 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "tgfx/gpu/DoubleBufferedWindow.h" +#include "gpu/Texture.h" + +namespace tgfx { +class DoubleBufferedWindowExternal : public DoubleBufferedWindow { + public: + DoubleBufferedWindowExternal(std::shared_ptr device, HardwareBufferRef frontBuffer, + HardwareBufferRef backBuffer) + : DoubleBufferedWindow(std::move(device)), frontBuffer(frontBuffer), backBuffer(backBuffer) { + HardwareBufferRetain(frontBuffer); + HardwareBufferRetain(backBuffer); + } + + ~DoubleBufferedWindowExternal() override { + HardwareBufferRelease(frontBuffer); + HardwareBufferRelease(backBuffer); + } + + bool isFront(HardwareBufferRef buffer) const override { + return frontBuffer == buffer; + } + + private: + std::shared_ptr onCreateSurface(Context* context) override { + if (frontSurface == nullptr) { + frontSurface = Surface::MakeFrom(context, frontBuffer); + } + if (backSurface == nullptr) { + backSurface = Surface::MakeFrom(context, backBuffer); + } + return backSurface; + } + + void onSwapSurfaces(Context*) override { + std::swap(frontBuffer, backBuffer); + } + + HardwareBufferRef frontBuffer = nullptr; + HardwareBufferRef backBuffer = nullptr; +}; + +class DoubleBufferedWindowTexture : public DoubleBufferedWindow { + public: + DoubleBufferedWindowTexture(std::shared_ptr device, + const BackendTexture& frontBackendTexture, + const BackendTexture& backBackendTexture) + : DoubleBufferedWindow(std::move(device)), + frontBackendTexture(frontBackendTexture), + backBackendTexture(backBackendTexture) { + } + + bool isFront(const BackendTexture& texture) const override { + if (!texture.isValid() || !frontBackendTexture.isValid()) { + return false; + } + if (texture.backend() != Backend::OPENGL) { + return false; + } + GLTextureInfo info1; + texture.getGLTextureInfo(&info1); + GLTextureInfo info2; + frontBackendTexture.getGLTextureInfo(&info2); + if (info1.format != info2.format) { + return false; + } + if (info1.target != info2.target) { + return false; + } + return info1.id != info2.id; + } + + private: + std::shared_ptr onCreateSurface(Context* context) override { + if (frontSurface == nullptr) { + frontSurface = Surface::MakeFrom(context, frontBackendTexture, ImageOrigin::TopLeft); + } + if (backSurface == nullptr) { + backSurface = Surface::MakeFrom(context, backBackendTexture, ImageOrigin::TopLeft); + } + return backSurface; + } + + void onSwapSurfaces(Context*) override { + std::swap(frontBackendTexture, backBackendTexture); + } + + BackendTexture frontBackendTexture; + BackendTexture backBackendTexture; +}; + +std::shared_ptr DoubleBufferedWindow::Make(std::shared_ptr device, + HardwareBufferRef frontBuffer, + HardwareBufferRef backBuffer) { + if (device == nullptr || frontBuffer == nullptr || backBuffer == nullptr) { + return nullptr; + } + return std::shared_ptr( + new DoubleBufferedWindowExternal(std::move(device), frontBuffer, backBuffer)); +} + +std::shared_ptr DoubleBufferedWindow::Make( + std::shared_ptr device, const BackendTexture& frontBackendTexture, + const BackendTexture& backBackendTexture) { + if (device == nullptr || !frontBackendTexture.isValid() || !backBackendTexture.isValid()) { + return nullptr; + } + return std::shared_ptr( + new DoubleBufferedWindowTexture(std::move(device), frontBackendTexture, backBackendTexture)); +} + +DoubleBufferedWindow::DoubleBufferedWindow(std::shared_ptr device) + : Window(std::move(device)) { +} + +DoubleBufferedWindow::~DoubleBufferedWindow() { + frontSurface = nullptr; + backSurface = nullptr; +} + +void DoubleBufferedWindow::onPresent(Context* context, int64_t) { + if (frontSurface == nullptr) { + return; + } + std::swap(frontSurface, backSurface); + onSwapSurfaces(context); +} +} // namespace tgfx diff --git a/tgfx/src/opengl/qt/QGLWindow.cpp b/tgfx/src/opengl/qt/QGLWindow.cpp index d2673837a80..31dd0a70a81 100644 --- a/tgfx/src/opengl/qt/QGLWindow.cpp +++ b/tgfx/src/opengl/qt/QGLWindow.cpp @@ -40,11 +40,10 @@ std::shared_ptr QGLWindow::MakeFrom(QQuickItem* quickItem, } QGLWindow::QGLWindow(std::shared_ptr device, QQuickItem* quickItem) - : Window(std::move(device)), quickItem(quickItem) { + : DoubleBufferedWindow(std::move(device)), quickItem(quickItem) { } QGLWindow::~QGLWindow() { - surface = nullptr; frontTexture = nullptr; backTexture = nullptr; delete outTexture; @@ -92,7 +91,6 @@ void QGLWindow::invalidateTexture() { } std::shared_ptr QGLWindow::onCreateSurface(Context* context) { - surface = nullptr; frontTexture = nullptr; backTexture = nullptr; auto nativeWindow = quickItem->window(); @@ -104,22 +102,13 @@ std::shared_ptr QGLWindow::onCreateSurface(Context* context) { } frontTexture = Texture::MakeRGBA(context, width, height); backTexture = Texture::MakeRGBA(context, width, height); - surface = Surface::MakeFrom(backTexture); - return surface; + frontSurface = Surface::MakeFrom(frontTexture); + backSurface = Surface::MakeFrom(backTexture); + return backSurface; } -void QGLWindow::onPresent(Context* context, int64_t) { - if (surface == nullptr) { - return; - } - auto gl = GLFunctions::Get(context); +void QGLWindow::onSwapSurfaces(Context*) { std::swap(frontTexture, backTexture); - surface->texture = backTexture; - auto renderTarget = std::static_pointer_cast(surface->renderTarget); - gl->bindFramebuffer(GL_FRAMEBUFFER, renderTarget->getFrameBufferID()); - auto textureID = static_cast(backTexture->getSampler())->id; - gl->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0); - gl->bindFramebuffer(GL_FRAMEBUFFER, 0); invalidateTexture(); } } // namespace tgfx