diff --git a/include/freetype/ftglyph.h b/include/freetype/ftglyph.h index b29751e04..e34644409 100644 --- a/include/freetype/ftglyph.h +++ b/include/freetype/ftglyph.h @@ -268,6 +268,12 @@ FT_BEGIN_HEADER * end_glyph_id :: * The ending glyph ID for the glyph range that this document has. * + * transform :: + * Transformation matrix to apply on the glyph while rendering. + * + * delta :: + * Translation to apply on the glyph while rendering. + * * @note: * `metrics` and `units_per_EM` might look like repetitions since both * fields are stored in face objects. However, the Glyph Management API @@ -289,7 +295,8 @@ FT_BEGIN_HEADER FT_UShort units_per_EM; FT_UShort start_glyph_id; FT_UShort end_glyph_id; - /* TODO: (OT-SVG) Maybe put a transformation matrix here */ + FT_Matrix transform; + FT_Vector delta; } FT_SvgGlyphRec; diff --git a/include/freetype/otsvg.h b/include/freetype/otsvg.h index 62761c432..09039d528 100644 --- a/include/freetype/otsvg.h +++ b/include/freetype/otsvg.h @@ -147,6 +147,12 @@ FT_BEGIN_HEADER * end_glyph_id :: * The ending glyph ID for the glyph range that this document has. * + * transform :: + * Transformation matrix to apply on the glyph while rendering. + * + * delta :: + * Translation to apply on the glyph while rendering. + * * @note: * `metrics` and `units_per_EM` might look like repetitions since both * fields are stored in face object, but they are not; When the slot is @@ -165,6 +171,8 @@ FT_BEGIN_HEADER FT_UShort units_per_EM; FT_UShort start_glyph_id; FT_UShort end_glyph_id; + FT_Matrix transform; + FT_Vector delta; } FT_SVG_DocumentRec; /************************************************************************** diff --git a/src/base/ftglyph.c b/src/base/ftglyph.c index fa60ea1e7..300c05baa 100644 --- a/src/base/ftglyph.c +++ b/src/base/ftglyph.c @@ -326,6 +326,9 @@ glyph->units_per_EM = document->units_per_EM; glyph->start_glyph_id = document->start_glyph_id; glyph->end_glyph_id = document->end_glyph_id; + glyph->transform = document->transform; + glyph->delta = document->delta; + /* copy the document into glyph */ FT_MEM_COPY( glyph->svg_document, document->svg_document, doc_length ); @@ -372,6 +375,8 @@ target->units_per_EM = source->units_per_EM; target->start_glyph_id = source->start_glyph_id; target->end_glyph_id = source->end_glyph_id; + target->transform = source->transform; + target->delta = source->delta; /* allocate space for the svg document */ target->svg_document = memory->alloc( memory, @@ -385,6 +390,29 @@ return error; } + FT_CALLBACK_DEF( void ) + ft_svg_glyph_transform( FT_Glyph svg_glyph, + const FT_Matrix* matrix, + const FT_Vector* delta ) + { + FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph; + + if ( matrix ) + { + FT_Matrix a, b; + a = glyph->transform; + b = *matrix; + FT_Matrix_Multiply( &b, &a ); + glyph->transform = a; + } + + if ( delta ) + { + glyph->delta.x = ADD_LONG( glyph->delta.x, delta->x ); + glyph->delta.y = ADD_LONG( glyph->delta.y, delta->y ); + } + } + FT_CALLBACK_DEF( FT_Error ) ft_svg_glyph_prepare( FT_Glyph svg_glyph, FT_GlyphSlot slot ) @@ -404,6 +432,8 @@ document->units_per_EM = glyph->units_per_EM; document->start_glyph_id = glyph->start_glyph_id; document->end_glyph_id = glyph->end_glyph_id; + document->transform = glyph->transform; + document->delta = glyph->delta; slot->format = FT_GLYPH_FORMAT_SVG; slot->glyph_index = glyph->glyph_index; @@ -421,7 +451,7 @@ ft_svg_glyph_init, /* FT_Glyph_InitFunc glyph_init */ ft_svg_glyph_done, /* FT_Glyph_DoneFunc glyph_done */ ft_svg_glyph_copy, /* FT_Glyph_CopyFunc glyph_copy */ - NULL, /* FT_Glyph_TransformFunc glyph_transform */ + ft_svg_glyph_transform, /* FT_Glyph_TransformFunc glyph_transform */ NULL, /* FT_Glyph_GetBBoxFunc glyph_bbox */ ft_svg_glyph_prepare /* FT_Glyph_PrepareFunc glyph_prepare */ ) diff --git a/src/sfnt/ttsvg.c b/src/sfnt/ttsvg.c index 4607c1e6f..da83168b0 100644 --- a/src/sfnt/ttsvg.c +++ b/src/sfnt/ttsvg.c @@ -320,6 +320,13 @@ svg_document->start_glyph_id = start_glyph_id; svg_document->end_glyph_id = end_glyph_id; + svg_document->transform.xx = 0x10000; + svg_document->transform.xy = 0; + svg_document->transform.yx = 0; + svg_document->transform.yy = 0x10000; + svg_document->delta.x = 0; + svg_document->delta.y = 0; + FT_TRACE5(( "start_glyph_id: %d\n", start_glyph_id )); FT_TRACE5(( "end_glyph_id: %d\n", end_glyph_id )); FT_TRACE5(( "svg_document:\n%.*s\n", doc_length, doc_list )); diff --git a/src/svg/ftsvg.c b/src/svg/ftsvg.c index 2f04758d5..2ba0a17ee 100644 --- a/src/svg/ftsvg.c +++ b/src/svg/ftsvg.c @@ -187,6 +187,32 @@ 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; + + if ( matrix ) + { + FT_Matrix a, b; + a = doc->transform; + b = *matrix; + FT_Matrix_Multiply( &b, &a ); + doc->transform = a; + } + + if ( delta ) + { + doc->delta.x = ADD_LONG( doc->delta.x, delta->x ); + doc->delta.y = ADD_LONG( doc->delta.y, delta->y ); + } + + return FT_Err_Ok; + } + #endif #ifdef FT_CONFIG_OPTION_SVG @@ -213,7 +239,7 @@ PUT_SVG_MODULE( ft_svg_get_interface ), /* get_interface */ SVG_GLYPH_FORMAT, (FT_Renderer_RenderFunc)PUT_SVG_MODULE( ft_svg_render ), - NULL, + (FT_Renderer_TransformFunc)PUT_SVG_MODULE( ft_svg_transform ), NULL, NULL, NULL