- Fixed compilation of the updated freetype

svn path=/trunk/; revision=8068
This commit is contained in:
Filip Navara 2004-02-07 00:11:02 +00:00
parent 650d796921
commit 88b0aebe1a
40 changed files with 7973 additions and 0 deletions

View file

@ -0,0 +1,16 @@
#ifndef ATARI_H
#define ATARI_H
#pragma warn -stu
/* PureC doesn't like 32bit enumerations */
#ifndef FT_IMAGE_TAG
#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) value
#endif /* FT_IMAGE_TAG */
#ifndef FT_ENC_TAG
#define FT_ENC_TAG( value, a, b, c, d ) value
#endif /* FT_ENC_TAG */
#endif /* ATARI_H */

View file

@ -0,0 +1,37 @@
/* the following changes file names for PureC projects */
if (argc > 0)
{
ordner = argv[0];
if (basename(ordner) == "") /* ist Ordner */
{
ChangeFilenames(ordner);
}
}
proc ChangeFilenames(folder)
local i,entries,directory,file;
{
entries = filelist(directory,folder);
for (i = 0; i < entries; ++i)
{
file = directory[i,0];
if ((directory[i,3]&16) > 0) /* subdirectory */
{
ChangeFilenames(folder+file+"\\");
}
else
{
if ((stricmp(suffix(file),".h")==0)|(stricmp(suffix(file),".c")==0))
ChangeFilename(folder,file);
}
}
}
proc ChangeFilename(path,datei)
local newfile,err;
{
newfile=datei;
newfile[0]=(newfile[0] | 32) ^ 32;
err=files.rename("-q",path+datei,newfile);
}

View file

@ -0,0 +1,33 @@
;FreeType project file
FREETYPE.LIB
.C [-K -P -R -A]
.L [-J -V]
.S
=
..\..\src\base\ftsystem.c
..\..\src\base\ftdebug.c
..\..\src\base\ftinit.c
..\..\src\base\ftglyph.c
..\..\src\base\ftmm
..\..\src\base\ftbbox
..\..\src\base\ftbase.c
..\..\src\autohint\autohint.c
;..\..\src\cache\ftcache.c
..\..\src\cff\cff.c
..\..\src\cid\type1cid.c
..\..\src\psaux\psaux.c
..\..\src\pshinter\pshinter.c
..\..\src\psnames\psnames.c
..\..\src\raster\raster.c
..\..\src\sfnt\sfnt.c
..\..\src\smooth\smooth.c
..\..\src\truetype\truetype.c
..\..\src\type1\type1.c
..\..\src\type42\type42.c

View file

