cleaned up, and it seems a bug was introduced ??? I'll start checking this under Linux, as debugging is a lot easier under this environment..VER-2-0-4-PATCH
parent
6930b45f78
commit
3469d0d038
19 changed files with 5140 additions and 0 deletions
@ -0,0 +1,123 @@ |
||||
The Catharon Open Source LICENSE |
||||
---------------------------- |
||||
|
||||
2000-Jul-4 |
||||
|
||||
Copyright (C) 2000 by Catharon Productions, Inc. |
||||
|
||||
|
||||
|
||||
Introduction |
||||
============ |
||||
|
||||
This license applies to source files distributed by Catharon |
||||
Productions, Inc. in several archive packages. This license |
||||
applies to all files found in such packages which do not fall |
||||
under their own explicit license. |
||||
|
||||
This license was inspired by the BSD, Artistic, and IJG |
||||
(Independent JPEG Group) licenses, which all encourage inclusion |
||||
and use of free software in commercial and freeware products |
||||
alike. As a consequence, its main points are that: |
||||
|
||||
o We don't promise that this software works. However, we are |
||||
interested in any kind of bug reports. (`as is' distribution) |
||||
|
||||
o You can use this software for whatever you want, in parts or |
||||
full form, without having to pay us. (`royalty-free' usage) |
||||
|
||||
o You may not pretend that you wrote this software. If you use |
||||
it, or only parts of it, in a program, you must acknowledge |
||||
somewhere in your documentation that you have used the |
||||
Catharon Code. (`credits') |
||||
|
||||
We specifically permit and encourage the inclusion of this |
||||
software, with or without modifications, in commercial products. |
||||
We disclaim all warranties covering the packages distributed by |
||||
Catharon Productions, Inc. and assume no liability related to |
||||
their use. |
||||
|
||||
|
||||
Legal Terms |
||||
=========== |
||||
|
||||
0. Definitions |
||||
-------------- |
||||
|
||||
Throughout this license, the terms `Catharon Package', `package', |
||||
and `Catharon Code' refer to the set of files originally |
||||
distributed by Catharon Productions, Inc. |
||||
|
||||
`You' refers to the licensee, or person using the project, where |
||||
`using' is a generic term including compiling the project's source |
||||
code as well as linking it to form a `program' or `executable'. |
||||
This program is referred to as `a program using one of the |
||||
Catharon Packages'. |
||||
|
||||
This license applies to all files distributed in the original |
||||
Catharon Package(s), including all source code, binaries and |
||||
documentation, unless otherwise stated in the file in its |
||||
original, unmodified form as distributed in the original archive. |
||||
If you are unsure whether or not a particular file is covered by |
||||
this license, you must contact us to verify this. |
||||
|
||||
The Catharon Packages are copyright (C) 2000 by Catharon |
||||
Productions, Inc. All rights reserved except as specified below. |
||||
|
||||
1. No Warranty |
||||
-------------- |
||||
|
||||
THE CATHARON PACKAGES ARE PROVIDED `AS IS' WITHOUT WARRANTY OF ANY |
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, |
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS |
||||
BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OF OR THE INABILITY TO |
||||
USE THE CATHARON PACKAGE. |
||||
|
||||
2. Redistribution |
||||
----------------- |
||||
|
||||
This license grants a worldwide, royalty-free, perpetual and |
||||
irrevocable right and license to use, execute, perform, compile, |
||||
display, copy, create derivative works of, distribute and |
||||
sublicense the Catharon Packages (in both source and object code |
||||
forms) and derivative works thereof for any purpose; and to |
||||
authorize others to exercise some or all of the rights granted |
||||
herein, subject to the following conditions: |
||||
|
||||
o Redistribution of source code must retain this license file |
||||
(`license.txt') unaltered; any additions, deletions or changes |
||||
to the original files must be clearly indicated in |
||||
accompanying documentation. The copyright notices of the |
||||
unaltered, original files must be preserved in all copies of |
||||
source files. |
||||
|
||||
o Redistribution in binary form must provide a disclaimer that |
||||
states that the software is based in part on the work of |
||||
Catharon Productions, Inc. in the distribution documentation. |
||||
|
||||
These conditions apply to any software derived from or based on |
||||
the Catharon Packages, not just the unmodified files. If you use |
||||
our work, you must acknowledge us. However, no fee need be paid |
||||
to us. |
||||
|
||||
3. Advertising |
||||
-------------- |
||||
|
||||
Neither Catharon Productions, Inc. and contributors nor you shall |
||||
use the name of the other for commercial, advertising, or |
||||
promotional purposes without specific prior written permission. |
||||
|
||||
We suggest, but do not require, that you use the following phrase |
||||
to refer to this software in your documentation: 'this software is |
||||
based in part on the Catharon Typography Project'. |
||||
|
||||
As you have not signed this license, you are not required to |
||||
accept it. However, as the Catharon Packages are copyrighted |
||||
material, only this license, or another one contracted with the |
||||
authors, grants you the right to use, distribute, and modify it. |
||||
Therefore, by using, distributing, or modifying the Catharon |
||||
Packages, you indicate that you understand and accept all the |
||||
terms of this license. |
||||
|
||||
--- end of license.txt --- |
@ -0,0 +1,125 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ahangles.h */ |
||||
/* */ |
||||
/* a routine used to compute vector angles with limited accuracy */ |
||||
/* and very high speed. */ |
||||
/* */ |
||||
/* Copyright 2000: Catharon Productions Inc. */ |
||||
/* Author: David Turner */ |
||||
/* */ |
||||
/* This file is part of the Catharon Typography Project and shall only */ |
||||
/* be used, modified, and distributed under the terms of the Catharon */ |
||||
/* Open Source License that should come with this file under the name */ |
||||
/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ |
||||
/* this file you indicate that you have read the license and */ |
||||
/* understand and accept it fully. */ |
||||
/* */ |
||||
/* Note that this license is compatible with the FreeType license */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
#ifdef FT_FLAT_COMPILE |
||||
#include "ahangles.h" |
||||
#else |
||||
#include <autohint/ahangles.h> |
||||
#endif |
||||
|
||||
/* the following two tables are automatically generated with */ |
||||
/* the "mather.py" Python script.. */ |
||||
|
||||
static const AH_Angle ah_arctan[ 1L << AH_ATAN_BITS ] = |
||||
{ |
||||
0, 0, 1, 1, 1, 2, 2, 2, |
||||
3, 3, 3, 3, 4, 4, 4, 5, |
||||
5, 5, 6, 6, 6, 7, 7, 7, |
||||
8, 8, 8, 9, 9, 9, 10, 10, |
||||
10, 10, 11, 11, 11, 12, 12, 12, |
||||
13, 13, 13, 14, 14, 14, 14, 15, |
||||
15, 15, 16, 16, 16, 17, 17, 17, |
||||
18, 18, 18, 18, 19, 19, 19, 20, |
||||
20, 20, 21, 21, 21, 21, 22, 22, |
||||
22, 23, 23, 23, 24, 24, 24, 24, |
||||
25, 25, 25, 26, 26, 26, 26, 27, |
||||
27, 27, 28, 28, 28, 28, 29, 29, |
||||
29, 30, 30, 30, 30, 31, 31, 31, |
||||
31, 32, 32, 32, 33, 33, 33, 33, |
||||
34, 34, 34, 34, 35, 35, 35, 35, |
||||
36, 36, 36, 36, 37, 37, 37, 38, |
||||
38, 38, 38, 39, 39, 39, 39, 40, |
||||
40, 40, 40, 41, 41, 41, 41, 42, |
||||
42, 42, 42, 42, 43, 43, 43, 43, |
||||
44, 44, 44, 44, 45, 45, 45, 45, |
||||
46, 46, 46, 46, 46, 47, 47, 47, |
||||
47, 48, 48, 48, 48, 48, 49, 49, |
||||
49, 49, 50, 50, 50, 50, 50, 51, |
||||
51, 51, 51, 51, 52, 52, 52, 52, |
||||
52, 53, 53, 53, 53, 53, 54, 54, |
||||
54, 54, 54, 55, 55, 55, 55, 55, |
||||
56, 56, 56, 56, 56, 57, 57, 57, |
||||
57, 57, 57, 58, 58, 58, 58, 58, |
||||
59, 59, 59, 59, 59, 59, 60, 60, |
||||
60, 60, 60, 61, 61, 61, 61, 61, |
||||
61, 62, 62, 62, 62, 62, 62, 63, |
||||
63, 63, 63, 63, 63, 64, 64, 64 |
||||
}; |
||||
|
||||
|
||||
LOCAL_FUNC |
||||
AH_Angle ah_angle( FT_Vector* v ) |
||||
{ |
||||
FT_Pos dx, dy; |
||||
AH_Angle angle; |
||||
|
||||
dx = v->x; |
||||
dy = v->y; |
||||
|
||||
/* check trivial cases */ |
||||
if (dy == 0) |
||||
{ |
||||
angle = 0; |
||||
if (dx < 0) |
||||
angle = AH_PI; |
||||
return angle; |
||||
} |
||||
else if (dx == 0) |
||||
{ |
||||
angle = AH_HALF_PI; |
||||
if (dy < 0) |
||||
angle = -AH_HALF_PI; |
||||
return angle; |
||||
} |
||||
|
||||
angle = 0; |
||||
if ( dx < 0 ) |
||||
{ |
||||
dx = -v->x; |
||||
dy = -v->y; |
||||
angle = AH_PI; |
||||
} |
||||
|
||||
if ( dy < 0 ) |
||||
{ |
||||
FT_Pos tmp; |
||||
tmp = dx; |
||||
dx = -dy; |
||||
dy = tmp; |
||||
angle -= AH_HALF_PI; |
||||
} |
||||
|
||||
if (dx == 0 && dy == 0) |
||||
return 0; |
||||
|
||||
if (dx == dy) |
||||
angle += AH_PI/4; |
||||
else if (dx > dy) |
||||
angle += ah_arctan[ FT_DivFix( dy, dx ) >> (16-AH_ATAN_BITS) ]; |
||||
else |
||||
angle += AH_HALF_PI - ah_arctan[ FT_DivFix( dx, dy ) >> (16-AH_ATAN_BITS) ]; |
||||
|
||||
if (angle > AH_PI) |
||||
angle -= AH_2PI; |
||||
|
||||
return angle; |
||||
} |
||||
|
||||
|
@ -0,0 +1,47 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ahangles.h */ |
||||
/* */ |
||||
/* a routine used to compute vector angles with limited accuracy */ |
||||
/* and very high speed. */ |
||||
/* */ |
||||
/* Copyright 2000: Catharon Productions Inc. */ |
||||
/* Author: David Turner */ |
||||
/* */ |
||||
/* This file is part of the Catharon Typography Project and shall only */ |
||||
/* be used, modified, and distributed under the terms of the Catharon */ |
||||
/* Open Source License that should come with this file under the name */ |
||||
/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ |
||||
/* this file you indicate that you have read the license and */ |
||||
/* understand and accept it fully. */ |
||||
/* */ |
||||
/* Note that this license is compatible with the FreeType license */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
#ifndef AGANGLES_H |
||||
#define AGANGLES_H |
||||
|
||||
#ifdef FT_FLAT_COMPILE |
||||
#include "ahtypes.h" |
||||
#else |
||||
#include <autohint/ahtypes.h> |
||||
#endif |
||||
|
||||
#include <freetype/internal/ftobjs.h> |
||||
|
||||
/* PI expressed in ah_angles - we don't really need an important */ |
||||
/* precision, so 256 should be enough.. */ |
||||
#define AH_PI 256 |
||||
#define AH_2PI (AH_PI*2) |
||||
#define AH_HALF_PI (AH_PI/2) |
||||
#define AH_2PIMASK (AH_2PI-1) |
||||
|
||||
/* the number of bits to use to express an arc tangent */ |
||||
/* see the structure of the lookup table.. */ |
||||
#define AH_ATAN_BITS 8 |
||||
|
||||
LOCAL_DEF const AH_Angle ah_arctan[ 1L << AH_ATAN_BITS ]; |
||||
|
||||
LOCAL_DEF AH_Angle ah_angle( FT_Vector* v ); |
||||
|
||||
#endif /* AGANGLES_H */ |
@ -0,0 +1,365 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ahglobal.c */ |
||||
/* */ |
||||
/* routines used to compute global metrics automatically */ |
||||
/* */ |
||||
/* Copyright 2000: Catharon Productions Inc. */ |
||||
/* Author: David Turner */ |
||||
/* */ |
||||
/* This file is part of the Catharon Typography Project and shall only */ |
||||
/* be used, modified, and distributed under the terms of the Catharon */ |
||||
/* Open Source License that should come with this file under the name */ |
||||
/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ |
||||
/* this file you indicate that you have read the license and */ |
||||
/* understand and accept it fully. */ |
||||
/* */ |
||||
/* Note that this license is compatible with the FreeType license */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
#ifdef FT_FLAT_COMPILE |
||||
#include "ahglobal.h" |
||||
#include "ahglyph.h" |
||||
#else |
||||
#include <autohint/ahglobal.h> |
||||
#include <autohint/ahglyph.h> |
||||
#endif |
||||
|
||||
#define MAX_TEST_CHARACTERS 12 |
||||
|
||||
static const char* blue_chars[ ah_blue_max ] = |
||||
{ |
||||
"THEZOCQS", |
||||
"HEZLOCUS", |
||||
"xzroesc", |
||||
"xzroesc", |
||||
"pqgjy" |
||||
}; |
||||
|
||||
/* simple insertion sort */ |
||||
static |
||||
void sort_values( FT_Int count, FT_Pos* table ) |
||||
{ |
||||
FT_Int i, j, swap; |
||||
|
||||
for ( i = 1; i < count; i++ ) |
||||
{ |
||||
for ( j = i; j > 1; j-- ) |
||||
{ |
||||
if ( table[j] > table[j-1] ) |
||||
break; |
||||
|
||||
swap = table[j]; |
||||
table[j] = table[j-1]; |
||||
table[j-1] = swap; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
static |
||||
FT_Error ah_hinter_compute_blues( AH_Hinter* hinter ) |
||||
{ |
||||
AH_Blue blue; |
||||
AH_Globals* globals = &hinter->globals->design; |
||||
FT_Pos flats [ MAX_TEST_CHARACTERS ]; |
||||
FT_Pos rounds[ MAX_TEST_CHARACTERS ]; |
||||
FT_Int num_flats; |
||||
FT_Int num_rounds; |
||||
|
||||
FT_Face face; |
||||
FT_GlyphSlot glyph; |
||||
FT_Error error; |
||||
FT_CharMap charmap; |
||||
|
||||
face = hinter->face; |
||||
glyph = face->glyph; |
||||
|
||||
/* save current charmap */ |
||||
charmap = face->charmap; |
||||
|
||||
/* do we have a Unicode charmap in there ?? */ |
||||
error = FT_Select_Charmap( face, ft_encoding_unicode ); |
||||
if (error) goto Exit; |
||||
|
||||
/* we compute the blues simply by loading each character from the */ |
||||
/* 'blue_chars[blues]' string, then compute its top-most and bottom-most */ |
||||
/* points */ |
||||
|
||||
AH_LOG(( "blue zones computation\n" )); |
||||
AH_LOG(( "------------------------------------------------\n" )); |
||||
|
||||
for ( blue = (AH_Blue)0; blue < ah_blue_max; blue++ ) |
||||
{ |
||||
const char* p = blue_chars[blue]; |
||||
const char* limit = p + MAX_TEST_CHARACTERS; |
||||
FT_Pos *blue_ref, *blue_shoot; |
||||
|
||||
AH_LOG(( "blue %3d : ", (int)blue )); |
||||
|
||||
num_flats = 0; |
||||
num_rounds = 0; |
||||
for ( ; p < limit; p++ ) |
||||
{ |
||||
FT_UInt glyph_index; |
||||
FT_Vector* extremum; |
||||
FT_Vector* points; |
||||
FT_Vector* point_limit; |
||||
FT_Vector* point; |
||||
FT_Bool round; |
||||
|
||||
/* exit if we reach the end of the string */ |
||||
if (!*p) break; |
||||
|
||||
AH_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 ( AH_IS_TOP_BLUE(blue) ) |
||||
{ |
||||
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; |
||||
} |
||||
|
||||
AH_LOG(( "%5d", (int)extremum->y )); |
||||
|
||||
/* now, see if 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 index = extremum - points; |
||||
FT_Int n; |
||||
FT_Int first = 0; |
||||
FT_Int 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 >= index ) |
||||
{ |
||||
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 = index; |
||||
next = prev; |
||||
|
||||
do |
||||
{ |
||||
if (prev > first) prev--; |
||||
else prev = last; |
||||
|
||||
dist = points[prev].y - extremum->y; |
||||
if ( dist < -5 || dist > 5 ) |
||||
break; |
||||
|
||||
} while (prev != index); |
||||
|
||||
do |
||||
{ |
||||
if (next < last) next++; |
||||
else next = first; |
||||
|
||||
dist = points[next].y - extremum->y; |
||||
if ( dist < -5 || dist > 5 ) |
||||
break; |
||||
|
||||
} while (next != index); |
||||
|
||||
/* now, set the "round" flag depending on the segment's kind */ |
||||
round = FT_CURVE_TAG(glyph->outline.tags[prev]) != FT_Curve_Tag_On || |
||||
FT_CURVE_TAG(glyph->outline.tags[next]) != FT_Curve_Tag_On ; |
||||
|
||||
AH_LOG(( "%c ", round ? 'r' : 'f' )); |
||||
} |
||||
|
||||
if (round) |
||||
rounds[ num_rounds++ ] = extremum->y; |
||||
else |
||||
flats[ num_flats++ ] = extremum->y; |
||||
} |
||||
|
||||
AH_LOG(( "\n" )); |
||||
/* 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 short.. */ |
||||
sort_values( num_rounds, rounds ); |
||||
sort_values( num_flats, flats ); |
||||
|
||||
blue_ref = globals->blue_refs + blue; |
||||
blue_shoot = globals->blue_shoots + blue; |
||||
if ( num_flats == 0 && num_rounds == 0 ) |
||||
{ |
||||
*blue_ref = -10000; |
||||
*blue_shoot = -10000; |
||||
} |
||||
else 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, when 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 = ( shoot > ref ); |
||||
|
||||
if ( AH_IS_TOP_BLUE(blue) ^ over_ref ) |
||||
*blue_shoot = *blue_ref = (shoot+ref)/2; |
||||
} |
||||
AH_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot )); |
||||
} |
||||
|
||||
/* reset original face charmap */ |
||||
FT_Set_Charmap( face, charmap ); |
||||
error = 0; |
||||
|
||||
Exit: |
||||
return error; |
||||
} |
||||
|
||||
|
||||
static |
||||
FT_Error ah_hinter_compute_widths( AH_Hinter* hinter ) |
||||
{ |
||||
/* scan the array of segments in each direction */ |
||||
AH_Outline* outline = hinter->glyph; |
||||
AH_Segment* segments; |
||||
AH_Segment* limit; |
||||
AH_Globals* globals = &hinter->globals->design; |
||||
FT_Pos* widths; |
||||
FT_Int dimension; |
||||
FT_Int* p_num_widths; |
||||
FT_Error error = 0; |
||||
FT_Pos edge_distance_threshold = 32000; |
||||
|
||||
globals->num_widths = 0; |
||||
globals->num_heights = 0; |
||||
|
||||
/* for now, compute the standard width and height from the "o" character */ |
||||
/* I started computing the stem width of the "i" and the stem height of */ |
||||
/* the "-", but it wasn't too good.. Moreover, we now have a single */ |
||||
/* character that gives us standard width and height */ |
||||
{ |
||||
FT_UInt glyph_index; |
||||
|
||||
glyph_index = FT_Get_Char_Index( hinter->face, 'o' ); |
||||
if (glyph_index == 0) return 0; |
||||
|
||||
error = FT_Load_Glyph( hinter->face, glyph_index, FT_LOAD_NO_SCALE ); |
||||
if (error) goto Exit; |
||||
|
||||
error = ah_outline_load( hinter->glyph, hinter->face ); |
||||
if (error) goto Exit; |
||||
|
||||
ah_outline_compute_segments( hinter->glyph ); |
||||
ah_outline_link_segments( hinter->glyph ); |
||||
} |
||||
|
||||
segments = outline->horz_segments; |
||||
limit = segments + outline->num_hsegments; |
||||
widths = globals->heights; |
||||
p_num_widths = &globals->num_heights; |
||||
|
||||
for ( dimension = 1; dimension >= 0; dimension-- ) |
||||
{ |
||||
AH_Segment* seg = segments; |
||||
AH_Segment* link; |
||||
FT_Int num_widths = 0; |
||||
|
||||
for ( ; seg < limit; seg++ ) |
||||
{ |
||||
link = seg->link; |
||||
/* we only consider the stem segments there ! */ |
||||
if (link && link->link == seg && link > seg) |
||||
{ |
||||
FT_Int dist; |
||||
|
||||
dist = seg->pos - link->pos; |
||||
if (dist < 0) dist = -dist; |
||||
|
||||
if ( num_widths < 12 ) |
||||
widths[ num_widths++ ] = dist; |
||||
} |
||||
} |
||||
|
||||
sort_values( num_widths, widths ); |
||||
*p_num_widths = num_widths; |
||||
|
||||
/* we will now try to find the smallest width */ |
||||
if (num_widths > 0 && widths[0] < edge_distance_threshold ) |
||||
edge_distance_threshold = widths[0]; |
||||
|
||||
segments = outline->vert_segments; |
||||
limit = segments + outline->num_vsegments; |
||||
widths = globals->widths; |
||||
p_num_widths = &globals->num_widths; |
||||
|
||||
} |
||||
|
||||
/* 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% */ |
||||
hinter->glyph->edge_distance_threshold = edge_distance_threshold/5; |
||||
|
||||
Exit: |
||||
return error; |
||||
} |
||||
|
||||
|
||||
LOCAL_FUNC |
||||
FT_Error ah_hinter_compute_globals( AH_Hinter* hinter ) |
||||
{ |
||||
return ah_hinter_compute_widths( hinter ) || |
||||
ah_hinter_compute_blues ( hinter ); |
||||
} |
||||
|
@ -0,0 +1,38 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ahglobal.h */ |
||||
/* */ |
||||
/* routines used to compute global metrics automatically */ |
||||
/* */ |
||||
/* Copyright 2000: Catharon Productions Inc. */ |
||||
/* Author: David Turner */ |
||||
/* */ |
||||
/* This file is part of the Catharon Typography Project and shall only */ |
||||
/* be used, modified, and distributed under the terms of the Catharon */ |
||||
/* Open Source License that should come with this file under the name */ |
||||
/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ |
||||
/* this file you indicate that you have read the license and */ |
||||
/* understand and accept it fully. */ |
||||
/* */ |
||||
/* Note that this license is compatible with the FreeType license */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
#ifndef AGGLOBAL_H |
||||
#define AGGLOBAL_H |
||||
|
||||
#ifdef FT_FLAT_COMPILE |
||||
#include "ahtypes.h" |
||||
#else |
||||
#include <autohint/ahtypes.h> |
||||
#endif |
||||
|
||||
#include <freetype/internal/ftobjs.h> /* for LOCAL_DEF/LOCAL_FUNC */ |
||||
|
||||
#define AH_IS_TOP_BLUE(b) ( (b) == ah_blue_capital_top || \ |
||||
(b) == ah_blue_small_top ) |
||||
|
||||
/* compute global metrics automatically */ |
||||
LOCAL_DEF |
||||
FT_Error ah_hinter_compute_globals( AH_Hinter* hinter ); |
||||
|
||||
#endif /* AGGLOBAL_H */ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,79 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ahglyph.h */ |
||||
/* */ |
||||
/* routines used to load and analyze a given glyph before hinting */ |
||||
/* */ |
||||
/* Copyright 2000: Catharon Productions Inc. */ |
||||
/* Author: David Turner */ |
||||
/* */ |
||||
/* This file is part of the Catharon Typography Project and shall only */ |
||||
/* be used, modified, and distributed under the terms of the Catharon */ |
||||
/* Open Source License that should come with this file under the name */ |
||||
/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ |
||||
/* this file you indicate that you have read the license and */ |
||||
/* understand and accept it fully. */ |
||||
/* */ |
||||
/* Note that this license is compatible with the FreeType license */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
#ifndef AGGLYPH_H |
||||
#define AGGLYPH_H |
||||
|
||||
#ifdef FT_FLAT_COMPILE |
||||
#include "ahtypes.h" |
||||
#else |
||||
#include <autohint/ahtypes.h> |
||||
#endif |
||||
|
||||
typedef enum AH_UV_ |
||||
{ |
||||
ah_uv_fxy, |
||||
ah_uv_fyx, |
||||
ah_uv_oxy, |
||||
ah_uv_oyx, |
||||
ah_uv_ox, |
||||
ah_uv_oy, |
||||
ah_uv_yx, |
||||
ah_uv_xy /* should always be last !! */ |
||||
|
||||
} AH_UV; |
||||
|
||||
LOCAL_DEF |
||||
void ah_setup_uv( AH_Outline* outline, |
||||
AH_UV source ); |
||||
|
||||
|
||||
/* AH_Outline functions - they should be typically called in this order */ |
||||
|
||||
LOCAL_DEF |
||||
FT_Error ah_outline_new( FT_Memory memory, AH_Outline* *aoutline ); |
||||
|
||||
LOCAL_DEF |
||||
FT_Error ah_outline_load( AH_Outline* outline, FT_Face face ); |
||||
|
||||
LOCAL_DEF |
||||
void ah_outline_compute_segments( AH_Outline* outline ); |
||||
|
||||
LOCAL_DEF |
||||
void ah_outline_link_segments( AH_Outline* outline ); |
||||
|
||||
LOCAL_DEF |
||||
void ah_outline_detect_features( AH_Outline* outline ); |
||||
|
||||
LOCAL_DEF |
||||
void ah_outline_compute_blue_edges( AH_Outline* outline, |
||||
AH_Face_Globals* globals ); |
||||
|
||||
LOCAL_DEF |
||||
void ah_outline_scale_blue_edges( AH_Outline* outline, |
||||
AH_Face_Globals* globals ); |
||||
|
||||
LOCAL_DEF |
||||
void ah_outline_save( AH_Outline* outline, AH_Loader* loader ); |
||||
|
||||
LOCAL_DEF |
||||
void ah_outline_done( AH_Outline* outline ); |
||||
|
||||
|
||||
#endif /* AGGLYPH_H */ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,65 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ahhint.h */ |
||||
/* */ |
||||
/* Glyph hinter declarations */ |
||||
/* */ |
||||
/* Copyright 2000: Catharon Productions Inc. */ |
||||
/* Author: David Turner */ |
||||
/* */ |
||||
/* This file is part of the Catharon Typography Project and shall only */ |
||||
/* be used, modified, and distributed under the terms of the Catharon */ |
||||
/* Open Source License that should come with this file under the name */ |
||||
/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ |
||||
/* this file you indicate that you have read the license and */ |
||||
/* understand and accept it fully. */ |
||||
/* */ |
||||
/* Note that this license is compatible with the FreeType license */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
#ifndef AGHINT_H |
||||
#define AGHINT_H |
||||
|
||||
#ifdef FT_FLAT_COMPILE |
||||
#include "ahglobal.h" |
||||
#else |
||||
#include <autohint/ahglobal.h> |
||||
#endif |
||||
|
||||
#define AH_HINT_DEFAULT 0 |
||||
#define AH_HINT_NO_ALIGNMENT 1 |
||||
#define AH_HINT_NO_HORZ_EDGES 0x20000 |
||||
#define AH_HINT_NO_VERT_EDGES 0x40000 |
||||
|
||||
|
||||
|
||||
/* create a new empty hinter object */ |
||||
extern |
||||
FT_Error ah_hinter_new( FT_Library library, AH_Hinter* *ahinter ); |
||||
|
||||
/* Load a hinted glyph in the hinter */ |
||||
extern |
||||
FT_Error ah_hinter_load_glyph( AH_Hinter* hinter, |
||||
FT_GlyphSlot slot, |
||||
FT_Size size, |
||||
FT_UInt glyph_index, |
||||
FT_Int load_flags ); |
||||
|
||||
/* finalise a hinter object */ |
||||
extern |
||||
void ah_hinter_done( AH_Hinter* hinter ); |
||||
|
||||
LOCAL_DEF |
||||
void ah_hinter_done_face_globals( AH_Face_Globals* globals ); |
||||
|
||||
extern |
||||
void ah_hinter_get_global_hints( AH_Hinter* hinter, |
||||
FT_Face face, |
||||
void* *global_hints, |
||||
long *global_len ); |
||||
|
||||
extern |
||||
void ah_hinter_done_global_hints( AH_Hinter* hinter, |
||||
void* global_hints ); |
||||
|
||||
#endif /* AGHINT_H */ |
@ -0,0 +1,103 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ahloader.h */ |
||||
/* */ |
||||
/* Glyph loader implementation for the auto-hinting module */ |
||||
/* This defines the AG_GlyphLoader type in two different ways: */ |
||||
/* */ |
||||
/* - when the module is compiled within FreeType 2, the type */ |
||||
/* is simply a typedef to FT_GlyphLoader */ |
||||
/* */ |
||||
/* - when the module is compiled as a standalone object, */ |
||||
/* AG_GlyphLoader has its own implementation.. */ |
||||
/* */ |
||||
/* Copyright 2000: Catharon Productions Inc. */ |
||||
/* Author: David Turner */ |
||||
/* */ |
||||
/* This file is part of the Catharon Typography Project and shall only */ |
||||
/* be used, modified, and distributed under the terms of the Catharon */ |
||||
/* Open Source License that should come with this file under the name */ |
||||
/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ |
||||
/* this file you indicate that you have read the license and */ |
||||
/* understand and accept it fully. */ |
||||
/* */ |
||||
/* Note that this license is compatible with the FreeType license */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
#ifndef AGLOADER_H |
||||
#define AGLOADER_H |
||||
|
||||
#ifdef _STANDALONE_ |
||||
|
||||
typedef struct AH_GlyphLoad_ |
||||
{ |
||||
FT_Outline outline; /* outline */ |
||||
FT_UInt num_subglyphs; /* number of subglyphs */ |
||||
FT_SubGlyph* subglyphs; /* subglyphs */ |
||||
FT_Vector* extra_points; /* extra points table.. */ |
||||
|
||||
} AH_GlyphLoad; |
||||
|
||||
|
||||
struct AH_GlyphLoader_ |
||||
{ |
||||
FT_Memory memory; |
||||
FT_UInt max_points; |
||||
FT_UInt max_contours; |
||||
FT_UInt max_subglyphs; |
||||
FT_Bool use_extra; |
||||
|
||||
AH_GlyphLoad base; |
||||
AH_GlyphLoad current; |
||||
|
||||
void* other; /* for possible future extension ? */ |
||||
|
||||
}; |
||||
|
||||
|
||||
LOCAL_DEF FT_Error AH_GlyphLoader_New( FT_Memory memory, |
||||
AH_GlyphLoader* *aloader ); |
||||
|
||||
LOCAL_DEF FT_Error AH_GlyphLoader_Create_Extra( AH_GlyphLoader* loader ); |
||||
|
||||
LOCAL_DEF void AH_GlyphLoader_Done( AH_GlyphLoader* loader ); |
||||
|
||||
LOCAL_DEF void AH_GlyphLoader_Reset( AH_GlyphLoader* loader ); |
||||
|
||||
LOCAL_DEF void AH_GlyphLoader_Rewind( AH_GlyphLoader* loader ); |
||||
|
||||
LOCAL_DEF FT_Error AH_GlyphLoader_Check_Points( AH_GlyphLoader* loader, |
||||
FT_UInt n_points, |
||||
FT_UInt n_contours ); |
||||
|
||||
LOCAL_DEF FT_Error AH_GlyphLoader_Check_Subglyphs( AH_GlyphLoader* loader, |
||||
FT_UInt n_subs ); |
||||
|
||||
LOCAL_DEF void AH_GlyphLoader_Prepare( AH_GlyphLoader* loader ); |
||||
|
||||
|
||||
LOCAL_DEF void AH_GlyphLoader_Add( AH_GlyphLoader* loader ); |
||||
|
||||
LOCAL_DEF FT_Error AH_GlyphLoader_Copy_Points( AH_GlyphLoader* target, |
||||
FT_GlyphLoader* source ); |
||||
|
||||
#else |
||||
#include <freetype/internal/ftobjs.h> |
||||
|
||||
#define AH_Load FT_GlyphLoad |
||||
#define AH_Loader FT_GlyphLoader |
||||
|
||||
#define ah_loader_new FT_GlyphLoader_New |
||||
#define ah_loader_done FT_GlyphLoader_Done |
||||
#define ah_loader_reset FT_GlyphLoader_Reset |
||||
#define ah_loader_rewind FT_GlyphLoader_Rewind |
||||
#define ah_loader_create_extra FT_GlyphLoader_Create_Extra |
||||
#define ah_loader_check_points FT_GlyphLoader_Check_Points |
||||
#define ah_loader_check_subglyphs FT_GlyphLoader_Check_Subglyphs |
||||
#define ah_loader_prepare FT_GlyphLoader_Prepare |
||||
#define ah_loader_add FT_GlyphLoader_Add |
||||
#define ah_loader_copy_points FT_GlyphLoader_Copy_Points |
||||
|
||||
#endif |
||||
|
||||
#endif /* AGLOADER_H */ |
@ -0,0 +1,111 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ahmodule.c */ |
||||
/* */ |
||||
/* Auto-hinting module implementation */ |
||||
/* */ |
||||
/* Copyright 2000: Catharon Productions Inc. */ |
||||
/* Author: David Turner */ |
||||
/* */ |
||||
/* This file is part of the Catharon Typography Project and shall only */ |
||||
/* be used, modified, and distributed under the terms of the Catharon */ |
||||
/* Open Source License that should come with this file under the name */ |
||||
/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ |
||||
/* this file you indicate that you have read the license and */ |
||||
/* understand and accept it fully. */ |
||||
/* */ |
||||
/* Note that this license is compatible with the FreeType license */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
#include <freetype/ftmodule.h> |
||||
|
||||
#ifdef FT_FLAT_COMPILE |
||||
#include "ahhint.h" |
||||
#else |
||||
#include <autohint/ahhint.h> |
||||
#endif |
||||
|
||||
|
||||
typedef struct FT_AutoHinterRec_ |
||||
{ |
||||
FT_ModuleRec root; |
||||
AH_Hinter* hinter; |
||||
|
||||
} FT_AutoHinterRec; |
||||
|
||||
|
||||
static |
||||
FT_Error ft_autohinter_init( FT_AutoHinter module ) |
||||
{ |
||||
return ah_hinter_new( module->root.library, &module->hinter ); |
||||
} |
||||
|
||||
static |
||||
void ft_autohinter_done( FT_AutoHinter module ) |
||||
{ |
||||
ah_hinter_done( module->hinter ); |
||||
} |
||||
|
||||
static |
||||
FT_Error ft_autohinter_load( FT_AutoHinter module, |
||||
FT_GlyphSlot slot, |
||||
FT_Size size, |
||||
FT_UInt glyph_index, |
||||
FT_ULong load_flags ) |
||||
{ |
||||
return ah_hinter_load_glyph( module->hinter, |
||||
slot, size, glyph_index, load_flags ); |
||||
} |
||||
|
||||
static |
||||
void ft_autohinter_reset( FT_AutoHinter module, |
||||
FT_Face face ) |
||||
{ |
||||
UNUSED(module); |
||||
if (face->autohint.data) |
||||
ah_hinter_done_face_globals( face->autohint.data ); |
||||
} |
||||
|
||||
static |
||||
void ft_autohinter_get_globals( FT_AutoHinter module, |
||||
FT_Face face, |
||||
void* *global_hints, |
||||
long *global_len ) |
||||
{ |
||||
ah_hinter_get_global_hints( module->hinter, face, |
||||
global_hints, global_len ); |
||||
} |
||||
|
||||
|
||||
static |
||||
void ft_autohinter_done_globals( FT_AutoHinter module, |
||||
void* global_hints ) |
||||
{ |
||||
ah_hinter_done_global_hints( module->hinter, global_hints ); |
||||
} |
||||
|
||||
|
||||
static |
||||
const FT_AutoHinter_Interface autohinter_interface = |
||||
{ |
||||
ft_autohinter_reset, |
||||
ft_autohinter_load, |
||||
ft_autohinter_get_globals, |
||||
ft_autohinter_done_globals |
||||
}; |
||||
|
||||
const FT_Module_Class autohint_module_class = |
||||
{ |
||||
ft_module_hinter, |
||||
sizeof( FT_AutoHinterRec ), |
||||
|
||||
"autohinter", |
||||
0x10000, /* version 1.0 of the autohinter */ |
||||
0x20000, /* requires FreeType 2.0 or above */ |
||||
|
||||
(const void*)&autohinter_interface, |
||||
|
||||
(FT_Module_Constructor) ft_autohinter_init, |
||||
(FT_Module_Destructor) ft_autohinter_done, |
||||
(FT_Module_Requester) 0 |
||||
}; |
@ -0,0 +1,27 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ahmodule.h */ |
||||
/* */ |
||||
/* Auto-hinting module declaration */ |
||||
/* */ |
||||
/* Copyright 2000: Catharon Productions Inc. */ |
||||
/* Author: David Turner */ |
||||
/* */ |
||||
/* This file is part of the Catharon Typography Project and shall only */ |
||||
/* be used, modified, and distributed under the terms of the Catharon */ |
||||
/* Open Source License that should come with this file under the name */ |
||||
/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ |
||||
/* this file you indicate that you have read the license and */ |
||||
/* understand and accept it fully. */ |
||||
/* */ |
||||
/* Note that this license is compatible with the FreeType license */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
#ifndef AHMODULE_H |
||||
#define AHMODULE_H |
||||
|
||||
#include <freetype/ftmodule.h> |
||||
|
||||
FT_EXPORT_VAR(const FT_Module_Class) autohint_module_class; |
||||
|
||||
#endif /* AHMODULE_H */ |
@ -0,0 +1,808 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* FreeType Auto-Gridder Outline Optimisation */ |
||||
/* */ |
||||
/* This module is in charge of optimising the outlines produced by the */ |
||||
/* auto-hinter in direct mode. This is required at small pixel sizes in */ |
||||
/* order to ensure coherent spacing, among other things.. */ |
||||
/* */ |
||||
/* The technique used in this module is a simplified simulated annealing. */ |
||||
/* */ |
||||
/* */ |
||||
/* Copyright 2000: Catharon Productions Inc. */ |
||||
/* Author: David Turner */ |
||||
/* */ |
||||
/* This file is part of the Catharon Typography Project and shall only */ |
||||
/* be used, modified, and distributed under the terms of the Catharon */ |
||||
/* Open Source License that should come with this file under the name */ |
||||
/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ |
||||
/* this file you indicate that you have read the license and */ |
||||
/* understand and accept it fully. */ |
||||
/* */ |
||||
/* Note that this license is compatible with the FreeType license */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
#include <freetype/internal/ftobjs.h> /* for ALLOC_ARRAY and FREE */ |
||||
|
||||
#ifdef FT_FLAT_COMPILE |
||||
#include "ahoptim.h" |
||||
#else |
||||
#include <autohint/ahoptim.h> |
||||
#endif |
||||
|
||||
/* define this macro to use brute force optimisation, this is slow, but */ |
||||
/* a good way to perfect the distortion function "by hand" through */ |
||||
/* tweaking.. */ |
||||
#define BRUTE_FORCE |
||||
|
||||
#define xxxDEBUG_OPTIM |
||||
|
||||
#undef LOG |
||||
#ifdef DEBUG_OPTIM |
||||
#define LOG(x) optim_log##x |
||||
#else |
||||
#define LOG(x) |
||||
#endif |
||||
|
||||
#ifdef DEBUG_OPTIM |
||||
#include <stdarg.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#define FLOAT(x) ((float)((x)/64.0)) |
||||
|
||||
static |
||||
void optim_log( const char* fmt, ... ) |
||||
{ |
||||
va_list ap; |
||||
|
||||
|
||||
va_start( ap, fmt ); |
||||
vprintf( fmt, ap ); |
||||
va_end( ap ); |
||||
} |
||||
#endif |
||||
|
||||
|
||||
#ifdef DEBUG_OPTIM |
||||
static |
||||
void AH_Dump_Stems( AH_Optimizer* optimizer ) |
||||
{ |
||||
int n; |
||||
AH_Stem* stem; |
||||
|
||||
stem = optimizer->stems; |
||||
for ( n = 0; n < optimizer->num_stems; n++, stem++ ) |
||||
{ |
||||
LOG(( " %c%2d [%.1f:%.1f]={%.1f:%.1f}=<%1.f..%1.f> force=%.1f speed=%.1f\n", |
||||
optimizer->vertical ? 'V' : 'H', n, |
||||
FLOAT(stem->edge1->opos), FLOAT(stem->edge2->opos), |
||||
FLOAT(stem->edge1->pos), FLOAT(stem->edge2->pos), |
||||
FLOAT(stem->min_pos), FLOAT(stem->max_pos), |
||||
FLOAT(stem->force), FLOAT(stem->velocity) )); |
||||
} |
||||
} |
||||
|
||||
static |
||||
void AH_Dump_Stems2( AH_Optimizer* optimizer ) |
||||
{ |
||||
int n; |
||||
AH_Stem* stem; |
||||
|
||||
stem = optimizer->stems; |
||||
for ( n = 0; n < optimizer->num_stems; n++, stem++ ) |
||||
{ |
||||
LOG(( " %c%2d [%.1f]=<%1.f..%1.f> force=%.1f speed=%.1f\n", |
||||
optimizer->vertical ? 'V' : 'H', n, |
||||
FLOAT(stem->pos), |
||||
FLOAT(stem->min_pos), FLOAT(stem->max_pos), |
||||
FLOAT(stem->force), FLOAT(stem->velocity) )); |
||||
} |
||||
} |
||||
|
||||
static |
||||
void AH_Dump_Springs( AH_Optimizer* optimizer ) |
||||
{ |
||||
int n; |
||||
AH_Spring* spring; |
||||
AH_Stem* stems; |
||||
|
||||
spring = optimizer->springs; |
||||
stems = optimizer->stems; |
||||
LOG(( "%cSprings ", optimizer->vertical ? 'V' : 'H' )); |
||||
for ( n = 0; n < optimizer->num_springs; n++, spring++ ) |
||||
{ |
||||
LOG(( " [%d-%d:%.1f:%1.f:%.1f]", spring->stem1 - stems, spring->stem2 - stems, |
||||
FLOAT(spring->owidth), |
||||
FLOAT(spring->stem2->pos-(spring->stem1->pos+spring->stem1->width)), |
||||
FLOAT(spring->tension) )); |
||||
} |
||||
|
||||
LOG(( "\n" )); |
||||
} |
||||
#endif |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/**** ****/ |
||||
/**** COMPUTE STEMS AND SPRINGS IN AN OUTLINE ****/ |
||||
/**** ****/ |
||||
/**** ****/ |
||||
/**** ****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
static |
||||
int valid_stem_segments( AH_Segment* seg1, AH_Segment* seg2 ) |
||||
{ |
||||
return seg1->serif == 0 && seg2 && seg2->link == seg1 && seg1->pos < seg2->pos && |
||||
seg1->min_coord <= seg2->max_coord && |
||||
seg2->min_coord <= seg1->max_coord; |
||||
} |
||||
|
||||
/* compute all stems in an outline */ |
||||
static |
||||
int optim_compute_stems( AH_Optimizer* optimizer ) |
||||
{ |
||||
AH_Outline* outline = optimizer->outline; |
||||
FT_Fixed scale; |
||||
FT_Memory memory = optimizer->memory; |
||||
FT_Error error = 0; |
||||
FT_Int dimension; |
||||
AH_Edge* edges; |
||||
AH_Edge* edge_limit; |
||||
AH_Stem** p_stems; |
||||
FT_Int* p_num_stems; |
||||
|
||||
edges = outline->horz_edges; |
||||
edge_limit = edges + outline->num_hedges; |
||||
scale = outline->y_scale; |
||||
|
||||
p_stems = &optimizer->horz_stems; |
||||
p_num_stems = &optimizer->num_hstems; |
||||
|
||||
for ( dimension = 1; dimension >= 0; dimension-- ) |
||||
{ |
||||
AH_Stem* stems = 0; |
||||
FT_Int num_stems = 0; |
||||
AH_Edge* edge; |
||||
|
||||
/* first of all, count the number of stems in this direction */ |
||||
for ( edge = edges; edge < edge_limit; edge++ ) |
||||
{ |
||||
AH_Segment* seg = edge->first; |
||||
do |
||||
{ |
||||
if (valid_stem_segments( seg, seg->link )) |
||||
num_stems++; |
||||
|
||||
seg = seg->edge_next; |
||||
|
||||
} while (seg != edge->first); |
||||
} |
||||
|
||||
/* now allocate the stems and build their table */ |
||||
if (num_stems > 0) |
||||
{ |
||||
AH_Stem* stem; |
||||
|
||||
if ( ALLOC_ARRAY( stems, num_stems, AH_Stem ) ) |
||||
goto Exit; |
||||
|
||||
stem = stems; |
||||
for ( edge = edges; edge < edge_limit; edge++ ) |
||||
{ |
||||
AH_Segment* seg = edge->first; |
||||
AH_Segment* seg2; |
||||
do |
||||
{ |
||||
seg2 = seg->link; |
||||
if (valid_stem_segments(seg,seg2)) |
||||
{ |
||||
AH_Edge* edge1 = seg->edge; |
||||
AH_Edge* edge2 = seg2->edge; |
||||
|
||||
stem->edge1 = edge1; |
||||
stem->edge2 = edge2; |
||||
stem->opos = edge1->opos; |
||||
stem->pos = edge1->pos; |
||||
stem->owidth = edge2->opos - edge1->opos; |
||||
stem->width = edge2->pos - edge1->pos; |
||||
|
||||
/* compute min_coord and max_coord */ |
||||
{ |
||||
FT_Pos min_coord = seg->min_coord; |
||||
FT_Pos max_coord = seg->max_coord; |
||||
|
||||
if (seg2->min_coord > min_coord) |
||||
min_coord = seg2->min_coord; |
||||
|
||||
if (seg2->max_coord < max_coord) |
||||
max_coord = seg2->max_coord; |
||||
|
||||
stem->min_coord = min_coord; |
||||
stem->max_coord = max_coord; |
||||
} |
||||
|
||||
/* compute minimum and maximum positions for stem */ |
||||
/* note that the left-most/bottom-most stem has always */ |
||||
/* a fixed position.. */ |
||||
if (stem == stems || edge1->blue_edge || edge2->blue_edge) |
||||
{ |
||||
/* this stem cannot move, it is snapped to a blue edge */ |
||||
stem->min_pos = stem->pos; |
||||
stem->max_pos = stem->pos; |
||||
} |
||||
else |
||||
{ |
||||
/* this edge can move, compute its min and max positions */ |
||||
FT_Pos pos1 = stem->opos; |
||||
FT_Pos pos2 = pos1 + stem->owidth - stem->width; |
||||
FT_Pos min1 = (pos1 & -64); |
||||
FT_Pos min2 = (pos2 & -64); |
||||
|
||||
stem->min_pos = min1; |
||||
stem->max_pos = min1+64; |
||||
if (min2 < min1) |
||||
stem->min_pos = min2; |
||||
else |
||||
stem->max_pos = min2+64; |
||||
|
||||
/* XXX : just to see what it does */ |
||||
stem->max_pos += 64; |
||||
|
||||
/* just for the case where direct hinting did some incredible */ |
||||
/* things (e.g. blue edge shifts..) */ |
||||
if (stem->min_pos > stem->pos) |
||||
stem->min_pos = stem->pos; |
||||
|
||||
if (stem->max_pos < stem->pos) |
||||
stem->max_pos = stem->pos; |
||||
} |
||||
|
||||
stem->velocity = 0; |
||||
stem->force = 0; |
||||
|
||||
stem++; |
||||
} |
||||
seg = seg->edge_next; |
||||
} |
||||
while (seg != edge->first); |
||||
} |
||||
} |
||||
|
||||
*p_stems = stems; |
||||
*p_num_stems = num_stems; |
||||
|
||||
edges = outline->vert_edges; |
||||
edge_limit = edges + outline->num_vedges; |
||||
scale = outline->x_scale; |
||||
|
||||
p_stems = &optimizer->vert_stems; |
||||
p_num_stems = &optimizer->num_vstems; |
||||
} |
||||
Exit: |
||||
#ifdef DEBUG_OPTIM |
||||
AH_Dump_Stems(optimizer); |
||||
#endif |
||||
return error; |
||||
} |
||||
|
||||
|
||||
/* returns the spring area between two stems, 0 if none */ |
||||
static |
||||
FT_Pos stem_spring_area( AH_Stem* stem1, AH_Stem* stem2 ) |
||||
{ |
||||
FT_Pos area1 = stem1->max_coord - stem1->min_coord; |
||||
FT_Pos area2 = stem2->max_coord - stem2->min_coord; |
||||
FT_Pos min = stem1->min_coord; |
||||
FT_Pos max = stem1->max_coord; |
||||
FT_Pos area; |
||||
|
||||
/* order stems */ |
||||
if (stem2->opos <= stem1->opos + stem1->owidth) |
||||
return 0; |
||||
|
||||
if (min < stem2->min_coord) |
||||
min = stem2->min_coord; |
||||
|
||||
if (max < stem2->max_coord) |
||||
max = stem2->max_coord; |
||||
|
||||
area = (max-min); |
||||
if ( 2*area < area1 && 2*area < area2 ) |
||||
area = 0; |
||||
|
||||
return area; |
||||
} |
||||
|
||||
|
||||
/* compute all springs in an outline */ |
||||
static |
||||
int optim_compute_springs( AH_Optimizer* optimizer ) |
||||
{ |
||||
/* basically, a spring exists between two stems if most of their */ |
||||
/* surface is aligned.. */ |
||||
FT_Memory memory = optimizer->memory; |
||||
|
||||
AH_Stem* stems; |
||||
AH_Stem* stem_limit; |
||||
AH_Stem* stem; |
||||
int dimension; |
||||
int error = 0; |
||||
|
||||
FT_Int* p_num_springs; |
||||
AH_Spring** p_springs; |
||||
|
||||
stems = optimizer->horz_stems; |
||||
stem_limit = stems + optimizer->num_hstems; |
||||
|
||||
p_springs = &optimizer->horz_springs; |
||||
p_num_springs = &optimizer->num_hsprings; |
||||
|
||||
for ( dimension = 1; dimension >= 0; dimension-- ) |
||||
{ |
||||
FT_Int num_springs = 0; |
||||
AH_Spring* springs = 0; |
||||
|
||||
/* first of all, count stem springs */ |
||||
for ( stem = stems; stem+1 < stem_limit; stem++ ) |
||||
{ |
||||
AH_Stem* stem2; |
||||
for ( stem2 = stem+1; stem2 < stem_limit; stem2++ ) |
||||
if (stem_spring_area(stem,stem2)) |
||||
num_springs++; |
||||
} |
||||
|
||||
/* then allocate and build the springs table */ |
||||
if (num_springs > 0) |
||||
{ |
||||
AH_Spring* spring; |
||||
|
||||
/* allocate table of springs */ |
||||
if ( ALLOC_ARRAY( springs, num_springs, AH_Spring ) ) |
||||
goto Exit; |
||||
|
||||
/* fill the springs table */ |
||||
spring = springs; |
||||
for ( stem = stems; stem+1 < stem_limit; stem++ ) |
||||
{ |
||||
AH_Stem* stem2; |
||||
FT_Pos area; |
||||
|
||||
for ( stem2 = stem+1; stem2 < stem_limit; stem2++ ) |
||||
{ |
||||
area = stem_spring_area(stem,stem2); |
||||
if (area) |
||||
{ |
||||
/* add a new spring here */ |
||||
spring->stem1 = stem; |
||||
spring->stem2 = stem2; |
||||
spring->owidth = stem2->opos - (stem->opos + stem->owidth); |
||||
spring->tension = 0; |
||||
|
||||
spring++; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
*p_num_springs = num_springs; |
||||
*p_springs = springs; |
||||
|
||||
stems = optimizer->vert_stems; |
||||
stem_limit = stems + optimizer->num_vstems; |
||||
|
||||
p_springs = &optimizer->vert_springs; |
||||
p_num_springs = &optimizer->num_vsprings; |
||||
} |
||||
|
||||
Exit: |
||||
#ifdef DEBUG_OPTIM |
||||
AH_Dump_Springs(optimizer); |
||||
#endif |
||||
return error; |
||||
} |
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/**** ****/ |
||||
/**** OPTIMISE THROUGH MY STRANGE SIMULATED ANNEALING ALGO ;-) ****/ |
||||
/**** ****/ |
||||
/**** ****/ |
||||
/**** ****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
#ifndef BRUTE_FORCE |
||||
/* compute all spring tensions */ |
||||
static |
||||
void optim_compute_tensions( AH_Optimizer* optimizer ) |
||||
{ |
||||
AH_Spring* spring = optimizer->springs; |
||||
AH_Spring* limit = spring + optimizer->num_springs; |
||||
for ( ; spring < limit; spring++ ) |
||||
{ |
||||
AH_Stem* stem1 = spring->stem1; |
||||
AH_Stem* stem2 = spring->stem2; |
||||
FT_Int status; |
||||
|
||||
FT_Pos width; |
||||
FT_Pos tension; |
||||
FT_Pos sign; |
||||
|
||||
/* compute the tension, it simply is -K*(new_width-old_width) */ |
||||
width = stem2->pos - (stem1->pos + stem1->width); |
||||
tension = width - spring->owidth; |
||||
|
||||
sign = 1; |
||||
if (tension < 0) |
||||
{ |
||||
sign = -1; |
||||
tension = -tension; |
||||
} |
||||
|
||||
if (width <= 0) |
||||
tension = 32000; |
||||
else |
||||
tension = (tension << 10)/width; |
||||
|
||||
tension = -sign*FT_MulFix( tension, optimizer->tension_scale ); |
||||
spring->tension = tension; |
||||
|
||||
/* now, distribute tension among the englobing stems, if they */ |
||||
/* are able to move.. */ |
||||
status = 0; |
||||
if (stem1->pos <= stem1->min_pos) |
||||
status |= 1; |
||||
if (stem2->pos >= stem2->max_pos) |
||||
status |= 2; |
||||
|
||||
if (!status) |
||||
tension /= 2; |
||||
|
||||
if ((status & 1)== 0) |
||||
stem1->force -= tension; |
||||
|
||||
if ((status & 2)== 0) |
||||
stem2->force += tension; |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
/* compute all stem movements - returns 0 if nothing moved */ |
||||
static |
||||
int optim_compute_stem_movements( AH_Optimizer* optimizer ) |
||||
{ |
||||
AH_Stem* stems = optimizer->stems; |
||||
AH_Stem* limit = stems + optimizer->num_stems; |
||||
AH_Stem* stem = stems; |
||||
int moved = 0; |
||||
|
||||
/* set initial forces to velocity */ |
||||
for ( stem = stems; stem < limit; stem++ ) |
||||
{ |
||||
stem->force = stem->velocity; |
||||
stem->velocity /= 2; /* XXXX: Heuristics */ |
||||
} |
||||
|
||||
/* compute the sum of forces applied on each stem */ |
||||
optim_compute_tensions( optimizer ); |
||||
#ifdef DEBUG_OPTIM |
||||
AH_Dump_Springs( optimizer ); |
||||
AH_Dump_Stems2( optimizer ); |
||||
#endif |
||||
|
||||
/* now, see if something can move ? */ |
||||
for ( stem = stems; stem < limit; stem++ ) |
||||
{ |
||||
if (stem->force > optimizer->tension_threshold) |
||||
{ |
||||
/* there is enough tension to move the stem to the right */ |
||||
if (stem->pos < stem->max_pos) |
||||
{ |
||||
stem->pos += 64; |
||||
stem->velocity = stem->force/2; |
||||
moved = 1; |
||||
} |
||||
else |
||||
stem->velocity = 0; |
||||
} |
||||
else if (stem->force < optimizer->tension_threshold) |
||||
{ |
||||
/* there is enough tension to move the stem to the left */ |
||||
if (stem->pos > stem->min_pos) |
||||
{ |
||||
stem->pos -= 64; |
||||
stem->velocity = stem->force/2; |
||||
moved = 1; |
||||
} |
||||
else |
||||
stem->velocity = 0; |
||||
} |
||||
} |
||||
/* return 0 if nothing moved */ |
||||
return moved; |
||||
} |
||||
|
||||
#endif /* BRUTE_FORCE */ |
||||
|
||||
|
||||
/* compute current global distortion from springs */ |
||||
static |
||||
FT_Pos optim_compute_distorsion( AH_Optimizer* optimizer ) |
||||
{ |
||||
AH_Spring* spring = optimizer->springs; |
||||
AH_Spring* limit = spring + optimizer->num_springs; |
||||
FT_Pos distorsion = 0; |
||||
|
||||
for ( ; spring < limit; spring++ ) |
||||
{ |
||||
AH_Stem* stem1 = spring->stem1; |
||||
AH_Stem* stem2 = spring->stem2; |
||||
FT_Pos width; |
||||
|
||||
width = stem2->pos - (stem1->pos + stem1->width); |
||||
width -= spring->owidth; |
||||
if (width < 0) |
||||
width = -width; |
||||
|
||||
distorsion += width; |
||||
} |
||||
return distorsion; |
||||
} |
||||
|
||||
|
||||
/* record stems configuration in "best of" history */ |
||||
static |
||||
void optim_record_configuration( AH_Optimizer* optimizer ) |
||||
{ |
||||
FT_Pos distorsion; |
||||
AH_Configuration* configs = optimizer->configs; |
||||
AH_Configuration* limit = configs + optimizer->num_configs; |
||||
AH_Configuration* config; |
||||
|
||||
distorsion = optim_compute_distorsion( optimizer ); |
||||
LOG(( "config distorsion = %.1f ", FLOAT(distorsion*64) )); |
||||
|
||||
/* check that we really need to add this configuration to our */ |
||||
/* sorted history.. */ |
||||
if ( limit > configs && limit[-1].distorsion < distorsion ) |
||||
{ |
||||
LOG(( "ejected\n" )); |
||||
return; |
||||
} |
||||
|
||||
/* add new configuration at the end of the table */ |
||||
{ |
||||
int n; |
||||
|
||||
config = limit; |
||||
if (optimizer->num_configs < AH_MAX_CONFIGS) |
||||
optimizer->num_configs++; |
||||
else |
||||
config--; |
||||
|
||||
config->distorsion = distorsion; |
||||
|
||||
for ( n = 0; n < optimizer->num_stems; n++ ) |
||||
config->positions[n] = optimizer->stems[n].pos; |
||||
} |
||||
|
||||
/* move the current configuration towards the front of the list */ |
||||
/* when necessary, yes this is slow bubble sort ;-) */ |
||||
while ( config > configs && config[0].distorsion < config[-1].distorsion ) |
||||
{ |
||||
AH_Configuration temp; |
||||
config--; |
||||
temp = config[0]; |
||||
config[0] = config[1]; |
||||
config[1] = temp; |
||||
} |
||||
LOG(( "recorded !!\n" )); |
||||
} |
||||
|
||||
|
||||
#ifdef BRUTE_FORCE |
||||
/* optimize outline in a single direction */ |
||||
static |
||||
void optim_compute( AH_Optimizer* optimizer ) |
||||
{ |
||||
int n; |
||||
FT_Bool moved; |
||||
|
||||
|
||||
AH_Stem* stem = optimizer->stems; |
||||
AH_Stem* limit = stem + optimizer->num_stems; |
||||
|
||||
/* empty, exit */ |
||||
if (stem >= limit) |
||||
return; |
||||
|
||||
optimizer->num_configs = 0; |
||||
|
||||
stem = optimizer->stems; |
||||
for ( ; stem < limit; stem++ ) |
||||
stem->pos = stem->min_pos; |
||||
|
||||
do |
||||
{ |
||||
/* record current configuration */ |
||||
optim_record_configuration(optimizer); |
||||
|
||||
/* now change configuration */ |
||||
moved = 0; |
||||
for ( stem = optimizer->stems; stem < limit; stem++ ) |
||||
{ |
||||
if (stem->pos < stem->max_pos) |
||||
{ |
||||
stem->pos += 64; |
||||
moved = 1; |
||||
break; |
||||
} |
||||
|
||||
stem->pos = stem->min_pos; |
||||
} |
||||
} |
||||
while (moved); |
||||
|
||||
/* now, set the best stem positions */ |
||||
for ( n = 0; n < optimizer->num_stems; n++ ) |
||||
{ |
||||
AH_Stem* stem = optimizer->stems + n; |
||||
FT_Pos pos = optimizer->configs[0].positions[n]; |
||||
|
||||
stem->edge1->pos = pos; |
||||
stem->edge2->pos = pos + stem->width; |
||||
|
||||
stem->edge1->flags |= ah_edge_done; |
||||
stem->edge2->flags |= ah_edge_done; |
||||
} |
||||
} |
||||
#else |
||||
/* optimize outline in a single direction */ |
||||
static |
||||
void optim_compute( AH_Optimizer* optimizer ) |
||||
{ |
||||
int n, counter, counter2; |
||||
|
||||
optimizer->num_configs = 0; |
||||
optimizer->tension_scale = 0x80000L; |
||||
optimizer->tension_threshold = 64; |
||||
|
||||
/* record initial configuration threshold */ |
||||
optim_record_configuration(optimizer); |
||||
counter = 0; |
||||
for ( counter2 = optimizer->num_stems*8; counter2 >= 0; counter2-- ) |
||||
{ |
||||
if (counter == 0) |
||||
counter = 2*optimizer->num_stems; |
||||
|
||||
if (!optim_compute_stem_movements( optimizer )) |
||||
break; |
||||
|
||||
optim_record_configuration(optimizer); |
||||
counter--; |
||||
if (counter == 0) |
||||
optimizer->tension_scale /= 2; |
||||
} |
||||
|
||||
/* now, set the best stem positions */ |
||||
for ( n = 0; n < optimizer->num_stems; n++ ) |
||||
{ |
||||
AH_Stem* stem = optimizer->stems + n; |
||||
FT_Pos pos = optimizer->configs[0].positions[n]; |
||||
|
||||
stem->edge1->pos = pos; |
||||
stem->edge2->pos = pos + stem->width; |
||||
|
||||
stem->edge1->flags |= ah_edge_done; |
||||
stem->edge2->flags |= ah_edge_done; |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/**** ****/ |
||||
/**** HIGH-LEVEL OPTIMIZER API ****/ |
||||
/**** ****/ |
||||
/**** ****/ |
||||
/**** ****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
/* releases the optimisation data */ |
||||
void AH_Optimizer_Done( AH_Optimizer* optimizer ) |
||||
{ |
||||
if (optimizer) |
||||
{ |
||||
FT_Memory memory = optimizer->memory; |
||||
FREE( optimizer->horz_stems ); |
||||
FREE( optimizer->vert_stems ); |
||||
FREE( optimizer->horz_springs ); |
||||
FREE( optimizer->vert_springs ); |
||||
FREE( optimizer->positions ); |
||||
} |
||||
} |
||||
|
||||
/* loads the outline into the optimizer */ |
||||
int AH_Optimizer_Init( AH_Optimizer* optimizer, |
||||
AH_Outline* outline, |
||||
FT_Memory memory ) |
||||
{ |
||||
FT_Error error; |
||||
|
||||
MEM_Set( optimizer, 0, sizeof(*optimizer)); |
||||
optimizer->outline = outline; |
||||
optimizer->memory = memory; |
||||
|
||||
LOG(( "initializing new optimizer\n" )); |
||||
/* compute stems and springs */ |
||||
error = optim_compute_stems ( optimizer ) || |
||||
optim_compute_springs( optimizer ); |
||||
if (error) goto Fail; |
||||
|
||||
/* allocate stem positions history and configurations */ |
||||
{ |
||||
int n, max_stems; |
||||
|
||||
max_stems = optimizer->num_hstems; |
||||
if (max_stems < optimizer->num_vstems) |
||||
max_stems = optimizer->num_vstems; |
||||
|
||||
if ( ALLOC_ARRAY( optimizer->positions, max_stems*AH_MAX_CONFIGS, FT_Pos ) ) |
||||
goto Fail; |
||||
|
||||
optimizer->num_configs = 0; |
||||
for ( n = 0; n < AH_MAX_CONFIGS; n++ ) |
||||
optimizer->configs[n].positions = optimizer->positions + n*max_stems; |
||||
} |
||||
|
||||
return error; |
||||
|
||||
Fail: |
||||
AH_Optimizer_Done( optimizer ); |
||||
return error; |
||||
} |
||||
|
||||
|
||||
/* compute optimal outline */ |
||||
void AH_Optimizer_Compute( AH_Optimizer* optimizer ) |
||||
{ |
||||
optimizer->num_stems = optimizer->num_hstems; |
||||
optimizer->stems = optimizer->horz_stems; |
||||
optimizer->num_springs = optimizer->num_hsprings; |
||||
optimizer->springs = optimizer->horz_springs; |
||||
|
||||
if (optimizer->num_springs > 0) |
||||
{ |
||||
LOG(( "horizontal optimisation ------------------------\n" )); |
||||
optim_compute( optimizer ); |
||||
} |
||||
|
||||
optimizer->num_stems = optimizer->num_vstems; |
||||
optimizer->stems = optimizer->vert_stems; |
||||
optimizer->num_springs = optimizer->num_vsprings; |
||||
optimizer->springs = optimizer->vert_springs; |
||||
|
||||
if (optimizer->num_springs) |
||||
{ |
||||
LOG(( "vertical optimisation --------------------------\n" )); |
||||
optim_compute( optimizer ); |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,137 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* FreeType Auto-Gridder Outline Optimisation */ |
||||
/* */ |
||||
/* This module is in charge of optimising the outlines produced by the */ |
||||
/* auto-hinter in direct mode. This is required at small pixel sizes in */ |
||||
/* order to ensure coherent spacing, among other things.. */ |
||||
/* */ |
||||
/* The technique used in this module is a simplified simulated annealing. */ |
||||
/* */ |
||||
/* Copyright 2000: Catharon Productions Inc. */ |
||||
/* Author: David Turner */ |
||||
/* */ |
||||
/* This file is part of the Catharon Typography Project and shall only */ |
||||
/* be used, modified, and distributed under the terms of the Catharon */ |
||||
/* Open Source License that should come with this file under the name */ |
||||
/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ |
||||
/* this file you indicate that you have read the license and */ |
||||
/* understand and accept it fully. */ |
||||
/* */ |
||||
/* Note that this license is compatible with the FreeType license */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
#ifndef AGOPTIM_H |
||||
#define AGOPTIM_H |
||||
|
||||
#ifdef FT_FLAT_COMPILE |
||||
#include "ahtypes.h" |
||||
#else |
||||
#include <autohint/ahtypes.h> |
||||
#endif |
||||
|
||||
/* the maximal number of stem configurations to record during optimisation */ |
||||
#define AH_MAX_CONFIGS 8 |
||||
|
||||
|
||||
typedef struct AH_Stem_ |
||||
{ |
||||
FT_Pos pos; /* current position */ |
||||
FT_Pos velocity; /* current velocity */ |
||||
FT_Pos force; /* sum of current forces */ |
||||
FT_Pos width; /* normalized width */ |
||||
|
||||
FT_Pos min_pos; /* minimum grid position */ |
||||
FT_Pos max_pos; /* maximum grid position */ |
||||
|
||||
AH_Edge* edge1; /* left/bottom edge */ |
||||
AH_Edge* edge2; /* right/top edge */ |
||||
|
||||
FT_Pos opos; /* original position */ |
||||
FT_Pos owidth; /* original width */ |
||||
|
||||
FT_Pos min_coord; /* minimum coordinate */ |
||||
FT_Pos max_coord; /* maximum coordinate */ |
||||
|
||||
} AH_Stem; |
||||
|
||||
|
||||
/* A spring between two stems */ |
||||
typedef struct AH_Spring_ |
||||
{ |
||||
AH_Stem* stem1; |
||||
AH_Stem* stem2; |
||||
FT_Pos owidth; /* original width */ |
||||
FT_Pos tension; /* current tension */ |
||||
|
||||
} AH_Spring; |
||||
|
||||
|
||||
/* A configuration records the position of each stem at a given time */ |
||||
/* as well as the associated distortion.. */ |
||||
typedef struct AH_Configuration_ |
||||
{ |
||||
FT_Pos* positions; |
||||
FT_Long distorsion; |
||||
|
||||
} AH_Configuration; |
||||
|
||||
|
||||
|
||||
|
||||
typedef struct AH_Optimizer_ |
||||
{ |
||||
FT_Memory memory; |
||||
AH_Outline* outline; |
||||
|
||||
FT_Int num_hstems; |
||||
AH_Stem* horz_stems; |
||||
|
||||
FT_Int num_vstems; |
||||
AH_Stem* vert_stems; |
||||
|
||||
FT_Int num_hsprings; |
||||
FT_Int num_vsprings; |
||||
AH_Spring* horz_springs; |
||||
AH_Spring* vert_springs; |
||||
|
||||
FT_Int num_configs; |
||||
AH_Configuration configs[ AH_MAX_CONFIGS ]; |
||||
FT_Pos* positions; |
||||
|
||||
/* during each pass, use these instead */ |
||||
FT_Int num_stems; |
||||
AH_Stem* stems; |
||||
|
||||
FT_Int num_springs; |
||||
AH_Spring* springs; |
||||
FT_Bool vertical; |
||||
|
||||
FT_Fixed tension_scale; |
||||
FT_Pos tension_threshold; |
||||
|
||||
} AH_Optimizer; |
||||
|
||||
|
||||
/* loads the outline into the optimizer */ |
||||
extern |
||||
int AH_Optimizer_Init( AH_Optimizer* optimizer, |
||||
AH_Outline* outline, |
||||
FT_Memory memory ); |
||||
|
||||
|
||||
|
||||
/* compute optimal outline */ |
||||
extern |
||||
void AH_Optimizer_Compute( AH_Optimizer* optimizer ); |
||||
|
||||
|
||||
|
||||
|
||||
/* releases the optimisation data */ |
||||
extern |
||||
void AH_Optimizer_Done( AH_Optimizer* optimizer ); |
||||
|
||||
|
||||
#endif /* AGOPTIM_H */ |
@ -0,0 +1,440 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ahtypes.h */ |
||||
/* */ |
||||
/* General types and definitions for the auto-hint module */ |
||||
/* */ |
||||
/* Copyright 2000: Catharon Productions Inc. */ |
||||
/* Author: David Turner */ |
||||
/* */ |
||||
/* This file is part of the Catharon Typography Project and shall only */ |
||||
/* be used, modified, and distributed under the terms of the Catharon */ |
||||
/* Open Source License that should come with this file under the name */ |
||||
/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ |
||||
/* this file you indicate that you have read the license and */ |
||||
/* understand and accept it fully. */ |
||||
/* */ |
||||
/* Note that this license is compatible with the FreeType license */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
#ifndef AGTYPES_H |
||||
#define AGTYPES_H |
||||
|
||||
#include <freetype/internal/ftobjs.h> /* for freetype.h + LOCAL_DEF etc.. */ |
||||
|
||||
#ifdef FT_FLAT_COMPILE |
||||
#include "ahloader.h" /* glyph loader types & declarations */ |
||||
#else |
||||
#include <autohint/ahloader.h> /* glyph loader types & declarations */ |
||||
#endif |
||||
|
||||
#define xxDEBUG_AG |
||||
|
||||
#ifdef DEBUG_AG |
||||
#include <stdio.h> |
||||
#define AH_LOG(x) printf##x |
||||
#else |
||||
#define AH_LOG(x) /* nothing */ |
||||
#endif |
||||
|
||||
|
||||
/***************************************************************************/ |
||||
/***************************************************************************/ |
||||
/***************************************************************************/ |
||||
/**** ****/ |
||||
/**** COMPILE-TIME BUILD OPTIONS ****/ |
||||
/**** ****/ |
||||
/**** Toggle these configuration macros to experiment with ****/ |
||||
/**** "features" of the auto-hinter.. ****/ |
||||
/**** ****/ |
||||
/***************************************************************************/ |
||||
/***************************************************************************/ |
||||
/***************************************************************************/ |
||||
|
||||
/* if this option is defined, only strong interpolation will be used to */ |
||||
/* place the points between edges. Otherwise, "smooth" points are detected */ |
||||
/* and later hinted through weak interpolation to correct some unpleasant */ |
||||
/* artefacts.. */ |
||||
/* */ |
||||
#undef AH_OPTION_NO_WEAK_INTERPOLATION |
||||
#undef AH_OPTION_NO_STRONG_INTERPOLATION |
||||
|
||||
/* undefine this macro if you don't want to hint the metrics */ |
||||
/* there is no reason to do this, except for experimentation */ |
||||
#define AH_HINT_METRICS |
||||
|
||||
/* define this macro if you do not want to insert extra edges at a glyph's */ |
||||
/* x and y extrema (when there isn't one already available). This help */ |
||||
/* reduce a number of artefacts and allow hinting of metrics.. */ |
||||
/* */ |
||||
#undef AH_OPTION_NO_EXTREMUM_EDGES |
||||
|
||||
/* don't touch for now.. */ |
||||
#define AH_MAX_WIDTHS 12 |
||||
#define AH_MAX_HEIGHTS 12 |
||||
|
||||
/***************************************************************************/ |
||||
/***************************************************************************/ |
||||
/***************************************************************************/ |
||||
/**** ****/ |
||||
/**** TYPES DEFINITIONS ****/ |
||||
/**** ****/ |
||||
/***************************************************************************/ |
||||
/***************************************************************************/ |
||||
/***************************************************************************/ |
||||
|
||||
/* see agangles.h */ |
||||
typedef FT_Int AH_Angle; |
||||
|
||||
|
||||
/* hint flags */ |
||||
typedef enum AH_Flags_ |
||||
{ |
||||
ah_flah_none = 0, |
||||
|
||||
/* bezier control points flags */ |
||||
ah_flah_conic = 1, |
||||
ah_flah_cubic = 2, |
||||
ah_flah_control = ah_flah_conic | ah_flah_cubic, |
||||
|
||||
/* extrema flags */ |
||||
ah_flah_extrema_x = 4, |
||||
ah_flah_extrema_y = 8, |
||||
|
||||
/* roundness */ |
||||
ah_flah_round_x = 16, |
||||
ah_flah_round_y = 32, |
||||
|
||||
/* touched */ |
||||
ah_flah_touch_x = 64, |
||||
ah_flah_touch_y = 128, |
||||
|
||||
/* weak interpolation */ |
||||
ah_flah_weak_interpolation = 256, |
||||
|
||||
/* never remove this one !! */ |
||||
ah_flah_max |
||||
|
||||
} AH_Flags; |
||||
|
||||
|
||||
/* edge hint flags */ |
||||
typedef enum AH_Edge_Flags_ |
||||
{ |
||||
ah_edge_normal = 0, |
||||
ah_edge_round = 1, |
||||
ah_edge_serif = 2, |
||||
ah_edge_done = 4 |
||||
|
||||
} AH_Edge_Flags; |
||||
|
||||
|
||||
/* hint directions - the values are computed so that two vectors are */ |
||||
/* in opposite directions iff "dir1+dir2 == 0" */ |
||||
typedef enum AH_Direction_ |
||||
{ |
||||
ah_dir_none = 4, |
||||
ah_dir_right = 1, |
||||
ah_dir_left = -1, |
||||
ah_dir_up = 2, |
||||
ah_dir_down = -2 |
||||
|
||||
} AH_Direction; |
||||
|
||||
|
||||
typedef struct AH_Point AH_Point; |
||||
typedef struct AH_Segment AH_Segment; |
||||
typedef struct AH_Edge AH_Edge; |
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* <Struct> |
||||
* AH_Point |
||||
* |
||||
* <Description> |
||||
* A structure used to model an outline point to the AH_Outline type |
||||
* |
||||
* <Fields> |
||||
* flags :: current point hint flags |
||||
* ox, oy :: current original scaled coordinates |
||||
* fx, fy :: current coordinates in font units |
||||
* x, y :: current hinter coordinates |
||||
* u, v :: point coordinates - meaning varies with context |
||||
* |
||||
* in_dir :: direction of inwards vector (prev->point) |
||||
* out_dir :: direction of outwards vector (point->next) |
||||
* |
||||
* in_angle :: angle of inwards vector |
||||
* out_angle :: angle of outwards vector |
||||
* |
||||
* next :: next point in same contour |
||||
* prev :: previous point in same contour |
||||
* |
||||
*/ |
||||
struct AH_Point |
||||
{ |
||||
AH_Flags flags; /* point flags used by hinter */ |
||||
FT_Pos ox, oy; |
||||
FT_Pos fx, fy; |
||||
FT_Pos x, y; |
||||
FT_Pos u, v; |
||||
|
||||
AH_Direction in_dir; /* direction of inwards vector */ |
||||
AH_Direction out_dir; /* direction of outwards vector */ |
||||
|
||||
AH_Angle in_angle; |
||||
AH_Angle out_angle; |
||||
|
||||
AH_Point* next; /* next point in contour */ |
||||
AH_Point* prev; /* previous point in contour */ |
||||
}; |
||||
|
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* <Struct> |
||||
* AH_Segment |
||||
* |
||||
* <Description> |
||||
* a structure used to describe an edge segment to the auto-hinter. A |
||||
* segment is simply a sequence of successive points located on the same |
||||
* horizontal or vertical "position", in a given direction. |
||||
* |
||||
* <Fields> |
||||
* flags :: segment edge flags ( straight, rounded.. ) |
||||
* dir :: segment direction |
||||
* |
||||
* first :: first point in segment |
||||
* last :: last point in segment |
||||
* contour :: ptr to first point of segment's contour |
||||
* |
||||
* pos :: segment position in font units |
||||
* size :: segment size |
||||
* |
||||
* edge :: edge of current segment |
||||
* edge_next :: next segment on same edge |
||||
* |
||||
* link :: the pairing segment for this edge |
||||
* serif :: the primary segment for serifs |
||||
* num_linked :: the number of other segments that link to this one |
||||
* |
||||
* score :: used to score the segment when selecting them.. |
||||
* |
||||
*/ |
||||
struct AH_Segment |
||||
{ |
||||
AH_Edge_Flags flags; |
||||
AH_Direction dir; |
||||
|
||||
AH_Point* first; /* first point in edge segment */ |
||||
AH_Point* last; /* last point in edge segment */ |
||||
AH_Point** contour; /* ptr to first point of segment's contour */ |
||||
|
||||
FT_Pos pos; /* position of segment */ |
||||
FT_Pos min_coord; /* minimum coordinate of segment */ |
||||
FT_Pos max_coord; /* maximum coordinate of segment */ |
||||
|
||||
AH_Edge* edge; |
||||
AH_Segment* edge_next; |
||||
|
||||
AH_Segment* link; /* link segment */ |
||||
AH_Segment* serif; /* primary segment for serifs */ |
||||
FT_Pos num_linked; /* number of linked segments */ |
||||
FT_Int score; |
||||
}; |
||||
|
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* <Struct> |
||||
* AH_Edge |
||||
* |
||||
* <Description> |
||||
* a structure used to describe an edge, which really is a horizontal |
||||
* or vertical coordinate which will be hinted depending on the segments |
||||
* located on it.. |
||||
* |
||||
* <Fields> |
||||
* flags :: segment edge flags ( straight, rounded.. ) |
||||
* dir :: main segment direction on this edge |
||||
* |
||||
* first :: first edge segment |
||||
* last :: last edge segment |
||||
* |
||||
* fpos :: original edge position in font units |
||||
* opos :: original scaled edge position |
||||
* pos :: hinted edge position |
||||
* |
||||
* link :: the linked edge |
||||
* serif :: the serif edge |
||||
* num_paired :: the number of other edges that pair to this one |
||||
* |
||||
* score :: used to score the edge when selecting them.. |
||||
* |
||||
* blue_edge :: indicate the blue zone edge this edge is related to |
||||
* only set for some of the horizontal edges in a Latin |
||||
* font.. |
||||
* |
||||
***************************************************************************/ |
||||
struct AH_Edge |
||||
{ |
||||
AH_Edge_Flags flags; |
||||
AH_Direction dir; |
||||
|
||||
AH_Segment* first; |
||||
AH_Segment* last; |
||||
|
||||
FT_Pos fpos; |
||||
FT_Pos opos; |
||||
FT_Pos pos; |
||||
|
||||
AH_Edge* link; |
||||
AH_Edge* serif; |
||||
FT_Int num_linked; |
||||
|
||||
FT_Int score; |
||||
FT_Pos* blue_edge; |
||||
}; |
||||
|
||||
|
||||
/* an outline as seen by the hinter */ |
||||
typedef struct AH_Outline_ |
||||
{ |
||||
FT_Memory memory; |
||||
|
||||
AH_Direction vert_major_dir; /* vertical major direction */ |
||||
AH_Direction horz_major_dir; /* horizontal major direction */ |
||||
|
||||
FT_Fixed x_scale; |
||||
FT_Fixed y_scale; |
||||
FT_Pos edge_distance_threshold; |
||||
|
||||
FT_Int max_points; |
||||
FT_Int num_points; |
||||
AH_Point* points; |
||||
|
||||
FT_Int max_contours; |
||||
FT_Int num_contours; |
||||
AH_Point** contours; |
||||
|
||||
FT_Int num_hedges; |
||||
AH_Edge* horz_edges; |
||||
|
||||
FT_Int num_vedges; |
||||
AH_Edge* vert_edges; |
||||
|
||||
FT_Int num_hsegments; |
||||
AH_Segment* horz_segments; |
||||
|
||||
FT_Int num_vsegments; |
||||
AH_Segment* vert_segments; |
||||
|
||||
} AH_Outline; |
||||
|
||||
|
||||
|
||||
typedef enum AH_Blue_ |
||||
{ |
||||
ah_blue_capital_top, /* THEZOCQS */ |
||||
ah_blue_capital_bottom, /* HEZLOCUS */ |
||||
ah_blue_small_top, /* xzroesc */ |
||||
ah_blue_small_bottom, /* xzroesc */ |
||||
ah_blue_small_minor, /* pqgjy */ |
||||
|
||||
ah_blue_max |
||||
|
||||
} AH_Blue; |
||||
|
||||
typedef enum |
||||
{ |
||||
ah_hinter_monochrome = 1, |
||||
ah_hinter_optimize = 2 |
||||
|
||||
} AH_Hinter_Flags; |
||||
|
||||
|
||||
/************************************************************************
|
||||
* |
||||
* <Struct> |
||||
* AH_Globals |
||||
* |
||||
* <Description> |
||||
* Holds the global metrics for a given font face (be it in design |
||||
* units, or scaled pixel values).. |
||||
* |
||||
* <Fields> |
||||
* num_widths :: number of widths |
||||
* num_heights :: number of heights |
||||
* widths :: snap widths, including standard one |
||||
* heights :: snap height, including standard one |
||||
* blue_refs :: reference position of blue zones |
||||
* blue_shoots :: overshoot position of blue zones |
||||
* |
||||
************************************************************************/ |
||||
|
||||
typedef struct AH_Globals_ |
||||
{ |
||||
FT_Int num_widths; |
||||
FT_Int num_heights; |
||||
|
||||
FT_Pos widths [ AH_MAX_WIDTHS ]; |
||||
FT_Pos heights[ AH_MAX_HEIGHTS ]; |
||||
|
||||
FT_Pos blue_refs [ ah_blue_max ]; |
||||
FT_Pos blue_shoots[ ah_blue_max ]; |
||||
|
||||
} AH_Globals; |
||||
|
||||
|
||||
/************************************************************************
|
||||
* |
||||
* <Struct> |
||||
* AH_Face_Globals |
||||
* |
||||
* <Description> |
||||
* Holds the complete global metrics for a given font face (i.e. the |
||||
* design units version + a scaled version + the current scales used) |
||||
* |
||||
* <Fields> |
||||
* face :: handle to source face object |
||||
* design :: globals in font design units |
||||
* scaled :: scaled globals in sub-pixel values |
||||
* x_scale :: current horizontal scale |
||||
* y_scale :: current vertical scale |
||||
* |
||||
************************************************************************/ |
||||
|
||||
typedef struct AH_Face_Globals_ |
||||
{ |
||||
FT_Face face; |
||||
AH_Globals design; |
||||
AH_Globals scaled; |
||||
FT_Fixed x_scale; |
||||
FT_Fixed y_scale; |
||||
FT_Bool control_overshoot; |
||||
|
||||
} AH_Face_Globals; |
||||
|
||||
|
||||
|
||||
|
||||
typedef struct AH_Hinter |
||||
{ |
||||
FT_Memory memory; |
||||
FT_Long flags; |
||||
|
||||
FT_Int algorithm; |
||||
FT_Face face; |
||||
|
||||
AH_Face_Globals* globals; |
||||
|
||||
AH_Outline* glyph; |
||||
|
||||
AH_Loader* loader; |
||||
FT_Vector pp1; |
||||
FT_Vector pp2; |
||||
|
||||
} AH_Hinter; |
||||
|
||||
#endif /* AGTYPES_H */ |
@ -0,0 +1,40 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* autohint.c */ |
||||
/* */ |
||||
/* Automatic Hinting wrapper. */ |
||||
/* */ |
||||
/* Copyright 2000: Catharon Productions Inc. */ |
||||
/* Author: David Turner */ |
||||
/* */ |
||||
/* This file is part of the Catharon Typography Project and shall only */ |
||||
/* be used, modified, and distributed under the terms of the Catharon */ |
||||
/* Open Source License that should come with this file under the name */ |
||||
/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ |
||||
/* this file you indicate that you have read the license and */ |
||||
/* understand and accept it fully. */ |
||||
/* */ |
||||
/* Note that this license is compatible with the FreeType license */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
#define FT_MAKE_OPTION_SINGLE_OBJECT |
||||
|
||||
#ifdef FT_FLAT_COMPILE |
||||
|
||||
#include "ahangles.c" |
||||
#include "ahglyph.c" |
||||
#include "ahglobal.c" |
||||
#include "ahhint.c" |
||||
#include "ahmodule.c" |
||||
|
||||
#else |
||||
|
||||
#include <autohint/ahangles.c> |
||||
#include <autohint/ahglyph.c> |
||||
#include <autohint/ahglobal.c> |
||||
#include <autohint/ahhint.c> |
||||
#include <autohint/ahmodule.c> |
||||
|
||||
#endif |
||||
|
@ -0,0 +1,54 @@ |
||||
import math |
||||
|
||||
ag_pi = 256 |
||||
|
||||
def print_arctan( atan_bits ): |
||||
atan_base = 1 << atan_bits |
||||
|
||||
print "static AH_Angle ag_arctan[ 1L << AG_ATAN_BITS ] =" |
||||
print "{" |
||||
|
||||
count = 0 |
||||
line = "" |
||||
|
||||
for n in range(atan_base): |
||||
comma = "," |
||||
if (n == atan_base-1): |
||||
comma = "" |
||||
|
||||
angle = math.atan(n*1.0/atan_base)/math.pi*ag_pi |
||||
line = line + " " + repr(int(angle+0.5)) + comma |
||||
count = count+1; |
||||
if (count == 8): |
||||
count = 0 |
||||
print line |
||||
line = "" |
||||
|
||||
if (count >0): |
||||
print line |
||||
print "};" |
||||
|
||||
|
||||
def print_sines(): |
||||
print "static FT_Fixed ah_sines[ AG_HALF_PI+1 ] =" |
||||
print "{" |
||||
count = 0 |
||||
line = "" |
||||
|
||||
for n in range(ag_pi/2): |
||||
sinus = math.sin(n*math.pi/ag_pi) |
||||
line = line + " " + repr(int(65536.0*sinus)) + "," |
||||
count = count+1 |
||||
if (count == 8): |
||||
count = 0 |
||||
print line |
||||
line = "" |
||||
|
||||
if (count > 0): |
||||
print line |
||||
print " 65536" |
||||
print "};" |
||||
|
||||
print_arctan(8) |
||||
print |
||||
|
@ -0,0 +1,7 @@ |
||||
make_module_list: add_autohint_module |
||||
|
||||
add_autohint_module: |
||||
$(OPEN_DRIVER)autohint_module_class$(CLOSE_DRIVER)
|
||||
$(ECHO_DRIVER)autohint $(ECHO_DRIVER_DESC)automatic hinting module$(ECHO_DRIVER_DONE)
|
||||
|
||||
# EOF
|
@ -0,0 +1,86 @@ |
||||
#
|
||||
# FreeType 2 auto-hinter module configuration rules
|
||||
#
|
||||
|
||||
|
||||
#
|
||||
# Copyright 2000: Catharon Productions Inc.
|
||||
# Author: David Turner
|
||||
#
|
||||
# This file is part of the Catharon Typography Project and shall only
|
||||
# be used, modified, and distributed under the terms of the Catharon
|
||||
# Open Source License that should come with this file under the name
|
||||
# "CatharonLicense.txt". By continuing to use, modify, or distribute
|
||||
# this file you indicate that you have read the license and
|
||||
# understand and accept it fully.
|
||||
#
|
||||
# Note that this license is compatible with the FreeType license
|
||||
#
|
||||
#
|
||||
# Copyright 1996-2000 by
|
||||
# David Turner, Robert Wilhelm, and Werner Lemberg.
|
||||
#
|
||||
# This file is part of the FreeType project, and may only be used, modified,
|
||||
# and distributed under the terms of the FreeType project license,
|
||||
# LICENSE.TXT. By continuing to use, modify, or distribute this file you
|
||||
# indicate that you have read the license and understand and accept it
|
||||
# fully.
|
||||
|
||||
|
||||
# AUTO driver directory
|
||||
#
|
||||
AUTO_DIR := $(SRC_)autohint
|
||||
AUTO_DIR_ := $(AUTO_DIR)$(SEP)
|
||||
|
||||
|
||||
# compilation flags for the driver
|
||||
#
|
||||
AUTO_COMPILE := $(FT_COMPILE)
|
||||
|
||||
|
||||
# AUTO driver sources (i.e., C files)
|
||||
#
|
||||
AUTO_DRV_SRC := $(AUTO_DIR_)ahangles.c \
|
||||
$(AUTO_DIR_)ahglobal.c \
|
||||
$(AUTO_DIR_)ahglyph.c \
|
||||
$(AUTO_DIR_)ahhint.c \
|
||||
$(AUTO_DIR_)ahmodule.c
|
||||
|
||||
# AUTO driver headers
|
||||
#
|
||||
AUTO_DRV_H := $(AUTO_DRV_SRC:%c=%h)
|
||||
|
||||
|
||||
# AUTO driver object(s)
|
||||
#
|
||||
# AUTO_DRV_OBJ_M is used during `multi' builds.
|
||||
# AUTO_DRV_OBJ_S is used during `single' builds.
|
||||
#
|
||||
AUTO_DRV_OBJ_M := $(AUTO_DRV_SRC:$(AUTO_DIR_)%.c=$(OBJ_)%.$O)
|
||||
AUTO_DRV_OBJ_S := $(OBJ_)autohint.$O
|
||||
|
||||
# AUTO driver source file for single build
|
||||
#
|
||||
AUTO_DRV_SRC_S := $(AUTO_DIR_)autohint.c
|
||||
|
||||
|
||||
# AUTO driver - single object
|
||||
#
|
||||
$(AUTO_DRV_OBJ_S): $(AUTO_DRV_SRC_S) $(AUTO_DRV_SRC) \
|
||||
$(FREETYPE_H) $(AUTO_DRV_H)
|
||||
$(AUTO_COMPILE) $T$@ $(AUTO_DRV_SRC_S)
|
||||
|
||||
|
||||
# AUTO driver - multiple objects
|
||||
#
|
||||
$(OBJ_)%.$O: $(AUTO_DIR_)%.c $(FREETYPE_H) $(AUTO_DRV_H) |
||||
$(AUTO_COMPILE) $T$@ $<
|
||||
|
||||
|
||||
# update main driver object lists
|
||||
#
|
||||
DRV_OBJS_S += $(AUTO_DRV_OBJ_S)
|
||||
DRV_OBJS_M += $(AUTO_DRV_OBJ_M)
|
||||
|
||||
|
||||
# EOF
|
Loading…
Reference in new issue