ReactOS  0.4.15-dev-994-ga9f6032
aflatin.h File Reference
#include "afhints.h"
Include dependency graph for aflatin.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  AF_LatinBlueRec_
 
struct  AF_LatinAxisRec_
 
struct  AF_LatinMetricsRec_
 

Macros

#define AFLATIN_H_
 
#define AF_LATIN_CONSTANT(metrics, c)   ( ( (c) * (FT_Long)( (AF_LatinMetrics)(metrics) )->units_per_em ) / 2048 )
 
#define AF_LATIN_IS_TOP_BLUE(b)   ( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP )
 
#define AF_LATIN_IS_SUB_TOP_BLUE(b)   ( (b)->properties & AF_BLUE_PROPERTY_LATIN_SUB_TOP )
 
#define AF_LATIN_IS_NEUTRAL_BLUE(b)   ( (b)->properties & AF_BLUE_PROPERTY_LATIN_NEUTRAL )
 
#define AF_LATIN_IS_X_HEIGHT_BLUE(b)   ( (b)->properties & AF_BLUE_PROPERTY_LATIN_X_HEIGHT )
 
#define AF_LATIN_IS_LONG_BLUE(b)   ( (b)->properties & AF_BLUE_PROPERTY_LATIN_LONG )
 
#define AF_LATIN_MAX_WIDTHS   16
 
#define AF_LATIN_BLUE_ACTIVE   ( 1U << 0 ) /* zone height is <= 3/4px */
 
#define AF_LATIN_BLUE_TOP   ( 1U << 1 ) /* we have a top blue zone */
 
#define AF_LATIN_BLUE_SUB_TOP   ( 1U << 2 ) /* we have a subscript top */
 
#define AF_LATIN_BLUE_NEUTRAL   ( 1U << 3 ) /* we have neutral blue zone */
 
#define AF_LATIN_BLUE_ADJUSTMENT   ( 1U << 4 ) /* used for scale adjustment */
 
#define AF_LATIN_HINTS_HORZ_SNAP   ( 1U << 0 ) /* stem width snapping */
 
#define AF_LATIN_HINTS_VERT_SNAP   ( 1U << 1 ) /* stem height snapping */
 
#define AF_LATIN_HINTS_STEM_ADJUST   ( 1U << 2 ) /* stem width/height */
 
#define AF_LATIN_HINTS_MONO   ( 1U << 3 ) /* monochrome rendering */
 
#define AF_LATIN_HINTS_DO_HORZ_SNAP(h)   AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_HORZ_SNAP )
 
#define AF_LATIN_HINTS_DO_VERT_SNAP(h)   AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_VERT_SNAP )
 
#define AF_LATIN_HINTS_DO_STEM_ADJUST(h)   AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_STEM_ADJUST )
 
#define AF_LATIN_HINTS_DO_MONO(h)   AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_MONO )
 
#define AF_LATIN_CONSTANT(metrics, c)   ( ( (c) * (FT_Long)( (AF_LatinMetrics)(metrics) )->units_per_em ) / 2048 )
 
#define AF_LATIN_IS_TOP_BLUE(b)   ( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP )
 
#define AF_LATIN_IS_SUB_TOP_BLUE(b)   ( (b)->properties & AF_BLUE_PROPERTY_LATIN_SUB_TOP )
 
#define AF_LATIN_IS_NEUTRAL_BLUE(b)   ( (b)->properties & AF_BLUE_PROPERTY_LATIN_NEUTRAL )
 
#define AF_LATIN_IS_X_HEIGHT_BLUE(b)   ( (b)->properties & AF_BLUE_PROPERTY_LATIN_X_HEIGHT )
 
#define AF_LATIN_IS_LONG_BLUE(b)   ( (b)->properties & AF_BLUE_PROPERTY_LATIN_LONG )
 
#define AF_LATIN_MAX_WIDTHS   16
 
#define AF_LATIN_BLUE_ACTIVE   ( 1U << 0 ) /* zone height is <= 3/4px */
 
#define AF_LATIN_BLUE_TOP   ( 1U << 1 ) /* we have a top blue zone */
 
#define AF_LATIN_BLUE_SUB_TOP   ( 1U << 2 ) /* we have a subscript top */
 
#define AF_LATIN_BLUE_NEUTRAL   ( 1U << 3 ) /* we have neutral blue zone */
 
#define AF_LATIN_BLUE_ADJUSTMENT   ( 1U << 4 ) /* used for scale adjustment */
 
#define AF_LATIN_HINTS_HORZ_SNAP   ( 1U << 0 ) /* stem width snapping */
 
#define AF_LATIN_HINTS_VERT_SNAP   ( 1U << 1 ) /* stem height snapping */
 
#define AF_LATIN_HINTS_STEM_ADJUST   ( 1U << 2 ) /* stem width/height */
 
#define AF_LATIN_HINTS_MONO   ( 1U << 3 ) /* monochrome rendering */
 
#define AF_LATIN_HINTS_DO_HORZ_SNAP(h)   AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_HORZ_SNAP )
 
#define AF_LATIN_HINTS_DO_VERT_SNAP(h)   AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_VERT_SNAP )
 
#define AF_LATIN_HINTS_DO_STEM_ADJUST(h)   AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_STEM_ADJUST )
 
#define AF_LATIN_HINTS_DO_MONO(h)   AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_MONO )
 

Typedefs

typedef struct AF_LatinBlueRec_ AF_LatinBlueRec
 
typedef struct AF_LatinBlueRec_AF_LatinBlue
 
typedef struct AF_LatinAxisRec_ AF_LatinAxisRec
 
typedef struct AF_LatinAxisRec_AF_LatinAxis
 
typedef struct AF_LatinMetricsRec_ AF_LatinMetricsRec
 
typedef struct AF_LatinMetricsRec_AF_LatinMetrics
 

Functions

 af_latin_metrics_init (AF_LatinMetrics metrics, FT_Face face)
 
 af_latin_metrics_scale (AF_LatinMetrics metrics, AF_Scaler scaler)
 
 af_latin_metrics_init_widths (AF_LatinMetrics metrics, FT_Face face)
 
 af_latin_metrics_check_digits (AF_LatinMetrics metrics, FT_Face face)
 
 af_latin_hints_compute_segments (AF_GlyphHints hints, AF_Dimension dim)
 
 af_latin_hints_link_segments (AF_GlyphHints hints, FT_UInt width_count, AF_WidthRec *widths, AF_Dimension dim)
 
 af_latin_hints_compute_edges (AF_GlyphHints hints, AF_Dimension dim)
 
 af_latin_hints_detect_features (AF_GlyphHints hints, FT_UInt width_count, AF_WidthRec *widths, AF_Dimension dim)
 

Macro Definition Documentation

◆ AF_LATIN_BLUE_ACTIVE [1/2]

#define AF_LATIN_BLUE_ACTIVE   ( 1U << 0 ) /* zone height is <= 3/4px */

◆ AF_LATIN_BLUE_ACTIVE [2/2]

#define AF_LATIN_BLUE_ACTIVE   ( 1U << 0 ) /* zone height is <= 3/4px */

Definition at line 68 of file aflatin.h.

◆ AF_LATIN_BLUE_ADJUSTMENT [1/2]

#define AF_LATIN_BLUE_ADJUSTMENT   ( 1U << 4 ) /* used for scale adjustment */

Definition at line 73 of file aflatin.h.

◆ AF_LATIN_BLUE_ADJUSTMENT [2/2]

#define AF_LATIN_BLUE_ADJUSTMENT   ( 1U << 4 ) /* used for scale adjustment */

◆ AF_LATIN_BLUE_NEUTRAL [1/2]

#define AF_LATIN_BLUE_NEUTRAL   ( 1U << 3 ) /* we have neutral blue zone */

Definition at line 72 of file aflatin.h.

◆ AF_LATIN_BLUE_NEUTRAL [2/2]

#define AF_LATIN_BLUE_NEUTRAL   ( 1U << 3 ) /* we have neutral blue zone */

◆ AF_LATIN_BLUE_SUB_TOP [1/2]

#define AF_LATIN_BLUE_SUB_TOP   ( 1U << 2 ) /* we have a subscript top */

◆ AF_LATIN_BLUE_SUB_TOP [2/2]

#define AF_LATIN_BLUE_SUB_TOP   ( 1U << 2 ) /* we have a subscript top */

Definition at line 70 of file aflatin.h.

◆ AF_LATIN_BLUE_TOP [1/2]

#define AF_LATIN_BLUE_TOP   ( 1U << 1 ) /* we have a top blue zone */

◆ AF_LATIN_BLUE_TOP [2/2]

#define AF_LATIN_BLUE_TOP   ( 1U << 1 ) /* we have a top blue zone */

Definition at line 69 of file aflatin.h.

◆ AF_LATIN_CONSTANT [1/2]

#define AF_LATIN_CONSTANT (   metrics,
  c 
)    ( ( (c) * (FT_Long)( (AF_LatinMetrics)(metrics) )->units_per_em ) / 2048 )

◆ AF_LATIN_CONSTANT [2/2]

#define AF_LATIN_CONSTANT (   metrics,
  c 
)    ( ( (c) * (FT_Long)( (AF_LatinMetrics)(metrics) )->units_per_em ) / 2048 )

Definition at line 34 of file aflatin.h.

◆ AF_LATIN_HINTS_DO_HORZ_SNAP [1/2]

#define AF_LATIN_HINTS_DO_HORZ_SNAP (   h)    AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_HORZ_SNAP )

◆ AF_LATIN_HINTS_DO_HORZ_SNAP [2/2]

#define AF_LATIN_HINTS_DO_HORZ_SNAP (   h)    AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_HORZ_SNAP )

Definition at line 150 of file aflatin.h.

◆ AF_LATIN_HINTS_DO_MONO [1/2]

#define AF_LATIN_HINTS_DO_MONO (   h)    AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_MONO )

◆ AF_LATIN_HINTS_DO_MONO [2/2]

#define AF_LATIN_HINTS_DO_MONO (   h)    AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_MONO )

Definition at line 159 of file aflatin.h.

◆ AF_LATIN_HINTS_DO_STEM_ADJUST [1/2]

#define AF_LATIN_HINTS_DO_STEM_ADJUST (   h)    AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_STEM_ADJUST )

◆ AF_LATIN_HINTS_DO_STEM_ADJUST [2/2]

#define AF_LATIN_HINTS_DO_STEM_ADJUST (   h)    AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_STEM_ADJUST )

Definition at line 156 of file aflatin.h.

◆ AF_LATIN_HINTS_DO_VERT_SNAP [1/2]

#define AF_LATIN_HINTS_DO_VERT_SNAP (   h)    AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_VERT_SNAP )

◆ AF_LATIN_HINTS_DO_VERT_SNAP [2/2]

#define AF_LATIN_HINTS_DO_VERT_SNAP (   h)    AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_VERT_SNAP )

Definition at line 153 of file aflatin.h.

◆ AF_LATIN_HINTS_HORZ_SNAP [1/2]

#define AF_LATIN_HINTS_HORZ_SNAP   ( 1U << 0 ) /* stem width snapping */

Definition at line 143 of file aflatin.h.

◆ AF_LATIN_HINTS_HORZ_SNAP [2/2]

#define AF_LATIN_HINTS_HORZ_SNAP   ( 1U << 0 ) /* stem width snapping */

◆ AF_LATIN_HINTS_MONO [1/2]

#define AF_LATIN_HINTS_MONO   ( 1U << 3 ) /* monochrome rendering */

◆ AF_LATIN_HINTS_MONO [2/2]

#define AF_LATIN_HINTS_MONO   ( 1U << 3 ) /* monochrome rendering */

Definition at line 147 of file aflatin.h.

◆ AF_LATIN_HINTS_STEM_ADJUST [1/2]

#define AF_LATIN_HINTS_STEM_ADJUST   ( 1U << 2 ) /* stem width/height */

◆ AF_LATIN_HINTS_STEM_ADJUST [2/2]

#define AF_LATIN_HINTS_STEM_ADJUST   ( 1U << 2 ) /* stem width/height */

Definition at line 145 of file aflatin.h.

◆ AF_LATIN_HINTS_VERT_SNAP [1/2]

#define AF_LATIN_HINTS_VERT_SNAP   ( 1U << 1 ) /* stem height snapping */

Definition at line 144 of file aflatin.h.

◆ AF_LATIN_HINTS_VERT_SNAP [2/2]

#define AF_LATIN_HINTS_VERT_SNAP   ( 1U << 1 ) /* stem height snapping */

◆ AF_LATIN_IS_LONG_BLUE [1/2]

#define AF_LATIN_IS_LONG_BLUE (   b)    ( (b)->properties & AF_BLUE_PROPERTY_LATIN_LONG )

Definition at line 62 of file aflatin.h.

◆ AF_LATIN_IS_LONG_BLUE [2/2]

#define AF_LATIN_IS_LONG_BLUE (   b)    ( (b)->properties & AF_BLUE_PROPERTY_LATIN_LONG )

◆ AF_LATIN_IS_NEUTRAL_BLUE [1/2]

#define AF_LATIN_IS_NEUTRAL_BLUE (   b)    ( (b)->properties & AF_BLUE_PROPERTY_LATIN_NEUTRAL )

◆ AF_LATIN_IS_NEUTRAL_BLUE [2/2]

#define AF_LATIN_IS_NEUTRAL_BLUE (   b)    ( (b)->properties & AF_BLUE_PROPERTY_LATIN_NEUTRAL )

Definition at line 58 of file aflatin.h.

◆ AF_LATIN_IS_SUB_TOP_BLUE [1/2]

#define AF_LATIN_IS_SUB_TOP_BLUE (   b)    ( (b)->properties & AF_BLUE_PROPERTY_LATIN_SUB_TOP )

Definition at line 56 of file aflatin.h.

◆ AF_LATIN_IS_SUB_TOP_BLUE [2/2]

#define AF_LATIN_IS_SUB_TOP_BLUE (   b)    ( (b)->properties & AF_BLUE_PROPERTY_LATIN_SUB_TOP )

◆ AF_LATIN_IS_TOP_BLUE [1/2]

#define AF_LATIN_IS_TOP_BLUE (   b)    ( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP )

◆ AF_LATIN_IS_TOP_BLUE [2/2]

#define AF_LATIN_IS_TOP_BLUE (   b)    ( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP )

Definition at line 54 of file aflatin.h.

◆ AF_LATIN_IS_X_HEIGHT_BLUE [1/2]

#define AF_LATIN_IS_X_HEIGHT_BLUE (   b)    ( (b)->properties & AF_BLUE_PROPERTY_LATIN_X_HEIGHT )

◆ AF_LATIN_IS_X_HEIGHT_BLUE [2/2]

#define AF_LATIN_IS_X_HEIGHT_BLUE (   b)    ( (b)->properties & AF_BLUE_PROPERTY_LATIN_X_HEIGHT )

Definition at line 60 of file aflatin.h.

◆ AF_LATIN_MAX_WIDTHS [1/2]

#define AF_LATIN_MAX_WIDTHS   16

Definition at line 65 of file aflatin.h.

◆ AF_LATIN_MAX_WIDTHS [2/2]

#define AF_LATIN_MAX_WIDTHS   16

◆ AFLATIN_H_

#define AFLATIN_H_

Typedef Documentation

◆ AF_LatinAxis

◆ AF_LatinAxisRec

◆ AF_LatinBlue

◆ AF_LatinBlueRec

◆ AF_LatinMetrics

◆ AF_LatinMetricsRec

Function Documentation

◆ af_latin_hints_compute_edges()

af_latin_hints_compute_edges ( AF_GlyphHints  hints,
AF_Dimension  dim 
)

Definition at line 2065 of file aflatin.c.

2067  {
2068  AF_AxisHints axis = &hints->axis[dim];
2070  FT_Memory memory = hints->memory;
2071  AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim];
2072 
2073 #ifdef FT_CONFIG_OPTION_PIC
2074  AF_FaceGlobals globals = hints->metrics->globals;
2075 #endif
2076 
2077  AF_StyleClass style_class = hints->metrics->style_class;
2078  AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET
2079  [style_class->script];
2080 
2081  FT_Bool top_to_bottom_hinting = 0;
2082 
2083  AF_Segment segments = axis->segments;
2084  AF_Segment segment_limit = segments + axis->num_segments;
2085  AF_Segment seg;
2086 
2087 #if 0
2088  AF_Direction up_dir;
2089 #endif
2090  FT_Fixed scale;
2091  FT_Pos edge_distance_threshold;
2092  FT_Pos segment_length_threshold;
2093  FT_Pos segment_width_threshold;
2094 
2095 
2096  axis->num_edges = 0;
2097 
2098  scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
2099  : hints->y_scale;
2100 
2101 #if 0
2102  up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP
2103  : AF_DIR_RIGHT;
2104 #endif
2105 
2106  if ( dim == AF_DIMENSION_VERT )
2107  top_to_bottom_hinting = script_class->top_to_bottom_hinting;
2108 
2109  /*
2110  * We ignore all segments that are less than 1 pixel in length
2111  * to avoid many problems with serif fonts. We compute the
2112  * corresponding threshold in font units.
2113  */
2114  if ( dim == AF_DIMENSION_HORZ )
2115  segment_length_threshold = FT_DivFix( 64, hints->y_scale );
2116  else
2117  segment_length_threshold = 0;
2118 
2119  /*
2120  * Similarly, we ignore segments that have a width delta
2121  * larger than 0.5px (i.e., a width larger than 1px).
2122  */
2123  segment_width_threshold = FT_DivFix( 32, scale );
2124 
2125  /*********************************************************************/
2126  /* */
2127  /* We begin by generating a sorted table of edges for the current */
2128  /* direction. To do so, we simply scan each segment and try to find */
2129  /* an edge in our table that corresponds to its position. */
2130  /* */
2131  /* If no edge is found, we create and insert a new edge in the */
2132  /* sorted table. Otherwise, we simply add the segment to the edge's */
2133  /* list which gets processed in the second step to compute the */
2134  /* edge's properties. */
2135  /* */
2136  /* Note that the table of edges is sorted along the segment/edge */
2137  /* position. */
2138  /* */
2139  /*********************************************************************/
2140 
2141  /* assure that edge distance threshold is at most 0.25px */
2142  edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
2143  scale );
2144  if ( edge_distance_threshold > 64 / 4 )
2145  edge_distance_threshold = 64 / 4;
2146 
2147  edge_distance_threshold = FT_DivFix( edge_distance_threshold,
2148  scale );
2149 
2150  for ( seg = segments; seg < segment_limit; seg++ )
2151  {
2152  AF_Edge found = NULL;
2153  FT_Int ee;
2154 
2155 
2156  /* ignore too short segments, too wide ones, and, in this loop, */
2157  /* one-point segments without a direction */
2158  if ( seg->height < segment_length_threshold ||
2159  seg->delta > segment_width_threshold ||
2160  seg->dir == AF_DIR_NONE )
2161  continue;
2162 
2163  /* A special case for serif edges: If they are smaller than */
2164  /* 1.5 pixels we ignore them. */
2165  if ( seg->serif &&
2166  2 * seg->height < 3 * segment_length_threshold )
2167  continue;
2168 
2169  /* look for an edge corresponding to the segment */
2170  for ( ee = 0; ee < axis->num_edges; ee++ )
2171  {
2172  AF_Edge edge = axis->edges + ee;
2173  FT_Pos dist;
2174 
2175 
2176  dist = seg->pos - edge->fpos;
2177  if ( dist < 0 )
2178  dist = -dist;
2179 
2180  if ( dist < edge_distance_threshold && edge->dir == seg->dir )
2181  {
2182  found = edge;
2183  break;
2184  }
2185  }
2186 
2187  if ( !found )
2188  {
2189  AF_Edge edge;
2190 
2191 
2192  /* insert a new edge in the list and */
2193  /* sort according to the position */
2194  error = af_axis_hints_new_edge( axis, seg->pos,
2195  (AF_Direction)seg->dir,
2196  top_to_bottom_hinting,
2197  memory, &edge );
2198  if ( error )
2199  goto Exit;
2200 
2201  /* add the segment to the new edge's list */
2202  FT_ZERO( edge );
2203 
2204  edge->first = seg;
2205  edge->last = seg;
2206  edge->dir = seg->dir;
2207  edge->fpos = seg->pos;
2208  edge->opos = FT_MulFix( seg->pos, scale );
2209  edge->pos = edge->opos;
2210  seg->edge_next = seg;
2211  }
2212  else
2213  {
2214  /* if an edge was found, simply add the segment to the edge's */
2215  /* list */
2216  seg->edge_next = found->first;
2217  found->last->edge_next = seg;
2218  found->last = seg;
2219  }
2220  }
2221 
2222  /* we loop again over all segments to catch one-point segments */
2223  /* without a direction: if possible, link them to existing edges */
2224  for ( seg = segments; seg < segment_limit; seg++ )
2225  {
2226  AF_Edge found = NULL;
2227  FT_Int ee;
2228 
2229 
2230  if ( seg->dir != AF_DIR_NONE )
2231  continue;
2232 
2233  /* look for an edge corresponding to the segment */
2234  for ( ee = 0; ee < axis->num_edges; ee++ )
2235  {
2236  AF_Edge edge = axis->edges + ee;
2237  FT_Pos dist;
2238 
2239 
2240  dist = seg->pos - edge->fpos;
2241  if ( dist < 0 )
2242  dist = -dist;
2243 
2244  if ( dist < edge_distance_threshold )
2245  {
2246  found = edge;
2247  break;
2248  }
2249  }
2250 
2251  /* one-point segments without a match are ignored */
2252  if ( found )
2253  {
2254  seg->edge_next = found->first;
2255  found->last->edge_next = seg;
2256  found->last = seg;
2257  }
2258  }
2259 
2260 
2261  /******************************************************************/
2262  /* */
2263  /* Good, we now compute each edge's properties according to the */
2264  /* segments found on its position. Basically, these are */
2265  /* */
2266  /* - the edge's main direction */
2267  /* - stem edge, serif edge or both (which defaults to stem then) */
2268  /* - rounded edge, straight or both (which defaults to straight) */
2269  /* - link for edge */
2270  /* */
2271  /******************************************************************/
2272 
2273  /* first of all, set the `edge' field in each segment -- this is */
2274  /* required in order to compute edge links */
2275 
2276  /*
2277  * Note that removing this loop and setting the `edge' field of each
2278  * segment directly in the code above slows down execution speed for
2279  * some reasons on platforms like the Sun.
2280  */
2281  {
2282  AF_Edge edges = axis->edges;
2283  AF_Edge edge_limit = edges + axis->num_edges;
2284  AF_Edge edge;
2285 
2286 
2287  for ( edge = edges; edge < edge_limit; edge++ )
2288  {
2289  seg = edge->first;
2290  if ( seg )
2291  do
2292  {
2293  seg->edge = edge;
2294  seg = seg->edge_next;
2295 
2296  } while ( seg != edge->first );
2297  }
2298 
2299  /* now compute each edge properties */
2300  for ( edge = edges; edge < edge_limit; edge++ )
2301  {
2302  FT_Int is_round = 0; /* does it contain round segments? */
2303  FT_Int is_straight = 0; /* does it contain straight segments? */
2304 #if 0
2305  FT_Pos ups = 0; /* number of upwards segments */
2306  FT_Pos downs = 0; /* number of downwards segments */
2307 #endif
2308 
2309 
2310  seg = edge->first;
2311 
2312  do
2313  {
2314  FT_Bool is_serif;
2315 
2316 
2317  /* check for roundness of segment */
2318  if ( seg->flags & AF_EDGE_ROUND )
2319  is_round++;
2320  else
2321  is_straight++;
2322 
2323 #if 0
2324  /* check for segment direction */
2325  if ( seg->dir == up_dir )
2326  ups += seg->max_coord - seg->min_coord;
2327  else
2328  downs += seg->max_coord - seg->min_coord;
2329 #endif
2330 
2331  /* check for links -- if seg->serif is set, then seg->link must */
2332  /* be ignored */
2333  is_serif = (FT_Bool)( seg->serif &&
2334  seg->serif->edge &&
2335  seg->serif->edge != edge );
2336 
2337  if ( ( seg->link && seg->link->edge ) || is_serif )
2338  {
2339  AF_Edge edge2;
2340  AF_Segment seg2;
2341 
2342 
2343  edge2 = edge->link;
2344  seg2 = seg->link;
2345 
2346  if ( is_serif )
2347  {
2348  seg2 = seg->serif;
2349  edge2 = edge->serif;
2350  }
2351 
2352  if ( edge2 )
2353  {
2354  FT_Pos edge_delta;
2355  FT_Pos seg_delta;
2356 
2357 
2358  edge_delta = edge->fpos - edge2->fpos;
2359  if ( edge_delta < 0 )
2360  edge_delta = -edge_delta;
2361 
2362  seg_delta = seg->pos - seg2->pos;
2363  if ( seg_delta < 0 )
2364  seg_delta = -seg_delta;
2365 
2366  if ( seg_delta < edge_delta )
2367  edge2 = seg2->edge;
2368  }
2369  else
2370  edge2 = seg2->edge;
2371 
2372  if ( is_serif )
2373  {
2374  edge->serif = edge2;
2375  edge2->flags |= AF_EDGE_SERIF;
2376  }
2377  else
2378  edge->link = edge2;
2379  }
2380 
2381  seg = seg->edge_next;
2382 
2383  } while ( seg != edge->first );
2384 
2385  /* set the round/straight flags */
2386  edge->flags = AF_EDGE_NORMAL;
2387 
2388  if ( is_round > 0 && is_round >= is_straight )
2389  edge->flags |= AF_EDGE_ROUND;
2390 
2391 #if 0
2392  /* set the edge's main direction */
2393  edge->dir = AF_DIR_NONE;
2394 
2395  if ( ups > downs )
2396  edge->dir = (FT_Char)up_dir;
2397 
2398  else if ( ups < downs )
2399  edge->dir = (FT_Char)-up_dir;
2400 
2401  else if ( ups == downs )
2402  edge->dir = 0; /* both up and down! */
2403 #endif
2404 
2405  /* get rid of serifs if link is set */
2406  /* XXX: This gets rid of many unpleasant artefacts! */
2407  /* Example: the `c' in cour.pfa at size 13 */
2408 
2409  if ( edge->serif && edge->link )
2410  edge->serif = NULL;
2411  }
2412  }
2413 
2414  Exit:
2415  return error;
2416  }
namespace GUID const ADDRINFOEXW * hints
Definition: sock.c:80
int FT_Error
Definition: fttypes.h:300
FT_DivFix(FT_Long a, FT_Long b)
Definition: ftcalc.c:608
AF_Script script
Definition: aftypes.h:450
FT_BEGIN_HEADER typedef signed long FT_Pos
Definition: ftimage.h:58
AF_Segment edge_next
Definition: afhints.h:269
#define error(str)
Definition: mkdosfs.c:1605
signed int FT_Int
Definition: fttypes.h:220
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9032
signed char FT_Char
Definition: fttypes.h:143
struct AF_LatinMetricsRec_ * AF_LatinMetrics
enum AF_Direction_ AF_Direction
AF_Edge link
Definition: afhints.h:293
AF_Segment last
Definition: afhints.h:298
return FT_Err_Ok
Definition: ftbbox.c:511
static char memory[1024 *256]
Definition: process.c:116
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
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)
Definition: afhints.c:99
FT_Byte flags
Definition: afhints.h:288
#define AF_SCRIPT_CLASSES_GET
Definition: afpic.h:32
FT_Bool top_to_bottom_hinting
Definition: aftypes.h:346
smooth NULL
Definition: ftsmooth.c:416
FT_Char dir
Definition: afhints.h:289
unsigned int dir
Definition: maze.c:112
FT_Int num_edges
Definition: afhints.h:314
#define FT_ZERO(p)
Definition: ftmemory.h:237
#define AF_EDGE_SERIF
static void Exit(void)
Definition: sock.c:1331
FT_Pos pos
Definition: afhints.h:286
AF_Segment segments
Definition: afhints.h:309
FT_Short fpos
Definition: afhints.h:284
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
seg
Definition: i386-dis.c:3857
AF_Edge edge
Definition: afhints.h:268
FT_Int num_segments
Definition: afhints.h:307
FT_MulFix(FT_Long a, FT_Long b)
Definition: ftcalc.c:509
FT_Pos edge_distance_threshold
Definition: aflatin.h:95
FT_Short pos
Definition: afhints.h:262
signed long FT_Fixed
Definition: fttypes.h:288
AF_Segment first
Definition: afhints.h:297
AF_Edge serif
Definition: afhints.h:294
#define AF_EDGE_ROUND
#define AF_EDGE_NORMAL
FT_Pos opos
Definition: afhints.h:285
AF_Edge edges
Definition: afhints.h:316

Referenced by af_latin_hints_detect_features().

◆ af_latin_hints_compute_segments()

af_latin_hints_compute_segments ( AF_GlyphHints  hints,
AF_Dimension  dim 
)

Definition at line 1499 of file aflatin.c.

1501  {
1503  AF_AxisHints axis = &hints->axis[dim];
1504  FT_Memory memory = hints->memory;
1506  AF_Segment segment = NULL;
1507  AF_SegmentRec seg0;
1508  AF_Point* contour = hints->contours;
1509  AF_Point* contour_limit = contour + hints->num_contours;
1510  AF_Direction major_dir, segment_dir;
1511 
1512  FT_Pos flat_threshold = FLAT_THRESHOLD( metrics->units_per_em );
1513 
1514 
1515  FT_ZERO( &seg0 );
1516  seg0.score = 32000;
1517  seg0.flags = AF_EDGE_NORMAL;
1518 
1519  major_dir = (AF_Direction)FT_ABS( axis->major_dir );
1520  segment_dir = major_dir;
1521 
1522  axis->num_segments = 0;
1523 
1524  /* set up (u,v) in each point */
1525  if ( dim == AF_DIMENSION_HORZ )
1526  {
1527  AF_Point point = hints->points;
1528  AF_Point limit = point + hints->num_points;
1529 
1530 
1531  for ( ; point < limit; point++ )
1532  {
1533  point->u = point->fx;
1534  point->v = point->fy;
1535  }
1536  }
1537  else
1538  {
1539  AF_Point point = hints->points;
1540  AF_Point limit = point + hints->num_points;
1541 
1542 
1543  for ( ; point < limit; point++ )
1544  {
1545  point->u = point->fy;
1546  point->v = point->fx;
1547  }
1548  }
1549 
1550  /* do each contour separately */
1551  for ( ; contour < contour_limit; contour++ )
1552  {
1553  AF_Point point = contour[0];
1554  AF_Point last = point->prev;
1555  int on_edge = 0;
1556 
1557  /* we call values measured along a segment (point->v) */
1558  /* `coordinates', and values orthogonal to it (point->u) */
1559  /* `positions' */
1560  FT_Pos min_pos = 32000;
1561  FT_Pos max_pos = -32000;
1562  FT_Pos min_coord = 32000;
1563  FT_Pos max_coord = -32000;
1564  FT_UShort min_flags = AF_FLAG_NONE;
1565  FT_UShort max_flags = AF_FLAG_NONE;
1566  FT_Pos min_on_coord = 32000;
1567  FT_Pos max_on_coord = -32000;
1568 
1569  FT_Bool passed;
1570 
1571  AF_Segment prev_segment = NULL;
1572 
1573  FT_Pos prev_min_pos = min_pos;
1574  FT_Pos prev_max_pos = max_pos;
1575  FT_Pos prev_min_coord = min_coord;
1576  FT_Pos prev_max_coord = max_coord;
1577  FT_UShort prev_min_flags = min_flags;
1578  FT_UShort prev_max_flags = max_flags;
1579  FT_Pos prev_min_on_coord = min_on_coord;
1580  FT_Pos prev_max_on_coord = max_on_coord;
1581 
1582 
1583  if ( FT_ABS( last->out_dir ) == major_dir &&
1584  FT_ABS( point->out_dir ) == major_dir )
1585  {
1586  /* we are already on an edge, try to locate its start */
1587  last = point;
1588 
1589  for (;;)
1590  {
1591  point = point->prev;
1592  if ( FT_ABS( point->out_dir ) != major_dir )
1593  {
1594  point = point->next;
1595  break;
1596  }
1597  if ( point == last )
1598  break;
1599  }
1600  }
1601 
1602  last = point;
1603  passed = 0;
1604 
1605  for (;;)
1606  {
1607  FT_Pos u, v;
1608 
1609 
1610  if ( on_edge )
1611  {
1612  /* get minimum and maximum position */
1613  u = point->u;
1614  if ( u < min_pos )
1615  min_pos = u;
1616  if ( u > max_pos )
1617  max_pos = u;
1618 
1619  /* get minimum and maximum coordinate together with flags */
1620  v = point->v;
1621  if ( v < min_coord )
1622  {
1623  min_coord = v;
1624  min_flags = point->flags;
1625  }
1626  if ( v > max_coord )
1627  {
1628  max_coord = v;
1629  max_flags = point->flags;
1630  }
1631 
1632  /* get minimum and maximum coordinate of `on' points */
1633  if ( !( point->flags & AF_FLAG_CONTROL ) )
1634  {
1635  v = point->v;
1636  if ( v < min_on_coord )
1637  min_on_coord = v;
1638  if ( v > max_on_coord )
1639  max_on_coord = v;
1640  }
1641 
1642  if ( point->out_dir != segment_dir || point == last )
1643  {
1644  /* check whether the new segment's start point is identical to */
1645  /* the previous segment's end point; for example, this might */
1646  /* happen for spikes */
1647 
1648  if ( !prev_segment || segment->first != prev_segment->last )
1649  {
1650  /* points are different: we are just leaving an edge, thus */
1651  /* record a new segment */
1652 
1653  segment->last = point;
1654  segment->pos = (FT_Short)( ( min_pos + max_pos ) >> 1 );
1655  segment->delta = (FT_Short)( ( max_pos - min_pos ) >> 1 );
1656 
1657  /* a segment is round if either its first or last point */
1658  /* is a control point, and the length of the on points */
1659  /* inbetween doesn't exceed a heuristic limit */
1660  if ( ( min_flags | max_flags ) & AF_FLAG_CONTROL &&
1661  ( max_on_coord - min_on_coord ) < flat_threshold )
1662  segment->flags |= AF_EDGE_ROUND;
1663 
1664  segment->min_coord = (FT_Short)min_coord;
1665  segment->max_coord = (FT_Short)max_coord;
1666  segment->height = segment->max_coord - segment->min_coord;
1667 
1668  prev_segment = segment;
1669  prev_min_pos = min_pos;
1670  prev_max_pos = max_pos;
1671  prev_min_coord = min_coord;
1672  prev_max_coord = max_coord;
1673  prev_min_flags = min_flags;
1674  prev_max_flags = max_flags;
1675  prev_min_on_coord = min_on_coord;
1676  prev_max_on_coord = max_on_coord;
1677  }
1678  else
1679  {
1680  /* points are the same: we don't create a new segment but */
1681  /* merge the current segment with the previous one */
1682 
1683  if ( prev_segment->last->in_dir == point->in_dir )
1684  {
1685  /* we have identical directions (this can happen for */
1686  /* degenerate outlines that move zig-zag along the main */
1687  /* axis without changing the coordinate value of the other */
1688  /* axis, and where the segments have just been merged): */
1689  /* unify segments */
1690 
1691  /* update constraints */
1692 
1693  if ( prev_min_pos < min_pos )
1694  min_pos = prev_min_pos;
1695  if ( prev_max_pos > max_pos )
1696  max_pos = prev_max_pos;
1697 
1698  if ( prev_min_coord < min_coord )
1699  {
1700  min_coord = prev_min_coord;
1701  min_flags = prev_min_flags;
1702  }
1703  if ( prev_max_coord > max_coord )
1704  {
1705  max_coord = prev_max_coord;
1706  max_flags = prev_max_flags;
1707  }
1708 
1709  if ( prev_min_on_coord < min_on_coord )
1710  min_on_coord = prev_min_on_coord;
1711  if ( prev_max_on_coord > max_on_coord )
1712  max_on_coord = prev_max_on_coord;
1713 
1714  prev_segment->last = point;
1715  prev_segment->pos = (FT_Short)( ( min_pos +
1716  max_pos ) >> 1 );
1717  prev_segment->delta = (FT_Short)( ( max_pos -
1718  min_pos ) >> 1 );
1719 
1720  if ( ( min_flags | max_flags ) & AF_FLAG_CONTROL &&
1721  ( max_on_coord - min_on_coord ) < flat_threshold )
1722  prev_segment->flags |= AF_EDGE_ROUND;
1723  else
1724  prev_segment->flags &= ~AF_EDGE_ROUND;
1725 
1726  prev_segment->min_coord = (FT_Short)min_coord;
1727  prev_segment->max_coord = (FT_Short)max_coord;
1728  prev_segment->height = prev_segment->max_coord -
1729  prev_segment->min_coord;
1730  }
1731  else
1732  {
1733  /* we have different directions; use the properties of the */
1734  /* longer segment and discard the other one */
1735 
1736  if ( FT_ABS( prev_max_coord - prev_min_coord ) >
1737  FT_ABS( max_coord - min_coord ) )
1738  {
1739  /* discard current segment */
1740 
1741  if ( min_pos < prev_min_pos )
1742  prev_min_pos = min_pos;
1743  if ( max_pos > prev_max_pos )
1744  prev_max_pos = max_pos;
1745 
1746  prev_segment->last = point;
1747  prev_segment->pos = (FT_Short)( ( prev_min_pos +
1748  prev_max_pos ) >> 1 );
1749  prev_segment->delta = (FT_Short)( ( prev_max_pos -
1750  prev_min_pos ) >> 1 );
1751  }
1752  else
1753  {
1754  /* discard previous segment */
1755 
1756  if ( prev_min_pos < min_pos )
1757  min_pos = prev_min_pos;
1758  if ( prev_max_pos > max_pos )
1759  max_pos = prev_max_pos;
1760 
1761  segment->last = point;
1762  segment->pos = (FT_Short)( ( min_pos + max_pos ) >> 1 );
1763  segment->delta = (FT_Short)( ( max_pos - min_pos ) >> 1 );
1764 
1765  if ( ( min_flags | max_flags ) & AF_FLAG_CONTROL &&
1766  ( max_on_coord - min_on_coord ) < flat_threshold )
1767  segment->flags |= AF_EDGE_ROUND;
1768 
1769  segment->min_coord = (FT_Short)min_coord;
1770  segment->max_coord = (FT_Short)max_coord;
1771  segment->height = segment->max_coord -
1772  segment->min_coord;
1773 
1774  *prev_segment = *segment;
1775 
1776  prev_min_pos = min_pos;
1777  prev_max_pos = max_pos;
1778  prev_min_coord = min_coord;
1779  prev_max_coord = max_coord;
1780  prev_min_flags = min_flags;
1781  prev_max_flags = max_flags;
1782  prev_min_on_coord = min_on_coord;
1783  prev_max_on_coord = max_on_coord;
1784  }
1785  }
1786 
1787  axis->num_segments--;
1788  }
1789 
1790  on_edge = 0;
1791  segment = NULL;
1792 
1793  /* fall through */
1794  }
1795  }
1796 
1797  /* now exit if we are at the start/end point */
1798  if ( point == last )
1799  {
1800  if ( passed )
1801  break;
1802  passed = 1;
1803  }
1804 
1805  /* if we are not on an edge, check whether the major direction */
1806  /* coincides with the current point's `out' direction, or */
1807  /* whether we have a single-point contour */
1808  if ( !on_edge &&
1809  ( FT_ABS( point->out_dir ) == major_dir ||
1810  point == point->prev ) )
1811  {
1812  /* this is the start of a new segment! */
1813  segment_dir = (AF_Direction)point->out_dir;
1814 
1815  error = af_axis_hints_new_segment( axis, memory, &segment );
1816  if ( error )
1817  goto Exit;
1818 
1819  /* clear all segment fields */
1820  segment[0] = seg0;
1821 
1822  segment->dir = (FT_Char)segment_dir;
1823  segment->first = point;
1824  segment->last = point;
1825 
1826  /* `af_axis_hints_new_segment' reallocates memory, */
1827  /* thus we have to refresh the `prev_segment' pointer */
1828  if ( prev_segment )
1829  prev_segment = segment - 1;
1830 
1831  min_pos = max_pos = point->u;
1832  min_coord = max_coord = point->v;
1833  min_flags = max_flags = point->flags;
1834 
1835  if ( point->flags & AF_FLAG_CONTROL )
1836  {
1837  min_on_coord = 32000;
1838  max_on_coord = -32000;
1839  }
1840  else
1841  min_on_coord = max_on_coord = point->v;
1842 
1843  on_edge = 1;
1844 
1845  if ( point == point->prev )
1846  {
1847  /* we have a one-point segment: this is a one-point */
1848  /* contour with `in' and `out' direction set to */
1849  /* AF_DIR_NONE */
1850  segment->pos = (FT_Short)min_pos;
1851 
1852  if (point->flags & AF_FLAG_CONTROL)
1853  segment->flags |= AF_EDGE_ROUND;
1854 
1855  segment->min_coord = (FT_Short)point->v;
1856  segment->max_coord = (FT_Short)point->v;
1857  segment->height = 0;
1858 
1859  on_edge = 0;
1860  segment = NULL;
1861  }
1862  }
1863 
1864  point = point->next;
1865  }
1866 
1867  } /* contours */
1868 
1869 
1870  /* now slightly increase the height of segments if this makes */
1871  /* sense -- this is used to better detect and ignore serifs */
1872  {
1873  AF_Segment segments = axis->segments;
1874  AF_Segment segments_end = segments + axis->num_segments;
1875 
1876 
1877  for ( segment = segments; segment < segments_end; segment++ )
1878  {
1879  AF_Point first = segment->first;
1880  AF_Point last = segment->last;
1881  FT_Pos first_v = first->v;
1882  FT_Pos last_v = last->v;
1883 
1884 
1885  if ( first_v < last_v )
1886  {
1887  AF_Point p;
1888 
1889 
1890  p = first->prev;
1891  if ( p->v < first_v )
1892  segment->height = (FT_Short)( segment->height +
1893  ( ( first_v - p->v ) >> 1 ) );
1894 
1895  p = last->next;
1896  if ( p->v > last_v )
1897  segment->height = (FT_Short)( segment->height +
1898  ( ( p->v - last_v ) >> 1 ) );
1899  }
1900  else
1901  {
1902  AF_Point p;
1903 
1904 
1905  p = first->prev;
1906  if ( p->v > first_v )
1907  segment->height = (FT_Short)( segment->height +
1908  ( ( p->v - first_v ) >> 1 ) );
1909 
1910  p = last->next;
1911  if ( p->v < last_v )
1912  segment->height = (FT_Short)( segment->height +
1913  ( ( last_v - p->v ) >> 1 ) );
1914  }
1915  }
1916  }
1917 
1918  Exit:
1919  return error;
1920  }
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
namespace GUID const ADDRINFOEXW * hints
Definition: sock.c:80
int FT_Error
Definition: fttypes.h:300
#define FLAT_THRESHOLD(x)
Definition: aflatin.c:45
FT_BEGIN_HEADER typedef signed long FT_Pos
Definition: ftimage.h:58
#define error(str)
Definition: mkdosfs.c:1605
GLsizei GLenum const GLvoid GLuint GLsizei GLfloat * metrics
Definition: glext.h:11745
POINT last
Definition: font.c:46
FT_Short min_coord
Definition: afhints.h:264
#define FT_ABS(a)
Definition: ftobjs.h:74
const GLint * first
Definition: glext.h:5794
signed char FT_Char
Definition: fttypes.h:143
FT_Short max_coord
Definition: afhints.h:265
struct AF_LatinMetricsRec_ * AF_LatinMetrics
enum AF_Direction_ AF_Direction
return FT_Err_Ok
Definition: ftbbox.c:511
static char memory[1024 *256]
Definition: process.c:116
POINTL point
Definition: edittest.c:50
FT_Byte flags
Definition: afhints.h:260
GLint limit
Definition: glext.h:10326
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
#define AF_FLAG_CONTROL
FT_Char in_dir
Definition: afhints.h:244
smooth NULL
Definition: ftsmooth.c:416
FT_Short delta
Definition: afhints.h:263
#define FT_ZERO(p)
Definition: ftmemory.h:237
static void Exit(void)
Definition: sock.c:1331
signed short FT_Short
Definition: fttypes.h:198
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
af_axis_hints_new_segment(AF_AxisHints axis, FT_Memory memory, AF_Segment *asegment)
Definition: afhints.c:38
FT_Short height
Definition: afhints.h:266
FT_Short pos
Definition: afhints.h:262
const GLdouble * v
Definition: gl.h:2040
#define AF_FLAG_NONE
#define AF_EDGE_ROUND
GLfloat GLfloat p
Definition: glext.h:8902
unsigned short FT_UShort
Definition: fttypes.h:209
#define AF_EDGE_NORMAL
AF_Point last
Definition: afhints.h:277