@ -0,0 +1,51 @@
Compiling FreeType 2 with PureC compiler
========================================
[See below for a German version.]
To compile FreeType 2 as a library the following changes must be applied:
- All *.c files must start with an uppercase letter.
(In case GEMSCRIPT is available:
Simply drag the whole FreeType 2 directory to the file `FNames.SIC'.)
- You have to change the INCLUDE directory in PureC's compiler options
to contain both the `INCLUDE' and `freetype2\include' directory.
Example:
INCLUDE;E:\freetype2\include
- The file `freetype2/include/Ft2build.h' must be patched as follows to
include ATARI.H:
#ifndef __FT2_BUILD_GENERIC_H__
#define __FT2_BUILD_GENERIC_H__
#include "ATARI.H"
Compilieren von FreeType 2 mit PureC
====================================
Um FreeType 2 als eine Bibliothek (library) zu compilieren, muss folgendes
ge„ndert werden:
- Alle *.c-files m<>ssen mit einem GROSSBUCHSTABEN beginnen.
(Falls GEMSCRIPT zur Verf<72>gung steht:
Den kompletten Ordner freetype2 auf die Datei `FNames.SIC' draggen.)
- In den Compiler-Optionen von PureC muss das INCLUDE directory auf INCLUDE
und freetype2\include verweisen. Z.B.:
INCLUDE;E:\freetype2\include
- In der Datei freetype2/include/Ft2build.h muss zu Beginn
ein #include "ATARI.H" wie folgt eingef<65>gt werden:
#ifndef __FT2_BUILD_GENERIC_H__
#define __FT2_BUILD_GENERIC_H__
#include "ATARI.H"
--- end of README.TXT ---

View file

@ -0,0 +1,624 @@
How FreeType's rasterizer work
by David Turner
Revised 2003-Dec-08
This file is an attempt to explain the internals of the FreeType
rasterizer. The rasterizer is of quite general purpose and could
easily be integrated into other programs.
I. Introduction
II. Rendering Technology
1. Requirements
2. Profiles and Spans
a. Sweeping the Shape
b. Decomposing Outlines into Profiles
c. The Render Pool
d. Computing Profiles Extents
e. Computing Profiles Coordinates
f. Sweeping and Sorting the Spans
I. Introduction
===============
A rasterizer is a library in charge of converting a vectorial
representation of a shape into a bitmap. The FreeType rasterizer
has been originally developed to render the glyphs found in
TrueType files, made up of segments and second-order Béziers.
Meanwhile it has been extended to render third-order Bézier curves
also. This document is an explanation of its design and
implementation.
While these explanations start from the basics, a knowledge of
common rasterization techniques is assumed.
II. Rendering Technology
========================
1. Requirements
---------------
We assume that all scaling, rotating, hinting, etc., has been
already done. The glyph is thus described by a list of points in
the device space.
- All point coordinates are in the 26.6 fixed float format. The
used orientation is:
^ y
| reference orientation
|
*----> x
0
`26.6' means that 26 bits are used for the integer part of a
value and 6 bits are used for the fractional part.
Consequently, the `distance' between two neighbouring pixels is
64 `units' (1 unit = 1/64th of a pixel).
Note that, for the rasterizer, pixel centers are located at
integer coordinates. The TrueType bytecode interpreter,
however, assumes that the lower left edge of a pixel (which is
taken to be a square with a length of 1 unit) has integer
coordinates.
^ y ^ y
| |
| (1,1) | (0.5,0.5)
+-----------+ +-----+-----+
| | | | |
| | | | |
| | | o-----+-----> x
| | | (0,0) |
| | | |
o-----------+-----> x +-----------+
(0,0) (-0.5,-0.5)
TrueType bytecode interpreter FreeType rasterizer
A pixel line in the target bitmap is called a `scanline'.
- A glyph is usually made of several contours, also called
`outlines'. A contour is simply a closed curve that delimits an
outer or inner region of the glyph. It is described by a series
of successive points of the points table.
Each point of the glyph has an associated flag that indicates
whether it is `on' or `off' the curve. Two successive `on'
points indicate a line segment joining the two points.
One `off' point amidst two `on' points indicates a second-degree
(conic) Bézier parametric arc, defined by these three points
(the `off' point being the control point, and the `on' ones the
start and end points). Similarly, a third-degree (cubic) Bézier
curve is described by four points (two `off' control points
between two `on' points).
Finally, for second-order curves only, two successive `off'
points forces the rasterizer to create, during rendering, an
`on' point amidst them, at their exact middle. This greatly
facilitates the definition of successive Bézier arcs.
The parametric form of a second-order Bézier curve is:
P(t) = (1-t)^2*P1 + 2*t*(1-t)*P2 + t^2*P3
(P1 and P3 are the end points, P2 the control point.)
The parametric form of a third-order Bézier curve is:
P(t) = (1-t)^3*P1 + 3*t*(1-t)^2*P2 + 3*t^2*(1-t)*P3 + t^3*P4
(P1 and P4 are the end points, P2 and P3 the control points.)
For both formulae, t is a real number in the range [0..1].
Note that the rasterizer does not use these formulae directly.
They exhibit, however, one very useful property of Bézier arcs:
Each point of the curve is a weighted average of the control
points.
As all weights are positive and always sum up to 1, whatever the
value of t, each arc point lies within the triangle (polygon)
defined by the arc's three (four) control points.
In the following, only second-order curves are discussed since
rasterization of third-order curves is completely identical.
Here some samples for second-order curves.
* # on curve
* off curve
__---__
#-__ _-- -_
--__ _- -
--__ # \
--__ #
-#
Two `on' points
Two `on' points and one `off' point
between them
*
# __ Two `on' points with two `off'
\ - - points between them. The point
\ / \ marked `0' is the middle of the
- 0 \ `off' points, and is a `virtual
-_ _- # on' point where the curve passes.
-- It does not appear in the point
* list.
2. Profiles and Spans
---------------------
The following is a basic explanation of the _kind_ of computations
made by the rasterizer to build a bitmap from a vector
representation. Note that the actual implementation is slightly
different, due to performance tuning and other factors.
However, the following ideas remain in the same category, and are
more convenient to understand.
a. Sweeping the Shape
The best way to fill a shape is to decompose it into a number of
simple horizontal segments, then turn them on in the target
bitmap. These segments are called `spans'.
__---__
_-- -_
_- -
- \
/ \
/ \
| \
__---__ Example: filling a shape
_----------_ with spans.
_--------------
----------------\
/-----------------\ This is typically done from the top
/ \ to the bottom of the shape, in a
| | \ movement called a `sweep'.
V
__---__
_----------_
_--------------
----------------\
/-----------------\
/-------------------\
|---------------------\
In order to draw a span, the rasterizer must compute its
coordinates, which are simply the x coordinates of the shape's
contours, taken on the y scanlines.
/---/ |---| Note that there are usually
/---/ |---| several spans per scanline.
| /---/ |---|
| /---/_______|---| When rendering this shape to the
V /----------------| current scanline y, we must
/-----------------| compute the x values of the
a /----| |---| points a, b, c, and d.
- - - * * - - - - * * - - y -
/ / b c| |d
/---/ |---|
/---/ |---| And then turn on the spans a-b
/---/ |---| and c-d.
/---/_______|---|
/----------------|
/-----------------|
a /----| |---|
- - - ####### - - - - ##### - - y -
/ / b c| |d
b. Decomposing Outlines into Profiles
For each scanline during the sweep, we need the following
information:
o The number of spans on the current scanline, given by the
number of shape points intersecting the scanline (these are
the points a, b, c, and d in the above example).
o The x coordinates of these points.
x coordinates are computed before the sweep, in a phase called
`decomposition' which converts the glyph into *profiles*.
Put it simply, a `profile' is a contour's portion that can only
be either ascending or descending, i.e., it is monotonic in the
vertical direction (we also say y-monotonic). There is no such
thing as a horizontal profile, as we shall see.
Here are a few examples:
this square
1 2
---->---- is made of two
| | | |
| | profiles | |
^ v ^ + v
| | | |
| | | |
----<----
up down
this triangle
P2 1 2
|\ is made of two | \
^ | \ \ | \
| | \ \ profiles | \ |
| | \ v ^ | \ |
| \ | | + \ v
| \ | | \
P1 ---___ \ ---___ \
---_\ ---_ \
<--__ P3 up down
A more general contour can be made of more than two profiles:
__ ^
/ | / ___ / |
/ | / | / | / |
| | / / => | v / /
| | | | | | ^ |
^ | |___| | | ^ + | + | + v
| | | v | |
| | | up |
|___________| | down |
<-- up down
Successive profiles are always joined by horizontal segments
that are not part of the profiles themselves.
For the rasterizer, a profile is simply an *array* that
associates one horizontal *pixel* coordinate to each bitmap
*scanline* crossed by the contour's section containing the
profile. Note that profiles are *oriented* up or down along the
glyph's original flow orientation.
In other graphics libraries, profiles are also called `edges' or
`edgelists'.
c. The Render Pool
FreeType has been designed to be able to run well on _very_
light systems, including embedded systems with very few memory.
A render pool will be allocated once; the rasterizer uses this
pool for all its needs by managing this memory directly in it.
The algorithms that are used for profile computation make it
possible to use the pool as a simple growing heap. This means
that this memory management is actually quite easy and faster
than any kind of malloc()/free() combination.
Moreover, we'll see later that the rasterizer is able, when
dealing with profiles too large and numerous to lie all at once
in the render pool, to immediately decompose recursively the
rendering process into independent sub-tasks, each taking less
memory to be performed (see `sub-banding' below).
The render pool doesn't need to be large. A 4KByte pool is
enough for nearly all renditions, though nearly 100% slower than
a more confortable 16KByte or 32KByte pool (that was tested with
complex glyphs at sizes over 500 pixels).
d. Computing Profiles Extents
Remember that a profile is an array, associating a _scanline_ to
the x pixel coordinate of its intersection with a contour.
Though it's not exactly how the FreeType rasterizer works, it is
convenient to think that we need a profile's height before
allocating it in the pool and computing its coordinates.
The profile's height is the number of scanlines crossed by the
y-monotonic section of a contour. We thus need to compute these
sections from the vectorial description. In order to do that,
we are obliged to compute all (local and global) y extrema of
the glyph (minima and maxima).
P2 For instance, this triangle has only
two y-extrema, which are simply
|\
| \ P2.y as a vertical maximum
| \ P3.y as a vertical minimum
| \
| \ P1.y is not a vertical extremum (though
| \ it is a horizontal minimum, which we
P1 ---___ \ don't need).
---_\
P3
Note that the extrema are expressed in pixel units, not in
scanlines. The triangle's height is certainly (P3.y-P2.y+1)
pixel units, but its profiles' heights are computed in
scanlines. The exact conversion is simple:
- min scanline = FLOOR ( min y )
- max scanline = CEILING( max y )
A problem arises with Bézier Arcs. While a segment is always
necessarily y-monotonic (i.e., flat, ascending, or descending),
which makes extrema computations easy, the ascent of an arc can
vary between its control points.
P2
*
# on curve
* off curve
__-x--_
_-- -_
P1 _- - A non y-monotonic Bézier arc.
# \
- The arc goes from P1 to P3.
\
\ P3
#
We first need to be able to easily detect non-monotonic arcs,
according to their control points. I will state here, without
proof, that the monotony condition can be expressed as:
P1.y <= P2.y <= P3.y for an ever-ascending arc
P1.y >= P2.y >= P3.y for an ever-descending arc
with the special case of
P1.y = P2.y = P3.y where the arc is said to be `flat'.
As you can see, these conditions can be very easily tested.
They are, however, extremely important, as any arc that does not
satisfy them necessarily contains an extremum.
Note also that a monotonic arc can contain an extremum too,
which is then one of its `on' points:
P1 P2
#---__ * P1P2P3 is ever-descending, but P1
-_ is an y-extremum.
-
---_ \
-> \
\ P3
#
Let's go back to our previous example:
P2
*
# on curve
* off curve
__-x--_
_-- -_
P1 _- - A non-y-monotonic Bézier arc.
# \
- Here we have
\ P2.y >= P1.y &&
\ P3 P2.y >= P3.y (!)
#
We need to compute the vertical maximum of this arc to be able
to compute a profile's height (the point marked by an `x'). The
arc's equation indicates that a direct computation is possible,
but we rely on a different technique, which use will become
apparent soon.
Bézier arcs have the special property of being very easily
decomposed into two sub-arcs, which are themselves Bézier arcs.
Moreover, it is easy to prove that there is at most one vertical
extremum on each Bézier arc (for second-degree curves; similar
conditions can be found for third-order arcs).
For instance, the following arc P1P2P3 can be decomposed into
two sub-arcs Q1Q2Q3 and R1R2R3:
P2
*
# on curve
* off curve
original Bézier arc P1P2P3.
__---__
_-- --_
_- -_
- -
/ \
/ \
# #
P1 P3
P2
*
Q3 Decomposed into two subarcs
Q2 R2 Q1Q2Q3 and R1R2R3
* __-#-__ *
_-- --_
_- R1 -_ Q1 = P1 R3 = P3
- - Q2 = (P1+P2)/2 R2 = (P2+P3)/2
/ \
/ \ Q3 = R1 = (Q2+R2)/2
# #
Q1 R3 Note that Q2, R2, and Q3=R1
are on a single line which is
tangent to the curve.
We have then decomposed a non-y-monotonic Bézier curve into two
smaller sub-arcs. Note that in the above drawing, both sub-arcs
are monotonic, and that the extremum is then Q3=R1. However, in
a more general case, only one sub-arc is guaranteed to be
monotonic. Getting back to our former example:
Q2
*
__-x--_ R1
_-- #_
Q1 _- Q3 - R2
# \ *
-
\
\ R3
#
Here, we see that, though Q1Q2Q3 is still non-monotonic, R1R2R3
is ever descending: We thus know that it doesn't contain the
extremum. We can then re-subdivide Q1Q2Q3 into two sub-arcs and
go on recursively, stopping when we encounter two monotonic
subarcs, or when the subarcs become simply too small.
We will finally find the vertical extremum. Note that the
iterative process of finding an extremum is called `flattening'.
e. Computing Profiles Coordinates
Once we have the height of each profile, we are able to allocate
it in the render pool. The next task is to compute coordinates
for each scanline.
In the case of segments, the computation is straightforward,
using the Euclidian algorithm (also known as Bresenham).
However, for Bézier arcs, the job is a little more complicated.
We assume that all Béziers that are part of a profile are the
result of flattening the curve, which means that they are all
y-monotonic (ascending or descending, and never flat). We now
have to compute the intersections of arcs with the profile's
scanlines. One way is to use a similar scheme to flattening
called `stepping'.
Consider this arc, going from P1 to
--------------------- P3. Suppose that we need to
compute its intersections with the
drawn scanlines. As already
--------------------- mentioned this can be done
directly, but the involed algorithm
* P2 _---# P3 is far too slow.
------------- _-- --
_-
_/ Instead, it is still possible to
---------/----------- use the decomposition property in
/ the same recursive way, i.e.,
| subdivide the arc into subarcs
------|-------------- until these get too small to cross
| more than one scanline!
|
-----|--------------- This is very easily done using a
| rasterizer-managed stack of
| subarcs.
# P1
f. Sweeping and Sorting the Spans
Once all our profiles have been computed, we begin the sweep to
build (and fill) the spans.
As both the TrueType and Type 1 specifications use the winding
fill rule (but with opposite directions), we place, on each
scanline, the present profiles in two separate lists.
One list, called the `left' one, only contains ascending
profiles, while the other `right' list contains the descending
profiles.
As each glyph is made of closed curves, a simple geometric
property ensures that the two lists contain the same number of
elements.
Creating spans is thus straightforward:
1. We sort each list in increasing horizontal order.
2. We pair each value of the left list with its corresponding
value in the right list.
/ / | | For example, we have here
/ / | | four profiles. Two of
>/ / | | | them are ascending (1 &
1// / ^ | | | 2 3), while the two others
// // 3| | | v are descending (2 & 4).
/ //4 | | | On the given scanline,
a / /< | | the left list is (1,3),
- - - *-----* - - - - *---* - - y - and the right one is
/ / b c| |d (4,2) (sorted).
There are then two spans, joining
1 to 4 (i.e. a-b) and 3 to 2
(i.e. c-d)!
Sorting doesn't necessarily take much time, as in 99 cases out
of 100, the lists' order is kept from one scanline to the next.
We can thus implement it with two simple singly-linked lists,
sorted by a classic bubble-sort, which takes a minimum amount of
time when the lists are already sorted.
A previous version of the rasterizer used more elaborate
structures, like arrays to perform `faster' sorting. It turned
out that this old scheme is not faster than the one described
above.
Once the spans have been `created', we can simply draw them in
the target bitmap.
--- end of raster.txt ---
Local Variables:
coding: latin-1
End:

View file

@ -0,0 +1 @@
*.html

View file

@ -0,0 +1,246 @@
/***************************************************************************/
/* */
/* ftcmru.h */
/* */
/* Simple MRU list-cache (specification). */
/* */
/* Copyright 2000-2001, 2003, 2004 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* An MRU is a list that cannot hold more than a certain number of */
/* elements (`max_elements'). All elements in the list are sorted in */
/* least-recently-used order, i.e., the `oldest' element is at the tail */
/* of the list. */
/* */
/* When doing a lookup (either through `Lookup()' or `Lookup_Node()'), */
/* the list is searched for an element with the corresponding key. If */
/* it is found, the element is moved to the head of the list and is */
/* returned. */
/* */
/* If no corresponding element is found, the lookup routine will try to */
/* obtain a new element with the relevant key. If the list is already */
/* full, the oldest element from the list is discarded and replaced by a */
/* new one; a new element is added to the list otherwise. */
/* */
/* Note that it is possible to pre-allocate the element list nodes. */
/* This is handy if `max_elements' is sufficiently small, as it saves */
/* allocations/releases during the lookup process. */
/* */
/*************************************************************************/
#ifndef __FTCMRU_H__
#define __FTCMRU_H__
#include <ft2build.h>
#include FT_FREETYPE_H
#ifdef FREETYPE_H
#error "freetype.h of FreeType 1 has been loaded!"
#error "Please fix the directory search order for header files"
#error "so that freetype.h of FreeType 2 is found first."
#endif
#define xxFT_DEBUG_ERROR
#define FTC_INLINE
FT_BEGIN_HEADER
typedef struct FTC_MruNodeRec_* FTC_MruNode;
typedef struct FTC_MruNodeRec_
{
FTC_MruNode next;
FTC_MruNode prev;
} FTC_MruNodeRec;
FT_EXPORT( void )
FTC_MruNode_Prepend( FTC_MruNode *plist,
FTC_MruNode node );
FT_EXPORT( void )
FTC_MruNode_Up( FTC_MruNode *plist,
FTC_MruNode node );
FT_EXPORT( void )
FTC_MruNode_Remove( FTC_MruNode *plist,
FTC_MruNode node );
typedef struct FTC_MruListRec_* FTC_MruList;
typedef struct FTC_MruListClassRec_ const * FTC_MruListClass;
typedef FT_Int
(*FTC_MruNode_CompareFunc)( FTC_MruNode node,
FT_Pointer key );
typedef FT_Error
(*FTC_MruNode_InitFunc)( FTC_MruNode node,
FT_Pointer key,
FT_Pointer data );
typedef FT_Error
(*FTC_MruNode_ResetFunc)( FTC_MruNode node,
FT_Pointer key,
FT_Pointer data );
typedef void
(*FTC_MruNode_DoneFunc)( FTC_MruNode node,
FT_Pointer data );
typedef struct FTC_MruListClassRec_
{
FT_UInt node_size;
FTC_MruNode_CompareFunc node_compare;
FTC_MruNode_InitFunc node_init;
FTC_MruNode_ResetFunc node_reset;
FTC_MruNode_DoneFunc node_done;
} FTC_MruListClassRec;
typedef struct FTC_MruListRec_
{
FT_UInt num_nodes;
FT_UInt max_nodes;
FTC_MruNode nodes;
FT_Pointer data;
FTC_MruListClassRec clazz;
FT_Memory memory;
} FTC_MruListRec;
FT_EXPORT( void )
FTC_MruList_Init( FTC_MruList list,
FTC_MruListClass clazz,
FT_UInt max_nodes,
FT_Pointer data,
FT_Memory memory );
FT_EXPORT( void )
FTC_MruList_Reset( FTC_MruList list );
FT_EXPORT( void )
FTC_MruList_Done( FTC_MruList list );
FT_EXPORT( FTC_MruNode )
FTC_MruList_Find( FTC_MruList list,
FT_Pointer key );
FT_EXPORT( FT_Error )
FTC_MruList_New( FTC_MruList list,
FT_Pointer key,
FTC_MruNode *anode );
FT_EXPORT( FT_Error )
FTC_MruList_Lookup( FTC_MruList list,
FT_Pointer key,
FTC_MruNode *pnode );
FT_EXPORT( void )
FTC_MruList_Remove( FTC_MruList list,
FTC_MruNode node );
FT_EXPORT( void )
FTC_MruList_RemoveSelection( FTC_MruList list,
FTC_MruNode_CompareFunc selection,
FT_Pointer key );
#ifdef FTC_INLINE
#define FTC_MRULIST_LOOKUP_CMP( list, key, compare, node, error ) \
FT_BEGIN_STMNT \
FTC_MruNode* _pfirst = &(list)->nodes; \
FTC_MruNode_CompareFunc _compare = (FTC_MruNode_CompareFunc)(compare); \
FTC_MruNode _first, _node; \
\
\
error = 0; \
_first = *(_pfirst); \
_node = NULL; \
\
if ( _first ) \
{ \
_node = _first; \
do \
{ \
if ( _compare( _node, (key) ) ) \
{ \
if ( _node != _first ) \
FTC_MruNode_Up( _pfirst, _node ); \
\
*(FTC_MruNode*)&(node) = _node; \
goto _MruOk; \
} \
_node = _node->next; \
\
} while ( _node != _first) ; \
} \
\
error = FTC_MruList_New( (list), (key), (FTC_MruNode*)&(node) ); \
_MruOk: \
; \
FT_END_STMNT
#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
FTC_MRULIST_LOOKUP_CMP( list, key, (list)->clazz.node_compare, node, error )
#else /* !FTC_INLINE */
#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
error = FTC_MruList_Lookup( (list), (key), (FTC_MruNode*)&(node) )
#endif /* !FTC_INLINE */
#define FTC_MRULIST_LOOP( list, node ) \
FT_BEGIN_STMNT \
FTC_MruNode _first = (list)->nodes; \
\
\
if ( _first ) \
{ \
FTC_MruNode _node = _first; \
\
\
do \
{ \
*(FTC_MruNode*)&(node) = _node;
#define FTC_MRULIST_LOOP_END() \
_node = _node->next; \
\
} while ( _node != _first ); \
} \
FT_END_STMNT
/* */
FT_END_HEADER
#endif /* __FTCMRU_H__ */
/* END */

View file

@ -0,0 +1,314 @@
/***************************************************************************/
/* */
/* ftmodule.h */
/* */
/* FreeType modules public interface (specification). */
/* */
/* Copyright 1996-2001, 2002, 2003 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. */
/* */
/***************************************************************************/
#ifndef __FTMODULE_H__
#define __FTMODULE_H__
#include <ft2build.h>
#include FT_FREETYPE_H
FT_BEGIN_HEADER
/*************************************************************************/
/* */
/* <Section> */
/* module_management */
/* */
/* <Title> */
/* Module Management */
/* */
/* <Abstract> */
/* How to add, upgrade, and remove modules from FreeType. */
/* */
/* <Description> */
/* The definitions below are used to manage modules within FreeType. */
/* Modules can be added, upgraded, and removed at runtime. */
/* */
/*************************************************************************/
/* module bit flags */
#define FT_MODULE_FONT_DRIVER 1 /* this module is a font driver */
#define FT_MODULE_RENDERER 2 /* this module is a renderer */
#define FT_MODULE_HINTER 4 /* this module is a glyph hinter */
#define FT_MODULE_STYLER 8 /* this module is a styler */
#define FT_MODULE_DRIVER_SCALABLE 0x100 /* the driver supports */
/* scalable fonts */
#define FT_MODULE_DRIVER_NO_OUTLINES 0x200 /* the driver does not */
/* support vector outlines */
#define FT_MODULE_DRIVER_HAS_HINTER 0x400 /* the driver provides its */
/* own hinter */
/* deprecated values */
#define ft_module_font_driver FT_MODULE_FONT_DRIVER
#define ft_module_renderer FT_MODULE_RENDERER
#define ft_module_hinter FT_MODULE_HINTER
#define ft_module_styler FT_MODULE_STYLER
#define ft_module_driver_scalable FT_MODULE_DRIVER_SCALABLE
#define ft_module_driver_no_outlines FT_MODULE_DRIVER_NO_OUTLINES
#define ft_module_driver_has_hinter FT_MODULE_DRIVER_HAS_HINTER
typedef void
(*FT_Module_Interface)( void );
typedef FT_Error
(*FT_Module_Constructor)( FT_Module module );
typedef void
(*FT_Module_Destructor)( FT_Module module );
typedef FT_Module_Interface
(*FT_Module_Requester)( FT_Module module,
const char* name );
/*************************************************************************/
/* */
/* <Struct> */
/* FT_Module_Class */
/* */
/* <Description> */
/* The module class descriptor. */
/* */
/* <Fields> */
/* module_flags :: Bit flags describing the module. */
/* */
/* module_size :: The size of one module object/instance in */
/* bytes. */
/* */
/* module_name :: The name of the module. */
/* */
/* module_version :: The version, as a 16.16 fixed number */
/* (major.minor). */
/* */
/* module_requires :: The version of FreeType this module requires */
/* (starts at version 2.0, i.e 0x20000) */
/* */
/* module_init :: A function used to initialize (not create) a */
/* new module object. */
/* */
/* module_done :: A function used to finalize (not destroy) a */
/* given module object */
/* */
/* get_interface :: Queries a given module for a specific */
/* interface by name. */
/* */
typedef struct FT_Module_Class_
{
FT_ULong module_flags;
FT_Long module_size;
const FT_String* module_name;
FT_Fixed module_version;
FT_Fixed module_requires;
const void* module_interface;
FT_Module_Constructor module_init;
FT_Module_Destructor module_done;
FT_Module_Requester get_interface;
} FT_Module_Class;
/*************************************************************************/
/* */
/* <Function> */
/* FT_Add_Module */
/* */
/* <Description> */
/* Adds a new module to a given library instance. */
/* */
/* <InOut> */
/* library :: A handle to the library object. */
/* */
/* <Input> */
/* clazz :: A pointer to class descriptor for the module. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
/* <Note> */
/* An error will be returned if a module already exists by that name, */
/* or if the module requires a version of FreeType that is too great. */
/* */
FT_EXPORT( FT_Error )
FT_Add_Module( FT_Library library,
const FT_Module_Class* clazz );
/*************************************************************************/
/* */
/* <Function> */
/* FT_Get_Module */
/* */
/* <Description> */
/* Finds a module by its name. */
/* */
/* <Input> */
/* library :: A handle to the library object. */
/* */
/* module_name :: The module's name (as an ASCII string). */
/* */
/* <Return> */
/* A module handle. 0 if none was found. */
/* */
/* <Note> */
/* You should better be familiar with FreeType internals to know */
/* which module to look for :-) */
/* */
FT_EXPORT( FT_Module )
FT_Get_Module( FT_Library library,
const char* module_name );
/*************************************************************************/
/* */
/* <Function> */
/* FT_Remove_Module */
/* */
/* <Description> */
/* Removes a given module from a library instance. */
/* */
/* <InOut> */
/* library :: A handle to a library object. */
/* */
/* <Input> */
/* module :: A handle to a module object. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
/* <Note> */
/* The module object is destroyed by the function in case of success. */
/* */
FT_EXPORT( FT_Error )
FT_Remove_Module( FT_Library library,
FT_Module module );
/*************************************************************************/
/* */
/* <Function> */
/* FT_New_Library */
/* */
/* <Description> */
/* This function is used to create a new FreeType library instance */
/* from a given memory object. It is thus possible to use libraries */
/* with distinct memory allocators within the same program. */
/* */
/* <Input> */
/* memory :: A handle to the original memory object. */
/* */
/* <Output> */
/* alibrary :: A pointer to handle of a new library object. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_EXPORT( FT_Error )
FT_New_Library( FT_Memory memory,
FT_Library *alibrary );
/*************************************************************************/
/* */
/* <Function> */
/* FT_Done_Library */
/* */
/* <Description> */
/* Discards a given library object. This closes all drivers and */
/* discards all resource objects. */
/* */
/* <Input> */
/* library :: A handle to the target library. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_EXPORT( FT_Error )
FT_Done_Library( FT_Library library );
typedef void
(*FT_DebugHook_Func)( void* arg );
/*************************************************************************/
/* */
/* <Function> */
/* FT_Set_Debug_Hook */
/* */
/* <Description> */
/* Sets a debug hook function for debugging the interpreter of a font */
/* format. */
/* */
/* <InOut> */
/* library :: A handle to the library object. */
/* */
/* <Input> */
/* hook_index :: The index of the debug hook. You should use the */
/* values defined in ftobjs.h, e.g. */
/* FT_DEBUG_HOOK_TRUETYPE. */
/* */
/* debug_hook :: The function used to debug the interpreter. */
/* */
/* <Note> */
/* Currently, four debug hook slots are available, but only two (for */
/* the TrueType and the Type 1 interpreter) are defined. */
/* */
FT_EXPORT( void )
FT_Set_Debug_Hook( FT_Library library,
FT_UInt hook_index,
FT_DebugHook_Func debug_hook );
/*************************************************************************/
/* */
/* <Function> */
/* FT_Add_Default_Modules */
/* */
/* <Description> */
/* Adds the set of default drivers to a given library object. */
/* This is only useful when you create a library object with */
/* FT_New_Library() (usually to plug a custom memory manager). */
/* */
/* <InOut> */
/* library :: A handle to a new library object. */
/* */
FT_EXPORT( void )
FT_Add_Default_Modules( FT_Library library );
/* */
FT_END_HEADER
#endif /* __FTMODULE_H__ */
/* END */

View file

@ -0,0 +1,260 @@
/***************************************************************************/
/* */
/* ftserv.h */
/* */
/* The FreeType services (specification only). */
/* */
/* Copyright 2003 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* Each module can export one or more `services'. Each service is */
/* identified by a constant string and modeled by a pointer; the latter */
/* generally corresponds to a structure containing function pointers. */
/* */
/* Note that a service's data cannot be a mere function pointer because */
/* in C it is possible that function pointers might be implemented */
/* differently than data pointers (e.g. 48 bits instead of 32). */
/* */
/*************************************************************************/
#ifndef __FTSERV_H__
#define __FTSERV_H__
FT_BEGIN_HEADER
/*
* @macro:
* FT_FACE_FIND_SERVICE
*
* @description:
* This macro is used to look up a service from a face's driver module.
*
* @input:
* face ::
* The source face handle.
*
* id ::
* A string describing the service as defined in the service's
* header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
* `multi-masters'). It is automatically prefixed with
* `FT_SERVICE_ID_'.
*
* @output:
* ptr ::
* A variable that receives the service pointer. Will be NULL
* if not found.
*/
#define FT_FACE_FIND_SERVICE( face, ptr, id ) \
FT_BEGIN_STMNT \
FT_Module module = FT_MODULE( FT_FACE(face)->driver ); \
/* the strange cast is to allow C++ compilation */ \
FT_Pointer* Pptr = (FT_Pointer*) &(ptr); \
\
\
*Pptr = NULL; \
if ( module->clazz->get_interface ) \
*Pptr = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
FT_END_STMNT
/*
* @macro:
* FT_FACE_FIND_GLOBAL_SERVICE
*
* @description:
* This macro is used to look up a service from all modules.
*
* @input:
* face ::
* The source face handle.
*
* id ::
* A string describing the service as defined in the service's
* header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
* `multi-masters'). It is automatically prefixed with
* `FT_SERVICE_ID_'.
*
* @output:
* ptr ::
* A variable that receives the service pointer. Will be NULL
* if not found.
*/
#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \
FT_BEGIN_STMNT \
FT_Module module = FT_MODULE( FT_FACE(face)->driver ); \
/* the strange cast is to allow C++ compilation */ \
FT_Pointer* Pptr = (FT_Pointer*) &(ptr); \
\
\
*Pptr = ft_module_get_service( module, FT_SERVICE_ID_ ## id ); \
FT_END_STMNT
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** S E R V I C E D E S C R I P T O R S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
* The following structure is used to _describe_ a given service
* to the library. This is useful to build simple static service lists.
*/
typedef struct FT_ServiceDescRec_
{
const char* serv_id; /* service name */
const void* serv_data; /* service pointer/data */
} FT_ServiceDescRec;
typedef const FT_ServiceDescRec* FT_ServiceDesc;
/*
* Parse a list of FT_ServiceDescRec descriptors and look for
* a specific service by ID. Note that the last element in the
* array must be { NULL, NULL }, and that the function should
* return NULL if the service isn't available.
*
* This function can be used by modules to implement their
* `get_service' method.
*/
FT_BASE( FT_Pointer )
ft_service_list_lookup( FT_ServiceDesc service_descriptors,
const char* service_id );
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** S E R V I C E S C A C H E *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
* This structure is used to store a cache for several frequently used
* services. It is the type of `face->internal->services'. You
* should only use FT_FACE_LOOKUP_SERVICE to access it.
*
* All fields should have the type FT_Pointer to relax compilation
* dependencies. We assume the developer isn't completely stupid.
*
* Each field must be named `service_XXXX' where `XXX' corresponds to
* the correct FT_SERVICE_ID_XXXX macro. See the definition of
* FT_FACE_LOOKUP_SERVICE below how this is implemented.
*
*/
typedef struct FT_ServiceCacheRec_
{
FT_Pointer service_POSTSCRIPT_FONT_NAME;
FT_Pointer service_MULTI_MASTERS;
FT_Pointer service_GLYPH_DICT;
FT_Pointer service_PFR_METRICS;
FT_Pointer service_WINFNT;
} FT_ServiceCacheRec, *FT_ServiceCache;
/*
* A magic number used within the services cache.
*/
#define FT_SERVICE_UNAVAILABLE ((FT_Pointer)-2) /* magic number */
/*
* @macro:
* FT_FACE_LOOKUP_SERVICE
*
* @description:
* This macro is used to lookup a service from a face's driver module
* using its cache.
*
* @input:
* face::
* The source face handle containing the cache.
*
* field ::
* The field name in the cache.
*
* id ::
* The service ID.
*
* @output:
* ptr ::
* A variable receiving the service data. NULL if not available.
*/
#define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \
FT_BEGIN_STMNT \
/* the strange cast is to allow C++ compilation */ \
FT_Pointer* pptr = (FT_Pointer*)&(ptr); \
FT_Pointer svc; \
\
\
svc = FT_FACE(face)->internal->services. service_ ## id ; \
if ( svc == FT_SERVICE_UNAVAILABLE ) \
svc = NULL; \
else if ( svc == NULL ) \
{ \
FT_FACE_FIND_SERVICE( face, svc, id ); \
\
FT_FACE(face)->internal->services. service_ ## id = \
(FT_Pointer)( svc != NULL ? svc \
: FT_SERVICE_UNAVAILABLE ); \
} \
*pptr = svc; \
FT_END_STMNT
/*
* A macro used to define new service structure types.
*/
#define FT_DEFINE_SERVICE( name ) \
typedef struct FT_Service_ ## name ## Rec_ \
FT_Service_ ## name ## Rec ; \
typedef struct FT_Service_ ## name ## Rec_ \
const * FT_Service_ ## name ; \
struct FT_Service_ ## name ## Rec_
/* */
/*
* The header files containing the services.
*/
#define FT_SERVICE_MULTIPLE_MASTERS_H <freetype/internal/services/svmm.h>
#define FT_SERVICE_POSTSCRIPT_NAME_H <freetype/internal/services/svpostnm.h>
#define FT_SERVICE_POSTSCRIPT_CMAPS_H <freetype/internal/services/svpscmap.h>
#define FT_SERVICE_POSTSCRIPT_INFO_H <freetype/internal/services/svpsinfo.h>
#define FT_SERVICE_GLYPH_DICT_H <freetype/internal/services/svgldict.h>
#define FT_SERVICE_BDF_H <freetype/internal/services/svbdf.h>
#define FT_SERVICE_XFREE86_NAME_H <freetype/internal/services/svxf86nm.h>
#define FT_SERVICE_SFNT_H <freetype/internal/services/svsfnt.h>
#define FT_SERVICE_PFR_H <freetype/internal/services/svpfr.h>
#define FT_SERVICE_WINFNT_H <freetype/internal/services/svwinfnt.h>
#define FT_SERVICE_TT_CMAP_H <freetype/internal/services/svttcmap.h>
/* */
FT_END_HEADER
#endif /* __FTSERV_H__ */
/* END */

View file

@ -0,0 +1,57 @@
/***************************************************************************/
/* */
/* svbdf.h */
/* */
/* The FreeType BDF services (specification). */
/* */
/* Copyright 2003 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. */
/* */
/***************************************************************************/
#ifndef __SVBDF_H__
#define __SVBDF_H__
#include FT_BDF_H
#include FT_INTERNAL_SERVICE_H
FT_BEGIN_HEADER
#define FT_SERVICE_ID_BDF "bdf"
typedef FT_Error
(*FT_BDF_GetCharsetIdFunc)( FT_Face face,
const char* *acharset_encoding,
const char* *acharset_registry );
typedef FT_Error
(*FT_BDF_GetPropertyFunc)( FT_Face face,
const char* prop_name,
BDF_PropertyRec *aproperty );
FT_DEFINE_SERVICE( BDF )
{
FT_BDF_GetCharsetIdFunc get_charset_id;
FT_BDF_GetPropertyFunc get_property;
};
/* */
FT_END_HEADER
#endif /* __SVBDF_H__ */
/* END */

View file

@ -0,0 +1,60 @@
/***************************************************************************/
/* */
/* svgldict.h */
/* */
/* The FreeType glyph dictionary services (specification). */
/* */
/* Copyright 2003 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. */
/* */
/***************************************************************************/
#ifndef __SVGLDICT_H__
#define __SVGLDICT_H__
#include FT_INTERNAL_SERVICE_H
FT_BEGIN_HEADER
/*
* A service used to retrieve glyph names, as well as to find the
* index of a given glyph name in a font.
*
*/
#define FT_SERVICE_ID_GLYPH_DICT "glyph-dict"
typedef FT_Error
(*FT_GlyphDict_GetNameFunc)( FT_Face face,
FT_UInt glyph_index,
FT_Pointer buffer,
FT_UInt buffer_max );
typedef FT_UInt
(*FT_GlyphDict_NameIndexFunc)( FT_Face face,
FT_String* glyph_name );
FT_DEFINE_SERVICE( GlyphDict )
{
FT_GlyphDict_GetNameFunc get_name;
FT_GlyphDict_NameIndexFunc name_index; /* optional */
};
/* */
FT_END_HEADER
#endif /* __SVGLDICT_H__ */

View file

@ -0,0 +1,68 @@
/***************************************************************************/
/* */
/* svmm.h */
/* */
/* The FreeType Multiple Masters services (specification). */
/* */
/* Copyright 2003 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. */
/* */
/***************************************************************************/
#ifndef __SVMM_H__
#define __SVMM_H__
#include FT_INTERNAL_SERVICE_H
FT_BEGIN_HEADER
/*
* A service used to manage multiple-masters data in a given face.
*
* See the related APIs in `ftmm.h' (FT_MULTIPLE_MASTERS_H).
*
*/
#define FT_SERVICE_ID_MULTI_MASTERS "multi-masters"
typedef FT_Error
(*FT_Get_MM_Func)( FT_Face face,
FT_Multi_Master* master );
typedef FT_Error
(*FT_Set_MM_Design_Func)( FT_Face face,
FT_UInt num_coords,
FT_Long* coords );
typedef FT_Error
(*FT_Set_MM_Blend_Func)( FT_Face face,
FT_UInt num_coords,
FT_Long* coords );
FT_DEFINE_SERVICE( MultiMasters )
{
FT_Get_MM_Func get_mm;
FT_Set_MM_Design_Func set_mm_design;
FT_Set_MM_Blend_Func set_mm_blend;
};
/* */
FT_END_HEADER
#endif /* __SVMM_H__ */
/* END */

View file

@ -0,0 +1,65 @@
/***************************************************************************/
/* */
/* svpfr.h */
/* */
/* Internal PFR service functions (specification). */
/* */
/* Copyright 2003 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. */
/* */
/***************************************************************************/
#ifndef __SVPFR_H__
#define __SVPFR_H__
#include FT_INTERNAL_SERVICE_H
FT_BEGIN_HEADER
#define FT_SERVICE_ID_PFR_METRICS "pfr-metrics"
typedef FT_Error
(*FT_PFR_GetMetricsFunc)( FT_Face face,
FT_UInt *aoutline,
FT_UInt *ametrics,
FT_Fixed *ax_scale,
FT_Fixed *ay_scale );
typedef FT_Error
(*FT_PFR_GetKerningFunc)( FT_Face face,
FT_UInt left,
FT_UInt right,
FT_Vector *avector );
typedef FT_Error
(*FT_PFR_GetAdvanceFunc)( FT_Face face,
FT_UInt gindex,
FT_Pos *aadvance );
FT_DEFINE_SERVICE( PfrMetrics )
{
FT_PFR_GetMetricsFunc get_metrics;
FT_PFR_GetKerningFunc get_kerning;
FT_PFR_GetAdvanceFunc get_advance;
};
/* */
FT_END_HEADER
#endif /* __SVPFR_H__ */
/* END */

View file

@ -0,0 +1,58 @@
/***************************************************************************/
/* */
/* svpostnm.h */
/* */
/* The FreeType PostScript name services (specification). */
/* */
/* Copyright 2003 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. */
/* */
/***************************************************************************/
#ifndef __SVPOSTNM_H__
#define __SVPOSTNM_H__
#include FT_INTERNAL_SERVICE_H
FT_BEGIN_HEADER
/*
* A trivial service used to retrieve the PostScript name of a given
* font when available. The `get_name' field should never be NULL.
*
* The correponding function can return NULL to indicate that the
* PostScript name is not available.
*
* The name is owned by the face and will be destroyed with it.
*/
#define FT_SERVICE_ID_POSTSCRIPT_FONT_NAME "postscript-font-name"
typedef const char*
(*FT_PsName_GetFunc)( FT_Face face );
FT_DEFINE_SERVICE( PsFontName )
{
FT_PsName_GetFunc get_ps_font_name;
};
/* */
FT_END_HEADER
#endif /* __SVPOSTNM_H__ */
/* END */

View file

@ -0,0 +1,113 @@
/***************************************************************************/
/* */
/* svpscmap.h */
/* */
/* The FreeType PostScript charmap service (specification). */
/* */
/* Copyright 2003 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. */
/* */
/***************************************************************************/
#ifndef __SVPSCMAP_H__
#define __SVPSCMAP_H__
FT_BEGIN_HEADER
#define FT_SERVICE_ID_POSTSCRIPT_CMAPS "postscript-cmaps"
/*
* Adobe glyph name to unicode value
*/
typedef FT_UInt32
(*PS_Unicode_ValueFunc)( const char* glyph_name );
/*
* Unicode value to Adobe glyph name index. 0xFFFF if not found.
*/
typedef FT_UInt
(*PS_Unicode_Index_Func)( FT_UInt num_glyphs,
const char** glyph_names,
FT_ULong unicode );
/*
* Macintosh name id to glyph name. NULL if invalid index.
*/
typedef const char*
(*PS_Macintosh_Name_Func)( FT_UInt name_index );
/*
* Adobe standard string ID to glyph name. NULL if invalid index.
*/
typedef const char*
(*PS_Adobe_Std_Strings_Func)( FT_UInt string_index );
/*
* Simple unicode -> glyph index charmap built from font glyph names
* table.
*/
typedef struct PS_UniMap_
{
FT_UInt unicode;
FT_UInt glyph_index;
} PS_UniMap;
typedef struct PS_Unicodes_
{
FT_UInt num_maps;
PS_UniMap* maps;
} PS_Unicodes;
typedef FT_Error
(*PS_Unicodes_InitFunc)( FT_Memory memory,
FT_UInt num_glyphs,
const char** glyph_names,
PS_Unicodes* unicodes );
typedef FT_UInt
(*PS_Unicodes_CharIndexFunc)( PS_Unicodes* unicodes,
FT_UInt unicode );
typedef FT_ULong
(*PS_Unicodes_CharNextFunc)( PS_Unicodes* unicodes,
FT_ULong unicode );
FT_DEFINE_SERVICE( PsCMaps )
{
PS_Unicode_ValueFunc unicode_value;
PS_Unicodes_InitFunc unicodes_init;
PS_Unicodes_CharIndexFunc unicodes_char_index;
PS_Unicodes_CharNextFunc unicodes_char_next;
PS_Macintosh_Name_Func macintosh_name;
PS_Adobe_Std_Strings_Func adobe_std_strings;
const unsigned short* adobe_std_encoding;
const unsigned short* adobe_expert_encoding;
};
/* */
FT_END_HEADER
#endif /* __SVPSCMAP_H__ */
/* END */

View file

@ -0,0 +1,55 @@
/***************************************************************************/
/* */
/* svpsinfo.h */
/* */
/* The FreeType PostScript info service (specification). */
/* */
/* Copyright 2003 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. */
/* */
/***************************************************************************/
#ifndef __SVPSINFO_H__
#define __SVPSINFO_H__
#include FT_INTERNAL_SERVICE_H
#include FT_INTERNAL_TYPE1_TYPES_H
FT_BEGIN_HEADER
#define FT_SERVICE_ID_POSTSCRIPT_INFO "postscript-info"
typedef FT_Error
(*PS_GetFontInfoFunc)( FT_Face face,
PS_FontInfoRec* afont_info );
typedef FT_Int
(*PS_HasGlyphNamesFunc)( FT_Face face );
FT_DEFINE_SERVICE( PsInfo )
{
PS_GetFontInfoFunc ps_get_font_info;
PS_HasGlyphNamesFunc ps_has_glyph_names;
};
/* */
FT_END_HEADER
#endif /* __SVPSINFO_H__ */
/* END */

View file

@ -0,0 +1,69 @@
/***************************************************************************/
/* */
/* svsfnt.h */
/* */
/* The FreeType PostScript name services (specification). */
/* */
/* Copyright 2003 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. */
/* */
/***************************************************************************/
#ifndef __SVSFNT_H__
#define __SVSFNT_H__
#include FT_INTERNAL_SERVICE_H
#include FT_TRUETYPE_TABLES_H
FT_BEGIN_HEADER
/*
* SFNT table loading service.
*/
#define FT_SERVICE_ID_SFNT_TABLE "sfnt-table"
/*
* Used to implement FT_Load_Sfnt_Table().
*/
typedef FT_Error
(*FT_SFNT_TableLoadFunc)( FT_Face face,
FT_ULong tag,
FT_Long offset,
FT_Byte* buffer,
FT_ULong* length );
/*
* Used to implement FT_Get_Sfnt_Table().
*/
typedef void*
(*FT_SFNT_TableGetFunc)( FT_Face face,
FT_Sfnt_Tag tag );
FT_DEFINE_SERVICE( SFNT_Table )
{
FT_SFNT_TableLoadFunc load_table;
FT_SFNT_TableGetFunc get_table;
};
/* */
FT_END_HEADER
#endif /* __SVSFNT_H__ */
/* END */

View file

@ -0,0 +1,77 @@
/***************************************************************************/
/* */
/* svsttcmap.h */
/* */
/* The FreeType TrueType/sfnt cmap extra information service. */
/* */
/* Copyright 2003 by */
/* Masatake YAMATO, Redhat K.K. */
/* */
/* Copyright 2003 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. */
/* */
/***************************************************************************/
/* Development of this service is support of
Information-technology Promotion Agency, Japan. */
#ifndef __SVTTCMAP_H__
#define __SVTTCMAP_H__
#include FT_INTERNAL_SERVICE_H
#include FT_TRUETYPE_TABLES_H
FT_BEGIN_HEADER
#define FT_SERVICE_ID_TT_CMAP "tt-cmaps"
/*************************************************************************/
/* */
/* <Struct> */
/* TT_CMapInfo */
/* */
/* <Description> */
/* A structure used to store TrueType/sfnt specific cmap information */
/* which is not covered by the generic @FT_CharMap structure. This */
/* structure can be accessed with the @FT_Get_TT_CMap_Info function. */
/* */
/* <Fields> */
/* language :: */
/* The language ID used in Mac fonts. Definitions of values are in */
/* freetype/ttnameid.h. */
/* */
typedef struct TT_CMapInfo_
{
FT_ULong language;
} TT_CMapInfo;
typedef FT_Error
(*TT_CMap_Info_GetFunc)( FT_CharMap charmap,
TT_CMapInfo *cmap_info );
FT_DEFINE_SERVICE( TTCMaps )
{
TT_CMap_Info_GetFunc get_cmap_info;
};
/* */
FT_END_HEADER
#endif /* __SVTTCMAP_H__ */
/* END */

View file

@ -0,0 +1,50 @@
/***************************************************************************/
/* */
/* svwinfnt.h */
/* */
/* The FreeType Windows FNT/FONT service (specification). */
/* */
/* Copyright 2003 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. */
/* */
/***************************************************************************/
#ifndef __SVWINFNT_H__
#define __SVWINFNT_H__
#include FT_INTERNAL_SERVICE_H
#include FT_WINFONTS_H
FT_BEGIN_HEADER
#define FT_SERVICE_ID_WINFNT "winfonts"
typedef FT_Error
(*FT_WinFnt_GetHeaderFunc)( FT_Face face,
FT_WinFNT_HeaderRec *aheader );
FT_DEFINE_SERVICE( WinFnt )
{
FT_WinFnt_GetHeaderFunc get_header;
};
/* */
FT_END_HEADER
#endif /* __SVWINFNT_H__ */
/* END */

View file

@ -0,0 +1,55 @@
/***************************************************************************/
/* */
/* svxf86nm.h */
/* */
/* The FreeType XFree86 services (specification only). */
/* */
/* Copyright 2003 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. */
/* */
/***************************************************************************/
#ifndef __SVXF86NM_H__
#define __SVXF86NM_H__
#include FT_INTERNAL_SERVICE_H
FT_BEGIN_HEADER
/*
* A trivial service used to return the name of a face's font driver,
* according to the XFree86 nomenclature. Note that the service data
* is a simple constant string pointer.
*/
#define FT_SERVICE_ID_XF86_NAME "xf86-driver-name"
#define FT_XF86_FORMAT_TRUETYPE "TrueType"
#define FT_XF86_FORMAT_TYPE_1 "Type 1"
#define FT_XF86_FORMAT_BDF "BDF"
#define FT_XF86_FORMAT_PCF "PCF"
#define FT_XF86_FORMAT_TYPE_42 "Type 42"
#define FT_XF86_FORMAT_CID "CID Type 1"
#define FT_XF86_FORMAT_CFF "CFF"
#define FT_XF86_FORMAT_PFR "PFR"
#define FT_XF86_FORMAT_WINFNT "Windows FNT"
/* */
FT_END_HEADER
#endif /* __SVXF86NM_H__ */
/* END */

View file

@ -0,0 +1,18 @@
SubDir FT2_TOP src autofit ;
{
local _sources ;
if $(FT2_MULTI)
{
_sources = afangles afglobal afhints aflatin afloader afmodule ;
}
else
{
_sources = autofit ;
}
Library $(FT2_LIB) : $(_sources).c ;
}
# end of src/autofir Jamfile

View file

@ -0,0 +1,214 @@
#include "aftypes.h"
/* this table was generated for AF_ANGLE_PI = 256 */
#define AF_ANGLE_MAX_ITERS 8
#define AF_TRIG_MAX_ITERS 9
static const FT_Fixed
af_angle_arctan_table[9] =
{
90, 64, 38, 20, 10, 5, 3, 1, 1
};
static FT_Int
af_angle_prenorm( FT_Vector* vec )
{
FT_Fixed x, y, z;
FT_Int shift;
x = vec->x;
y = vec->y;
z = ( ( x >= 0 ) ? x : - x ) | ( (y >= 0) ? y : -y );
shift = 0;
if ( z < ( 1L << 27 ) )
{
do
{
shift++;
z <<= 1;
} while ( z < ( 1L << 27 ) );
vec->x = x << shift;
vec->y = y << shift;
}
else if ( z > ( 1L << 28 ) )
{
do
{
shift++;
z >>= 1;
} while ( z > ( 1L << 28 ) );
vec->x = x >> shift;
vec->y = y >> shift;
shift = -shift;
}
return shift;
}
static void
af_angle_pseudo_polarize( FT_Vector* vec )
{
FT_Fixed theta;
FT_Fixed yi, i;
FT_Fixed x, y;
const FT_Fixed *arctanptr;
x = vec->x;
y = vec->y;
/* Get the vector into the right half plane */
theta = 0;
if ( x < 0 )
{
x = -x;
y = -y;
theta = 2 * AF_ANGLE_PI2;
}
if ( y > 0 )
theta = - theta;
arctanptr = af_angle_arctan_table;
if ( y < 0 )
{
/* Rotate positive */
yi = y + ( x << 1 );
x = x - ( y << 1 );
y = yi;
theta -= *arctanptr++; /* Subtract angle */
}
else
{
/* Rotate negative */
yi = y - ( x << 1 );
x = x + ( y << 1 );
y = yi;
theta += *arctanptr++; /* Add angle */
}
i = 0;
do
{
if ( y < 0 )
{
/* Rotate positive */
yi = y + ( x >> i );
x = x - ( y >> i );
y = yi;
theta -= *arctanptr++;
}
else
{
/* Rotate negative */
yi = y - ( x >> i );
x = x + ( y >> i );
y = yi;
theta += *arctanptr++;
}
} while ( ++i < AF_TRIG_MAX_ITERS );
/* round theta */
if ( theta >= 0 )
theta = FT_PAD_ROUND( theta, 4 );
else
theta = - FT_PAD_ROUND( theta, 4 );
vec->x = x;
vec->y = theta;
}
/* documentation is in fttrigon.h */
FT_LOCAL_DEF( AF_Angle )
af_angle_atan( FT_Fixed dx,
FT_Fixed dy )
{
FT_Vector v;
if ( dx == 0 && dy == 0 )
return 0;
v.x = dx;
v.y = dy;
af_angle_prenorm( &v );
af_angle_pseudo_polarize( &v );
return v.y;
}
FT_LOCAL_DEF( AF_Angle )
af_angle_diff( AF_Angle angle1,
AF_Angle angle2 )
{
AF_Angle delta = angle2 - angle1;
delta %= AF_ANGLE_2PI;
if ( delta < 0 )
delta += AF_ANGLE_2PI;
if ( delta > AF_ANGLE_PI )
delta -= AF_ANGLE_2PI;
return delta;
}
/* well, this needs to be somewhere, right :-)
*/
FT_LOCAL_DEF( void )
af_sort_pos( FT_UInt count,
FT_Pos* table )
{
FT_UInt i, j;
FT_Pos swap;
for ( i = 1; i < count; i++ )
{
for ( j = i; j > 0; j-- )
{
if ( table[j] > table[j - 1] )
break;
swap = table[j];
table[j] = table[j - 1];
table[j - 1] = swap;
}
}
}
FT_LOCAL_DEF( void )
af_sort_widths( FT_UInt count,
AF_Width table )
{
FT_UInt i, j;
AF_WidthRec swap;
for ( i = 1; i < count; i++ )
{
for ( j = i; j > 0; j-- )
{
if ( table[j].org > table[j - 1].org )
break;
swap = table[j];
table[j] = table[j - 1];
table[j - 1] = swap;
}
}
}

View file

@ -0,0 +1,231 @@
#include "afglobal.h"
#include "aflatin.h"
/* populate this list when you add new scripts
*/
static AF_ScriptClass const af_script_classes[] =
{
& af_latin_script_class,
NULL /* do not remove */
};
#define AF_SCRIPT_LIST_DEFAULT 0 /* index of default script in 'af_script_classes' */
#define AF_SCRIPT_LIST_NONE 255 /* indicates an uncovered glyph */
/*
* note that glyph_scripts[] is used to map each glyph into
* an index into the 'af_script_classes' array.
*
*/
typedef struct AF_FaceGlobalsRec_
{
FT_Face face;
FT_UInt glyph_count; /* same as face->num_glyphs */
FT_Byte* glyph_scripts;
AF_ScriptMetrics metrics[ AF_SCRIPT_MAX ];
} AF_FaceGlobalsRec;
/* this function is used to compute the script index of each glyph
* within a given face
*/
static FT_Error
af_face_globals_compute_script_coverage( AF_FaceGlobals globals )
{
FT_Error error = 0;
FT_Face face = globals->face;
FT_CharMap old_charmap = face->charmap;
FT_Byte* gscripts = globals->glyph_scripts;
FT_UInt ss;
/* the value 255 means "uncovered glyph"
*/
FT_MEM_SET( globals->glyph_scripts,
AF_SCRIPT_LIST_NONE,
globals->glyph_count );
error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
if ( error )
{
/* ignore this error, we'll simply use Latin as the standard
* script. XXX: Shouldn't we rather disable hinting ??
*/
error = 0;
goto Exit;
}
/* scan each script in a Unicode charmap
*/
for ( ss = 0; af_script_classes[ss]; ss++ )
{
AF_ScriptClass clazz = af_script_classes[ss];
AF_Script_UniRange range;
/* scan all unicode points in the range, and set the corresponding
* glyph script index
*/
for ( range = clazz->script_uni_ranges; range->first != 0; range++ )
{
FT_ULong charcode = range->first;
FT_UInt gindex;
gindex = FT_Get_Char_Index( face, charcode );
if ( gindex != 0 &&
gindex < globals->glyph_count &&
gscripts[ gindex ] == AF_SCRIPT_LIST_NONE )
{
gscripts[ gindex ] = (FT_Byte) ss;
}
for (;;)
{
charcode = FT_Get_Next_Char( face, charcode, &gindex );
if ( gindex == 0 || charcode > range->last )
break;
if ( gindex < globals->glyph_count &&
gscripts[ gindex ] == AF_SCRIPT_LIST_NONE )
{
gscripts[ gindex ] = (FT_Byte) ss;
}
}
}
}
Exit:
/* by default, all uncovered glyphs are set to the latin script
* XXX: shouldnt' we disable hinting or do something similar ?
*/
{
FT_UInt nn;
for ( nn = 0; nn < globals->glyph_count; nn++ )
{
if ( gscripts[ nn ] == AF_SCRIPT_LIST_NONE )
gscripts[ nn ] = AF_SCRIPT_LIST_DEFAULT;
}
}
FT_Set_Charmap( face, old_charmap );
return error;
}
FT_LOCAL_DEF( FT_Error )
af_face_globals_new( FT_Face face,
AF_FaceGlobals *aglobals )
{
FT_Error error;
FT_Memory memory;
AF_FaceGlobals globals;
memory = face->memory;
if ( !FT_ALLOC( globals, sizeof(*globals) +
face->num_glyphs*sizeof(FT_Byte) ) )
{
globals->face = face;
globals->glyph_count = face->num_glyphs;
globals->glyph_scripts = (FT_Byte*)( globals+1 );
error = af_face_globals_compute_script_coverage( globals );
if ( error )
{
af_face_globals_free( globals );
globals = NULL;
}
}
*aglobals = globals;
return error;
}
FT_LOCAL_DEF( void )
af_face_globals_free( AF_FaceGlobals globals )
{
if ( globals )
{
FT_Memory memory = globals->face->memory;
FT_UInt nn;
for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ )
{
if ( globals->metrics[nn] )
{
AF_ScriptClass clazz = af_script_classes[nn];
FT_ASSERT( globals->metrics[nn]->clazz == clazz );
if ( clazz->script_metrics_done )
clazz->script_metrics_done( globals->metrics[nn] );
FT_FREE( globals->metrics[nn] );
}
}
globals->glyph_count = 0;
globals->glyph_scripts = NULL; /* no need to free this one !! */
globals->face = NULL;
FT_FREE( globals );
}
}
FT_LOCAL_DEF( FT_Error )
af_face_globals_get_metrics( AF_FaceGlobals globals,
FT_UInt gindex,
AF_ScriptMetrics *ametrics )
{
AF_ScriptMetrics metrics = NULL;
FT_UInt index;
AF_ScriptClass clazz;
FT_Error error = 0;
if ( gindex >= globals->glyph_count )
{
error = FT_Err_Invalid_Argument;
goto Exit;
}
index = globals->glyph_scripts[ gindex ];
clazz = af_script_classes[ index ];
metrics = globals->metrics[ clazz->script ];
if ( metrics == NULL )
{
/* create the global metrics object when needed
*/
FT_Memory memory = globals->face->memory;
if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
goto Exit;
metrics->clazz = clazz;
if ( clazz->script_metrics_init )
{
error = clazz->script_metrics_init( metrics, globals->face );
if ( error )
{
if ( clazz->script_metrics_done )
clazz->script_metrics_done( metrics );
FT_FREE( metrics );
goto Exit;
}
}
globals->metrics[ clazz->script ] = metrics;
}
Exit:
*ametrics = metrics;
return error;
}

View file

@ -0,0 +1,41 @@
#ifndef __AF_GLOBAL_H__
#define __AF_GLOBAL_H__
#include "aftypes.h"
FT_BEGIN_HEADER
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** F A C E G L O B A L S *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
/*
* models the global hints data for a given face, decomposed into
* script-specific items..
*
*/
typedef struct AF_FaceGlobalsRec_* AF_FaceGlobals;
FT_LOCAL( FT_Error )
af_face_globals_new( FT_Face face,
AF_FaceGlobals *aglobals );
FT_LOCAL( FT_Error )
af_face_globals_get_metrics( AF_FaceGlobals globals,
FT_UInt gindex,
AF_ScriptMetrics *ametrics );
FT_LOCAL( void )
af_face_globals_free( AF_FaceGlobals globals );
/* */
FT_END_HEADER
#endif /* __AF_GLOBALS_H__ */

View file

@ -0,0 +1,934 @@
#include "afhints.h"
#ifdef AF_DEBUG
#include <stdio.h>
void
af_glyph_hints_dump_edges( AF_GlyphHints hints )
{
AF_Edge edges;
AF_Edge edge_limit;
AF_Segment segments;
FT_Int dimension;
edges = hints->horz_edges;
edge_limit = edges + hints->num_hedges;
segments = hints->horz_segments;
for ( dimension = 1; dimension >= 0; dimension-- )
{
AF_Edge edge;
printf ( "Table of %s edges:\n",
!dimension ? "vertical" : "horizontal" );
printf ( " [ index | pos | dir | link |"
" serif | blue | opos | pos ]\n" );
for ( edge = edges; edge < edge_limit; edge++ )
{
printf ( " [ %5d | %4d | %5s | %4d | %5d | %c | %5.2f | %5.2f ]\n",
edge - edges,
(int)edge->fpos,
edge->dir == AF_DIR_UP
? "up"
: ( edge->dir == AF_DIR_DOWN
? "down"
: ( edge->dir == AF_DIR_LEFT
? "left"
: ( edge->dir == AF_DIR_RIGHT
? "right"
: "none" ) ) ),
edge->link ? ( edge->link - edges ) : -1,
edge->serif ? ( edge->serif - edges ) : -1,
edge->blue_edge ? 'y' : 'n',
edge->opos / 64.0,
edge->pos / 64.0 );
}
edges = hints->vert_edges;
edge_limit = edges + hints->num_vedges;
segments = hints->vert_segments;
}
}
/* A function used to dump the array of linked segments */
void
af_glyph_hints_dump_segments( AF_GlyphHints hints )
{
AF_Segment segments;
AF_Segment segment_limit;
AF_Point points;
FT_Int dimension;
points = hints->points;
segments = hints->horz_segments;
segment_limit = segments + hints->num_hsegments;
for ( dimension = 1; dimension >= 0; dimension-- )
{
AF_Segment seg;
printf ( "Table of %s segments:\n",
!dimension ? "vertical" : "horizontal" );
printf ( " [ index | pos | dir | link | serif |"
" numl | first | start ]\n" );
for ( seg = segments; seg < segment_limit; seg++ )
{
printf ( " [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n",
seg - segments,
(int)seg->pos,
seg->dir == AF_DIR_UP
? "up"
: ( seg->dir == AF_DIR_DOWN
? "down"
: ( seg->dir == AF_DIR_LEFT
? "left"
: ( seg->dir == AF_DIR_RIGHT
? "right"
: "none" ) ) ),
seg->link ? ( seg->link - segments ) : -1,
seg->serif ? ( seg->serif - segments ) : -1,
(int)seg->num_linked,
seg->first - points,
seg->last - points );
}
segments = hints->vert_segments;
segment_limit = segments + hints->num_vsegments;
}
}
#endif /* AF_DEBUG */
/* compute the direction value of a given vector */
FT_LOCAL_DEF( AF_Direction )
af_direction_compute( FT_Pos dx,
FT_Pos dy )
{
AF_Direction dir;
FT_Pos ax = ABS( dx );
FT_Pos ay = ABS( dy );
dir = AF_DIR_NONE;
/* atan(1/12) == 4.7 degrees */
/* test for vertical direction */
if ( ax * 12 < ay )
{
dir = dy > 0 ? AF_DIR_UP : AF_DIR_DOWN;
}
/* test for horizontal direction */
else if ( ay * 12 < ax )
{
dir = dx > 0 ? AF_DIR_RIGHT : AF_DIR_LEFT;
}
return dir;
}
/* compute all inflex points in a given glyph */
static void
af_glyph_hints_compute_inflections( AF_GlyphHints hints )
{
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
/* do each contour separately */
for ( ; contour < contour_limit; contour++ )
{
AF_Point point = contour[0];
AF_Point first = point;
AF_Point start = point;
AF_Point end = point;
AF_Point before;
AF_Point after;
AF_Angle angle_in, angle_seg, angle_out;
AF_Angle diff_in, diff_out;
FT_Int finished = 0;
/* compute first segment in contour */
first = point;
start = end = first;
do
{
end = end->next;
if ( end == first )
goto Skip;
} while ( end->fx == first->fx && end->fy == first->fy );
angle_seg = af_angle_atan( end->fx - start->fx,
end->fy - start->fy );
/* extend the segment start whenever possible */
before = start;
do
{
do
{
start = before;
before = before->prev;
if ( before == first )
goto Skip;
} while ( before->fx == start->fx && before->fy == start->fy );
angle_in = af_angle_atan( start->fx - before->fx,
start->fy - before->fy );
} while ( angle_in == angle_seg );
first = start;
diff_in = af_angle_diff( angle_in, angle_seg );
/* now, process all segments in the contour */
do
{
/* first, extend current segment's end whenever possible */
after = end;
do
{
do
{
end = after;
after = after->next;
if ( after == first )
finished = 1;
} while ( end->fx == after->fx && end->fy == after->fy );
angle_out = af_angle_atan( after->fx - end->fx,
after->fy - end->fy );
} while ( angle_out == angle_seg );
diff_out = af_angle_diff( angle_seg, angle_out );
if ( ( diff_in ^ diff_out ) < 0 )
{
/* diff_in and diff_out have different signs, we have */
/* inflection points here... */
do
{
start->flags |= AF_FLAG_INFLECTION;
start = start->next;
} while ( start != end );
start->flags |= AF_FLAG_INFLECTION;
}
start = end;
end = after;
angle_seg = angle_out;
diff_in = diff_out;
} while ( !finished );
Skip:
;
}
}
FT_LOCAL_DEF( void )
af_glyph_hints_init( AF_GlyphHints hints,
FT_Memory memory )
{
FT_ZERO( hints );
hints->memory = memory;
}
FT_LOCAL_DEF( void )
af_glyph_hints_done( AF_GlyphHints hints )
{
if ( hints && hints->memory )
{
FT_Memory memory = hints->memory;
AF_Dimension dim;
/* note that we don't need to free the segment and edge
* buffers, since they're really within the hints->points array
*/
for ( dim = 0; dim < 2; dim++ )
{
AF_AxisHints axis = &hints->axis[ dim ];
axis->num_segments = 0;
axis->num_edges = 0;
axis->segments = NULL;
axis->edges = NULL;
}
FT_FREE( hints->contours );
hints->max_contours = 0;
hints->num_contours = 0;
FT_FREE( hints->points );
hints->num_points = 0;
hints->max_points = 0;
hints->memory = NULL;
}
}
FT_LOCAL_DEF( FT_Error )
af_glyph_hints_reset( AF_GlyphHints hints,
AF_Scaler scaler,
FT_Outline* outline )
{
FT_Error error = FT_Err_Ok;
AF_Point points;
FT_UInt old_max, new_max;
FT_Fixed x_scale = scaler->x_scale;
FT_Fixed y_scale = scaler->y_scale;
FT_Pos x_delta = scaler->x_delta;
FT_Pos y_delta = scaler->y_delta;
FT_Memory memory = hints->memory;
hints->scaler_flags = scaler->flags;
hints->other_flags = 0;
hints->num_points = 0;
hints->num_contours = 0;
hints->axis[0].num_segments = 0;
hints->axis[0].num_edges = 0;
hints->axis[1].num_segments = 0;
hints->axis[1].num_edges = 0;
/* first of all, reallocate the contours array when necessary
*/
new_max = (FT_UInt) outline->n_contours;
old_max = hints->max_contours;
if ( new_max > old_max )
{
new_max = (new_max + 3) & ~3;
if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
goto Exit;
hints->max_contours = new_max;
}
/* then, reallocate the points, segments & edges arrays if needed --
* note that we reserved two additional point positions, used to
* hint metrics appropriately
*/
new_max = (FT_UInt)( outline->n_points + 2 );
old_max = hints->max_points;
if ( new_max > old_max )
{
FT_Byte* items;
FT_ULong off1, off2, off3;
/* we store in a single buffer the following arrays:
*
* - an array of N AF_PointRec items
* - an array of 2*N AF_SegmentRec items
* - an array of 2*N AF_EdgeRec items
*
*/
new_max = ( new_max + 2 + 7 ) & ~7;
#undef OFF_INCREMENT
#define OFF_INCREMENT( _off, _type, _count ) \
( FT_PAD_CEIL( _off, sizeof(_type) ) + (_count)*sizeof(_type))
off1 = OFF_INCREMENT( 0, AF_PointRec, new_max );
off2 = OFF_INCREMENT( off1, AF_SegmentRec, new_max );
off3 = OFF_INCREMENT( off2, AF_EdgeRec, new_max*2 );
FT_FREE( hints->points );
if ( FT_ALLOC( items, off3 ) )
{
hints->max_points = 0;
hints->axis[0].segments = NULL;
hints->axis[0].edges = NULL;
hints->axis[1].segments = NULL;
hints->axis[1].edges = NULL;
goto Exit;
}
/* readjust some pointers
*/
hints->max_points = new_max;
hints->points = (AF_Point) items;
hints->axis[0].segments = (AF_Segment)( items + off1 );
hints->axis[1].segments = hints->axis[0].segments + new_max;
hints->axis[0].edges = (AF_Edge) ( items + off2 );
hints->axis[1].edges = hints->axis[0].edges + new_max;
}
hints->num_points = outline->n_points;
hints->num_contours = outline->n_contours;
/* We can't rely on the value of `FT_Outline.flags' to know the fill */
/* direction used for a glyph, given that some fonts are broken (e.g. */
/* the Arphic ones). We thus recompute it each time we need to. */
/* */
hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_UP;
hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_LEFT;
if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
{
hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_DOWN;
hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_RIGHT;
}
hints->x_scale = x_scale;
hints->y_scale = y_scale;
hints->x_delta = x_delta;
hints->y_delta = y_delta;
points = hints->points;
if ( hints->num_points == 0 )
goto Exit;
{
AF_Point point;
AF_Point point_limit = points + hints->num_points;
/* compute coordinates & bezier flags */
{
FT_Vector* vec = outline->points;
char* tag = outline->tags;
for ( point = points; point < point_limit; point++, vec++, tag++ )
{
point->fx = vec->x;
point->fy = vec->y;
point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
switch ( FT_CURVE_TAG( *tag ) )
{
case FT_CURVE_TAG_CONIC:
point->flags = AF_FLAG_CONIC;
break;
case FT_CURVE_TAG_CUBIC:
point->flags = AF_FLAG_CUBIC;
break;
default:
point->flags = 0;
;
}
}
}
/* compute `next' and `prev' */
{
FT_Int contour_index;
AF_Point prev;
AF_Point first;
AF_Point end;
contour_index = 0;
first = points;
end = points + outline->contours[0];
prev = end;
for ( point = points; point < point_limit; point++ )
{
point->prev = prev;
if ( point < end )
{
point->next = point + 1;
prev = point;
}
else
{
point->next = first;
contour_index++;
if ( point + 1 < point_limit )
{
end = points + outline->contours[contour_index];
first = point + 1;
prev = end;
}
}
}
}
/* set-up the contours array */
{
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
short* end = outline->contours;
short idx = 0;
for ( ; contour < contour_limit; contour++, end++ )
{
contour[0] = points + idx;
idx = (short)( end[0] + 1 );
}
}
/* compute directions of in & out vectors */
{
for ( point = points; point < point_limit; point++ )
{
AF_Point prev;
AF_Point next;
FT_Pos in_x, in_y, out_x, out_y;
prev = point->prev;
in_x = point->fx - prev->fx;
in_y = point->fy - prev->fy;
point->in_dir = af_direction_compute( in_x, in_y );
next = point->next;
out_x = next->fx - point->fx;
out_y = next->fy - point->fy;
point->out_dir = af_direction_compute( out_x, out_y );
if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
{
Is_Weak_Point:
point->flags |= AF_FLAG_WEAK_INTERPOLATION;
}
else if ( point->out_dir == point->in_dir )
{
AF_Angle angle_in, angle_out, delta;
if ( point->out_dir != AF_DIR_NONE )
goto Is_Weak_Point;
angle_in = af_angle_atan( in_x, in_y );
angle_out = af_angle_atan( out_x, out_y );
delta = af_angle_diff( angle_in, angle_out );
if ( delta < 2 && delta > -2 )
goto Is_Weak_Point;
}
else if ( point->in_dir == -point->out_dir )
goto Is_Weak_Point;
}
}
}
/* compute inflection points
*/
af_glyph_hints_compute_inflections( hints );
Exit:
return error;
}
/*
*
* E D G E P O I N T G R I D - F I T T I N G
*
*/
FT_LOCAL_DEF( void )
af_glyph_hints_align_edge_points( AF_GlyphHints hints,
AF_Dimension dim )
{
AF_AxisHints axis = & hints->axis[ dim ];
AF_Edge edges = axis->edges;
AF_Edge edge_limit = edges + axis->num_edges;
AF_Edge edge;
for ( edge = edges; edge < edge_limit; edge++ )
{
/* move the points of each segment */
/* in each edge to the edge's position */
AF_Segment seg = edge->first;
do
{
AF_Point point = seg->first;
for (;;)
{
if ( dim == AF_DIMENSION_HORZ )
{
point->x = edge->pos;
point->flags |= AF_FLAG_TOUCH_X;
}
else
{
point->y = edge->pos;
point->flags |= AF_FLAG_TOUCH_Y;
}
if ( point == seg->last )
break;
point = point->next;
}
seg = seg->edge_next;
} while ( seg != edge->first );
}
}
/*
*
* S T R O N G P O I N T I N T E R P O L A T I O N
*
*/
/* hint the strong points -- this is equivalent to the TrueType `IP' */
/* hinting instruction */
FT_LOCAL_DEF( void )
af_glyph_hints_align_strong_points( AF_GlyphHints hints,
AF_Dimension dim )
{
AF_Point points = hints->points;
AF_Point point_limit = points + hints->num_points;
AF_AxisHints axis = &hints->axis[dim];
AF_Edge edges = axis->edges;
AF_Edge edge_limit = edges + axis->num_edges;
AF_Flags touch_flag;
if ( dim == AF_DIMENSION_HORZ )
touch_flag = AF_FLAG_TOUCH_X;
else
touch_flag = AF_FLAG_TOUCH_Y;
if ( edges < edge_limit )
{
AF_Point point;
AF_Edge edge;
for ( point = points; point < point_limit; point++ )
{
FT_Pos u, ou, fu; /* point position */
FT_Pos delta;
if ( point->flags & touch_flag )
continue;
/* if this point is candidate to weak interpolation, we will */
/* interpolate it after all strong points have been processed */
if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&
!( point->flags & AF_FLAG_INFLECTION ) )
continue;
if ( dim == AF_DIMENSION_VERT )
{
u = point->fy;
ou = point->oy;
}
else
{
u = point->fx;
ou = point->ox;
}
fu = u;
/* is the point before the first edge? */
edge = edges;
delta = edge->fpos - u;
if ( delta >= 0 )
{
u = edge->pos - ( edge->opos - ou );
goto Store_Point;
}
/* is the point after the last edge? */
edge = edge_limit - 1;
delta = u - edge->fpos;
if ( delta >= 0 )
{
u = edge->pos + ( ou - edge->opos );
goto Store_Point;
}
{
FT_UInt min, max, mid;
FT_Pos fpos;
/* find enclosing edges */
min = 0;
max = edge_limit - edges;
while ( min < max )
{
mid = ( max + min ) >> 1;
edge = edges + mid;
fpos = edge->fpos;
if ( u < fpos )
max = mid;
else if ( u > fpos )
min = mid + 1;
else
{
/* we are on the edge */
u = edge->pos;
goto Store_Point;
}
}
{
AF_Edge before = edges + min - 1;
AF_Edge after = edges + min + 0;
/* assert( before && after && before != after ) */
if ( before->scale == 0 )
before->scale = FT_DivFix( after->pos - before->pos,
after->fpos - before->fpos );
u = before->pos + FT_MulFix( fu - before->fpos,
before->scale );
}
}
Store_Point:
/* save the point position */
if ( dim == AF_DIMENSION_HORZ )
point->x = u;
else
point->y = u;
point->flags |= touch_flag;
}
}
}
/*
*
* W E A K P O I N T I N T E R P O L A T I O N
*
*/
static void
af_iup_shift( AF_Point p1,
AF_Point p2,
AF_Point ref )
{
AF_Point p;
FT_Pos delta = ref->u - ref->v;
for ( p = p1; p < ref; p++ )
p->u = p->v + delta;
for ( p = ref + 1; p <= p2; p++ )
p->u = p->v + delta;
}
static void
af_iup_interp( AF_Point p1,
AF_Point p2,
AF_Point ref1,
AF_Point ref2 )
{
AF_Point p;
FT_Pos u;
FT_Pos v1 = ref1->v;
FT_Pos v2 = ref2->v;
FT_Pos d1 = ref1->u - v1;
FT_Pos d2 = ref2->u - v2;
if ( p1 > p2 )
return;
if ( v1 == v2 )
{
for ( p = p1; p <= p2; p++ )
{
u = p->v;
if ( u <= v1 )
u += d1;
else
u += d2;
p->u = u;
}
return;
}
if ( v1 < v2 )
{
for ( p = p1; p <= p2; p++ )
{
u = p->v;
if ( u <= v1 )
u += d1;
else if ( u >= v2 )
u += d2;
else
u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
p->u = u;
}
}
else
{
for ( p = p1; p <= p2; p++ )
{
u = p->v;
if ( u <= v2 )
u += d2;
else if ( u >= v1 )
u += d1;
else
u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
p->u = u;
}
}
}
FT_LOCAL_DEF( void )
af_glyph_hints_align_weak_points( AF_GlyphHints hints,
AF_Dimension dim )
{
AF_Point points = hints->points;
AF_Point point_limit = points + hints->num_points;
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
AF_Flags touch_flag;
AF_Point point;
AF_Point end_point;
AF_Point first_point;
/* PASS 1: Move segment points to edge positions */
if ( dim == AF_DIMENSION_HORZ )
{
touch_flag = AF_FLAG_TOUCH_X;
for ( point = points; point < point_limit; point++ )
{
point->u = point->x;
point->v = point->ox;
}
}
else
{
touch_flag = AF_FLAG_TOUCH_Y;
for ( point = points; point < point_limit; point++ )
{
point->u = point->y;
point->v = point->oy;
}
}
point = points;
for ( ; contour < contour_limit; contour++ )
{
point = *contour;
end_point = point->prev;
first_point = point;
while ( point <= end_point && !( point->flags & touch_flag ) )
point++;
if ( point <= end_point )
{
AF_Point first_touched = point;
AF_Point cur_touched = point;
point++;
while ( point <= end_point )
{
if ( point->flags & touch_flag )
{
/* we found two successive touched points; we interpolate */
/* all contour points between them */
af_iup_interp( cur_touched + 1, point - 1,
cur_touched, point );
cur_touched = point;
}
point++;
}
if ( cur_touched == first_touched )
{
/* this is a special case: only one point was touched in the */
/* contour; we thus simply shift the whole contour */
af_iup_shift( first_point, end_point, cur_touched );
}
else
{
/* now interpolate after the last touched point to the end */
/* of the contour */
af_iup_interp( cur_touched + 1, end_point,
cur_touched, first_touched );
/* if the first contour point isn't touched, interpolate */
/* from the contour start to the first touched point */
if ( first_touched > points )
af_iup_interp( first_point, first_touched - 1,
cur_touched, first_touched );
}
}
}
/* now save the interpolated values back to x/y */
if ( dim == AF_DIMENSION_HORZ )
{
for ( point = points; point < point_limit; point++ )
point->x = point->u;
}
else
{
for ( point = points; point < point_limit; point++ )
point->y = point->u;
}
}

View file

@ -0,0 +1,241 @@
#ifndef __AFHINTS_H__
#define __AFHINTS_H__
#include "aftypes.h"
FT_BEGIN_HEADER
/*
* The definition of outline glyph hints. These are shared by all
* script analysis routines (until now)
*
*/
typedef enum
{
AF_DIMENSION_HORZ = 0, /* x coordinates, i.e. vertical segments & edges */
AF_DIMENSION_VERT = 1, /* y coordinates, i.e. horizontal segments & edges */
AF_DIMENSION_MAX /* do not remove */
} AF_Dimension;
/* hint directions -- the values are computed so that two vectors are */
/* in opposite directions iff `dir1+dir2 == 0' */
typedef enum
{
AF_DIR_NONE = 4,
AF_DIR_RIGHT = 1,
AF_DIR_LEFT = -1,
AF_DIR_UP = 2,
AF_DIR_DOWN = -2
} AF_Direction;
/* point hint flags */
typedef enum
{
AF_FLAG_NONE = 0,
/* point type flags */
AF_FLAG_CONIC = (1 << 0),
AF_FLAG_CUBIC = (1 << 1),
AF_FLAG_CONTROL = AF_FLAG_CONIC | AF_FLAG_CUBIC,
/* point extremum flags */
AF_FLAG_EXTREMA_X = (1 << 2),
AF_FLAG_EXTREMA_Y = (1 << 3),
/* point roundness flags */
AF_FLAG_ROUND_X = (1 << 4),
AF_FLAG_ROUND_Y = (1 << 5),
/* point touch flags */
AF_FLAG_TOUCH_X = (1 << 6),
AF_FLAG_TOUCH_Y = (1 << 7),
/* candidates for weak interpolation have this flag set */
AF_FLAG_WEAK_INTERPOLATION = (1 << 8),
/* all inflection points in the outline have this flag set */
AF_FLAG_INFLECTION = (1 << 9)
} AF_Flags;
/* edge hint flags */
typedef enum
{
AF_EDGE_NORMAL = 0,
AF_EDGE_ROUND = (1 << 0),
AF_EDGE_SERIF = (1 << 1),
AF_EDGE_DONE = (1 << 2)
} AF_Edge_Flags;
typedef struct AF_PointRec_* AF_Point;
typedef struct AF_SegmentRec_* AF_Segment;
typedef struct AF_EdgeRec_* AF_Edge;
typedef struct AF_PointRec_
{
AF_Flags flags; /* point flags used by hinter */
FT_Pos ox, oy; /* original, scaled position */
FT_Pos fx, fy; /* original, unscaled position (font units) */
FT_Pos x, y; /* current position */
FT_Pos u, v; /* current (x,y) or (y,x) depending on context */
AF_Direction in_dir; /* direction of inwards vector */
AF_Direction out_dir; /* direction of outwards vector */
AF_Point next; /* next point in contour */
AF_Point prev; /* previous point in contour */
} AF_PointRec;
typedef struct AF_SegmentRec_
{
AF_Edge_Flags flags; /* edge/segment flags for this segment */
AF_Direction dir; /* segment direction */
FT_Pos pos; /* position of segment */
FT_Pos min_coord; /* minimum coordinate of segment */
FT_Pos max_coord; /* maximum coordinate of segment */
AF_Edge edge; /* the segment's parent edge */
AF_Segment edge_next; /* link to next segment in parent edge */
AF_Segment link; /* (stem) link segment */
AF_Segment serif; /* primary segment for serifs */
FT_Pos num_linked; /* number of linked segments */
FT_Pos score; /* used during stem matching */
AF_Point first; /* first point in edge segment */
AF_Point last; /* last point in edge segment */
AF_Point* contour; /* ptr to first point of segment's contour */
} AF_SegmentRec;
typedef struct AF_EdgeRec_
{
FT_Pos fpos; /* original, unscaled position (font units) */
FT_Pos opos; /* original, scaled position */
FT_Pos pos; /* current position */
AF_Edge_Flags flags; /* edge flags */
AF_Direction dir; /* edge direction */
FT_Fixed scale; /* used to speed up interpolation between edges */
AF_Width blue_edge; /* non-NULL if this is a blue edge */
AF_Edge link;
AF_Edge serif;
FT_Int num_linked;
FT_Int score;
AF_Segment first;
AF_Segment last;
} AF_EdgeRec;
typedef struct AF_AxisHintsRec_
{
FT_Int num_segments;
AF_Segment segments;
FT_Int num_edges;
AF_Edge edges;
AF_Direction major_dir;
} AF_AxisHintsRec, *AF_AxisHints;
typedef struct AF_GlyphHintsRec_
{
FT_Memory memory;
FT_Fixed x_scale;
FT_Pos x_delta;
FT_Fixed y_scale;
FT_Pos y_delta;
FT_Pos edge_distance_threshold;
FT_Int max_points;
FT_Int num_points;
AF_Point points;
FT_Int max_contours;
FT_Int num_contours;
AF_Point* contours;
AF_AxisHintsRec axis[ AF_DIMENSION_MAX ];
FT_UInt32 scaler_flags; /* copy of scaler flags */
FT_UInt32 other_flags; /* free for script-specific implementations */
AF_ScriptMetrics metrics;
} AF_GlyphHintsRec;
#define AF_HINTS_TEST_SCALER(h,f) ( (h)->scaler_flags & (f) )
#define AF_HINTS_TEST_OTHER(h,f) ( (h)->other_flags & (f) )
#define AF_HINTS_DO_HORIZONTAL(h) \
!AF_HINTS_TEST_SCALER(h,AF_SCALER_FLAG_NO_HORIZONTAL)
#define AF_HINTS_DO_VERTICAL(h) \
!AF_HINTS_TEST_SCALER(h,AF_SCALER_FLAG_NO_VERTICAL)
#define AF_HINTS_DO_ADVANCE(h) \
!AF_HINTS_TEST_SCALER(h,AF_SCALER_FLAG_NO_ADVANCE)
FT_LOCAL( AF_Direction )
af_direction_compute( FT_Pos dx,
FT_Pos dy );
FT_LOCAL( void )
af_glyph_hints_init( AF_GlyphHints hints,
FT_Memory memory );
/* recomputes all AF_Point in a AF_GlyphHints from the definitions
* in a source outline
*/
FT_LOCAL( FT_Error )
af_glyph_hints_reset( AF_GlyphHints hints,
AF_Scaler scaler,
FT_Outline* outline );
FT_LOCAL( void )
af_glyph_hints_align_edge_points( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_glyph_hints_align_strong_points( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_glyph_hints_align_weak_points( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_glyph_hints_done( AF_GlyphHints hints );
/* */
FT_END_HEADER
#endif /* __AFHINTS_H__ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,169 @@
#ifndef __AFLATIN_H__
#define __AFLATIN_H__
#include "afhints.h"
FT_BEGIN_HEADER
/*
* the latin-specific script class
*
*/
FT_LOCAL( const AF_ScriptClassRec ) af_latin_script_class;
/***************************************************************************/
/***************************************************************************/
/***** *****/
/***** L A T I N G L O B A L M E T R I C S *****/
/***** *****/
/***************************************************************************/
/***************************************************************************/
/*
* the following declarations could be embedded in the file "aflatin.c"
* they've been made semi-public to allow alternate script hinters to
* re-use some of them
*/
/*
* Latin (global) metrics management
*
*/
enum
{
AF_LATIN_BLUE_CAPITAL_TOP,
AF_LATIN_BLUE_CAPITAL_BOTTOM,
AF_LATIN_BLUE_SMALL_F_TOP,
AF_LATIN_BLUE_SMALL_TOP,
AF_LATIN_BLUE_SMALL_BOTTOM,
AF_LATIN_BLUE_SMALL_MINOR,
AF_LATIN_BLUE_MAX
};
#define AF_LATIN_IS_TOP_BLUE( b ) ( (b) == AF_LATIN_BLUE_CAPITAL_TOP || \
(b) == AF_LATIN_BLUE_SMALL_F_TOP || \
(b) == AF_LATIN_BLUE_SMALL_TOP )
#define AF_LATIN_MAX_WIDTHS 16
#define AF_LATIN_MAX_BLUES AF_LATIN_BLUE_MAX
enum
{
AF_LATIN_BLUE_ACTIVE = (1 << 0),
AF_LATIN_BLUE_TOP = (1 << 1),
AF_LATIN_BLUE_FLAG_MAX
};
typedef struct AF_LatinBlueRec_
{
AF_WidthRec ref;
AF_WidthRec shoot;
FT_UInt flags;
} AF_LatinBlueRec, *AF_LatinBlue;
typedef struct AF_LatinAxisRec_
{
FT_Fixed scale;
FT_Pos delta;
FT_UInt width_count;
AF_WidthRec widths[ AF_LATIN_MAX_WIDTHS ];
FT_Pos edge_distance_threshold;
/* ignored for horizontal metrics */
FT_Bool control_overshoot;
FT_UInt blue_count;
AF_LatinBlueRec blues[ AF_LATIN_BLUE_MAX ];
FT_Fixed org_scale;
FT_Pos org_delta;
} AF_LatinAxisRec, *AF_LatinAxis;
typedef struct AF_LatinMetricsRec_
{
AF_ScriptMetricsRec root;
FT_UInt units_per_em;
AF_LatinAxisRec axis[ AF_DIMENSION_MAX ];
AF_ScalerRec scaler;
} AF_LatinMetricsRec, *AF_LatinMetrics;
FT_LOCAL( FT_Error )
af_latin_metrics_init( AF_LatinMetrics metrics,
FT_Face face );
FT_LOCAL( void )
af_latin_metrics_scale( AF_LatinMetrics metrics,
AF_Scaler scaler );
/***************************************************************************/
/***************************************************************************/
/***** *****/
/***** L A T I N G L Y P H A N A L Y S I S *****/
/***** *****/
/***************************************************************************/
/***************************************************************************/
enum
{
AF_LATIN_HINTS_HORZ_SNAP = (1 << 0), /* enable stem width snapping */
AF_LATIN_HINTS_VERT_SNAP = (1 << 1), /* enable stem height snapping */
AF_LATIN_HINTS_STEM_ADJUST = (1 << 2), /* enable stem width/height adjustment */
AF_LATIN_HINTS_MONO = (1 << 3) /* indicate 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)
/* this shouldn't normally be exported. However, other scripts might
* like to use this function as-is
*/
FT_LOCAL( void )
af_latin_hints_compute_segments( AF_GlyphHints hints,
AF_Dimension dim );
/* this shouldn't normally be exported. However, other scripts might
* want to use this function as-is
*/
FT_LOCAL( void )
af_latin_hints_link_segments( AF_GlyphHints hints,
AF_Dimension dim );
/* this shouldn't normally be exported. However, other scripts might
* want to use this function as-is
*/
FT_LOCAL( void )
af_latin_hints_compute_edges( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_latin_hints_detect_features( AF_GlyphHints hints,
AF_Dimension dim );
/* */
FT_END_HEADER
#endif /* __AFLATIN_H__ */

View file

@ -0,0 +1,431 @@
#include "afloader.h"
#include "afhints.h"
#include "afglobal.h"
#include "aflatin.h"
FT_LOCAL_DEF( FT_Error )
af_loader_init( AF_Loader loader,
FT_Memory memory )
{
FT_Error error;
FT_ZERO( loader );
af_glyph_hints_init( &loader->hints, memory );
error = FT_GlyphLoader_New( memory, &loader->gloader );
if ( !error )
{
error = FT_GlyphLoader_CreateExtra( loader->gloader );
if ( error )
{
FT_GlyphLoader_Done( loader->gloader );
loader->gloader = NULL;
}
}
return error;
}
FT_LOCAL_DEF( FT_Error )
af_loader_reset( AF_Loader loader,
FT_Face face )
{
FT_Error error = 0;
loader->face = face;
loader->gloader = face->glyph->internal->loader;
loader->globals = (AF_FaceGlobals) face->autohint.data;
if ( loader->globals == NULL )
{
error = af_face_globals_new( face, &loader->globals );
if ( !error )
{
face->autohint.data = (FT_Pointer) loader->globals;
face->autohint.finalizer = (FT_Generic_Finalizer) af_face_globals_free;
}
}
return error;
}
FT_LOCAL_DEF( void )
af_loader_done( AF_Loader loader )
{
loader->face = NULL;
loader->globals = NULL;
FT_GlyphLoader_Done( loader->gloader );
loader->gloader = NULL;
}
static FT_Error
af_loader_load_g( AF_Loader loader,
AF_Scaler scaler,
FT_UInt glyph_index,
FT_Int32 load_flags,
FT_UInt depth )
{
FT_Error error = 0;
FT_Face face = loader->face;
AF_FaceGlobals globals = loader->globals;
FT_GlyphLoader gloader = loader->gloader;
AF_ScriptMetrics metrics = loader->metrics;
AF_GlyphHints hints = &loader->hints;
FT_GlyphSlot slot = face->glyph;
FT_Slot_Internal internal = slot->internal;
error = FT_Load_Glyph( face, glyph_index, load_flags );
if ( error )
goto Exit;
loader->transformed = internal->glyph_transformed;
if ( loader->transformed )
{
FT_Matrix inverse;
loader->trans_matrix = internal->glyph_matrix;
loader->trans_delta = internal->glyph_delta;
inverse = loader->trans_matrix;
FT_Matrix_Invert( &inverse );
FT_Vector_Transform( &loader->trans_delta, &inverse );
}
/* set linear metrics */
slot->linearHoriAdvance = slot->metrics.horiAdvance;
slot->linearVertAdvance = slot->metrics.vertAdvance;
switch ( slot->format )
{
case FT_GLYPH_FORMAT_OUTLINE:
/* translate the loaded glyph when an internal transform
* is needed
*/
if ( loader->transformed )
{
FT_Vector* point = slot->outline.points;
FT_Vector* limit = point + slot->outline.n_points;
for ( ; point < limit; point++ )
{
point->x += loader->trans_delta.x;
point->y += loader->trans_delta.y;
}
}
/* copy the outline points in the loader's current */
/* extra points which is used to keep original glyph coordinates */
error = FT_GlyphLoader_CheckPoints( gloader,
slot->outline.n_points + 2,
slot->outline.n_contours );
if ( error )
goto Exit;
FT_ARRAY_COPY( gloader->current.extra_points,
slot->outline.points,
slot->outline.n_points );
FT_ARRAY_COPY( gloader->current.outline.contours,
slot->outline.contours,
slot->outline.n_contours );
FT_ARRAY_COPY( gloader->current.outline.tags,
slot->outline.tags,
slot->outline.n_points );
gloader->current.outline.n_points = slot->outline.n_points;
gloader->current.outline.n_contours = slot->outline.n_contours;
/* compute original phantom points */
loader->pp1.x = hints->x_delta;
loader->pp1.y = hints->y_delta;
loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance,
hints->x_scale ) + hints->x_delta;
loader->pp2.y = hints->y_delta;
/* be sure to check for spacing glyphs */
if ( slot->outline.n_points == 0 )
goto Hint_Metrics;
/* now load the slot image into the auto-outline and run the */
/* automatic hinting process */
error = metrics->clazz->script_hints_init( hints,
&gloader->current.outline,
metrics );
if ( error )
goto Exit;
/* apply the hints */
metrics->clazz->script_hints_apply( hints,
&gloader->current.outline,
metrics );
/* we now need to hint the metrics according to the change in */
/* width/positioning that occured during the hinting process */
{
FT_Pos old_advance, old_rsb, old_lsb, new_lsb;
AF_AxisHints axis = &hints->axis[ AF_DIMENSION_HORZ ];
AF_Edge edge1 = axis->edges; /* leftmost edge */
AF_Edge edge2 = edge1 + axis->num_edges - 1; /* rightmost edge */
old_advance = loader->pp2.x;
old_rsb = old_advance - edge2->opos;
old_lsb = edge1->opos;
new_lsb = edge1->pos;
loader->pp1.x = FT_PIX_ROUND( new_lsb - old_lsb );
loader->pp2.x = FT_PIX_ROUND( edge2->pos + old_rsb );
#if 0
/* try to fix certain bad advance computations */
if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 )
loader->pp2.x += 64;
#endif
}
/* good, we simply add the glyph to our loader's base */
FT_GlyphLoader_Add( gloader );
break;
case FT_GLYPH_FORMAT_COMPOSITE:
{
FT_UInt nn, num_subglyphs = slot->num_subglyphs;
FT_UInt num_base_subgs, start_point;
FT_SubGlyph subglyph;
start_point = gloader->base.outline.n_points;
/* first of all, copy the subglyph descriptors in the glyph loader */
error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs );
if ( error )
goto Exit;
FT_ARRAY_COPY( gloader->current.subglyphs,
slot->subglyphs,
num_subglyphs );
gloader->current.num_subglyphs = num_subglyphs;
num_base_subgs = gloader->base.num_subglyphs;
/* now, read each subglyph independently */
for ( nn = 0; nn < num_subglyphs; nn++ )
{
FT_Vector pp1, pp2;
FT_Pos x, y;
FT_UInt num_points, num_new_points, num_base_points;
/* gloader.current.subglyphs can change during glyph loading due */
/* to re-allocation -- we must recompute the current subglyph on */
/* each iteration */
subglyph = gloader->base.subglyphs + num_base_subgs + nn;
pp1 = loader->pp1;
pp2 = loader->pp2;
num_base_points = gloader->base.outline.n_points;
error = af_loader_load_g( loader, scaler, subglyph->index,
load_flags, depth + 1 );
if ( error )
goto Exit;
/* recompute subglyph pointer */
subglyph = gloader->base.subglyphs + num_base_subgs + nn;
if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
{
pp1 = loader->pp1;
pp2 = loader->pp2;
}
else
{
loader->pp1 = pp1;
loader->pp2 = pp2;
}
num_points = gloader->base.outline.n_points;
num_new_points = num_points - num_base_points;
/* now perform the transform required for this subglyph */
if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE |
FT_SUBGLYPH_FLAG_XY_SCALE |
FT_SUBGLYPH_FLAG_2X2 ) )
{
FT_Vector* cur = gloader->base.outline.points +
num_base_points;
FT_Vector* org = gloader->base.extra_points +
num_base_points;
FT_Vector* limit = cur + num_new_points;
for ( ; cur < limit; cur++, org++ )
{
FT_Vector_Transform( cur, &subglyph->transform );
FT_Vector_Transform( org, &subglyph->transform );
}
}
/* apply offset */
if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
{
FT_Int k = subglyph->arg1;
FT_UInt l = subglyph->arg2;
FT_Vector* p1;
FT_Vector* p2;
if ( start_point + k >= num_base_points ||
l >= (FT_UInt)num_new_points )
{
error = FT_Err_Invalid_Composite;
goto Exit;
}
l += num_base_points;
/* for now, only use the current point coordinates; */
/* we may consider another approach in the near future */
p1 = gloader->base.outline.points + start_point + k;
p2 = gloader->base.outline.points + start_point + l;
x = p1->x - p2->x;
y = p1->y - p2->y;
}
else
{
x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta;
y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta;
x = FT_PIX_ROUND(x);
y = FT_PIX_ROUND(y);
}
{
FT_Outline dummy = gloader->base.outline;
dummy.points += num_base_points;
dummy.n_points = (short)num_new_points;
FT_Outline_Translate( &dummy, x, y );
}
}
}
break;
default:
/* we don't support other formats (yet?) */
error = FT_Err_Unimplemented_Feature;
}
Hint_Metrics:
if ( depth == 0 )
{
FT_BBox bbox;
/* transform the hinted outline if needed */
if ( loader->transformed )
FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix );
/* we must translate our final outline by -pp1.x and compute */
/* the new metrics */
if ( loader->pp1.x )
FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 );
FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
bbox.yMin = FT_PIX_FLOOR( bbox.yMin );
bbox.xMax = FT_PIX_CEIL( bbox.xMax );
bbox.yMax = FT_PIX_CEIL( bbox.yMax );
slot->metrics.width = bbox.xMax - bbox.xMin;
slot->metrics.height = bbox.yMax - bbox.yMin;
slot->metrics.horiBearingX = bbox.xMin;
slot->metrics.horiBearingY = bbox.yMax;
/* for mono-width fonts (like Andale, Courier, etc.) we need */
/* to keep the original rounded advance width */
#if 0
if ( !FT_IS_FIXED_WIDTH( slot->face ) )
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
else
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
x_scale );
#else
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
#endif
slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
/* now copy outline into glyph slot */
FT_GlyphLoader_Rewind( loader->gloader );
error = FT_GlyphLoader_CopyPoints( loader->gloader, gloader );
if ( error )
goto Exit;
slot->outline = slot->internal->loader->base.outline;
slot->format = FT_GLYPH_FORMAT_OUTLINE;
}
#ifdef DEBUG_HINTER
af_debug_hinter = hinter;
#endif
Exit:
return error;
}
FT_LOCAL_DEF( FT_Error )
af_loader_load_glyph( AF_Loader loader,
FT_Face face,
FT_UInt gindex,
FT_UInt32 load_flags )
{
FT_Error error;
FT_Size size = face->size;
AF_ScalerRec scaler;
if ( !size )
return FT_Err_Invalid_Argument;
FT_ZERO( &scaler );
scaler.face = face;
scaler.x_scale = size->metrics.x_scale;
scaler.x_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */
scaler.y_scale = size->metrics.y_scale;
scaler.y_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */
scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
scaler.flags = 0; /* XXX: fix this */
error = af_loader_reset( loader, face );
if ( !error )
{
AF_ScriptMetrics metrics;
error = af_face_globals_get_metrics( loader->globals, gindex, &metrics );
if ( !error )
{
metrics->clazz->script_metrics_scale( metrics, &scaler );
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM;
load_flags &= ~FT_LOAD_RENDER;
error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );
}
}
return error;
}

View file

@ -0,0 +1,49 @@
#ifndef __AF_LOADER_H__
#define __AF_LOADER_H__
#include "afhints.h"
#include "afglobal.h"
FT_BEGIN_HEADER
typedef struct AF_LoaderRec_
{
FT_Face face; /* current face */
AF_FaceGlobals globals; /* current face globals */
FT_GlyphLoader gloader; /* glyph loader */
AF_GlyphHintsRec hints;
AF_ScriptMetrics metrics;
FT_Bool transformed;
FT_Matrix trans_matrix;
FT_Vector trans_delta;
FT_Vector pp1;
FT_Vector pp2;
} AF_LoaderRec, *AF_Loader;
FT_LOCAL( FT_Error )
af_loader_init( AF_Loader loader,
FT_Memory memory );
FT_LOCAL( FT_Error )
af_loader_reset( AF_Loader loader,
FT_Face face );
FT_LOCAL( void )
af_loader_done( AF_Loader loader );
FT_LOCAL( FT_Error )
af_loader_load_glyph( AF_Loader loader,
FT_Face face,
FT_UInt gindex,
FT_UInt32 load_flags );
/* */
FT_END_HEADER
#endif /* __AF_LOADER_H__ */

View file

@ -0,0 +1,68 @@
#include "afmodule.h"
#include "afloader.h"
#include FT_INTERNAL_OBJECTS_H
typedef struct FT_AutofitterRec_
{
FT_ModuleRec root;
AF_LoaderRec loader[1];
} FT_AutofitterRec, *FT_Autofitter;
FT_CALLBACK_DEF( FT_Error )
af_autofitter_init( FT_Autofitter module )
{
return af_loader_init( module->loader, module->root.library->memory );
}
FT_CALLBACK_DEF( void )
af_autofitter_done( FT_Autofitter module )
{
af_loader_done( module->loader );
}
FT_CALLBACK_DEF( FT_Error )
af_autofitter_load_glyph( FT_Autofitter module,
FT_GlyphSlot slot,
FT_Size size,
FT_UInt glyph_index,
FT_Int32 load_flags )
{
return af_loader_load_glyph( module->loader, slot->face,
glyph_index, load_flags );
}
FT_CALLBACK_TABLE_DEF
const FT_AutoHinter_ServiceRec af_autofitter_service =
{
NULL,
NULL,
NULL,
(FT_AutoHinter_GlyphLoadFunc) af_autofitter_load_glyph
};
FT_CALLBACK_TABLE_DEF
const FT_Module_Class autofit_module_class =
{
FT_MODULE_HINTER,
sizeof ( FT_AutofitterRec ),
"autofitter",
0x10000L, /* version 1.0 of the autofitter */
0x20000L, /* requires FreeType 2.0 or above */
(const void*) &af_autofitter_service,
(FT_Module_Constructor) af_autofitter_init,
(FT_Module_Destructor) af_autofitter_done,
(FT_Module_Requester) 0
};
/* END */

