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:
w1naenator 2026-01-08 03:08:29 +02:00
parent 9387adc79e
commit e9ca20b65d
10 changed files with 11887 additions and 1937 deletions

View File

@ -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)

View File

@ -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

View File

@ -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();

File diff suppressed because it is too large Load Diff

View 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

View File

@ -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;
}

View File

@ -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();

File diff suppressed because it is too large Load Diff

View 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