Referenced by af_latin_hints_detect_features(), and af_latin_metrics_init_widths().

◆ af_latin_hints_detect_features()

af_latin_hints_detect_features ( AF_GlyphHints  hints,
FT_UInt  width_count,
AF_WidthRec widths,
AF_Dimension  dim 
)

Definition at line 2422 of file aflatin.c.

2426  {
2427  FT_Error error;
2428 
2429 
2431  if ( !error )
2432  {
2433  af_latin_hints_link_segments( hints, width_count, widths, dim );
2434 
2436  }
2437 
2438  return error;
2439  }
namespace GUID const ADDRINFOEXW * hints
Definition: sock.c:80
int FT_Error
Definition: fttypes.h:300
#define error(str)
Definition: mkdosfs.c:1605
af_latin_hints_compute_segments(AF_GlyphHints hints, AF_Dimension dim)
Definition: aflatin.c:1499
af_latin_hints_link_segments(AF_GlyphHints hints, FT_UInt width_count, AF_WidthRec *widths, AF_Dimension dim)
Definition: aflatin.c:1927
af_latin_hints_compute_edges(AF_GlyphHints hints, AF_Dimension dim)
Definition: aflatin.c:2065

Referenced by af_latin_hints_apply().

◆ af_latin_hints_link_segments()

