📄 ahglyph.c
字号:
/***************************************************************************//* *//* ahglyph.c *//* *//* Routines used to load and analyze a given glyph before hinting *//* (body). *//* *//* Copyright 2000-2001, 2002, 2003 Catharon Productions Inc. *//* Author: David Turner *//* *//* This file is part of the Catharon Typography Project and shall only *//* be used, modified, and distributed under the terms of the Catharon *//* Open Source License that should come with this file under the name *//* `CatharonLicense.txt'. By continuing to use, modify, or distribute *//* this file you indicate that you have read the license and *//* understand and accept it fully. *//* *//* Note that this license is compatible with the FreeType license. *//* *//***************************************************************************/#include <ft2build.h>#include "ahglyph.h"#include "ahangles.h"#include "ahglobal.h"#include "aherrors.h"#ifdef AH_DEBUG#include <stdio.h> void ah_dump_edges( AH_Outline outline ) { AH_Edge edges; AH_Edge edge_limit; AH_Segment segments; FT_Int dimension; edges = outline->horz_edges; edge_limit = edges + outline->num_hedges; segments = outline->horz_segments; for ( dimension = 1; dimension >= 0; dimension-- ) { AH_Edge edge; printf ( "Table of %s edges:\n", !dimension ? "vertical" : "horizontal" ); printf ( " [ index | pos | dir | link |" " serif | blue | opos | pos ]\n" ); for ( edge = edges; edge < edge_limit; edge++ ) { printf ( " [ %5d | %4d | %5s | %4d | %5d | %c | %5.2f | %5.2f ]\n", edge - edges, (int)edge->fpos, edge->dir == AH_DIR_UP ? "up" : ( edge->dir == AH_DIR_DOWN ? "down" : ( edge->dir == AH_DIR_LEFT ? "left" : ( edge->dir == AH_DIR_RIGHT ? "right" : "none" ) ) ), edge->link ? ( edge->link - edges ) : -1, edge->serif ? ( edge->serif - edges ) : -1, edge->blue_edge ? 'y' : 'n', edge->opos / 64.0, edge->pos / 64.0 ); } edges = outline->vert_edges; edge_limit = edges + outline->num_vedges; segments = outline->vert_segments; } } /* A function used to dump the array of linked segments */ void ah_dump_segments( AH_Outline outline ) { AH_Segment segments; AH_Segment segment_limit; AH_Point points; FT_Int dimension; points = outline->points; segments = outline->horz_segments; segment_limit = segments + outline->num_hsegments; for ( dimension = 1; dimension >= 0; dimension-- ) { AH_Segment seg; printf ( "Table of %s segments:\n", !dimension ? "vertical" : "horizontal" ); printf ( " [ index | pos | dir | link | serif |" " numl | first | start ]\n" ); for ( seg = segments; seg < segment_limit; seg++ ) { printf ( " [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n", seg - segments, (int)seg->pos, seg->dir == AH_DIR_UP ? "up" : ( seg->dir == AH_DIR_DOWN ? "down" : ( seg->dir == AH_DIR_LEFT ? "left" : ( seg->dir == AH_DIR_RIGHT ? "right" : "none" ) ) ), seg->link ? ( seg->link - segments ) : -1, seg->serif ? ( seg->serif - segments ) : -1, (int)seg->num_linked, seg->first - points, seg->last - points ); } segments = outline->vert_segments; segment_limit = segments + outline->num_vsegments; } }#endif /* AH_DEBUG */ /* compute the direction value of a given vector */ static AH_Direction ah_compute_direction( FT_Pos dx, FT_Pos dy ) { AH_Direction dir; FT_Pos ax = ABS( dx ); FT_Pos ay = ABS( dy ); dir = AH_DIR_NONE; /* atan(1/12) == 4.7 degrees */ /* test for vertical direction */ if ( ax * 12 < ay ) { dir = dy > 0 ? AH_DIR_UP : AH_DIR_DOWN; } /* test for horizontal direction */ else if ( ay * 12 < ax ) { dir = dx > 0 ? AH_DIR_RIGHT : AH_DIR_LEFT; } return dir; } /* this function is used by ah_get_orientation (see below) to test */ /* the fill direction of given bbox extremum */ static FT_Int ah_test_extremum( FT_Outline* outline, FT_Int n ) { FT_Vector *prev, *cur, *next; FT_Pos product; FT_Int first, last, c; FT_Int retval; /* we need to compute the `previous' and `next' point */ /* for this extremum; we check whether the extremum */ /* is start or end of a contour and providing */ /* appropriate values if so */ 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; } /* compute the vectorial product -- since we know that the angle */ /* is <= 180 degrees (otherwise it wouldn't be an extremum) we */ /* can determine the filling orientation if the product is */ /* either positive or negative */ 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 ); retval = 0; if ( product ) retval = product > 0 ? 2 : 1; return retval; } /* 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 2. */ /* */ static FT_Int ah_get_orientation( FT_Outline* outline ) { FT_BBox box; FT_Int indices_xMin, indices_yMin, indices_xMax, indices_yMax; FT_Int n, last; indices_xMin = -1; indices_yMin = -1; indices_xMax = -1; indices_yMax = -1; box.xMin = box.yMin = 32767L; box.xMax = box.yMax = -32768L; /* 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 extrema */ n = ah_test_extremum( outline, indices_xMin ); if ( n ) goto Exit; n = ah_test_extremum( outline, indices_yMin ); if ( n ) goto Exit; n = ah_test_extremum( outline, indices_xMax ); if ( n ) goto Exit; n = ah_test_extremum( outline, indices_yMax ); if ( !n ) n = 1; Exit: return n; } /*************************************************************************/ /* */ /* <Function> */ /* ah_outline_new */ /* */ /* <Description> */ /* Creates a new and empty AH_OutlineRec object. */ /* */ FT_LOCAL_DEF( FT_Error ) ah_outline_new( FT_Memory memory, AH_Outline* aoutline ) { FT_Error error; AH_Outline outline; if ( !FT_NEW( outline ) ) { outline->memory = memory; *aoutline = outline; } return error; } /*************************************************************************/ /* */ /* <Function> */ /* ah_outline_done */ /* */ /* <Description> */ /* Destroys a given AH_OutlineRec object. */ /* */ FT_LOCAL_DEF( void ) ah_outline_done( AH_Outline outline ) { FT_Memory memory = outline->memory; FT_FREE( outline->horz_edges ); FT_FREE( outline->horz_segments ); FT_FREE( outline->contours ); FT_FREE( outline->points ); FT_FREE( outline ); } /*************************************************************************/ /* */ /* <Function> */ /* ah_outline_save */ /* */ /* <Description> */ /* Saves the contents of a given AH_OutlineRec object into a face's */ /* glyph slot. */ /* */ FT_LOCAL_DEF( void ) ah_outline_save( AH_Outline outline, AH_Loader gloader ) { AH_Point point = outline->points; AH_Point point_limit = point + outline->num_points; FT_Vector* vec = gloader->current.outline.points; char* tag = gloader->current.outline.tags; /* we assume that the glyph loader has already been checked for storage */ for ( ; point < point_limit; point++, vec++, tag++ ) { vec->x = point->x; vec->y = point->y; if ( point->flags & AH_FLAG_CONIC ) tag[0] = FT_CURVE_TAG_CONIC; else if ( point->flags & AH_FLAG_CUBIC ) tag[0] = FT_CURVE_TAG_CUBIC; else tag[0] = FT_CURVE_TAG_ON; } } /*************************************************************************/ /* */ /* <Function> */ /* ah_outline_load */ /* */ /* <Description> */ /* Loads an unscaled outline from a glyph slot into an AH_OutlineRec */ /* object. */ /* */ FT_LOCAL_DEF( FT_Error ) ah_outline_load( AH_Outline outline, FT_Fixed x_scale, FT_Fixed y_scale, FT_Face face ) { FT_Memory memory = outline->memory; FT_Error error = AH_Err_Ok; FT_Outline* source = &face->glyph->outline; FT_Int num_points = source->n_points; FT_Int num_contours = source->n_contours; AH_Point points; /* check arguments */ if ( !face || !face->size || face->glyph->format != FT_GLYPH_FORMAT_OUTLINE ) return AH_Err_Invalid_Argument; /* first of all, reallocate the contours array if necessary */ if ( num_contours > outline->max_contours ) { FT_Int new_contours = ( num_contours + 3 ) & -4; if ( FT_RENEW_ARRAY( outline->contours, outline->max_contours,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -