af_axis_hints_new_edge( AF_AxisHints axis, FT_Int fpos, AF_Direction dir, FT_Memory memory, AF_Edge *anedge ) { FT_Error error = FT_Err_Ok; AF_Edge edge = NULL; AF_Edge edges; if ( axis->num_edges >= axis->max_edges ) { FT_Int old_max = axis->max_edges; FT_Int new_max = old_max; FT_Int big_max = (FT_Int)( FT_INT_MAX / sizeof ( *edge ) ); if ( old_max >= big_max ) { error = FT_THROW( Out_Of_Memory ); goto Exit; } new_max += ( new_max >> 2 ) + 4; if ( new_max < old_max || new_max > big_max ) new_max = big_max; if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) ) goto Exit; axis->max_edges = new_max; }
af_axis_hints_new_segment( AF_AxisHints axis, FT_Memory memory, AF_Segment *asegment ) { FT_Error error = FT_Err_Ok; AF_Segment segment = NULL; if ( axis->num_segments >= axis->max_segments ) { FT_Int old_max = axis->max_segments; FT_Int new_max = old_max; FT_Int big_max = (FT_Int)( FT_INT_MAX / sizeof ( *segment ) ); if ( old_max >= big_max ) { error = FT_THROW( Out_Of_Memory ); goto Exit; } new_max += ( new_max >> 2 ) + 4; if ( new_max < old_max || new_max > big_max ) new_max = big_max; if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) ) goto Exit; axis->max_segments = new_max; }
FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader loader, FT_UInt n_subs ) { FT_Memory memory = loader->memory; FT_Error error = FT_Err_Ok; FT_UInt new_max, old_max; FT_GlyphLoad base = &loader->base; FT_GlyphLoad current = &loader->current; new_max = base->num_subglyphs + current->num_subglyphs + n_subs; old_max = loader->max_subglyphs; if ( new_max > old_max ) { new_max = FT_PAD_CEIL( new_max, 2 ); if ( FT_RENEW_ARRAY( base->subglyphs, old_max, new_max ) ) goto Exit; loader->max_subglyphs = new_max; FT_GlyphLoader_Adjust_Subglyphs( loader ); } Exit: return error; }
/* remove a node from its cache's hash table */ static FT_Error ftc_node_hash_unlink( FTC_Node node, FTC_Cache cache ) { FT_Error error = 0; FTC_Node *pnode; FT_UInt idx, num_buckets; idx = (FT_UInt)( node->hash & cache->mask ); if ( idx < cache->p ) idx = (FT_UInt)( node->hash & ( 2 * cache->mask + 1 ) ); pnode = cache->buckets + idx; for (;;) { if ( *pnode == NULL ) { FT_ERROR(( "ftc_node_hash_unlink: unknown node!\n" )); return FT_Err_Ok; } if ( *pnode == node ) { *pnode = node->link; node->link = NULL; break; } pnode = &(*pnode)->link; } num_buckets = ( cache->p + cache->mask + 1 ); if ( ++cache->slack > (FT_Long)num_buckets * FTC_HASH_SUB_LOAD ) { FT_UInt p = cache->p; FT_UInt mask = cache->mask; FT_UInt old_index = p + mask; FTC_Node* pold; if ( old_index+1 <= FTC_HASH_INITIAL_SIZE ) goto Exit; if ( p == 0 ) { FT_Memory memory = cache->memory; cache->mask >>= 1; p = cache->mask; if ( FT_RENEW_ARRAY( cache->buckets, ( mask + 1 ) * 2, (mask+1) ) ) { FT_ERROR(( "ftc_node_hash_unlink: couldn't shunk buckets!\n" )); goto Exit; } }
af_axis_hints_new_edge( AF_AxisHints axis, FT_Int fpos, AF_Direction dir, FT_Bool top_to_bottom_hinting, FT_Memory memory, AF_Edge *anedge ) { FT_Error error = FT_Err_Ok; AF_Edge edge = NULL; AF_Edge edges; if ( axis->num_edges < AF_EDGES_EMBEDDED ) { if ( !axis->edges ) { axis->edges = axis->embedded.edges; axis->max_edges = AF_EDGES_EMBEDDED; } } else if ( axis->num_edges >= axis->max_edges ) { FT_Int old_max = axis->max_edges; FT_Int new_max = old_max; FT_Int big_max = (FT_Int)( FT_INT_MAX / sizeof ( *edge ) ); if ( old_max >= big_max ) { error = FT_THROW( Out_Of_Memory ); goto Exit; } new_max += ( new_max >> 2 ) + 4; if ( new_max < old_max || new_max > big_max ) new_max = big_max; if ( axis->edges == axis->embedded.edges ) { if ( FT_NEW_ARRAY( axis->edges, new_max ) ) goto Exit; ft_memcpy( axis->edges, axis->embedded.edges, sizeof ( axis->embedded.edges ) ); } else { if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) ) goto Exit; } axis->max_edges = new_max; }
af_axis_hints_new_segment( AF_AxisHints axis, FT_Memory memory, AF_Segment *asegment ) { FT_Error error = FT_Err_Ok; AF_Segment segment = NULL; if ( axis->num_segments < AF_SEGMENTS_EMBEDDED ) { if ( axis->segments == NULL ) { axis->segments = axis->embedded.segments; axis->max_segments = AF_SEGMENTS_EMBEDDED; } } else if ( axis->num_segments >= axis->max_segments ) { FT_Int old_max = axis->max_segments; FT_Int new_max = old_max; FT_Int big_max = (FT_Int)( FT_INT_MAX / sizeof ( *segment ) ); if ( old_max >= big_max ) { error = FT_THROW( Out_Of_Memory ); goto Exit; } new_max += ( new_max >> 2 ) + 4; if ( new_max < old_max || new_max > big_max ) new_max = big_max; if ( axis->segments == axis->embedded.segments ) { if ( FT_NEW_ARRAY( axis->segments, new_max ) ) goto Exit; ft_memcpy( axis->segments, axis->embedded.segments, sizeof ( axis->embedded.segments ) ); } else { if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) ) goto Exit; } axis->max_segments = new_max; }
/* ensure that a table can contain "count" elements */ static FT_Error ps_hint_table_ensure( PS_Hint_Table table, FT_UInt count, FT_Memory memory ) { FT_UInt old_max = table->max_hints; FT_UInt new_max = count; FT_Error error = 0; if ( new_max > old_max ) { /* try to grow the table */ new_max = FT_PAD_CEIL( new_max, 8 ); if ( !FT_RENEW_ARRAY( table->hints, old_max, new_max ) ) table->max_hints = new_max; } return error; }
pfr_extra_item_load_bitmap_info( FT_Byte* p, FT_Byte* limit, PFR_PhyFont phy_font ) { FT_Memory memory = phy_font->memory; PFR_Strike strike; FT_UInt flags0; FT_UInt n, count, size1; FT_Error error = FT_Err_Ok; PFR_CHECK( 5 ); p += 3; /* skip bctSize */ flags0 = PFR_NEXT_BYTE( p ); count = PFR_NEXT_BYTE( p ); /* re-allocate when needed */ if ( phy_font->num_strikes + count > phy_font->max_strikes ) { FT_UInt new_max = FT_PAD_CEIL( phy_font->num_strikes + count, 4 ); if ( FT_RENEW_ARRAY( phy_font->strikes, phy_font->num_strikes, new_max ) ) goto Exit; phy_font->max_strikes = new_max; } size1 = 1 + 1 + 1 + 2 + 2 + 1; if ( flags0 & PFR_STRIKE_2BYTE_XPPM ) size1++; if ( flags0 & PFR_STRIKE_2BYTE_YPPM ) size1++; if ( flags0 & PFR_STRIKE_3BYTE_SIZE ) size1++; if ( flags0 & PFR_STRIKE_3BYTE_OFFSET ) size1++; if ( flags0 & PFR_STRIKE_2BYTE_COUNT ) size1++; strike = phy_font->strikes + phy_font->num_strikes; PFR_CHECK( count * size1 ); for ( n = 0; n < count; n++, strike++ ) { strike->x_ppm = ( flags0 & PFR_STRIKE_2BYTE_XPPM ) ? PFR_NEXT_USHORT( p ) : PFR_NEXT_BYTE( p ); strike->y_ppm = ( flags0 & PFR_STRIKE_2BYTE_YPPM ) ? PFR_NEXT_USHORT( p ) : PFR_NEXT_BYTE( p ); strike->flags = PFR_NEXT_BYTE( p ); strike->bct_size = ( flags0 & PFR_STRIKE_3BYTE_SIZE ) ? PFR_NEXT_ULONG( p ) : PFR_NEXT_USHORT( p ); strike->bct_offset = ( flags0 & PFR_STRIKE_3BYTE_OFFSET ) ? PFR_NEXT_ULONG( p ) : PFR_NEXT_USHORT( p ); strike->num_bitmaps = ( flags0 & PFR_STRIKE_2BYTE_COUNT ) ? PFR_NEXT_USHORT( p ) : PFR_NEXT_BYTE( p ); } phy_font->num_strikes += count; Exit: return error; Too_Short: error = FT_THROW( Invalid_Table ); FT_ERROR(( "pfr_extra_item_load_bitmap_info:" " invalid bitmap info table\n" )); goto Exit; }
FT_GlyphLoader_CheckPoints( FT_GlyphLoader loader, FT_UInt n_points, FT_UInt n_contours ) { FT_Memory memory = loader->memory; FT_Error error = FT_Err_Ok; FT_Outline* base = &loader->base.outline; FT_Outline* current = &loader->current.outline; FT_Bool adjust = 0; FT_UInt new_max, old_max; /* check points & tags */ new_max = base->n_points + current->n_points + n_points; old_max = loader->max_points; if ( new_max > old_max ) { new_max = FT_PAD_CEIL( new_max, 8 ); if ( new_max > FT_OUTLINE_POINTS_MAX ) return FT_Err_Array_Too_Large; if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) || FT_RENEW_ARRAY( base->tags, old_max, new_max ) ) goto Exit; if ( loader->use_extra ) { if ( FT_RENEW_ARRAY( loader->base.extra_points, old_max * 2, new_max * 2 ) ) goto Exit; FT_ARRAY_MOVE( loader->base.extra_points + new_max, loader->base.extra_points + old_max, old_max ); loader->base.extra_points2 = loader->base.extra_points + new_max; } adjust = 1; loader->max_points = new_max; } /* check contours */ old_max = loader->max_contours; new_max = base->n_contours + current->n_contours + n_contours; if ( new_max > old_max ) { new_max = FT_PAD_CEIL( new_max, 4 ); if ( new_max > FT_OUTLINE_CONTOURS_MAX ) return FT_Err_Array_Too_Large; if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) ) goto Exit; adjust = 1; loader->max_contours = new_max; } if ( adjust ) FT_GlyphLoader_Adjust_Points( loader ); Exit: return 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, 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 = x_scale; outline->y_scale = 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; 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 ); point->oy = point->y = FT_MulFix( vec->y, y_scale ); point->flags = 0; } } /* compute Bezier flags */ { char* tag = source->tags; for ( point = points; point < point_limit; point++, tag++ ) { switch ( FT_CURVE_TAG( *tag ) ) { case FT_CURVE_TAG_CONIC: point->flags = AH_FLAG_CONIC; break; case FT_CURVE_TAG_CUBIC: point->flags = AH_FLAG_CUBIC; break; default: ; } } } /* compute `next' and `prev' */ { FT_Int contour_index; AH_Point prev; AH_Point first; AH_Point end; contour_index = 0; first = points; end = points + source->contours[0]; prev = end; for ( point = points; point < point_limit; point++ ) { point->prev = prev; if ( point < end ) { point->next = point + 1; prev = point; } else { point->next = first; contour_index++; if ( point + 1 < point_limit ) { end = points + source->contours[contour_index]; first = point + 1; prev = end; } } } } /* set-up the contours array */ { AH_Point* contour = outline->contours; AH_Point* contour_limit = contour + outline->num_contours; short* end = source->contours; short idx = 0; for ( ; contour < contour_limit; contour++, end++ ) { contour[0] = points + idx; idx = (short)( end[0] + 1 ); } } /* compute directions of in & out vectors */ { for ( point = points; point < point_limit; point++ ) { AH_Point prev; AH_Point next; FT_Vector ivec, ovec; prev = point->prev; ivec.x = point->fx - prev->fx; ivec.y = point->fy - prev->fy; point->in_dir = ah_compute_direction( ivec.x, ivec.y ); next = point->next; ovec.x = next->fx - point->fx; ovec.y = next->fy - point->fy; point->out_dir = ah_compute_direction( ovec.x, ovec.y ); #ifndef AH_OPTION_NO_WEAK_INTERPOLATION if ( point->flags & (AH_FLAG_CONIC | AH_FLAG_CUBIC) ) { Is_Weak_Point: point->flags |= AH_FLAG_WEAK_INTERPOLATION; } else if ( point->out_dir == point->in_dir ) { AH_Angle angle_in, angle_out, delta; if ( point->out_dir != AH_DIR_NONE ) goto Is_Weak_Point; angle_in = ah_angle( &ivec ); angle_out = ah_angle( &ovec ); delta = angle_in - angle_out; if ( delta > AH_PI ) delta = AH_2PI - delta; if ( delta < 0 ) delta = -delta; if ( delta < 2 ) goto Is_Weak_Point; } else if ( point->in_dir == -point->out_dir ) goto Is_Weak_Point; #endif } } } Exit: return error; }
/* Note that this function cannot fail. If we cannot re-size the * buckets array appropriately, we simply degrade the hash table's * performance! */ static void ftc_cache_resize( FTC_Cache cache ) { for (;;) { FTC_Node node, *pnode; FT_UFast p = cache->p; FT_UFast mask = cache->mask; FT_UFast count = mask + p + 1; /* number of buckets */ /* do we need to shrink the buckets array? */ if ( cache->slack < 0 ) { FTC_Node new_list = NULL; /* try to expand the buckets array _before_ splitting * the bucket lists */ if ( p >= mask ) { FT_Memory memory = cache->memory; FT_Error error; /* if we can't expand the array, leave immediately */ if ( FT_RENEW_ARRAY( cache->buckets, ( mask + 1 ) * 2, ( mask + 1 ) * 4 ) ) break; } /* split a single bucket */ pnode = cache->buckets + p; for (;;) { node = *pnode; if ( node == NULL ) break; if ( node->hash & ( mask + 1 ) ) { *pnode = node->link; node->link = new_list; new_list = node; } else pnode = &node->link; } cache->buckets[p + mask + 1] = new_list; cache->slack += FTC_HASH_MAX_LOAD; if ( p >= mask ) { cache->mask = 2 * mask + 1; cache->p = 0; } else cache->p = p + 1; } /* do we need to expand the buckets array? */ else if ( cache->slack > (FT_Long)count * FTC_HASH_SUB_LOAD ) { FT_UFast old_index = p + mask; FTC_Node* pold; if ( old_index + 1 <= FTC_HASH_INITIAL_SIZE ) break; if ( p == 0 ) { FT_Memory memory = cache->memory; FT_Error error; /* if we can't shrink the array, leave immediately */ if ( FT_RENEW_ARRAY( cache->buckets, ( mask + 1 ) * 2, mask + 1 ) ) break; cache->mask >>= 1; p = cache->mask; } else
static FT_Error pcf_get_encodings( FT_Stream stream, PCF_Face face ) { FT_Error error; FT_Memory memory = FT_FACE( face )->memory; FT_ULong format, size; int firstCol, lastCol; int firstRow, lastRow; int nencoding, encodingOffset; int i, j, k; PCF_Encoding encoding = NULL; error = pcf_seek_to_table_type( stream, face->toc.tables, face->toc.count, PCF_BDF_ENCODINGS, &format, &size ); if ( error ) return error; error = FT_Stream_EnterFrame( stream, 14 ); if ( error ) return error; format = FT_GET_ULONG_LE(); if ( PCF_BYTE_ORDER( format ) == MSBFirst ) { firstCol = FT_GET_SHORT(); lastCol = FT_GET_SHORT(); firstRow = FT_GET_SHORT(); lastRow = FT_GET_SHORT(); face->defaultChar = FT_GET_SHORT(); } else { firstCol = FT_GET_SHORT_LE(); lastCol = FT_GET_SHORT_LE(); firstRow = FT_GET_SHORT_LE(); lastRow = FT_GET_SHORT_LE(); face->defaultChar = FT_GET_SHORT_LE(); } FT_Stream_ExitFrame( stream ); if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) return FT_THROW( Invalid_File_Format ); /* sanity checks */ if ( firstCol < 0 || firstCol > lastCol || lastCol > 0xFF || firstRow < 0 || firstRow > lastRow || lastRow > 0xFF ) return FT_THROW( Invalid_Table ); FT_TRACE4(( "pdf_get_encodings:\n" )); FT_TRACE4(( " firstCol %d, lastCol %d, firstRow %d, lastRow %d\n", firstCol, lastCol, firstRow, lastRow )); nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 ); if ( FT_NEW_ARRAY( encoding, nencoding ) ) return FT_THROW( Out_Of_Memory ); error = FT_Stream_EnterFrame( stream, 2 * nencoding ); if ( error ) goto Bail; k = 0; for ( i = firstRow; i <= lastRow; i++ ) { for ( j = firstCol; j <= lastCol; j++ ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) encodingOffset = FT_GET_SHORT(); else encodingOffset = FT_GET_SHORT_LE(); if ( encodingOffset != -1 ) { encoding[k].enc = i * 256 + j; encoding[k].glyph = (FT_Short)encodingOffset; FT_TRACE5(( " code %d (0x%04X): idx %d\n", encoding[k].enc, encoding[k].enc, encoding[k].glyph )); k++; } } } FT_Stream_ExitFrame( stream ); if ( FT_RENEW_ARRAY( encoding, nencoding, k ) ) goto Bail; face->nencodings = k; face->encodings = encoding; return error; Bail: FT_FREE( encoding ); return error; }
af_glyph_hints_reload( AF_GlyphHints hints, FT_Outline* outline ) { FT_Error error = FT_Err_Ok; AF_Point points; FT_UInt old_max, new_max; AF_Scaler scaler = &hints->metrics->scaler; FT_Fixed x_scale = hints->x_scale; FT_Fixed y_scale = hints->y_scale; FT_Pos x_delta = hints->x_delta; FT_Pos y_delta = hints->y_delta; FT_Memory memory = hints->memory; hints->scaler_flags = scaler->flags; hints->num_points = 0; hints->num_contours = 0; hints->axis[0].num_segments = 0; hints->axis[0].num_edges = 0; hints->axis[1].num_segments = 0; hints->axis[1].num_edges = 0; /* first of all, reallocate the contours array when necessary */ new_max = (FT_UInt) outline->n_contours; old_max = hints->max_contours; if ( new_max > old_max ) { new_max = (new_max + 3) & ~3; if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) ) goto Exit; hints->max_contours = new_max; } /* then, reallocate the points, segments & edges arrays if needed -- * note that we reserved two additional point positions, used to * hint metrics appropriately */ new_max = (FT_UInt)( outline->n_points + 2 ); old_max = hints->max_points; if ( new_max > old_max ) { FT_Byte* items; FT_ULong off1, off2, off3; /* we store in a single buffer the following arrays: * * - an array of N AF_PointRec items * - an array of 2*N AF_SegmentRec items * - an array of 2*N AF_EdgeRec items * */ new_max = ( new_max + 2 + 7 ) & ~7; #define OFF_PAD2(x,y) (((x)+(y)-1) & ~((y)-1)) #define OFF_PADX(x,y) ((((x)+(y)-1)/(y))*(y)) #define OFF_PAD(x,y) ( ((y) & ((y)-1)) ? OFF_PADX(x,y) : OFF_PAD2(x,y) ) #undef OFF_INCREMENT #define OFF_INCREMENT( _off, _type, _count ) \ ( OFF_PAD( _off, sizeof(_type) ) + (_count)*sizeof(_type)) off1 = OFF_INCREMENT( 0, AF_PointRec, new_max ); off2 = OFF_INCREMENT( off1, AF_SegmentRec, new_max*2 ); off3 = OFF_INCREMENT( off2, AF_EdgeRec, new_max*2 ); FT_FREE( hints->points ); if ( FT_ALLOC( items, off3 ) ) { hints->max_points = 0; hints->axis[0].segments = NULL; hints->axis[0].edges = NULL; hints->axis[1].segments = NULL; hints->axis[1].edges = NULL; goto Exit; } /* readjust some pointers */ hints->max_points = new_max; hints->points = (AF_Point) items; hints->axis[0].segments = (AF_Segment)( items + off1 ); hints->axis[1].segments = hints->axis[0].segments + new_max; hints->axis[0].edges = (AF_Edge) ( items + off2 ); hints->axis[1].edges = hints->axis[0].edges + new_max; } hints->num_points = outline->n_points; hints->num_contours = outline->n_contours; /* 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. */ /* */ hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_UP; hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_LEFT; if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT ) { hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_DOWN; hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_RIGHT; } hints->x_scale = x_scale; hints->y_scale = y_scale; hints->x_delta = x_delta; hints->y_delta = y_delta; points = hints->points; if ( hints->num_points == 0 ) goto Exit; { AF_Point point; AF_Point point_limit = points + hints->num_points; /* compute coordinates & bezier flags */ { FT_Vector* vec = outline->points; char* tag = outline->tags; for ( point = points; point < point_limit; point++, vec++, tag++ ) { point->fx = vec->x; point->fy = vec->y; point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta; point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta; switch ( FT_CURVE_TAG( *tag ) ) { case FT_CURVE_TAG_CONIC: point->flags = AF_FLAG_CONIC; break; case FT_CURVE_TAG_CUBIC: point->flags = AF_FLAG_CUBIC; break; default: point->flags = 0; ; } } } /* compute `next' and `prev' */ { FT_Int contour_index; AF_Point prev; AF_Point first; AF_Point end; contour_index = 0; first = points; end = points + outline->contours[0]; prev = end; for ( point = points; point < point_limit; point++ ) { point->prev = prev; if ( point < end ) { point->next = point + 1; prev = point; } else { point->next = first; contour_index++; if ( point + 1 < point_limit ) { end = points + outline->contours[contour_index]; first = point + 1; prev = end; } } } } /* set-up the contours array */ { AF_Point* contour = hints->contours; AF_Point* contour_limit = contour + hints->num_contours; short* end = outline->contours; short idx = 0; for ( ; contour < contour_limit; contour++, end++ ) { contour[0] = points + idx; idx = (short)( end[0] + 1 ); } } /* compute directions of in & out vectors */ { for ( point = points; point < point_limit; point++ ) { AF_Point prev; AF_Point next; FT_Pos in_x, in_y, out_x, out_y; prev = point->prev; in_x = point->fx - prev->fx; in_y = point->fy - prev->fy; point->in_dir = af_direction_compute( in_x, in_y ); next = point->next; out_x = next->fx - point->fx; out_y = next->fy - point->fy; point->out_dir = af_direction_compute( out_x, out_y ); if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) ) { Is_Weak_Point: point->flags |= AF_FLAG_WEAK_INTERPOLATION; } else if ( point->out_dir == point->in_dir ) { AF_Angle angle_in, angle_out, delta; if ( point->out_dir != AF_DIR_NONE ) goto Is_Weak_Point; angle_in = af_angle_atan( in_x, in_y ); angle_out = af_angle_atan( out_x, out_y ); delta = af_angle_diff( angle_in, angle_out ); if ( delta < 2 && delta > -2 ) goto Is_Weak_Point; } else if ( point->in_dir == -point->out_dir ) goto Is_Weak_Point; } } } /* compute inflection points */ af_glyph_hints_compute_inflections( hints ); Exit: return error; }
ftc_family_table_alloc( FTC_FamilyTable table, FT_Memory memory, FTC_FamilyEntry *aentry ) { FTC_FamilyEntry entry; FT_Error error = 0; /* re-allocate table size when needed */ if ( table->free == FTC_FAMILY_ENTRY_NONE && table->count >= table->size ) { FT_UInt old_size = table->size; FT_UInt new_size, idx; if ( old_size == 0 ) new_size = 8; else { new_size = old_size * 2; /* check for (unlikely) overflow */ if ( new_size < old_size ) new_size = 65534; } if ( FT_RENEW_ARRAY( table->entries, old_size, new_size ) ) return error; table->size = new_size; entry = table->entries + old_size; table->free = old_size; for ( idx = old_size; idx + 1 < new_size; idx++, entry++ ) { entry->link = idx + 1; entry->index = idx; } entry->link = FTC_FAMILY_ENTRY_NONE; entry->index = idx; } if ( table->free != FTC_FAMILY_ENTRY_NONE ) { entry = table->entries + table->free; table->free = entry->link; } else if ( table->count < table->size ) { entry = table->entries + table->count++; } else { FT_ERROR(( "ftc_family_table_alloc: internal bug!" )); return FTC_Err_Invalid_Argument; } entry->link = FTC_FAMILY_ENTRY_NONE; table->count++; *aentry = entry; return error; }