af_latin_hints_link_segments ( AF_GlyphHints  hints,
FT_UInt  width_count,
AF_WidthRec widths,
AF_Dimension  dim 
)

Definition at line 1927 of file aflatin.c.

1931  {
1932  AF_AxisHints axis = &hints->axis[dim];
1933  AF_Segment segments = axis->segments;
1934  AF_Segment segment_limit = segments + axis->num_segments;
1935  FT_Pos len_threshold, len_score, dist_score, max_width;
1936  AF_Segment seg1, seg2;
1937 
1938 
1939  if ( width_count )
1940  max_width = widths[width_count - 1].org;
1941  else
1942  max_width = 0;
1943 
1944  /* a heuristic value to set up a minimum value for overlapping */
1945  len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );
1946  if ( len_threshold == 0 )
1947  len_threshold = 1;
1948 
1949  /* a heuristic value to weight lengths */
1950  len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 );
1951 
1952  /* a heuristic value to weight distances (no call to */
1953  /* AF_LATIN_CONSTANT needed, since we work on multiples */
1954  /* of the stem width) */
1955  dist_score = 3000;
1956 
1957  /* now compare each segment to the others */
1958  for ( seg1 = segments; seg1 < segment_limit; seg1++ )
1959  {
1960  if ( seg1->dir != axis->major_dir )
1961  continue;
1962 
1963  /* search for stems having opposite directions, */
1964  /* with seg1 to the `left' of seg2 */
1965  for ( seg2 = segments; seg2 < segment_limit; seg2++ )
1966  {
1967  FT_Pos pos1 = seg1->pos;
1968  FT_Pos pos2 = seg2->pos;
1969 
1970 
1971  if ( seg1->dir + seg2->dir == 0 && pos2 > pos1 )
1972  {
1973  /* compute distance between the two segments */
1974  FT_Pos min = seg1->min_coord;
1975  FT_Pos max = seg1->max_coord;
1976  FT_Pos len;
1977 
1978 
1979  if ( min < seg2->min_coord )
1980  min = seg2->min_coord;
1981 
1982  if ( max > seg2->max_coord )
1983  max = seg2->max_coord;
1984 
1985  /* compute maximum coordinate difference of the two segments */
1986  /* (this is, how much they overlap) */
1987  len = max - min;
1988  if ( len >= len_threshold )
1989  {
1990  /*
1991  * The score is the sum of two demerits indicating the
1992  * `badness' of a fit, measured along the segments' main axis
1993  * and orthogonal to it, respectively.
1994  *
1995  * o The less overlapping along the main axis, the worse it
1996  * is, causing a larger demerit.
1997  *
1998  * o The nearer the orthogonal distance to a stem width, the
1999  * better it is, causing a smaller demerit. For simplicity,
2000  * however, we only increase the demerit for values that
2001  * exceed the largest stem width.
2002  */
2003 
2004  FT_Pos dist = pos2 - pos1;
2005 
2006  FT_Pos dist_demerit, score;
2007 
2008 
2009  if ( max_width )
2010  {
2011  /* distance demerits are based on multiples of `max_width'; */
2012  /* we scale by 1024 for getting more precision */
2013  FT_Pos delta = ( dist << 10 ) / max_width - ( 1 << 10 );
2014 
2015 
2016  if ( delta > 10000 )
2017  dist_demerit = 32000;
2018  else if ( delta > 0 )
2019  dist_demerit = delta * delta / dist_score;
2020  else
2021  dist_demerit = 0;
2022  }
2023  else
2024  dist_demerit = dist; /* default if no widths available */
2025 
2026  score = dist_demerit + len_score / len;
2027 
2028  /* and we search for the smallest score */
2029  if ( score < seg1->score )
2030  {
2031  seg1->score = score;
2032  seg1->link = seg2;
2033  }
2034 
2035  if ( score < seg2->score )
2036  {
2037  seg2->score = score;
2038  seg2->link = seg1;
2039  }
2040  }
2041  }
2042  }
2043  }
2044 
2045  /* now compute the `serif' segments, cf. explanations in `afhints.h' */
2046  for ( seg1 = segments; seg1 < segment_limit; seg1++ )
2047  {
2048  seg2 = seg1->link;
2049 
2050  if ( seg2 )
2051  {
2052  if ( seg2->link != seg1 )
2053  {
2054  seg1->link = 0;
2055  seg1->serif = seg2->link;
2056  }
2057  }
2058  }
2059  }
namespace GUID const ADDRINFOEXW * hints
Definition: sock.c:80
#define max(a, b)
Definition: svc.c:63
FT_Char dir
Definition: afhints.h:261
FT_BEGIN_HEADER typedef signed long FT_Pos
Definition: ftimage.h:58
FT_Short min_coord
Definition: afhints.h:264
FT_Short max_coord
Definition: afhints.h:265
AF_Segment link
Definition: afhints.h:271
FT_Pos score
Definition: afhints.h:273
AF_Segment segments
Definition: afhints.h:309
AF_Segment serif
Definition: afhints.h:272
GLenum GLsizei len
Definition: glext.h:6722
AF_Direction major_dir
Definition: afhints.h:318
FT_Int num_segments
Definition: afhints.h:307
FT_Short pos
Definition: afhints.h:262
#define AF_LATIN_CONSTANT(metrics, c)
#define min(a, b)
Definition: monoChain.cc:55