View file

@ -0,0 +1,16 @@
#ifndef __AFMODULE_H__
#define __AFMODULE_H__
#include <ft2build.h>
#include FT_MODULE_H
FT_BEGIN_HEADER
FT_CALLBACK_TABLE
const FT_Module_Class autofit_module_class;
FT_END_HEADER
#endif /* __AFMODULE_H__ */

View file

@ -0,0 +1,266 @@
#ifndef __AFTYPES_H__
#define __AFTYPES_H__
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_OUTLINE_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
FT_BEGIN_HEADER
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** D E B U G G I N G *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
#define xxAF_DEBUG
#ifdef AF_DEBUG
# include <stdio.h>
# define AF_LOG( x ) printf ## x
#else
# define AF_LOG( x ) do ; while ( 0 ) /* nothing */
#endif /* AF_DEBUG */
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** U T I L I T Y *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
typedef struct AF_WidthRec_
{
FT_Pos org; /* original position/width in font units */
FT_Pos cur; /* current/scaled position/width in device sub-pixels */
FT_Pos fit; /* current/fitted position/width in device sub-pixels */
} AF_WidthRec, *AF_Width;
FT_LOCAL( void )
af_sort_pos( FT_UInt count,
FT_Pos* table );
FT_LOCAL( void )
af_sort_widths( FT_UInt count,
AF_Width widths );
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** A N G L E T Y P E S *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
/*
* Angle type. The auto-fitter doesn't need a very high angular accuracy,
* and this allows us to speed up some computations considerably with a
* light Cordic algorithm (see afangles.c)
*
*/
typedef FT_Int AF_Angle;
#define AF_ANGLE_PI 128
#define AF_ANGLE_2PI (AF_ANGLE_PI*2)
#define AF_ANGLE_PI2 (AF_ANGLE_PI/2)
#define AF_ANGLE_PI4 (AF_ANGLE_PI/4)
/*
* compute the angle of a given 2-D vector
*
*/
FT_LOCAL( AF_Angle )
af_angle_atan( FT_Pos dx,
FT_Pos dy );
/*
* computes "angle2 - angle1", the result is always within
* the range [ -AF_ANGLE_PI .. AF_ANGLE_PI-1 ]
*
*/
FT_LOCAL( AF_Angle )
af_angle_diff( AF_Angle angle1,
AF_Angle angle2 );
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** O U T L I N E S *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
/* opaque handle to glyph-specific hints. see "afhints.h" for more
* details
*/
typedef struct AF_GlyphHintsRec_* AF_GlyphHints;
/* this structure is used to model an input glyph outline to
* the auto-hinter. The latter will set the "hints" field
* depending on the glyph's script
*/
typedef struct AF_OutlineRec_
{
FT_Face face;
FT_Outline outline;
FT_UInt outline_resolution;
FT_Int advance;
FT_UInt metrics_resolution;
AF_GlyphHints hints;
} AF_OutlineRec;
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** S C A L E R S *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
/*
* A scaler models the target pixel device that will receive the
* auto-hinted glyph image
*
*/
typedef enum
{
AF_SCALER_FLAG_NO_HORIZONTAL = 1, /* disable horizontal hinting */
AF_SCALER_FLAG_NO_VERTICAL = 2, /* disable vertical hinting */
AF_SCALER_FLAG_NO_ADVANCE = 4 /* disable advance hinting */
} AF_ScalerFlags;
typedef struct AF_ScalerRec_
{
FT_Face face; /* source font face */
FT_Fixed x_scale; /* from font units to 1/64th device pixels */
FT_Fixed y_scale; /* from font units to 1/64th device pixels */
FT_Pos x_delta; /* in 1/64th device pixels */
FT_Pos y_delta; /* in 1/64th device pixels */
FT_Render_Mode render_mode; /* monochrome, anti-aliased, LCD, etc.. */
FT_UInt32 flags; /* additionnal control flags, see above */
} AF_ScalerRec, *AF_Scaler;
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** S C R I P T S *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
/*
* the list of know scripts. Each different script correspond to the
* following information:
*
* - a set of Unicode ranges to test weither the face supports the
* script
*
* - a specific global analyzer that will compute global metrics
* specific to the script.
*
* - a specific glyph analyzer that will compute segments and
* edges for each glyph covered by the script
*
* - a specific grid-fitting algorithm that will distort the
* scaled glyph outline according to the results of the glyph
* analyzer
*
* note that a given analyzer and/or grid-fitting algorithm can be
* used by more than one script
*/
typedef enum
{
AF_SCRIPT_LATIN = 0,
/* add new scripts here. don't forget to update the list in "afglobal.c" */
AF_SCRIPT_MAX /* do not remove */
} AF_Script;
typedef struct AF_ScriptClassRec_ const* AF_ScriptClass;
typedef struct AF_ScriptMetricsRec_
{
AF_ScriptClass clazz;
} AF_ScriptMetricsRec, *AF_ScriptMetrics;
/* this function parses a FT_Face to compute global metrics for
* a specific script
*/
typedef FT_Error (*AF_Script_InitMetricsFunc)( AF_ScriptMetrics metrics,
FT_Face face );
typedef void (*AF_Script_ScaleMetricsFunc)( AF_ScriptMetrics metrics,
AF_Scaler scaler );
typedef void (*AF_Script_DoneMetricsFunc)( AF_ScriptMetrics metrics );
typedef FT_Error (*AF_Script_InitHintsFunc)( AF_GlyphHints hints,
FT_Outline* outline,
AF_ScriptMetrics metrics );
typedef void (*AF_Script_ApplyHintsFunc)( AF_GlyphHints hints,
FT_Outline* outline,
AF_ScriptMetrics metrics );
typedef struct AF_Script_UniRangeRec_
{
FT_UInt32 first;
FT_UInt32 last;
} AF_Script_UniRangeRec;
typedef const AF_Script_UniRangeRec * AF_Script_UniRange;
typedef struct AF_ScriptClassRec_
{
AF_Script script;
AF_Script_UniRange script_uni_ranges; /* last must be { 0, 0 } */
FT_UInt script_metrics_size;
AF_Script_InitMetricsFunc script_metrics_init;
AF_Script_ScaleMetricsFunc script_metrics_scale;
AF_Script_DoneMetricsFunc script_metrics_done;
AF_Script_InitHintsFunc script_hints_init;
AF_Script_ApplyHintsFunc script_hints_apply;
} AF_ScriptClassRec;
/* */
FT_END_HEADER
#endif /* __AFTYPES_H__ */

View file

@ -0,0 +1,8 @@
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include <ft2build.h>
#include "afangles.c"
#include "afglobal.c"
#include "afhints.c"
#include "aflatin.c"
#include "afloader.c"
#include "afmodule.c"

View file

@ -0,0 +1,420 @@
/***************************************************************************/
/* */
/* ftcbasic.c */
/* */
/* The FreeType basic cache interface (body). */
/* */
/* Copyright 2003, 2004 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. */
/* */
/***************************************************************************/
#include <ft2build.h>
#include FT_CACHE_H
#include FT_CACHE_INTERNAL_GLYPH_H
#include FT_CACHE_INTERNAL_IMAGE_H
#include FT_CACHE_INTERNAL_SBITS_H
#include FT_INTERNAL_MEMORY_H
#include "ftcerror.h"
/*
* Basic Families
*
*/
typedef struct FTC_BasicAttrRec_
{
FTC_ScalerRec scaler;
FT_UInt load_flags;
} FTC_BasicAttrRec, *FTC_BasicAttrs;
#define FTC_BASIC_ATTR_COMPARE( a, b ) \
( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \
(a)->load_flags == (b)->load_flags )
#define FTC_BASIC_ATTR_HASH( a ) \
( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags )
typedef struct FTC_BasicQueryRec_
{
FTC_GQueryRec gquery;
FTC_BasicAttrRec attrs;
} FTC_BasicQueryRec, *FTC_BasicQuery;
typedef struct FTC_BasicFamilyRec_
{
FTC_FamilyRec family;
FTC_BasicAttrRec attrs;
} FTC_BasicFamilyRec, *FTC_BasicFamily;
static FT_Bool
ftc_basic_family_compare( FTC_BasicFamily family,
FTC_BasicQuery query )
{
return FT_BOOL( FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs ) );
}
static FT_Error
ftc_basic_family_init( FTC_BasicFamily family,
FTC_BasicQuery query,
FTC_Cache cache )
{
FTC_Family_Init( FTC_FAMILY( family ), cache );
family->attrs = query->attrs;
return 0;
}
static FT_UInt
ftc_basic_family_get_count( FTC_BasicFamily family,
FTC_Manager manager )
{
FT_Error error;
FT_Face face;
FT_UInt result = 0;
error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id,
&face );
if ( !error )
result = face->num_glyphs;
return result;
}
static FT_Error
ftc_basic_family_load_bitmap( FTC_BasicFamily family,
FT_UInt gindex,
FTC_Manager manager,
FT_Face *aface )
{
FT_Error error;
FT_Size size;
error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size );
if ( !error )
{
FT_Face face = size->face;
error = FT_Load_Glyph( face, gindex,
family->attrs.load_flags | FT_LOAD_RENDER );
if ( !error )
*aface = face;
}
return error;
}
static FT_Error
ftc_basic_family_load_glyph( FTC_BasicFamily family,
FT_UInt gindex,
FTC_Cache cache,
FT_Glyph *aglyph )
{
FT_Error error;
FTC_Scaler scaler = &family->attrs.scaler;
FT_Face face;
FT_Size size;
/* we will now load the glyph image */
error = FTC_Manager_LookupSize( cache->manager,
scaler,
&size );
if ( !error )
{
face = size->face;
error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );
if ( !error )
{
if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP ||
face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
{
/* ok, copy it */
FT_Glyph glyph;
error = FT_Get_Glyph( face->glyph, &glyph );
if ( !error )
{
*aglyph = glyph;
goto Exit;
}
}
else
error = FTC_Err_Invalid_Argument;
}
}
Exit:
return error;
}
static FT_Bool
ftc_basic_gnode_compare_faceid( FTC_GNode gnode,
FTC_FaceID face_id,
FTC_Cache cache )
{
FTC_BasicFamily family = (FTC_BasicFamily)gnode->family;
FT_Bool result;
result = FT_BOOL( family->attrs.scaler.face_id == face_id );
if ( result )
{
/* we must call this function to avoid this node from appearing
* in later lookups with the same face_id!
*/
FTC_GNode_UnselectFamily( gnode, cache );
}
return result;
}
/*
*
* basic image cache
*
*/
static const FTC_IFamilyClassRec ftc_basic_image_family_class =
{
{
sizeof( FTC_BasicFamilyRec ),
(FTC_MruNode_CompareFunc)ftc_basic_family_compare,
(FTC_MruNode_InitFunc) ftc_basic_family_init,
(FTC_MruNode_ResetFunc) NULL,
(FTC_MruNode_DoneFunc) NULL
},
(FTC_IFamily_LoadGlyphFunc)ftc_basic_family_load_glyph
};
static const FTC_GCacheClassRec ftc_basic_image_cache_class =
{
{
(FTC_Node_NewFunc) FTC_INode_New,
(FTC_Node_WeightFunc) FTC_INode_Weight,
(FTC_Node_CompareFunc)FTC_GNode_Compare,
(FTC_Node_CompareFunc)ftc_basic_gnode_compare_faceid,
(FTC_Node_FreeFunc) FTC_INode_Free,
sizeof( FTC_GCacheRec ),
(FTC_Cache_InitFunc) FTC_GCache_Init,
(FTC_Cache_DoneFunc) FTC_GCache_Done
},
(FTC_MruListClass)&ftc_basic_image_family_class
};
FT_EXPORT_DEF( FT_Error )
FTC_ImageCache_New( FTC_Manager manager,
FTC_ImageCache *acache )
{
return FTC_GCache_New( manager, &ftc_basic_image_cache_class,
(FTC_GCache*)acache );
}
/* documentation is in ftcimage.h */
FT_EXPORT_DEF( FT_Error )
FTC_ImageCache_Lookup( FTC_ImageCache cache,
FTC_ImageType type,
FT_UInt gindex,
FT_Glyph *aglyph,
FTC_Node *anode )
{
FTC_BasicQueryRec query;
FTC_INode node;
FT_Error error;
FT_UInt32 hash;
/* some argument checks are delayed to FTC_Cache_Lookup */
if ( !aglyph )
{
error = FTC_Err_Invalid_Argument;
goto Exit;
}
*aglyph = NULL;
if ( anode )
*anode = NULL;
query.attrs.scaler.face_id = type->face_id;
query.attrs.scaler.width = type->width;
query.attrs.scaler.height = type->height;
query.attrs.scaler.pixel = 1;
query.attrs.load_flags = type->flags;
query.attrs.scaler.x_res = 0; /* make compilers happy */
query.attrs.scaler.y_res = 0;
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
#if 1 /* inlining is about 50% faster! */
FTC_GCACHE_LOOKUP_CMP( cache,
ftc_basic_family_compare,
FTC_GNode_Compare,
hash, gindex,
&query,
node,
error );
#else
error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
hash, gindex,
FTC_GQUERY( &query ),
(FTC_Node*) &node );
#endif
if ( !error )
{
*aglyph = FTC_INODE( node )->glyph;
if ( anode )
{
*anode = FTC_NODE( node );
FTC_NODE( node )->ref_count++;
}
}
Exit:
return error;
}
/*
*
* basic small bitmap cache
*
*/
static const FTC_SFamilyClassRec ftc_basic_sbit_family_class =
{
{
sizeof( FTC_BasicFamilyRec ),
(FTC_MruNode_CompareFunc)ftc_basic_family_compare,
(FTC_MruNode_InitFunc) ftc_basic_family_init,
(FTC_MruNode_ResetFunc) NULL,
(FTC_MruNode_DoneFunc) NULL
},
(FTC_SFamily_GetCountFunc) ftc_basic_family_get_count,
(FTC_SFamily_LoadGlyphFunc)ftc_basic_family_load_bitmap
};
static const FTC_GCacheClassRec ftc_basic_sbit_cache_class =
{
{
(FTC_Node_NewFunc) FTC_SNode_New,
(FTC_Node_WeightFunc) FTC_SNode_Weight,
(FTC_Node_CompareFunc)FTC_SNode_Compare,
(FTC_Node_CompareFunc)ftc_basic_gnode_compare_faceid,
(FTC_Node_FreeFunc) FTC_SNode_Free,
sizeof( FTC_GCacheRec ),
(FTC_Cache_InitFunc) FTC_GCache_Init,
(FTC_Cache_DoneFunc) FTC_GCache_Done
},
(FTC_MruListClass)&ftc_basic_sbit_family_class
};
FT_EXPORT_DEF( FT_Error )
FTC_SBitCache_New( FTC_Manager manager,
FTC_SBitCache *acache )
{
return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class,
(FTC_GCache*)acache );
}
FT_EXPORT_DEF( FT_Error )
FTC_SBitCache_Lookup( FTC_SBitCache cache,
FTC_ImageType type,
FT_UInt gindex,
FTC_SBit *ansbit,
FTC_Node *anode )
{
FT_Error error;
FTC_BasicQueryRec query;
FTC_SNode node;
FT_UInt32 hash;
if ( anode )
*anode = NULL;
/* other argument checks delayed to FTC_Cache_Lookup */
if ( !ansbit )
return FTC_Err_Invalid_Argument;
*ansbit = NULL;
query.attrs.scaler.face_id = type->face_id;
query.attrs.scaler.width = type->width;
query.attrs.scaler.height = type->height;
query.attrs.scaler.pixel = 1;
query.attrs.load_flags = type->flags;
query.attrs.scaler.x_res = 0; /* make compilers happy */
query.attrs.scaler.y_res = 0;
/* beware, the hash must be the same for all glyph ranges! */
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
gindex / FTC_SBIT_ITEMS_PER_NODE;
#if 1 /* inlining is about 50% faster! */
FTC_GCACHE_LOOKUP_CMP( cache,
ftc_basic_family_compare,
FTC_SNode_Compare,
hash, gindex,
&query,
node,
error );
#else
error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
hash,
gindex,
FTC_GQUERY( &query ),
(FTC_Node*)&node );
#endif
if ( error )
goto Exit;
*ansbit = node->sbits + ( gindex - FTC_GNODE( node )->gindex );
if ( anode )
{
*anode = FTC_NODE( node );
FTC_NODE( node )->ref_count++;
}
Exit:
return error;
}
/* END */

