mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-09 11:11:29 -06:00
Add internal font handling structures and layout computation functions
This commit introduces a new header file `fontft_internal.h` containing various structures and functions for managing font handles, layout metrics, and rendering operations. Key additions include: - Definitions for `FontHandleOpenInfo`, `FontHandleStyleStateTail`, and `FontHandleOpaqueNative` to encapsulate font state and properties. - Layout-related structures such as `HorizontalLayoutBlocks`, `VerticalLayoutBlocks`, and their respective I/O structures for managing layout metrics and effects. - Functions for computing horizontal and vertical layout blocks, along with utility functions for handling layout words in byte format. - Stubs for library functions related to font management and rendering. These changes aim to enhance the font rendering capabilities of the shadPS4 Emulator Project, providing a robust foundation for future font-related features.
This commit is contained in:
parent
9387adc79e
commit
e9ca20b65d
@ -468,8 +468,12 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
|
||||
src/core/libraries/web_browser_dialog/webbrowserdialog.h
|
||||
src/core/libraries/font/font.cpp
|
||||
src/core/libraries/font/font.h
|
||||
src/core/libraries/font/font_internal.cpp
|
||||
src/core/libraries/font/font_internal.h
|
||||
src/core/libraries/font/fontft.cpp
|
||||
src/core/libraries/font/fontft.h
|
||||
src/core/libraries/font/fontft_internal.cpp
|
||||
src/core/libraries/font/fontft_internal.h
|
||||
src/core/libraries/font/font_error.h
|
||||
|
||||
)
|
||||
@ -1085,7 +1089,7 @@ add_executable(shadps4
|
||||
|
||||
create_target_directory_groups(shadps4)
|
||||
|
||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG)
|
||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG freetype)
|
||||
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 SDL3_mixer::SDL3_mixer pugixml::pugixml)
|
||||
target_link_libraries(shadps4 PRIVATE stb::headers libusb::usb lfreist-hwinfo::hwinfo nlohmann_json::nlohmann_json miniz fdk-aac)
|
||||
|
||||
|
||||
10
externals/CMakeLists.txt
vendored
10
externals/CMakeLists.txt
vendored
@ -56,6 +56,16 @@ if (NOT TARGET ZLIB::ZLIB)
|
||||
set(ZLIB_INCLUDE_DIRS "${FETCHCONTENT_BASE_DIR}/zlib-build")
|
||||
endif()
|
||||
|
||||
# FreeType
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/freetype/CMakeLists.txt" AND NOT TARGET freetype)
|
||||
# Keep optional deps off to reduce build surface; zlib stays enabled for compressed fonts.
|
||||
set(FT_DISABLE_BZIP2 ON CACHE BOOL "" FORCE)
|
||||
set(FT_DISABLE_BROTLI ON CACHE BOOL "" FORCE)
|
||||
set(FT_DISABLE_HARFBUZZ ON CACHE BOOL "" FORCE)
|
||||
set(FT_DISABLE_PNG ON CACHE BOOL "" FORCE)
|
||||
add_subdirectory(freetype)
|
||||
endif()
|
||||
|
||||
# SDL3
|
||||
if (NOT TARGET SDL3::SDL3)
|
||||
set(SDL_TEST_LIBRARY OFF)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -31,27 +31,55 @@ struct OrbisFontOpenParams {
|
||||
};
|
||||
|
||||
struct OrbisFontGlyphMetrics {
|
||||
float w;
|
||||
float h;
|
||||
float h_bearing_x;
|
||||
float h_bearing_y;
|
||||
float h_adv;
|
||||
float v_bearing_x;
|
||||
float v_bearing_y;
|
||||
float v_adv;
|
||||
float width;
|
||||
float height;
|
||||
struct {
|
||||
float bearingX;
|
||||
float bearingY;
|
||||
float advance;
|
||||
} Horizontal;
|
||||
struct {
|
||||
float bearingX;
|
||||
float bearingY;
|
||||
float advance;
|
||||
} Vertical;
|
||||
};
|
||||
|
||||
struct OrbisFontGlyphMetricsHorizontal {
|
||||
float width;
|
||||
float height;
|
||||
struct {
|
||||
float bearing_x;
|
||||
float bearing_y;
|
||||
float advance;
|
||||
} horizontal;
|
||||
};
|
||||
|
||||
struct OrbisFontGlyphMetricsHorizontalX {
|
||||
float width;
|
||||
struct {
|
||||
float bearing_x;
|
||||
float advance;
|
||||
} horizontal;
|
||||
};
|
||||
|
||||
struct OrbisFontGlyphMetricsHorizontalAdvance {
|
||||
struct {
|
||||
float advance;
|
||||
} horizontal;
|
||||
};
|
||||
|
||||
struct OrbisFontKerning {
|
||||
float dx;
|
||||
float dy;
|
||||
float px;
|
||||
float py;
|
||||
float offsetX;
|
||||
float offsetY;
|
||||
float positionX;
|
||||
float positionY;
|
||||
};
|
||||
|
||||
struct OrbisFontGlyphImageMetrics {
|
||||
float bearing_x;
|
||||
float bearing_y;
|
||||
float dv;
|
||||
float bearingX;
|
||||
float bearingY;
|
||||
float advance;
|
||||
float stride;
|
||||
u32 width;
|
||||
u32 height;
|
||||
@ -106,20 +134,23 @@ struct OrbisFontResultStage {
|
||||
u32 u32_10;
|
||||
};
|
||||
|
||||
struct OrbisFontResultSlot {
|
||||
u8* maybe_addr;
|
||||
u32 maybe_rowBytes;
|
||||
u8 maybe_pixelSize;
|
||||
u8 maybe_pixelFmt;
|
||||
struct OrbisFontSurfaceImage {
|
||||
u8* address;
|
||||
u32 widthByte;
|
||||
u8 pixelSizeByte;
|
||||
u8 pixelFormat;
|
||||
u16 pad16;
|
||||
};
|
||||
|
||||
struct OrbisFontRenderOutput {
|
||||
const OrbisFontResultStage* stage;
|
||||
OrbisFontResultSlot slot;
|
||||
u32 new_x;
|
||||
u32 new_y;
|
||||
u32 new_w;
|
||||
u32 new_h;
|
||||
OrbisFontSurfaceImage SurfaceImage;
|
||||
struct {
|
||||
u32 x;
|
||||
u32 y;
|
||||
u32 w;
|
||||
u32 h;
|
||||
} UpdateRect;
|
||||
OrbisFontGlyphImageMetrics ImageMetrics;
|
||||
};
|
||||
|
||||
@ -163,16 +194,15 @@ struct OrbisFontMem {
|
||||
};
|
||||
|
||||
struct OrbisFontTextCharacter {
|
||||
// Other fields...
|
||||
struct OrbisFontTextCharacter* next; // Pointer to the next node 0x00
|
||||
struct OrbisFontTextCharacter* prev; // Pointer to the next node 0x08
|
||||
void* textOrder; // Field at offset 0x10 (pointer to text order info)
|
||||
u32 characterCode; // Field assumed at offset 0x28
|
||||
u8 unkn_0x31; // Offset 0x31
|
||||
u8 unkn_0x33; // Offset 0x33
|
||||
u8 charType; // Field assumed at offset 0x39
|
||||
u8 bidiLevel; // Field assumed at offset 0x3B stores the Bidi level
|
||||
u8 formatFlags; // Field at offset 0x3D (stores format-related flags)
|
||||
struct OrbisFontTextCharacter* next;
|
||||
struct OrbisFontTextCharacter* prev;
|
||||
void* textOrder;
|
||||
u32 characterCode;
|
||||
u8 unknown_0x31;
|
||||
u8 unknown_0x33;
|
||||
u8 charType;
|
||||
u8 bidiLevel;
|
||||
u8 formatFlags;
|
||||
};
|
||||
|
||||
struct OrbisFontRenderSurface {
|
||||
@ -191,19 +221,48 @@ struct OrbisFontRenderSurface {
|
||||
};
|
||||
|
||||
struct OrbisFontStyleFrame {
|
||||
/*0x00*/ u16 magic; // Expected to be 0xF09
|
||||
/*0x02*/ u16 flags;
|
||||
/*0x04*/ s32 dpiX; // DPI scaling factor for width
|
||||
/*0x08*/ s32 dpiY; // DPI scaling factor for height
|
||||
/*0x0c*/ s32 scalingFlag; // Indicates whether scaling is enabled
|
||||
/*0x10*/ float scaleWidth; // Width scaling factor
|
||||
/*0x14*/ float scaleHeight; // Height scaling factor
|
||||
/*0x18*/ float weightXScale;
|
||||
/*0x1c*/ float weightYScale;
|
||||
/*0x20*/ float slantRatio;
|
||||
/*0x24*/
|
||||
/*0x00*/ u16 magic;
|
||||
/*0x02*/ u8 flags1;
|
||||
/*0x03*/ u8 flags2;
|
||||
/*0x04*/ u32 hDpi;
|
||||
/*0x08*/ u32 vDpi;
|
||||
/*0x0C*/ u32 scaleUnit;
|
||||
/*0x10*/ float baseScale;
|
||||
/*0x14*/ float scalePixelW;
|
||||
/*0x18*/ float scalePixelH;
|
||||
/*0x1C*/ float effectWeightX;
|
||||
/*0x20*/ float effectWeightY;
|
||||
/*0x24*/ float slantRatio;
|
||||
/*0x28*/ u32 reserved_0x28;
|
||||
/*0x2C*/ u32 layout_cache_state;
|
||||
/*0x30*/ u32 cache_flags_and_direction;
|
||||
/*0x34*/ u32 cache_lock_word;
|
||||
/*0x38*/ u8 layout_cache_bytes[0x20];
|
||||
/*0x58*/ u32 reserved_0x58;
|
||||
/*0x5C*/ u32 cached_scalar_bits;
|
||||
};
|
||||
|
||||
static_assert(sizeof(OrbisFontStyleFrame) == 0x60, "OrbisFontStyleFrame size");
|
||||
static_assert(offsetof(OrbisFontStyleFrame, magic) == 0x00, "OrbisFontStyleFrame magic offset");
|
||||
static_assert(offsetof(OrbisFontStyleFrame, flags1) == 0x02, "OrbisFontStyleFrame flags1 offset");
|
||||
static_assert(offsetof(OrbisFontStyleFrame, hDpi) == 0x04, "OrbisFontStyleFrame hDpi offset");
|
||||
static_assert(offsetof(OrbisFontStyleFrame, vDpi) == 0x08, "OrbisFontStyleFrame vDpi offset");
|
||||
static_assert(offsetof(OrbisFontStyleFrame, scaleUnit) == 0x0C,
|
||||
"OrbisFontStyleFrame scaleUnit offset");
|
||||
static_assert(offsetof(OrbisFontStyleFrame, scalePixelW) == 0x14,
|
||||
"OrbisFontStyleFrame scalePixelW offset");
|
||||
static_assert(offsetof(OrbisFontStyleFrame, scalePixelH) == 0x18,
|
||||
"OrbisFontStyleFrame scalePixelH offset");
|
||||
static_assert(offsetof(OrbisFontStyleFrame, cache_lock_word) == 0x34,
|
||||
"OrbisFontStyleFrame cache_lock_word offset");
|
||||
static_assert(offsetof(OrbisFontStyleFrame, reserved_0x58) == 0x58,
|
||||
"OrbisFontStyleFrame reserved_0x58 offset");
|
||||
|
||||
static_assert(sizeof(OrbisFontGlyphMetrics) == 0x20, "OrbisFontGlyphMetrics size");
|
||||
static_assert(sizeof(OrbisFontResultStage) == 0x18, "OrbisFontTransImage size");
|
||||
static_assert(sizeof(OrbisFontSurfaceImage) == 0x10, "OrbisFontSurfaceImage size");
|
||||
static_assert(sizeof(OrbisFontRenderOutput) == 0x40, "OrbisFontRenderOutput size");
|
||||
|
||||
struct OrbisFontHorizontalLayout {
|
||||
float baselineOffset;
|
||||
float lineAdvance;
|
||||
@ -278,8 +337,9 @@ s32 PS4_SYSV_ABI sceFontGetAttribute();
|
||||
s32 PS4_SYSV_ABI sceFontGetCharGlyphCode();
|
||||
s32 PS4_SYSV_ABI sceFontGetCharGlyphMetrics(OrbisFontHandle fontHandle, u32 code,
|
||||
OrbisFontGlyphMetrics* metrics);
|
||||
s32 PS4_SYSV_ABI sceFontGetEffectSlant();
|
||||
s32 PS4_SYSV_ABI sceFontGetEffectWeight();
|
||||
s32 PS4_SYSV_ABI sceFontGetEffectSlant(OrbisFontHandle fontHandle, float* slantRatio);
|
||||
s32 PS4_SYSV_ABI sceFontGetEffectWeight(OrbisFontHandle fontHandle, float* weightXScale,
|
||||
float* weightYScale, u32* mode);
|
||||
s32 PS4_SYSV_ABI sceFontGetFontGlyphsCount();
|
||||
s32 PS4_SYSV_ABI sceFontGetFontGlyphsOutlineProfile();
|
||||
s32 PS4_SYSV_ABI sceFontGetFontMetrics();
|
||||
@ -294,8 +354,9 @@ s32 PS4_SYSV_ABI sceFontGetLibrary(OrbisFontHandle fontHandle, OrbisFontLib* pLi
|
||||
s32 PS4_SYSV_ABI sceFontGetPixelResolution();
|
||||
s32 PS4_SYSV_ABI sceFontGetRenderCharGlyphMetrics(OrbisFontHandle fontHandle, u32 codepoint,
|
||||
OrbisFontGlyphMetrics* out_metrics);
|
||||
s32 PS4_SYSV_ABI sceFontGetRenderEffectSlant();
|
||||
s32 PS4_SYSV_ABI sceFontGetRenderEffectWeight();
|
||||
s32 PS4_SYSV_ABI sceFontGetRenderEffectSlant(OrbisFontHandle fontHandle, float* slantRatio);
|
||||
s32 PS4_SYSV_ABI sceFontGetRenderEffectWeight(OrbisFontHandle fontHandle, float* weightXScale,
|
||||
float* weightYScale, u32* mode);
|
||||
s32 PS4_SYSV_ABI sceFontGetRenderScaledKerning();
|
||||
s32 PS4_SYSV_ABI sceFontGetRenderScalePixel(OrbisFontHandle fontHandle, float* out_w, float* out_h);
|
||||
s32 PS4_SYSV_ABI sceFontGetRenderScalePoint(OrbisFontHandle fontHandle, float* out_w, float* out_h);
|
||||
@ -393,7 +454,10 @@ s32 PS4_SYSV_ABI sceFontRenderCharGlyphImageHorizontal(OrbisFontHandle fontHandl
|
||||
OrbisFontRenderSurface* surf, float x,
|
||||
float y, OrbisFontGlyphMetrics* metrics,
|
||||
OrbisFontRenderOutput* result);
|
||||
s32 PS4_SYSV_ABI sceFontRenderCharGlyphImageVertical();
|
||||
s32 PS4_SYSV_ABI sceFontRenderCharGlyphImageVertical(OrbisFontHandle fontHandle, u32 code,
|
||||
OrbisFontRenderSurface* surf, float x, float y,
|
||||
OrbisFontGlyphMetrics* metrics,
|
||||
OrbisFontRenderOutput* result);
|
||||
s32 PS4_SYSV_ABI sceFontRendererGetOutlineBufferSize();
|
||||
s32 PS4_SYSV_ABI sceFontRendererResetOutlineBuffer();
|
||||
s32 PS4_SYSV_ABI sceFontRendererSetOutlineBufferPolicy();
|
||||
@ -404,16 +468,18 @@ void PS4_SYSV_ABI sceFontRenderSurfaceSetScissor(OrbisFontRenderSurface* renderS
|
||||
int y0, int w, int h);
|
||||
s32 PS4_SYSV_ABI sceFontRenderSurfaceSetStyleFrame(OrbisFontRenderSurface* renderSurface,
|
||||
OrbisFontStyleFrame* styleFrame);
|
||||
s32 PS4_SYSV_ABI sceFontSetEffectSlant();
|
||||
s32 PS4_SYSV_ABI sceFontSetEffectWeight();
|
||||
s32 PS4_SYSV_ABI sceFontSetEffectSlant(OrbisFontHandle fontHandle, float slantRatio);
|
||||
s32 PS4_SYSV_ABI sceFontSetEffectWeight(OrbisFontHandle fontHandle, float weightXScale,
|
||||
float weightYScale, u32 mode);
|
||||
s32 PS4_SYSV_ABI sceFontSetFontsOpenMode();
|
||||
s32 PS4_SYSV_ABI sceFontSetResolutionDpi(OrbisFontHandle fontHandle, u32 h_dpi, u32 v_dpi);
|
||||
s32 PS4_SYSV_ABI sceFontSetScalePixel(OrbisFontHandle fontHandle, float w, float h);
|
||||
s32 PS4_SYSV_ABI sceFontSetScalePoint(OrbisFontHandle fontHandle, float w, float h);
|
||||
s32 PS4_SYSV_ABI sceFontSetScriptLanguage();
|
||||
s32 PS4_SYSV_ABI sceFontSetTypographicDesign();
|
||||
s32 PS4_SYSV_ABI sceFontSetupRenderEffectSlant();
|
||||
s32 PS4_SYSV_ABI sceFontSetupRenderEffectWeight();
|
||||
s32 PS4_SYSV_ABI sceFontSetupRenderEffectSlant(OrbisFontHandle fontHandle, float slantRatio);
|
||||
s32 PS4_SYSV_ABI sceFontSetupRenderEffectWeight(OrbisFontHandle fontHandle, float weightXScale,
|
||||
float weightYScale, u32 mode);
|
||||
s32 PS4_SYSV_ABI sceFontSetupRenderScalePixel(OrbisFontHandle fontHandle, float w, float h);
|
||||
s32 PS4_SYSV_ABI sceFontSetupRenderScalePoint(OrbisFontHandle fontHandle, float w, float h);
|
||||
s32 PS4_SYSV_ABI sceFontStringGetTerminateCode();
|
||||
|
||||
1932
src/core/libraries/font/font_internal.cpp
Normal file
1932
src/core/libraries/font/font_internal.cpp
Normal file
File diff suppressed because it is too large
Load Diff
760
src/core/libraries/font/font_internal.h
Normal file
760
src/core/libraries/font/font_internal.h
Normal file
@ -0,0 +1,760 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cmath>
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <new>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <system_error>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#include "common/config.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/singleton.h"
|
||||
#include "core/file_sys/fs.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/font/font.h"
|
||||
#include "core/libraries/libs.h"
|
||||
#include "font_error.h"
|
||||
|
||||
namespace Libraries::Font::Internal {
|
||||
|
||||
struct FontLibOpaque;
|
||||
struct OrbisFontRenderer_;
|
||||
struct FontSetCache;
|
||||
|
||||
template <typename T>
|
||||
std::string DescribeValue(const T& value) {
|
||||
using Clean = std::remove_cvref_t<T>;
|
||||
if constexpr (std::is_same_v<Clean, bool>) {
|
||||
return value ? "true" : "false";
|
||||
} else if constexpr (std::is_pointer_v<Clean>) {
|
||||
if constexpr (std::is_same_v<Clean, const char*> || std::is_same_v<Clean, char*>) {
|
||||
return value ? fmt::format("\"{}\"", value) : "(null)";
|
||||
}
|
||||
return fmt::format("{}", reinterpret_cast<const void*>(value));
|
||||
} else if constexpr (std::is_floating_point_v<Clean>) {
|
||||
return fmt::format("{:.6g}", value);
|
||||
} else if constexpr (std::is_enum_v<Clean>) {
|
||||
using Underlying = std::underlying_type_t<Clean>;
|
||||
return DescribeValue(static_cast<Underlying>(value));
|
||||
} else if constexpr (std::is_same_v<Clean, std::string> ||
|
||||
std::is_same_v<Clean, std::string_view>) {
|
||||
return fmt::format("\"{}\"", value);
|
||||
} else {
|
||||
return fmt::format("{}", value);
|
||||
}
|
||||
}
|
||||
|
||||
struct ParamRecord {
|
||||
std::string name;
|
||||
std::string initial;
|
||||
std::string current;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ChangeTracked {
|
||||
T before;
|
||||
T after;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_change_tracked : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_change_tracked<ChangeTracked<T>> : std::true_type {
|
||||
using value_type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
ChangeTracked<T> trackChange(T before, T after) {
|
||||
return ChangeTracked<T>{before, after};
|
||||
}
|
||||
|
||||
inline std::string TrimName(std::string_view name) {
|
||||
const auto start = name.find_first_not_of(" \t\n\r");
|
||||
if (start == std::string_view::npos) {
|
||||
return {};
|
||||
}
|
||||
const auto end = name.find_last_not_of(" \t\n\r");
|
||||
return std::string{name.substr(start, end - start + 1)};
|
||||
}
|
||||
|
||||
inline std::vector<std::string> SplitArgumentNames(std::string_view names) {
|
||||
std::vector<std::string> result;
|
||||
std::string current;
|
||||
int depth = 0;
|
||||
for (char c : names) {
|
||||
if (c == ',' && depth == 0) {
|
||||
result.push_back(TrimName(current));
|
||||
current.clear();
|
||||
continue;
|
||||
}
|
||||
if (c == '(' || c == '{' || c == '[') {
|
||||
++depth;
|
||||
} else if (c == ')' || c == '}' || c == ']') {
|
||||
depth = std::max(0, depth - 1);
|
||||
}
|
||||
current.push_back(c);
|
||||
}
|
||||
if (!current.empty() ||
|
||||
(!names.empty() && names.find_first_not_of(" \t\n\r") != std::string_view::npos)) {
|
||||
result.push_back(TrimName(current));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ParamRecord MakeParamRecord(std::string name, T&& value) {
|
||||
using Clean = std::remove_cvref_t<T>;
|
||||
if constexpr (is_change_tracked<Clean>::value) {
|
||||
using ValueType = typename Clean::value_type;
|
||||
return ParamRecord{std::move(name), DescribeValue(value.before),
|
||||
DescribeValue(value.after)};
|
||||
} else {
|
||||
const std::string rendered = DescribeValue(value);
|
||||
return ParamRecord{std::move(name), rendered, rendered};
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string FormatParamRecords(const std::vector<ParamRecord>& records) {
|
||||
fmt::memory_buffer buffer;
|
||||
fmt::format_to(std::back_inserter(buffer), "params:\n");
|
||||
for (const auto& entry : records) {
|
||||
const bool changed = entry.initial != entry.current;
|
||||
if (changed) {
|
||||
fmt::format_to(std::back_inserter(buffer), "{}: {} -> {}\n", entry.name, entry.initial,
|
||||
entry.current);
|
||||
} else {
|
||||
fmt::format_to(std::back_inserter(buffer), "{}: {}\n", entry.name, entry.initial);
|
||||
}
|
||||
}
|
||||
return fmt::to_string(buffer);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
std::string formatParamsImpl(const char* arg_names, Args&&... args) {
|
||||
std::vector<std::string> names = SplitArgumentNames(arg_names ? arg_names : "");
|
||||
std::vector<ParamRecord> records;
|
||||
records.reserve(sizeof...(Args));
|
||||
std::size_t index = 0;
|
||||
auto append_record = [&](auto&& value) {
|
||||
std::string name = (index < names.size() && !names[index].empty())
|
||||
? std::move(names[index])
|
||||
: fmt::format("arg{}", index);
|
||||
++index;
|
||||
records.push_back(MakeParamRecord(std::move(name), std::forward<decltype(value)>(value)));
|
||||
};
|
||||
(append_record(std::forward<Args>(args)), ...);
|
||||
return FormatParamRecords(records);
|
||||
}
|
||||
|
||||
inline void log_info(std::string_view message) {
|
||||
LOG_INFO(Lib_Font, "{}", message);
|
||||
}
|
||||
|
||||
inline void log_debug(std::string_view message) {
|
||||
LOG_DEBUG(Lib_Font, "{}", message);
|
||||
}
|
||||
|
||||
#define formatParams(...) formatParamsImpl(#__VA_ARGS__ __VA_OPT__(, ) __VA_ARGS__)
|
||||
|
||||
struct FontSetSelector;
|
||||
|
||||
struct GlyphEntry {
|
||||
std::vector<std::uint8_t> bitmap;
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
int x0 = 0;
|
||||
int y0 = 0;
|
||||
int x1 = 0;
|
||||
int y1 = 0;
|
||||
float advance = 0.0f;
|
||||
float bearingX = 0.0f;
|
||||
};
|
||||
|
||||
struct FontState {
|
||||
float scale_w = 16.0f;
|
||||
float scale_h = 16.0f;
|
||||
float scale_point_w = 12.0f;
|
||||
float scale_point_h = 12.0f;
|
||||
bool scale_point_active = false;
|
||||
float render_scale_w = 16.0f;
|
||||
float render_scale_h = 16.0f;
|
||||
float render_scale_point_w = 12.0f;
|
||||
float render_scale_point_h = 12.0f;
|
||||
bool render_scale_point_active = false;
|
||||
u32 dpi_x = 72;
|
||||
u32 dpi_y = 72;
|
||||
u32 font_set_type = 0;
|
||||
std::filesystem::path system_font_path;
|
||||
u32 system_font_id = 0;
|
||||
float system_font_scale_factor = 1.0f;
|
||||
s32 system_font_shift_value = 0;
|
||||
struct SystemFallbackFace {
|
||||
u32 font_id = 0;
|
||||
float scale_factor = 1.0f;
|
||||
s32 shift_value = 0;
|
||||
std::filesystem::path path;
|
||||
std::shared_ptr<std::vector<unsigned char>> bytes;
|
||||
FT_Face ft_face = nullptr;
|
||||
bool ready = false;
|
||||
};
|
||||
std::vector<SystemFallbackFace> system_fallback_faces;
|
||||
Libraries::Font::OrbisFontLib library = nullptr;
|
||||
bool ext_face_ready = false;
|
||||
std::vector<unsigned char> ext_face_data;
|
||||
FT_Face ext_ft_face = nullptr;
|
||||
float ext_scale_for_height = 0.0f;
|
||||
int ext_ascent = 0, ext_descent = 0, ext_lineGap = 0;
|
||||
int ext_units_per_em = 0;
|
||||
int ext_typo_ascent = 0, ext_typo_descent = 0, ext_typo_lineGap = 0;
|
||||
bool ext_use_typo_metrics = false;
|
||||
std::unordered_map<std::uint64_t, GlyphEntry> ext_cache;
|
||||
std::vector<std::uint8_t> scratch;
|
||||
bool logged_ext_use = false;
|
||||
float cached_baseline_y = 0.0f;
|
||||
bool layout_cached = false;
|
||||
Libraries::Font::OrbisFontRenderer bound_renderer = nullptr;
|
||||
bool system_requested = false;
|
||||
std::shared_ptr<std::vector<u8>> fontset_record_storage;
|
||||
std::shared_ptr<FontSetSelector> fontset_selector;
|
||||
float effect_weight_x = 1.0f;
|
||||
float effect_weight_y = 1.0f;
|
||||
u32 effect_weight_mode = 0;
|
||||
float effect_slant = 0.0f;
|
||||
float render_effect_weight_x = 1.0f;
|
||||
float render_effect_weight_y = 1.0f;
|
||||
u32 render_effect_weight_mode = 0;
|
||||
float render_effect_slant = 0.0f;
|
||||
|
||||
~FontState();
|
||||
};
|
||||
|
||||
struct LibraryState {
|
||||
bool support_system = false;
|
||||
bool support_external = false;
|
||||
u32 external_formats = 0;
|
||||
u32 external_fontMax = 0;
|
||||
const Libraries::Font::OrbisFontMem* backing_memory = nullptr;
|
||||
Libraries::Font::OrbisFontLibCreateParams create_params = nullptr;
|
||||
u64 edition = 0;
|
||||
FontLibOpaque* native = nullptr;
|
||||
void* owned_device_cache = nullptr;
|
||||
u32 owned_device_cache_size = 0;
|
||||
};
|
||||
|
||||
struct FaceMetrics {
|
||||
int units_per_em = 0;
|
||||
int hhea_ascent = 0;
|
||||
int hhea_descent = 0;
|
||||
int hhea_lineGap = 0;
|
||||
int typo_ascent = 0;
|
||||
int typo_descent = 0;
|
||||
int typo_lineGap = 0;
|
||||
bool has_typo = false;
|
||||
bool use_typo = false;
|
||||
};
|
||||
|
||||
struct GeneratedGlyph {
|
||||
OrbisFontGlyphOpaque glyph{};
|
||||
OrbisFontGlyphMetrics metrics{};
|
||||
OrbisFontGlyphMetricsHorizontal metrics_horizontal{};
|
||||
OrbisFontGlyphMetricsHorizontalX metrics_horizontal_x{};
|
||||
OrbisFontGlyphMetricsHorizontalAdvance metrics_horizontal_adv{};
|
||||
float origin_x = 0.0f;
|
||||
float origin_y = 0.0f;
|
||||
float scale_x_used = 0.0f;
|
||||
float scale_y_used = 0.0f;
|
||||
int bbox_x0 = 0;
|
||||
int bbox_y0 = 0;
|
||||
int bbox_w = 0;
|
||||
int bbox_h = 0;
|
||||
u32 codepoint = 0;
|
||||
Libraries::Font::OrbisFontHandle owner_handle{};
|
||||
OrbisFontGlyphOutline outline{};
|
||||
std::vector<OrbisFontGlyphOutlinePoint> outline_points;
|
||||
std::vector<u8> outline_tags;
|
||||
std::vector<u16> outline_contours;
|
||||
bool metrics_initialized = false;
|
||||
bool outline_initialized = false;
|
||||
};
|
||||
|
||||
struct SysDriver {
|
||||
using PixelResFn = u32(PS4_SYSV_ABI*)();
|
||||
using InitFn = s32(PS4_SYSV_ABI*)(const void* memory, void* library);
|
||||
using TermFn = s32(PS4_SYSV_ABI*)(void* library);
|
||||
using SupportFn = s32(PS4_SYSV_ABI*)(void* library, u32 formats);
|
||||
using OpenFn = s32(PS4_SYSV_ABI*)(void* library, u32 mode, const void* fontAddress,
|
||||
u32 fontSize, u32 subFontIndex, u32 uniqueWord,
|
||||
void** inoutFontObj);
|
||||
using CloseFn = s32(PS4_SYSV_ABI*)(void* fontObj, u32 flags);
|
||||
using ScaleFn = s32(PS4_SYSV_ABI*)(void* fontObj, u16* outUnitsPerEm, float* outScale);
|
||||
using MetricFn = s32(PS4_SYSV_ABI*)(void* fontObj, u32 metricId, u16* outMetric);
|
||||
using GlyphsCountFn = s32(PS4_SYSV_ABI*)(void* fontObj, u32* out_count);
|
||||
using GlyphIndexFn = s32(PS4_SYSV_ABI*)(void* fontObj, u32 codepoint_u16, u32* out_glyph_index);
|
||||
|
||||
using SetCharWithDpiFn = s32(PS4_SYSV_ABI*)(void* fontObj, u32 dpi_x, u32 dpi_y, float scale_x,
|
||||
float scale_y, float* out_scale_x,
|
||||
float* out_scale_y);
|
||||
using SetCharDefaultDpiFn = s32(PS4_SYSV_ABI*)(void* fontObj, float scale_x, float scale_y,
|
||||
float* out_scale_x, float* out_scale_y);
|
||||
using ComputeLayoutFn = s32(PS4_SYSV_ABI*)(void* fontObj, const void* style_state_block,
|
||||
u8 (*out_words)[16]);
|
||||
using ComputeLayoutAltFn = s32(PS4_SYSV_ABI*)(void* fontObj, const void* style_state_block,
|
||||
u8 (*out_words)[16]);
|
||||
|
||||
using LoadGlyphCachedFn = s32(PS4_SYSV_ABI*)(void* fontObj, u32 glyphIndex, s32 mode,
|
||||
std::uint64_t* out_words);
|
||||
using GetGlyphMetricsFn = s32(PS4_SYSV_ABI*)(
|
||||
void* fontObj, std::uint32_t* opt_param2, std::uint8_t mode, std::uint8_t* out_params,
|
||||
Libraries::Font::OrbisFontGlyphMetrics* out_metrics);
|
||||
using ApplyGlyphAdjustFn = s32(PS4_SYSV_ABI*)(void* fontObj, u32 p2, u32 glyphIndex, s32 p4,
|
||||
s32 p5, u32* inoutGlyphIndex);
|
||||
using ConfigureGlyphFn = s32(PS4_SYSV_ABI*)(void* fontObj, std::uint32_t* in_params, s32 mode,
|
||||
std::uint32_t* inout_state);
|
||||
|
||||
/*0x00*/ u8 reserved_00[0x10];
|
||||
/*0x10*/ PixelResFn pixel_resolution;
|
||||
/*0x18*/ InitFn init;
|
||||
/*0x20*/ TermFn term;
|
||||
/*0x28*/ SupportFn support_formats;
|
||||
/*0x30*/ u8 reserved_30[0x08];
|
||||
/*0x38*/ OpenFn open;
|
||||
/*0x40*/ CloseFn close;
|
||||
/*0x48*/ u8 reserved_48[0x08];
|
||||
/*0x50*/ ScaleFn scale;
|
||||
/*0x58*/ u8 reserved_58[0x08];
|
||||
/*0x60*/ MetricFn metric;
|
||||
/*0x68*/ GlyphsCountFn glyphs_count;
|
||||
/*0x70*/ u8 reserved_70[0x08];
|
||||
/*0x78*/ GlyphIndexFn glyph_index;
|
||||
/*0x80*/ SetCharWithDpiFn set_char_with_dpi;
|
||||
/*0x88*/ SetCharDefaultDpiFn set_char_default_dpi;
|
||||
/*0x90*/ u8 reserved_90[0x10];
|
||||
/*0xA0*/ ComputeLayoutFn compute_layout;
|
||||
/*0xA8*/ LoadGlyphCachedFn load_glyph_cached;
|
||||
/*0xB0*/ u8 reserved_B0[0x08];
|
||||
/*0xB8*/ GetGlyphMetricsFn get_glyph_metrics;
|
||||
/*0xC0*/ u8 reserved_C0[0x20];
|
||||
/*0xE0*/ ApplyGlyphAdjustFn apply_glyph_adjust;
|
||||
/*0xE8*/ u8 reserved_E8[0x20];
|
||||
/*0x108*/ ConfigureGlyphFn configure_glyph;
|
||||
/*0x110*/ u8 reserved_0x110_pad[0x08];
|
||||
/*0x118*/ ComputeLayoutAltFn compute_layout_alt;
|
||||
};
|
||||
static_assert(sizeof(SysDriver) == 0x120, "SysDriver size");
|
||||
static_assert(offsetof(SysDriver, pixel_resolution) == 0x10, "SysDriver pixel_resolution offset");
|
||||
static_assert(offsetof(SysDriver, init) == 0x18, "SysDriver init offset");
|
||||
static_assert(offsetof(SysDriver, term) == 0x20, "SysDriver term offset");
|
||||
static_assert(offsetof(SysDriver, support_formats) == 0x28, "SysDriver support_formats offset");
|
||||
static_assert(offsetof(SysDriver, open) == 0x38, "SysDriver open offset");
|
||||
static_assert(offsetof(SysDriver, close) == 0x40, "SysDriver close offset");
|
||||
static_assert(offsetof(SysDriver, scale) == 0x50, "SysDriver scale offset");
|
||||
static_assert(offsetof(SysDriver, metric) == 0x60, "SysDriver metric offset");
|
||||
static_assert(offsetof(SysDriver, glyphs_count) == 0x68, "SysDriver glyphs_count offset");
|
||||
static_assert(offsetof(SysDriver, glyph_index) == 0x78, "SysDriver glyph_index offset");
|
||||
static_assert(offsetof(SysDriver, set_char_with_dpi) == 0x80, "SysDriver set_char_with_dpi offset");
|
||||
static_assert(offsetof(SysDriver, set_char_default_dpi) == 0x88,
|
||||
"SysDriver set_char_default_dpi offset");
|
||||
static_assert(offsetof(SysDriver, compute_layout) == 0xA0, "SysDriver compute_layout offset");
|
||||
static_assert(offsetof(SysDriver, load_glyph_cached) == 0xA8, "SysDriver load_glyph_cached offset");
|
||||
static_assert(offsetof(SysDriver, get_glyph_metrics) == 0xB8, "SysDriver get_glyph_metrics offset");
|
||||
static_assert(offsetof(SysDriver, apply_glyph_adjust) == 0xE0,
|
||||
"SysDriver apply_glyph_adjust offset");
|
||||
static_assert(offsetof(SysDriver, configure_glyph) == 0x108, "SysDriver configure_glyph offset");
|
||||
static_assert(offsetof(SysDriver, compute_layout_alt) == 0x118,
|
||||
"SysDriver compute_layout_alt offset");
|
||||
struct StyleStateBlock {
|
||||
/*0x00*/ u32 dpi_x;
|
||||
/*0x04*/ u32 dpi_y;
|
||||
/*0x08*/ u32 scale_unit;
|
||||
/*0x0C*/ u32 reserved_0x0c;
|
||||
/*0x10*/ float scale_w;
|
||||
/*0x14*/ float scale_h;
|
||||
/*0x18*/ float effect_weight_x;
|
||||
/*0x1C*/ float effect_weight_y;
|
||||
/*0x20*/ float slant_ratio;
|
||||
/*0x24*/ float reserved_0x24;
|
||||
};
|
||||
static_assert(sizeof(StyleStateBlock) == 0x28, "StyleStateBlock size");
|
||||
static_assert(offsetof(StyleStateBlock, dpi_x) == 0x00, "StyleStateBlock dpi_x offset");
|
||||
static_assert(offsetof(StyleStateBlock, dpi_y) == 0x04, "StyleStateBlock dpi_y offset");
|
||||
static_assert(offsetof(StyleStateBlock, scale_unit) == 0x08, "StyleStateBlock scale_unit offset");
|
||||
static_assert(offsetof(StyleStateBlock, scale_w) == 0x10, "StyleStateBlock scale_w offset");
|
||||
static_assert(offsetof(StyleStateBlock, scale_h) == 0x14, "StyleStateBlock scale_h offset");
|
||||
static_assert(offsetof(StyleStateBlock, effect_weight_x) == 0x18,
|
||||
"StyleStateBlock effect_weight_x offset");
|
||||
static_assert(offsetof(StyleStateBlock, effect_weight_y) == 0x1C,
|
||||
"StyleStateBlock effect_weight_y offset");
|
||||
static_assert(offsetof(StyleStateBlock, slant_ratio) == 0x20, "StyleStateBlock slant_ratio offset");
|
||||
|
||||
struct FontSetSelector {
|
||||
static constexpr u32 kMagic = 0x53464C42u;
|
||||
|
||||
struct Candidate {
|
||||
u32 font_id = 0xffffffffu;
|
||||
FT_Face face = nullptr;
|
||||
};
|
||||
|
||||
u32 magic = kMagic;
|
||||
u32 font_set_type = 0;
|
||||
void* library = nullptr;
|
||||
u32 mode_low = 0;
|
||||
u32 sub_font_index = 0;
|
||||
u32 primary_font_id = 0xffffffffu;
|
||||
u32 roman_font_id = 0xffffffffu;
|
||||
u32 arabic_font_id = 0xffffffffu;
|
||||
std::vector<Candidate> candidates;
|
||||
};
|
||||
|
||||
struct FontSetRecordHeader {
|
||||
/*0x00*/ u32 font_set_type;
|
||||
/*0x04*/ u8 reserved_0x04[0x18];
|
||||
/*0x1C*/ u32 magic;
|
||||
/*0x20*/ u32 entry_count;
|
||||
};
|
||||
static_assert(sizeof(FontSetRecordHeader) == 0x24, "FontSetRecordHeader size");
|
||||
static_assert(offsetof(FontSetRecordHeader, font_set_type) == 0x00,
|
||||
"FontSetRecordHeader font_set_type offset");
|
||||
static_assert(offsetof(FontSetRecordHeader, magic) == 0x1C, "FontSetRecordHeader magic offset");
|
||||
static_assert(offsetof(FontSetRecordHeader, entry_count) == 0x20,
|
||||
"FontSetRecordHeader entry_count offset");
|
||||
|
||||
struct FontSetRecordView {
|
||||
const FontSetRecordHeader* header = nullptr;
|
||||
const u32* entry_indices = nullptr;
|
||||
const FontSetSelector* selector = nullptr;
|
||||
};
|
||||
|
||||
inline std::size_t FontSetRecordSelectorOffset(u32 entry_count) {
|
||||
const std::size_t indices_bytes = static_cast<std::size_t>(entry_count) * sizeof(u32);
|
||||
const std::size_t ptr_off_unaligned = sizeof(FontSetRecordHeader) + indices_bytes;
|
||||
const std::size_t ptr_align = alignof(const FontSetSelector*);
|
||||
return (ptr_off_unaligned + (ptr_align - 1u)) & ~(ptr_align - 1u);
|
||||
}
|
||||
|
||||
inline FontSetRecordView MakeFontSetRecordView(const FontSetRecordHeader* record) {
|
||||
if (!record) {
|
||||
return {};
|
||||
}
|
||||
FontSetRecordView view{};
|
||||
view.header = record;
|
||||
view.entry_indices = reinterpret_cast<const u32*>(static_cast<const void*>(record + 1));
|
||||
const std::size_t ptr_off = FontSetRecordSelectorOffset(record->entry_count);
|
||||
view.selector = *reinterpret_cast<const FontSetSelector* const*>(
|
||||
static_cast<const void*>(reinterpret_cast<const u8*>(record) + ptr_off));
|
||||
return view;
|
||||
}
|
||||
|
||||
struct FontCtxHeader {
|
||||
/*0x00*/ u32 lock_word;
|
||||
/*0x04*/ u32 max_entries;
|
||||
/*0x08*/ void* base;
|
||||
/*0x10*/ u8 reserved_0x10[0x10];
|
||||
};
|
||||
static_assert(sizeof(FontCtxHeader) == 0x20, "FontCtxHeader size");
|
||||
static_assert(offsetof(FontCtxHeader, lock_word) == 0x00, "FontCtxHeader lock_word offset");
|
||||
static_assert(offsetof(FontCtxHeader, max_entries) == 0x04, "FontCtxHeader max_entries offset");
|
||||
static_assert(offsetof(FontCtxHeader, base) == 0x08, "FontCtxHeader base offset");
|
||||
|
||||
struct FontCtxEntry {
|
||||
/*0x00*/ u32 reserved_0x00;
|
||||
/*0x04*/ u32 active;
|
||||
/*0x08*/ u64 font_address;
|
||||
/*0x10*/ u32 unique_id;
|
||||
/*0x14*/ u32 lock_mode1;
|
||||
/*0x18*/ u32 lock_mode3;
|
||||
/*0x1C*/ u32 lock_mode2;
|
||||
/*0x20*/ void* obj_mode1;
|
||||
/*0x28*/ void* obj_mode3;
|
||||
/*0x30*/ void* obj_mode2;
|
||||
/*0x38*/ u8 reserved_0x38[0x08];
|
||||
};
|
||||
static_assert(sizeof(FontCtxEntry) == 0x40, "FontCtxEntry size");
|
||||
static_assert(offsetof(FontCtxEntry, lock_mode1) == 0x14, "FontCtxEntry lock_mode1 offset");
|
||||
static_assert(offsetof(FontCtxEntry, lock_mode3) == 0x18, "FontCtxEntry lock_mode3 offset");
|
||||
static_assert(offsetof(FontCtxEntry, lock_mode2) == 0x1C, "FontCtxEntry lock_mode2 offset");
|
||||
static_assert(offsetof(FontCtxEntry, obj_mode1) == 0x20, "FontCtxEntry obj_mode1 offset");
|
||||
static_assert(offsetof(FontCtxEntry, obj_mode3) == 0x28, "FontCtxEntry obj_mode3 offset");
|
||||
static_assert(offsetof(FontCtxEntry, obj_mode2) == 0x30, "FontCtxEntry obj_mode2 offset");
|
||||
|
||||
struct FontObj {
|
||||
/*0x00*/ u32 refcount;
|
||||
/*0x04*/ u32 reserved_0x04;
|
||||
/*0x08*/ u32 reserved_0x08;
|
||||
/*0x0C*/ u32 sub_font_index;
|
||||
/*0x10*/ FontObj* prev;
|
||||
/*0x18*/ FontObj* next;
|
||||
/*0x20*/ u8 reserved_0x20[0x08];
|
||||
/*0x28*/ void* open_ctx_0x28;
|
||||
/*0x30*/ void* ft_face;
|
||||
/*0x38*/ Libraries::Font::OrbisFontHandle font_handle;
|
||||
/*0x40*/ s32 shift_units_x;
|
||||
/*0x44*/ s32 shift_units_y;
|
||||
/*0x48*/ std::uint64_t layout_seed_pair;
|
||||
/*0x50*/ float scale_x_0x50;
|
||||
/*0x54*/ float scale_y_0x54;
|
||||
/*0x58*/ void* ft_ctx_0x58;
|
||||
/*0x60*/ u8 reserved_0x60[0x04];
|
||||
/*0x64*/ s32 cached_glyph_index_0x64;
|
||||
/*0x68*/ std::uint64_t cached_units_x_0x68;
|
||||
/*0x70*/ std::uint64_t cached_units_y_0x70;
|
||||
/*0x78*/ s64 shift_cache_x;
|
||||
/*0x80*/ s64 shift_cache_y;
|
||||
/*0x88*/ std::array<std::uint64_t, 2> layout_seed_vec;
|
||||
/*0x98*/ std::array<std::uint64_t, 2> layout_scale_vec;
|
||||
/*0xA8*/ u8 reserved_0xA8[0x130 - 0xA8];
|
||||
/*0x130*/ u32 glyph_cfg_word_0x130;
|
||||
/*0x134*/ u8 glyph_cfg_mode_0x134;
|
||||
/*0x135*/ u8 glyph_cfg_byte_0x135;
|
||||
/*0x136*/ u8 glyph_cfg_byte_0x136;
|
||||
/*0x137*/ u8 reserved_0x137[0x200 - 0x137];
|
||||
};
|
||||
static_assert(offsetof(FontObj, sub_font_index) == 0x0C, "FontObj sub_font_index offset");
|
||||
static_assert(offsetof(FontObj, next) == 0x18, "FontObj next offset");
|
||||
static_assert(offsetof(FontObj, ft_face) == 0x30, "FontObj ft_face offset");
|
||||
static_assert(offsetof(FontObj, font_handle) == 0x38, "FontObj font_handle offset");
|
||||
static_assert(offsetof(FontObj, shift_units_x) == 0x40, "FontObj shift_units_x offset");
|
||||
static_assert(offsetof(FontObj, shift_units_y) == 0x44, "FontObj shift_units_y offset");
|
||||
static_assert(offsetof(FontObj, layout_seed_pair) == 0x48, "FontObj layout_seed_pair offset");
|
||||
static_assert(offsetof(FontObj, shift_cache_x) == 0x78, "FontObj shift_cache_x offset");
|
||||
static_assert(offsetof(FontObj, shift_cache_y) == 0x80, "FontObj shift_cache_y offset");
|
||||
static_assert(offsetof(FontObj, layout_seed_vec) == 0x88, "FontObj layout_seed_vec offset");
|
||||
static_assert(offsetof(FontObj, layout_scale_vec) == 0x98, "FontObj layout_scale_vec offset");
|
||||
static_assert(offsetof(FontObj, glyph_cfg_word_0x130) == 0x130, "FontObj glyph_cfg_word offset");
|
||||
static_assert(sizeof(FontObj) == 0x200, "FontObj size");
|
||||
|
||||
struct SystemFontDefinition {
|
||||
u32 font_set_type;
|
||||
const char* config_key;
|
||||
const char* default_file;
|
||||
};
|
||||
|
||||
struct FontSetCache {
|
||||
bool loaded = false;
|
||||
bool available = false;
|
||||
std::vector<unsigned char> bytes;
|
||||
std::filesystem::path path;
|
||||
};
|
||||
|
||||
struct FontLibOpaque {
|
||||
u16 magic;
|
||||
u16 reserved0;
|
||||
u32 lock_word;
|
||||
u32 flags;
|
||||
u8 reserved1[0x14];
|
||||
void* alloc_ctx;
|
||||
void** alloc_vtbl;
|
||||
u8 reserved2[0x50];
|
||||
void* sys_driver;
|
||||
void* fontset_registry;
|
||||
union {
|
||||
u8 reserved3[0x10];
|
||||
std::array<std::uint64_t, 2> sysfonts_ctx_name_overrides;
|
||||
};
|
||||
void* sysfonts_ctx;
|
||||
void* external_fonts_ctx;
|
||||
u32* device_cache_buf;
|
||||
};
|
||||
static_assert(sizeof(FontLibOpaque) == 0xB8, "FontLibOpaque size");
|
||||
static_assert(offsetof(FontLibOpaque, alloc_ctx) == 0x20, "FontLibOpaque alloc_ctx offset");
|
||||
static_assert(offsetof(FontLibOpaque, alloc_vtbl) == 0x28, "FontLibOpaque alloc_vtbl offset");
|
||||
static_assert(offsetof(FontLibOpaque, sys_driver) == 0x80, "FontLibOpaque sys_driver offset");
|
||||
static_assert(offsetof(FontLibOpaque, fontset_registry) == 0x88,
|
||||
"FontLibOpaque fontset_registry offset");
|
||||
static_assert(offsetof(FontLibOpaque, sysfonts_ctx) == 0xA0, "FontLibOpaque sysfonts_ctx offset");
|
||||
static_assert(offsetof(FontLibOpaque, external_fonts_ctx) == 0xA8,
|
||||
"FontLibOpaque external_fonts_ctx offset");
|
||||
static_assert(offsetof(FontLibOpaque, device_cache_buf) == 0xB0,
|
||||
"FontLibOpaque device_cache_buf offset");
|
||||
|
||||
struct RendererOpaque {
|
||||
/*0x00*/ u16 magic;
|
||||
/*0x02*/ u16 reserved02;
|
||||
/*0x04*/ u8 reserved_04[0x08];
|
||||
/*0x0C*/ u8 feature_byte_0x0c;
|
||||
/*0x0D*/ u8 reserved_0d[0x03];
|
||||
/*0x10*/ u32 mem_kind;
|
||||
/*0x14*/ u32 region_size;
|
||||
/*0x18*/ void* region_base;
|
||||
/*0x20*/ void* alloc_ctx;
|
||||
/*0x28*/ const OrbisFontMemInterface* mem_iface;
|
||||
/*0x30*/ u8 reserved_30[0x20];
|
||||
/*0x50*/ std::uintptr_t alloc_fn;
|
||||
/*0x58*/ std::uintptr_t free_fn;
|
||||
/*0x60*/ std::uintptr_t realloc_fn;
|
||||
/*0x68*/ std::uintptr_t calloc_fn;
|
||||
/*0x70*/ u8 reserved_70[0x10];
|
||||
/*0x80*/ void* selection;
|
||||
/*0x88*/ u8 reserved_88[0x08];
|
||||
/*0x90*/ u64 outline_magic_0x90;
|
||||
/*0x98*/ void* workspace;
|
||||
/*0xA0*/ u64 workspace_size;
|
||||
/*0xA8*/ u32 reserved_a8;
|
||||
/*0xAC*/ u32 outline_policy_flag;
|
||||
};
|
||||
static_assert(sizeof(RendererOpaque) == 0xB0, "RendererOpaque size");
|
||||
static_assert(offsetof(RendererOpaque, magic) == 0x00, "RendererOpaque magic offset");
|
||||
static_assert(offsetof(RendererOpaque, feature_byte_0x0c) == 0x0C,
|
||||
"RendererOpaque feature byte offset");
|
||||
static_assert(offsetof(RendererOpaque, mem_kind) == 0x10, "RendererOpaque mem_kind offset");
|
||||
static_assert(offsetof(RendererOpaque, region_size) == 0x14, "RendererOpaque region_size offset");
|
||||
static_assert(offsetof(RendererOpaque, alloc_ctx) == 0x20, "RendererOpaque alloc_ctx offset");
|
||||
static_assert(offsetof(RendererOpaque, mem_iface) == 0x28, "RendererOpaque mem_iface offset");
|
||||
static_assert(offsetof(RendererOpaque, alloc_fn) == 0x50, "RendererOpaque alloc_fn offset");
|
||||
static_assert(offsetof(RendererOpaque, free_fn) == 0x58, "RendererOpaque free_fn offset");
|
||||
static_assert(offsetof(RendererOpaque, selection) == 0x80, "RendererOpaque selection offset");
|
||||
static_assert(offsetof(RendererOpaque, workspace) == 0x98, "RendererOpaque workspace offset");
|
||||
static_assert(offsetof(RendererOpaque, reserved_a8) == 0xA8, "RendererOpaque reserved_a8 offset");
|
||||
static_assert(offsetof(RendererOpaque, outline_policy_flag) == 0xAC,
|
||||
"RendererOpaque outline_policy_flag offset");
|
||||
|
||||
struct RendererFtBackend {
|
||||
/*0x00*/ void* renderer_header_0x10;
|
||||
/*0x08*/ std::uintptr_t unknown_0x08;
|
||||
/*0x10*/ std::uintptr_t unknown_0x10;
|
||||
/*0x18*/ std::uintptr_t unknown_0x18;
|
||||
/*0x20*/ void* initialized_marker;
|
||||
/*0x28*/ u8 reserved_0x28[0x20];
|
||||
};
|
||||
static_assert(sizeof(RendererFtBackend) == 0x48, "RendererFtBackend size");
|
||||
static_assert(offsetof(RendererFtBackend, renderer_header_0x10) == 0x00,
|
||||
"RendererFtBackend renderer_header_0x10 offset");
|
||||
static_assert(offsetof(RendererFtBackend, initialized_marker) == 0x20,
|
||||
"RendererFtBackend initialized_marker offset");
|
||||
|
||||
struct RendererFtOpaque {
|
||||
/*0x000*/ RendererOpaque base;
|
||||
/*0x0B0*/ u8 reserved_0x0B0[0x70];
|
||||
/*0x120*/ RendererFtBackend ft_backend;
|
||||
};
|
||||
static_assert(sizeof(RendererFtOpaque) == 0x168, "RendererFtOpaque size");
|
||||
static_assert(offsetof(RendererFtOpaque, ft_backend) == 0x120,
|
||||
"RendererFtOpaque ft_backend offset");
|
||||
|
||||
struct OrbisFontRenderer_ {};
|
||||
|
||||
struct StyleFrameScaleState {
|
||||
float scale_w;
|
||||
float scale_h;
|
||||
u32 dpi_x;
|
||||
u32 dpi_y;
|
||||
bool scale_overridden;
|
||||
bool dpi_overridden;
|
||||
};
|
||||
|
||||
extern const float kPointsPerInch;
|
||||
extern const float kScaleEpsilon;
|
||||
|
||||
extern const u16 kStyleFrameMagic;
|
||||
extern const u8 kStyleFrameFlagScale;
|
||||
extern const u8 kStyleFrameFlagWeight;
|
||||
extern const u8 kStyleFrameFlagSlant;
|
||||
|
||||
extern Core::FileSys::MntPoints* g_mnt;
|
||||
extern std::unordered_map<Libraries::Font::OrbisFontHandle, FontState> g_font_state;
|
||||
extern std::unordered_map<Libraries::Font::OrbisFontLib, LibraryState> g_library_state;
|
||||
extern std::unordered_map<Libraries::Font::OrbisFontRenderSurface*,
|
||||
const Libraries::Font::OrbisFontStyleFrame*>
|
||||
g_style_for_surface;
|
||||
extern std::mutex g_generated_glyph_mutex;
|
||||
extern std::unordered_set<Libraries::Font::OrbisFontGlyph> g_generated_glyphs;
|
||||
|
||||
extern void* g_allocator_vtbl_stub[4];
|
||||
extern std::uint8_t g_sys_driver_stub;
|
||||
extern std::uint8_t g_fontset_registry_stub;
|
||||
extern std::uint8_t g_sysfonts_ctx_stub;
|
||||
extern std::uint8_t g_external_fonts_ctx_stub;
|
||||
extern u32 g_device_cache_stub;
|
||||
|
||||
FontState& GetState(Libraries::Font::OrbisFontHandle h);
|
||||
FontState* TryGetState(Libraries::Font::OrbisFontHandle h);
|
||||
LibraryState& GetLibState(Libraries::Font::OrbisFontLib lib);
|
||||
void RemoveLibState(Libraries::Font::OrbisFontLib lib);
|
||||
FT_Face CreateFreeTypeFaceFromBytes(const unsigned char* data, std::size_t size, u32 subfont_index);
|
||||
void DestroyFreeTypeFace(FT_Face& face);
|
||||
void LogExternalFormatSupport(u32 formats_mask);
|
||||
void LogFontOpenParams(const Libraries::Font::OrbisFontOpenParams* params);
|
||||
std::filesystem::path ResolveGuestPath(const char* guest_path);
|
||||
bool LoadGuestFileBytes(const std::filesystem::path& host_path,
|
||||
std::vector<unsigned char>& out_bytes);
|
||||
FaceMetrics LoadFaceMetrics(FT_Face face);
|
||||
void PopulateStateMetrics(FontState& st, const FaceMetrics& m);
|
||||
float ComputeScaleExtForState(const FontState& st, FT_Face face, float pixel_h);
|
||||
float ComputeScaleForPixelHeight(const FontState& st, float pixel_h);
|
||||
float SafeDpiToFloat(u32 dpi);
|
||||
float PointsToPixels(float pt, u32 dpi);
|
||||
float PixelsToPoints(float px, u32 dpi);
|
||||
u16 ClampToU16(float value);
|
||||
StyleFrameScaleState ResolveStyleFrameScale(const Libraries::Font::OrbisFontStyleFrame* style,
|
||||
const FontState& st);
|
||||
void InitializeStyleFrame(Libraries::Font::OrbisFontStyleFrame& frame);
|
||||
bool EnsureStyleFrameInitialized(Libraries::Font::OrbisFontStyleFrame* frame);
|
||||
bool ValidateStyleFramePtr(const Libraries::Font::OrbisFontStyleFrame* frame);
|
||||
void UpdateCachedLayout(FontState& st);
|
||||
std::uint64_t MakeGlyphKey(u32 code, int pixel_h);
|
||||
void LogStrideOnce(const Libraries::Font::OrbisFontRenderSurface* surf);
|
||||
void ClearRenderOutputs(Libraries::Font::OrbisFontGlyphMetrics* metrics,
|
||||
Libraries::Font::OrbisFontRenderOutput* result);
|
||||
bool ResolveFaceAndScale(FontState& st, Libraries::Font::OrbisFontHandle handle, float pixel_h,
|
||||
FT_Face& face_out, float& scale_y_out);
|
||||
bool ResolveFace(FontState& st, Libraries::Font::OrbisFontHandle handle, FT_Face& face_out);
|
||||
s32 RenderCodepointToSurface(FontState& st, Libraries::Font::OrbisFontHandle handle, FT_Face face,
|
||||
float pixel_w, float pixel_h,
|
||||
Libraries::Font::OrbisFontRenderSurface* surf, u32 code, float x,
|
||||
float y, Libraries::Font::OrbisFontGlyphMetrics* metrics,
|
||||
Libraries::Font::OrbisFontRenderOutput* result, s32 shift_x_units,
|
||||
s32 shift_y_units);
|
||||
s32 RenderCodepointToSurfaceWithScale(FontState& st, Libraries::Font::OrbisFontHandle handle,
|
||||
FT_Face face, float scale_x, float scale_y,
|
||||
Libraries::Font::OrbisFontRenderSurface* surf, u32 code,
|
||||
float x, float y, Libraries::Font::OrbisFontGlyphMetrics* m,
|
||||
Libraries::Font::OrbisFontRenderOutput* result);
|
||||
const GlyphEntry* GetGlyphEntry(FontState& st, Libraries::Font::OrbisFontHandle handle, u32 code,
|
||||
FT_Face& face_out, float& scale_out);
|
||||
const SystemFontDefinition* FindSystemFontDefinition(u32 font_set_type);
|
||||
std::filesystem::path GetSysFontBaseDir();
|
||||
std::string MacroToCamel(const char* macro_key);
|
||||
std::filesystem::path ResolveSystemFontPath(u32 font_set_type);
|
||||
std::filesystem::path ResolveSystemFontPathFromConfigOnly(u32 font_set_type);
|
||||
const struct FontSetCache* EnsureFontSetCache(u32 font_set_type);
|
||||
bool HasSfntTables(const std::vector<unsigned char>& bytes);
|
||||
bool LoadFontFile(const std::filesystem::path& path, std::vector<unsigned char>& out_bytes);
|
||||
bool AttachSystemFont(FontState& st, Libraries::Font::OrbisFontHandle handle);
|
||||
std::string ReportSystemFaceRequest(FontState& st, Libraries::Font::OrbisFontHandle handle,
|
||||
bool& attached_out);
|
||||
void TrackGeneratedGlyph(Libraries::Font::OrbisFontGlyph glyph);
|
||||
bool ForgetGeneratedGlyph(Libraries::Font::OrbisFontGlyph glyph);
|
||||
GeneratedGlyph* TryGetGeneratedGlyph(Libraries::Font::OrbisFontGlyph glyph);
|
||||
void PopulateGlyphMetricVariants(GeneratedGlyph& gg);
|
||||
void BuildBoundingOutline(GeneratedGlyph& gg);
|
||||
bool BuildTrueOutline(GeneratedGlyph& gg);
|
||||
|
||||
} // namespace Libraries::Font::Internal
|
||||
@ -1,43 +1,79 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/font/font.h"
|
||||
#include "core/libraries/font/font_internal.h"
|
||||
#include "core/libraries/font/fontft.h"
|
||||
#include "core/libraries/font/fontft_internal.h"
|
||||
#include "core/libraries/libs.h"
|
||||
|
||||
namespace Libraries::FontFt {
|
||||
|
||||
namespace {
|
||||
bool g_library_selected = false;
|
||||
bool g_renderer_selected = false;
|
||||
|
||||
constexpr OrbisFontLibrarySelection kDefaultLibrarySelection{0xF2000000u, 0, nullptr, nullptr};
|
||||
static std::once_flag g_driver_table_once;
|
||||
alignas(Libraries::Font::Internal::SysDriver) static Libraries::Font::Internal::SysDriver
|
||||
g_driver_table{};
|
||||
|
||||
static void* PS4_SYSV_ABI RendererCreateStub() {
|
||||
LOG_ERROR(Lib_FontFt, "(STUBBED) renderer create called");
|
||||
return nullptr;
|
||||
static const OrbisFontLibrarySelection* GetDriverTable() {
|
||||
std::call_once(g_driver_table_once, [] {
|
||||
auto* selection = reinterpret_cast<OrbisFontLibrarySelection*>(&g_driver_table);
|
||||
selection->magic = 0;
|
||||
selection->reserved = 0;
|
||||
selection->reserved_ptr1 = nullptr;
|
||||
|
||||
auto* driver = &g_driver_table;
|
||||
|
||||
driver->pixel_resolution = &Libraries::FontFt::Internal::LibraryGetPixelResolutionStub;
|
||||
driver->init = &Libraries::FontFt::Internal::LibraryInitStub;
|
||||
driver->term = &Libraries::FontFt::Internal::LibraryTermStub;
|
||||
driver->support_formats = &Libraries::FontFt::Internal::LibrarySupportStub;
|
||||
|
||||
driver->open = &Libraries::FontFt::Internal::LibraryOpenFontMemoryStub;
|
||||
driver->close = &Libraries::FontFt::Internal::LibraryCloseFontObjStub;
|
||||
driver->scale = &Libraries::FontFt::Internal::LibraryGetFaceScaleStub;
|
||||
driver->metric = &Libraries::FontFt::Internal::LibraryGetFaceMetricStub;
|
||||
driver->glyph_index = &Libraries::FontFt::Internal::LibraryGetGlyphIndexStub;
|
||||
driver->set_char_with_dpi = &Libraries::FontFt::Internal::LibrarySetCharSizeWithDpiStub;
|
||||
driver->set_char_default_dpi =
|
||||
&Libraries::FontFt::Internal::LibrarySetCharSizeDefaultDpiStub;
|
||||
driver->compute_layout = &Libraries::FontFt::Internal::LibraryComputeLayoutBlockStub;
|
||||
driver->compute_layout_alt = &Libraries::FontFt::Internal::LibraryComputeLayoutAltBlockStub;
|
||||
|
||||
driver->load_glyph_cached = &Libraries::FontFt::Internal::LibraryLoadGlyphCachedStub;
|
||||
driver->get_glyph_metrics = &Libraries::FontFt::Internal::LibraryGetGlyphMetricsStub;
|
||||
driver->apply_glyph_adjust = &Libraries::FontFt::Internal::LibraryApplyGlyphAdjustStub;
|
||||
driver->configure_glyph = &Libraries::FontFt::Internal::LibraryConfigureGlyphStub;
|
||||
});
|
||||
|
||||
return reinterpret_cast<const OrbisFontLibrarySelection*>(&g_driver_table);
|
||||
}
|
||||
|
||||
static void PS4_SYSV_ABI RendererQueryStub() {
|
||||
LOG_ERROR(Lib_FontFt, "(STUBBED) renderer query called");
|
||||
static std::once_flag g_renderer_table_once;
|
||||
alignas(OrbisFontRendererSelection) static OrbisFontRendererSelection g_renderer_table{};
|
||||
|
||||
static const OrbisFontRendererSelection* GetRendererSelectionTable() {
|
||||
std::call_once(g_renderer_table_once, [] {
|
||||
g_renderer_table.magic = 0;
|
||||
g_renderer_table.size =
|
||||
static_cast<u32>(sizeof(Libraries::Font::Internal::RendererFtOpaque));
|
||||
|
||||
g_renderer_table.create_fn =
|
||||
reinterpret_cast<std::uintptr_t>(&Libraries::FontFt::Internal::FtRendererCreate);
|
||||
g_renderer_table.destroy_fn =
|
||||
reinterpret_cast<std::uintptr_t>(&Libraries::FontFt::Internal::FtRendererDestroy);
|
||||
g_renderer_table.query_fn =
|
||||
reinterpret_cast<std::uintptr_t>(&Libraries::FontFt::Internal::FtRendererQuery);
|
||||
});
|
||||
return &g_renderer_table;
|
||||
}
|
||||
|
||||
static void PS4_SYSV_ABI RendererDestroyStub() {
|
||||
LOG_ERROR(Lib_FontFt, "(STUBBED) renderer destroy called");
|
||||
}
|
||||
|
||||
static OrbisFontRendererSelection MakeRendererSelection() {
|
||||
OrbisFontRendererSelection sel{};
|
||||
sel.magic = 0xF2000000u;
|
||||
sel.size = 0x168;
|
||||
sel.create_fn = reinterpret_cast<uintptr_t>(&RendererCreateStub);
|
||||
sel.query_fn = reinterpret_cast<uintptr_t>(&RendererQueryStub);
|
||||
sel.destroy_fn = reinterpret_cast<uintptr_t>(&RendererDestroyStub);
|
||||
return sel;
|
||||
}
|
||||
|
||||
static const OrbisFontRendererSelection kDefaultRendererSelection = MakeRendererSelection();
|
||||
} // namespace
|
||||
|
||||
s32 PS4_SYSV_ABI sceFontFtInitAliases() {
|
||||
@ -136,31 +172,19 @@ s32 PS4_SYSV_ABI sceFontSelectGlyphsFt() {
|
||||
}
|
||||
|
||||
const OrbisFontLibrarySelection* PS4_SYSV_ABI sceFontSelectLibraryFt(int value) {
|
||||
if (!g_library_selected) {
|
||||
g_library_selected = true;
|
||||
LOG_INFO(Lib_FontFt, "library selection requested (FreeType shim)");
|
||||
}
|
||||
LOG_DEBUG(Lib_FontFt,
|
||||
"library selection params:\n"
|
||||
" value={}\n",
|
||||
value);
|
||||
LOG_INFO(Lib_FontFt, "called");
|
||||
LOG_DEBUG(Lib_FontFt, "params:\nvalue: {}\n", value);
|
||||
if (value == 0) {
|
||||
return &kDefaultLibrarySelection;
|
||||
return GetDriverTable();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const OrbisFontRendererSelection* PS4_SYSV_ABI sceFontSelectRendererFt(int value) {
|
||||
if (!g_renderer_selected) {
|
||||
g_renderer_selected = true;
|
||||
LOG_INFO(Lib_FontFt, "renderer selection requested (stb_truetype backend)");
|
||||
}
|
||||
LOG_DEBUG(Lib_FontFt,
|
||||
"renderer selection params:\n"
|
||||
" value={}\n",
|
||||
value);
|
||||
LOG_INFO(Lib_FontFt, "called");
|
||||
LOG_DEBUG(Lib_FontFt, "params:\nvalue: {}\n", value);
|
||||
if (value == 0) {
|
||||
return &kDefaultRendererSelection;
|
||||
return GetRendererSelectionTable();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -15,15 +15,18 @@ struct OrbisFontLibrarySelection {
|
||||
u32 magic;
|
||||
u32 reserved;
|
||||
void* reserved_ptr1;
|
||||
void* reserved_ptr2;
|
||||
uintptr_t get_pixel_resolution_fn;
|
||||
uintptr_t init_fn;
|
||||
uintptr_t term_fn;
|
||||
uintptr_t support_fn;
|
||||
};
|
||||
|
||||
struct OrbisFontRendererSelection {
|
||||
u32 magic;
|
||||
u32 size;
|
||||
uintptr_t create_fn;
|
||||
uintptr_t query_fn;
|
||||
uintptr_t destroy_fn;
|
||||
uintptr_t query_fn;
|
||||
};
|
||||
|
||||
s32 PS4_SYSV_ABI sceFontFtInitAliases();
|
||||
|
||||
3672
src/core/libraries/font/fontft_internal.cpp
Normal file
3672
src/core/libraries/font/fontft_internal.cpp
Normal file
File diff suppressed because it is too large
Load Diff
603
src/core/libraries/font/fontft_internal.h
Normal file
603
src/core/libraries/font/fontft_internal.h
Normal file
@ -0,0 +1,603 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <bit>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include "core/libraries/font/font.h"
|
||||
|
||||
namespace Libraries::Font {
|
||||
|
||||
struct FontHandleOpenInfo {
|
||||
/*0x00*/ u32 unique_id_packed;
|
||||
/*0x04*/ u32 ctx_entry_index;
|
||||
/*0x08*/ u32 sub_font_index;
|
||||
/*0x0C*/ u32 fontset_flags;
|
||||
/*0x10*/ const void* fontset_record;
|
||||
/*0x18*/ u64 reserved_0x18;
|
||||
};
|
||||
static_assert(sizeof(FontHandleOpenInfo) == 0x20, "FontHandleOpenInfo size");
|
||||
static_assert(offsetof(FontHandleOpenInfo, sub_font_index) == 0x08,
|
||||
"FontHandleOpenInfo sub_font_index offset");
|
||||
static_assert(offsetof(FontHandleOpenInfo, fontset_record) == 0x10,
|
||||
"FontHandleOpenInfo fontset_record offset");
|
||||
|
||||
struct FontHandleStyleStateTail {
|
||||
/*0x00*/ u32 scale_unit;
|
||||
/*0x04*/ u32 reserved_0x0c;
|
||||
/*0x08*/ float scale_w;
|
||||
/*0x0C*/ float scale_h;
|
||||
/*0x10*/ float effect_weight_x;
|
||||
/*0x14*/ float effect_weight_y;
|
||||
/*0x18*/ float slant_ratio;
|
||||
/*0x1C*/ float reserved_0x24;
|
||||
};
|
||||
static_assert(sizeof(FontHandleStyleStateTail) == 0x20, "FontHandleStyleStateTail size");
|
||||
|
||||
struct FontHandleOpaqueNative {
|
||||
u16 magic;
|
||||
u16 flags;
|
||||
u32 lock_word;
|
||||
FontHandleOpenInfo open_info;
|
||||
OrbisFontLib library;
|
||||
struct RendererBinding {
|
||||
void* renderer;
|
||||
u8 reserved_0x08[0x10 - sizeof(void*)];
|
||||
};
|
||||
static_assert(sizeof(RendererBinding) == 0x10, "RendererBinding size");
|
||||
union {
|
||||
u8 reserved_0x30[0x10];
|
||||
RendererBinding renderer_binding;
|
||||
};
|
||||
u32 style_frame[2];
|
||||
union {
|
||||
u8 reserved_0x48[0x20];
|
||||
FontHandleStyleStateTail style_tail;
|
||||
};
|
||||
OrbisFontStyleFrame cached_style;
|
||||
u16 metricA;
|
||||
u16 metricB;
|
||||
u8 reserved_0xcc[0x1C];
|
||||
u8 reserved_0xe8[0x08];
|
||||
OrbisFontHandle prevFont;
|
||||
OrbisFontHandle nextFont;
|
||||
};
|
||||
static_assert(sizeof(FontHandleOpaqueNative) == 0x100, "FontHandleOpaqueNative size");
|
||||
static_assert(offsetof(FontHandleOpaqueNative, renderer_binding) == 0x30,
|
||||
"FontHandleOpaqueNative renderer_binding offset");
|
||||
static_assert(offsetof(FontHandleOpaqueNative, magic) == 0x00,
|
||||
"FontHandleOpaqueNative magic offset");
|
||||
static_assert(offsetof(FontHandleOpaqueNative, lock_word) == 0x04,
|
||||
"FontHandleOpaqueNative lock_word offset");
|
||||
static_assert(offsetof(FontHandleOpaqueNative, open_info) == 0x08,
|
||||
"FontHandleOpaqueNative open_info offset");
|
||||
static_assert(offsetof(FontHandleOpaqueNative, library) == 0x28,
|
||||
"FontHandleOpaqueNative library offset");
|
||||
static_assert(offsetof(FontHandleOpaqueNative, reserved_0x30) == 0x30,
|
||||
"FontHandleOpaqueNative reserved_0x30 offset");
|
||||
static_assert(offsetof(FontHandleOpaqueNative, style_frame) == 0x40,
|
||||
"FontHandleOpaqueNative style_frame offset");
|
||||
static_assert(offsetof(FontHandleOpaqueNative, reserved_0x48) == 0x48,
|
||||
"FontHandleOpaqueNative reserved_0x48 offset");
|
||||
static_assert(offsetof(FontHandleOpaqueNative, cached_style) == 0x68,
|
||||
"FontHandleOpaqueNative cached_style offset");
|
||||
static_assert(offsetof(FontHandleOpaqueNative, metricA) == 0xC8,
|
||||
"FontHandleOpaqueNative metricA offset");
|
||||
static_assert(offsetof(FontHandleOpaqueNative, metricB) == 0xCA,
|
||||
"FontHandleOpaqueNative metricB offset");
|
||||
static_assert(offsetof(FontHandleOpaqueNative, prevFont) == 0xF0,
|
||||
"FontHandleOpaqueNative prev offset");
|
||||
static_assert(offsetof(FontHandleOpaqueNative, nextFont) == 0xF8,
|
||||
"FontHandleOpaqueNative next offset");
|
||||
|
||||
} // namespace Libraries::Font
|
||||
|
||||
namespace Libraries::Font::Internal {
|
||||
|
||||
struct alignas(16) LayoutWord {
|
||||
std::array<u32, 4> words{};
|
||||
|
||||
constexpr u8* data() {
|
||||
return reinterpret_cast<u8*>(words.data());
|
||||
}
|
||||
constexpr const u8* data() const {
|
||||
return reinterpret_cast<const u8*>(words.data());
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(LayoutWord) == 16, "LayoutWord size");
|
||||
static_assert(alignof(LayoutWord) == 16, "LayoutWord alignment");
|
||||
|
||||
struct alignas(16) HorizontalLayoutMetricsWord {
|
||||
float line_advance = 0.0f;
|
||||
float baseline = 0.0f;
|
||||
float x_bound_lo = 0.0f;
|
||||
float x_bound_hi = 0.0f;
|
||||
};
|
||||
static_assert(sizeof(HorizontalLayoutMetricsWord) == 16, "HorizontalLayoutMetricsWord size");
|
||||
static_assert(alignof(HorizontalLayoutMetricsWord) == 16, "HorizontalLayoutMetricsWord alignment");
|
||||
|
||||
struct alignas(16) HorizontalLayoutEffectsWord {
|
||||
u32 unknown_0x00 = 0;
|
||||
u32 unknown_0x04 = 0;
|
||||
float effect_height = 0.0f;
|
||||
float packed_i8_adj_u13_lane1 = 0.0f;
|
||||
};
|
||||
static_assert(sizeof(HorizontalLayoutEffectsWord) == 16, "HorizontalLayoutEffectsWord size");
|
||||
static_assert(alignof(HorizontalLayoutEffectsWord) == 16, "HorizontalLayoutEffectsWord alignment");
|
||||
|
||||
struct alignas(16) HorizontalLayoutAuxWord {
|
||||
float packed_i8_adj_u13_lane0 = 0.0f;
|
||||
u32 unknown_0x04 = 0;
|
||||
u32 unknown_0x08 = 0;
|
||||
u32 unknown_0x0C = 0;
|
||||
};
|
||||
static_assert(sizeof(HorizontalLayoutAuxWord) == 16, "HorizontalLayoutAuxWord size");
|
||||
static_assert(alignof(HorizontalLayoutAuxWord) == 16, "HorizontalLayoutAuxWord alignment");
|
||||
|
||||
struct alignas(16) HorizontalLayoutBlocks {
|
||||
HorizontalLayoutMetricsWord metrics;
|
||||
HorizontalLayoutEffectsWord effects;
|
||||
HorizontalLayoutAuxWord aux;
|
||||
|
||||
constexpr void* words() {
|
||||
return &metrics;
|
||||
}
|
||||
constexpr const void* words() const {
|
||||
return &metrics;
|
||||
}
|
||||
|
||||
struct Values {
|
||||
float line_advance = 0.0f;
|
||||
float baseline = 0.0f;
|
||||
float effect_height = 0.0f;
|
||||
u64 x_bounds_bits = 0;
|
||||
u64 i8_adj_u13_bits = 0;
|
||||
};
|
||||
|
||||
float line_advance() const {
|
||||
return metrics.line_advance;
|
||||
}
|
||||
|
||||
float baseline() const {
|
||||
return metrics.baseline;
|
||||
}
|
||||
|
||||
float effect_height() const {
|
||||
return effects.effect_height;
|
||||
}
|
||||
|
||||
u64 x_bounds_bits() const {
|
||||
return static_cast<u64>(std::bit_cast<u32>(metrics.x_bound_lo)) |
|
||||
(static_cast<u64>(std::bit_cast<u32>(metrics.x_bound_hi)) << 32);
|
||||
}
|
||||
|
||||
u64 i8_adj_u13_bits() const {
|
||||
return static_cast<u64>(std::bit_cast<u32>(effects.packed_i8_adj_u13_lane1)) |
|
||||
(static_cast<u64>(std::bit_cast<u32>(aux.packed_i8_adj_u13_lane0)) << 32);
|
||||
}
|
||||
|
||||
Values values() const {
|
||||
return {
|
||||
.line_advance = line_advance(),
|
||||
.baseline = baseline(),
|
||||
.effect_height = effect_height(),
|
||||
.x_bounds_bits = x_bounds_bits(),
|
||||
.i8_adj_u13_bits = i8_adj_u13_bits(),
|
||||
};
|
||||
}
|
||||
|
||||
void set_line_advance(float v) {
|
||||
metrics.line_advance = v;
|
||||
}
|
||||
|
||||
void set_baseline(float v) {
|
||||
metrics.baseline = v;
|
||||
}
|
||||
|
||||
void set_x_bounds(float lo, float hi) {
|
||||
metrics.x_bound_lo = lo;
|
||||
metrics.x_bound_hi = hi;
|
||||
}
|
||||
|
||||
void set_effect_height(float v) {
|
||||
effects.effect_height = v;
|
||||
}
|
||||
|
||||
void set_i8_adj_u13_lanes(float lane0, float lane1) {
|
||||
aux.packed_i8_adj_u13_lane0 = lane0;
|
||||
effects.packed_i8_adj_u13_lane1 = lane1;
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(HorizontalLayoutBlocks) == 0x30, "HorizontalLayoutBlocks size");
|
||||
static_assert(alignof(HorizontalLayoutBlocks) == 16, "HorizontalLayoutBlocks alignment");
|
||||
static_assert(offsetof(HorizontalLayoutBlocks, metrics) == 0x00,
|
||||
"HorizontalLayoutBlocks metrics offset");
|
||||
static_assert(offsetof(HorizontalLayoutBlocks, effects) == 0x10,
|
||||
"HorizontalLayoutBlocks effects offset");
|
||||
static_assert(offsetof(HorizontalLayoutBlocks, aux) == 0x20, "HorizontalLayoutBlocks aux offset");
|
||||
|
||||
struct alignas(16) VerticalLayoutMetricsWord {
|
||||
float column_advance = 0.0f;
|
||||
float baseline_offset_x = 0.0f;
|
||||
float unknown_0x08 = 0.0f;
|
||||
float unknown_0x0C = 0.0f;
|
||||
};
|
||||
static_assert(sizeof(VerticalLayoutMetricsWord) == 16, "VerticalLayoutMetricsWord size");
|
||||
static_assert(alignof(VerticalLayoutMetricsWord) == 16, "VerticalLayoutMetricsWord alignment");
|
||||
|
||||
struct alignas(16) VerticalLayoutDecorationWord {
|
||||
u32 unknown_0x00 = 0;
|
||||
float decoration_span = 0.0f;
|
||||
float unknown_0x08 = 0.0f;
|
||||
float unknown_0x0C = 0.0f;
|
||||
};
|
||||
static_assert(sizeof(VerticalLayoutDecorationWord) == 16, "VerticalLayoutDecorationWord size");
|
||||
static_assert(alignof(VerticalLayoutDecorationWord) == 16,
|
||||
"VerticalLayoutDecorationWord alignment");
|
||||
|
||||
struct alignas(16) VerticalLayoutBlocks {
|
||||
VerticalLayoutMetricsWord metrics;
|
||||
VerticalLayoutDecorationWord decoration;
|
||||
|
||||
constexpr void* words() {
|
||||
return &metrics;
|
||||
}
|
||||
constexpr const void* words() const {
|
||||
return &metrics;
|
||||
}
|
||||
|
||||
float column_advance() const {
|
||||
return metrics.column_advance;
|
||||
}
|
||||
|
||||
float baseline_offset_x() const {
|
||||
return metrics.baseline_offset_x;
|
||||
}
|
||||
|
||||
float decoration_span() const {
|
||||
return decoration.decoration_span;
|
||||
}
|
||||
|
||||
struct Values {
|
||||
float column_advance = 0.0f;
|
||||
float baseline_offset_x = 0.0f;
|
||||
float decoration_span = 0.0f;
|
||||
};
|
||||
|
||||
Values values() const {
|
||||
return {
|
||||
.column_advance = column_advance(),
|
||||
.baseline_offset_x = baseline_offset_x(),
|
||||
.decoration_span = decoration_span(),
|
||||
};
|
||||
}
|
||||
|
||||
void set_column_advance(float v) {
|
||||
metrics.column_advance = v;
|
||||
}
|
||||
|
||||
void set_baseline_offset_x(float v) {
|
||||
metrics.baseline_offset_x = v;
|
||||
}
|
||||
|
||||
void set_unknown_metrics_0x08(float v) {
|
||||
metrics.unknown_0x08 = v;
|
||||
}
|
||||
|
||||
void set_unknown_metrics_0x0C(float v) {
|
||||
metrics.unknown_0x0C = v;
|
||||
}
|
||||
|
||||
void set_decoration_span(float v) {
|
||||
decoration.decoration_span = v;
|
||||
}
|
||||
|
||||
void set_unknown_decoration_0x08(float v) {
|
||||
decoration.unknown_0x08 = v;
|
||||
}
|
||||
|
||||
void set_unknown_decoration_0x0C(float v) {
|
||||
decoration.unknown_0x0C = v;
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(VerticalLayoutBlocks) == 0x20, "VerticalLayoutBlocks size");
|
||||
static_assert(alignof(VerticalLayoutBlocks) == 16, "VerticalLayoutBlocks alignment");
|
||||
static_assert(offsetof(VerticalLayoutBlocks, metrics) == 0x00,
|
||||
"VerticalLayoutBlocks metrics offset");
|
||||
static_assert(offsetof(VerticalLayoutBlocks, decoration) == 0x10,
|
||||
"VerticalLayoutBlocks decoration offset");
|
||||
|
||||
struct HorizontalLayoutBlocksIo {
|
||||
u8 (*words)[16] = nullptr;
|
||||
|
||||
struct F32Field {
|
||||
u8* base = nullptr;
|
||||
std::size_t offset = 0;
|
||||
|
||||
float value() const {
|
||||
float v = 0.0f;
|
||||
std::memcpy(&v, base + offset, sizeof(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
F32Field& operator=(float v) {
|
||||
std::memcpy(base + offset, &v, sizeof(v));
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator float() const {
|
||||
return value();
|
||||
}
|
||||
};
|
||||
|
||||
struct Fields {
|
||||
F32Field line_advance;
|
||||
F32Field baseline;
|
||||
F32Field x_bound_0;
|
||||
F32Field x_bound_1;
|
||||
F32Field effect_height;
|
||||
F32Field u13_i8_lane0;
|
||||
F32Field u13_i8_lane1;
|
||||
};
|
||||
|
||||
Fields fields() const {
|
||||
return {
|
||||
.line_advance = {words ? words[0] : nullptr, 0x00},
|
||||
.baseline = {words ? words[0] : nullptr, 0x04},
|
||||
.x_bound_0 = {words ? words[0] : nullptr, 0x08},
|
||||
.x_bound_1 = {words ? words[0] : nullptr, 0x0C},
|
||||
.effect_height = {words ? words[1] : nullptr, 0x08},
|
||||
.u13_i8_lane0 = {words ? words[2] : nullptr, 0x00},
|
||||
.u13_i8_lane1 = {words ? words[1] : nullptr, 0x0C},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
struct VerticalLayoutBlocksIo {
|
||||
u8 (*words)[16] = nullptr;
|
||||
|
||||
struct F32Field {
|
||||
u8* base = nullptr;
|
||||
std::size_t offset = 0;
|
||||
|
||||
float value() const {
|
||||
float v = 0.0f;
|
||||
std::memcpy(&v, base + offset, sizeof(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
F32Field& operator=(float v) {
|
||||
std::memcpy(base + offset, &v, sizeof(v));
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator float() const {
|
||||
return value();
|
||||
}
|
||||
};
|
||||
|
||||
struct Fields {
|
||||
F32Field column_advance;
|
||||
F32Field baseline_offset_x;
|
||||
F32Field decoration_span;
|
||||
F32Field unknown_metrics_0x08;
|
||||
F32Field unknown_metrics_0x0C;
|
||||
F32Field unknown_decoration_0x08;
|
||||
F32Field unknown_decoration_0x0C;
|
||||
};
|
||||
|
||||
Fields fields() const {
|
||||
return {
|
||||
.column_advance = {words ? words[0] : nullptr, 0x00},
|
||||
.baseline_offset_x = {words ? words[0] : nullptr, 0x04},
|
||||
.decoration_span = {words ? words[1] : nullptr, 0x04},
|
||||
.unknown_metrics_0x08 = {words ? words[0] : nullptr, 0x08},
|
||||
.unknown_metrics_0x0C = {words ? words[0] : nullptr, 0x0C},
|
||||
.unknown_decoration_0x08 = {words ? words[1] : nullptr, 0x08},
|
||||
.unknown_decoration_0x0C = {words ? words[1] : nullptr, 0x0C},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
struct alignas(16) VerticalLayoutAltBlocks {
|
||||
struct MetricsWord {
|
||||
float unknown_0x00 = 0.0f;
|
||||
float baseline_offset_x_candidate = 0.0f;
|
||||
float unknown_0x08 = 0.0f;
|
||||
float unknown_0x0C = 0.0f;
|
||||
};
|
||||
|
||||
struct ExtrasWord {
|
||||
float unknown_0x00 = 0.0f;
|
||||
float decoration_span_candidate = 0.0f;
|
||||
float unknown_0x08 = 0.0f;
|
||||
float unknown_0x0C = 0.0f;
|
||||
};
|
||||
|
||||
MetricsWord metrics;
|
||||
ExtrasWord extras;
|
||||
|
||||
constexpr void* words() {
|
||||
return &metrics;
|
||||
}
|
||||
constexpr const void* words() const {
|
||||
return &metrics;
|
||||
}
|
||||
|
||||
struct Values {
|
||||
MetricsWord metrics{};
|
||||
ExtrasWord extras{};
|
||||
};
|
||||
|
||||
Values values() const {
|
||||
return {
|
||||
.metrics = metrics,
|
||||
.extras = extras,
|
||||
};
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(VerticalLayoutAltBlocks) == 0x20, "VerticalLayoutAltBlocks size");
|
||||
static_assert(alignof(VerticalLayoutAltBlocks) == 16, "VerticalLayoutAltBlocks alignment");
|
||||
static_assert(offsetof(VerticalLayoutAltBlocks, metrics) == 0x00,
|
||||
"VerticalLayoutAltBlocks metrics offset");
|
||||
static_assert(offsetof(VerticalLayoutAltBlocks, extras) == 0x10,
|
||||
"VerticalLayoutAltBlocks extras offset");
|
||||
|
||||
s32 ComputeHorizontalLayoutBlocks(Libraries::Font::OrbisFontHandle fontHandle,
|
||||
const void* style_state_block, u8 (*out_words)[16]);
|
||||
s32 ComputeVerticalLayoutBlocks(Libraries::Font::OrbisFontHandle fontHandle,
|
||||
const void* style_state_block, u8 (*out_words)[16]);
|
||||
|
||||
inline u8 (*LayoutWordsBytes(void* bytes))[16] {
|
||||
return reinterpret_cast<u8(*)[16]>(bytes);
|
||||
}
|
||||
inline const u8 (*LayoutWordsBytes(const void* bytes))[16] {
|
||||
return reinterpret_cast<const u8(*)[16]>(bytes);
|
||||
}
|
||||
|
||||
inline s32 ComputeHorizontalLayoutBlocksWords(Libraries::Font::OrbisFontHandle fontHandle,
|
||||
const void* style_state_block,
|
||||
LayoutWord* out_words) {
|
||||
return ComputeHorizontalLayoutBlocks(fontHandle, style_state_block,
|
||||
reinterpret_cast<u8(*)[16]>(out_words));
|
||||
}
|
||||
|
||||
inline s32 ComputeHorizontalLayoutBlocksTyped(Libraries::Font::OrbisFontHandle fontHandle,
|
||||
const void* style_state_block,
|
||||
HorizontalLayoutBlocks* out_blocks) {
|
||||
return ComputeHorizontalLayoutBlocks(fontHandle, style_state_block,
|
||||
reinterpret_cast<u8(*)[16]>(out_blocks->words()));
|
||||
}
|
||||
|
||||
inline s32 ComputeVerticalLayoutBlocksWords(Libraries::Font::OrbisFontHandle fontHandle,
|
||||
const void* style_state_block, LayoutWord* out_words) {
|
||||
return ComputeVerticalLayoutBlocks(fontHandle, style_state_block,
|
||||
reinterpret_cast<u8(*)[16]>(out_words));
|
||||
}
|
||||
|
||||
inline s32 ComputeVerticalLayoutBlocksTyped(Libraries::Font::OrbisFontHandle fontHandle,
|
||||
const void* style_state_block,
|
||||
VerticalLayoutBlocks* out_blocks) {
|
||||
return ComputeVerticalLayoutBlocks(fontHandle, style_state_block,
|
||||
reinterpret_cast<u8(*)[16]>(out_blocks->words()));
|
||||
}
|
||||
|
||||
inline s32 ComputeHorizontalLayoutBlocksToBytes(Libraries::Font::OrbisFontHandle fontHandle,
|
||||
const void* style_state_block, void* out_bytes) {
|
||||
return ComputeHorizontalLayoutBlocks(fontHandle, style_state_block,
|
||||
LayoutWordsBytes(out_bytes));
|
||||
}
|
||||
|
||||
inline s32 ComputeVerticalLayoutBlocksToBytes(Libraries::Font::OrbisFontHandle fontHandle,
|
||||
const void* style_state_block, void* out_bytes) {
|
||||
return ComputeVerticalLayoutBlocks(fontHandle, style_state_block, LayoutWordsBytes(out_bytes));
|
||||
}
|
||||
|
||||
struct SysFontDesc {
|
||||
float scale_factor;
|
||||
s32 shift_value;
|
||||
};
|
||||
|
||||
SysFontDesc GetSysFontDesc(u32 font_id);
|
||||
|
||||
Libraries::Font::FontHandleOpaqueNative* GetNativeFont(Libraries::Font::OrbisFontHandle h);
|
||||
bool AcquireFontLock(Libraries::Font::FontHandleOpaqueNative* font, u32& out_prev_lock_word);
|
||||
void ReleaseFontLock(Libraries::Font::FontHandleOpaqueNative* font, u32 prev_lock_word);
|
||||
bool AcquireCachedStyleLock(Libraries::Font::FontHandleOpaqueNative* font, u32& out_prev_lock_word);
|
||||
void ReleaseCachedStyleLock(Libraries::Font::FontHandleOpaqueNative* font, u32 prev_lock_word);
|
||||
|
||||
std::uint8_t* AcquireFontCtxEntry(std::uint8_t* ctx, u32 idx, u32 mode_low, void** out_obj,
|
||||
u32* out_lock_word);
|
||||
|
||||
void ReleaseFontObjectsForHandle(Libraries::Font::OrbisFontHandle fontHandle, int entryCount);
|
||||
|
||||
s32 ComputeHorizontalLayoutBlocks(Libraries::Font::OrbisFontHandle fontHandle,
|
||||
const void* style_state_block, u8 (*out_words)[16]);
|
||||
|
||||
s32 ComputeVerticalLayoutBlocks(Libraries::Font::OrbisFontHandle fontHandle,
|
||||
const void* style_state_block, u8 (*out_words)[16]);
|
||||
|
||||
s32 GetCharGlyphMetrics(Libraries::Font::OrbisFontHandle fontHandle, u32 code,
|
||||
Libraries::Font::OrbisFontGlyphMetrics* metrics, bool use_cached_style);
|
||||
|
||||
const std::uint8_t* FindSysFontRangeRecord(u32 font_id, u32 codepoint);
|
||||
|
||||
u32 ResolveSysFontCodepoint(const void* record, u64 code, u32 flags, u32* out_font_id);
|
||||
|
||||
s32 RenderCharGlyphImageCore(Libraries::Font::OrbisFontHandle fontHandle, u32 code,
|
||||
Libraries::Font::OrbisFontRenderSurface* surf, float x, float y,
|
||||
Libraries::Font::OrbisFontGlyphMetrics* metrics,
|
||||
Libraries::Font::OrbisFontRenderOutput* result);
|
||||
|
||||
s32 RenderGlyphImageCore(Libraries::Font::OrbisFontGlyph fontGlyph,
|
||||
Libraries::Font::OrbisFontStyleFrame* fontStyleFrame,
|
||||
Libraries::Font::OrbisFontRenderer fontRenderer,
|
||||
Libraries::Font::OrbisFontRenderSurface* surface, float x, float y,
|
||||
int mode, Libraries::Font::OrbisFontGlyphMetrics* metrics,
|
||||
Libraries::Font::OrbisFontRenderOutput* result);
|
||||
|
||||
s32 StyleStateSetScalePixel(void* style_state_block, float w, float h);
|
||||
|
||||
s32 StyleStateSetScalePoint(void* style_state_block, float w, float h);
|
||||
|
||||
s32 StyleStateGetScalePixel(const void* style_state_block, float* w, float* h);
|
||||
|
||||
s32 StyleStateGetScalePoint(const void* style_state_block, float* w, float* h);
|
||||
|
||||
s32 StyleStateSetDpi(u32* dpi_pair, u32 h_dpi, u32 v_dpi);
|
||||
|
||||
s32 StyleStateSetSlantRatio(void* style_state_block, float slantRatio);
|
||||
|
||||
s32 StyleStateGetSlantRatio(const void* style_state_block, float* slantRatio);
|
||||
|
||||
s32 StyleStateSetWeightScale(void* style_state_block, float weightXScale, float weightYScale);
|
||||
|
||||
s32 StyleStateGetWeightScale(const void* style_state_block, float* weightXScale,
|
||||
float* weightYScale, u32* mode);
|
||||
|
||||
} // namespace Libraries::Font::Internal
|
||||
|
||||
namespace Libraries::FontFt::Internal {
|
||||
|
||||
u32 PS4_SYSV_ABI LibraryGetPixelResolutionStub();
|
||||
s32 PS4_SYSV_ABI LibraryInitStub(const void* memory, void* library);
|
||||
s32 PS4_SYSV_ABI LibraryTermStub(void* library);
|
||||
s32 PS4_SYSV_ABI LibrarySupportStub(void* library, u32 formats);
|
||||
s32 PS4_SYSV_ABI LibraryOpenFontMemoryStub(void* library, u32 mode, const void* fontAddress,
|
||||
u32 fontSize, u32 subFontIndex, u32 uniqueWord,
|
||||
void** inoutFontObj);
|
||||
s32 PS4_SYSV_ABI LibraryCloseFontObjStub(void* fontObj, u32 flags);
|
||||
s32 PS4_SYSV_ABI LibraryGetFaceMetricStub(void* fontObj, u32 metricId, u16* outMetric);
|
||||
s32 PS4_SYSV_ABI LibraryGetFaceScaleStub(void* fontObj, u16* outUnitsPerEm, float* outScale);
|
||||
s32 PS4_SYSV_ABI LibraryGetGlyphIndexStub(void* fontObj, u32 codepoint_u16, u32* out_glyph_index);
|
||||
|
||||
s32 PS4_SYSV_ABI LibrarySetCharSizeWithDpiStub(void* fontObj, u32 dpi_x, u32 dpi_y, float scale_x,
|
||||
float scale_y, float* out_scale_x,
|
||||
float* out_scale_y);
|
||||
s32 PS4_SYSV_ABI LibrarySetCharSizeDefaultDpiStub(void* fontObj, float scale_x, float scale_y,
|
||||
float* out_scale_x, float* out_scale_y);
|
||||
s32 PS4_SYSV_ABI LibraryComputeLayoutBlockStub(void* fontObj, const void* style_state_block,
|
||||
u8 (*out_words)[16]);
|
||||
s32 PS4_SYSV_ABI LibraryComputeLayoutAltBlockStub(void* fontObj, const void* style_state_block,
|
||||
u8 (*out_words)[16]);
|
||||
|
||||
s32 PS4_SYSV_ABI LibraryLoadGlyphCachedStub(void* fontObj, u32 glyphIndex, s32 mode,
|
||||
std::uint64_t* out_words);
|
||||
s32 PS4_SYSV_ABI LibraryGetGlyphMetricsStub(void* fontObj, std::uint32_t* opt_param2,
|
||||
std::uint8_t mode, std::uint8_t* out_params,
|
||||
Libraries::Font::OrbisFontGlyphMetrics* out_metrics);
|
||||
s32 PS4_SYSV_ABI LibraryApplyGlyphAdjustStub(void* fontObj, u32 p2, u32 glyphIndex, s32 p4, s32 p5,
|
||||
u32* inoutGlyphIndex);
|
||||
s32 PS4_SYSV_ABI LibraryConfigureGlyphStub(void* fontObj, std::uint32_t* in_params, s32 mode,
|
||||
std::uint32_t* inout_state);
|
||||
|
||||
s32 PS4_SYSV_ABI FtRendererCreate(void* renderer);
|
||||
u64 PS4_SYSV_ABI FtRendererQuery(void* renderer, u8* params, s64* out_ptr, u8 (*out_vec)[16]);
|
||||
s32 PS4_SYSV_ABI FtRendererDestroy(void* renderer);
|
||||
|
||||
} // namespace Libraries::FontFt::Internal
|
||||
Loading…
Reference in New Issue
Block a user