Referenced by af_latin_hints_detect_features(), and af_latin_metrics_init_widths().

◆ af_latin_metrics_check_digits()

af_latin_metrics_check_digits ( AF_LatinMetrics  metrics,
FT_Face  face 
)

Definition at line 1054 of file aflatin.c.

1056  {
1057  FT_Bool started = 0, same_width = 1;
1058  FT_Fixed advance = 0, old_advance = 0;
1059 
1060  void* shaper_buf;
1061 
1062  /* in all supported charmaps, digits have character codes 0x30-0x39 */
1063  const char digits[] = "0 1 2 3 4 5 6 7 8 9";
1064  const char* p;
1065 
1066 
1067  p = digits;
1068  shaper_buf = af_shaper_buf_create( face );
1069 
1070  while ( *p )
1071  {
1072  FT_ULong glyph_index;
1073  unsigned int num_idx;
1074 
1075 
1076  /* reject input that maps to more than a single glyph */
1077  p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
1078  if ( num_idx > 1 )
1079  continue;
1080 
1081  glyph_index = af_shaper_get_elem( &metrics->root,
1082  shaper_buf,
1083  0,
1084  &advance,
1085  NULL );
1086  if ( !glyph_index )
1087  continue;
1088 
1089  if ( started )
1090  {
1091  if ( advance != old_advance )
1092  {
1093  same_width = 0;
1094  break;
1095  }
1096  }
1097  else
1098  {
1099  old_advance = advance;
1100  started = 1;
1101  }
1102  }
1103 
1104  af_shaper_buf_destroy( face, shaper_buf );
1105 
1106  metrics->root.digits_have_same_width = same_width;
1107  }
unsigned long FT_ULong
Definition: fttypes.h:253
GLsizei GLenum const GLvoid GLuint GLsizei GLfloat * metrics
Definition: glext.h:11745
const char * af_shaper_get_cluster(const char *p, AF_StyleMetrics metrics, void *buf_, unsigned int *count)
Definition: afshaper.c:617
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
smooth NULL
Definition: ftsmooth.c:416
_STLP_MOVE_TO_STD_NAMESPACE void _STLP_CALL advance(_InputIterator &__i, _Distance __n)
signed long FT_Fixed
Definition: fttypes.h:288
void af_shaper_buf_destroy(FT_Face face, void *buf)
Definition: afshaper.c:606
void * af_shaper_buf_create(FT_Face face)
Definition: afshaper.c:592
GLfloat GLfloat p
Definition: glext.h:8902
static const int digits[]
Definition: decode.c:71
FT_ULong af_shaper_get_elem(AF_StyleMetrics metrics, void *buf_, unsigned int idx, FT_Long *advance, FT_Long *y_offset)
Definition: afshaper.c:653
GLenum GLuint GLint GLenum face
Definition: glext.h:7025

Referenced by af_latin_metrics_init().

◆ af_latin_metrics_init()

af_latin_metrics_init ( AF_LatinMetrics  metrics,
FT_Face  face 
)

Definition at line 1113 of file aflatin.c.

1115  {
1116  FT_CharMap oldmap = face->charmap;
1117 
1118 
1119  metrics->units_per_em = face->units_per_EM;
1120 
1121  if ( !FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
1122  {
1126  }
1127 
1128  FT_Set_Charmap( face, oldmap );
1129  return FT_Err_Ok;
1130  }
GLsizei GLenum const GLvoid GLuint GLsizei GLfloat * metrics
Definition: glext.h:11745
af_latin_metrics_init_widths(AF_LatinMetrics metrics, FT_Face face)
Definition: aflatin.c:61
af_latin_metrics_check_digits(AF_LatinMetrics metrics, FT_Face face)
Definition: aflatin.c:1054
return FT_Err_Ok
Definition: ftbbox.c:511
FT_Select_Charmap(FT_Face face, FT_Encoding encoding)
Definition: ftobjs.c:3457
FT_Set_Charmap(FT_Face face, FT_CharMap charmap)
Definition: ftobjs.c:3499
static void af_latin_metrics_init_blues(AF_LatinMetrics metrics, FT_Face face)
Definition: aflatin.c:332
GLenum GLuint GLint GLenum face
Definition: glext.h:7025

◆ af_latin_metrics_init_widths()

af_latin_metrics_init_widths ( AF_LatinMetrics  metrics,
FT_Face  face 
)

Definition at line 61 of file aflatin.c.

63  {
64  /* scan the array of segments in each direction */
65 #ifdef __REACTOS__
67  if (!hints) return;
68 #else
70 #endif
71 
72 
73  FT_TRACE5(( "\n"
74  "latin standard widths computation (style `%s')\n"
75  "=====================================================\n"
76  "\n",
77  af_style_names[metrics->root.style_class->style] ));
78 
79  af_glyph_hints_init( hints, face->memory );
80 
81  metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
82  metrics->axis[AF_DIMENSION_VERT].width_count = 0;
83 
84  {
86  FT_ULong glyph_index;
87  int dim;
88 #ifdef __REACTOS__
90  if (!dummy)
91  goto Exit;
92  {
93 #else
95 #endif
96  AF_Scaler scaler = &dummy->root.scaler;
97 
98 #ifdef FT_CONFIG_OPTION_PIC
99  AF_FaceGlobals globals = metrics->root.globals;
100 #endif
101 
102  AF_StyleClass style_class = metrics->root.style_class;
104  [style_class->script];
105 
106  void* shaper_buf;
107  const char* p;
108 
109 #ifdef FT_DEBUG_LEVEL_TRACE
110  FT_ULong ch = 0;
111 #endif
112 
113  p = script_class->standard_charstring;
114  shaper_buf = af_shaper_buf_create( face );
115 
116  /*
117  * We check a list of standard characters to catch features like
118  * `c2sc' (small caps from caps) that don't contain lowercase letters
119  * by definition, or other features that mainly operate on numerals.
120  * The first match wins.
121  */
122 
123  glyph_index = 0;
124  while ( *p )
125  {
126  unsigned int num_idx;
127 
128 #ifdef FT_DEBUG_LEVEL_TRACE
129  const char* p_old;
130 #endif
131 
132 
133  while ( *p == ' ' )
134  p++;
135 
136 #ifdef FT_DEBUG_LEVEL_TRACE
137  p_old = p;
138  GET_UTF8_CHAR( ch, p_old );
139 #endif
140 
141  /* reject input that maps to more than a single glyph */
142  p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
143  if ( num_idx > 1 )
144  continue;
145 
146  /* otherwise exit loop if we have a result */
147  glyph_index = af_shaper_get_elem( &metrics->root,
148  shaper_buf,
149  0,
150  NULL,
151  NULL );
152  if ( glyph_index )
153  break;
154  }
155 
156  af_shaper_buf_destroy( face, shaper_buf );
157 
158  if ( !glyph_index )
159  goto Exit;
160 
161  FT_TRACE5(( "standard character: U+%04lX (glyph index %d)\n",
162  ch, glyph_index ));
163 
164  error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
165  if ( error || face->glyph->outline.n_points <= 0 )
166  goto Exit;
167 
168  FT_ZERO( dummy );
169 
170  dummy->units_per_em = metrics->units_per_em;
171 
172  scaler->x_scale = 0x10000L;
173  scaler->y_scale = 0x10000L;
174  scaler->x_delta = 0;
175  scaler->y_delta = 0;
176 
177  scaler->face = face;
179  scaler->flags = 0;
180 
182 
183  error = af_glyph_hints_reload( hints, &face->glyph->outline );
184  if ( error )
185  goto Exit;
186 
187  for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
188  {
189  AF_LatinAxis axis = &metrics->axis[dim];
190  AF_AxisHints axhints = &hints->axis[dim];
192  FT_UInt num_widths = 0;
193 
194 
196  (AF_Dimension)dim );
197  if ( error )
198  goto Exit;
199 
200  /*
201  * We assume that the glyphs selected for the stem width
202  * computation are `featureless' enough so that the linking
203  * algorithm works fine without adjustments of its scoring
204  * function.
205  */
207  0,
208  NULL,
209  (AF_Dimension)dim );
210 
211  seg = axhints->segments;
212  limit = seg + axhints->num_segments;
213 
214  for ( ; seg < limit; seg++ )
215  {
216  link = seg->link;
217 
218  /* we only consider stem segments there! */
219  if ( link && link->link == seg && link > seg )
220  {
221  FT_Pos dist;
222 
223 
224  dist = seg->pos - link->pos;
225  if ( dist < 0 )
226  dist = -dist;
227 
228  if ( num_widths < AF_LATIN_MAX_WIDTHS )
229  axis->widths[num_widths++].org = dist;
230  }
231  }
232 
233  /* this also replaces multiple almost identical stem widths */
234  /* with a single one (the value 100 is heuristic) */
235  af_sort_and_quantize_widths( &num_widths, axis->widths,
236  dummy->units_per_em / 100 );
237  axis->width_count = num_widths;
238  }
239 
240  Exit:
241  for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
242  {
243  AF_LatinAxis axis = &metrics->axis[dim];
244  FT_Pos stdw;
245 
246 
247  stdw = ( axis->width_count > 0 ) ? axis->widths[0].org
248  : AF_LATIN_CONSTANT( metrics, 50 );
249 
250  /* let's try 20% of the smallest width */
251  axis->edge_distance_threshold = stdw / 5;
252  axis->standard_width = stdw;
253  axis->extra_light = 0;
254 
255 #ifdef FT_DEBUG_LEVEL_TRACE
256  {
257  FT_UInt i;
258 
259 
260  FT_TRACE5(( "%s widths:\n",
261  dim == AF_DIMENSION_VERT ? "horizontal"
262  : "vertical" ));
263 
264  FT_TRACE5(( " %d (standard)", axis->standard_width ));
265  for ( i = 1; i < axis->width_count; i++ )
266  FT_TRACE5(( " %d", axis->widths[i].org ));
267 
268  FT_TRACE5(( "\n" ));
269  }
270 #endif
271  }
272 #ifdef __REACTOS__
273  free(dummy);
274  }
275 #endif
276  }
277 
278  FT_TRACE5(( "\n" ));
279 
281 
282 #ifdef __REACTOS__
283  free(hints);
284 #endif
285 
286  }
namespace GUID const ADDRINFOEXW * hints
Definition: sock.c:80
int FT_Error
Definition: fttypes.h:300
AF_Script script
Definition: aftypes.h:450
unsigned long FT_ULong
Definition: fttypes.h:253
af_glyph_hints_done(AF_GlyphHints hints)
Definition: afhints.c:672
FT_BEGIN_HEADER typedef signed long FT_Pos
Definition: ftimage.h:58
#define error(str)
Definition: mkdosfs.c:1605
FT_Pos standard_width
Definition: aflatin.h:96
FT_Face face
Definition: aftypes.h:180
GLsizei GLenum const GLvoid GLuint GLsizei GLfloat * metrics
Definition: glext.h:11745
FT_Bool extra_light
Definition: aflatin.h:97
#define free
Definition: debug_ros.c:5
af_glyph_hints_init(AF_GlyphHints hints, FT_Memory memory)
Definition: afhints.c:662
AF_WidthRec widths[AF_LATIN_MAX_WIDTHS]
Definition: aflatin.h:94
af_latin_hints_compute_segments(AF_GlyphHints hints, AF_Dimension dim)
Definition: aflatin.c:1499
FT_UInt32 flags
Definition: aftypes.h:186
const char * af_shaper_get_cluster(const char *p, AF_StyleMetrics metrics, void *buf_, unsigned int *count)
Definition: afshaper.c:617
af_glyph_hints_reload(AF_GlyphHints hints, FT_Outline *outline)
Definition: afhints.c:732
GLint limit
Definition: glext.h:10326
#define FT_LOAD_NO_SCALE
Definition: freetype.h:3009
af_sort_and_quantize_widths(FT_UInt *count, AF_Width table, FT_Pos threshold)
Definition: afangles.c:210
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
FT_Fixed y_scale
Definition: aftypes.h:182
#define AF_SCRIPT_CLASSES_GET
Definition: afpic.h:32
FT_Load_Glyph(FT_Face face, FT_UInt glyph_index, FT_Int32 load_flags)
Definition: ftobjs.c:760
smooth NULL
Definition: ftsmooth.c:416
af_latin_hints_link_segments(AF_GlyphHints hints, FT_UInt width_count, AF_WidthRec *widths, AF_Dimension dim)
Definition: aflatin.c:1927
#define AF_LATIN_MAX_WIDTHS
af_glyph_hints_rescale(AF_GlyphHints hints, AF_StyleMetrics metrics)
Definition: afhints.c:720
FT_UInt width_count
Definition: aflatin.h:93
#define FT_ZERO(p)
Definition: ftmemory.h:237
static void Exit(void)
Definition: sock.c:1331
AF_Segment segments
Definition: afhints.h:309
WORD face[3]
Definition: mesh.c:4747
FT_Render_Mode render_mode
Definition: aftypes.h:185
#define GET_UTF8_CHAR(ch, p)
Definition: afblue.h:31
FT_Pos x_delta
Definition: aftypes.h:183
static const WCHAR L[]
Definition: oid.c:1250
seg
Definition: i386-dis.c:3857
FT_Int num_segments
Definition: afhints.h:307
FT_Pos edge_distance_threshold
Definition: aflatin.h:95
FT_BEGIN_HEADER enum AF_Dimension_ AF_Dimension
void af_shaper_buf_destroy(FT_Face face, void *buf)
Definition: afshaper.c:606
unsigned int FT_UInt
Definition: fttypes.h:231
#define AF_LATIN_CONSTANT(metrics, c)
#define FT_TRACE5(varformat)
Definition: ftdebug.h:162
FT_Fixed x_scale
Definition: aftypes.h:181
FT_Pos y_delta
Definition: aftypes.h:184
const char * standard_charstring
Definition: aftypes.h:348
#define malloc
Definition: debug_ros.c:4
const WCHAR * link
Definition: db.cpp:989
void * af_shaper_buf_create(FT_Face face)
Definition: afshaper.c:592
GLfloat GLfloat p
Definition: glext.h:8902
FT_ULong af_shaper_get_elem(AF_StyleMetrics metrics, void *buf_, unsigned int idx, FT_Long *advance, FT_Long *y_offset)
Definition: afshaper.c:653
GLenum GLuint GLint GLenum face
Definition: glext.h:7025

Referenced by af_latin_metrics_init().

◆ af_latin_metrics_scale()

af_latin_metrics_scale ( AF_LatinMetrics  metrics,
AF_Scaler  scaler 
)

Definition at line 1459 of file aflatin.c.

1461  {
1462  metrics->root.scaler.render_mode = scaler->render_mode;
1463  metrics->root.scaler.face = scaler->face;
1464  metrics->root.scaler.flags = scaler->flags;
1465 
1468  }
FT_Face face
Definition: aftypes.h:180
GLsizei GLenum const GLvoid GLuint GLsizei GLfloat * metrics
Definition: glext.h:11745
FT_UInt32 flags
Definition: aftypes.h:186
FT_Render_Mode render_mode
Definition: aftypes.h:185
static void af_latin_metrics_scale_dim(AF_LatinMetrics metrics, AF_Scaler scaler, AF_Dimension dim)
Definition: aflatin.c:1137