Commit 04aa800c authored by David Turner's avatar David Turner
Browse files

added a CID-keyed font driver in "src/cid"

fixed two bugs in the smooth renderer
parent 3581d064
LATEST_CHANGES
- added the CID-keyed Type 1 driver in "src/cid". Works pretty well for
only 13 Kb of code ;-) Doesn't read AFM files though, nor the really
useful CMAP files..
- fixed two bugs in the smooth renderer (src/base/ftgrays.c). Thanks to
Boris Letocha for spotting them and providing a fix..
- fixed potential "divide by zero" bugs in ftcalc.c.. my god..
- added source code for the OpenType/CFF driver (still incomplete though..)
......
......@@ -81,6 +81,20 @@
for ( file_index = 2; file_index < argc; file_index++ )
{
fname = argv[file_index];
/* try to open the file with no extra extension first */
error = FT_New_Face( library, fname, 0, &face );
if (!error) goto Success;
if ( error == FT_Err_Unknown_File_Format )
{
printf( "unknown format\n" );
continue;
}
/* ok, we could not load the file, try to add an extension to */
/* its name if possible.. */
i = strlen( fname );
while ( i > 0 && fname[i] != '\\' && fname[i] != '/' )
{
......@@ -124,7 +138,7 @@
error = FT_New_Face( library, filename, 0, &face );
if (error)
{
if (error == FT_Err_Invalid_File_Format)
if (error == FT_Err_Unknown_File_Format)
printf( "unknown format\n" );
else
printf( "could not find/open file (error: %d)\n", error );
......@@ -132,6 +146,7 @@
}
if (error) Panic( "Could not open file" );
Success:
num_glyphs = face->num_glyphs;
error = FT_Set_Char_Size( face, ptsize << 6, ptsize << 6, 72, 72 );
......
......@@ -59,9 +59,9 @@
static grColor fore_color = { 255 };
static int graph_init = 0;
static int graph_init = 0;
static int render_mode = 1;
static int use_grays = 0;
static int use_grays = 1;
/* the standard raster's interface */
static FT_Raster_Funcs std_raster;
......
......@@ -74,7 +74,7 @@ $\243^\250*\265\371%!\247:/;.,?<>";
int graph_init = 0;
int render_mode = 1;
int use_grays = 0;
int use_grays = 1;
/* the standard raster's interface */
FT_Raster_Funcs std_raster;
......@@ -618,6 +618,16 @@ $\243^\250*\265\371%!\247:/;.,?<>";
hinted = 1;
file_loaded = 0;
filename[128] = '\0';
alt_filename[128] = '\0';
strncpy( filename, argv[file], 128 );
strncpy( alt_filename, argv[file], 128 );
/* try to load the file name as is, first */
error = FT_New_Face( library, argv[file], 0, &face );
if (!error) goto Success;
#ifndef macintosh
i = strlen( argv[file] );
while ( i > 0 && argv[file][i] != '\\' && argv[file][i] != '/' )
......@@ -628,12 +638,6 @@ $\243^\250*\265\371%!\247:/;.,?<>";
}
#endif
filename[128] = '\0';
alt_filename[128] = '\0';
strncpy( filename, argv[file], 128 );
strncpy( alt_filename, argv[file], 128 );
#ifndef macintosh
if ( i >= 0 )
{
......@@ -647,6 +651,7 @@ $\243^\250*\265\371%!\247:/;.,?<>";
error = FT_New_Face( library, filename, 0, &face );
if (error) goto Display_Font;
Success:
file_loaded++;
error = Reset_Scale( ptsize );
......
FT_DRIVER(cff_driver_interface)
FT_DRIVER(t1cid_driver_interface)
FT_DRIVER(psnames_driver_interface)
FT_DRIVER(sfnt_driver_interface)
FT_DRIVER(tt_driver_interface)
......
......@@ -394,6 +394,12 @@
/* */
#undef T1_CONFIG_OPTION_NO_AFM
/*******************************************************************/
/* Define this configuration macro if you want to prevent the */
/* compilation of the multiple-masters support in the Type 1 driver*/
/* AFM files into an existing face. Note that when set, the T1 */
/* driver will be unable to produce kerning distances.. */
/* */
#undef T1_CONFIG_OPTION_NO_MM_SUPPORT
#endif /* FTOPTION_H */
......@@ -612,6 +612,7 @@
FT_CharMap charmap;
FT_ListRec sizes_list;
void* autohint_globals;
void* extensions;
FT_UShort max_points;
......@@ -934,11 +935,15 @@
/* FT_Load_Glyph() API function) and can be expressed */
/* either in 26.6 fractional pixels or font units. */
/* */
/* metrics2 :: This field can be used to return alternate glyph */
/* metrics after a single load. It can contain either */
/* the glyph's metrics in font units, or the scaled but */
/* unhinted ones. See the load flags that apply when */
/* calling the API function FT_Load_Glyph(). */
/* metrics2 :: This field is used to return alternate glyph metrics */
/* for scalable formats. Only four fields in it are */
/* valid: horiBearingX, horiAdvance, vertBearingY and */
/* vertAdvance. All other fields should be ignored. */
/* By default, it contains the glyph metrics expressed */
/* in font units. However, when FT_Load_Glyph() is called */
/* with FT_LOAD_LINEAR set, the metrics are expressed */
/* in 16.16 unhinted pixel values.. This can be useful */
/* to perform WYSIWYG glyph layout.. */
/* */
/* generic :: A typeless pointer which is unused by the FreeType */
/* library or any of its drivers. It can be used by */
......@@ -955,7 +960,6 @@
/* loaded glyph can be retrieved through the result value */
/* returned by FT_Load_Glyph(). */
/* */
/* */
enum
{
......
......@@ -344,6 +344,13 @@
} T1_Font;
typedef struct CID_Subrs_
{
FT_UInt num_subrs;
FT_Byte** code;
} CID_Subrs;
/*************************************************************************/
/*************************************************************************/
......@@ -372,7 +379,7 @@
typedef struct T1_FaceRec_* T1_Face;
typedef struct CID_FaceRec_* CID_Face;
/***************************************************/
/* */
......@@ -397,4 +404,13 @@
} T1_FaceRec;
typedef struct CID_FaceRec_
{
FT_FaceRec root;
void* psnames;
CID_Info cid;
CID_Subrs* subrs;
} CID_FaceRec;
#endif /* T1TYPES_H */
......@@ -69,7 +69,7 @@
FT_Int unique_id;
FT_Int lenIV;
FT_Byte num_blues;
FT_Byte num_blue_values;
FT_Byte num_other_blues;
FT_Byte num_family_blues;
FT_Byte num_family_other_blues;
......@@ -92,8 +92,8 @@
FT_Bool force_bold;
FT_Bool round_stem_up;
FT_Short stem_snap_widths [13]; /* reserve one place for the std */
FT_Short stem_snap_heights[13]; /* reserve one place for the std */
FT_Short snap_widths [13]; /* reserve one place for the std */
FT_Short snap_heights[13]; /* reserve one place for the std */
FT_Long language_group;
FT_Long password;
......@@ -181,9 +181,17 @@
typedef struct CID_FontDict_
{
T1_FontInfo font_info;
T1_Private private_dict;
FT_UInt len_buildchar;
FT_Fixed forcebold_threshold;
FT_Pos stroke_width;
FT_Fixed expansion_factor;
FT_Byte paint_type;
FT_Byte font_type;
FT_Matrix font_matrix;
FT_UInt num_subrs;
FT_ULong subrmap_offset;
FT_Int sd_bytes;
......@@ -201,6 +209,8 @@
FT_String* ordering;
FT_Int supplement;
T1_FontInfo font_info;
FT_BBox font_bbox;
FT_ULong uid_base;
FT_Int num_xuid;
......@@ -212,9 +222,11 @@
FT_Int gd_bytes;
FT_ULong cid_count;
FT_Int num_font_dicts;
FT_Int num_dicts;
CID_FontDict* font_dicts;
FT_ULong data_offset;
} CID_Info;
......
......@@ -300,7 +300,7 @@
/* in during the render phase. This means that: */
/* */
/* . the new vertical position must be within min_ey..max_ey - 1. */
/* . the new horizontal position must be strictly less than max_ey */
/* . the new horizontal position must be strictly less than max_ex */
/* */
/* Note that if a cell is to the left of the clipping region, it is */
/* actually set to the (min_ex-1) horizontal position. */
......@@ -1198,7 +1198,7 @@
coverage = -coverage;
while ( coverage >= 512 )
coverage -= 512;
coverage = 512-coverage;
if ( coverage > 256 )
coverage = 0;
......@@ -1216,6 +1216,7 @@
}
y += ras.min_ey;
x += ras.min_ex;
if ( coverage )
{
......@@ -1330,9 +1331,9 @@
else
{
/* draw a gray span until the end of the clipping region */
if ( cover && x < ras.max_ex )
if ( cover && x < ras.max_ex - ras.min_ex )
grays_hline( RAS_VAR_ x, y,
cover * ( ONE_PIXEL * 2 ), ras.max_ex - x );
cover * ( ONE_PIXEL * 2 ), ras.max_ex - x - ras.min_ex );
cover = 0;
}
......
/***************************************************************************
*
* t1afm.c - support for reading Type 1 AFM files
*
*
***************************************************************************/
#include <cidafm.h>
#include <freetype/internal/ftstream.h>
#include <freetype/internal/t1types.h>
#include <stdlib.h> /* for qsort */
LOCAL_FUNC
void CID_Done_AFM( FT_Memory memory, T1_AFM* afm )
{
FREE( afm->kern_pairs );
afm->num_pairs = 0;
}
#undef IS_KERN_PAIR
#define IS_KERN_PAIR(p) ( p[0] == 'K' && p[1] == 'P' )
#define IS_ALPHANUM(c) ( (c >= 'A' && c <= 'Z') || \
(c >= 'a' && c <= 'z') || \
(c >= '0' && c <= '9') || \
(c == '_' && c == '.') )
/* read a glyph name and return the equivalent glyph index */
static
FT_UInt afm_atoindex( FT_Byte* *start, FT_Byte* limit, T1_Font* type1 )
{
FT_Byte* p = *start;
FT_Int len;
FT_UInt result = 0;
char temp[64];
/* skip whitespace */
while ( (*p == ' ' || *p == '\t' || *p == ':' || *p == ';') && p < limit )
p++;
*start = p;
/* now, read glyph name */
while ( IS_ALPHANUM(*p) && p < limit ) p++;
len = p - *start;
if (len > 0 && len < 64)
{
FT_Int n;
/* copy glyph name to intermediate array */
MEM_Copy( temp, *start, len );
temp[len] = 0;
/* lookup glyph name in face array */
for ( n = 0; n < type1->num_glyphs; n++ )
{
char* gname = (char*)type1->glyph_names[n];
if ( gname && gname[0] == temp[0] && strcmp(gname,temp) == 0 )
{
result = n;
break;
}
}
}
*start = p;
return result;
}
/* read an integer */
static
int afm_atoi( FT_Byte** start, FT_Byte* limit )
{
FT_Byte* p = *start;
int sum = 0;
int sign = 1;
/* skip everything that is not a number */
while ( p < limit && (*p < '0' || *p > '9') )
{
sign = 1;
if (*p == '-')
sign = -1;
p++;
}
while ( p < limit && (*p >= '0' && *p < '9') )
{
sum = sum*10 + (*p - '0');
p++;
}
*start = p;
return sum*sign;
}
#undef KERN_INDEX
#define KERN_INDEX(g1,g2) (((FT_ULong)g1 << 16) | g2)
/* compare two kerning pairs */
static
int compare_kern_pairs( const void* a, const void* b )
{
T1_Kern_Pair* pair1 = (T1_Kern_Pair*)a;
T1_Kern_Pair* pair2 = (T1_Kern_Pair*)b;
FT_ULong index1 = KERN_INDEX(pair1->glyph1,pair1->glyph2);
FT_ULong index2 = KERN_INDEX(pair2->glyph1,pair2->glyph2);
return ( index1 - index2 );
}
/* parse an AFM file - for now, only read the kerning pairs */
LOCAL_FUNC
FT_Error CID_Read_AFM( FT_Face t1_face,
FT_Stream stream )
{
FT_Error error;
FT_Memory memory = stream->memory;
FT_Byte* start;
FT_Byte* limit;
FT_Byte* p;
FT_Int count = 0;
T1_Kern_Pair* pair;
T1_Font* type1 = &((T1_Face)t1_face)->type1;
T1_AFM* afm = 0;
if ( ACCESS_Frame(stream->size) )
return error;
start = (FT_Byte*)stream->cursor;
limit = (FT_Byte*)stream->limit;
p = start;
/* we are now going to count the occurences of "KP" or "KPX" in */
/* the AFM file.. */
count = 0;
for ( p = start; p < limit-3; p++ )
{
if ( IS_KERN_PAIR(p) )
count++;
}
/* Actually, kerning pairs are simply optional !! */
if (count == 0)
goto Exit;
/* allocate the pairs */
if ( ALLOC( afm, sizeof(*afm ) ) ||
ALLOC_ARRAY( afm->kern_pairs, count, T1_Kern_Pair ) )
goto Exit;
/* now, read each kern pair */
pair = afm->kern_pairs;
afm->num_pairs = count;
/* save in face object */
((T1_Face)t1_face)->afm_data = afm;
for ( p = start; p < limit-3; p++ )
{
if ( IS_KERN_PAIR(p) )
{
FT_Byte* q;
/* skip keyword (KP or KPX) */
q = p+2;
if (*q == 'X') q++;
pair->glyph1 = afm_atoindex( &q, limit, type1 );
pair->glyph2 = afm_atoindex( &q, limit, type1 );
pair->kerning.x = afm_atoi( &q, limit );
pair->kerning.y = 0;
if ( p[2] != 'X' )
pair->kerning.y = afm_atoi( &q, limit );
pair++;
}
}
/* now, sort the kern pairs according to their glyph indices */
qsort( afm->kern_pairs, count, sizeof(T1_Kern_Pair), compare_kern_pairs );
Exit:
if (error)
FREE( afm );
FORGET_Frame();
return error;
}
/* find the kerning for a given glyph pair */
LOCAL_FUNC
void CID_Get_Kerning( T1_AFM* afm,
FT_UInt glyph1,
FT_UInt glyph2,
FT_Vector* kerning )
{
T1_Kern_Pair *min, *mid, *max;
FT_ULong index = KERN_INDEX(glyph1,glyph2);
/* simple binary search */
min = afm->kern_pairs;
max = min + afm->num_pairs-1;
while (min <= max)
{
FT_ULong midi;
mid = min + (max-min)/2;
midi = KERN_INDEX(mid->glyph1,mid->glyph2);
if ( midi == index )
{
*kerning = mid->kerning;
return;
}
if ( midi < index ) min = mid+1;
else max = mid-1;
}
kerning->x = 0;
kerning->y = 0;
}
/***************************************************************************
*
* t1afm.h - support for reading Type 1 AFM files
*
*
***************************************************************************/
#ifndef T1AFM_H
#define T1AFM_H
#include <freetype/internal/ftobjs.h>
/* In this version, we only read the kerning table from the */
/* AFM file. We may add support for ligatures a bit later.. */
typedef struct T1_Kern_Pair_
{
FT_UInt glyph1;
FT_UInt glyph2;
FT_Vector kerning;
} T1_Kern_Pair;
typedef struct T1_AFM_
{
FT_Int num_pairs;
T1_Kern_Pair* kern_pairs;
} T1_AFM;
#if 0
LOCAL_DEF
FT_Error CID_Read_AFM( FT_Face face,
FT_Stream stream );
LOCAL_DEF
void CID_Done_AFM( FT_Memory memory,
T1_AFM* afm );
LOCAL_DEF
void CID_Get_Kerning( T1_AFM* afm,
FT_UInt glyph1,
FT_UInt glyph2,
FT_Vector* kerning );
#endif
#endif /* T1AFM_H */
This diff is collapsed.
/*******************************************************************
*
* cidgload.h 1.0
*
* CID-Keyed Type1 Glyph Loader.
*
* Copyright 1996-1998 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.
*
*
* The Type 1 glyph loader uses three distinct objects to build
* scaled and hinted outlines from a charstrings program. These are :
*
* - a glyph builder, CID_Builder, used to store the built outline
*
* - a glyph hinter, T1_Hinter, used to record and apply the stem
* hints
*
* - a charstrings interpreter, CID_Decoder, used to parse the
* Type 1 charstrings stream, manage a stack and call the builder
* and/or hinter depending on the opcodes.
*
* Ideally, a Type 2 glyph loader would only need to have its own
* T2_Decoder object (assuming the hinter is able to manage all
* kinds of hints).
*
******************************************************************/
#ifndef CIDGLOAD_H
#define CIDGLOAD_H
#include <cidobjs.h>
#ifdef __cplusplus
extern "C" {
#endif
/*************************************************************************/
/* */
/* <Structure> CID_Builder */
/* */
/* <Description> */
/* a structure used during glyph loading to store its outline. */
/* */
/* <Fields> */