355
reactos/lib/freetype/src/cache/ftcmru.c vendored Normal file
View file

@ -0,0 +1,355 @@
/***************************************************************************/
/* */
/* ftcmru.c */
/* */
/* FreeType MRU support (body). */
/* */
/* Copyright 2003, 2004 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. */
/* */
/***************************************************************************/
#include <ft2build.h>
#include FT_CACHE_H
#include FT_CACHE_INTERNAL_MRU_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include "ftcerror.h"
FT_EXPORT_DEF( void )
FTC_MruNode_Prepend( FTC_MruNode *plist,
FTC_MruNode node )
{
FTC_MruNode first = *plist;
if ( first )
{
FTC_MruNode last = first->prev;
#ifdef FT_DEBUG_ERROR
{
FTC_MruNode cnode = first;
do
{
if ( cnode == node )
{
fprintf( stderr, "FTC_MruNode_Prepend: invalid action!\n" );
exit( 2 );
}
cnode = cnode->next;
} while ( cnode != first );
}
#endif
first->prev = node;
last->next = node;
node->next = first;
node->prev = last;
}
else
{
node->next = node;
node->prev = node;
}
*plist = node;
}
FT_EXPORT_DEF( void )
FTC_MruNode_Up( FTC_MruNode *plist,
FTC_MruNode node )
{
FTC_MruNode first = *plist;
FT_ASSERT( first != NULL );
if ( first != node )
{
FTC_MruNode prev, next, last;
#ifdef FT_DEBUG_ERROR
{
FTC_MruNode cnode = first;
do
{
if ( cnode == node )
goto Ok;
cnode = cnode->next;
} while ( cnode != first );
fprintf( stderr, "FTC_MruNode_Up: invalid action!\n" );
exit( 2 );
Ok:
}
#endif
prev = node->prev;
next = node->next;
prev->next = next;
next->prev = prev;
last = first->prev;
last->next = node;
first->prev = node;
node->next = first;
node->prev = last;
*plist = node;
}
}
FT_EXPORT_DEF( void )
FTC_MruNode_Remove( FTC_MruNode *plist,
FTC_MruNode node )
{
FTC_MruNode first = *plist;
FTC_MruNode prev, next;
FT_ASSERT( first != NULL );
#ifdef FT_DEBUG_ERROR
{
FTC_MruNode cnode = first;
do
{
if ( cnode == node )
goto Ok;
cnode = cnode->next;
} while ( cnode != first );
fprintf( stderr, "FTC_MruNode_Remove: invalid action!\n" );
exit( 2 );
Ok:
}
#endif
prev = node->prev;
next = node->next;
prev->next = next;
next->prev = prev;
if ( node == next )
{
FT_ASSERT( first == node );
FT_ASSERT( prev == node );
*plist = NULL;
}
else if ( node == first )
*plist = next;
}
FT_EXPORT_DEF( void )
FTC_MruList_Init( FTC_MruList list,
FTC_MruListClass clazz,
FT_UInt max_nodes,
FT_Pointer data,
FT_Memory memory )
{
list->num_nodes = 0;
list->max_nodes = max_nodes;
list->nodes = NULL;
list->clazz = *clazz;
list->data = data;
list->memory = memory;
}
FT_EXPORT( void )
FTC_MruList_Reset( FTC_MruList list )
{
while ( list->nodes )
FTC_MruList_Remove( list, list->nodes );
FT_ASSERT( list->num_nodes == 0 );
}
FT_EXPORT( void )
FTC_MruList_Done( FTC_MruList list )
{
FTC_MruList_Reset( list );
}
FT_EXPORT_DEF( FTC_MruNode )
FTC_MruList_Find( FTC_MruList list,
FT_Pointer key )
{
FTC_MruNode_CompareFunc compare = list->clazz.node_compare;
FTC_MruNode first, node;
first = list->nodes;
node = NULL;
if ( first )
{
node = first;
do
{
if ( compare( node, key ) )
{
if ( node != first )
FTC_MruNode_Up( &list->nodes, node );
return node;
}
node = node->next;
} while ( node != first);
}
return NULL;
}
FT_EXPORT_DEF( FT_Error )
FTC_MruList_New( FTC_MruList list,
FT_Pointer key,
FTC_MruNode *anode )
{
FT_Error error;
FTC_MruNode node;
FT_Memory memory = list->memory;
if ( list->num_nodes >= list->max_nodes && list->max_nodes > 0 )
{
node = list->nodes->prev;
FT_ASSERT( node );
if ( list->clazz.node_reset )
{
FTC_MruNode_Up( &list->nodes, node );
error = list->clazz.node_reset( node, key, list->data );
if ( !error )
goto Exit;
}
FTC_MruNode_Remove( &list->nodes, node );
list->num_nodes--;
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
}
else if ( FT_ALLOC( node, list->clazz.node_size ) )
goto Exit;
error = list->clazz.node_init( node, key, list->data );
if ( error )
goto Fail;
FTC_MruNode_Prepend( &list->nodes, node );
list->num_nodes++;
Exit:
*anode = node;
return error;
Fail:
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
FT_FREE( node );
goto Exit;
}
FT_EXPORT( FT_Error )
FTC_MruList_Lookup( FTC_MruList list,
FT_Pointer key,
FTC_MruNode *anode )
{
FTC_MruNode node;
node = FTC_MruList_Find( list, key );
if ( node == NULL )
return FTC_MruList_New( list, key, anode );
*anode = node;
return 0;
}
FT_EXPORT_DEF( void )
FTC_MruList_Remove( FTC_MruList list,
FTC_MruNode node )
{
FTC_MruNode_Remove( &list->nodes, node );
list->num_nodes--;
{
FT_Memory memory = list->memory;
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
FT_FREE( node );
}
}
FT_EXPORT_DEF( void )
FTC_MruList_RemoveSelection( FTC_MruList list,
FTC_MruNode_CompareFunc selection,
FT_Pointer key )
{
FTC_MruNode first, node, next;
first = list->nodes;
while ( first && selection( first, key ) )
{
FTC_MruList_Remove( list, first );
first = list->nodes;
}
if ( first )
{
node = first->next;
while ( node != first )
{
next = node->next;
if ( selection( node, key ) )
FTC_MruList_Remove( list, node );
node = next;
}
}
}
/* END */

