First Commit

This commit is contained in:
2025-11-18 14:18:26 -07:00
parent 33eb6e3707
commit 27277ec342
6106 changed files with 3571167 additions and 0 deletions

291
3rdparty/plutosvg/source/plutosvg-ft.h vendored Normal file
View File

@@ -0,0 +1,291 @@
/*
* Copyright (c) 2020-2025 Samuel Ugochukwu <sammycageagle@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* @brief FreeType hooks for rendering SVG glyphs with PlutoSVG.
*
* This file implements the integration layer between FreeTypes SVG module (typically
* named "ot-svg") and PlutoSVG. It defines the necessary functions to initialize and
* free the SVG rendering state, render an SVG glyph into a glyph slot, load (and cache)
* SVG documents, and pre-configure glyph slots with appropriate metrics and transforms.
*
* These functions are aggregated into the `plutosvg_ft_hooks` structure.
*
* Usage example:
* @code
* #include <plutosvg-ft.h>
*
* #include <ft2build.h>
* #include FT_FREETYPE_H
* #include FT_MODULE_H
*
* int main(void)
* {
* FT_Library library;
* if (FT_Init_FreeType(&library))
* return -1;
*
* if (FT_Property_Set(library, "ot-svg", "svg-hooks", &plutosvg_ft_hooks))
* return -1;
*
* // ... your code ...
*
* FT_Done_FreeType(library);
* return 0;
* }
* @endcode
*/
#ifndef PLUTOSVG_FT_H
#define PLUTOSVG_FT_H
#include "plutosvg.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ft2build.h>
#include FT_OTSVG_H
#include FT_COLOR_H
typedef struct {
plutosvg_document_t* document;
const FT_Byte* data;
FT_ULong length;
} plutosvg_ft_document_entry_t;
#define PLUTOSVG_FT_MAX_DOCS 16
typedef struct {
plutosvg_document_t* document;
plutovg_matrix_t matrix;
plutovg_rect_t extents;
plutosvg_ft_document_entry_t entries[PLUTOSVG_FT_MAX_DOCS];
FT_ULong num_entries;
} plutosvg_ft_state_t;
static FT_Error plutosvg_ft_init(FT_Pointer* ft_state)
{
plutosvg_ft_state_t* state = (plutosvg_ft_state_t*)malloc(sizeof(plutosvg_ft_state_t));
memset(state, 0, sizeof(plutosvg_ft_state_t));
*ft_state = state;
return FT_Err_Ok;
}
static void plutosvg_ft_free(FT_Pointer* ft_state)
{
plutosvg_ft_state_t* state = (plutosvg_ft_state_t*)(*ft_state);
for(FT_ULong i = 0; i < state->num_entries; ++i)
plutosvg_document_destroy(state->entries[i].document);
free(state);
}
#define PLUTOSVG_FT_PALETTE_INDEX 0
static bool plutosvg_ft_palette_func(void* closure, const char* name, int length, plutovg_color_t* color)
{
FT_Face ft_face = (FT_Face)(closure);
if(length < 5 || strncmp(name, "color", 5) != 0)
return false;
FT_Palette_Data ft_palette_data;
if(FT_Palette_Data_Get(ft_face, &ft_palette_data))
return false;
FT_Color* ft_palette = NULL;
if(FT_Palette_Select(ft_face, PLUTOSVG_FT_PALETTE_INDEX, &ft_palette)) {
return false;
}
FT_Int index = 0;
for(int i = 5; i < length; ++i) {
const char ch = name[i];
if(ch < '0' || ch > '9')
return false;
index = index * 10 + ch - '0';
}
if(index >= ft_palette_data.num_palette_entries)
return false;
FT_Color* ft_color = ft_palette + index;
color->r = ft_color->red / 255.f;
color->g = ft_color->green / 255.f;
color->b = ft_color->blue / 255.f;
color->a = ft_color->alpha / 255.f;
return true;
}
static FT_Error plutosvg_ft_render(FT_GlyphSlot ft_slot, FT_Pointer* ft_state)
{
plutosvg_ft_state_t* state = (plutosvg_ft_state_t*)(*ft_state);
if(state->document == NULL)
return FT_Err_Invalid_SVG_Document;
plutovg_surface_t* surface = plutovg_surface_create_for_data(ft_slot->bitmap.buffer, ft_slot->bitmap.width, ft_slot->bitmap.rows, ft_slot->bitmap.pitch);
plutovg_canvas_t* canvas = plutovg_canvas_create(surface);
FT_SVG_Document ft_document = (FT_SVG_Document)ft_slot->other;
FT_UShort start_glyph_id = ft_document->start_glyph_id;
FT_UShort end_glyph_id = ft_document->end_glyph_id;
char buffer[64];
char* id = NULL;
if(start_glyph_id < end_glyph_id) {
sprintf(buffer, "glyph%u", ft_slot->glyph_index);
id = buffer;
}
plutovg_canvas_translate(canvas, -state->extents.x, -state->extents.y);
plutovg_canvas_transform(canvas, &state->matrix);
plutosvg_document_render(state->document, id, canvas, NULL, plutosvg_ft_palette_func, ft_slot->face);
ft_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
ft_slot->bitmap.num_grays = 256;
ft_slot->format = FT_GLYPH_FORMAT_BITMAP;
plutovg_canvas_destroy(canvas);
plutovg_surface_destroy(surface);
state->document = NULL;
return FT_Err_Ok;
}
static plutosvg_document_t* plutosvg_ft_document_load(plutosvg_ft_state_t* state, const FT_Byte* data, FT_ULong length, FT_UShort units_per_EM)
{
for(FT_ULong i = 0; i < state->num_entries; ++i) {
if(data == state->entries[i].data && length == state->entries[i].length) {
plutosvg_ft_document_entry_t entry = state->entries[i];
memmove(&state->entries[1], &state->entries[0], i * sizeof(plutosvg_ft_document_entry_t));
state->entries[0] = entry;
return entry.document;
}
}
plutosvg_document_t* document = plutosvg_document_load_from_data((const char*)data, length, units_per_EM, units_per_EM, NULL, NULL);
if(document == NULL)
return NULL;
if(state->num_entries == PLUTOSVG_FT_MAX_DOCS) {
state->num_entries--;
plutosvg_document_destroy(state->entries[state->num_entries].document);
}
memmove(&state->entries[1], &state->entries[0], state->num_entries * sizeof(plutosvg_ft_document_entry_t));
state->entries[0].document = document;
state->entries[0].data = data;
state->entries[0].length = length;
state->num_entries++;
return document;
}
static FT_Error plutosvg_ft_preset_slot(FT_GlyphSlot ft_slot, FT_Bool ft_cache, FT_Pointer* ft_state)
{
plutosvg_ft_state_t* state = (plutosvg_ft_state_t*)(*ft_state);
FT_SVG_Document ft_document = (FT_SVG_Document)ft_slot->other;
FT_Size_Metrics ft_metrics = ft_document->metrics;
FT_UShort start_glyph_id = ft_document->start_glyph_id;
FT_UShort end_glyph_id = ft_document->end_glyph_id;
plutosvg_document_t* document = plutosvg_ft_document_load(state, ft_document->svg_document, ft_document->svg_document_length, ft_document->units_per_EM);
if(document == NULL) {
return FT_Err_Invalid_SVG_Document;
}
float document_width = plutosvg_document_get_width(document);
float document_height = plutosvg_document_get_height(document);
plutovg_matrix_t transform = {
(float)ft_document->transform.xx / (1 << 16),
-(float)ft_document->transform.xy / (1 << 16),
-(float)ft_document->transform.yx / (1 << 16),
(float)ft_document->transform.yy / (1 << 16),
(float)ft_document->delta.x / 64 * document_width / ft_metrics.x_ppem,
-(float)ft_document->delta.y / 64 * document_height / ft_metrics.y_ppem
};
float x_svg_to_out = ft_metrics.x_ppem / document_width;
float y_svg_to_out = ft_metrics.y_ppem / document_height;
plutovg_matrix_t matrix;
plutovg_matrix_init_scale(&matrix, x_svg_to_out, y_svg_to_out);
plutovg_matrix_multiply(&matrix, &transform, &matrix);
char buffer[64];
char* id = NULL;
if(start_glyph_id < end_glyph_id) {
sprintf(buffer, "glyph%u", ft_slot->glyph_index);
id = buffer;
}
plutovg_rect_t extents;
if(!plutosvg_document_extents(document, id, &extents)) {
return FT_Err_Invalid_SVG_Document;
}
plutovg_matrix_map_rect(&matrix, &extents, &extents);
ft_slot->bitmap_left = (FT_Int)extents.x;
ft_slot->bitmap_top = (FT_Int)-extents.y;
ft_slot->bitmap.rows = (unsigned int)ceilf(extents.h);
ft_slot->bitmap.width = (unsigned int)ceilf(extents.w);
ft_slot->bitmap.pitch = (int)ft_slot->bitmap.width * 4;
ft_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
float metrics_width = extents.w;
float metrics_height = extents.h;
float horiBearingX = extents.x;
float horiBearingY = -extents.y;
float vertBearingX = ft_slot->metrics.horiBearingX / 64.f - ft_slot->metrics.horiAdvance / 64.f / 2;
float vertBearingY = (ft_slot->metrics.vertAdvance / 64.f - ft_slot->metrics.height / 64.f) / 2;
ft_slot->metrics.width = (FT_Pos)roundf(metrics_width * 64);
ft_slot->metrics.height = (FT_Pos)roundf(metrics_height * 64);
ft_slot->metrics.horiBearingX = (FT_Pos)(horiBearingX * 64);
ft_slot->metrics.horiBearingY = (FT_Pos)(horiBearingY * 64);
ft_slot->metrics.vertBearingX = (FT_Pos)(vertBearingX * 64);
ft_slot->metrics.vertBearingY = (FT_Pos)(vertBearingY * 64);
if(ft_slot->metrics.vertAdvance == 0)
ft_slot->metrics.vertAdvance = (FT_Pos)(metrics_height * 1.2f * 64);
if(ft_cache) {
state->document = document;
state->extents = extents;
state->matrix = matrix;
}
return FT_Err_Ok;
}
/**
* @brief FreeType SVG renderer hooks.
*
* This structure is passed to FreeType via FT_Property_Set to delegate SVG glyph
* rendering to PlutoSVG.
*/
static SVG_RendererHooks plutosvg_ft_hooks = {
(SVG_Lib_Init_Func)plutosvg_ft_init,
(SVG_Lib_Free_Func)plutosvg_ft_free,
(SVG_Lib_Render_Func)plutosvg_ft_render,
(SVG_Lib_Preset_Slot_Func)plutosvg_ft_preset_slot
};
#endif // PLUTOSVG_FT_H

2655
3rdparty/plutosvg/source/plutosvg.c vendored Normal file

File diff suppressed because it is too large Load Diff

191
3rdparty/plutosvg/source/plutosvg.h vendored Normal file
View File

@@ -0,0 +1,191 @@
/*
* Copyright (c) 2020-2025 Samuel Ugochukwu <sammycageagle@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef PLUTOSVG_H
#define PLUTOSVG_H
#include <plutovg.h>
#if !defined(PLUTOSVG_BUILD_STATIC) && (defined(_WIN32) || defined(__CYGWIN__))
#define PLUTOSVG_EXPORT __declspec(dllexport)
#define PLUTOSVG_IMPORT __declspec(dllimport)
#elif defined(__GNUC__) && (__GNUC__ >= 4)
#define PLUTOSVG_EXPORT __attribute__((__visibility__("default")))
#define PLUTOSVG_IMPORT
#else
#define PLUTOSVG_EXPORT
#define PLUTOSVG_IMPORT
#endif
#ifdef PLUTOSVG_BUILD
#define PLUTOSVG_API PLUTOSVG_EXPORT
#else
#define PLUTOSVG_API PLUTOSVG_IMPORT
#endif
#define PLUTOSVG_VERSION_MAJOR 0
#define PLUTOSVG_VERSION_MINOR 0
#define PLUTOSVG_VERSION_MICRO 6
#define PLUTOSVG_VERSION PLUTOVG_VERSION_ENCODE(PLUTOSVG_VERSION_MAJOR, PLUTOSVG_VERSION_MINOR, PLUTOSVG_VERSION_MICRO)
#define PLUTOSVG_VERSION_STRING PLUTOVG_VERSION_STRINGIZE(PLUTOSVG_VERSION_MAJOR, PLUTOSVG_VERSION_MINOR, PLUTOSVG_VERSION_MICRO)
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Returns the version number of PlutoSVG.
*
* @return The version number as an integer.
*/
PLUTOSVG_API int plutosvg_version(void);
/**
* @brief Returns the version string of PlutoSVG.
*
* @return Pointer to a string containing the version information.
*/
PLUTOSVG_API const char* plutosvg_version_string(void);
/**
* @brief plutosvg_document_t
*/
typedef struct plutosvg_document plutosvg_document_t;
/**
* @brief Callback type for resolving CSS color variables in SVG documents.
*
* @param closure User-defined data for the callback.
* @param name Name of the color variable.
* @param length Length of the color variable name.
* @param color Pointer to `plutovg_color_t` where the resolved color will be stored.
* @return `true` if the color variable was successfully resolved; `false` otherwise.
*/
typedef bool(*plutosvg_palette_func_t)(void* closure, const char* name, int length, plutovg_color_t* color);
/**
* @brief Loads an SVG document from a data buffer.
*
* @note The buffer pointed to by `data` must remain valid until the `plutosvg_document_t` object is destroyed.
*
* @param data Pointer to the SVG data buffer.
* @param length Length of the data buffer.
* @param width Container width for resolving the initial viewport.
* @param height Container height for resolving the initial viewport.
* @param destroy_func Custom function to call when the document is destroyed.
* @param closure User-defined data for the `destroy_func` callback.
* @return Pointer to the loaded `plutosvg_document_t` structure, or NULL if loading fails.
*/
PLUTOSVG_API plutosvg_document_t* plutosvg_document_load_from_data(const char* data, int length, float width, float height,
plutovg_destroy_func_t destroy_func, void* closure);
/**
* @brief Loads an SVG document from a file.
*
* @param filename Path to the SVG file.
* @param width Container width for resolving the initial viewport.
* @param height Container height for resolving the initial viewport.
* @return Pointer to the loaded `plutosvg_document_t` structure, or NULL if loading fails.
*/
PLUTOSVG_API plutosvg_document_t* plutosvg_document_load_from_file(const char* filename, float width, float height);
/**
* @brief Renders an SVG document or a specific element onto a canvas.
*
* @param document Pointer to the SVG document.
* @param id ID of the SVG element to render, or `NULL` to render the entire document.
* @param canvas Canvas onto which the SVG element or document will be rendered.
* @param current_color Color used to resolve CSS `currentColor` values.
* @param palette_func Callback for resolving CSS color variables.
* @param closure User-defined data for the `palette_func` callback.
* @return `true` if rendering was successful; `false` otherwise.
*/
PLUTOSVG_API bool plutosvg_document_render(const plutosvg_document_t* document, const char* id, plutovg_canvas_t* canvas,
const plutovg_color_t* current_color, plutosvg_palette_func_t palette_func, void* closure);
/**
* @brief Renders an SVG document or a specific element onto a surface.
*
* @param document Pointer to the SVG document.
* @param id ID of the SVG element to render, or `NULL` to render the entire document.
* @param width Width of the surface, or `-1` if unspecified.
* @param height Height of the surface, or `-1` if unspecified.
* @param current_color Color for resolving CSS `currentColor` values.
* @param palette_func Callback for resolving CSS color variables.
* @param closure User-defined data for the `palette_func` callback.
* @return Pointer to the rendered `plutovg_surface_t` structure, or `NULL` if rendering fails.
*/
PLUTOSVG_API plutovg_surface_t* plutosvg_document_render_to_surface(const plutosvg_document_t* document, const char* id, int width, int height,
const plutovg_color_t* current_color, plutosvg_palette_func_t palette_func, void* closure);
/**
* @brief Returns the intrinsic width of the SVG document.
*
* @param document Pointer to the SVG document.
* @return The intrinsic width of the SVG document.
*/
PLUTOSVG_API float plutosvg_document_get_width(const plutosvg_document_t* document);
/**
* @brief Returns the intrinsic height of the SVG document.
*
* @param document Pointer to the SVG document.
* @return The intrinsic height of the SVG document.
*/
PLUTOSVG_API float plutosvg_document_get_height(const plutosvg_document_t* document);
/**
* @brief Retrieves the bounding box of a specific element or the entire SVG document.
*
* Calculates and retrieves the extents of an element identified by `id` or the whole document if `id` is `NULL`.
*
* @param document Pointer to the SVG document.
* @param id ID of the element whose extents to retrieve, or `NULL` to retrieve the extents of the entire document.
* @param extents Pointer to a `plutovg_rect_t` structure where the extents will be stored.
* @return `true` if extents were successfully retrieved; `false` otherwise.
*/
PLUTOSVG_API bool plutosvg_document_extents(const plutosvg_document_t* document, const char* id, plutovg_rect_t* extents);
/**
* @brief Destroys an SVG document and frees its resources.
*
* @param document Pointer to a `plutosvg_document_t` structure to be destroyed. If `NULL`, the function does nothing.
*/
PLUTOSVG_API void plutosvg_document_destroy(plutosvg_document_t* document);
/**
* @deprecated Use `plutosvg_ft_hooks` in "plutosvg-ft.h" instead.
*
* @brief Retrieves PlutoSVG hooks for integrating with FreeType's SVG module.
*
* Provides hooks that allow FreeType to use PlutoSVG for rendering SVG graphics in fonts.
*
* @return Pointer to the structure containing PlutoSVG hooks for FreeType's SVG module, or `NULL` if FreeType integration is not enabled.
*/
PLUTOSVG_API const void* plutosvg_ft_svg_hooks(void);
#ifdef __cplusplus
}
#endif
#endif // PLUTOSVG_H