diff options
author | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2015-02-02 15:02:49 +0100 |
---|---|---|
committer | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2015-02-02 15:02:49 +0100 |
commit | b16b9e4656e7199c2aec74a4c8ebc7a875d3ba73 (patch) | |
tree | 4361edef0d42d5bf5ac984ef72b4fac35426eae7 /nx-X11/extras/freetype2/src/autofit/aflatin.c | |
parent | 0d5a83e986f39982c0924652a3662e60b1f23162 (diff) | |
download | nx-libs-b16b9e4656e7199c2aec74a4c8ebc7a875d3ba73.tar.gz nx-libs-b16b9e4656e7199c2aec74a4c8ebc7a875d3ba73.tar.bz2 nx-libs-b16b9e4656e7199c2aec74a4c8ebc7a875d3ba73.zip |
massive reduction of unneeded files
Diffstat (limited to 'nx-X11/extras/freetype2/src/autofit/aflatin.c')
-rw-r--r-- | nx-X11/extras/freetype2/src/autofit/aflatin.c | 1871 |
1 files changed, 0 insertions, 1871 deletions
diff --git a/nx-X11/extras/freetype2/src/autofit/aflatin.c b/nx-X11/extras/freetype2/src/autofit/aflatin.c deleted file mode 100644 index ce0f8c961..000000000 --- a/nx-X11/extras/freetype2/src/autofit/aflatin.c +++ /dev/null @@ -1,1871 +0,0 @@ -#include "aflatin.h" - - /***************************************************************************/ - /***************************************************************************/ - /***** *****/ - /***** L A T I N G L O B A L M E T R I C S *****/ - /***** *****/ - /***************************************************************************/ - /***************************************************************************/ - - static void - af_latin_metrics_init_widths( AF_LatinMetrics metrics, - FT_Face face ) - { - /* scan the array of segments in each direction */ - AF_GlyphHintsRec hints[1]; - - af_glyph_hints_init( hints, face->memory ); - - metrics->axis[ AF_DIMENSION_HORZ ].width_count = 0; - metrics->axis[ AF_DIMENSION_VERT ].width_count = 0; - - /* For now, compute the standard width and height from the `o' */ - { - FT_Error error; - FT_UInt glyph_index; - AF_Dimension dim; - AF_ScriptMetricsRec dummy[1]; - AF_Scaler scaler = &dummy->scaler; - - glyph_index = FT_Get_Char_Index( face, 'o' ); - if ( glyph_index == 0 ) - goto Exit; - - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); - if ( error || face->glyph->outline.n_points <= 0 ) - goto Exit; - - FT_ZERO( dummy ); - - scaler->x_scale = scaler->y_scale = 0x10000L; - scaler->x_delta = scaler->y_delta = 0; - scaler->face = face; - scaler->render_mode = 0; - scaler->flags = 0; - - af_glyph_hints_rescale( hints, dummy ); - - error = af_glyph_hints_reload( hints, &face->glyph->outline ); - if ( error ) - goto Exit; - - for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) - { - AF_LatinAxis axis = & metrics->axis[ dim ]; - AF_AxisHints axhints = & hints->axis[ dim ]; - AF_Segment seg, limit, link; - FT_UInt num_widths = 0; - FT_Pos edge_distance_threshold = 32000; - - af_latin_hints_compute_segments( hints, dim ); - af_latin_hints_link_segments ( hints, dim ); - - seg = axhints->segments; - limit = seg + axhints->num_segments; - - for ( ; seg < limit; seg++ ) - { - link = seg->link; - /* we only consider stem segments there! */ - if ( link && link->link == seg && link > seg ) - { - FT_Pos dist; - - - dist = seg->pos - link->pos; - if ( dist < 0 ) - dist = -dist; - - if ( num_widths < AF_LATIN_MAX_WIDTHS ) - axis->widths[ num_widths++ ].org = dist; - } - } - - af_sort_widths( num_widths, axis->widths ); - axis->width_count = num_widths; - - /* we will now try to find the smallest width */ - if ( num_widths > 0 && axis->widths[0].org < edge_distance_threshold ) - edge_distance_threshold = axis->widths[0].org; - - /* Now, compute the edge distance threshold as a fraction of the */ - /* smallest width in the font. Set it in `hinter->glyph' too! */ - if ( edge_distance_threshold == 32000 ) - edge_distance_threshold = 50; - - /* let's try 20% */ - axis->edge_distance_threshold = edge_distance_threshold / 5; - } - } - - Exit: - af_glyph_hints_done( hints ); - } - - - -#define AF_LATIN_MAX_TEST_CHARACTERS 12 - - - static const char* const af_latin_blue_chars[ AF_LATIN_MAX_BLUES ] = - { - "THEZOCQS", - "HEZLOCUS", - "fijkdbh", - "xzroesc", - "xzroesc", - "pqgjy" - }; - - - static void - af_latin_metrics_init_blues( AF_LatinMetrics metrics, - FT_Face face ) - { - FT_Pos flats [ AF_LATIN_MAX_TEST_CHARACTERS ]; - FT_Pos rounds[ AF_LATIN_MAX_TEST_CHARACTERS ]; - FT_Int num_flats; - FT_Int num_rounds; - FT_Int bb; - AF_LatinBlue blue; - FT_Error error; - AF_LatinAxis axis = &metrics->axis[ AF_DIMENSION_VERT ]; - FT_GlyphSlot glyph = face->glyph; - - /* we compute the blues simply by loading each character from the */ - /* 'af_latin_blue_chars[blues]' string, then compute its top-most or */ - /* bottom-most points (depending on `AF_IS_TOP_BLUE') */ - - AF_LOG(( "blue zones computation\n" )); - AF_LOG(( "------------------------------------------------\n" )); - - for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ ) - { - const char* p = af_latin_blue_chars[bb]; - const char* limit = p + AF_LATIN_MAX_TEST_CHARACTERS; - FT_Pos* blue_ref; - FT_Pos* blue_shoot; - - AF_LOG(( "blue %3d: ", bb )); - - num_flats = 0; - num_rounds = 0; - - for ( ; p < limit && *p; p++ ) - { - FT_UInt glyph_index; - FT_Vector* extremum; - FT_Vector* points; - FT_Vector* point_limit; - FT_Vector* point; - FT_Bool round; - - - AF_LOG(( "'%c'", *p )); - - /* load the character in the face -- skip unknown or empty ones */ - glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p ); - if ( glyph_index == 0 ) - continue; - - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); - if ( error || glyph->outline.n_points <= 0 ) - continue; - - /* now compute min or max point indices and coordinates */ - points = glyph->outline.points; - point_limit = points + glyph->outline.n_points; - point = points; - extremum = point; - point++; - - if ( AF_LATIN_IS_TOP_BLUE( bb ) ) - { - for ( ; point < point_limit; point++ ) - if ( point->y > extremum->y ) - extremum = point; - } - else - { - for ( ; point < point_limit; point++ ) - if ( point->y < extremum->y ) - extremum = point; - } - - AF_LOG(( "%5d", (int)extremum->y )); - - /* now, check whether the point belongs to a straight or round */ - /* segment; we first need to find in which contour the extremum */ - /* lies, then see its previous and next points */ - { - FT_Int idx = (FT_Int)( extremum - points ); - FT_Int n; - FT_Int first, last, prev, next, end; - FT_Pos dist; - - - last = -1; - first = 0; - - for ( n = 0; n < glyph->outline.n_contours; n++ ) - { - end = glyph->outline.contours[n]; - if ( end >= idx ) - { - last = end; - break; - } - first = end + 1; - } - - /* XXX: should never happen! */ - if ( last < 0 ) - continue; - - /* now look for the previous and next points that are not on the */ - /* same Y coordinate. Threshold the `closeness'... */ - - prev = idx; - next = prev; - - do - { - if ( prev > first ) - prev--; - else - prev = last; - - dist = points[prev].y - extremum->y; - if ( dist < -5 || dist > 5 ) - break; - - } while ( prev != idx ); - - do - { - if ( next < last ) - next++; - else - next = first; - - dist = points[next].y - extremum->y; - if ( dist < -5 || dist > 5 ) - break; - - } while ( next != idx ); - - /* now, set the `round' flag depending on the segment's kind */ - round = FT_BOOL( - FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_CURVE_TAG_ON || - FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_CURVE_TAG_ON ); - - AF_LOG(( "%c ", round ? 'r' : 'f' )); - } - - if ( round ) - rounds[num_rounds++] = extremum->y; - else - flats[num_flats++] = extremum->y; - } - - AF_LOG(( "\n" )); - - if ( num_flats == 0 && num_rounds == 0 ) - { - /* we couldn't find a single glyph to compute this blue zone, - * we will simply ignore it then - */ - AF_LOG(( "empty !!\n" )); - continue; - } - - /* we have computed the contents of the `rounds' and `flats' tables, */ - /* now determine the reference and overshoot position of the blue -- */ - /* we simply take the median value after a simple sort */ - af_sort_pos( num_rounds, rounds ); - af_sort_pos( num_flats, flats ); - - blue = & axis->blues[ axis->blue_count ]; - blue_ref = & blue->ref.org; - blue_shoot = & blue->shoot.org; - - axis->blue_count ++; - - if ( num_flats == 0 ) - { - *blue_ref = - *blue_shoot = rounds[num_rounds / 2]; - } - else if ( num_rounds == 0 ) - { - *blue_ref = - *blue_shoot = flats[num_flats / 2]; - } - else - { - *blue_ref = flats[num_flats / 2]; - *blue_shoot = rounds[num_rounds / 2]; - } - - /* there are sometimes problems: if the overshoot position of top */ - /* zones is under its reference position, or the opposite for bottom */ - /* zones. We must thus check everything there and correct the errors */ - if ( *blue_shoot != *blue_ref ) - { - FT_Pos ref = *blue_ref; - FT_Pos shoot = *blue_shoot; - FT_Bool over_ref = FT_BOOL( shoot > ref ); - - - if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref ) - *blue_shoot = *blue_ref = ( shoot + ref ) / 2; - } - - blue->flags = 0; - if ( AF_LATIN_IS_TOP_BLUE(bb) ) - blue->flags |= AF_LATIN_BLUE_TOP; - - /* the following flags is used later to adjust the y and x scales - * in order to optimize the pixel grid alignment of the top of small - * letters. - */ - if ( bb == AF_LATIN_BLUE_SMALL_TOP ) - blue->flags |= AF_LATIN_BLUE_ADJUSTMENT; - - AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot )); - } - - return; - } - - - FT_LOCAL_DEF( FT_Error ) - af_latin_metrics_init( AF_LatinMetrics metrics, - FT_Face face ) - { - FT_Error error; - FT_CharMap oldmap = face->charmap; - - /* do we have a Unicode charmap in there? */ - error = FT_Select_Charmap( face, FT_ENCODING_UNICODE ); - if ( error ) goto Exit; - - metrics->units_per_em = face->units_per_EM; - - af_latin_metrics_init_widths( metrics, face ); - af_latin_metrics_init_blues( metrics, face ); - - Exit: - FT_Set_Charmap( face, oldmap ); - return error; - } - - - static void - af_latin_metrics_scale_dim( AF_LatinMetrics metrics, - AF_Scaler scaler, - AF_Dimension dim ) - { - FT_Fixed scale; - FT_Pos delta; - AF_LatinAxis axis; - FT_UInt nn; - - if ( dim == AF_DIMENSION_HORZ ) - { - scale = scaler->x_scale; - delta = scaler->x_delta; - } - else - { - scale = scaler->y_scale; - delta = scaler->y_delta; - } - - axis = & metrics->axis[ dim ]; - - if ( axis->org_scale == scale && axis->org_delta == delta ) - return; - - axis->org_scale = scale; - axis->org_delta = delta; - - /* correct X and Y scale to optimize the alignment of the top of small - * letters to the pixel grid - */ - { - AF_LatinAxis axis = &metrics->axis[ AF_DIMENSION_VERT ]; - AF_LatinBlue blue = NULL; - FT_UInt nn; - - for ( nn = 0; nn < axis->blue_count; nn++ ) - { - if ( axis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT ) - { - blue = &axis->blues[nn]; - break; - } - } - - if ( blue ) - { - FT_Pos scaled = FT_MulFix( blue->shoot.org, scaler->y_scale ); - FT_Pos fitted = FT_PIX_ROUND( scaled ); - - - if ( scaled != fitted ) - { - if ( dim == AF_DIMENSION_HORZ ) - { - if ( fitted < scaled ) - scale -= scale/50; /* x_scale = x_scale*0.98 */ - } - else - { - scale = FT_MulDiv( scale, fitted, scaled ); - } - } - } - } - - axis->scale = scale; - axis->delta = delta; - - if ( dim == AF_DIMENSION_HORZ ) - { - metrics->root.scaler.x_scale = scale; - metrics->root.scaler.x_delta = delta; - } - else - { - metrics->root.scaler.y_scale = scale; - metrics->root.scaler.y_delta = delta; - } - - /* scale the standard widths - */ - for ( nn = 0; nn < axis->width_count; nn++ ) - { - AF_Width width = axis->widths + nn; - - width->cur = FT_MulFix( width->org, scale ); - width->fit = width->cur; - } - - if ( dim == AF_DIMENSION_VERT ) - { - /* scale the blue zones - */ - for ( nn = 0; nn < axis->blue_count; nn++ ) - { - AF_LatinBlue blue = & axis->blues[nn]; - FT_Pos dist; - - blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta; - blue->ref.fit = blue->ref.cur; - blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta; - blue->shoot.fit = blue->shoot.cur; - blue->flags &= ~AF_LATIN_BLUE_ACTIVE; - - /* a blue zone is only active when it is less than 3/4 pixels tall - */ - dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale ); - if ( dist <= 48 && dist >= -48 ) - { - FT_Pos delta, delta2; - - delta = blue->shoot.org - blue->ref.org; - delta2 = delta; - if ( delta < 0 ) - delta2 = -delta2; - - delta2 = FT_MulFix( delta2, scale ); - - if ( delta2 < 32 ) - delta2 = 0; - else if ( delta2 < 64 ) - delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 ); - else - delta2 = FT_PIX_ROUND( delta2 ); - - if ( delta < 0 ) - delta2 = -delta2; - - blue->ref.fit = FT_PIX_ROUND( blue->ref.cur ); - blue->shoot.fit = blue->ref.fit + delta2; - - blue->flags |= AF_LATIN_BLUE_ACTIVE; - } - } - } - } - - - FT_LOCAL_DEF( void ) - af_latin_metrics_scale( AF_LatinMetrics metrics, - AF_Scaler scaler ) - { - if ( AF_SCALER_EQUAL_SCALES( scaler, &metrics->root.scaler ) ) - return; - - af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ ); - af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT ); - } - - - /***************************************************************************/ - /***************************************************************************/ - /***** *****/ - /***** L A T I N G L Y P H A N A L Y S I S *****/ - /***** *****/ - /***************************************************************************/ - /***************************************************************************/ - - FT_LOCAL_DEF( void ) - af_latin_hints_compute_segments( AF_GlyphHints hints, - AF_Dimension dim ) - { - AF_AxisHints axis = &hints->axis[dim]; - AF_Segment segments = axis->segments; - AF_Segment segment = segments; - FT_Int num_segments = 0; - AF_Point* contour = hints->contours; - AF_Point* contour_limit = contour + hints->num_contours; - AF_Direction major_dir, segment_dir; - -#ifdef AF_HINT_METRICS - AF_Point min_point = 0; - AF_Point max_point = 0; - FT_Pos min_coord = 32000; - FT_Pos max_coord = -32000; -#endif - - major_dir = FT_ABS( axis->major_dir ); - segment_dir = major_dir; - - /* set up (u,v) in each point */ - if ( dim == AF_DIMENSION_HORZ ) - { - AF_Point point = hints->points; - AF_Point limit = point + hints->num_points; - - for ( ; point < limit; point++ ) - { - point->u = point->fx; - point->v = point->fy; - } - } - else - { - AF_Point point = hints->points; - AF_Point limit = point + hints->num_points; - - for ( ; point < limit; point++ ) - { - point->u = point->fy; - point->v = point->fx; - } - } - - - /* do each contour separately */ - for ( ; contour < contour_limit; contour++ ) - { - AF_Point point = contour[0]; - AF_Point last = point->prev; - int on_edge = 0; - FT_Pos min_pos = 32000; /* minimum segment pos != min_coord */ - FT_Pos max_pos = -32000; /* maximum segment pos != max_coord */ - FT_Bool passed; - - -#ifdef AF_HINT_METRICS - if ( point->u < min_coord ) - { - min_coord = point->u; - min_point = point; - } - if ( point->u > max_coord ) - { - max_coord = point->u; - max_point = point; - } -#endif - - if ( point == last ) /* skip singletons -- just in case */ - continue; - - if ( FT_ABS( last->out_dir ) == major_dir && - FT_ABS( point->out_dir ) == major_dir ) - { - /* we are already on an edge, try to locate its start */ - last = point; - - for (;;) - { - point = point->prev; - if ( FT_ABS( point->out_dir ) != major_dir ) - { - point = point->next; - break; - } - if ( point == last ) - break; - } - } - - last = point; - passed = 0; - - for (;;) - { - FT_Pos u, v; - - - if ( on_edge ) - { - u = point->u; - if ( u < min_pos ) - min_pos = u; - if ( u > max_pos ) - max_pos = u; - - if ( point->out_dir != segment_dir || point == last ) - { - /* we are just leaving an edge; record a new segment! */ - segment->last = point; - segment->pos = ( min_pos + max_pos ) >> 1; - - /* a segment is round if either its first or last point */ - /* is a control point */ - if ( ( segment->first->flags | point->flags ) & - AF_FLAG_CONTROL ) - segment->flags |= AF_EDGE_ROUND; - - /* compute segment size */ - min_pos = max_pos = point->v; - - v = segment->first->v; - if ( v < min_pos ) - min_pos = v; - if ( v > max_pos ) - max_pos = v; - - segment->min_coord = min_pos; - segment->max_coord = max_pos; - - on_edge = 0; - num_segments++; - segment++; - /* fallthrough */ - } - } - - /* now exit if we are at the start/end point */ - if ( point == last ) - { - if ( passed ) - break; - passed = 1; - } - - if ( !on_edge && FT_ABS( point->out_dir ) == major_dir ) - { - /* this is the start of a new segment! */ - segment_dir = point->out_dir; - - /* clear all segment fields */ - FT_ZERO( segment ); - - segment->dir = segment_dir; - segment->flags = AF_EDGE_NORMAL; - min_pos = max_pos = point->u; - segment->first = point; - segment->last = point; - segment->contour = contour; - segment->score = 32000; - segment->link = NULL; - on_edge = 1; - -#ifdef AF_HINT_METRICS - if ( point == max_point ) - max_point = 0; - - if ( point == min_point ) - min_point = 0; -#endif - } - - point = point->next; - } - - } /* contours */ - -#ifdef AF_HINT_METRICS - /* we need to ensure that there are edges on the left-most and */ - /* right-most points of the glyph in order to hint the metrics; */ - /* we do this by inserting fake segments when needed */ - if ( dim == AF_DIMENSION_HORZ ) - { - AF_Point point = hints->points; - AF_Point point_limit = point + hints->num_points; - - FT_Pos min_pos = 32000; - FT_Pos max_pos = -32000; - - - min_point = 0; - max_point = 0; - - /* compute minimum and maximum points */ - for ( ; point < point_limit; point++ ) - { - FT_Pos x = point->fx; - - - if ( x < min_pos ) - { - min_pos = x; - min_point = point; - } - if ( x > max_pos ) - { - max_pos = x; - max_point = point; - } - } - - /* insert minimum segment */ - if ( min_point ) - { - /* clear all segment fields */ - FT_ZERO( segment ); - - segment->dir = segment_dir; - segment->flags = AF_EDGE_NORMAL; - segment->first = min_point; - segment->last = min_point; - segment->pos = min_pos; - segment->score = 32000; - segment->link = NULL; - - num_segments++; - segment++; - } - - /* insert maximum segment */ - if ( max_point ) - { - /* clear all segment fields */ - FT_ZERO( segment ); - - segment->dir = segment_dir; - segment->flags = AF_EDGE_NORMAL; - segment->first = max_point; - segment->last = max_point; - segment->pos = max_pos; - segment->score = 32000; - segment->link = NULL; - - num_segments++; - segment++; - } - } -#endif /* AF_HINT_METRICS */ - - axis->num_segments = num_segments; - } - - - FT_LOCAL_DEF( void ) - af_latin_hints_link_segments( AF_GlyphHints hints, - AF_Dimension dim ) - { - AF_AxisHints axis = &hints->axis[dim]; - AF_Segment segments = axis->segments; - AF_Segment segment_limit = segments + axis->num_segments; - AF_Direction major_dir = axis->major_dir; - AF_Segment seg1, seg2; - - /* now compare each segment to the others */ - for ( seg1 = segments; seg1 < segment_limit; seg1++ ) - { - /* the fake segments are introduced to hint the metrics -- */ - /* we must never link them to anything */ - if ( seg1->first == seg1->last || seg1->dir != major_dir ) - continue; - - for ( seg2 = segments; seg2 < segment_limit; seg2++ ) - if ( seg2 != seg1 && seg1->dir + seg2->dir == 0 ) - { - FT_Pos pos1 = seg1->pos; - FT_Pos pos2 = seg2->pos; - FT_Pos dist = pos2 - pos1; - - - if ( dist < 0 ) - continue; - - { - FT_Pos min = seg1->min_coord; - FT_Pos max = seg1->max_coord; - FT_Pos len, score; - - - if ( min < seg2->min_coord ) - min = seg2->min_coord; - - if ( max > seg2->max_coord ) - max = seg2->max_coord; - - len = max - min; - if ( len >= 8 ) - { - score = dist + 3000 / len; - - if ( score < seg1->score ) - { - seg1->score = score; - seg1->link = seg2; - } - - if ( score < seg2->score ) - { - seg2->score = score; - seg2->link = seg1; - } - } - } - } - } - - /* now, compute the `serif' segments */ - for ( seg1 = segments; seg1 < segment_limit; seg1++ ) - { - seg2 = seg1->link; - - if ( seg2 ) - { - seg2->num_linked++; - if ( seg2->link != seg1 ) - { - seg1->link = 0; - seg1->serif = seg2->link; - } - } - } - } - - - FT_LOCAL_DEF( void ) - af_latin_hints_compute_edges( AF_GlyphHints hints, - AF_Dimension dim ) - { - AF_AxisHints axis = &hints->axis[dim]; - AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim]; - AF_Edge edges = axis->edges; - AF_Edge edge, edge_limit; - - AF_Segment segments = axis->segments; - AF_Segment segment_limit = segments + axis->num_segments; - AF_Segment seg; - - AF_Direction up_dir; - FT_Fixed scale; - FT_Pos edge_distance_threshold; - - - scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale - : hints->y_scale; - - up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP - : AF_DIR_RIGHT; - - /*********************************************************************/ - /* */ - /* We will begin by generating a sorted table of edges for the */ - /* current direction. To do so, we simply scan each segment and try */ - /* to find an edge in our table that corresponds to its position. */ - /* */ - /* If no edge is found, we create and insert a new edge in the */ - /* sorted table. Otherwise, we simply add the segment to the edge's */ - /* list which will be processed in the second step to compute the */ - /* edge's properties. */ - /* */ - /* Note that the edges table is sorted along the segment/edge */ - /* position. */ - /* */ - /*********************************************************************/ - - edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold, - scale ); - if ( edge_distance_threshold > 64 / 4 ) - edge_distance_threshold = 64 / 4; - - edge_distance_threshold = FT_DivFix( edge_distance_threshold, - scale ); - - edge_limit = edges; - for ( seg = segments; seg < segment_limit; seg++ ) - { - AF_Edge found = 0; - - - /* look for an edge corresponding to the segment */ - for ( edge = edges; edge < edge_limit; edge++ ) - { - FT_Pos dist; - - - dist = seg->pos - edge->fpos; - if ( dist < 0 ) - dist = -dist; - - if ( dist < edge_distance_threshold ) - { - found = edge; - break; - } - } - - if ( !found ) - { - /* insert a new edge in the list and */ - /* sort according to the position */ - while ( edge > edges && edge[-1].fpos > seg->pos ) - { - edge[0] = edge[-1]; - edge--; - } - edge_limit++; - - /* clear all edge fields */ - FT_ZERO( edge ); - - /* add the segment to the new edge's list */ - edge->first = seg; - edge->last = seg; - edge->fpos = seg->pos; - edge->opos = edge->pos = FT_MulFix( seg->pos, scale ); - seg->edge_next = seg; - } - else - { - /* if an edge was found, simply add the segment to the edge's */ - /* list */ - seg->edge_next = edge->first; - edge->last->edge_next = seg; - edge->last = seg; - } - } - axis->num_edges = (FT_Int)( edge_limit - edges ); - - - /*********************************************************************/ - /* */ - /* Good, we will now compute each edge's properties according to */ - /* segments found on its position. Basically, these are: */ - /* */ - /* - edge's main direction */ - /* - stem edge, serif edge or both (which defaults to stem then) */ - /* - rounded edge, straight or both (which defaults to straight) */ - /* - link for edge */ - /* */ - /*********************************************************************/ - - /* first of all, set the `edge' field in each segment -- this is */ - /* required in order to compute edge links */ - - /* Note that I've tried to remove this loop, setting - * the "edge" field of each segment directly in the - * code above. For some reason, it slows down execution - * speed -- on a Sun. - */ - for ( edge = edges; edge < edge_limit; edge++ ) - { - seg = edge->first; - if ( seg ) - do - { - seg->edge = edge; - seg = seg->edge_next; - } - while ( seg != edge->first ); - } - - /* now, compute each edge properties */ - for ( edge = edges; edge < edge_limit; edge++ ) - { - FT_Int is_round = 0; /* does it contain round segments? */ - FT_Int is_straight = 0; /* does it contain straight segments? */ - FT_Pos ups = 0; /* number of upwards segments */ - FT_Pos downs = 0; /* number of downwards segments */ - - - seg = edge->first; - - do - { - FT_Bool is_serif; - - - /* check for roundness of segment */ - if ( seg->flags & AF_EDGE_ROUND ) - is_round++; - else - is_straight++; - - /* check for segment direction */ - if ( seg->dir == up_dir ) - ups += seg->max_coord-seg->min_coord; - else - downs += seg->max_coord-seg->min_coord; - - /* check for links -- if seg->serif is set, then seg->link must */ - /* be ignored */ - is_serif = (FT_Bool)( seg->serif && seg->serif->edge != edge ); - - if ( seg->link || is_serif ) - { - AF_Edge edge2; - AF_Segment seg2; - - - edge2 = edge->link; - seg2 = seg->link; - - if ( is_serif ) - { - seg2 = seg->serif; - edge2 = edge->serif; - } - - if ( edge2 ) - { - FT_Pos edge_delta; - FT_Pos seg_delta; - - - edge_delta = edge->fpos - edge2->fpos; - if ( edge_delta < 0 ) - edge_delta = -edge_delta; - - seg_delta = seg->pos - seg2->pos; - if ( seg_delta < 0 ) - seg_delta = -seg_delta; - - if ( seg_delta < edge_delta ) - edge2 = seg2->edge; - } - else - edge2 = seg2->edge; - - if ( is_serif ) - { - edge->serif = edge2; - edge2->flags |= AF_EDGE_SERIF; - } - else - edge->link = edge2; - } - - seg = seg->edge_next; - - } while ( seg != edge->first ); - - /* set the round/straight flags */ - edge->flags = AF_EDGE_NORMAL; - - if ( is_round > 0 && is_round >= is_straight ) - edge->flags |= AF_EDGE_ROUND; - - /* set the edge's main direction */ - edge->dir = AF_DIR_NONE; - - if ( ups > downs ) - edge->dir = up_dir; - - else if ( ups < downs ) - edge->dir = -up_dir; - - else if ( ups == downs ) - edge->dir = 0; /* both up and down! */ - - /* gets rid of serifs if link is set */ - /* XXX: This gets rid of many unpleasant artefacts! */ - /* Example: the `c' in cour.pfa at size 13 */ - - if ( edge->serif && edge->link ) - edge->serif = 0; - } - } - - - FT_LOCAL_DEF( void ) - af_latin_hints_detect_features( AF_GlyphHints hints, - AF_Dimension dim ) - { - af_latin_hints_compute_segments( hints, dim ); - af_latin_hints_link_segments ( hints, dim ); - af_latin_hints_compute_edges ( hints, dim ); - } - - - FT_LOCAL_DEF( void ) - af_latin_hints_compute_blue_edges( AF_GlyphHints hints, - AF_LatinMetrics metrics ) - { - AF_AxisHints axis = &hints->axis[ AF_DIMENSION_VERT ]; - AF_Edge edge = axis->edges; - AF_Edge edge_limit = edge + axis->num_edges; - AF_LatinAxis latin = &metrics->axis[ AF_DIMENSION_VERT ]; - FT_Fixed scale = latin->scale; - - - /* compute which blue zones are active, i.e. have their scaled */ - /* size < 3/4 pixels */ - - /* for each horizontal edge search the blue zone which is closest */ - for ( ; edge < edge_limit; edge++ ) - { - FT_Int bb; - AF_Width best_blue = NULL; - FT_Pos best_dist; /* initial threshold */ - - - /* compute the initial threshold as a fraction of the EM size */ - best_dist = FT_MulFix( metrics->units_per_em / 40, scale ); - - if ( best_dist > 64 / 2 ) - best_dist = 64 / 2; - - for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ ) - { - AF_LatinBlue blue = latin->blues + bb; - FT_Bool is_top_blue, is_major_dir; - - /* skip inactive blue zones (i.e. those that are too small - */ - if ( !(blue->flags & AF_LATIN_BLUE_ACTIVE) ) - continue; - - /* if it is a top zone, check for right edges -- if it is a bottom */ - /* zone, check for left edges */ - /* */ - /* of course, that's for TrueType */ - is_top_blue = (blue->flags & AF_LATIN_BLUE_TOP) != 0; - is_major_dir = FT_BOOL( edge->dir == axis->major_dir ); - - /* if it is a top zone, the edge must be against the major */ - /* direction; if it is a bottom zone, it must be in the major */ - /* direction */ - if ( is_top_blue ^ is_major_dir ) - { - FT_Pos dist; - - - /* first of all, compare it to the reference position */ - dist = edge->fpos - blue->ref.org; - if ( dist < 0 ) - dist = -dist; - - dist = FT_MulFix( dist, scale ); - if ( dist < best_dist ) - { - best_dist = dist; - best_blue = & blue->ref; - } - - /* now, compare it to the overshoot position if the edge is */ - /* rounded, and if the edge is over the reference position of a */ - /* top zone, or under the reference position of a bottom zone */ - if ( edge->flags & AF_EDGE_ROUND && dist != 0 ) - { - FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org ); - - - if ( is_top_blue ^ is_under_ref ) - { - blue = latin->blues + bb; - dist = edge->fpos - blue->shoot.org; - if ( dist < 0 ) - dist = -dist; - - dist = FT_MulFix( dist, scale ); - if ( dist < best_dist ) - { - best_dist = dist; - best_blue = & blue->shoot; - } - } - } - } - } - - if ( best_blue ) - edge->blue_edge = best_blue; - } - } - - - static FT_Error - af_latin_hints_init( AF_GlyphHints hints, - AF_LatinMetrics metrics ) - { - FT_Render_Mode mode; - - af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics ); - - /* correct x_scale and y_scale when needed, since they may have - * been modified af_latin_scale_dim above - */ - hints->x_scale = metrics->axis[ AF_DIMENSION_HORZ ].scale; - hints->x_delta = metrics->axis[ AF_DIMENSION_HORZ ].delta; - hints->y_scale = metrics->axis[ AF_DIMENSION_VERT ].scale; - hints->y_delta = metrics->axis[ AF_DIMENSION_VERT ].delta; - - /* compute flags depending on render mode, etc... - */ - - mode = metrics->root.scaler.render_mode; - - /* we snap the width of vertical stems for the monochrome and - * horizontal LCD rendering targets only. - */ - if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD ) - hints->other_flags |= AF_LATIN_HINTS_HORZ_SNAP; - - /* we snap the width of horizontal stems for the monochrome and - * vertical LCD rendering targets only. - */ - if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V ) - hints->other_flags |= AF_LATIN_HINTS_VERT_SNAP; - - /* XXX - */ - if ( mode != FT_RENDER_MODE_LIGHT ) - hints->other_flags |= AF_LATIN_HINTS_STEM_ADJUST; - - if ( mode == FT_RENDER_MODE_MONO ) - hints->other_flags |= AF_LATIN_HINTS_MONO; - - return 0; - } - - - - /***************************************************************************/ - /***************************************************************************/ - /***** *****/ - /***** L A T I N G L Y P H G R I D - F I T T I N G *****/ - /***** *****/ - /***************************************************************************/ - /***************************************************************************/ - - /* snap a given width in scaled coordinates to one of the */ - /* current standard widths */ - static FT_Pos - af_latin_snap_width( AF_Width widths, - FT_Int count, - FT_Pos width ) - { - int n; - FT_Pos best = 64 + 32 + 2; - FT_Pos reference = width; - FT_Pos scaled; - - - for ( n = 0; n < count; n++ ) - { - FT_Pos w; - FT_Pos dist; - - - w = widths[n].cur; - dist = width - w; - if ( dist < 0 ) - dist = -dist; - if ( dist < best ) - { - best = dist; - reference = w; - } - } - - scaled = FT_PIX_ROUND( reference ); - - if ( width >= reference ) - { - if ( width < scaled + 48 ) - width = reference; - } - else - { - if ( width > scaled - 48 ) - width = reference; - } - - return width; - } - - - /* compute the snapped width of a given stem */ - - static FT_Pos - af_latin_compute_stem_width( AF_GlyphHints hints, - AF_Dimension dim, - FT_Pos width, - AF_Edge_Flags base_flags, - AF_Edge_Flags stem_flags ) - { - AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics; - AF_LatinAxis axis = & metrics->axis[ dim ]; - FT_Pos dist = width; - FT_Int sign = 0; - FT_Int vertical = AF_HINTS_DO_VERTICAL( hints ); - - - if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ) - return width; - - if ( dist < 0 ) - { - dist = -width; - sign = 1; - } - - if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) || - ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) - { - /* smooth hinting process: very lightly quantize the stem width */ - /* */ - - /* leave the widths of serifs alone */ - - if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) ) - goto Done_Width; - - else if ( ( base_flags & AF_EDGE_ROUND ) ) - { - if ( dist < 80 ) - dist = 64; - } - else if ( dist < 56 ) - dist = 56; - - if ( axis->width_count > 0 ) - { - FT_Pos delta; - - /* compare to standard width - */ - if ( axis->width_count > 0 ) - { - delta = dist - axis->widths[0].cur; - - if ( delta < 0 ) - delta = -delta; - - if ( delta < 40 ) - { - dist = axis->widths[ 0 ].cur; - if ( dist < 48 ) - dist = 48; - - goto Done_Width; - } - } - - if ( dist < 3 * 64 ) - { - delta = dist & 63; - dist &= -64; - - if ( delta < 10 ) - dist += delta; - - else if ( delta < 32 ) - dist += 10; - - else if ( delta < 54 ) - dist += 54; - - else - dist += delta; - } - else - dist = ( dist + 32 ) & ~63; - } - } - else - { - /* strong hinting process: snap the stem width to integer pixels */ - /* */ - dist = af_latin_snap_width( axis->widths, axis->width_count, dist ); - - if ( vertical ) - { - /* in the case of vertical hinting, always round */ - /* the stem heights to integer pixels */ - if ( dist >= 64 ) - dist = ( dist + 16 ) & ~63; - else - dist = 64; - } - else - { - if ( AF_LATIN_HINTS_DO_MONO( hints ) ) - { - /* monochrome horizontal hinting: snap widths to integer pixels */ - /* with a different threshold */ - if ( dist < 64 ) - dist = 64; - else - dist = ( dist + 32 ) & ~63; - } - else - { - /* for horizontal anti-aliased hinting, we adopt a more subtle */ - /* approach: we strengthen small stems, round stems whose size */ - /* is between 1 and 2 pixels to an integer, otherwise nothing */ - if ( dist < 48 ) - dist = ( dist + 64 ) >> 1; - - else if ( dist < 128 ) - dist = ( dist + 22 ) & ~63; - else - /* round otherwise to prevent color fringes in LCD mode */ - dist = ( dist + 32 ) & ~63; - } - } - } - - Done_Width: - if ( sign ) - dist = -dist; - - return dist; - } - - - - /* align one stem edge relative to the previous stem edge */ - static void - af_latin_align_linked_edge( AF_GlyphHints hints, - AF_Dimension dim, - AF_Edge base_edge, - AF_Edge stem_edge ) - { - FT_Pos dist = stem_edge->opos - base_edge->opos; - - FT_Pos fitted_width = af_latin_compute_stem_width( hints, - dim, - dist, - base_edge->flags, - stem_edge->flags ); - - stem_edge->pos = base_edge->pos + fitted_width; - } - - - static void - af_latin_align_serif_edge( AF_GlyphHints hints, - AF_Edge base, - AF_Edge serif ) - { - FT_UNUSED( hints ); - - serif->pos = base->pos + (serif->opos - base->opos); - } - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** E D G E H I N T I N G ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - FT_LOCAL_DEF( void ) - af_latin_hint_edges( AF_GlyphHints hints, - AF_Dimension dim ) - { - AF_AxisHints axis = & hints->axis[dim]; - AF_Edge edges = axis->edges; - AF_Edge edge_limit = edges + axis->num_edges; - FT_Int n_edges; - AF_Edge edge; - AF_Edge anchor = 0; - FT_Int has_serifs = 0; - - - /* we begin by aligning all stems relative to the blue zone */ - /* if needed -- that's only for horizontal edges */ - if ( dim == AF_DIMENSION_VERT ) - { - for ( edge = edges; edge < edge_limit; edge++ ) - { - AF_Width blue; - AF_Edge edge1, edge2; - - - if ( edge->flags & AF_EDGE_DONE ) - continue; - - blue = edge->blue_edge; - edge1 = NULL; - edge2 = edge->link; - - if ( blue ) - { - edge1 = edge; - } - else if ( edge2 && edge2->blue_edge ) - { - blue = edge2->blue_edge; - edge1 = edge2; - edge2 = edge; - } - - if ( !edge1 ) - continue; - - edge1->pos = blue->fit; - edge1->flags |= AF_EDGE_DONE; - - if ( edge2 && !edge2->blue_edge ) - { - af_latin_align_linked_edge( hints, dim, edge1, edge2 ); - edge2->flags |= AF_EDGE_DONE; - } - - if ( !anchor ) - anchor = edge; - } - } - - /* now we will align all stem edges, trying to maintain the */ - /* relative order of stems in the glyph */ - for ( edge = edges; edge < edge_limit; edge++ ) - { - AF_Edge edge2; - - - if ( edge->flags & AF_EDGE_DONE ) - continue; - - /* skip all non-stem edges */ - edge2 = edge->link; - if ( !edge2 ) - { - has_serifs++; - continue; - } - - /* now align the stem */ - - /* this should not happen, but it's better to be safe */ - if ( edge2->blue_edge || edge2 < edge ) - { - af_latin_align_linked_edge( hints, dim, edge2, edge ); - edge->flags |= AF_EDGE_DONE; - continue; - } - - if ( !anchor ) - { - FT_Pos org_len, org_center, cur_len; - FT_Pos cur_pos1, error1, error2, u_off, d_off; - - - org_len = edge2->opos - edge->opos; - cur_len = af_latin_compute_stem_width( hints, dim, org_len, - edge->flags, edge2->flags ); - if ( cur_len <= 64 ) - u_off = d_off = 32; - else - { - u_off = 38; - d_off = 26; - } - - if ( cur_len < 96 ) - { - org_center = edge->opos + ( org_len >> 1 ); - - cur_pos1 = FT_PIX_ROUND( org_center ); - - error1 = org_center - ( cur_pos1 - u_off ); - if ( error1 < 0 ) - error1 = -error1; - - error2 = org_center - ( cur_pos1 + d_off ); - if ( error2 < 0 ) - error2 = -error2; - - if ( error1 < error2 ) - cur_pos1 -= u_off; - else - cur_pos1 += d_off; - - edge->pos = cur_pos1 - cur_len / 2; - edge2->pos = cur_pos1 + cur_len / 2; - - } - else - edge->pos = FT_PIX_ROUND( edge->opos ); - - anchor = edge; - - edge->flags |= AF_EDGE_DONE; - - af_latin_align_linked_edge( hints, dim, edge, edge2 ); - } - else - { - FT_Pos org_pos, org_len, org_center, cur_len; - FT_Pos cur_pos1, cur_pos2, delta1, delta2; - - - org_pos = anchor->pos + ( edge->opos - anchor->opos ); - org_len = edge2->opos - edge->opos; - org_center = org_pos + ( org_len >> 1 ); - - cur_len = af_latin_compute_stem_width( hints, dim, org_len, - edge->flags, edge2->flags ); - - if ( cur_len < 96 ) - { - FT_Pos u_off, d_off; - - - cur_pos1 = FT_PIX_ROUND( org_center ); - - if (cur_len <= 64 ) - u_off = d_off = 32; - else - { - u_off = 38; - d_off = 26; - } - - delta1 = org_center - ( cur_pos1 - u_off ); - if ( delta1 < 0 ) - delta1 = -delta1; - - delta2 = org_center - ( cur_pos1 + d_off ); - if ( delta2 < 0 ) - delta2 = -delta2; - - if ( delta1 < delta2 ) - cur_pos1 -= u_off; - else - cur_pos1 += d_off; - - edge->pos = cur_pos1 - cur_len / 2; - edge2->pos = cur_pos1 + cur_len / 2; - } - else - { - org_pos = anchor->pos + ( edge->opos - anchor->opos ); - org_len = edge2->opos - edge->opos; - org_center = org_pos + ( org_len >> 1 ); - - cur_len = af_latin_compute_stem_width( hints, dim, org_len, - edge->flags, edge2->flags ); - - cur_pos1 = FT_PIX_ROUND( org_pos ); - delta1 = ( cur_pos1 + ( cur_len >> 1 ) - org_center ); - if ( delta1 < 0 ) - delta1 = -delta1; - - cur_pos2 = FT_PIX_ROUND( org_pos + org_len ) - cur_len; - delta2 = ( cur_pos2 + ( cur_len >> 1 ) - org_center ); - if ( delta2 < 0 ) - delta2 = -delta2; - - edge->pos = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2; - edge2->pos = edge->pos + cur_len; - } - - edge->flags |= AF_EDGE_DONE; - edge2->flags |= AF_EDGE_DONE; - - if ( edge > edges && edge->pos < edge[-1].pos ) - edge->pos = edge[-1].pos; - } - } - - /* make sure that lowercase m's maintain their symmetry */ - - /* In general, lowercase m's have six vertical edges if they are sans */ - /* serif, or twelve if they are avec serif. This implementation is */ - /* based on that assumption, and seems to work very well with most */ - /* faces. However, if for a certain face this assumption is not */ - /* true, the m is just rendered like before. In addition, any stem */ - /* correction will only be applied to symmetrical glyphs (even if the */ - /* glyph is not an m), so the potential for unwanted distortion is */ - /* relatively low. */ - - /* We don't handle horizontal edges since we can't easily assure that */ - /* the third (lowest) stem aligns with the base line; it might end up */ - /* one pixel higher or lower. */ - - n_edges = edge_limit - edges; - if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) ) - { - AF_Edge edge1, edge2, edge3; - FT_Pos dist1, dist2, span, delta; - - - if ( n_edges == 6 ) - { - edge1 = edges; - edge2 = edges + 2; - edge3 = edges + 4; - } - else - { - edge1 = edges + 1; - edge2 = edges + 5; - edge3 = edges + 9; - } - - dist1 = edge2->opos - edge1->opos; - dist2 = edge3->opos - edge2->opos; - - span = dist1 - dist2; - if ( span < 0 ) - span = -span; - - if ( span < 8 ) - { - delta = edge3->pos - ( 2 * edge2->pos - edge1->pos ); - edge3->pos -= delta; - if ( edge3->link ) - edge3->link->pos -= delta; - - /* move the serifs along with the stem */ - if ( n_edges == 12 ) - { - ( edges + 8 )->pos -= delta; - ( edges + 11 )->pos -= delta; - } - - edge3->flags |= AF_EDGE_DONE; - if ( edge3->link ) - edge3->link->flags |= AF_EDGE_DONE; - } - } - - if ( has_serifs || !anchor ) - { - /* now hint the remaining edges (serifs and single) in order - * to complete our processing - */ - for ( edge = edges; edge < edge_limit; edge++ ) - { - if ( edge->flags & AF_EDGE_DONE ) - continue; - - if ( edge->serif ) - af_latin_align_serif_edge( hints, edge->serif, edge ); - else if ( !anchor ) - { - edge->pos = FT_PIX_ROUND( edge->opos ); - anchor = edge; - } - else - edge->pos = anchor->pos + - FT_PIX_ROUND( edge->opos - anchor->opos ); - - edge->flags |= AF_EDGE_DONE; - - if ( edge > edges && edge->pos < edge[-1].pos ) - edge->pos = edge[-1].pos; - - if ( edge + 1 < edge_limit && - edge[1].flags & AF_EDGE_DONE && - edge->pos > edge[1].pos ) - edge->pos = edge[1].pos; - } - } - } - - - static FT_Error - af_latin_hints_apply( AF_GlyphHints hints, - FT_Outline* outline, - AF_LatinMetrics metrics ) - { - FT_Error error; - AF_Dimension dim; - - error = af_glyph_hints_reload( hints, outline ); - if ( error ) - goto Exit; - - /* analyze glyph outline - */ - if ( AF_HINTS_DO_HORIZONTAL(hints) ) - af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ ); - - if ( AF_HINTS_DO_VERTICAL(hints) ) - { - af_latin_hints_detect_features( hints, AF_DIMENSION_VERT ); - af_latin_hints_compute_blue_edges( hints, metrics ); - } - - /* grid-fit the outline - */ - for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) - { - if ( (dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL(hints)) || - (dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL(hints)) ) - { - af_latin_hint_edges( hints, dim ); - af_glyph_hints_align_edge_points( hints, dim ); - af_glyph_hints_align_strong_points( hints, dim ); - af_glyph_hints_align_weak_points( hints, dim ); - } - } - af_glyph_hints_save( hints, outline ); - - Exit: - return error; - } - - /***************************************************************************/ - /***************************************************************************/ - /***** *****/ - /***** L A T I N S C R I P T C L A S S *****/ - /***** *****/ - /***************************************************************************/ - /***************************************************************************/ - - static const AF_Script_UniRangeRec af_latin_uniranges[] = - { - { 32, 127 }, /* XXX: TODO: Add new Unicode ranges here !! */ - { 160, 255 }, - { 0, 0 } - }; - - - FT_LOCAL_DEF( const AF_ScriptClassRec ) af_latin_script_class = - { - AF_SCRIPT_LATIN, - af_latin_uniranges, - - sizeof( AF_LatinMetricsRec ), - (AF_Script_InitMetricsFunc) af_latin_metrics_init, - (AF_Script_ScaleMetricsFunc) af_latin_metrics_scale, - (AF_Script_DoneMetricsFunc) NULL, - - (AF_Script_InitHintsFunc) af_latin_hints_init, - (AF_Script_ApplyHintsFunc) af_latin_hints_apply - }; - |