View file

@ -0,0 +1,255 @@
/***************************************************************************/
/* */
/* cfftypes.h */
/* */
/* Basic OpenType/CFF type definitions and interface (specification */
/* only). */
/* */
/* Copyright 1996-2001, 2002, 2003 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. */
/* */
/***************************************************************************/
#ifndef __CFFTYPES_H__
#define __CFFTYPES_H__
#include <ft2build.h>
#include FT_FREETYPE_H
FT_BEGIN_HEADER
/*************************************************************************/
/* */
/* <Struct> */
/* CFF_IndexRec */
/* */
/* <Description> */
/* A structure used to model a CFF Index table. */
/* */
/* <Fields> */
/* stream :: The source input stream. */
/* */
/* count :: The number of elements in the index. */
/* */
/* off_size :: The size in bytes of object offsets in index. */
/* */
/* data_offset :: The position of first data byte in the index's */
/* bytes. */
/* */
/* offsets :: A table of element offsets in the index. */
/* */
/* bytes :: If the index is loaded in memory, its bytes. */
/* */
typedef struct CFF_IndexRec_
{
FT_Stream stream;
FT_UInt count;
FT_Byte off_size;
FT_ULong data_offset;
FT_ULong* offsets;
FT_Byte* bytes;
} CFF_IndexRec, *CFF_Index;
typedef struct CFF_EncodingRec_
{
FT_UInt format;
FT_ULong offset;
FT_UInt count;
FT_UShort sids [256]; /* avoid dynamic allocations */
FT_UShort codes[256];
} CFF_EncodingRec, *CFF_Encoding;
typedef struct CFF_CharsetRec_
{
FT_UInt format;
FT_ULong offset;
FT_UShort* sids;
FT_UShort* cids; /* the inverse mapping of `sids'; only needed */
/* for CID-keyed fonts */
} CFF_CharsetRec, *CFF_Charset;
typedef struct CFF_FontRecDictRec_
{
FT_UInt version;
FT_UInt notice;
FT_UInt copyright;
FT_UInt full_name;
FT_UInt family_name;
FT_UInt weight;
FT_Bool is_fixed_pitch;
FT_Fixed italic_angle;
FT_Fixed underline_position;
FT_Fixed underline_thickness;
FT_Int paint_type;
FT_Int charstring_type;
FT_Matrix font_matrix;
FT_UShort units_per_em;
FT_Vector font_offset;
FT_ULong unique_id;
FT_BBox font_bbox;
FT_Pos stroke_width;
FT_ULong charset_offset;
FT_ULong encoding_offset;
FT_ULong charstrings_offset;
FT_ULong private_offset;
FT_ULong private_size;
FT_Long synthetic_base;
FT_UInt embedded_postscript;
/* these should only be used for the top-level font dictionary */
FT_UInt cid_registry;
FT_UInt cid_ordering;
FT_ULong cid_supplement;
FT_Long cid_font_version;
FT_Long cid_font_revision;
FT_Long cid_font_type;
FT_ULong cid_count;
FT_ULong cid_uid_base;
FT_ULong cid_fd_array_offset;
FT_ULong cid_fd_select_offset;
FT_UInt cid_font_name;
} CFF_FontRecDictRec, *CFF_FontRecDict;
typedef struct CFF_PrivateRec_
{
FT_Byte num_blue_values;
FT_Byte num_other_blues;
FT_Byte num_family_blues;
FT_Byte num_family_other_blues;
FT_Pos blue_values[14];
FT_Pos other_blues[10];
FT_Pos family_blues[14];
FT_Pos family_other_blues[10];
FT_Fixed blue_scale;
FT_Pos blue_shift;
FT_Pos blue_fuzz;
FT_Pos standard_width;
FT_Pos standard_height;
FT_Byte num_snap_widths;
FT_Byte num_snap_heights;
FT_Pos snap_widths[13];
FT_Pos snap_heights[13];
FT_Bool force_bold;
FT_Fixed force_bold_threshold;
FT_Int lenIV;
FT_Int language_group;
FT_Fixed expansion_factor;
FT_Long initial_random_seed;
FT_ULong local_subrs_offset;
FT_Pos default_width;
FT_Pos nominal_width;
} CFF_PrivateRec, *CFF_Private;
typedef struct CFF_FDSelectRec_
{
FT_Byte format;
FT_UInt range_count;
/* that's the table, taken from the file `as is' */
FT_Byte* data;
FT_UInt data_size;
/* small cache for format 3 only */
FT_UInt cache_first;
FT_UInt cache_count;
FT_Byte cache_fd;
} CFF_FDSelectRec, *CFF_FDSelect;
/* A SubFont packs a font dict and a private dict together. They are */
/* needed to support CID-keyed CFF fonts. */
typedef struct CFF_SubFontRec_
{
CFF_FontRecDictRec font_dict;
CFF_PrivateRec private_dict;
CFF_IndexRec local_subrs_index;
FT_UInt num_local_subrs;
FT_Byte** local_subrs;
} CFF_SubFontRec, *CFF_SubFont;
/* maximum number of sub-fonts in a CID-keyed file */
#define CFF_MAX_CID_FONTS 32
typedef struct CFF_FontRec_
{
FT_Stream stream;
FT_Memory memory;
FT_UInt num_faces;
FT_UInt num_glyphs;
FT_Byte version_major;
FT_Byte version_minor;
FT_Byte header_size;
FT_Byte absolute_offsize;
CFF_IndexRec name_index;
CFF_IndexRec top_dict_index;
CFF_IndexRec string_index;
CFF_IndexRec global_subrs_index;
CFF_EncodingRec encoding;
CFF_CharsetRec charset;
CFF_IndexRec charstrings_index;
CFF_IndexRec font_dict_index;
CFF_IndexRec private_index;
CFF_IndexRec local_subrs_index;
FT_String* font_name;
FT_UInt num_global_subrs;
FT_Byte** global_subrs;
CFF_SubFontRec top_font;
FT_UInt num_subfonts;
CFF_SubFont subfonts[CFF_MAX_CID_FONTS];
CFF_FDSelectRec fd_select;
/* interface to PostScript hinter */
void* pshinter;
/* interface to Postscript Names service */
void* psnames;
} CFF_FontRec, *CFF_Font;
FT_END_HEADER
#endif /* __CFFTYPES_H__ */
/* END */

