summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/freetype/src/svg/ftsvg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/freetype/src/svg/ftsvg.c')
-rw-r--r--src/3rdparty/freetype/src/svg/ftsvg.c355
1 files changed, 355 insertions, 0 deletions
diff --git a/src/3rdparty/freetype/src/svg/ftsvg.c b/src/3rdparty/freetype/src/svg/ftsvg.c
new file mode 100644
index 0000000000..ba237f6380
--- /dev/null
+++ b/src/3rdparty/freetype/src/svg/ftsvg.c
@@ -0,0 +1,355 @@
+/****************************************************************************
+ *
+ * ftsvg.c
+ *
+ * The FreeType SVG renderer interface (body).
+ *
+ * Copyright (C) 2022-2023 by
+ * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftserv.h>
+#include <freetype/internal/services/svprop.h>
+#include <freetype/otsvg.h>
+#include <freetype/internal/svginterface.h>
+#include <freetype/ftbbox.h>
+
+#include "ftsvg.h"
+#include "svgtypes.h"
+
+
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, usued to print/log
+ * messages during execution.
+ */
+#undef FT_COMPONENT
+#define FT_COMPONENT otsvg
+
+
+#ifdef FT_CONFIG_OPTION_SVG
+
+ /* ft_svg_init */
+ static FT_Error
+ ft_svg_init( FT_Module module )
+ {
+ SVG_Renderer render = (SVG_Renderer)module;
+
+ FT_Error error = FT_Err_Ok;
+
+
+ render->loaded = FALSE;
+ render->hooks_set = FALSE;
+
+ return error;
+ }
+
+
+ static void
+ ft_svg_done( FT_Module module )
+ {
+ SVG_Renderer render = (SVG_Renderer)module;
+
+
+ if ( render->loaded == TRUE &&
+ render->hooks_set == TRUE )
+ render->hooks.free_svg( &render->state );
+
+ render->loaded = FALSE;
+ }
+
+
+ static FT_Error
+ ft_svg_preset_slot( FT_Module module,
+ FT_GlyphSlot slot,
+ FT_Bool cache )
+ {
+ SVG_Renderer svg_renderer = (SVG_Renderer)module;
+ SVG_RendererHooks hooks = svg_renderer->hooks;
+
+
+ if ( svg_renderer->hooks_set == FALSE )
+ {
+ FT_TRACE1(( "Hooks are NOT set. Can't render OT-SVG glyphs\n" ));
+ return FT_THROW( Missing_SVG_Hooks );
+ }
+
+ if ( svg_renderer->loaded == FALSE )
+ {
+ FT_TRACE3(( "ft_svg_preset_slot: first presetting call,"
+ " calling init hook\n" ));
+ hooks.init_svg( &svg_renderer->state );
+
+ svg_renderer->loaded = TRUE;
+ }
+
+ return hooks.preset_slot( slot, cache, &svg_renderer->state );
+ }
+
+
+ static FT_Error
+ ft_svg_render( FT_Renderer renderer,
+ FT_GlyphSlot slot,
+ FT_Render_Mode mode,
+ const FT_Vector* origin )
+ {
+ SVG_Renderer svg_renderer = (SVG_Renderer)renderer;
+
+ FT_Library library = renderer->root.library;
+ FT_Memory memory = library->memory;
+ FT_Error error;
+
+ FT_ULong size_image_buffer;
+
+ SVG_RendererHooks hooks = svg_renderer->hooks;
+
+
+ FT_UNUSED( mode );
+ FT_UNUSED( origin );
+
+ if ( mode != FT_RENDER_MODE_NORMAL )
+ return FT_THROW( Bad_Argument );
+
+ if ( svg_renderer->hooks_set == FALSE )
+ {
+ FT_TRACE1(( "Hooks are NOT set. Can't render OT-SVG glyphs\n" ));
+ return FT_THROW( Missing_SVG_Hooks );
+ }
+
+ if ( svg_renderer->loaded == FALSE )
+ {
+ FT_TRACE3(( "ft_svg_render: first rendering, calling init hook\n" ));
+ error = hooks.init_svg( &svg_renderer->state );
+
+ svg_renderer->loaded = TRUE;
+ }
+
+ ft_svg_preset_slot( (FT_Module)renderer, slot, TRUE );
+
+ size_image_buffer = (FT_ULong)slot->bitmap.pitch * slot->bitmap.rows;
+ /* No `FT_QALLOC` here since we need a clean, empty canvas */
+ /* to start with. */
+ if ( FT_ALLOC( slot->bitmap.buffer, size_image_buffer ) )
+ return error;
+
+ error = hooks.render_svg( slot, &svg_renderer->state );
+ if ( error )
+ FT_FREE( slot->bitmap.buffer );
+ else
+ slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
+
+ return error;
+ }
+
+
+ static const SVG_Interface svg_interface =
+ {
+ ft_svg_preset_slot /* Preset_Bitmap_Func preset_slot */
+ };
+
+
+ static FT_Error
+ ft_svg_property_set( FT_Module module,
+ const char* property_name,
+ const void* value,
+ FT_Bool value_is_string )
+ {
+ FT_Error error = FT_Err_Ok;
+ SVG_Renderer renderer = (SVG_Renderer)module;
+
+
+ if ( !ft_strcmp( property_name, "svg-hooks" ) )
+ {
+ SVG_RendererHooks* hooks;
+
+
+ if ( value_is_string == TRUE )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ hooks = (SVG_RendererHooks*)value;
+
+ if ( !hooks->init_svg ||
+ !hooks->free_svg ||
+ !hooks->render_svg ||
+ !hooks->preset_slot )
+ {
+ FT_TRACE0(( "ft_svg_property_set:"
+ " SVG rendering hooks not set because\n" ));
+ FT_TRACE0(( " "
+ " at least one function pointer is NULL\n" ));
+
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ renderer->hooks = *hooks;
+ renderer->hooks_set = TRUE;
+ }
+ else
+ error = FT_THROW( Missing_Property );
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ ft_svg_property_get( FT_Module module,
+ const char* property_name,
+ void* value )
+ {
+ FT_Error error = FT_Err_Ok;
+ SVG_Renderer renderer = (SVG_Renderer)module;
+
+
+ if ( !ft_strcmp( property_name, "svg-hooks" ) )
+ {
+ SVG_RendererHooks* hooks = (SVG_RendererHooks*)value;
+
+
+ *hooks = renderer->hooks;
+ }
+ else
+ error = FT_THROW( Missing_Property );
+
+ return error;
+ }
+
+
+ FT_DEFINE_SERVICE_PROPERTIESREC(
+ ft_svg_service_properties,
+
+ ft_svg_property_set, /* FT_Properties_SetFunc set_property */
+ ft_svg_property_get /* FT_Properties_GetFunc get_property */
+ )
+
+
+ FT_DEFINE_SERVICEDESCREC1(
+ ft_svg_services,
+ FT_SERVICE_ID_PROPERTIES, &ft_svg_service_properties )
+
+
+ FT_CALLBACK_DEF( FT_Module_Interface )
+ ft_svg_get_interface( FT_Module module,
+ const char* ft_svg_interface )
+ {
+ FT_Module_Interface result;
+
+
+ FT_UNUSED( module );
+
+ result = ft_service_list_lookup( ft_svg_services, ft_svg_interface );
+ if ( result )
+ return result;
+
+ return 0;
+ }
+
+
+ static FT_Error
+ ft_svg_transform( FT_Renderer renderer,
+ FT_GlyphSlot slot,
+ const FT_Matrix* _matrix,
+ const FT_Vector* _delta )
+ {
+ FT_SVG_Document doc = (FT_SVG_Document)slot->other;
+ FT_Matrix* matrix = (FT_Matrix*)_matrix;
+ FT_Vector* delta = (FT_Vector*)_delta;
+
+ FT_Matrix tmp_matrix;
+ FT_Vector tmp_delta;
+
+ FT_Matrix a, b;
+ FT_Pos x, y;
+
+
+ FT_UNUSED( renderer );
+
+ if ( !matrix )
+ {
+ tmp_matrix.xx = 0x10000;
+ tmp_matrix.xy = 0;
+ tmp_matrix.yx = 0;
+ tmp_matrix.yy = 0x10000;
+
+ matrix = &tmp_matrix;
+ }
+
+ if ( !delta )
+ {
+ tmp_delta.x = 0;
+ tmp_delta.y = 0;
+
+ delta = &tmp_delta;
+ }
+
+ a = doc->transform;
+ b = *matrix;
+ FT_Matrix_Multiply( &b, &a );
+
+
+ x = ADD_LONG( ADD_LONG( FT_MulFix( matrix->xx, doc->delta.x ),
+ FT_MulFix( matrix->xy, doc->delta.y ) ),
+ delta->x );
+ y = ADD_LONG( ADD_LONG( FT_MulFix( matrix->yx, doc->delta.x ),
+ FT_MulFix( matrix->yy, doc->delta.y ) ),
+ delta->y );
+
+ doc->delta.x = x;
+ doc->delta.y = y;
+ doc->transform = a;
+
+ return FT_Err_Ok;
+ }
+
+#endif /* FT_CONFIG_OPTION_SVG */
+
+
+#ifdef FT_CONFIG_OPTION_SVG
+#define PUT_SVG_MODULE( a ) a
+#define SVG_GLYPH_FORMAT FT_GLYPH_FORMAT_SVG
+#else
+#define PUT_SVG_MODULE( a ) NULL
+#define SVG_GLYPH_FORMAT FT_GLYPH_FORMAT_NONE
+#endif
+
+
+ FT_DEFINE_RENDERER(
+ ft_svg_renderer_class,
+
+ FT_MODULE_RENDERER,
+ sizeof ( SVG_RendererRec ),
+
+ "ot-svg",
+ 0x10000L,
+ 0x20000L,
+
+ (const void*)PUT_SVG_MODULE( &svg_interface ), /* module specific interface */
+
+ PUT_SVG_MODULE( ft_svg_init ), /* FT_Module_Constructor module_init */
+ PUT_SVG_MODULE( ft_svg_done ), /* FT_Module_Destructor module_done */
+ PUT_SVG_MODULE( ft_svg_get_interface ), /* FT_Module_Requester get_interface */
+
+ SVG_GLYPH_FORMAT,
+
+ PUT_SVG_MODULE( ft_svg_render ), /* FT_Renderer_RenderFunc render_glyph */
+ PUT_SVG_MODULE( ft_svg_transform ), /* FT_Renderer_TransformFunc transform_glyph */
+ NULL, /* FT_Renderer_GetCBoxFunc get_glyph_cbox */
+ NULL, /* FT_Renderer_SetModeFunc set_mode */
+ NULL /* FT_Raster_Funcs* raster_class */
+ )
+
+
+/* END */