diff options
Diffstat (limited to 'cut-n-paste-code/freetype/ftglyph.c')
-rw-r--r-- | cut-n-paste-code/freetype/ftglyph.c | 1194 |
1 files changed, 0 insertions, 1194 deletions
diff --git a/cut-n-paste-code/freetype/ftglyph.c b/cut-n-paste-code/freetype/ftglyph.c deleted file mode 100644 index be407b8d8..000000000 --- a/cut-n-paste-code/freetype/ftglyph.c +++ /dev/null @@ -1,1194 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftglyph.c */ -/* */ -/* FreeType convenience functions to handle glyphs (body). */ -/* */ -/* Copyright 1996-2000 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* 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. */ -/* */ -/***************************************************************************/ - - /*************************************************************************/ - /* */ - /* This file contains the definition of several convenience functions */ - /* that can be used by client applications to easily retrieve glyph */ - /* bitmaps and outlines from a given face. */ - /* */ - /* These functions should be optional if you are writing a font server */ - /* or text layout engine on top of FreeType. However, they are pretty */ - /* handy for many other simple uses of the library. */ - /* */ - /*************************************************************************/ - - -#ifdef FT_FLAT_COMPILE - -#include "ftglyph.h" -#include "ftoutln.h" -#include "ftobjs.h" - -#else - -#include <freetype/ftglyph.h> -#include <freetype/ftoutln.h> -#include <freetype/internal/ftobjs.h> - -#endif - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_glyph - - - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** Convenience functions ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Matrix_Multiply */ - /* */ - /* <Description> */ - /* Performs the matrix operation `b = a*b'. */ - /* */ - /* <Input> */ - /* a :: A pointer to matrix `a'. */ - /* */ - /* <InOut> */ - /* b :: A pointer to matrix `b'. */ - /* */ - /* <MT-Note> */ - /* Yes. */ - /* */ - /* <Note> */ - /* The result is undefined if either `a' or `b' is zero. */ - /* */ - FT_EXPORT_FUNC( void ) FT_Matrix_Multiply( FT_Matrix* a, - FT_Matrix* b ) - { - FT_Fixed xx, xy, yx, yy; - - - if ( !a || !b ) - return; - - xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx ); - xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy ); - yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx ); - yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy ); - - b->xx = xx; b->xy = xy; - b->yx = yx; b->yy = yy; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Matrix_Invert */ - /* */ - /* <Description> */ - /* Inverts a 2x2 matrix. Returns an error if it can't be inverted. */ - /* */ - /* <InOut> */ - /* matrix :: A pointer to the target matrix. Remains untouched in */ - /* case of error. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <MT-Note> */ - /* Yes. */ - /* */ - FT_EXPORT_FUNC( FT_Error ) FT_Matrix_Invert( FT_Matrix* matrix ) - { - FT_Pos delta, xx, yy; - - - if ( !matrix ) - return FT_Err_Invalid_Argument; - - /* compute discriminant */ - delta = FT_MulFix( matrix->xx, matrix->yy ) - - FT_MulFix( matrix->xy, matrix->yx ); - - if ( !delta ) - return FT_Err_Invalid_Argument; /* matrix can't be inverted */ - - matrix->xy = - FT_DivFix( matrix->xy, delta ); - matrix->yx = - FT_DivFix( matrix->yx, delta ); - - xx = matrix->xx; - yy = matrix->yy; - - matrix->xx = FT_DivFix( yy, delta ); - matrix->yy = FT_DivFix( xx, delta ); - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** FT_BitmapGlyph support ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - - static - FT_Error ft_bitmap_copy( FT_Memory memory, - FT_Bitmap* source, - FT_Bitmap* target ) - { - FT_Error error; - FT_Int pitch = source->pitch; - FT_ULong size; - - - *target = *source; - - if ( pitch < 0 ) - pitch = -pitch; - - size = (FT_ULong)( pitch * source->rows ); - - if ( !ALLOC( target->buffer, size ) ) - MEM_Copy( source->buffer, target->buffer, size ); - - return error; - } - - - static - FT_Error ft_bitmap_glyph_init( FT_BitmapGlyph glyph, - FT_GlyphSlot slot ) - { - FT_Error error = FT_Err_Ok; - FT_Library library = FT_GLYPH(glyph)->library; - FT_Memory memory = library->memory; - - - if ( slot->format != ft_glyph_format_bitmap ) - { - error = FT_Err_Invalid_Glyph_Format; - goto Exit; - } - - /* grab the bitmap in the slot - do lazy copying whenever possible */ - glyph->bitmap = slot->bitmap; - glyph->left = slot->bitmap_left; - glyph->top = slot->bitmap_top; - - if ( slot->flags & ft_glyph_own_bitmap ) - slot->flags &= ~ft_glyph_own_bitmap; - else - { - /* copy the bitmap into a new buffer */ - error = ft_bitmap_copy( memory, &slot->bitmap, &glyph->bitmap ); - } - - Exit: - return error; - } - - - static - FT_Error ft_bitmap_glyph_copy( FT_BitmapGlyph source, - FT_BitmapGlyph target ) - { - FT_Memory memory = source->root.library->memory; - - - target->left = source->left; - target->top = source->top; - - return ft_bitmap_copy( memory, &source->bitmap, &target->bitmap ); - } - - - static - void ft_bitmap_glyph_done( FT_BitmapGlyph glyph ) - { - FT_Memory memory = FT_GLYPH(glyph)->library->memory; - - - FREE( glyph->bitmap.buffer ); - } - - - static - void ft_bitmap_glyph_bbox( FT_BitmapGlyph glyph, - FT_BBox* cbox ) - { - cbox->xMin = glyph->left << 6; - cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 ); - cbox->yMax = glyph->top << 6; - cbox->yMin = cbox->xMax - ( glyph->bitmap.rows << 6 ); - } - - - const FT_Glyph_Class ft_bitmap_glyph_class = - { - sizeof( FT_BitmapGlyphRec ), - ft_glyph_format_bitmap, - - (FT_Glyph_Init_Func) ft_bitmap_glyph_init, - (FT_Glyph_Done_Func) ft_bitmap_glyph_done, - (FT_Glyph_Copy_Func) ft_bitmap_glyph_copy, - (FT_Glyph_Transform_Func)0, - (FT_Glyph_BBox_Func) ft_bitmap_glyph_bbox, - (FT_Glyph_Prepare_Func) 0 - }; - - - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** FT_OutlineGlyph support ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - - - static - FT_Error ft_outline_glyph_init( FT_OutlineGlyph glyph, - FT_GlyphSlot slot ) - { - FT_Error error = FT_Err_Ok; - FT_Library library = FT_GLYPH(glyph)->library; - FT_Outline* source = &slot->outline; - FT_Outline* target = &glyph->outline; - - - /* check format in glyph slot */ - if ( slot->format != ft_glyph_format_outline ) - { - error = FT_Err_Invalid_Glyph_Format; - goto Exit; - } - - /* allocate new outline */ - error = FT_Outline_New( library, source->n_points, source->n_contours, - &glyph->outline ); - if ( error ) - goto Exit; - - /* copy it */ - MEM_Copy( target->points, source->points, - source->n_points * sizeof ( FT_Vector ) ); - - MEM_Copy( target->tags, source->tags, - source->n_points * sizeof ( FT_Byte ) ); - - MEM_Copy( target->contours, source->contours, - source->n_contours * sizeof ( FT_Short ) ); - - /* copy all flags, except the `ft_outline_owner' one */ - target->flags = source->flags | ft_outline_owner; - - Exit: - return error; - } - - - static - void ft_outline_glyph_done( FT_OutlineGlyph glyph ) - { - FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline ); - } - - - static - FT_Error ft_outline_glyph_copy( FT_OutlineGlyph source, - FT_OutlineGlyph target ) - { - FT_Error error; - FT_Library library = FT_GLYPH( source )->library; - - - error = FT_Outline_New( library, source->outline.n_points, - source->outline.n_contours, &target->outline ); - if ( !error ) - FT_Outline_Copy( &source->outline, &target->outline ); - - return error; - } - - - static - void ft_outline_glyph_transform( FT_OutlineGlyph glyph, - FT_Matrix* matrix, - FT_Vector* delta ) - { - if ( matrix ) - FT_Outline_Transform( &glyph->outline, matrix ); - - if ( delta ) - FT_Outline_Translate( &glyph->outline, delta->x, delta->y ); - } - - - static - void ft_outline_glyph_bbox( FT_OutlineGlyph glyph, - FT_BBox* bbox ) - { - FT_Outline_Get_CBox( &glyph->outline, bbox ); - } - - - static - FT_Error ft_outline_glyph_prepare( FT_OutlineGlyph glyph, - FT_GlyphSlot slot ) - { - slot->format = ft_glyph_format_outline; - slot->outline = glyph->outline; - slot->outline.flags &= ~ft_outline_owner; - - return FT_Err_Ok; - } - - - const FT_Glyph_Class ft_outline_glyph_class = - { - sizeof( FT_OutlineGlyphRec ), - ft_glyph_format_outline, - - (FT_Glyph_Init_Func) ft_outline_glyph_init, - (FT_Glyph_Done_Func) ft_outline_glyph_done, - (FT_Glyph_Copy_Func) ft_outline_glyph_copy, - (FT_Glyph_Transform_Func)ft_outline_glyph_transform, - (FT_Glyph_BBox_Func) ft_outline_glyph_bbox, - (FT_Glyph_Prepare_Func) ft_outline_glyph_prepare - }; - - - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** FT_Glyph class and API ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - - static - FT_Error ft_new_glyph( FT_Library library, - const FT_Glyph_Class* clazz, - FT_Glyph* aglyph ) - { - FT_Memory memory = library->memory; - FT_Error error; - FT_Glyph glyph; - - - *aglyph = 0; - - if ( !ALLOC( glyph, clazz->glyph_size ) ) - { - glyph->library = library; - glyph->clazz = clazz; - glyph->format = clazz->glyph_format; - - *aglyph = glyph; - } - - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Glyph_Copy */ - /* */ - /* <Description> */ - /* A function used to copy a glyph image. */ - /* */ - /* <Input> */ - /* source :: A handle to the source glyph object. */ - /* */ - /* <Output> */ - /* target :: A handle to the target glyph object. 0 in case of */ - /* error. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_EXPORT_FUNC( FT_Error ) FT_Glyph_Copy( FT_Glyph source, - FT_Glyph* target ) - { - FT_Glyph copy; - FT_Error error; - const FT_Glyph_Class* clazz; - - - /* check arguments */ - if ( !target || !source || !source->clazz ) - { - error = FT_Err_Invalid_Argument; - goto Exit; - } - - *target = 0; - - clazz = source->clazz; - error = ft_new_glyph( source->library, clazz, © ); - if ( error ) - goto Exit; - - if ( clazz->glyph_copy ) - error = clazz->glyph_copy( source, copy ); - - if ( error ) - FT_Done_Glyph( copy ); - else - *target = copy; - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Glyph */ - /* */ - /* <Description> */ - /* A function used to extract a glyph image from a slot. */ - /* */ - /* <Input> */ - /* slot :: A handle to the source glyph slot. */ - /* */ - /* <Output> */ - /* aglyph :: A handle to the glyph object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_EXPORT_FUNC( FT_Error ) FT_Get_Glyph( FT_GlyphSlot slot, - FT_Glyph* aglyph ) - { - FT_Library library = slot->library; - FT_Error error; - FT_Glyph glyph; - - const FT_Glyph_Class* clazz = 0; - - - if ( !slot ) - return FT_Err_Invalid_Slot_Handle; - - if ( !aglyph ) - return FT_Err_Invalid_Argument; - - /* if it is a bitmap, that's easy :-) */ - if ( slot->format == ft_glyph_format_bitmap ) - clazz = &ft_bitmap_glyph_class; - - /* it it is an outline too */ - else if ( slot->format == ft_glyph_format_outline ) - clazz = &ft_outline_glyph_class; - - else - { - /* try to find a renderer that supports the glyph image format */ - FT_Renderer render = FT_Lookup_Renderer( library, slot->format, 0 ); - - - if ( render ) - clazz = &render->glyph_class; - } - - if ( !clazz ) - { - error = FT_Err_Invalid_Glyph_Format; - goto Exit; - } - - /* create FT_Glyph object */ - error = ft_new_glyph( library, clazz, &glyph ); - if ( error ) - goto Exit; - - /* copy advance while converting it to 16.16 format */ - glyph->advance.x = slot->advance.x << 10; - glyph->advance.y = slot->advance.y << 10; - - /* now import the image from the glyph slot */ - error = clazz->glyph_init( glyph, slot ); - - /* if an error occurred, destroy the glyph */ - if ( error ) - FT_Done_Glyph( glyph ); - else - *aglyph = glyph; - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Glyph_Transform */ - /* */ - /* <Description> */ - /* Transforms a glyph image if its format is scalable. */ - /* */ - /* <Input> */ - /* glyph :: A handle to the target glyph object. */ - /* */ - /* matrix :: A pointer to a 2x2 matrix to apply. */ - /* */ - /* delta :: A pointer to a 2d vector to apply. Coordinates are */ - /* expressed in 1/64th of a pixel. */ - /* */ - /* <Return> */ - /* FreeType error code (the glyph format is not scalable if it is */ - /* not zero). */ - /* */ - /* <Note> */ - /* The 2x2 transformation matrix is also applied to the glyph's */ - /* advance vector. */ - /* */ - FT_EXPORT_FUNC( FT_Error ) FT_Glyph_Transform( FT_Glyph glyph, - FT_Matrix* matrix, - FT_Vector* delta ) - { - const FT_Glyph_Class* clazz; - FT_Error error = FT_Err_Ok; - - - if ( !glyph || !glyph->clazz ) - error = FT_Err_Invalid_Argument; - else - { - clazz = glyph->clazz; - if ( clazz->glyph_transform ) - { - /* transform glyph image */ - clazz->glyph_transform( glyph, matrix, delta ); - - /* transform advance vector */ - if ( matrix ) - FT_Vector_Transform( &glyph->advance, matrix ); - } - else - error = FT_Err_Invalid_Glyph_Format; - } - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Glyph_Get_CBox */ - /* */ - /* <Description> */ - /* Returns the glyph image's bounding box. */ - /* */ - /* <Input> */ - /* glyph :: A handle to the source glyph object. */ - /* */ - /* mode :: A set of bit flags that indicate how to interpret the */ - /* returned bounding box values. */ - /* */ - /* <Output> */ - /* box :: The glyph bounding box. Coordinates are expressed in */ - /* 1/64th of pixels if it is grid-fitted. */ - /* */ - /* <Note> */ - /* Coordinates are relative to the glyph origin, using the Y-upwards */ - /* convention. */ - /* */ - /* If `ft_glyph_bbox_subpixels' is set in `mode', the bbox */ - /* coordinates are returned in 26.6 pixels (i.e. 1/64th of pixels). */ - /* Otherwise, coordinates are expressed in integer pixels. */ - /* */ - /* Note that the maximum coordinates are exclusive, which means that */ - /* one can compute the width and height of the glyph image (be it in */ - /* integer or 26.6 pixels) as: */ - /* */ - /* width = bbox.xMax - bbox.xMin; */ - /* height = bbox.yMax - bbox.yMin; */ - /* */ - /* Note also that for 26.6 coordinates, if the */ - /* `ft_glyph_bbox_gridfit' flag is set in `mode;, the coordinates */ - /* will also be grid-fitted, which corresponds to: */ - /* */ - /* bbox.xMin = FLOOR(bbox.xMin); */ - /* bbox.yMin = FLOOR(bbox.yMin); */ - /* bbox.xMax = CEILING(bbox.xMax); */ - /* bbox.yMax = CEILING(bbox.yMax); */ - /* */ - /* The default value (0) for `bbox_mode' is `ft_glyph_bbox_pixels'. */ - /* */ - FT_EXPORT_FUNC( void ) FT_Glyph_Get_CBox( FT_Glyph glyph, - FT_UInt bbox_mode, - FT_BBox* cbox ) - { - const FT_Glyph_Class* clazz; - FT_Error error = FT_Err_Ok; - - - if ( !cbox || !glyph || !glyph->clazz ) - error = FT_Err_Invalid_Argument; - else - { - clazz = glyph->clazz; - if ( !clazz->glyph_bbox ) - error = FT_Err_Invalid_Glyph_Format; - else - { - /* retrieve bbox in 26.6 coordinates */ - clazz->glyph_bbox( glyph, cbox ); - - /* perform grid fitting if needed */ - if ( bbox_mode & ft_glyph_bbox_gridfit ) - { - cbox->xMin &= -64; - cbox->yMin &= -64; - cbox->xMax = ( cbox->xMax + 63 ) & -64; - cbox->yMax = ( cbox->yMax + 63 ) & -64; - } - - /* convert to integer pixels if needed */ - if ( !( bbox_mode & ft_glyph_bbox_subpixels ) ) - { - cbox->xMin >>= 6; - cbox->yMin >>= 6; - cbox->xMax >>= 6; - cbox->yMax >>= 6; - } - } - } - return; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Glyph_To_Bitmap */ - /* */ - /* <Description> */ - /* Converts a given glyph object to a bitmap glyph object. */ - /* */ - /* <InOut> */ - /* glyph :: A pointer to a handle to the target glyph. */ - /* */ - /* <Input> */ - /* render_mode :: A set of bit flags that describe how the data is */ - /* */ - /* */ - /* origin :: A pointer to a vector used to translate the glyph */ - /* image before rendering. Can be 0 (if no */ - /* translation). The origin is expressed in */ - /* 26.6 pixels. */ - /* */ - /* destroy :: A boolean that indicates that the original glyph */ - /* image should be destroyed by this function. It is */ - /* never destroyed in case of error. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <Note> */ - /* The glyph image is translated with the `origin' vector before */ - /* rendering. In case of error, it it translated back to its */ - /* original position and the glyph is left untouched. */ - /* */ - /* The first parameter is a pointer to a FT_Glyph handle, that will */ - /* be replaced by this function. Typically, you would use (omitting */ - /* error handling): */ - /* */ - /* */ - /* { */ - /* FT_Glyph glyph; */ - /* FT_BitmapGlyph glyph_bitmap; */ - /* */ - /* */ - /* // load glyph */ - /* error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT ); */ - /* */ - /* // extract glyph image */ - /* error = FT_Get_Glyph( face->glyph, &glyph ); */ - /* */ - /* // convert to a bitmap (default render mode + destroy old) */ - /* if ( glyph->format != ft_glyph_format_bitmap ) */ - /* { */ - /* error = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_default, */ - /* 0, 1 ); */ - /* if ( error ) // glyph unchanged */ - /* ... */ - /* } */ - /* */ - /* // access bitmap content by typecasting */ - /* glyph_bitmap = (FT_BitmapGlyph)glyph; */ - /* */ - /* // do funny stuff with it, like blitting/drawing */ - /* ... */ - /* */ - /* // discard glyph image (bitmap or not) */ - /* FT_Done_Glyph( glyph ); */ - /* } */ - /* */ - /* */ - /* This function will always fail if the glyph's format isn't */ - /* scalable. */ - /* */ - FT_EXPORT_FUNC( FT_Error ) FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, - FT_ULong render_mode, - FT_Vector* origin, - FT_Bool destroy ) - { - FT_GlyphSlotRec dummy; - FT_Error error; - FT_Glyph glyph; - FT_BitmapGlyph bitmap; - - const FT_Glyph_Class* clazz; - - - /* check argument */ - if ( !the_glyph ) - goto Bad; - - /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */ - /* then calling FT_Render_Glyph_Internal() */ - - glyph = *the_glyph; - if ( !glyph ) - goto Bad; - - clazz = glyph->clazz; - if ( !clazz || !clazz->glyph_prepare ) - goto Bad; - - MEM_Set( &dummy, 0, sizeof ( dummy ) ); - dummy.library = glyph->library; - dummy.format = clazz->glyph_format; - - /* if `origin' is set, translate the glyph image */ - if ( origin ) - FT_Glyph_Transform( glyph, 0, origin ); - - /* create result bitmap glyph */ - error = ft_new_glyph( glyph->library, &ft_bitmap_glyph_class, - (FT_Glyph*)&bitmap ); - if ( error ) - goto Exit; - - /* prepare dummy slot for rendering */ - error = clazz->glyph_prepare( glyph, &dummy ) || - FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode ); - - if ( !destroy && origin ) - { - FT_Vector v; - - - v.x = -origin->x; - v.y = -origin->y; - FT_Glyph_Transform( glyph, 0, &v ); - } - - /* in case of succes, copy the bitmap to the glyph bitmap */ - if ( !error ) - { - error = ft_bitmap_glyph_init( bitmap, &dummy ); - if ( error ) - { - /* this should never happen, but let's be safe */ - FT_Done_Glyph( FT_GLYPH( bitmap ) ); - goto Exit; - } - - if ( destroy ) - FT_Done_Glyph( glyph ); - - *the_glyph = FT_GLYPH( bitmap ); - } - - Exit: - return error; - - Bad: - error = FT_Err_Invalid_Argument; - goto Exit; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Done_Glyph */ - /* */ - /* <Description> */ - /* Destroys a given glyph. */ - /* */ - /* <Input> */ - /* glyph :: A handle to the target glyph object. */ - /* */ - FT_EXPORT_FUNC( void ) FT_Done_Glyph( FT_Glyph glyph ) - { - if ( glyph ) - { - FT_Memory memory = glyph->library->memory; - const FT_Glyph_Class* clazz = glyph->clazz; - - - if ( clazz->glyph_done ) - clazz->glyph_done( glyph ); - - FREE( glyph ); - } - } - - -#if 0 - - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - - /* Compute the norm of a vector */ - -#ifdef FT_CONFIG_OPTION_OLD_CALCS - - static - FT_Pos ft_norm( FT_Vector* vec ) - { - FT_Int64 t1, t2; - - - MUL_64( vec->x, vec->x, t1 ); - MUL_64( vec->y, vec->y, t2 ); - ADD_64( t1, t2, t1 ); - - return (FT_Pos)SQRT_64( t1 ); - } - -#else /* FT_CONFIG_OPTION_OLD_CALCS */ - - static - FT_Pos ft_norm( FT_Vector* vec ) - { - FT_F26Dot6 u, v, d; - FT_Int shift; - FT_ULong H, L, L2, hi, lo, med; - - - u = vec->x; if ( u < 0 ) u = -u; - v = vec->y; if ( v < 0 ) v = -v; - - if ( u < v ) - { - d = u; - u = v; - v = d; - } - - /* check that we are not trying to normalize zero! */ - if ( u == 0 ) - return 0; - - /* compute (u*u + v*v) on 64 bits with two 32-bit registers [H:L] */ - hi = (FT_ULong)u >> 16; - lo = (FT_ULong)u & 0xFFFF; - med = hi * lo; - - H = hi * hi + ( med >> 15 ); - med <<= 17; - L = lo * lo + med; - if ( L < med ) - H++; - - hi = (FT_ULong)v >> 16; - lo = (FT_ULong)v & 0xFFFF; - med = hi * lo; - - H += hi * hi + ( med >> 15 ); - med <<= 17; - L2 = lo * lo + med; - if ( L2 < med ) - H++; - - L += L2; - if ( L < L2 ) - H++; - - /* if the value is smaller than 32 bits */ - shift = 0; - if ( H == 0 ) - { - while ( ( L & 0xC0000000UL ) == 0 ) - { - L <<= 2; - shift++; - } - return ( FT_Sqrt32( L ) >> shift ); - } - else - { - while ( H ) - { - L = ( L >> 2 ) | ( H << 30 ); - H >>= 2; - shift++; - } - return ( FT_Sqrt32( L ) << shift ); - } - } - -#endif /* FT_CONFIG_OPTION_OLD_CALCS */ - - - static - int ft_test_extrema( FT_Outline* outline, - int n ) - { - FT_Vector *prev, *cur, *next; - FT_Pos product; - FT_Int first, last; - - - /* we need to compute the `previous' and `next' point */ - /* for these extrema. */ - cur = outline->points + n; - prev = cur - 1; - next = cur + 1; - - first = 0; - for ( c = 0; c < outline->n_contours; c++ ) - { - last = outline->contours[c]; - - if ( n == first ) - prev = outline->points + last; - - if ( n == last ) - next = outline->points + first; - - first = last + 1; - } - - product = FT_MulDiv( cur->x - prev->x, /* in.x */ - next->y - cur->y, /* out.y */ - 0x40 ) - - - FT_MulDiv( cur->y - prev->y, /* in.y */ - next->x - cur->x, /* out.x */ - 0x40 ); - - if ( product ) - product = product > 0 ? 1 : -1; - - return product; - } - - - /* Compute the orientation of path filling. It differs between TrueType */ - /* and Type1 formats. We could use the `ft_outline_reverse_fill' flag, */ - /* but it is better to re-compute it directly (it seems that this flag */ - /* isn't correctly set for some weird composite glyphs currently). */ - /* */ - /* We do this by computing bounding box points, and computing their */ - /* curvature. */ - /* */ - /* The function returns either 1 or -1. */ - /* */ - static - int ft_get_orientation( FT_Outline* outline ) - { - FT_BBox box; - FT_BBox indices; - int n, last; - - - indices.xMin = -1; - indices.yMin = -1; - indices.xMax = -1; - indices.yMax = -1; - - box.xMin = box.yMin = 32767; - box.xMax = box.yMax = -32768; - - /* is it empty ? */ - if ( outline->n_contours < 1 ) - return 1; - - last = outline->contours[outline->n_contours - 1]; - - for ( n = 0; n <= last; n++ ) - { - FT_Pos x, y; - - - x = outline->points[n].x; - if ( x < box.xMin ) - { - box.xMin = x; - indices.xMin = n; - } - if ( x > box.xMax ) - { - box.xMax = x; - indices.xMax = n; - } - - y = outline->points[n].y; - if ( y < box.yMin ) - { - box.yMin = y; - indices.yMin = n; - } - if ( y > box.yMax ) - { - box.yMax = y; - indices.yMax = n; - } - } - - /* test orientation of the xmin */ - return ft_test_extrema( outline, indices.xMin ) || - ft_test_extrema( outline, indices.yMin ) || - ft_test_extrema( outline, indices.xMax ) || - ft_test_extrema( outline, indices.yMax ) || - 1; /* this is an empty glyph? */ - } - - - static - FT_Error ft_embolden( FT_Face original, - FT_Outline* outline, - FT_Pos* advance ) - { - FT_Vector u, v; - FT_Vector* points; - FT_Vector cur, prev, next; - FT_Pos distance; - int c, n, first, orientation; - - FT_UNUSED( advance ); - - - /* compute control distance */ - distance = FT_MulFix( original->em_size / 60, - original->size->metrics.y_scale ); - - orientation = ft_get_orientation( &original->glyph->outline ); - - points = original->glyph->outline.points; - - first = 0; - for ( c = 0; c < outline->n_contours; c++ ) - { - int last = outline->contours[c]; - - - prev = points[last]; - - for ( n = first; n <= last; n++ ) - { - FT_Pos norm, delta, d; - FT_Vector in, out; - - - cur = points[n]; - if ( n < last ) next = points[n + 1]; - else next = points[first]; - - /* compute the in and out vectors */ - in.x = cur.x - prev.x; - in.y = cur.y - prev.y; - - out.x = next.x - cur.x; - out.y = next.y - cur.y; - - /* compute U and V */ - norm = ft_norm( &in ); - u.x = orientation * FT_DivFix( in.y, norm ); - u.y = orientation * -FT_DivFix( in.x, norm ); - - norm = ft_norm( &out ); - v.x = orientation * FT_DivFix( out.y, norm ); - v.y = orientation * -FT_DivFix( out.x, norm ); - - d = distance; - - if ( ( outline->flags[n] & FT_Curve_Tag_On ) == 0 ) - d *= 2; - - /* Check discriminant for parallel vectors */ - delta = FT_MulFix( u.x, v.y ) - FT_MulFix( u.y, v.x ); - if ( delta > FT_BOLD_THRESHOLD || delta < -FT_BOLD_THRESHOLD ) - { - /* Move point -- compute A and B */ - FT_Pos x, y, A, B; - - - A = d + FT_MulFix( cur.x, u.x ) + FT_MulFix( cur.y, u.y ); - B = d + FT_MulFix( cur.x, v.x ) + FT_MulFix( cur.y, v.y ); - - x = FT_MulFix( A, v.y ) - FT_MulFix( B, u.y ); - y = FT_MulFix( B, u.x ) - FT_MulFix( A, v.x ); - - outline->points[n].x = distance + FT_DivFix( x, delta ); - outline->points[n].y = distance + FT_DivFix( y, delta ); - } - else - { - /* Vectors are nearly parallel */ - FT_Pos x, y; - - - x = distance + cur.x + FT_MulFix( d, u.x + v.x ) / 2; - y = distance + cur.y + FT_MulFix( d, u.y + v.y ) / 2; - - outline->points[n].x = x; - outline->points[n].y = y; - } - - prev = cur; - } - - first = last + 1; - } - - if ( advance ) - *advance = ( *advance + distance * 4 ) & -64; - - return 0; - } - -#endif /* 0 -- EXPERIMENTAL STUFF! */ - - -/* END */ |