View file

@ -0,0 +1 @@
*.pyc

View file

@ -0,0 +1,109 @@
#!/usr/bin/env python
#
# DocBeauty (c) 2003, 2004 David Turner <david@freetype.org>
#
# This program is used to beautify the documentation comments used
# in the FreeType 2 public headers.
#
from sources import *
from content import *
from utils import *
import utils
import sys, os, time, string, getopt
content_processor = ContentProcessor()
def beautify_block( block ):
if block.content:
content_processor.reset()
markups = content_processor.process_content( block.content )
text = []
first = 1
for markup in markups:
text.extend( markup.beautify( first ) )
first = 0
# now beautify the documentation "borders" themselves
lines = [ " /*************************************************************************" ]
for l in text:
lines.append( " *" + l )
lines.append( " */" )
block.lines = lines
def usage():
print "\nDocBeauty 0.1 Usage information\n"
print " docbeauty [options] file1 [ file2 ... ]\n"
print "using the following options:\n"
print " -h : print this page"
print " -b : backup original files with the 'orig' extension"
print ""
print " --backup : same as -b"
def main( argv ):
"""main program loop"""
global output_dir
try:
opts, args = getopt.getopt( sys.argv[1:],
"hb",
[ "help", "backup" ] )
except getopt.GetoptError:
usage()
sys.exit( 2 )
if args == []:
usage()
sys.exit( 1 )
# process options
#
output_dir = None
do_backup = None
for opt in opts:
if opt[0] in ( "-h", "--help" ):
usage()
sys.exit( 0 )
if opt[0] in ( "-b", "--backup" ):
do_backup = 1
# create context and processor
source_processor = SourceProcessor()
# retrieve the list of files to process
file_list = make_file_list( args )
for filename in file_list:
source_processor.parse_file( filename )
for block in source_processor.blocks:
beautify_block( block )
new_name = filename + ".new"
ok = None
try:
file = open( new_name, "wt" )
for block in source_processor.blocks:
for line in block.lines:
file.write( line )
file.write( "\n" )
file.close()
except:
ok = 0
# if called from the command line
#
if __name__ == '__main__':
main( sys.argv )
# eof

View file

@ -0,0 +1,54 @@
/***************************************************************************/
/* */
/* t42types.h */
/* */
/* Type 42 font data types (specification only). */
/* */
/* Copyright 2002, 2003 by Roberto Alameda. */
/* */
/* 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. */
/* */
/***************************************************************************/
#ifndef __T42TYPES_H__
#define __T42TYPES_H__
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_TYPE1_TABLES_H
#include FT_INTERNAL_TYPE1_TYPES_H
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
FT_BEGIN_HEADER
typedef struct T42_FaceRec_
{
FT_FaceRec root;
T1_FontRec type1;
const void* psnames;
const void* psaux;
const void* afm_data;
FT_Byte* ttf_data;
FT_ULong ttf_size;
FT_Face ttf_face;
FT_CharMapRec charmaprecs[2];
FT_CharMap charmaps[2];
PS_Unicodes unicode_map;
} T42_FaceRec, *T42_Face;
FT_END_HEADER
#endif /* __T1TYPES_H__ */
/* END */