?? ahglyph.c
字號:
/***************************************************************************//* *//* ahglyph.c *//* *//* Routines used to load and analyze a given glyph before hinting *//* (body). *//* *//* Copyright 2000-2001, 2002 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; /* 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 a given bbox extrema */ static int ah_test_extrema( FT_Outline* outline, int n ) { FT_Vector *prev, *cur, *next; FT_Pos product; FT_Int first, last, c; /* 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 ? 2 : 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 ah_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 = 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 xmin */ n = ah_test_extrema( outline, indices.xMin ); if ( n ) goto Exit; n = ah_test_extrema( outline, indices.yMin ); if ( n ) goto Exit; n = ah_test_extrema( outline, indices.xMax ); if ( n ) goto Exit; n = ah_test_extrema( outline, indices.yMax ); if ( !n ) n = 1; Exit: return n; } /*************************************************************************/ /* */ /* <Function> */ /* ah_outline_new */ /* */ /* <Description> */ /* Creates a new and empty AH_Outline 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_Outline 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 content of a given AH_Outline 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_Outline */ /* object. */ /* */ FT_LOCAL_DEF( FT_Error ) ah_outline_load( AH_Outline* outline, 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, new_contours ) ) goto Exit; outline->max_contours = new_contours; } /* then, reallocate the points, segments & edges arrays if needed -- */ /* note that we reserved two additional point positions, used to */ /* hint metrics appropriately */ /* */ if ( num_points + 2 > outline->max_points ) { FT_Int news = ( num_points + 2 + 7 ) & -8; FT_Int max = outline->max_points; if ( FT_RENEW_ARRAY( outline->points, max, news ) || FT_RENEW_ARRAY( outline->horz_edges, max * 2, news * 2 ) || FT_RENEW_ARRAY( outline->horz_segments, max * 2, news * 2 ) ) goto Exit; /* readjust some pointers */ outline->vert_edges = outline->horz_edges + news; outline->vert_segments = outline->horz_segments + news; outline->max_points = news; } outline->num_points = num_points; outline->num_contours = num_contours; outline->num_hedges = 0; outline->num_vedges = 0; outline->num_hsegments = 0; outline->num_vsegments = 0; /* We can't rely on the value of `FT_Outline.flags' to know the fill */ /* direction used for a glyph, given that some fonts are broken (e.g. */ /* the Arphic ones). We thus recompute it each time we need to. */ /* */ outline->vert_major_dir = ah_dir_up; outline->horz_major_dir = ah_dir_left; if ( ah_get_orientation( source ) > 1 ) { outline->vert_major_dir = ah_dir_down; outline->horz_major_dir = ah_dir_right; } outline->x_scale = face->size->metrics.x_scale; outline->y_scale = face->size->metrics.y_scale; points = outline->points; if ( outline->num_points == 0 ) goto Exit; { /* do one thing at a time -- it is easier to understand, and */ /* the code is clearer */ AH_Point* point; AH_Point* point_limit = points + outline->num_points; /* compute coordinates */ { FT_Vector* vec = source->points; FT_Fixed x_scale = outline->x_scale; FT_Fixed y_scale = outline->y_scale; for ( point = points; point < point_limit; vec++, point++ ) { point->fx = vec->x; point->fy = vec->y; point->ox = point->x = FT_MulFix( vec->x, x_scale );
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -