diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..d86a91a --- /dev/null +++ b/.clang-format @@ -0,0 +1,55 @@ +# Generated by CLion for STL +BasedOnStyle: LLVM + +AccessModifierOffset: -4 +AlignAfterOpenBracket: DontAlign +AlignConsecutiveAssignments: Consecutive +AlignConsecutiveMacros: Consecutive +AlignEscapedNewlines: Left +AlignOperands: AlignAfterOperator +AlignTrailingComments: + Kind: Never +AllowShortFunctionsOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +BreakBeforeBinaryOperators: NonAssignment +ColumnLimit: 120 +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^$' + Priority: 1 + - Regex: '^<(Windows|userenv)\.h>$' + Priority: 3 + SortPriority: 3 + - Regex: '^$' + Priority: 3 + SortPriority: 4 + - Regex: '^<__.*\.hpp>$' + Priority: 2 + - Regex: '\.hpp[>"]$' + Priority: 5 + - Regex: '.*' + Priority: 2 +IndentCaseBlocks: true +IndentWidth: 4 +IndentWrappedFunctionNames: true +InsertBraces: true +InsertNewlineAtEOF: true +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: All +PointerAlignment: Left +RemoveSemicolon: true +SpaceAfterCStyleCast: true +SpaceBeforeParens: Custom +SpaceBeforeParensOptions: + AfterRequiresInClause: true +StatementMacros: + - _EXTERN_CXX_WORKAROUND + - _END_EXTERN_CXX_WORKAROUND + - _STD_BEGIN + - _STD_END + - _STDEXT_BEGIN + - _STDEXT_END + - _FMT_P2286_BEGIN + - _FMT_P2286_END + - _EXTERN_C_UNLESS_PURE + - _END_EXTERN_C_UNLESS_PURE diff --git a/.gitmodules b/.gitmodules index e69de29..c54d914 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "third_party/LLGL"] + path = third_party/LLGL + url = https://github.com/LukasBanana/LLGL.git +[submodule "third_party/msdfgen"] + path = third_party/msdfgen + url = https://github.com/Chlumsky/msdfgen.git diff --git a/CMakeLists.txt b/CMakeLists.txt index b9d0952..fb06552 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,13 @@ cmake_minimum_required(VERSION 3.15) +cmake_policy(SET CMP0167 NEW) project(aorii) set(CMAKE_CXX_STANDARD 26) +set(MSDFGEN_USE_SKIA OFF CACHE BOOL "Use Skia for MSDFGen" FORCE) +set(MSDFGEN_USE_VCPKG OFF CACHE BOOL "Use VCPKG for MSDFGen" FORCE) +set(MSDFGEN_USE_OPENMP ON CACHE BOOL "Use OpenMP for MSDFGen" FORCE) +set(LLGL_BUILD_STATIC_LIB ON CACHE BOOL "Build LLGL as static library" FORCE) + include(cmake/retrieve_files.cmake) include(cmake/detect_os.cmake) include(cmake/configure_glfw_native.cmake) @@ -14,6 +20,8 @@ else () add_definitions(-DDEBUG=0) endif () +add_subdirectory(third_party/LLGL) +add_subdirectory(third_party/msdfgen) add_subdirectory(src/core) add_subdirectory(src/renderer) add_subdirectory(src/widget) diff --git a/src/core/containers/lrucache.hpp b/src/core/containers/lrucache.hpp new file mode 100644 index 0000000..9e5e285 --- /dev/null +++ b/src/core/containers/lrucache.hpp @@ -0,0 +1,72 @@ +/* + * File: lrucache.hpp + * Author: Alexander Ponomarev + * + * Created on June 20, 2013, 5:09 PM + */ + +#ifndef _LRUCACHE_HPP_INCLUDED_ +#define _LRUCACHE_HPP_INCLUDED_ + +#include +#include +#include +#include + +namespace cache { + +template +class lru_cache { +public: + typedef typename std::pair key_value_pair_t; + typedef typename std::list::iterator list_iterator_t; + + lru_cache(size_t max_size) : + _max_size(max_size) { + } + + void put(const key_t& key, const value_t& value) { + auto it = _cache_items_map.find(key); + _cache_items_list.push_front(key_value_pair_t(key, value)); + if (it != _cache_items_map.end()) { + _cache_items_list.erase(it->second); + _cache_items_map.erase(it); + } + _cache_items_map[key] = _cache_items_list.begin(); + + if (_cache_items_map.size() > _max_size) { + auto last = _cache_items_list.end(); + last--; + _cache_items_map.erase(last->first); + _cache_items_list.pop_back(); + } + } + + const value_t& get(const key_t& key) { + auto it = _cache_items_map.find(key); + if (it == _cache_items_map.end()) { + throw std::range_error("There is no such key in cache"); + } else { + _cache_items_list.splice(_cache_items_list.begin(), _cache_items_list, it->second); + return it->second->second; + } + } + + bool exists(const key_t& key) const { + return _cache_items_map.find(key) != _cache_items_map.end(); + } + + size_t size() const { + return _cache_items_map.size(); + } + +private: + std::list _cache_items_list; + std::unordered_map _cache_items_map; + size_t _max_size; +}; + +} // namespace cache + +#endif /* _LRUCACHE_HPP_INCLUDED_ */ + diff --git a/src/core/misc/color.cpp b/src/core/misc/color.cpp index 73452be..c5af376 100644 --- a/src/core/misc/color.cpp +++ b/src/core/misc/color.cpp @@ -1,2 +1,5 @@ #include "color.h" +const linear_color linear_color::white = { 1.0f, 1.0f, 1.0f, 1.0f }; +const linear_color linear_color::black = { 0.0f, 0.0f, 0.0f, 1.0f }; +const linear_color linear_color::transparent = { 0.0f, 0.0f, 0.0f, 1.0f }; diff --git a/src/core/misc/color.h b/src/core/misc/color.h index 5020c32..194a41e 100644 --- a/src/core/misc/color.h +++ b/src/core/misc/color.h @@ -52,8 +52,7 @@ public: float r, g, b, a; - - inline static const linear_color white = { 1.0f, 1.0f, 1.0f, 1.0f }; - inline static const linear_color black = { 0.0f, 0.0f, 0.0f, 1.0f }; - inline static const linear_color transparent = { 0.0f, 0.0f, 0.0f, 1.0f }; + static const linear_color white; + static const linear_color black; + static const linear_color transparent; }; diff --git a/src/renderer/CMakeLists.txt b/src/renderer/CMakeLists.txt index 5b4d8ed..d9b7bd5 100644 --- a/src/renderer/CMakeLists.txt +++ b/src/renderer/CMakeLists.txt @@ -1,69 +1,22 @@ project(aorii_renderer) find_package(harfbuzz REQUIRED) -find_package(msdfgen REQUIRED) find_package(Eigen3 REQUIRED) find_package(spdlog REQUIRED) find_package(glfw3 REQUIRED) -find_package(Stb REQUIRED) - -cmake_policy(SET CMP0167 NEW) -find_package(Boost REQUIRED COMPONENTS flyweight icl) - -set(GL_BACKEND FALSE CACHE BOOL "OpenGL backend to use") -set(DX_BACKEND FALSE CACHE BOOL "DirectX backend to use") -set(VK_BACKEND FALSE CACHE BOOL "Vulkan backend to use") -set(METAL_BACKEND FALSE CACHE BOOL "Metal backend to use") - -if (NOT GL_BACKEND AND NOT DX_BACKEND AND NOT VK_BACKEND AND NOT METAL_BACKEND) - message(FATAL_ERROR "No backend selected") -endif() +find_package(Boost REQUIRED COMPONENTS flyweight) +find_package(Freetype REQUIRED) set(RENDERER_SOURCES "") -retrieve_files(core RENDERER_SOURCES) -retrieve_files(misc RENDERER_SOURCES) -if (GL_BACKEND) - retrieve_files(backend/gl RENDERER_SOURCES) -endif() -if (DX_BACKEND) - retrieve_files(backend/dx RENDERER_SOURCES) -endif () -if (VK_BACKEND) - retrieve_files(backend/vk RENDERER_SOURCES) -endif () -if (METAL_BACKEND) - retrieve_files(backend/metal RENDERER_SOURCES) -endif () +retrieve_files(${CMAKE_CURRENT_SOURCE_DIR} RENDERER_SOURCES) add_library(${PROJECT_NAME} STATIC ${RENDERER_SOURCES}) -target_link_libraries(${PROJECT_NAME} PUBLIC harfbuzz::harfbuzz Eigen3::Eigen spdlog::spdlog glfw aorii_core msdfgen::msdfgen Boost::boost) -target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${Stb_INCLUDE_DIR}) +target_link_libraries(${PROJECT_NAME} PUBLIC harfbuzz Eigen3::Eigen spdlog::spdlog glfw aorii_core msdfgen-full Boost::boost LLGL) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(${PROJECT_NAME} PRIVATE NOMINMAX) add_os_definitions(${PROJECT_NAME}) configure_glfw_native(${PROJECT_NAME}) -set(ALL_BACKENDS GL_BACKEND DX_BACKEND VK_BACKEND METAL_BACKEND) -if (GL_BACKEND) - target_compile_definitions(${PROJECT_NAME} PUBLIC GL_BACKEND=1) - list(REMOVE_ITEM ALL_BACKENDS GL_BACKEND) -endif() -if (DX_BACKEND) - target_compile_definitions(${PROJECT_NAME} PUBLIC DX_BACKEND=1) - list(REMOVE_ITEM ALL_BACKENDS DX_BACKEND) - target_link_libraries(${PROJECT_NAME} PRIVATE d3d11 d3dcompiler dxgi) -endif () -if (VK_BACKEND) - target_compile_definitions(${PROJECT_NAME} PUBLIC VK_BACKEND=1) - list(REMOVE_ITEM ALL_BACKENDS VK_BACKEND) -endif () -if (METAL_BACKEND) - target_compile_definitions(${PROJECT_NAME} PUBLIC METAL_BACKEND=1) - list(REMOVE_ITEM ALL_BACKENDS METAL_BACKEND) -endif () -foreach(BACKEND ${ALL_BACKENDS}) - target_compile_definitions(${PROJECT_NAME} PUBLIC ${BACKEND}=0) -endforeach() - # 添加编译shader的自定义命令 if (NOT DEFINED SHADER_OUTPUT_DIR) set(SHADER_OUTPUT_DIR ${CMAKE_BINARY_DIR}/shaders CACHE PATH "Output directory for compiled shaders") diff --git a/src/renderer/backend/gl/gl_renderer.cpp b/src/renderer/backend/gl/gl_renderer.cpp deleted file mode 100644 index 1052439..0000000 --- a/src/renderer/backend/gl/gl_renderer.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "gl_renderer.h" - -#include -#include // 或 - -GLenum GetOpenGLInternalFormat(texture_format format) { - switch (format) { - // 8-bit formats - case texture_format::R8_UNORM: - return GL_R8; - case texture_format::R8_SNORM: - return GL_R8_SNORM; - case texture_format::R8_UINT: - return GL_R8UI; - case texture_format::R8_SINT: - return GL_R8I; - - // 16-bit formats - case texture_format::RG8_UNORM: - return GL_RG8; - case texture_format::RG8_SNORM: - return GL_RG8_SNORM; - case texture_format::RG8_UINT: - return GL_RG8UI; - case texture_format::RG8_SINT: - return GL_RG8I; - - // 24-bit formats - case texture_format::RGB8_UNORM: - return GL_RGB8; - case texture_format::RGB8_SNORM: - return GL_RGB8_SNORM; - case texture_format::RGB8_UINT: - return GL_RGB8UI; - case texture_format::RGB8_SINT: - return GL_RGB8I; - - // 32-bit formats - case texture_format::RGBA8_UNORM: - return GL_RGBA8; - case texture_format::RGBA8_SNORM: - return GL_RGBA8_SNORM; - case texture_format::RGBA8_UINT: - return GL_RGBA8UI; - case texture_format::RGBA8_SINT: - return GL_RGBA8I; - - // SRGB formats - case texture_format::SRGB8: - return GL_SRGB8; - case texture_format::SRGB8_ALPHA8: - return GL_SRGB8_ALPHA8; - - // 16-bit float formats - case texture_format::R16_FLOAT: - return GL_R16F; - case texture_format::RG16_FLOAT: - return GL_RG16F; - case texture_format::RGB16_FLOAT: - return GL_RGB16F; - case texture_format::RGBA16_FLOAT: - return GL_RGBA16F; - - // 32-bit float formats - case texture_format::R32_FLOAT: - return GL_R32F; - case texture_format::RG32_FLOAT: - return GL_RG32F; - case texture_format::RGB32_FLOAT: - return GL_RGB32F; - case texture_format::RGBA32_FLOAT: - return GL_RGBA32F; - - // Integer formats - case texture_format::R16_UINT: - return GL_R16UI; - case texture_format::R16_SINT: - return GL_R16I; - case texture_format::RG16_UINT: - return GL_RG16UI; - case texture_format::RG16_SINT: - return GL_RG16I; - case texture_format::RGBA16_UINT: - return GL_RGBA16UI; - case texture_format::RGBA16_SINT: - return GL_RGBA16I; - case texture_format::R32_UINT: - return GL_R32UI; - case texture_format::R32_SINT: - return GL_R32I; - case texture_format::RG32_UINT: - return GL_RG32UI; - case texture_format::RG32_SINT: - return GL_RG32I; - case texture_format::RGBA32_UINT: - return GL_RGBA32UI; - case texture_format::RGBA32_SINT: - return GL_RGBA32I; - - // Depth/stencil formats - case texture_format::D16_UNORM: - return GL_DEPTH_COMPONENT16; - case texture_format::D24_UNORM_S8_UINT: - return GL_DEPTH24_STENCIL8; - case texture_format::D32_FLOAT: - return GL_DEPTH_COMPONENT32F; - case texture_format::D32_FLOAT_S8X24_UINT: - return GL_DEPTH32F_STENCIL8; - - // Compressed formats - case texture_format::BC1_UNORM: - return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - case texture_format::BC3_UNORM: - return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - - default: - return 0; // Unsupported format - } -} diff --git a/src/renderer/backend/gl/gl_renderer.h b/src/renderer/backend/gl/gl_renderer.h deleted file mode 100644 index 8450ad4..0000000 --- a/src/renderer/backend/gl/gl_renderer.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#include "core/renderer/renderer.h" - -class gl_renderer : public renderer { - -}; diff --git a/src/renderer/backend/metal/texture_format.cpp b/src/renderer/backend/metal/texture_format.cpp deleted file mode 100644 index 578570c..0000000 --- a/src/renderer/backend/metal/texture_format.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include - -MTLPixelFormat GetMetalPixelFormat(texture_format format) { - switch (format) { - // 8-bit formats - case texture_format::R8_UNORM: - return MTLPixelFormatR8Unorm; - case texture_format::R8_SNORM: - return MTLPixelFormatR8Snorm; - case texture_format::R8_UINT: - return MTLPixelFormatR8Uint; - case texture_format::R8_SINT: - return MTLPixelFormatR8Sint; - - // 16-bit formats - case texture_format::RG8_UNORM: - return MTLPixelFormatRG8Unorm; - case texture_format::RG8_SNORM: - return MTLPixelFormatRG8Snorm; - case texture_format::RG8_UINT: - return MTLPixelFormatRG8Uint; - case texture_format::RG8_SINT: - return MTLPixelFormatRG8Sint; - - // 24-bit formats - case texture_format::RGB8_UNORM: - return MTLPixelFormatRGB8Unorm; - case texture_format::RGB8_SNORM: - return MTLPixelFormatRGB8Snorm; - case texture_format::RGB8_UINT: - return MTLPixelFormatRGB8Uint; - case texture_format::RGB8_SINT: - return MTLPixelFormatRGB8Sint; - - // 32-bit formats - case texture_format::RGBA8_UNORM: - return MTLPixelFormatRGBA8Unorm; - case texture_format::RGBA8_SNORM: - return MTLPixelFormatRGBA8Snorm; - case texture_format::RGBA8_UINT: - return MTLPixelFormatRGBA8Uint; - case texture_format::RGBA8_SINT: - return MTLPixelFormatRGBA8Sint; - - // SRGB formats - case texture_format::SRGB8: - return MTLPixelFormatBGRA8Unorm_sRGB; - case texture_format::SRGB8_ALPHA8: - return MTLPixelFormatRGBA8Unorm_sRGB; - - // 16-bit float formats - case texture_format::R16_FLOAT: - return MTLPixelFormatR16Float; - case texture_format::RG16_FLOAT: - return MTLPixelFormatRG16Float; - case texture_format::RGBA16_FLOAT: - return MTLPixelFormatRGBA16Float; - - // 32-bit float formats - case texture_format::R32_FLOAT: - return MTLPixelFormatR32Float; - case texture_format::RG32_FLOAT: - return MTLPixelFormatRG32Float; - case texture_format::RGBA32_FLOAT: - return MTLPixelFormatRGBA32Float; - - // Integer formats - case texture_format::R16_UINT: - return MTLPixelFormatR16Uint; - case texture_format::R16_SINT: - return MTLPixelFormatR16Sint; - case texture_format::RG16_UINT: - return MTLPixelFormatRG16Uint; - case texture_format::RG16_SINT: - return MTLPixelFormatRG16Sint; - case texture_format::RGBA16_UINT: - return MTLPixelFormatRGBA16Uint; - case texture_format::RGBA16_SINT: - return MTLPixelFormatRGBA16Sint; - case texture_format::R32_UINT: - return MTLPixelFormatR32Uint; - case texture_format::R32_SINT: - return MTLPixelFormatR32Sint; - case texture_format::RG32_UINT: - return MTLPixelFormatRG32Uint; - case texture_format::RG32_SINT: - return MTLPixelFormatRG32Sint; - case texture_format::RGBA32_UINT: - return MTLPixelFormatRGBA32Uint; - case texture_format::RGBA32_SINT: - return MTLPixelFormatRGBA32Sint; - - // Depth/stencil formats - case texture_format::D16_UNORM: - return MTLPixelFormatDepth16Unorm; - case texture_format::D24_UNORM_S8_UINT: - return MTLPixelFormatDepth24Unorm_Stencil8; - case texture_format::D32_FLOAT: - return MTLPixelFormatDepth32Float; - case texture_format::D32_FLOAT_S8X24_UINT: - return MTLPixelFormatDepth32Float_Stencil8; - - // Compressed formats - case texture_format::BC1_UNORM: - return MTLPixelFormatBC1_RGBA; - case texture_format::BC3_UNORM: - return MTLPixelFormatBC3_RGBA; - - default: - return MTLPixelFormatInvalid; // Unsupported format - } -} diff --git a/src/renderer/backend/vk/texture_forma.cpp b/src/renderer/backend/vk/texture_forma.cpp deleted file mode 100644 index 6bb6159..0000000 --- a/src/renderer/backend/vk/texture_forma.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include - -VkFormat GetVulkanFormat(texture_format format) { - switch (format) { - // 8-bit formats - case texture_format::R8_UNORM: - return VK_FORMAT_R8_UNORM; - case texture_format::R8_SNORM: - return VK_FORMAT_R8_SNORM; - case texture_format::R8_UINT: - return VK_FORMAT_R8_UINT; - case texture_format::R8_SINT: - return VK_FORMAT_R8_SINT; - - // 16-bit formats - case texture_format::RG8_UNORM: - return VK_FORMAT_R8G8_UNORM; - case texture_format::RG8_SNORM: - return VK_FORMAT_R8G8_SNORM; - case texture_format::RG8_UINT: - return VK_FORMAT_R8G8_UINT; - case texture_format::RG8_SINT: - return VK_FORMAT_R8G8_SINT; - - // 24-bit formats - case texture_format::RGB8_UNORM: - return VK_FORMAT_R8G8B8_UNORM; - case texture_format::RGB8_SNORM: - return VK_FORMAT_R8G8B8_SNORM; - case texture_format::RGB8_UINT: - return VK_FORMAT_R8G8B8_UINT; - case texture_format::RGB8_SINT: - return VK_FORMAT_R8G8B8_SINT; - - // 32-bit formats - case texture_format::RGBA8_UNORM: - return VK_FORMAT_R8G8B8A8_UNORM; - case texture_format::RGBA8_SNORM: - return VK_FORMAT_R8G8B8A8_SNORM; - case texture_format::RGBA8_UINT: - return VK_FORMAT_R8G8B8A8_UINT; - case texture_format::RGBA8_SINT: - return VK_FORMAT_R8G8B8A8_SINT; - - // SRGB formats - case texture_format::SRGB8: - return VK_FORMAT_R8G8B8_SRGB; - case texture_format::SRGB8_ALPHA8: - return VK_FORMAT_R8G8B8A8_SRGB; - - // 16-bit float formats - case texture_format::R16_FLOAT: - return VK_FORMAT_R16_SFLOAT; - case texture_format::RG16_FLOAT: - return VK_FORMAT_R16G16_SFLOAT; - case texture_format::RGB16_FLOAT: - return VK_FORMAT_R16G16B16_SFLOAT; - case texture_format::RGBA16_FLOAT: - return VK_FORMAT_R16G16B16A16_SFLOAT; - - // 32-bit float formats - case texture_format::R32_FLOAT: - return VK_FORMAT_R32_SFLOAT; - case texture_format::RG32_FLOAT: - return VK_FORMAT_R32G32_SFLOAT; - case texture_format::RGB32_FLOAT: - return VK_FORMAT_R32G32B32_SFLOAT; - case texture_format::RGBA32_FLOAT: - return VK_FORMAT_R32G32B32A32_SFLOAT; - - // Integer formats - case texture_format::R16_UINT: - return VK_FORMAT_R16_UINT; - case texture_format::R16_SINT: - return VK_FORMAT_R16_SINT; - case texture_format::RG16_UINT: - return VK_FORMAT_R16G16_UINT; - case texture_format::RG16_SINT: - return VK_FORMAT_R16G16_SINT; - case texture_format::RGBA16_UINT: - return VK_FORMAT_R16G16B16A16_UINT; - case texture_format::RGBA16_SINT: - return VK_FORMAT_R16G16B16A16_SINT; - case texture_format::R32_UINT: - return VK_FORMAT_R32_UINT; - case texture_format::R32_SINT: - return VK_FORMAT_R32_SINT; - case texture_format::RG32_UINT: - return VK_FORMAT_R32G32_UINT; - case texture_format::RG32_SINT: - return VK_FORMAT_R32G32_SINT; - case texture_format::RGBA32_UINT: - return VK_FORMAT_R32G32B32A32_UINT; - case texture_format::RGBA32_SINT: - return VK_FORMAT_R32G32B32A32_SINT; - - // Depth/stencil formats - case texture_format::D16_UNORM: - return VK_FORMAT_D16_UNORM; - case texture_format::D24_UNORM_S8_UINT: - return VK_FORMAT_D24_UNORM_S8_UINT; - case texture_format::D32_FLOAT: - return VK_FORMAT_D32_SFLOAT; - case texture_format::D32_FLOAT_S8X24_UINT: - return VK_FORMAT_D32_SFLOAT_S8_UINT; - - // Compressed formats - case texture_format::BC1_UNORM: - return VK_FORMAT_BC1_RGB_UNORM_BLOCK; - case texture_format::BC3_UNORM: - return VK_FORMAT_BC3_UNORM_BLOCK; - - default: - return VK_FORMAT_UNDEFINED; // Unsupported format - } -} diff --git a/src/renderer/core/fonts/composite_font.cpp b/src/renderer/core/fonts/composite_font.cpp deleted file mode 100644 index 01e625a..0000000 --- a/src/renderer/core/fonts/composite_font.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "composite_font.h" - -#include "misc/mapped_file.h" - -struct font_face_data_lazy_load : font_face_data::font_face_data_impl { - explicit font_face_data_lazy_load(const std::wstring& in_filename) { - mapped_file file; - if (!file.map_file(in_filename)) - return; - - font_data.resize(file.get_size()); - std::memcpy(font_data.data(), file.get_data(), file.get_size()); - } - - [[nodiscard]] bool empty() const noexcept override { return font_data.empty(); } - [[nodiscard]] uint8_t const* data() const noexcept override { return font_data.data(); } - [[nodiscard]] size_t size() const noexcept override { return font_data.size(); } - - std::vector font_data; -}; - -struct font_face_data_stream : font_face_data::font_face_data_impl { - explicit font_face_data_stream(const std::wstring& in_filename) { - file.map_file(in_filename); - } - - [[nodiscard]] bool empty() const noexcept override { return file.is_mapped(); } - [[nodiscard]] uint8_t const* data() const noexcept override { return static_cast(file.get_data()); } - [[nodiscard]] size_t size() const noexcept override { return file.get_size(); } - - mapped_file file; -}; - -font_face_data::font_face_data(const std::wstring& in_filename, font_loading_policy in_loading_policy) { - switch (in_loading_policy) { - case font_loading_policy::LAZY_LOAD: - impl = std::make_unique(in_filename); - break; - case font_loading_policy::STREAM: - impl = std::make_unique(in_filename); - break; - } -} diff --git a/src/renderer/core/fonts/composite_font.h b/src/renderer/core/fonts/composite_font.h deleted file mode 100644 index 6ac251b..0000000 --- a/src/renderer/core/fonts/composite_font.h +++ /dev/null @@ -1,160 +0,0 @@ -#pragma once -#include -#include - -#include "font_rasterization_mode.h" -#include -#include -#include -#include -#include - -// 字体渲染的hinting方式 -enum class font_hinting { - // 使用字体的默认hinting方式 - DEFAULT, - // 强制使用FreeType的自动hinting算法 - AUTO, - // 强制针对非单色显示器优化的hinting算法 - AUTO_LIGHT, - // 强制针对单色显示器优化的hinting算法 - MONOCHROME, - // 不使用hinting - NONE -}; - -// 字体加载策略 -enum class font_loading_policy { - // 将内存中的字体数据全部加载到内存中, 适用于字体文件较小的情况 - LAZY_LOAD, - // 流式加载字体数据, 适用于字体文件较大的情况 - STREAM, -}; - -// 字体布局方式 -enum class font_layout_method { - // 使用字体内置的度量信息进行布局, 但某些字体的度量信息可能不准确 - METRICS, - // 使用字体边界值进行布局, 通常会有较大的行高, 但适用于字体度量信息不准确的情况 - BOUNDING_BOX -}; - -struct font_face_data { - struct font_face_data_impl { - virtual ~font_face_data_impl() = default; - [[nodiscard]] virtual bool empty() const noexcept = 0; - [[nodiscard]] virtual uint8_t const* data() const noexcept = 0; - [[nodiscard]] virtual size_t size() const noexcept = 0; - }; -public: - font_face_data() = default; - - explicit font_face_data(const std::wstring& in_filename, font_loading_policy in_loading_policy); - - [[nodiscard]] bool empty() const noexcept { return impl->empty(); } - [[nodiscard]] uint8_t const* data() const noexcept { return impl->data(); } - [[nodiscard]] size_t size() const noexcept { return impl->size(); } -private: - std::unique_ptr impl; -}; - -using font_face_data_ptr = std::shared_ptr; -using font_face_data_const_ptr = std::shared_ptr; - -// 字体渲染设置 -struct font_rasterization_settings { - // 字体栅格化方式 - font_rasterization_mode mode = font_rasterization_mode::BITMAP; - // 距离场px/em分辨率, 如果是位图则不生效 - int32_t distance_field_ppem = 0; -}; - -class font_data { -public: - font_data(); - font_data(const std::wstring& in_font_filename, font_hinting in_hinting, font_loading_policy in_loading_policy, int32_t in_sub_face_index = 0); - [[nodiscard]] bool has_font() const; - - [[nodiscard]] const std::wstring& get_font_filename() const noexcept { return font_filename; } - [[nodiscard]] font_hinting get_hinting() const noexcept { return hinting; } - [[nodiscard]] font_loading_policy get_loading_policy() const noexcept { return loading_policy; } - [[nodiscard]] int32_t get_sub_face_index() const noexcept { return sub_face_index; } - void set_sub_face_index(const int32_t in_sub_face_index) noexcept { sub_face_index = in_sub_face_index; } - [[nodiscard]] font_layout_method get_layout_method() const noexcept { return layout_method; } - void set_font_layout_method(font_layout_method in_layout_method) noexcept { layout_method = in_layout_method; } - - [[nodiscard]] int32_t get_strike_line_height_percentage() const { return 60; } - - [[nodiscard]] font_rasterization_settings get_rasterization_settings() const { return {}; } -private: - std::wstring font_filename; - uint32_t font_filename_hash; - font_hinting hinting; - font_loading_policy loading_policy; - font_layout_method layout_method; - int32_t sub_face_index; -}; - -class typeface_entry { -public: - typeface_entry() = default; - explicit typeface_entry(const boost::flyweight& in_name) : name(std::move(in_name)) {} - - typeface_entry(const boost::flyweight& in_name, const std::wstring& in_font_filename, const font_hinting in_hinting, - const font_loading_policy in_loading_policy) : name(std::move(in_name)), - font(in_font_filename, in_hinting, - in_loading_policy) { - } - - [[nodiscard]] const boost::flyweight& get_name() const noexcept { return name; } - [[nodiscard]] const font_data& get_font() const noexcept { return font; } - // 字体名称 - boost::flyweight name; - // 字体数据 - font_data font; -}; - -class typeface { -public: - typeface() = default; - explicit typeface(const std::wstring& in_font_name, const std::wstring& in_font_filename, const font_hinting in_hinting, const font_loading_policy in_loading_policy) { - append_font(in_font_name, in_font_filename, in_hinting, in_loading_policy); - } - - typeface& append_font(const std::wstring& in_font_name, const std::wstring& in_font_filename, const font_hinting in_hinting, const font_loading_policy in_loading_policy) { - fonts.emplace_back(in_font_name, in_font_filename, in_hinting, in_loading_policy); - return *this; - } - - [[nodiscard]] const std::vector& get_fonts() const noexcept { return fonts; } - - std::vector fonts; -}; - -class composite_fallback_font { -public: - composite_fallback_font() : scaling_factor(1.0f) {} - - typeface fallback_typeface; - float scaling_factor; -}; - -class composite_subfont : public composite_fallback_font { -public: - std::vector character_ranges; - std::wstring cultures; -}; - -class composite_font { -public: - [[nodiscard]] bool is_ascent_descent_override_enabled() const { - return enable_ascent_descent_override; - } - - typeface default_typeface; - composite_fallback_font fallback_typeface; - std::vector sub_typefaces; -private: - bool enable_ascent_descent_override = true; -}; - diff --git a/src/renderer/core/fonts/font_cache.cpp b/src/renderer/core/fonts/font_cache.cpp deleted file mode 100644 index 5578804..0000000 --- a/src/renderer/core/fonts/font_cache.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "font_cache.h" - diff --git a/src/renderer/core/fonts/font_cache.h b/src/renderer/core/fonts/font_cache.h deleted file mode 100644 index ecb44ee..0000000 --- a/src/renderer/core/fonts/font_cache.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once -#include -#include - -#include "text_shaper.h" - -enum class font_cache_atlas_data_type { - REGULAR, - OUTLINE, - NUM -}; - -enum class text_shaping_method { - AUTO, - KERNING_ONLY, - FULL_SHAPING -}; - -struct shaped_glyph_font_atlas_data { - // 从baseline到字形位图最上边框的垂直距离 - int16_t vertical_offset = 0; - // 从原点到字形位图最左边框的水平距离 - int16_t horizontal_offset = 0; - uint16_t start_u = 0; - uint16_t start_v = 0; - uint16_t u_size = 0; - uint16_t v_size = 0; - uint8_t texture_index = 0; - bool supports_outline = false; - bool valid = false; -}; - -struct sdf_glyph_font_atlas_data { - int16_t vertical_offset = 0; - int16_t horizontal_offset = 0; - uint16_t start_u = 0; - uint16_t start_v = 0; - uint16_t u_size = 0; - uint16_t v_size = 0; - float em_outer_spread = 0.f; - float em_inner_spread = 0.f; - - struct metrics { - float bearing_x = 0.f; - float bearing_y = 0.f; - float width = 0.f; - float height = 0.f; - }; - - metrics sdf_metrics; - uint8_t texture_index = 0; - bool supports_sdf = false; - bool pending_respawn = false; - bool valid = false; -}; - -struct shaped_glyph_entry { - friend class font_cache; - - std::shared_ptr font_face_data; - uint32_t glyph_index = 0; - int32_t source_index = 0; - int16_t x_advance = 0; - int16_t y_advance = 0; - int16_t x_offset = 0; - int16_t y_offset = 0; - int8_t kerning = 0; - uint8_t num_characters_in_glyph = 0; - uint8_t num_grapheme_clusters_in_glyph = 0; - -}; - -class character_list { -public: -}; - -class font_cache { - -}; diff --git a/src/renderer/core/fonts/font_cache_composite_font.cpp b/src/renderer/core/fonts/font_cache_composite_font.cpp deleted file mode 100644 index d03f403..0000000 --- a/src/renderer/core/fonts/font_cache_composite_font.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "font_cache_composite_font.h" - -cached_typeface_data::cached_typeface_data(): typeface_(nullptr), scaling_factor_(1.f) { -} - -cached_typeface_data::cached_typeface_data(const typeface& in_typeface, float in_scaling_factor): typeface_(&in_typeface), - scaling_factor_(in_scaling_factor) { - for (const auto& typeface_entry : typeface_->fonts) { - cached_font_data_.emplace_back(typeface_entry.name, &typeface_entry.font); - } - std::sort(cached_font_data_.begin(), cached_font_data_.end(), [](const auto& lhs, const auto& rhs) { - return lhs.first < rhs.first; - }); - std::ranges::sort(cached_font_data_, &cached_font_data::sort_predicate); -} - -const font_data* cached_typeface_data::get_font_data(const boost::flyweight& in_name) const { - const auto it = std::ranges::lower_bound(cached_font_data_, in_name, &cached_font_data::key_sort_predicate, &cached_font_data::binary_search_key); - if (it != cached_font_data_.end() && *it == in_name) { - const auto index = std::distance(cached_font_data_.begin(), it); - return cached_font_data_[index].font_data; - } - return nullptr; -} - -void cached_typeface_data::get_cached_font_data(std::vector& out_font_data) const { - for (const auto& font_entry : cached_font_data_) { - out_font_data.push_back(font_entry.font_data); - } -} - -cached_composite_font_data::cached_composite_font_data(): composite_font_(nullptr) { -} - -cached_composite_font_data::cached_composite_font_data(const composite_font& in_composite_font): composite_font_(&in_composite_font) { - cached_typefaces_.push_back(std::make_shared(composite_font_->default_typeface)); - cached_typefaces_.push_back(std::make_shared(composite_font_->fallback_typeface.fallback_typeface, composite_font_->fallback_typeface.scaling_factor)); - for (const auto& sub_typeface : composite_font_->sub_typefaces) { - auto cached_typeface = std::make_shared(sub_typeface.fallback_typeface, sub_typeface.scaling_factor); - cached_typefaces_.push_back(cached_typeface); - } - refresh_font_ranges(); -} - -auto cached_composite_font_data::get_typeface_for_codepoint(char32_t in_codepoint) const { - int32_t char_index = in_codepoint; - - auto get_typeface_from_range = [char_index](const std::vector& in_font_ranges) -> const cached_typeface_data* { - auto get_typeface_from_range_index = [char_index, &in_font_ranges](const int32_t in_range_index) -> cached_typeface_data* { - bool is_valid_index = in_range_index >= 0 && in_range_index < static_cast(in_font_ranges.size()); - if (!is_valid_index) - return nullptr; - bool is_contains = boost::icl::contains(in_font_ranges[in_range_index].range, char_index); - if (!is_contains) - return nullptr; - return in_font_ranges[in_range_index].cached_typeface.get(); - }; - - if (in_font_ranges.empty() || char_index < in_font_ranges.front().range.lower() || char_index > in_font_ranges.back().range.upper()) - return nullptr; - - const auto found_range_index = std::ranges::lower_bound(in_font_ranges, char_index, - &cached_font_range::sort_predicate, - &cached_font_range::binary_search_key); - const int32_t range_index = std::distance(in_font_ranges.begin(), found_range_index); - - if (range_index < 0 || range_index >= static_cast(in_font_ranges.size())) - return nullptr; - - if (auto range_typeface = get_typeface_from_range_index(range_index)) - return range_typeface; - if (auto range_typeface = get_typeface_from_range_index(range_index - 1)) - return range_typeface; - return nullptr; - }; - - if (auto typeface = get_typeface_from_range(cached_priority_font_ranges_)) - return typeface; - if (auto typeface = get_typeface_from_range(cached_font_ranges_)) - return typeface; - return cached_typefaces_[cached_typeface_default_index].get(); -} - -void cached_composite_font_data::get_cached_font_data(std::vector& out_font_data) const { - for (const auto& typeface : cached_typefaces_) { - typeface->get_cached_font_data(out_font_data); - } -} - -void cached_composite_font_data::refresh_font_ranges() { - const auto prioritized_culture_names = composite_font_->get_prioritized_culture_names(); -} diff --git a/src/renderer/core/fonts/font_cache_composite_font.h b/src/renderer/core/fonts/font_cache_composite_font.h deleted file mode 100644 index a6150eb..0000000 --- a/src/renderer/core/fonts/font_cache_composite_font.h +++ /dev/null @@ -1,111 +0,0 @@ -#pragma once -#include "composite_font.h" -#include "boost/flyweight.hpp" -#include - -class freetype_library; - -class cached_typeface_data { -public: - cached_typeface_data(); - cached_typeface_data(const typeface& in_typeface, float in_scaling_factor = 1.f); - - [[nodiscard]] const auto& get_typeface() const { - return typeface_; - } - - [[nodiscard]] auto get_scaling_factor() const { - return scaling_factor_; - } - - [[nodiscard]] auto get_primary_font_data() const { - return typeface_->fonts.size() > 0 ? &typeface_->fonts[0] : nullptr; - } - - [[nodiscard]] const font_data* get_font_data(const boost::flyweight& in_name) const; - - void get_cached_font_data(std::vector& out_font_data) const; -private: - struct cached_font_data { - cached_font_data() : font_data(nullptr) {} - cached_font_data(const boost::flyweight& in_name, const font_data* in_font_data) : name(in_name), font_data(in_font_data) {} - - static auto binary_search_key(const cached_font_data& in_cached_font_data) { - return in_cached_font_data.name; - } - - static bool key_sort_predicate(const boost::flyweight& lhs, const boost::flyweight& rhs) { - return lhs < rhs; - } - - static bool sort_predicate(const cached_font_data& lhs, const cached_font_data& rhs) { - return key_sort_predicate(lhs.name, rhs.name); - } - - boost::flyweight name; - const font_data* font_data; - }; - const typeface* typeface_; - std::vector cached_font_data_; - float scaling_factor_; -}; - -class cached_composite_font_data { -public: - cached_composite_font_data(); - cached_composite_font_data(const composite_font& in_composite_font); - - [[nodiscard]] const auto& get_composite_font() const { - return composite_font_; - } - - [[nodiscard]] auto get_default_typeface() const { - return cached_typefaces_[cached_typeface_default_index].get(); - } - - [[nodiscard]] auto get_fallback_typeface() const { - return cached_typefaces_[cached_typeface_fallback_index].get(); - } - - [[nodiscard]] auto get_typeface_for_codepoint(char32_t in_codepoint) const; - - void get_cached_font_data(std::vector& out_font_data) const; - - void refresh_font_ranges(); -private: - struct cached_font_range { - cached_font_range() : range(), cached_typeface(nullptr) {} - - cached_font_range(const boost::icl::discrete_interval& in_code_points, - const std::shared_ptr& in_cached_typeface) : range(in_code_points), cached_typeface(in_cached_typeface) { - } - - static int32_t binary_search_key(const cached_font_range& in_cached_font_range) { - return in_cached_font_range.range.lower(); - } - - static bool sort_predicate(const int32_t& lhs, const int32_t& rhs) { - return lhs < rhs; - } - - mutable boost::icl::discrete_interval range; - std::shared_ptr cached_typeface; - }; - - static constexpr int32_t cached_typeface_default_index = 0; - static constexpr int32_t cached_typeface_fallback_index = 1; - static constexpr int32_t cached_typeface_first_sub_typeface_index = 2; - - const composite_font* composite_font_; - std::vector> cached_typefaces_; - std::vector cached_priority_font_ranges_; - std::vector cached_font_ranges_; -}; - -class composite_font_cache { -public: - composite_font_cache(const freetype_library* in_library); - ~composite_font_cache(); - - const font_data& get_default_font_data(); -}; diff --git a/src/renderer/core/fonts/font_cache_freetype.cpp b/src/renderer/core/fonts/font_cache_freetype.cpp deleted file mode 100644 index 1fcf4ae..0000000 --- a/src/renderer/core/fonts/font_cache_freetype.cpp +++ /dev/null @@ -1,529 +0,0 @@ -// Copyright Epic Games, Inc. All Rights Reserved. - -#include "font_cache_freetype.h" - -#include - -namespace freetype_memory { - static void* alloc(FT_Memory memory, long size) { - return std::malloc(size); - } - - static void* realloc(FT_Memory memory, long cur_size, long new_size, void* block) { - return std::realloc(block, new_size); - } - - static void free(FT_Memory memory, void* block) { - std::free(block); - } -} - -namespace freetype_utils { - bool is_face_eligible_for_sdf(FT_Face in_face) { - return in_face && !FT_IS_TRICKY(in_face) && FT_IS_SCALABLE(in_face) && (!FT_HAS_FIXED_SIZES(in_face) || in_face->num_glyphs > 0); - } - - bool is_glyph_eligible_for_sdf(FT_GlyphSlot in_glyph) { - return in_glyph && in_glyph->format == FT_GLYPH_FORMAT_OUTLINE; - } - - FT_F26Dot6 frac_26dot6(const FT_F26Dot6 in_value) { - return in_value & 63; - } - - FT_F26Dot6 floor_26dot6(const FT_F26Dot6 in_value) { - return in_value & -64; - } - - FT_F26Dot6 ceil_26dot6(const FT_F26Dot6 in_value) { - return floor_26dot6(in_value + 63); - } - - FT_F26Dot6 round_26dot6(const FT_F26Dot6 in_value) { - return floor_26dot6(in_value + 32); - } - - FT_F26Dot6 determine_26dot6_ppem(const float in_font_size, const float in_font_scale, const bool in_round_ppem) { - FT_F26Dot6 ppem = FT_MulFix( - (convert_pixel_to_26dot6(std::max(0.f, in_font_size)) * (FT_Long)font_constants::render_dpi + 36) / 72, - convert_pixel_to_16dot16(std::max(0.f, in_font_scale)) - ); - if (in_round_ppem) { - ppem = round_26dot6(ppem); - } - return ppem; - } - - FT_Fixed determine_em_scale(const uint16_t in_em_size, const FT_F26Dot6 in_ppem) { - return FT_DivFix(in_ppem, std::max(uint16_t{1}, in_em_size)); - } - - FT_Fixed determine_ppem_and_em_scale(const uint16_t in_em_size, const float in_font_size, const float in_font_scale, const bool in_round_ppem) { - return determine_em_scale(in_em_size, determine_26dot6_ppem(in_font_size, in_font_scale, in_round_ppem)); - } - - uint32_t compute_font_pixel_size(float in_font_size, float in_font_scale) { - // 转换为固定比例以获得最大精度 - const FT_F26Dot6 fixed_font_size = convert_pixel_to_26dot6(std::max(0.f, in_font_size)); - const FT_Long fixed_font_scale = convert_pixel_to_16dot16(std::max(0.f, in_font_scale)); - - // 根据我们的渲染DPI和请求的比例,将请求的字体大小转换为像素大小 - - // 将26.6字符大小转换为未缩放的26.6像素大小 - // 注意:此处的逻辑与在使用FT_Set_Char_Size时FT_REQUEST_WIDTH和FT_REQUEST_HEIGHT内部执行的逻辑相同 - FT_F26Dot6 required_fixed_font_pixel_size = (fixed_font_size * FT_Pos{font_constants::render_dpi} + 36) / 72; - - // 将26.6像素大小按照期望的16.16分数缩放值进行缩放。 - required_fixed_font_pixel_size = FT_MulFix(required_fixed_font_pixel_size, fixed_font_scale); - - return convert_26dot6_to_rounded_pixel(required_fixed_font_pixel_size); - } - - void apply_size_and_scale(FT_Face in_face, const float in_font_size, const float in_font_scale) { - apply_size_and_scale(in_face, compute_font_pixel_size(in_font_size, in_font_scale)); - } - - void apply_size_and_scale(FT_Face in_face, const uint32_t required_font_pixel_size) { - if (FT_IS_SCALABLE(in_face)) { - FT_Error error = FT_Set_Pixel_Sizes(in_face, 0, required_font_pixel_size); - if (error) { - spdlog::error("无法设置字体大小:{}", error); - assert(false); - } - } else if (FT_HAS_FIXED_SIZES(in_face)) { - FT_F26Dot6 required_fixed_font_pixel_size = convert_pixel_to_26dot6(required_font_pixel_size); - - int32_t best_strike_index = -1; - { - FT_F26Dot6 running_best_fixed_strike_height = 0; - for (int32_t potential_strike_index = 0; potential_strike_index < in_face->num_fixed_sizes; ++potential_strike_index) { - const FT_F26Dot6 potential_fixed_strike_height = in_face->available_sizes[potential_strike_index].y_ppem; - - // 如果我们找到一个完美的匹配,我们就可以停止了 - if (potential_fixed_strike_height == required_fixed_font_pixel_size) { - best_strike_index = potential_strike_index; - break; - } - - // 第一次迭代时,我们将选择一个最接近的匹配 - if (best_strike_index == -1) { - best_strike_index = potential_strike_index; - running_best_fixed_strike_height = potential_fixed_strike_height; - continue; - } - - // 我们当前的笔画尺寸比所需尺寸小,因此选择此尺寸作为我们的当前笔画尺寸 - if (running_best_fixed_strike_height < required_fixed_font_pixel_size) { - // 但前提是它扩大到我们的所需尺寸 - if (potential_fixed_strike_height > running_best_fixed_strike_height) { - best_strike_index = potential_strike_index; - running_best_fixed_strike_height = potential_fixed_strike_height; - } - continue; - } - - // 我们当前的笔画尺寸比所需尺寸大,因此选择此尺寸作为我们的当前笔画尺寸 - if (running_best_fixed_strike_height > required_fixed_font_pixel_size) { - // 但前提是它缩小到我们的所需尺寸 - if (potential_fixed_strike_height < running_best_fixed_strike_height) { - best_strike_index = potential_strike_index; - running_best_fixed_strike_height = potential_fixed_strike_height; - } - } - } - } - - assert(best_strike_index != -1); - FT_Error error = FT_Select_Size(in_face, best_strike_index); - if (error) { - spdlog::error("无法选择字体大小:{}", error); - assert(false); - } - - FT_Long fixed_strike_scale = 0; - { - // 将26.6的值转换为16.16的空间,以便我们可以使用FT_DivFix - const FT_Long required_fixed_font_pixel_size_16dot16 = required_fixed_font_pixel_size << 10; - const FT_Long beat_fixed_strike_height_16dot16 = in_face->available_sizes[best_strike_index].y_ppem << 10; - fixed_strike_scale = FT_DivFix(required_fixed_font_pixel_size_16dot16, beat_fixed_strike_height_16dot16); - } - - // 固定大小字体不使用 x_scale/y_scale 值,所以我们使用它们来存储我们需要应用于位图的缩放调整(作为16.16分数缩放值),以将其缩放到我们期望的像素大小 - // 注意:从技术上讲,度量应该是只读的,所以如果这造成问题,那么我们将不得不将信息添加到 freetype_face 中,然后通过传递给调用 apply_size_and_scale 的所有内容。 - in_face->size->metrics.x_scale = fixed_strike_scale; - in_face->size->metrics.y_scale = fixed_strike_scale; - } - } - - FT_Error load_glyph(FT_Face in_face, const uint32_t in_glyph_index, const uint32_t in_load_flags, const float in_font_size, const float in_font_scale) { - return load_glyph(in_face, in_glyph_index, in_load_flags, compute_font_pixel_size(in_font_size, in_font_scale)); - } - - FT_Error load_glyph(FT_Face in_face, const uint32_t in_glyph_index, const int32_t in_load_flags, const uint32_t in_required_font_pixel_size) { - assert(!(in_load_flags & FT_LOAD_NO_SCALE)); - apply_size_and_scale(in_face, in_required_font_pixel_size); - return FT_Load_Glyph(in_face, in_glyph_index, in_load_flags); - } - - FT_Pos get_height(FT_Face in_face, const font_layout_method in_layout_method) { - if (FT_IS_SCALABLE(in_face)) { - return in_layout_method == font_layout_method::METRICS - ? FT_Pos{ in_face->height } - : in_face->bbox.yMax - in_face->bbox.yMin; - } - if (FT_HAS_FIXED_SIZES(in_face)) { - return in_face->size->metrics.height; - } - return 0; - } - - FT_Pos get_scaled_height(FT_Face in_face, const font_layout_method in_layout_method) { - if (FT_IS_SCALABLE(in_face)) { - return FT_MulFix( - in_layout_method == font_layout_method::METRICS ? in_face->height : in_face->bbox.yMax - in_face->bbox.yMin, - in_face->size->metrics.y_scale - ); - } - if (FT_HAS_FIXED_SIZES(in_face)) { - return FT_MulFix(in_face->size->metrics.height, in_face->size->metrics.y_scale); - } - return 0; - } - - FT_Pos get_ascender(FT_Face in_face, const font_layout_method in_layout_method) { - if (FT_IS_SCALABLE(in_face)) { - return FT_MulFix( - in_layout_method == font_layout_method::METRICS ? FT_Pos{ in_face->ascender } : in_face->bbox.yMax, - in_face->size->metrics.y_scale - ); - } - if (FT_HAS_FIXED_SIZES(in_face)) { - return FT_MulFix(in_face->size->metrics.ascender, in_face->size->metrics.y_scale); - } - return 0; - } - - FT_Pos get_descender(FT_Face in_face, const font_layout_method in_layout_method) { - if (FT_IS_SCALABLE(in_face)) { - return FT_MulFix( - in_layout_method == font_layout_method::METRICS ? FT_Pos{ in_face->descender } : in_face->bbox.yMin, - in_face->size->metrics.y_scale - ); - } - if (FT_HAS_FIXED_SIZES(in_face)) { - return FT_MulFix(in_face->size->metrics.descender, in_face->size->metrics.y_scale); - } - return 0; - } - - float get_bitmap_atlas_scale(FT_Face in_face) { - if (!FT_IS_SCALABLE(in_face) && FT_HAS_FIXED_SIZES(in_face)) { - // 我们只将图像缩小以适应图集 - // 如果它们小于我们期望的尺寸,我们就让它们在渲染时在 GPU 上进行缩放(请参阅 get_bitmap_render_scale) - if (in_face->size->metrics.x_scale < convert_pixel_to_16dot16(1)) { - // 固定大小字体不支持缩放,但我们在 apply_size_and_scale 中计算了要用于字形的缩放比例 - return static_cast(in_face->size->metrics.x_scale) / 65536.f; // 16.16 -> pixel scale - } - } - return 1.f; - } - - float get_bitmap_render_scale(FT_Face in_face) { - if (!FT_IS_SCALABLE(in_face) && FT_HAS_FIXED_SIZES(in_face)) { - // 我们只在渲染时才放大图像 - // 如果它们大于我们期望的尺寸,我们会在它们进入图集之前对它们进行缩放(请参阅 get_bitmap_atlas_scale) - if (in_face->size->metrics.x_scale < convert_pixel_to_16dot16(1)) { - // 固定大小字体不支持缩放,但我们在 apply_size_and_scale 中计算了用于字形的缩放比例 - return static_cast(in_face->size->metrics.x_scale) / 65536.f; // 16.16 -> pixel scale - } - } - return 1.f; - } -} - -freetype_library::freetype_library() { - custom_memory = static_cast(malloc(sizeof(*custom_memory))); - custom_memory->alloc = freetype_memory::alloc; - custom_memory->realloc = freetype_memory::realloc; - custom_memory->free = freetype_memory::free; - custom_memory->user = nullptr; - - FT_Error error = FT_New_Library(custom_memory, &library); - if (error) { - spdlog::critical("无法创建FreeType库:{}", error); - } - - FT_Add_Default_Modules(library); - - FT_UInt interpreter_version = TT_INTERPRETER_VERSION_40; - error = FT_Property_Set(library, "truetype", "interpreter-version", &interpreter_version); - - static bool logged_version = false; - if (!logged_version) { - FT_Int major = 0; - FT_Int minor = 0; - FT_Int patch = 0; - FT_Library_Version(library, &major, &minor, &patch); - spdlog::info("FreeType版本 {}.{}.{}", major, minor, patch); - logged_version = true; - } -} - -freetype_library::~freetype_library() { - FT_Done_Library(library); - free(custom_memory); -} - -freetype_face::freetype_face(const freetype_library* in_library, font_face_data_const_ptr in_memory, - const int32_t in_face_index, const font_layout_method in_layout_method) { - face = nullptr; - pending_async_load = true; - layout_method = in_layout_method; - complete_async_load(in_library, in_memory, in_face_index); -} - -freetype_face::freetype_face(const font_layout_method in_layout_method) { - face = nullptr; - pending_async_load = true; - layout_method = in_layout_method; -} - -freetype_face::~freetype_face() { - if (!face) - return; - - FT_Done_Face(face); -} - -void freetype_face::fail_async_load() { - pending_async_load = false; -} - -void freetype_face::complete_async_load(const freetype_library* in_library, font_face_data_const_ptr in_memory, const int32_t in_face_index) { - pending_async_load = false; - - face = nullptr; - memory = std::move(in_memory); - - FT_Error error = FT_New_Memory_Face(in_library->get_library(), memory->data(), memory->size(), in_face_index, &face); - if (error) { - spdlog::error("无法加载字体:{}", error); - face = nullptr; - } - - parse_styles(); -} - -std::vector freetype_face::get_available_sub_faces(const freetype_library* in_library, font_face_data_const_ptr in_memory) { - std::vector result; - - FT_Face face = nullptr; - FT_Error error = FT_New_Memory_Face(in_library->get_library(), in_memory->data(), in_memory->size(), -1, &face); - if (!face) - return result; - - const int32_t num_faces = face->num_faces; - FT_Done_Face(face); - face = nullptr; - - result.reserve(num_faces); - for (int i = 0; i < num_faces; ++i) { - FT_New_Memory_Face(in_library->get_library(), in_memory->data(), in_memory->size(), i, &face); - if (!face) - continue; - - result.emplace_back(face->style_name); - FT_Done_Face(face); - face = nullptr; - } - - return result; -} - -void freetype_face::parse_styles() { - if (!face) - return; - - std::string style_name = face->style_name; - if (style_name.empty()) - return; - - // 将样式按照空格分割 - size_t start = 0; - size_t end = 0; - while (end != std::string::npos) { - end = style_name.find(' ', start); - styles.push_back(style_name.substr(start, end - start)); - start = end + 1; - } -} - -freetype_glyph_cache::freetype_glyph_cache(FT_Face in_face, const int32_t in_load_flags, const float in_font_size, - const float in_font_scale) : face(in_face), load_flags(in_load_flags), font_render_size(freetype_utils::compute_font_pixel_size(in_font_size, in_font_scale)) { - -} - -bool freetype_glyph_cache::find_or_cache(const uint32_t in_glyph_index, cached_glyph_data& out) { - if (auto found_cached_glyph_data = glyph_data_map.find(in_glyph_index); found_cached_glyph_data != glyph_data_map.end()) { - out = found_cached_glyph_data->second; - return true; - } - - FT_Error error = freetype_utils::load_glyph(face, in_glyph_index, load_flags, font_render_size); - if (error) { - spdlog::error("无法加载字形:{}", error); - return false; - } - - out = {}; - out.height = face->height; - out.glyph_metrics = face->glyph->metrics; - out.size_metrics = face->size->metrics; - - if (face->glyph->outline.n_points > 0) { - const int32_t num_points = face->glyph->outline.n_points; - out.outline_points.resize(num_points); - for (int32_t i = 0; i < num_points; ++i) { - out.outline_points[i] = face->glyph->outline.points[i]; - } - } - - glyph_data_map[in_glyph_index] = out; - return true; -} - -freetype_advance_cache::freetype_advance_cache() :face(nullptr), load_flags(), font_render_size() { -} - -freetype_advance_cache::freetype_advance_cache(FT_Face in_face, int32_t in_load_flags, float in_font_size, - float in_font_scale) : face(in_face), load_flags(in_load_flags), - font_render_size( - 0 != (in_load_flags & FT_LOAD_NO_SCALE) ? - freetype_utils::determine_ppem_and_em_scale(in_face->units_per_EM, in_font_size, in_font_scale, true) : - freetype_utils::compute_font_pixel_size(in_font_size, in_font_scale) - ) { - assert(((load_flags & FT_LOAD_NO_SCALE) == 0) || freetype_utils::is_face_eligible_for_sdf(face)); -} - -bool freetype_advance_cache::find_or_cache(uint32_t in_glyph_index, FT_Fixed& out) { - if (!face) - return false; - if (const auto found_advance = advance_map.find(in_glyph_index); found_advance != advance_map.end()) { - out = found_advance->second; - return true; - } - - if ((load_flags & FT_LOAD_NO_SCALE) != 0) { - const FT_Error error = FT_Get_Advance(face, in_glyph_index, load_flags, &out); - if (error) { - spdlog::error("无法获取字形进度:{}", error); - return false; - } - FT_Long em_scale = font_render_size; - out = FT_MulDiv(out, em_scale, FT_Long{ 64L }); - advance_map[in_glyph_index] = out; - return true; - } - - freetype_utils::apply_size_and_scale(face, font_render_size); - - const FT_Error error = FT_Get_Advance(face, in_glyph_index, load_flags, &out); - if (error) { - spdlog::error("无法获取字形进度:{}", error); - return false; - } - - if (!FT_IS_SCALABLE(face) && FT_HAS_FIXED_SIZES(face)) { - out = FT_MulFix(out, load_flags & FT_LOAD_VERTICAL_LAYOUT ? face->size->metrics.y_scale : face->size->metrics.x_scale); - } - - advance_map[in_glyph_index] = out; - return true; -} - -freetype_kerning_cache::freetype_kerning_cache(FT_Face in_face, int32_t in_kerning_flags, float in_font_size, - float in_font_scale) : face(in_face), kerning_flags(in_kerning_flags), font_render_size( - in_kerning_flags == FT_KERNING_UNSCALED ? - freetype_utils::determine_ppem_and_em_scale(in_face->units_per_EM, in_font_size, in_font_scale, true) : - freetype_utils::compute_font_pixel_size(in_font_size, in_font_scale) - ) { - assert(face); - assert(FT_HAS_KERNING(face)); - assert(kerning_flags != FT_KERNING_UNSCALED || freetype_utils::is_face_eligible_for_sdf(face)); -} - -bool freetype_kerning_cache::find_or_cache(uint32_t in_first_glyph_index, uint32_t in_second_glyph_index, - FT_Vector& out) { - const kerning_pair kerning_key(in_first_glyph_index, in_second_glyph_index); - if (const auto found_kerning = kerning_map.find(kerning_key); found_kerning != kerning_map.end()) { - out = found_kerning->second; - return true; - } - - if (kerning_flags == FT_KERNING_UNSCALED) { - const FT_Error error = FT_Get_Kerning(face, in_first_glyph_index, in_second_glyph_index, kerning_flags, &out); - if (error) { - spdlog::error("无法获取字形间距:{}", error); - return false; - } - FT_Long em_scale = font_render_size; - out.x = FT_MulFix(out.x, em_scale); - out.y = FT_MulFix(out.y, em_scale); - kerning_map[kerning_key] = out; - return true; - } - - freetype_utils::apply_size_and_scale(face, font_render_size); - - const FT_Error error = FT_Get_Kerning(face, in_first_glyph_index, in_second_glyph_index, kerning_flags, &out); - if (error) { - spdlog::error("无法获取字形间距:{}", error); - return false; - } - - if (!FT_IS_SCALABLE(face) && FT_HAS_FIXED_SIZES(face)) { - out.x = FT_MulFix(out.x, face->size->metrics.x_scale); - out.y = FT_MulFix(out.y, face->size->metrics.y_scale); - } - kerning_map[kerning_key] = out; - return true; -} - -freetype_cache_directory::freetype_cache_directory() : invalid_advance_cache(std::make_shared()) { -} - -std::shared_ptr freetype_cache_directory::get_glyph_cache(FT_Face in_face, int32_t in_flags, - float in_font_size, float in_font_scale) { - const font_key key(in_face, in_flags, in_font_size, in_font_scale); - auto result = glyph_cache_map.try_emplace(key, std::make_shared(in_face, in_flags, in_font_size, in_font_scale)); - return result.first->second; -} - -std::shared_ptr freetype_cache_directory::get_advance_cache(FT_Face in_face, int32_t in_flags, - float in_font_size, float in_font_scale) { - const font_key key(in_face, in_flags, in_font_size, in_font_scale); - auto result = advance_cache_map.try_emplace(key, std::make_shared(in_face, in_flags, in_font_size, in_font_scale)); - return result.first->second; -} - -std::shared_ptr freetype_cache_directory::get_kerning_cache(FT_Face in_face, int32_t in_flags, - float in_font_size, float in_font_scale) { - if (!in_face) - return nullptr; - if (!FT_HAS_KERNING(in_face)) - return nullptr; - if (in_flags == FT_KERNING_UNFITTED) - return nullptr; - if (!freetype_utils::is_face_eligible_for_sdf(in_face)) - return nullptr; - - const font_key key(in_face, in_flags, in_font_size, in_font_scale); - auto result = kerning_cache_map.try_emplace(key, std::make_shared(in_face, in_flags, in_font_size, in_font_scale)); - return result.first->second; -} - -void freetype_cache_directory::flush_cache() { - glyph_cache_map.clear(); - advance_cache_map.clear(); - kerning_cache_map.clear(); -} diff --git a/src/renderer/core/fonts/font_cache_freetype.h b/src/renderer/core/fonts/font_cache_freetype.h deleted file mode 100644 index 0748a50..0000000 --- a/src/renderer/core/fonts/font_cache_freetype.h +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright Epic Games, Inc. All Rights Reserved. - -#pragma once - -#include -#include -#include -#include - -#include "composite_font.h" -#include "ft2build.h" -#include "misc/type_hash.h" - -#include FT_GLYPH_H -#include FT_MODULE_H -#include FT_BITMAP_H -#include FT_ADVANCES_H -#include FT_STROKER_H -#include FT_SIZES_H -#include FT_DRIVER_H - -namespace font_constants { - inline constexpr uint32_t render_dpi = 96; -} - -enum class font_fallback { - no_fallback, - last_resort_fallback, - max_fallback, -}; - -namespace freetype_utils { - /** - * 检查字体是否适合生成SDF - * @param in_face 字体 - * @return 是否适合生成SDF - */ - bool is_face_eligible_for_sdf(FT_Face in_face); - - /** - * 检查字形是否适合生成SDF - * @param in_glyph 字形 - * @return 是否适合生成SDF - */ - bool is_glyph_eligible_for_sdf(FT_GlyphSlot in_glyph); - - FT_F26Dot6 frac_26dot6(FT_F26Dot6 in_value); - - /** - * 将26.6空间中的值向上取整 - * @param in_value 输入值 - * @return 向上取整后的值 - */ - FT_F26Dot6 floor_26dot6(FT_F26Dot6 in_value); - - /** - * 将26.6空间中的值向下取整 - * @param in_value 输入值 - * @return 向下取整后的值 - */ - FT_F26Dot6 ceil_26dot6(FT_F26Dot6 in_value); - - /** - * 将26.6空间中的值四舍五入 - * @param in_value 输入值 - * @return - */ - FT_F26Dot6 round_26dot6(FT_F26Dot6 in_value); - - /** - * 从以点为单位的字体大小(每英寸72点)和96 dpi分辨率下的任意UI缩放确定(可选四舍五入)像素尺寸(每em平方维度的像素数) - * @param in_font_size 字体大小 - * @param in_font_scale UI缩放 - * @param in_round_ppem 每em平方维度的像素数 - * @return - */ - FT_F26Dot6 determine_26dot6_ppem(float in_font_size, float in_font_scale, bool in_round_ppem); - - /** - * EmScale将设计空间距离(相对于em方块,分辨率为InEmSize单位)映射到设备像素平面中的绝对1/64像素距离(96 dpi分辨率) - * @param in_em_size 字符大小 - * @param in_ppem 每em平方维度的像素数 - * @return - */ - FT_Fixed determine_em_scale(uint16_t in_em_size, FT_F26Dot6 in_ppem); - - /** - * 在一次调用中确定(可选四舍五入)ppem,然后根据它确定EmScale - * @param in_em_size - * @param in_font_size - * @param in_font_scale - * @param in_round_ppem - * @return - */ - FT_Fixed determine_ppem_and_em_scale(uint16_t in_em_size, float in_font_size, float in_font_scale, bool in_round_ppem); - - uint32_t compute_font_pixel_size(float in_font_size, float in_font_scale); - - void apply_size_and_scale(FT_Face in_face, float in_font_size, float in_font_scale); - - void apply_size_and_scale(FT_Face in_face, uint32_t required_font_pixel_size); - - FT_Error load_glyph(FT_Face in_face, uint32_t in_glyph_index, uint32_t in_load_flags, float in_font_size, float in_font_scale); - FT_Error load_glyph(FT_Face in_face, uint32_t in_glyph_index, int32_t in_load_flags, uint32_t in_required_font_pixel_size); - - FT_Pos get_height(FT_Face in_face, font_layout_method in_layout_method); - FT_Pos get_scaled_height(FT_Face in_face, font_layout_method in_layout_method); - FT_Pos get_ascender(FT_Face in_face, font_layout_method in_layout_method); - FT_Pos get_descender(FT_Face in_face, font_layout_method in_layout_method); - - float get_bitmap_atlas_scale(FT_Face in_face); - float get_bitmap_render_scale(FT_Face in_face); - - template - std::enable_if_t, ret_type> convert_26dot6_to_rounded_pixel(param_type in_value) { - return static_cast((in_value + (1 << 5)) >> 6); - } - - template - std::enable_if_t, ret_type> convert_26dot6_to_rounded_pixel(param_type in_value) { - return static_cast(std::round(in_value / 64.0)); - } - - template - std::enable_if_t, ret_type> convert_pixel_to_26dot6(param_type in_value) { - return static_cast(in_value << 6); - } - - template - std::enable_if_t, ret_type> convert_pixel_to_26dot6(param_type in_value) { - return static_cast(in_value * 64.0); - } - - template - std::enable_if_t, ret_type> convert_pixel_to_16dot16(param_type in_value) { - return static_cast(in_value << 16); - } - - template - std::enable_if_t, ret_type> convert_pixel_to_16dot16(param_type in_value) { - return static_cast(in_value * 65536); - } -} - -class freetype_library { -public: - freetype_library(); - ~freetype_library(); - - [[nodiscard]] FT_Library get_library() const noexcept { return library; } -private: - FT_Library library; - FT_Memory custom_memory; -}; - -class freetype_face { -public: - freetype_face(const freetype_library* in_library, font_face_data_const_ptr in_memory, int32_t in_face_index, font_layout_method in_layout_method); - - explicit freetype_face(font_layout_method in_layout_method); - ~freetype_face(); - - [[nodiscard]] bool is_face_valid() const noexcept { return face != nullptr; } - [[nodiscard]] bool is_face_loading() const noexcept { return pending_async_load; } - [[nodiscard]] bool support_sdf() const noexcept { return freetype_utils::is_face_eligible_for_sdf(face); } - - [[nodiscard]] FT_Face get_face() const noexcept { return face; } - - [[nodiscard]] FT_Pos get_height() const { return freetype_utils::get_height(face, layout_method); } - [[nodiscard]] FT_Pos get_scaled_height() const { return freetype_utils::get_scaled_height(face, layout_method); } - [[nodiscard]] FT_Pos get_ascender(bool in_allow_override) const { - if (in_allow_override && ascent_override.has_value()) { - FT_F26Dot6 scaled_ascender = FT_MulFix(ascent_override.value(), face->size->metrics.y_scale); - return scaled_ascender + 0b111111 & ~0b111111; //(26.6固定点向上取整)。使用缩放上升的天花板,正如Freetype建议的那样,以避免网格拟合/提示问题。 - } - return freetype_utils::get_ascender(face, layout_method); - } - [[nodiscard]] FT_Pos get_descender(bool in_allow_override) const { - if (in_allow_override && descent_override.has_value()) { - FT_F26Dot6 scaled_descender = FT_MulFix(descent_override.value(), face->size->metrics.y_scale); - return scaled_descender + 0b111111 & ~0b111111; //(26.6固定点向下取整)。使用缩放下降的地板,正如Freetype建议的那样,以避免网格拟合/提示问题。 - } - return freetype_utils::get_descender(face, layout_method); - } - - [[nodiscard]] float get_bitmap_atlas_scale() const { return freetype_utils::get_bitmap_atlas_scale(face); } - [[nodiscard]] float get_bitmap_render_scale() const { return freetype_utils::get_bitmap_render_scale(face); } - - [[nodiscard]] const auto& get_styles() const noexcept { return styles; } - [[nodiscard]] font_layout_method get_layout_method() const noexcept { return layout_method; } - - void override_ascent(bool in_override, const int32_t in_value = 0) { - if (in_override) { - ascent_override = freetype_utils::convert_pixel_to_26dot6(in_value); - } else { - ascent_override.reset(); - } - } - void override_descent(bool in_override, const int32_t in_value = 0) { - if (in_override) { - descent_override = freetype_utils::convert_pixel_to_26dot6(in_value); - } else { - descent_override.reset(); - } - } - - void fail_async_load(); - void complete_async_load(const freetype_library* in_library, font_face_data_const_ptr in_memory, int32_t in_face_index); - - static std::vector get_available_sub_faces(const freetype_library* in_library, font_face_data_const_ptr in_memory); -private: - void parse_styles(); - - FT_Face face; - font_face_data_const_ptr memory; - - bool pending_async_load = false; - - std::optional ascent_override; - std::optional descent_override; - font_layout_method layout_method; - std::vector styles; -}; - -class freetype_glyph_cache { -public: - struct cached_glyph_data { - FT_Short height; - FT_Glyph_Metrics glyph_metrics; - FT_Size_Metrics size_metrics; - std::vector outline_points; - }; - - freetype_glyph_cache(FT_Face in_face, int32_t in_load_flags, float in_font_size, float in_font_scale); - [[nodiscard]] bool find_or_cache(uint32_t in_glyph_index, cached_glyph_data& out); -private: - FT_Face face; - const int32_t load_flags; - const uint32_t font_render_size; - std::unordered_map glyph_data_map; -}; - -class freetype_advance_cache { -public: - freetype_advance_cache(); - freetype_advance_cache(FT_Face in_face, int32_t in_load_flags, float in_font_size, float in_font_scale); - - bool find_or_cache(uint32_t in_glyph_index, FT_Fixed& out); -private: - FT_Face face; - const int32_t load_flags; - const uint32_t font_render_size; - std::unordered_map advance_map; -}; - -struct kerning_pair { - kerning_pair(uint32_t in_first_glyph_index, uint32_t in_second_glyph_index) : first_glyph_index( - in_first_glyph_index), second_glyph_index(in_second_glyph_index) { - } - - bool operator==(const kerning_pair& other) const { - return first_glyph_index == other.first_glyph_index && second_glyph_index == other.second_glyph_index; - } - - bool operator!=(const kerning_pair& other) const { return !(*this == other); } - - uint32_t first_glyph_index; - uint32_t second_glyph_index; -}; -namespace std { - template<> - struct hash - { - std::size_t operator()(const kerning_pair& key) const - { - return hash_combine(get_type_hash(key.first_glyph_index), get_type_hash(key.second_glyph_index)); - } - }; -} - -class font_key { -public: - font_key(FT_Face in_face, int32_t in_flags, float in_font_size, float in_font_scale) : face(in_face), - flags(in_flags), font_render_size(freetype_utils::compute_font_pixel_size(in_font_size, in_font_scale)), - key_hash() { - key_hash = get_type_hash(face); - key_hash = hash_combine(key_hash, get_type_hash(flags)); - key_hash = hash_combine(key_hash, get_type_hash(font_render_size)); - } - - bool operator==(const font_key& other) const { - return face == other.face && flags == other.flags && font_render_size == other.font_render_size; - } - - bool operator!=(const font_key& other) const { return !(*this == other); } - - friend uint32_t get_type_hash(const font_key& in_key) { return in_key.key_hash; } - -private: - FT_Face face; - const int32_t flags; - const uint32_t font_render_size; - uint32_t key_hash; -}; - -namespace std -{ - template<> - struct hash - { - std::size_t operator()(const font_key& key) const - { - return get_type_hash(key); - } - }; -} - -class freetype_kerning_cache { -public: - freetype_kerning_cache(FT_Face in_face, int32_t in_kerning_flags, float in_font_size, float in_font_scale); - - bool find_or_cache(uint32_t in_first_glyph_index, uint32_t in_second_glyph_index, FT_Vector& out); -private: - FT_Face face; - const int32_t kerning_flags; - const uint32_t font_render_size; - std::unordered_map kerning_map; -}; - -class freetype_cache_directory { -public: - freetype_cache_directory(); - std::shared_ptr get_glyph_cache(FT_Face in_face, int32_t in_flags, float in_font_size, float in_font_scale); - std::shared_ptr get_advance_cache(FT_Face in_face, int32_t in_flags, float in_font_size, float in_font_scale); - std::shared_ptr get_kerning_cache(FT_Face in_face, int32_t in_flags, float in_font_size, float in_font_scale); - - void flush_cache(); -private: - std::unordered_map> glyph_cache_map; - std::unordered_map> advance_cache_map; - std::unordered_map> kerning_cache_map; - std::shared_ptr invalid_advance_cache; -}; diff --git a/src/renderer/core/fonts/font_info.cpp b/src/renderer/core/fonts/font_info.cpp deleted file mode 100644 index d799d58..0000000 --- a/src/renderer/core/fonts/font_info.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "font_info.h" - -font_info::font_info(const std::shared_ptr& in_composite_font, float in_size, - const boost::flyweight& in_typeface_font_name, const font_outline_settings& in_outline_settings) : - outline_settings(in_outline_settings), font(in_composite_font), typeface_font_name(in_typeface_font_name), size(in_size) { -} - -font_info::font_info(const std::string& in_font_name, float in_size, - const font_outline_settings& in_outline_settings) : outline_settings(in_outline_settings), - typeface_font_name(in_font_name), - size(in_size) { - upgrade_legacy_font(boost::flyweight{ in_font_name }, font_hinting::DEFAULT); -} - -font_info::font_info(const boost::flyweight& in_typeface_font_name, float in_size, - const font_outline_settings& in_outline_settings) : outline_settings(in_outline_settings), - typeface_font_name(in_typeface_font_name), - size(in_size) { - upgrade_legacy_font(in_typeface_font_name, font_hinting::DEFAULT); -} - -bool font_info::has_valid_font() const { - return font != nullptr; -} - -const composite_font* font_info::get_composite_font() const { - return font.get(); -} - -float font_info::get_clamp_size() const { - GetWeightFromFT(); -} - -float font_info::get_clamp_skew() const { -} - -void font_info::upgrade_legacy_font(boost::flyweight in_legacy_font_name, font_hinting in_hinting) { -} diff --git a/src/renderer/core/fonts/font_info.h b/src/renderer/core/fonts/font_info.h deleted file mode 100644 index f833647..0000000 --- a/src/renderer/core/fonts/font_info.h +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once -#include - -#include "composite_font.h" -#include "font_cache_freetype.h" -#include "misc/color.h" - -struct font_outline_settings { - font_outline_settings() : outline_size(0), mitered_corners(false), separate_fill_alpha(false), - apply_outline_to_drop_shadows(false), outline_color(linear_color::black) { - - } - - font_outline_settings(int32_t in_outline_size, - const linear_color in_color = linear_color::black) : outline_size(in_outline_size), - mitered_corners(false), - separate_fill_alpha(false), - apply_outline_to_drop_shadows(false), - outline_color(in_color) { - - } - - [[nodiscard]] bool is_identical_to_for_caching(const font_outline_settings& other) const { - return outline_size == other.outline_size && - mitered_corners == other.mitered_corners && - separate_fill_alpha == other.separate_fill_alpha; - } - - [[nodiscard]] bool is_identical_to(const font_outline_settings& other) const { - return outline_size == other.outline_size && - mitered_corners == other.mitered_corners && - separate_fill_alpha == other.separate_fill_alpha && - apply_outline_to_drop_shadows == other.apply_outline_to_drop_shadows && - outline_color == other.outline_color; - } - - [[nodiscard]] bool is_visible() const { - return outline_size > 0 && outline_color.a > 0; - } - - int32_t outline_size; - bool mitered_corners; - bool separate_fill_alpha; - bool apply_outline_to_drop_shadows; - linear_color outline_color; - - inline static font_outline_settings no_outline; -}; - -struct font_info { - font_info(const std::shared_ptr& in_composite_font, float in_size, const boost::flyweight& in_typeface_font_name = {}, const font_outline_settings& in_outline_settings = {}); - font_info(const std::string& in_font_name, float in_size, const font_outline_settings& in_outline_settings = {}); - font_info(const boost::flyweight& in_typeface_font_name, float in_size, const font_outline_settings& in_outline_settings = {}); - - [[nodiscard]] bool is_legacy_identical_to(const font_info& other) const { - return outline_settings.is_identical_to_for_caching(other.outline_settings) && - font == other.font && - typeface_font_name == other.typeface_font_name && - get_clamp_size() == other.get_clamp_size(); - } - - [[nodiscard]] bool is_identical_to(const font_info& other) const { - return outline_settings.is_identical_to(other.outline_settings) && - font == other.font && - typeface_font_name == other.typeface_font_name && - size == other.size && - letter_spacing == other.letter_spacing && - skew_amount == other.skew_amount && - fallback_level == other.fallback_level && - force_monospaced == other.force_monospaced && - (force_monospaced ? monospaced_width == other.monospaced_width : true); - } - - [[nodiscard]] bool operator==(const font_info& other) const { - return is_identical_to(other); - } - - [[nodiscard]] bool has_valid_font() const; - [[nodiscard]] const composite_font* get_composite_font() const; - [[nodiscard]] float get_clamp_size() const; - [[nodiscard]] float get_clamp_skew() const; - - font_outline_settings outline_settings; - std::shared_ptr font; - boost::flyweight typeface_font_name; - float size; - int32_t letter_spacing = 0; - float skew_amount = 0.f; - font_fallback fallback_level; - bool force_monospaced = false; - float monospaced_width = 1.f; -private: - void upgrade_legacy_font(boost::flyweight in_legacy_font_name, font_hinting in_hinting); -}; diff --git a/src/renderer/core/fonts/font_manager.h b/src/renderer/core/fonts/font_manager.h new file mode 100644 index 0000000..0341678 --- /dev/null +++ b/src/renderer/core/fonts/font_manager.h @@ -0,0 +1,19 @@ +#pragma once +#include "font_type.h" +#include + +class font_manager { +public: + void set_font_family( + const font_family& name, + const font_path& path, + const font_style style = font_style::regular + ) { + auto& entry = family_paths[name]; + entry[style] = path; + } +private: + using path_entry = std::unordered_map; + + std::unordered_map family_paths{}; +}; diff --git a/src/renderer/core/fonts/font_rasterization_mode.h b/src/renderer/core/fonts/font_rasterization_mode.h deleted file mode 100644 index ac9d4fb..0000000 --- a/src/renderer/core/fonts/font_rasterization_mode.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -// 字体光栅化方式 -enum class font_rasterization_mode { - // 字形按大小和倾斜直接栅格化为 Alpha 掩码位图。 - BITMAP, - // 字形被栅格化为多通道有符号距离字段,这些字段的大小和倾斜无关。 - MSDF, - // 字形被栅格化为单通道有符号距离字段,这些字段的大小和倾斜无关。内存效率更高,但边角可能会显得圆角。 - SDF, - // 字形被栅格化为近似距离字段,这些字段的大小和倾斜无关。内存和计算效率更高,但质量较低。 - SDF_APPROXIMATION -}; - -inline bool is_sdf_font_rasterization_mode(font_rasterization_mode mode) { - switch (mode) { - case font_rasterization_mode::MSDF: - case font_rasterization_mode::SDF: - case font_rasterization_mode::SDF_APPROXIMATION: - return true; - default: - return false; - } -} diff --git a/src/renderer/core/fonts/font_renderer.cpp b/src/renderer/core/fonts/font_renderer.cpp deleted file mode 100644 index 4895428..0000000 --- a/src/renderer/core/fonts/font_renderer.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "font_renderer.h" diff --git a/src/renderer/core/fonts/font_renderer.h b/src/renderer/core/fonts/font_renderer.h deleted file mode 100644 index a2af63f..0000000 --- a/src/renderer/core/fonts/font_renderer.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "font_cache_freetype.h" - -class composite_font_cache; - -struct freetype_face_glyph_data { - std::shared_ptr face_and_memory; - uint32_t glyph_index; - uint32_t glyph_flags; - font_fallback char_fallback_level; - - freetype_face_glyph_data() : face_and_memory(nullptr), glyph_index(0), glyph_flags(0), char_fallback_level(font_fallback::no_fallback) { - } -}; - -namespace font_renderer_utils { - inline const char32_t invalid_sub_char = u'\uFFFD'; - void append_glyph_flags(const freetype_face& in_face, const font_data& in_font_data, uint32_t in_glyph_flags); -} - -class font_renderer { -public: - font_renderer(const freetype_library* in_library, freetype_cache_directory* in_cache_directory, composite_font* in_composite_font_cache); - - uint16_t get_max_height(const font_info) const; -}; diff --git a/src/renderer/core/fonts/font_type.h b/src/renderer/core/fonts/font_type.h new file mode 100644 index 0000000..4926eee --- /dev/null +++ b/src/renderer/core/fonts/font_type.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include + +enum class font_style { + regular = 1 << 1, // 正常 + light = 1 << 2, // 轻体 + thin = 1 << 3, // 细体 + medium = 1 << 4, // 中等 + bold = 1 << 5, // 粗体 + + italic = 1 << 11, // 斜体 + bold_italic = bold | italic, // 粗斜体 + thin_italic = thin | italic, // 细斜体 + light_italic = light | italic, // 轻斜体 + medium_italic = medium | italic, // 中等斜体 +}; + +using font_family = boost::flyweight< + boost::flyweights::key_value, + boost::flyweights::no_tracking +>; + +using font_path = boost::flyweight< + boost::flyweights::key_value, + boost::flyweights::no_tracking +>; diff --git a/src/renderer/core/fonts/glyph_cache.cpp b/src/renderer/core/fonts/glyph_cache.cpp new file mode 100644 index 0000000..8369079 --- /dev/null +++ b/src/renderer/core/fonts/glyph_cache.cpp @@ -0,0 +1,18 @@ +// +// Created by Administrator on 25-2-2. +// +#include "glyph_cache.h" + +void glyph_cache::initialize(LLGL::RenderSystem& in_render_system) { + render_system = &in_render_system; +} + +glyph_metadata glyph_cache::get_glyph(const glyph_key& in_key) { + +} + +glyph_cache::atlas_page* glyph_cache::allocate_space(uint32_t in_width, uint32_t in_height) { + LLGL::TextureDescriptor descriptor{}; + descriptor.type = LLGL::TextureType::Texture2D; + render_system->CreateTexture(descriptor); +} diff --git a/src/renderer/core/fonts/glyph_cache.h b/src/renderer/core/fonts/glyph_cache.h new file mode 100644 index 0000000..04fccd1 --- /dev/null +++ b/src/renderer/core/fonts/glyph_cache.h @@ -0,0 +1,67 @@ +#pragma once +#include +#include +#include + +#include "font_type.h" +#include "containers/lrucache.hpp" +#include "LLGL/RenderSystem.h" + +struct glyph_key { + font_family family{}; + uint32_t code_point{}; + float font_size{}; + float dpi_scale{}; + + bool operator==(const glyph_key& other) const { + return family == other.family && + code_point == other.code_point && + font_size == other.font_size && + dpi_scale == other.dpi_scale; + } +}; + +template <> +struct std::hash { + size_t operator()(const glyph_key& in_key) const noexcept { + size_t hash = 0; + hash_combine(hash, in_key.family.get()); + hash_combine(hash, in_key.code_point); + hash_combine(hash, in_key.font_size); + hash_combine(hash, in_key.dpi_scale); + return hash; + } +private: + template + static void hash_combine(size_t& in_seed, const T& in_v) { + std::hash hasher; + in_seed ^= hasher(in_v) + 0x9e3779b9 + (in_seed << 6) + (in_seed >> 2); + } +}; + +struct glyph_metadata { + LLGL::Texture* atlas_texture; + Eigen::AlignedBox2f uv_rect; + Eigen::Vector2f size; + Eigen::Vector2f bearing; +}; + +class glyph_cache { +public: + void initialize(LLGL::RenderSystem& in_render_system); + glyph_metadata get_glyph(const glyph_key& in_key); +private: + struct atlas_page { + LLGL::Texture* texture = nullptr; + uint32_t current_x = 0; + uint32_t current_y = 0; + uint32_t row_height = 0; + }; + + cache::lru_cache metadata_cache; + std::vector active_atlases; + std::mutex atlas_mutex; + LLGL::RenderSystem* render_system = nullptr; + + atlas_page* allocate_space(uint32_t in_width, uint32_t in_height); +}; diff --git a/src/renderer/core/fonts/sdf_generator.cpp b/src/renderer/core/fonts/sdf_generator.cpp deleted file mode 100644 index acaeee7..0000000 --- a/src/renderer/core/fonts/sdf_generator.cpp +++ /dev/null @@ -1,300 +0,0 @@ -#include "sdf_generator.h" - -#include -#include -#include - -#include -#include - -#include "font_cache_freetype.h" -#include -#include -#include - -#include "core/pixel_format/pixel.h" -#include "misc/scope_exit.h" - -#define MAX_GLYPH_SDF_SIDE 4096 - -static constexpr double SDF_CORNER_ANGLE_THRESHOLD = 3.0; - -static constexpr double SDF_BOUNDS_MITER_LIMIT = 1.0; - -class glyph_sdf_mapping { -public: - void wrap_non_mitered(const msdfgen::Shape::Bounds& in_bounds, const uint16_t in_units_per_em, const int32_t in_ppem, const float in_em_outer_spread) { - wrap(nullptr, in_bounds, in_units_per_em, in_ppem, in_em_outer_spread, 0); - } - - void wrap_mitered(const msdfgen::Shape& msdfgen_shape, const msdfgen::Shape::Bounds& in_bounds, const uint16_t in_units_per_em, const int32_t in_ppem, const float in_em_outer_spread, const double in_miter_limit) { - wrap(&msdfgen_shape, in_bounds, in_units_per_em, in_ppem, in_em_outer_spread, in_miter_limit); - } - - void set_spread(uint16_t in_units_per_em, float in_em_outer_spread, float in_em_inner_spread); - - [[nodiscard]] const auto& get_msdfgen_transformation() const { - return transformation; - } - - [[nodiscard]] int32_t get_sdf_width() const { - return sdf_bounds.max().x() - sdf_bounds.min().x(); - } - - [[nodiscard]] int32_t get_sdf_height() const { - return sdf_bounds.max().y() - sdf_bounds.min().y(); - } - - [[nodiscard]] int32_t get_bearing_x() const { - return sdf_bounds.min().x(); - } - - [[nodiscard]] int32_t get_bearing_y() const { - return sdf_bounds.min().y(); - } -private: - msdfgen::SDFTransformation transformation; - Eigen::AlignedBox2i sdf_bounds; - - void wrap(const msdfgen::Shape* in_shape, msdfgen::Shape::Bounds in_bounds, uint16_t in_units_per_em, int32_t in_ppem, float in_em_outer_spread, double in_miter_limit); -}; - -void glyph_sdf_mapping::set_spread(uint16_t in_units_per_em, float in_em_outer_spread, float in_em_inner_spread) { - const float units_per_em = in_units_per_em; - transformation.distanceMapping = msdfgen::Range(-units_per_em * in_em_outer_spread, units_per_em * in_em_inner_spread); -} - -void glyph_sdf_mapping::wrap(const msdfgen::Shape* in_shape, msdfgen::Shape::Bounds in_bounds, uint16_t in_units_per_em, - int32_t in_ppem, float in_em_outer_spread, double in_miter_limit) { - const float units_per_em = in_units_per_em; - const float unit_scale = float(in_ppem) / units_per_em; - - const float msdfgen_outer_spread = units_per_em * in_em_outer_spread; - in_bounds.l -= msdfgen_outer_spread; - in_bounds.b -= msdfgen_outer_spread; - in_bounds.r += msdfgen_outer_spread; - in_bounds.t += msdfgen_outer_spread; - - if (in_shape && in_miter_limit > 0) { - in_shape->boundMiters(in_bounds.l, in_bounds.b, in_bounds.r, in_bounds.t, msdfgen_outer_spread, in_miter_limit, 1); - } - - in_bounds.l *= unit_scale; - in_bounds.b *= unit_scale; - in_bounds.r *= unit_scale; - in_bounds.t *= unit_scale; - - in_bounds.l -= 0.5; - in_bounds.b -= 0.5; - in_bounds.r += 0.5; - in_bounds.t += 0.5; - - if (in_bounds.l > in_bounds.r) { - in_bounds.l = 0; - in_bounds.r = 0; - } - if (in_bounds.b > in_bounds.t) { - in_bounds.b = 0; - in_bounds.t = 0; - } - - sdf_bounds.min() = Eigen::Vector2i(int(std::floor(in_bounds.l)), int(std::floor(in_bounds.b))); - sdf_bounds.max() = Eigen::Vector2i(int(std::ceil(in_bounds.r)), int(std::ceil(in_bounds.t))); - - const msdfgen::Projection projection( - msdfgen::Vector2(unit_scale), - msdfgen::Vector2(-sdf_bounds.min().x(), -sdf_bounds.min().y()) / unit_scale - ); - const msdfgen::Range range(2); - transformation = msdfgen::SDFTransformation(projection, range); -} - -inline bool freetype_shape_build(std::shared_ptr in_face, uint32_t in_glyph_index, - float in_em_outer_spread, float in_em_inner_spread, int32_t in_ppem, - msdfgen::Shape& out_shape, glyph_sdf_mapping& out_glyph_sdf_mapping) { - if (!freetype_utils::is_face_eligible_for_sdf(in_face->get_face())) return false; - - uint32_t load_flags = FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT | - FT_LOAD_NO_BITMAP; - FT_Error error = FT_Load_Glyph(in_face->get_face(), in_glyph_index, load_flags); - if (error) { - spdlog::error("无法加载字形:{}", error); - return false; - } - - if (!freetype_utils::is_glyph_eligible_for_sdf(in_face->get_face()->glyph) - || in_face->get_face()->glyph->metrics.width <= 0 - || in_face->get_face()->glyph->metrics.height <= 0 - || in_face->get_face()->glyph->outline.n_points <= 0) { return false; } - - error = msdfgen::readFreetypeOutline(out_shape, &in_face->get_face()->glyph->outline, 1.0); - if (error) { - spdlog::error("无法读取字形轮廓:{}", error); - return false; - } - out_shape.inverseYAxis = !out_shape.inverseYAxis; - - msdfgen::Shape::Bounds bounds = out_shape.getBounds(); - msdfgen::Point2 outer_point(bounds.l - (bounds.r - bounds.l) - 1, bounds.b - (bounds.t - bounds.b) - 1); - if (msdfgen::SimpleTrueShapeDistanceFinder::oneShotDistance(out_shape, outer_point) > 0) { - for (auto& contour: out_shape.contours) { contour.reverse(); } - } - - const uint16_t units_per_em = in_face->get_face()->units_per_EM; - out_glyph_sdf_mapping.wrap_mitered(out_shape, bounds, units_per_em, in_ppem, in_em_outer_spread, - SDF_BOUNDS_MITER_LIMIT); - out_glyph_sdf_mapping.set_spread(units_per_em, in_em_outer_spread, in_em_inner_spread); - - return out_glyph_sdf_mapping.get_sdf_width() > 0 && - out_glyph_sdf_mapping.get_sdf_height() > 0 && - out_glyph_sdf_mapping.get_sdf_width() < MAX_GLYPH_SDF_SIDE && - out_glyph_sdf_mapping.get_sdf_height() < MAX_GLYPH_SDF_SIDE; -} - -static int32_t get_num_sdf_channels(sdf_generator::sdf_type in_type) { - switch (in_type) { - case sdf_generator::sdf_type::SIMPLE: - case sdf_generator::sdf_type::PERPENDICULAR: - return 1; - case sdf_generator::sdf_type::MULTICHANNEL_AND_SIMPLE: - return 4; - default: - break; - } - return 0; -} - -class sdf_generator_impl : public sdf_generator { - struct task { - request_descriptor descriptor{}; - std::vector output_pixels; - msdfgen::Shape shape; - glyph_sdf_mapping sdf_mapping; - - request_response prepare(const request_descriptor& in_request, request_output_info& out_char_info) { - auto font_face = in_request.font_face.lock(); - if (font_face && font_face->is_face_loading()) return request_response::BUSY; - - if (!font_face || !font_face->is_face_valid()) return request_response::SDF_UNAVAILABLE; - - if (freetype_shape_build( - font_face, - in_request.glyph_index, - in_request.em_outer_spread, - in_request.em_inner_spread, - in_request.ppem, - shape, - sdf_mapping - )) { - descriptor = in_request; - - out_char_info.image_width = sdf_mapping.get_sdf_width(); - out_char_info.image_height = sdf_mapping.get_sdf_height(); - out_char_info.bearing_x = sdf_mapping.get_bearing_x(); - out_char_info.bearing_y = sdf_mapping.get_bearing_y(); - - return request_response::SUCCESS; - } - return request_response::SDF_UNAVAILABLE; - } - void do_work() { - const bool overlapped_contour_support = true; - const int32_t target_widget = sdf_mapping.get_sdf_width(); - const int32_t target_height = sdf_mapping.get_sdf_height(); - const int32_t target_channels = get_num_sdf_channels(descriptor.type); - const auto float_pixels = new float[target_widget * target_height * target_channels]; - ON_SCOPE_EXIT { - delete[] float_pixels; - }; - output_pixels.resize(target_widget * target_height * target_channels); - - switch (descriptor.type) { - case sdf_type::SIMPLE: { - const msdfgen::BitmapRef bitmap{float_pixels, target_widget, target_height}; - generateSDF( - bitmap, - shape, - sdf_mapping.get_msdfgen_transformation(), - msdfgen::GeneratorConfig{overlapped_contour_support} - ); - break; - } - case sdf_type::PERPENDICULAR: { - const msdfgen::BitmapRef bitmap{float_pixels, target_widget, target_height}; - generatePSDF( - bitmap, - shape, - sdf_mapping.get_msdfgen_transformation(), - msdfgen::GeneratorConfig{overlapped_contour_support} - ); - break; - } - case sdf_type::MULTICHANNEL_AND_SIMPLE: { - const msdfgen::BitmapRef bitmap{float_pixels, target_widget, target_height}; - const msdfgen::MSDFGeneratorConfig config{ - overlapped_contour_support, - msdfgen::ErrorCorrectionConfig{ - msdfgen::ErrorCorrectionConfig::EDGE_PRIORITY, - msdfgen::ErrorCorrectionConfig::CHECK_DISTANCE_AT_EDGE, - msdfgen::ErrorCorrectionConfig::defaultMinDeviationRatio, - msdfgen::ErrorCorrectionConfig::defaultMinImproveRatio, - output_pixels.data() // Temporarily repurpose output buffer as error correction buffer - } - }; - generateMTSDF( - bitmap, - shape, - sdf_mapping.get_msdfgen_transformation(), - config - ); - break; - } - default: - assert(false); // 不应该到达这里 - } - - const size_t end_offset = target_channels * target_widget * target_height; - uint8_t* begin_ptr = output_pixels.data(); - const uint8_t* end_ptr = begin_ptr + end_offset; - - auto src = float_pixels; - for (uint8_t* dst = begin_ptr; dst < end_ptr; ++dst, ++src) { - *dst = msdfgen::pixelFloatToByte(*src); - } - } - }; -public: - sdf_generator_impl(); - ~sdf_generator_impl(); - - request_response spawn(const request_descriptor& in_request, request_output_info& out_char_info) override { - auto new_task = std::make_shared(); - const auto result = new_task->prepare(in_request, out_char_info); - if (result == request_response::SUCCESS) { - auto task_func = [new_task] { - new_task->do_work(); - return new_task; - }; - auto task_callback = [](const std::optional>& in_result) { - if (!in_result) { - return; - } - auto& task = *in_result; - - }; - thread_pool::global().submit_with_callback(task_func, task_callback); - } - return result; - } - request_response respawn(const request_descriptor& in_request, const request_output_info& in_char_info) override { - return request_response::BAD_REQUEST; - } - void update(const for_each_request_done_callback& in_enumerator) override; - void flush() override; -private: - void sdf_task_done(); -}; - -std::unique_ptr sdf_generator::create() { - return std::make_unique(); -} diff --git a/src/renderer/core/fonts/sdf_generator.h b/src/renderer/core/fonts/sdf_generator.h deleted file mode 100644 index bd10be5..0000000 --- a/src/renderer/core/fonts/sdf_generator.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once -#include -#include -#include -#include - -#include -#include -#include - -class freetype_face; - -class sdf_generator { -public: - enum class request_response { - SUCCESS = 0, - SDF_UNAVAILABLE, - BUSY, - BAD_REQUEST, - }; - - enum class sdf_type { - SIMPLE, - PERPENDICULAR, - MULTICHANNEL_AND_SIMPLE - }; - - struct request_output_info { - uint16_t image_width; - uint16_t image_height; - int16_t bearing_x; - int16_t bearing_y; - }; - - struct request_descriptor { - std::weak_ptr font_face; - uint32_t glyph_index; - sdf_type type; - float em_outer_spread; - float em_inner_spread; - int32_t ppem; - }; - - using for_each_request_done_callback = std::function raw_pixels)>; - - virtual ~sdf_generator() = default; - - virtual request_response spawn(const request_descriptor& in_request, request_output_info& out_char_info) = 0; - virtual request_response respawn(const request_descriptor& in_request, const request_output_info& in_char_info) = 0; - virtual void update(const for_each_request_done_callback& in_enumerator) = 0; - virtual void flush() = 0; - - static std::unique_ptr create(); -protected: - sdf_generator() = default; -}; diff --git a/src/renderer/core/fonts/shape_distance_finder.cpp b/src/renderer/core/fonts/shape_distance_finder.cpp deleted file mode 100644 index 6627eab..0000000 --- a/src/renderer/core/fonts/shape_distance_finder.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "shape_distance_finder.h" diff --git a/src/renderer/core/fonts/shape_distance_finder.h b/src/renderer/core/fonts/shape_distance_finder.h deleted file mode 100644 index ec2a5b7..0000000 --- a/src/renderer/core/fonts/shape_distance_finder.h +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once -#include -#include - -#define DISTANCE_DELTA_FACTOR 1.001 - -template -class shape_distance_finder { -public: - using distance_type = typename contour_combiner::distance_type; - using edge_cache_type = typename contour_combiner::edge_selector_type::edge_cache; - - explicit shape_distance_finder(const msdfgen::Shape& in_shape) : shape(in_shape), combiner(in_shape), edge_caches(in_shape.edgeCount()) {} - distance_type distance(const msdfgen::Point2& origin) { - combiner.reset(origin); - auto* edge_cache = edge_caches.data(); - - for (auto contour = shape.contours.begin(); contour != shape.contours.end(); ++contour) { - if (contour->edges.empty()) - continue; - auto& edge_selector = combiner.edge_selector(int(contour - shape.contours.begin())); - - const msdfgen::EdgeSegment* prev_edge = contour->edges.size() >= 2 ? *(contour->edges.end() - 2) : (*contour->edges.begin()); - const msdfgen::EdgeSegment* cur_edge = contour->edges.back(); - for (auto edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) { - const msdfgen::EdgeSegment* next_edge = *edge; - - edge_selector.add_edge(*edge_cache++, prev_edge, cur_edge, next_edge); - prev_edge = cur_edge; - cur_edge = next_edge; - } - } - - return combiner.distance(); - } - - static distance_type one_shot_distance(const msdfgen::Shape& in_shape, const msdfgen::Point2& in_origin) { - contour_combiner combiner(in_shape); - combiner.reset(in_origin); - - for (auto contour = in_shape.contours.begin(); contour != in_shape.contours.end(); ++contour) { - if (contour->edges.empty()) - continue; - auto& edge_selector = combiner.edge_selector(int(contour - in_shape.contours.begin())); - - const msdfgen::EdgeSegment* prev_edge = contour->edges.size() >= 2 ? *(contour->edges.end() - 2) : (*contour->edges.begin()); - const msdfgen::EdgeSegment* cur_edge = contour->edges.back(); - for (auto edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) { - const msdfgen::EdgeSegment* next_edge = *edge; - - edge_cache_type dummy; - edge_selector.add_edge(dummy, prev_edge, cur_edge, next_edge); - prev_edge = cur_edge; - cur_edge = next_edge; - } - } - - return combiner.distance(); - } -private: - const msdfgen::Shape shape; - contour_combiner combiner; - std::vector edge_caches; -}; - diff --git a/src/renderer/core/fonts/text_shaper.cpp b/src/renderer/core/fonts/text_shaper.cpp deleted file mode 100644 index 9748a36..0000000 --- a/src/renderer/core/fonts/text_shaper.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "text_shaper.h" diff --git a/src/renderer/core/fonts/text_shaper.h b/src/renderer/core/fonts/text_shaper.h deleted file mode 100644 index cc2f260..0000000 --- a/src/renderer/core/fonts/text_shaper.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include "font_cache.h" -#include "font_cache_freetype.h" - -class shaped_glyph_face_data { -public: - shaped_glyph_face_data(std::weak_ptr in_font_face, uint32_t in_glyph_flags, float in_font_size, float in_font_scale, float in_font_skew, font_rasterization_mode in_rasterization_mode, int16_t in_sdf_ppem) - : font_face(in_font_face) - , glyph_flags(in_glyph_flags) - , font_size(in_font_size) - , font_scale(in_font_scale) - , font_skew(in_font_skew) - , rasterization_mode(in_rasterization_mode) - , sdf_ppem(in_sdf_ppem) - { - if (const auto font_face_ptr = font_face.lock()) { - bitmap_render_scale = font_face_ptr->get_bitmap_render_scale(); - } - } - - std::hash a; - std::weak_ptr font_face; - uint32_t glyph_flags = 0; - float font_size = 0.f; - float font_scale = 0.f; - float bitmap_render_scale; - float font_skew = 0.f; - font_rasterization_mode rasterization_mode; - int16_t sdf_ppem = 0; -}; - -class text_shaper { -public: - text_shaper(freetype_cache_directory* in_cache_directory, composite_font* in_composite_font_cache, font_renderer* in_font_renderer, font_cache* in_font_cache); -}; diff --git a/src/renderer/core/internationalization/culture.cpp b/src/renderer/core/internationalization/culture.cpp deleted file mode 100644 index 1d376f5..0000000 --- a/src/renderer/core/internationalization/culture.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "culture.h" diff --git a/src/renderer/core/internationalization/culture.h b/src/renderer/core/internationalization/culture.h deleted file mode 100644 index e3f9c17..0000000 --- a/src/renderer/core/internationalization/culture.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include -#include - -class culture; -using culture_ptr = std::shared_ptr; - -class culture { -public: - ~culture() = default; - - static culture_ptr create(const std::u32string& name) { - } - - const std::u32string& get_display_name() const { - } -}; - diff --git a/src/renderer/core/internationalization/internationalization.cpp b/src/renderer/core/internationalization/internationalization.cpp deleted file mode 100644 index 0d127e0..0000000 --- a/src/renderer/core/internationalization/internationalization.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "internationalization.h" diff --git a/src/renderer/core/internationalization/internationalization.h b/src/renderer/core/internationalization/internationalization.h deleted file mode 100644 index 546cb48..0000000 --- a/src/renderer/core/internationalization/internationalization.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -#include "misc/lazy_singleton.h" - -class internationalization { -public: - static internationalization& get() { - return lazy_singleton::get(); - } - - static void tear_down() { - lazy_singleton::tear_down(); - } - - bool set_current_culture(const std::u32string& culture) { - } -}; diff --git a/third_party/LLGL b/third_party/LLGL new file mode 160000 index 0000000..75174b9 --- /dev/null +++ b/third_party/LLGL @@ -0,0 +1 @@ +Subproject commit 75174b96df56888508bdd0bc024c1cb6c5c2f277 diff --git a/third_party/msdfgen b/third_party/msdfgen new file mode 160000 index 0000000..5a88b0c --- /dev/null +++ b/third_party/msdfgen @@ -0,0 +1 @@ +Subproject commit 5a88b0c2b95033f7eee826b27c48d399d544d814