--- /dev/null
+ The Catharon Open Source LICENSE
+ ----------------------------
+
+ 2000-Jul-04
+
+ Copyright (C) 2000 by Catharon Productions, Inc.
+
+
+
+Introduction
+============
+
+ This license applies to source files distributed by Catharon
+ Productions, Inc. in several archive packages. This license
+ applies to all files found in such packages which do not fall
+ under their own explicit license.
+
+ This license was inspired by the BSD, Artistic, and IJG
+ (Independent JPEG Group) licenses, which all encourage inclusion
+ and use of free software in commercial and freeware products
+ alike. As a consequence, its main points are that:
+
+ o We don't promise that this software works. However, we are
+ interested in any kind of bug reports. (`as is' distribution)
+
+ o You can use this software for whatever you want, in parts or
+ full form, without having to pay us. (`royalty-free' usage)
+
+ o You may not pretend that you wrote this software. If you use
+ it, or only parts of it, in a program, you must acknowledge
+ somewhere in your documentation that you have used the
+ Catharon Code. (`credits')
+
+ We specifically permit and encourage the inclusion of this
+ software, with or without modifications, in commercial products.
+ We disclaim all warranties covering the packages distributed by
+ Catharon Productions, Inc. and assume no liability related to
+ their use.
+
+
+Legal Terms
+===========
+
+0. Definitions
+--------------
+
+ Throughout this license, the terms `Catharon Package', `package',
+ and `Catharon Code' refer to the set of files originally
+ distributed by Catharon Productions, Inc.
+
+ `You' refers to the licensee, or person using the project, where
+ `using' is a generic term including compiling the project's source
+ code as well as linking it to form a `program' or `executable'.
+ This program is referred to as `a program using one of the
+ Catharon Packages'.
+
+ This license applies to all files distributed in the original
+ Catharon Package(s), including all source code, binaries and
+ documentation, unless otherwise stated in the file in its
+ original, unmodified form as distributed in the original archive.
+ If you are unsure whether or not a particular file is covered by
+ this license, you must contact us to verify this.
+
+ The Catharon Packages are copyright (C) 2000 by Catharon
+ Productions, Inc. All rights reserved except as specified below.
+
+1. No Warranty
+--------------
+
+ THE CATHARON PACKAGES ARE PROVIDED `AS IS' WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OF OR THE INABILITY TO
+ USE THE CATHARON PACKAGE.
+
+2. Redistribution
+-----------------
+
+ This license grants a worldwide, royalty-free, perpetual and
+ irrevocable right and license to use, execute, perform, compile,
+ display, copy, create derivative works of, distribute and
+ sublicense the Catharon Packages (in both source and object code
+ forms) and derivative works thereof for any purpose; and to
+ authorize others to exercise some or all of the rights granted
+ herein, subject to the following conditions:
+
+ o Redistribution of source code must retain this license file
+ (`license.txt') unaltered; any additions, deletions or changes
+ to the original files must be clearly indicated in
+ accompanying documentation. The copyright notices of the
+ unaltered, original files must be preserved in all copies of
+ source files.
+
+ o Redistribution in binary form must provide a disclaimer that
+ states that the software is based in part on the work of
+ Catharon Productions, Inc. in the distribution documentation.
+
+ These conditions apply to any software derived from or based on
+ the Catharon Packages, not just the unmodified files. If you use
+ our work, you must acknowledge us. However, no fee need be paid
+ to us.
+
+3. Advertising
+--------------
+
+ Neither Catharon Productions, Inc. and contributors nor you shall
+ use the name of the other for commercial, advertising, or
+ promotional purposes without specific prior written permission.
+
+ We suggest, but do not require, that you use the following phrase
+ to refer to this software in your documentation: 'this software is
+ based in part on the Catharon Typography Project'.
+
+ As you have not signed this license, you are not required to
+ accept it. However, as the Catharon Packages are copyrighted
+ material, only this license, or another one contracted with the
+ authors, grants you the right to use, distribute, and modify it.
+ Therefore, by using, distributing, or modifying the Catharon
+ Packages, you indicate that you understand and accept all the
+ terms of this license.
+
+--- end of license.txt ---
--- /dev/null
+/***************************************************************************/
+/* */
+/* ahangles.h */
+/* */
+/* A routine used to compute vector angles with limited accuracy */
+/* and very high speed (body). */
+/* */
+/* Copyright 2000 Catharon Productions Inc. */
+/* Author: David Turner */
+/* */
+/* This file is part of the Catharon Typography Project and shall only */
+/* be used, modified, and distributed under the terms of the Catharon */
+/* Open Source License that should come with this file under the name */
+/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* Note that this license is compatible with the FreeType license. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahangles.h"
+
+#else
+
+#include <autohint/ahangles.h>
+
+#endif
+
+
+ /* the following table has been automatically generated with */
+ /* the `mather.py' Python script */
+
+ const AH_Angle ah_arctan[1L << AH_ATAN_BITS] =
+ {
+ 0, 0, 1, 1, 1, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 5,
+ 5, 5, 6, 6, 6, 7, 7, 7,
+ 8, 8, 8, 9, 9, 9, 10, 10,
+ 10, 10, 11, 11, 11, 12, 12, 12,
+ 13, 13, 13, 14, 14, 14, 14, 15,
+ 15, 15, 16, 16, 16, 17, 17, 17,
+ 18, 18, 18, 18, 19, 19, 19, 20,
+ 20, 20, 21, 21, 21, 21, 22, 22,
+ 22, 23, 23, 23, 24, 24, 24, 24,
+ 25, 25, 25, 26, 26, 26, 26, 27,
+ 27, 27, 28, 28, 28, 28, 29, 29,
+ 29, 30, 30, 30, 30, 31, 31, 31,
+ 31, 32, 32, 32, 33, 33, 33, 33,
+ 34, 34, 34, 34, 35, 35, 35, 35,
+ 36, 36, 36, 36, 37, 37, 37, 38,
+ 38, 38, 38, 39, 39, 39, 39, 40,
+ 40, 40, 40, 41, 41, 41, 41, 42,
+ 42, 42, 42, 42, 43, 43, 43, 43,
+ 44, 44, 44, 44, 45, 45, 45, 45,
+ 46, 46, 46, 46, 46, 47, 47, 47,
+ 47, 48, 48, 48, 48, 48, 49, 49,
+ 49, 49, 50, 50, 50, 50, 50, 51,
+ 51, 51, 51, 51, 52, 52, 52, 52,
+ 52, 53, 53, 53, 53, 53, 54, 54,
+ 54, 54, 54, 55, 55, 55, 55, 55,
+ 56, 56, 56, 56, 56, 57, 57, 57,
+ 57, 57, 57, 58, 58, 58, 58, 58,
+ 59, 59, 59, 59, 59, 59, 60, 60,
+ 60, 60, 60, 61, 61, 61, 61, 61,
+ 61, 62, 62, 62, 62, 62, 62, 63,
+ 63, 63, 63, 63, 63, 64, 64, 64
+ };
+
+
+ LOCAL_FUNC
+ AH_Angle ah_angle( FT_Vector* v )
+ {
+ FT_Pos dx, dy;
+ AH_Angle angle;
+
+
+ dx = v->x;
+ dy = v->y;
+
+ /* check trivial cases */
+ if ( dy == 0 )
+ {
+ angle = 0;
+ if ( dx < 0 )
+ angle = AH_PI;
+ return angle;
+ }
+ else if ( dx == 0 )
+ {
+ angle = AH_HALF_PI;
+ if ( dy < 0 )
+ angle = -AH_HALF_PI;
+ return angle;
+ }
+
+ angle = 0;
+ if ( dx < 0 )
+ {
+ dx = -v->x;
+ dy = -v->y;
+ angle = AH_PI;
+ }
+
+ if ( dy < 0 )
+ {
+ FT_Pos tmp;
+
+
+ tmp = dx;
+ dx = -dy;
+ dy = tmp;
+ angle -= AH_HALF_PI;
+ }
+
+ if ( dx == 0 && dy == 0 )
+ return 0;
+
+ if ( dx == dy )
+ angle += AH_PI / 4;
+ else if ( dx > dy )
+ angle += ah_arctan[FT_DivFix( dy, dx ) >> ( 16 - AH_ATAN_BITS )];
+ else
+ angle += AH_HALF_PI -
+ ah_arctan[FT_DivFix( dx, dy ) >> ( 16 - AH_ATAN_BITS )];
+
+ if ( angle > AH_PI )
+ angle -= AH_2PI;
+
+ return angle;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ahangles.h */
+/* */
+/* A routine used to compute vector angles with limited accuracy */
+/* and very high speed (specification). */
+/* */
+/* Copyright 2000 Catharon Productions Inc. */
+/* Author: David Turner */
+/* */
+/* This file is part of the Catharon Typography Project and shall only */
+/* be used, modified, and distributed under the terms of the Catharon */
+/* Open Source License that should come with this file under the name */
+/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* Note that this license is compatible with the FreeType license. */
+/* */
+/***************************************************************************/
+
+
+#ifndef AHANGLES_H
+#define AHANGLES_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahtypes.h"
+
+#else
+
+#include <autohint/ahtypes.h>
+
+#endif
+
+
+#include <freetype/internal/ftobjs.h>
+
+
+ /* PI expressed in ah_angles -- we don't really need an important */
+ /* precision, so 256 should be enough */
+#define AH_PI 256
+#define AH_2PI ( AH_PI * 2 )
+#define AH_HALF_PI ( AH_PI / 2 )
+#define AH_2PIMASK ( AH_2PI - 1 )
+
+ /* the number of bits used to express an arc tangent; */
+ /* see the structure of the lookup table */
+#define AH_ATAN_BITS 8
+
+ extern
+ const AH_Angle ah_arctan[1L << AH_ATAN_BITS];
+
+
+ LOCAL_DEF
+ AH_Angle ah_angle( FT_Vector* v );
+
+
+#endif /* AHANGLES_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ahglobal.c */
+/* */
+/* Routines used to compute global metrics automatically (body). */
+/* */
+/* Copyright 2000 Catharon Productions Inc. */
+/* Author: David Turner */
+/* */
+/* This file is part of the Catharon Typography Project and shall only */
+/* be used, modified, and distributed under the terms of the Catharon */
+/* Open Source License that should come with this file under the name */
+/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* Note that this license is compatible with the FreeType license. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahglobal.h"
+#include "ahglyph.h"
+
+#else
+
+#include <autohint/ahglobal.h>
+#include <autohint/ahglyph.h>
+
+#endif
+
+
+#define MAX_TEST_CHARACTERS 12
+
+ static
+ const char* blue_chars[ah_blue_max] =
+ {
+ "THEZOCQS",
+ "HEZLOCUS",
+ "xzroesc",
+ "xzroesc",
+ "pqgjy"
+ };
+
+
+ /* simple insertion sort */
+ static
+ void sort_values( FT_Int count,
+ FT_Pos* table )
+ {
+ FT_Int i, j, swap;
+
+
+ for ( i = 1; i < count; i++ )
+ {
+ for ( j = i; j > 1; j-- )
+ {
+ if ( table[j] > table[j - 1] )
+ break;
+
+ swap = table[j];
+ table[j] = table[j - 1];
+ table[j - 1] = swap;
+ }
+ }
+ }
+
+
+ static
+ FT_Error ah_hinter_compute_blues( AH_Hinter* hinter )
+ {
+ AH_Blue blue;
+ AH_Globals* globals = &hinter->globals->design;
+ FT_Pos flats [MAX_TEST_CHARACTERS];
+ FT_Pos rounds[MAX_TEST_CHARACTERS];
+ FT_Int num_flats;
+ FT_Int num_rounds;
+
+ FT_Face face;
+ FT_GlyphSlot glyph;
+ FT_Error error;
+ FT_CharMap charmap;
+
+
+ face = hinter->face;
+ glyph = face->glyph;
+
+ /* save current charmap */
+ charmap = face->charmap;
+
+ /* do we have a Unicode charmap in there? */
+ error = FT_Select_Charmap( face, ft_encoding_unicode );
+ if ( error )
+ goto Exit;
+
+ /* we compute the blues simply by loading each character from the */
+ /* 'blue_chars[blues]' string, then compute its top-most and */
+ /* bottom-most points */
+
+ AH_LOG(( "blue zones computation\n" ));
+ AH_LOG(( "------------------------------------------------\n" ));
+
+ for ( blue = ah_blue_capital_top; blue < ah_blue_max; blue++ )
+ {
+ const char* p = blue_chars[blue];
+ const char* limit = p + MAX_TEST_CHARACTERS;
+ FT_Pos *blue_ref, *blue_shoot;
+
+
+ AH_LOG(( "blue %3d: ", blue ));
+
+ num_flats = 0;
+ num_rounds = 0;
+
+ for ( ; p < limit; p++ )
+ {
+ FT_UInt glyph_index;
+ FT_Vector* extremum;
+ FT_Vector* points;
+ FT_Vector* point_limit;
+ FT_Vector* point;
+ FT_Bool round;
+
+
+ /* exit if we reach the end of the string */
+ if ( !*p )
+ break;
+
+ AH_LOG(( "`%c'", *p ));
+
+ /* load the character in the face -- skip unknown or empty ones */
+ glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
+ if ( glyph_index == 0 )
+ continue;
+
+ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+ if ( error || glyph->outline.n_points <= 0 )
+ continue;
+
+ /* now compute min or max point indices and coordinates */
+ points = glyph->outline.points;
+ point_limit = points + glyph->outline.n_points;
+ point = points;
+ extremum = point;
+ point++;
+
+ if ( AH_IS_TOP_BLUE( blue ) )
+ {
+ for ( ; point < point_limit; point++ )
+ if ( point->y > extremum->y )
+ extremum = point;
+ }
+ else
+ {
+ for ( ; point < point_limit; point++ )
+ if ( point->y < extremum->y )
+ extremum = point;
+ }
+
+ AH_LOG(( "%5d", (int)extremum->y ));
+
+ /* now, check whether the point belongs to a straight or round */
+ /* segment; we first need to find in which contour the extremum */
+ /* lies, then see its previous and next points */
+ {
+ FT_Int index = extremum - points;
+ FT_Int n;
+ FT_Int first, last, prev, next, end;
+ FT_Pos dist;
+
+
+ last = -1;
+ first = 0;
+
+ for ( n = 0; n < glyph->outline.n_contours; n++ )
+ {
+ end = glyph->outline.contours[n];
+ if ( end >= index )
+ {
+ last = end;
+ break;
+ }
+ first = end + 1;
+ }
+
+ /* XXX: should never happen! */
+ if ( last < 0 )
+ continue;
+
+ /* now look for the previous and next points that are not on the */
+ /* same Y coordinate. Threshold the `closeness'... */
+
+ prev = index;
+ next = prev;
+
+ do
+ {
+ if ( prev > first )
+ prev--;
+ else
+ prev = last;
+
+ dist = points[prev].y - extremum->y;
+ if ( dist < -5 || dist > 5 )
+ break;
+
+ } while ( prev != index );
+
+ do
+ {
+ if ( next < last )
+ next++;
+ else
+ next = first;
+
+ dist = points[next].y - extremum->y;
+ if ( dist < -5 || dist > 5 )
+ break;
+
+ } while ( next != index );
+
+ /* now, set the `round' flag depending on the segment's kind */
+ round =
+ FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_Curve_Tag_On ||
+ FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_Curve_Tag_On ;
+
+ AH_LOG(( "%c ", round ? 'r' : 'f' ));
+ }
+
+ if ( round )
+ rounds[num_rounds++] = extremum->y;
+ else
+ flats[num_flats++] = extremum->y;
+ }
+
+ AH_LOG(( "\n" ));
+
+ /* we have computed the contents of the `rounds' and `flats' tables, */
+ /* now determine the reference and overshoot position of the blue; */
+ /* we simply take the median value after a simple short */
+ sort_values( num_rounds, rounds );
+ sort_values( num_flats, flats );
+
+ blue_ref = globals->blue_refs + blue;
+ blue_shoot = globals->blue_shoots + blue;
+ if ( num_flats == 0 && num_rounds == 0 )
+ {
+ *blue_ref = -10000;
+ *blue_shoot = -10000;
+ }
+ else if ( num_flats == 0 )
+ {
+ *blue_ref =
+ *blue_shoot = rounds[num_rounds / 2];
+ }
+ else if ( num_rounds == 0 )
+ {
+ *blue_ref =
+ *blue_shoot = flats[num_flats / 2];
+ }
+ else
+ {
+ *blue_ref = flats[num_flats / 2];
+ *blue_shoot = rounds[num_rounds / 2];
+ }
+
+ /* there are sometimes problems: if the overshoot position of top */
+ /* zones is under its reference position, or the opposite for bottom */
+ /* zones. We must thus check everything there and correct the errors */
+ if ( *blue_shoot != *blue_ref )
+ {
+ FT_Pos ref = *blue_ref;
+ FT_Pos shoot = *blue_shoot;
+ FT_Bool over_ref = ( shoot > ref );
+
+
+ if ( AH_IS_TOP_BLUE( blue ) ^ over_ref )
+ *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
+ }
+
+ AH_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
+ }
+
+ /* reset original face charmap */
+ FT_Set_Charmap( face, charmap );
+ error = 0;
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ FT_Error ah_hinter_compute_widths( AH_Hinter* hinter )
+ {
+ /* scan the array of segments in each direction */
+ AH_Outline* outline = hinter->glyph;
+ AH_Segment* segments;
+ AH_Segment* limit;
+ AH_Globals* globals = &hinter->globals->design;
+ FT_Pos* widths;
+ FT_Int dimension;
+ FT_Int* p_num_widths;
+ FT_Error error = 0;
+ FT_Pos edge_distance_threshold = 32000;
+
+
+ globals->num_widths = 0;
+ globals->num_heights = 0;
+
+ /* For now, compute the standard width and height from the `o' */
+ /* character. I started computing the stem width of the `i' and the */
+ /* stem height of the "-", but it wasn't too good. Moreover, we now */
+ /* have a single character that gives us standard width and height. */
+ {
+ FT_UInt glyph_index;
+
+
+ glyph_index = FT_Get_Char_Index( hinter->face, 'o' );
+ if ( glyph_index == 0 )
+ return 0;
+
+ error = FT_Load_Glyph( hinter->face, glyph_index, FT_LOAD_NO_SCALE );
+ if ( error )
+ goto Exit;
+
+ error = ah_outline_load( hinter->glyph, hinter->face );
+ if ( error )
+ goto Exit;
+
+ ah_outline_compute_segments( hinter->glyph );
+ ah_outline_link_segments( hinter->glyph );
+ }
+
+ segments = outline->horz_segments;
+ limit = segments + outline->num_hsegments;
+ widths = globals->heights;
+ p_num_widths = &globals->num_heights;
+
+ for ( dimension = 1; dimension >= 0; dimension-- )
+ {
+ AH_Segment* seg = segments;
+ AH_Segment* link;
+ FT_Int num_widths = 0;
+
+
+ for ( ; seg < limit; seg++ )
+ {
+ link = seg->link;
+ /* we only consider stem segments there! */
+ if ( link && link->link == seg && link > seg )
+ {
+ FT_Int dist;
+
+
+ dist = seg->pos - link->pos;
+ if ( dist < 0 )
+ dist = -dist;
+
+ if ( num_widths < 12 )
+ widths[num_widths++] = dist;
+ }
+ }
+
+ sort_values( num_widths, widths );
+ *p_num_widths = num_widths;
+
+ /* we will now try to find the smallest width */
+ if ( num_widths > 0 && widths[0] < edge_distance_threshold )
+ edge_distance_threshold = widths[0];
+
+ segments = outline->vert_segments;
+ limit = segments + outline->num_vsegments;
+ widths = globals->widths;
+ p_num_widths = &globals->num_widths;
+
+ }
+
+ /* Now, compute the edge distance threshold as a fraction of the */
+ /* smallest width in the font. Set it in `hinter.glyph' too! */
+ if ( edge_distance_threshold == 32000 )
+ edge_distance_threshold = 50;
+
+ /* let's try 20% */
+ hinter->glyph->edge_distance_threshold = edge_distance_threshold / 5;
+
+ Exit:
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ FT_Error ah_hinter_compute_globals( AH_Hinter* hinter )
+ {
+ return ah_hinter_compute_widths( hinter ) ||
+ ah_hinter_compute_blues ( hinter );
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ahglobal.h */
+/* */
+/* Routines used to compute global metrics automatically */
+/* (specification). */
+/* */
+/* Copyright 2000 Catharon Productions Inc. */
+/* Author: David Turner */
+/* */
+/* This file is part of the Catharon Typography Project and shall only */
+/* be used, modified, and distributed under the terms of the Catharon */
+/* Open Source License that should come with this file under the name */
+/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* Note that this license is compatible with the FreeType license. */
+/* */
+/***************************************************************************/
+
+
+#ifndef AHGLOBAL_H
+#define AHGLOBAL_H
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahtypes.h"
+
+#else
+
+#include <autohint/ahtypes.h>
+
+#endif
+
+
+#include <freetype/internal/ftobjs.h> /* for LOCAL_DEF/LOCAL_FUNC */
+
+
+#define AH_IS_TOP_BLUE( b ) ( (b) == ah_blue_capital_top || \
+ (b) == ah_blue_small_top )
+
+
+ /* compute global metrics automatically */
+ LOCAL_DEF
+ FT_Error ah_hinter_compute_globals( AH_Hinter* hinter );
+
+
+#endif /* AHGLOBAL_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ahglyph.c */
+/* */
+/* Routines used to load and analyze a given glyph before hinting */
+/* (body). */
+/* */
+/* Copyright 2000 Catharon Productions Inc. */
+/* Author: David Turner */
+/* */
+/* This file is part of the Catharon Typography Project and shall only */
+/* be used, modified, and distributed under the terms of the Catharon */
+/* Open Source License that should come with this file under the name */
+/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* Note that this license is compatible with the FreeType license. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahglyph.h"
+#include "ahangles.h"
+#include "ahglobal.h"
+
+#else
+
+#include <autohint/ahglyph.h>
+#include <autohint/ahangles.h>
+#include <autohint/ahglobal.h>
+
+#endif
+
+
+#include <stdio.h>
+
+
+#define xxxAH_DEBUG_GLYPH
+
+
+ /* compute the direction value of a given vector.. */
+ static
+ AH_Direction ah_compute_direction( FT_Pos dx,
+ FT_Pos dy )
+ {
+ AH_Direction dir;
+ FT_Pos ax = ABS( dx );
+ FT_Pos ay = ABS( dy );
+
+
+ dir = ah_dir_none;
+
+ /* test for vertical direction */
+ if ( ax * 12 < ay )
+ {
+ dir = dy > 0 ? ah_dir_up : ah_dir_down;
+ }
+ /* test for horizontal direction */
+ else if ( ay * 12 < ax )
+ {
+ dir = dx > 0 ? ah_dir_right : ah_dir_left;
+ }
+
+ return dir;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ah_outline_new */
+ /* */
+ /* <Description> */
+ /* Creates a new and empty AH_Outline object. */
+ /* */
+ LOCAL_FUNC
+ FT_Error ah_outline_new( FT_Memory memory,
+ AH_Outline** aoutline )
+ {
+ FT_Error error;
+ AH_Outline* outline;
+
+
+ if ( !ALLOC( outline, sizeof ( *outline ) ) )
+ {
+ outline->memory = memory;
+ *aoutline = outline;
+ }
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ah_outline_done */
+ /* */
+ /* <Description> */
+ /* Destroys a given AH_Outline object. */
+ /* */
+ LOCAL_FUNC
+ void ah_outline_done( AH_Outline* outline )
+ {
+ FT_Memory memory = outline->memory;
+
+
+ FREE( outline->horz_edges );
+ FREE( outline->horz_segments );
+ FREE( outline->contours );
+ FREE( outline->points );
+
+ FREE( outline );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ah_outline_save */
+ /* */
+ /* <Description> */
+ /* Saves the content of a given AH_Outline object into a face's glyph */
+ /* slot. */
+ /* */
+ LOCAL_FUNC
+ void ah_outline_save( AH_Outline* outline,
+ AH_Loader* gloader )
+ {
+ AH_Point* point = outline->points;
+ AH_Point* limit = point + outline->num_points;
+ FT_Vector* vec = gloader->current.outline.points;
+ char* tag = gloader->current.outline.tags;
+
+
+ /* we assume that the glyph loader has already been checked for storage */
+ for ( ; point < limit; point++, vec++, tag++ )
+ {
+ vec->x = point->x;
+ vec->y = point->y;
+
+ if ( point->flags & ah_flah_conic )
+ tag[0] = FT_Curve_Tag_Conic;
+ else if ( point->flags & ah_flah_cubic )
+ tag[0] = FT_Curve_Tag_Cubic;
+ else
+ tag[0] = FT_Curve_Tag_On;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ah_outline_load */
+ /* */
+ /* <Description> */
+ /* Loads an unscaled outline from a glyph slot into an AH_Outline */
+ /* object. */
+ /* */
+ LOCAL_FUNC
+ FT_Error ah_outline_load( AH_Outline* outline,
+ FT_Face face )
+ {
+ FT_Memory memory = outline->memory;
+ FT_Error error = FT_Err_Ok;
+ FT_Outline* source = &face->glyph->outline;
+ FT_Int num_points = source->n_points;
+ FT_Int num_contours = source->n_contours;
+ AH_Point* points;
+
+
+ /* check arguments */
+ if ( !face ||
+ !face->size ||
+ face->glyph->format != ft_glyph_format_outline )
+ return FT_Err_Invalid_Argument;
+
+ /* first of all, reallocate the contours array if necessary */
+ if ( num_contours > outline->max_contours )
+ {
+ FT_Int new_contours = ( num_contours + 3 ) & -4;
+
+
+ if ( REALLOC_ARRAY( outline->contours, outline->max_contours,
+ new_contours, AH_Point* ) )
+ goto Exit;
+
+ outline->max_contours = new_contours;
+ }
+
+ /* then, realloc the points, segments & edges arrays if needed */
+ if ( num_points > outline->max_points )
+ {
+ FT_Int news = ( num_points + 7 ) & -8;
+ FT_Int max = outline->max_points;
+
+
+ if ( REALLOC_ARRAY( outline->points, max, news, AH_Point ) ||
+ REALLOC_ARRAY( outline->horz_edges, max, news, AH_Edge ) ||
+ REALLOC_ARRAY( outline->horz_segments, max, news, AH_Segment ) )
+ goto Exit;
+
+ /* readjust some pointers */
+ outline->vert_edges = outline->horz_edges + ( news >> 1 );
+ outline->vert_segments = outline->horz_segments + ( news >> 1 );
+ outline->max_points = news;
+ }
+
+ outline->num_points = num_points;
+ outline->num_contours = num_contours;
+
+ outline->num_hedges = 0;
+ outline->num_vedges = 0;
+ outline->num_hsegments = 0;
+ outline->num_vsegments = 0;
+
+ /* Compute the vertical and horizontal major directions; this is */
+ /* currently done by inspecting the `ft_outline_reverse_fill' flag. */
+ /* However, some fonts have improper glyphs, and it'd be a good idea */
+ /* to be able to re-compute these values on the fly. */
+ outline->vert_major_dir = ah_dir_up;
+ outline->horz_major_dir = ah_dir_left;
+
+ if ( source->flags & ft_outline_reverse_fill )
+ {
+ outline->vert_major_dir = ah_dir_down;
+ outline->horz_major_dir = ah_dir_right;
+ }
+
+ outline->x_scale = face->size->metrics.x_scale;
+ outline->y_scale = face->size->metrics.y_scale;
+
+ points = outline->points;
+
+ {
+ /* do one thing at a time -- it is easier to understand, and */
+ /* the code is clearer */
+ AH_Point* point = points;
+ AH_Point* limit = point + outline->num_points;
+
+
+ /* compute coordinates */
+ {
+ FT_Vector* vec = source->points;
+ FT_Fixed x_scale = outline->x_scale;
+ FT_Fixed y_scale = outline->y_scale;
+
+
+ for (; point < limit; vec++, point++ )
+ {
+ point->fx = vec->x;
+ point->fy = vec->y;
+ point->ox = point->x = FT_MulFix( vec->x, x_scale );
+ point->oy = point->y = FT_MulFix( vec->y, y_scale );
+
+ point->flags = 0;
+ }
+ }
+
+ /* compute Bezier flags */
+ {
+ char* tag = source->tags;
+
+
+ for ( point = points; point < limit; point++, tag++ )
+ {
+ switch ( FT_CURVE_TAG( *tag ) )
+ {
+ case FT_Curve_Tag_Conic:
+ point->flags = ah_flah_conic; break;
+ case FT_Curve_Tag_Cubic:
+ point->flags = ah_flah_cubic; break;
+ default:
+ ;
+ }
+ }
+ }
+
+ /* compute `next' and `prev' */
+ {
+ FT_Int contour_index;
+ AH_Point* prev;
+ AH_Point* first;
+ AH_Point* end;
+
+
+ contour_index = 0;
+
+ first = points;
+ end = points + source->contours[0];
+ prev = end;
+
+ for ( point = points; point < limit; point++ )
+ {
+ point->prev = prev;
+ if ( point < end )
+ {
+ point->next = point + 1;
+ prev = point;
+ }
+ else
+ {
+ point->next = first;
+ contour_index++;
+ if ( point + 1 < limit )
+ {
+ end = points + source->contours[contour_index];
+ first = point + 1;
+ prev = end;
+ }
+ }
+ }
+ }
+
+ /* set-up the contours array */
+ {
+ AH_Point** contour = outline->contours;
+ AH_Point** limit = contour + outline->num_contours;
+ short* end = source->contours;
+ short index = 0;
+
+
+ for ( ; contour < limit; contour++, end++ )
+ {
+ contour[0] = points + index;
+ index = end[0] + 1;
+ }
+ }
+
+ /* compute directions of in & out vectors */
+ {
+ for ( point = points; point < limit; point++ )
+ {
+ AH_Point* prev;
+ AH_Point* next;
+ FT_Vector vec;
+
+
+ prev = point->prev;
+ vec.x = point->fx - prev->fx;
+ vec.y = point->fy - prev->fy;
+
+ point->in_dir = ah_compute_direction( vec.x, vec.y );
+
+#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
+ point->in_angle = ah_angle( &vec );
+#endif
+
+ next = point->next;
+ vec.x = next->fx - point->fx;
+ vec.y = next->fy - point->fy;
+
+ point->out_dir = ah_compute_direction( vec.x, vec.y );
+
+#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
+ point->out_angle = ah_angle( &vec );
+
+ {
+ AH_Angle delta = point->in_angle - point->out_angle;
+
+
+ if ( delta < 0 )
+ delta = -delta;
+ if ( delta < 2 )
+ point->flags |= ah_flah_weak_interpolation;
+ }
+
+#if 0
+ if ( point->flags & ( ah_flah_conic | ah_flah_cubic ) )
+ point->flags |= ah_flah_weak_interpolation;
+#endif
+
+#endif /* !AH_OPTION_NO_WEAK_INTERPOLATION */
+
+#ifdef AH_OPTION_NO_STRONG_INTERPOLATION
+ point->flags |= ah_flah_weak_interpolation;
+#endif
+ }
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ void ah_setup_uv( AH_Outline* outline,
+ AH_UV source )
+ {
+ AH_Point* point = outline->points;
+ AH_Point* limit = point + outline->num_points;
+
+
+ for ( ; point < limit; point++ )
+ {
+ FT_Pos u, v;
+
+
+ switch ( source )
+ {
+ case ah_uv_fxy:
+ u = point->fx;
+ v = point->fy;
+ break;
+ case ah_uv_fyx:
+ u = point->fy;
+ v = point->fx;
+ break;
+ case ah_uv_oxy:
+ u = point->ox;
+ v = point->oy;
+ break;
+ case ah_uv_oyx:
+ u = point->oy;
+ v = point->ox;
+ break;
+ case ah_uv_yx:
+ u = point->y;
+ v = point->x;
+ break;
+ case ah_uv_ox:
+ u = point->x;
+ v = point->ox;
+ break;
+ case ah_uv_oy:
+ u = point->y;
+ v = point->oy;
+ break;
+ default:
+ u = point->x;
+ v = point->y;
+ break;
+ }
+ point->u = u;
+ point->v = v;
+ }
+ }
+
+
+ LOCAL_FUNC
+ void ah_outline_compute_segments( AH_Outline* outline )
+ {
+ int dimension;
+ AH_Segment* segments;
+ FT_Int* p_num_segments;
+ AH_Direction segment_dir;
+ AH_Direction major_dir;
+
+
+ segments = outline->horz_segments;
+ p_num_segments = &outline->num_hsegments;
+ major_dir = ah_dir_right; /* This value must be positive! */
+ segment_dir = major_dir;
+
+ /* set up (u,v) in each point */
+ ah_setup_uv( outline, ah_uv_fyx );
+
+ for ( dimension = 1; dimension >= 0; dimension-- )
+ {
+ AH_Point** contour = outline->contours;
+ AH_Point** contour_limit = contour + outline->num_contours;
+ AH_Segment* segment = segments;
+ FT_Int num_segments = 0;
+
+#ifdef AH_HINT_METRICS
+ AH_Point* min_point = 0;
+ AH_Point* max_point = 0;
+ FT_Pos min_coord = 32000;
+ FT_Pos max_coord = -32000;
+#endif
+
+
+ /* do each contour separately */
+ for ( ; contour < contour_limit; contour++ )
+ {
+ AH_Point* point = contour[0];
+ AH_Point* last = point->prev;
+ int on_edge = 0;
+ FT_Pos min_pos = +32000; /* minimum segment pos != min_coord */
+ FT_Pos max_pos = -32000; /* maximum segment pos != max_coord */
+ FT_Bool passed;
+
+
+#ifdef AH_HINT_METRICS
+ if ( point->u < min_coord )
+ {
+ min_coord = point->u;
+ min_point = point;
+ }
+ if ( point->u > max_coord )
+ {
+ max_coord = point->u;
+ max_point = point;
+ }
+#endif
+
+ if ( point == last ) /* skip singletons -- just in case? */
+ continue;
+
+ if ( ABS( last->out_dir ) == major_dir &&
+ ABS( point->out_dir ) == major_dir )
+ {
+ /* we are already on an edge, try to locate its start */
+ last = point;
+
+ for (;;)
+ {
+ point = point->prev;
+ if ( ABS( point->out_dir ) != major_dir )
+ {
+ point = point->next;
+ break;
+ }
+ if ( point == last )
+ break;
+ }
+
+ }
+
+ last = point;
+ passed = 0;
+
+ for (;;)
+ {
+ FT_Pos u, v;
+
+
+ if ( on_edge )
+ {
+ u = point->u;
+ if ( u < min_pos )
+ min_pos = u;
+ if ( u > max_pos )
+ max_pos = u;
+
+ if ( point->out_dir != segment_dir || point == last )
+ {
+ /* we are just leaving an edge; record a new segment! */
+ segment->last = point;
+ segment->pos = ( min_pos + max_pos ) >> 1;
+
+ /* a segment is round if either its first or last point */
+ /* is a control point */
+ if ( ( segment->first->flags | point->flags ) &
+ ah_flah_control )
+ segment->flags |= ah_edge_round;
+
+ /* compute segment size */
+ min_pos = max_pos = point->v;
+
+ v = segment->first->v;
+ if ( v < min_pos )
+ min_pos = v;
+ if ( v > max_pos )
+ max_pos = v;
+
+ segment->min_coord = min_pos;
+ segment->max_coord = max_pos;
+
+ on_edge = 0;
+ num_segments++;
+ segment++;
+ /* fallthrough */
+ }
+ }
+
+ /* now exit if we are at the start/end point */
+ if ( point == last )
+ {
+ if ( passed )
+ break;
+ passed = 1;
+ }
+
+ if ( !on_edge && ABS( point->out_dir ) == major_dir )
+ {
+ /* this is the start of a new segment! */
+ segment_dir = point->out_dir;
+
+ /* clear all segment fields */
+ memset( segment, 0, sizeof ( *segment ) );
+
+ segment->dir = segment_dir;
+ segment->flags = ah_edge_normal;
+ min_pos = max_pos = point->u;
+ segment->first = point;
+ segment->last = point;
+ segment->contour = contour;
+ on_edge = 1;
+
+ if ( point == max_point )
+ max_point = 0;
+
+ if ( point == min_point )
+ min_point = 0;
+ }
+
+ point = point->next;
+ }
+
+ } /* contours */
+
+#ifdef AH_HINT_METRICS
+ /* we need to ensure that there are edges on the left-most and */
+ /* right-most points of the glyph in order to hint the metrics; */
+ /* we do this by inserting fake segments when needed */
+ if ( dimension == 0 )
+ {
+ AH_Point* point = outline->points;
+ AH_Point* limit = point + outline->num_points;
+
+ AH_Point* min_point = 0;
+ AH_Point* max_point = 0;
+ FT_Pos min_pos = 32000;
+ FT_Pos max_pos = -32000;
+
+
+ /* compute minimum and maximum points */
+ for ( ; point < limit; point++ )
+ {
+ FT_Pos x = point->fx;
+
+
+ if ( x < min_pos )
+ {
+ min_pos = x;
+ min_point = point;
+ }
+ if ( x > max_pos )
+ {
+ max_pos = x;
+ max_point = point;
+ }
+ }
+
+ /* insert minimum segment */
+ if ( min_point )
+ {
+ /* clear all segment fields */
+ memset( segment, 0, sizeof ( *segment ) );
+
+ segment->dir = segment_dir;
+ segment->flags = ah_edge_normal;
+ segment->first = min_point;
+ segment->last = min_point;
+ segment->pos = min_pos;
+
+ num_segments++;
+ segment++;
+ }
+
+ /* insert maximum segment */
+ if ( max_point )
+ {
+ /* clear all segment fields */
+ memset( segment, 0, sizeof ( *segment ) );
+
+ segment->dir = segment_dir;
+ segment->flags = ah_edge_normal;
+ segment->first = max_point;
+ segment->last = max_point;
+ segment->pos = max_pos;
+
+ num_segments++;
+ segment++;
+ }
+ }
+#endif /* AH_HINT_METRICS */
+
+ *p_num_segments = num_segments;
+
+ segments = outline->vert_segments;
+ major_dir = ah_dir_up;
+ p_num_segments = &outline->num_vsegments;
+ ah_setup_uv( outline, ah_uv_fxy );
+ }
+ }
+
+
+ LOCAL_FUNC
+ void ah_outline_link_segments( AH_Outline* outline )
+ {
+ AH_Segment* segments;
+ AH_Segment* limit;
+ int dimension;
+
+
+ ah_setup_uv( outline, ah_uv_fyx );
+
+ segments = outline->horz_segments;
+ limit = segments + outline->num_hsegments;
+
+ for ( dimension = 1; dimension >= 0; dimension-- )
+ {
+ AH_Segment* seg1;
+ AH_Segment* seg2;
+
+
+ /* now compare each segment to the others */
+ for ( seg1 = segments; seg1 < limit; seg1++ )
+ {
+ FT_Pos best_score = 32000;
+ AH_Segment* best_segment = 0;
+
+
+ /* the fake segments are introduced to hint the metrics -- */
+ /* we must never link them to anything */
+ if ( seg1->first == seg1->last )
+ continue;
+
+ for ( seg2 = segments; seg2 < limit; seg2++ )
+ if ( seg1 != seg2 && seg1->dir + seg2->dir == 0 )
+ {
+ FT_Pos pos1 = seg1->pos;
+ FT_Pos pos2 = seg2->pos;
+ FT_Bool is_dir;
+ FT_Bool is_pos;
+
+
+ /* check that the segments are correctly oriented and */
+ /* positioned to form a black distance */
+
+ is_dir = ( seg1->dir == outline->horz_major_dir ||
+ seg1->dir == outline->vert_major_dir );
+ is_pos = pos1 > pos2;
+
+ if ( pos1 == pos2 || !(is_dir ^ is_pos) )
+ continue;
+
+ /* Check the two segments. We now have a better algorithm */
+ /* that doesn't rely on the segment points themselves but */
+ /* on their relative position. This gets rids of many */
+ /* unpleasant artefacts and incorrect stem/serifs */
+ /* computations. */
+
+ /* first of all, compute the size of the `common' height */
+ {
+ FT_Pos min = seg1->min_coord;
+ FT_Pos max = seg1->max_coord;
+ FT_Pos len, score;
+ FT_Pos size1, size2;
+
+
+ size1 = max - min;
+ size2 = seg2->max_coord - seg2->min_coord;
+
+ if ( min < seg2->min_coord )
+ min = seg2->min_coord;
+
+ if ( max < seg2->max_coord )
+ max = seg2->max_coord;
+
+ len = max - min;
+ score = seg2->pos - seg1->pos;
+ if ( score < 0 )
+ score = -score;
+
+ /* before comparing the scores, take care that the segments */
+ /* are really facing each other (often not for italics..) */
+ if ( 4 * len >= size1 && 4 * len >= size2 )
+ if ( score < best_score )
+ {
+ best_score = score;
+ best_segment = seg2;
+ }
+ }
+ }
+
+ if ( best_segment )
+ {
+ seg1->link = best_segment;
+ seg1->score = best_score;
+
+ best_segment->num_linked++;
+ }
+
+
+ } /* edges 1 */
+
+ /* now, compute the `serif' segments */
+ for ( seg1 = segments; seg1 < limit; seg1++ )
+ {
+ seg2 = seg1->link;
+
+ if ( seg2 && seg2->link != seg1 )
+ {
+ seg1->link = 0;
+ seg1->serif = seg2->link;
+ }
+ }
+
+ ah_setup_uv( outline, ah_uv_fxy );
+
+ segments = outline->vert_segments;
+ limit = segments + outline->num_vsegments;
+ }
+ }
+
+
+#ifdef AH_DEBUG_GLYPH
+
+ /* A function used to dump the array of linked segments */
+ void ah_dump_segments( AH_Outline* outline )
+ {
+ AH_Segment* segments;
+ AH_Segment* limit;
+ AH_Point* points;
+ FT_Int dimension;
+
+
+ points = outline->points;
+ segments = outline->horz_segments;
+ limit = segments + outline->num_hsegments;
+
+ for ( dimension = 1; dimension >= 0; dimension-- )
+ {
+ AH_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 < limit; seg++ )
+ {
+ printf ( " [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n",
+ seg - segments,
+ (int)seg->pos,
+ seg->dir == ah_dir_up
+ ? "up"
+ : ( seg->dir == ah_dir_down
+ ? "down"
+ : ( seg->dir == ah_dir_left
+ ? "left"
+ : ( seg->dir == ah_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 = outline->vert_segments;
+ limit = segments + outline->num_vsegments;
+ }
+ }
+
+#endif /* AH_DEBUG_GLYPH */
+
+
+ static
+ void ah_outline_compute_edges( AH_Outline* outline )
+ {
+ AH_Edge* edges;
+ AH_Segment* segments;
+ AH_Segment* segment_limit;
+ AH_Direction up_dir;
+ FT_Int* p_num_edges;
+ FT_Int dimension;
+ FT_Fixed scale;
+ FT_Pos edge_distance_threshold;
+
+
+ edges = outline->horz_edges;
+ segments = outline->horz_segments;
+ segment_limit = segments + outline->num_hsegments;
+ p_num_edges = &outline->num_hedges;
+ up_dir = ah_dir_right;
+ scale = outline->y_scale;
+
+ for ( dimension = 1; dimension >= 0; dimension-- )
+ {
+ AH_Edge* edge;
+ AH_Edge* edge_limit; /* really == edge + num_edges */
+ AH_Segment* seg;
+
+
+ /*********************************************************************/
+ /* */
+ /* We will begin by generating a sorted table of edges for the */
+ /* current direction. To do so, we simply scan each segment and try */
+ /* to find an edge in our table that corresponds to its position. */
+ /* */
+ /* If no edge is found, we create and insert a new edge in the */
+ /* sorted table. Otherwise, we simply add the segment to the edge's */
+ /* list which will be processed in the second step to compute the */
+ /* edge's properties. */
+ /* */
+ /* Note that the edges table is sorted along the segment/edge */
+ /* position. */
+ /* */
+ /*********************************************************************/
+
+ edge_distance_threshold = FT_MulFix( outline->edge_distance_threshold,
+ scale );
+ if ( edge_distance_threshold > 64 / 4 )
+ edge_distance_threshold = 64 / 4;
+
+ edge_limit = edges;
+ for ( seg = segments; seg < segment_limit; seg++ )
+ {
+ AH_Edge* found = 0;
+
+
+ /* look for an edge corresponding to the segment */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ FT_Pos dist;
+
+
+ dist = seg->pos - edge->fpos;
+ if ( dist < 0 )
+ dist = -dist;
+
+ dist = FT_MulFix( dist, scale );
+ if ( dist < edge_distance_threshold )
+ {
+ found = edge;
+ break;
+ }
+ }
+
+ if ( !found )
+ {
+ /* insert a new edge in the list and */
+ /* sort according to the position */
+ while ( edge > edges && edge[-1].fpos > seg->pos )
+ {
+ edge[0] = edge[-1];
+ edge--;
+ }
+ edge_limit++;
+
+ /* clear all edge fields */
+ memset( edge, 0, sizeof ( *edge ) );
+
+ /* add the segment to the new edge's list */
+ edge->first = seg;
+ edge->last = seg;
+ edge->fpos = seg->pos;
+ edge->opos = edge->pos = FT_MulFix( seg->pos, scale );
+ seg->edge_next = seg;
+ }
+ else
+ {
+ /* if an edge was found, simply add the segment to the edge's */
+ /* list */
+ seg->edge_next = edge->first;
+ edge->last->edge_next = seg;
+ edge->last = seg;
+ }
+ }
+
+ *p_num_edges = edge_limit - edges;
+
+
+ /*********************************************************************/
+ /* */
+ /* Good, we will now compute each edge's properties according to */
+ /* segments found on its position. Basically, these are: */
+ /* */
+ /* - edge's main direction */
+ /* - stem edge, serif edge or both (which defaults to stem then) */
+ /* - rounded edge, straigth or both (which defaults to straight) */
+ /* - link for edge */
+ /* */
+ /*********************************************************************/
+
+ /* first of all, set the `edge' field in each segment -- this is */
+ /* required in order to compute edge links */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ seg = edge->first;
+ if ( seg )
+ do
+ {
+ seg->edge = edge;
+ seg = seg->edge_next;
+ }
+ while ( seg != edge->first );
+ }
+
+ /* now, compute each edge properties */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ int is_round = 0; /* does it contain round segments? */
+ int is_straight = 0; /* does it contain straight segments? */
+ int ups = 0; /* number of upwards segments */
+ int downs = 0; /* number of downwards segments */
+
+
+ seg = edge->first;
+
+ do
+ {
+ FT_Bool is_serif;
+
+
+ /* check for roundness of segment */
+ if ( seg->flags & ah_edge_round )
+ is_round++;
+ else
+ is_straight++;
+
+ /* check for segment direction */
+ if ( seg->dir == up_dir )
+ ups += seg->max_coord-seg->min_coord;
+ else
+ downs += seg->max_coord-seg->min_coord;
+
+ /* check for links -- if seg->serif is set, then seg->link must */
+ /* be ignored */
+ is_serif = seg->serif && seg->serif->edge != edge;
+
+ if ( seg->link || is_serif )
+ {
+ AH_Edge* edge2;
+ AH_Segment* seg2;
+
+
+ edge2 = edge->link;
+ seg2 = seg->link;
+
+ if ( is_serif )
+ {
+ seg2 = seg->serif;
+ edge2 = edge->serif;
+ }
+
+ if ( edge2 )
+ {
+ FT_Pos edge_delta;
+ FT_Pos seg_delta;
+
+
+ edge_delta = edge->fpos - edge2->fpos;
+ if ( edge_delta < 0 )
+ edge_delta = -edge_delta;
+
+ seg_delta = seg->pos - seg2->pos;
+ if ( seg_delta < 0 )
+ seg_delta = -seg_delta;
+
+ if ( seg_delta < edge_delta )
+ edge2 = seg2->edge;
+ }
+ else
+ edge2 = seg2->edge;
+
+ if ( is_serif )
+ edge->serif = edge2;
+ else
+ edge->link = edge2;
+ }
+
+ seg = seg->edge_next;
+
+ } while ( seg != edge->first );
+
+ /* set the round/straight flags */
+ edge->flags = ah_edge_normal;
+
+ if ( is_straight == 0 && is_round )
+ edge->flags |= ah_edge_round;
+
+ /* set the edge's main direction */
+ edge->dir = ah_dir_none;
+
+ if ( ups > downs )
+ edge->dir = up_dir;
+
+ else if ( ups < downs )
+ edge->dir = - up_dir;
+
+ else if ( ups == downs )
+ edge->dir = 0; /* both up and down !! */
+
+ /* gets rid of serifs if link is set */
+ /* XXX: This gets rid of many unpleasant artefacts! */
+ /* Example: the `c' in cour.pfa at size 13 */
+
+ if ( edge->serif && edge->link )
+ edge->serif = 0;
+ }
+
+ edges = outline->vert_edges;
+ segments = outline->vert_segments;
+ segment_limit = segments + outline->num_vsegments;
+ p_num_edges = &outline->num_vedges;
+ up_dir = ah_dir_up;
+ scale = outline->x_scale;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ah_outline_detect_features */
+ /* */
+ /* <Description> */
+ /* Performs feature detection on a given AH_Outline object. */
+ /* */
+ LOCAL_FUNC
+ void ah_outline_detect_features( AH_Outline* outline )
+ {
+ ah_outline_compute_segments( outline );
+ ah_outline_link_segments ( outline );
+ ah_outline_compute_edges ( outline );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ah_outline_compute_blue_edges */
+ /* */
+ /* <Description> */
+ /* Computes the `blue edges' in a given outline (i.e. those that must */
+ /* be snapped to a blue zone edge (top or bottom). */
+ /* */
+ LOCAL_FUNC
+ void ah_outline_compute_blue_edges( AH_Outline* outline,
+ AH_Face_Globals* face_globals )
+ {
+ AH_Edge* edge = outline->horz_edges;
+ AH_Edge* limit = edge + outline->num_hedges;
+ AH_Globals* globals = &face_globals->design;
+ FT_Fixed y_scale = outline->y_scale;
+
+
+ /* compute for each horizontal edge, which blue zone is closer */
+ for ( ; edge < limit; edge++ )
+ {
+ AH_Blue blue;
+ FT_Pos* best_blue = 0;
+ FT_Pos best_dist; /* initial threshold */
+
+
+ /* compute the initial threshold as a fraction of the EM size */
+ best_dist = FT_MulFix( face_globals->face->units_per_EM / 40, y_scale );
+ if ( best_dist > 64 / 4 )
+ best_dist = 64 / 4;
+
+ for ( blue = ah_blue_capital_top; blue < ah_blue_max; blue++ )
+ {
+ /* if it is a top zone, check for right edges -- if it is a bottom */
+ /* zone, check for left edges */
+ /* */
+ /* of course, that's for TrueType XXX */
+ FT_Bool is_top_blue = AH_IS_TOP_BLUE( blue );
+ FT_Bool is_major_dir = edge->dir == outline->horz_major_dir;
+
+
+ /* if it is a top zone, the edge must be against the major */
+ /* direction; if it is a bottom zone, it must be in the major */
+ /* direction */
+ if ( is_top_blue ^ is_major_dir )
+ {
+ FT_Pos dist;
+ FT_Pos* blue_pos = globals->blue_refs + blue;
+
+
+ /* first of all, compare it to the reference position */
+ dist = edge->fpos - *blue_pos;
+ if ( dist < 0 )
+ dist = -dist;
+
+ dist = FT_MulFix( dist, y_scale );
+ if ( dist < best_dist )
+ {
+ best_dist = dist;
+ best_blue = blue_pos;
+ }
+
+ /* now, compare it to the overshoot position if the edge is */
+ /* rounded, and if the edge is over the reference position of a */
+ /* top zone, or under the reference position of a bottom zone */
+ if ( edge->flags & ah_edge_round && dist != 0 )
+ {
+ FT_Bool is_under_ref = edge->fpos < *blue_pos;
+
+
+ if ( is_top_blue ^ is_under_ref )
+ {
+ blue_pos = globals->blue_shoots + blue;
+ dist = edge->fpos - *blue_pos;
+ if ( dist < 0 )
+ dist = -dist;
+
+ dist = FT_MulFix( dist, y_scale );
+ if ( dist < best_dist )
+ {
+ best_dist = dist;
+ best_blue = blue_pos;
+ }
+ }
+ }
+ }
+ }
+
+ if ( best_blue )
+ edge->blue_edge = best_blue;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ah_outline_scale_blue_edges */
+ /* */
+ /* <Description> */
+ /* This functions must be called before hinting in order to re-adjust */
+ /* the contents of the detected edges (basically change the `blue */
+ /* edge' pointer from `design units' to `scaled ones'). */
+ /* */
+ LOCAL_FUNC
+ void ah_outline_scale_blue_edges( AH_Outline* outline,
+ AH_Face_Globals* globals )
+ {
+ AH_Edge* edge = outline->horz_edges;
+ AH_Edge* limit = edge + outline->num_hedges;
+ FT_Int delta;
+
+
+ delta = globals->scaled.blue_refs - globals->design.blue_refs;
+
+ for ( ; edge < limit; edge++ )
+ {
+ if ( edge->blue_edge )
+ edge->blue_edge += delta;
+ }
+ }
+
+
+#ifdef AH_DEBUG_GLYPH
+
+ void ah_dump_edges( AH_Outline* outline )
+ {
+ AH_Edge* edges;
+ AH_Edge* limit;
+ AH_Segment* segments;
+ FT_Int dimension;
+
+
+ edges = outline->horz_edges;
+ limit = edges + outline->num_hedges;
+ segments = outline->horz_segments;
+
+ for ( dimension = 1; dimension >= 0; dimension-- )
+ {
+ AH_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 < limit; edge++ )
+ {
+ printf ( " [ %5d | %4d | %5s | %4d | %5d | %c | %5.2f | %5.2f ]\n",
+ edge - edges,
+ (int)edge->fpos,
+ edge->dir == ah_dir_up
+ ? "up"
+ : ( edge->dir == ah_dir_down
+ ? "down"
+ : ( edge->dir == ah_dir_left
+ ? "left"
+ : ( edge->dir == ah_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 = outline->vert_edges;
+ limit = edges + outline->num_vedges;
+ segments = outline->vert_segments;
+ }
+ }
+
+#endif /* AH_DEBUG_GLYPH */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ahglyph.h */
+/* */
+/* Routines used to load and analyze a given glyph before hinting */
+/* (specification). */
+/* */
+/* Copyright 2000 Catharon Productions Inc. */
+/* Author: David Turner */
+/* */
+/* This file is part of the Catharon Typography Project and shall only */
+/* be used, modified, and distributed under the terms of the Catharon */
+/* Open Source License that should come with this file under the name */
+/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* Note that this license is compatible with the FreeType license. */
+/* */
+/***************************************************************************/
+
+
+#ifndef AHGLYPH_H
+#define AHGLYPH_H
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahtypes.h"
+
+#else
+
+#include <autohint/ahtypes.h>
+
+#endif
+
+
+ typedef enum AH_UV_
+ {
+ ah_uv_fxy,
+ ah_uv_fyx,
+ ah_uv_oxy,
+ ah_uv_oyx,
+ ah_uv_ox,
+ ah_uv_oy,
+ ah_uv_yx,
+ ah_uv_xy /* should always be last! */
+
+ } AH_UV;
+
+
+ LOCAL_DEF
+ void ah_setup_uv( AH_Outline* outline,
+ AH_UV source );
+
+
+ /* AH_Outline functions - they should be typically called in this order */
+
+ LOCAL_DEF
+ FT_Error ah_outline_new( FT_Memory memory,
+ AH_Outline** aoutline );
+
+ LOCAL_DEF
+ FT_Error ah_outline_load( AH_Outline* outline,
+ FT_Face face );
+
+ LOCAL_DEF
+ void ah_outline_compute_segments( AH_Outline* outline );
+
+ LOCAL_DEF
+ void ah_outline_link_segments( AH_Outline* outline );
+
+ LOCAL_DEF
+ void ah_outline_detect_features( AH_Outline* outline );
+
+ LOCAL_DEF
+ void ah_outline_compute_blue_edges( AH_Outline* outline,
+ AH_Face_Globals* globals );
+
+ LOCAL_DEF
+ void ah_outline_scale_blue_edges( AH_Outline* outline,
+ AH_Face_Globals* globals );
+
+ LOCAL_DEF
+ void ah_outline_save( AH_Outline* outline, AH_Loader* loader );
+
+ LOCAL_DEF
+ void ah_outline_done( AH_Outline* outline );
+
+
+#endif /* AHGLYPH_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ahhint.c */
+/* */
+/* Glyph hinter (body). */
+/* */
+/* Copyright 2000 Catharon Productions Inc. */
+/* Author: David Turner */
+/* */
+/* This file is part of the Catharon Typography Project and shall only */
+/* be used, modified, and distributed under the terms of the Catharon */
+/* Open Source License that should come with this file under the name */
+/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* Note that this license is compatible with the FreeType license. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahhint.h"
+#include "ahglyph.h"
+#include "ahangles.h"
+
+#else
+
+#include <autohint/ahhint.h>
+#include <autohint/ahglyph.h>
+#include <autohint/ahangles.h>
+
+#endif
+
+#include <freetype/ftoutln.h>
+
+
+#define FACE_GLOBALS( face ) ((AH_Face_Globals*)(face)->autohint.data)
+
+#define AH_USE_IUP
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** Hinting routines ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static int disable_horz_edges = 0;
+ static int disable_vert_edges = 0;
+
+
+ /* snap a given width in scaled coordinates to one of the */
+ /* current standard widths */
+ static
+ FT_Pos ah_snap_width( FT_Pos* widths,
+ FT_Int count,
+ FT_Pos width )
+ {
+ int n;
+ FT_Pos best = 64 + 32 + 2;
+ FT_Pos reference = width;
+
+
+ for ( n = 0; n < count; n++ )
+ {
+ FT_Pos w;
+ FT_Pos dist;
+
+
+ w = widths[n];
+ dist = width - w;
+ if ( dist < 0 )
+ dist = -dist;
+ if ( dist < best )
+ {
+ best = dist;
+ reference = w;
+ }
+ }
+
+ if ( width >= reference )
+ {
+ width -= 0x21;
+ if ( width < reference )
+ width = reference;
+ }
+ else
+ {
+ width += 0x21;
+ if ( width > reference )
+ width = reference;
+ }
+
+ return width;
+ }
+
+
+ /* align one stem edge relative to the previous stem edge */
+ static
+ void ah_align_linked_edge( AH_Hinter* hinter,
+ AH_Edge* base_edge,
+ AH_Edge* stem_edge,
+ int vertical )
+ {
+ FT_Pos dist = stem_edge->opos - base_edge->opos;
+ AH_Globals* globals = &hinter->globals->scaled;
+ FT_Pos sign = 1;
+
+
+ if ( dist < 0 )
+ {
+ dist = -dist;
+ sign = -1;
+ }
+
+ if ( vertical )
+ {
+ dist = ah_snap_width( globals->heights, globals->num_heights, dist );
+
+ /* in the case of vertical hinting, always round */
+ /* the stem heights to integer pixels */
+ if ( dist >= 64 )
+ dist = ( dist + 16 ) & -64;
+ else
+ dist = 64;
+ }
+ else
+ {
+ dist = ah_snap_width( globals->widths, globals->num_widths, dist );
+
+ if ( hinter->flags & ah_hinter_monochrome )
+ {
+ /* monochrome horizontal hinting: snap widths to integer pixels */
+ /* with a different threshold */
+ if ( dist < 64 )
+ dist = 64;
+ else
+ dist = ( dist + 32 ) & -64;
+ }
+ else
+ {
+ /* for horizontal anti-aliased hinting, we adopt a more subtle */
+ /* approach: we strengthen small stems, round stems whose size */
+ /* is between 1 and 2 pixels to an integer, otherwise nothing */
+ if ( dist < 48 )
+ dist = ( dist + 64 ) >> 1;
+
+ else if ( dist < 128 )
+ dist = ( dist + 42 ) & -64;
+ }
+ }
+
+ stem_edge->pos = base_edge->pos + sign * dist;
+ }
+
+
+ static
+ void ah_align_serif_edge( AH_Hinter* hinter,
+ AH_Edge* base,
+ AH_Edge* serif )
+ {
+ FT_Pos dist;
+ FT_Pos sign = 1;
+
+ UNUSED( hinter );
+
+
+ dist = serif->opos - base->opos;
+ if ( dist < 0 )
+ {
+ dist = -dist;
+ sign = -1;
+ }
+
+ /* do not strengthen serifs */
+ if ( base->flags & ah_edge_done )
+ {
+ if ( dist > 64 )
+ dist = ( dist + 16 ) & -64;
+
+ else if ( dist <= 32 )
+ dist = ( dist + 33 ) >> 1;
+ }
+
+ serif->pos = base->pos + sign * dist;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** E D G E H I N T I N G ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* Another alternative edge hinting algorithm */
+ static
+ void ah_hint_edges_3( AH_Hinter* hinter )
+ {
+ AH_Edge* edges;
+ AH_Edge* edge_limit;
+ AH_Outline* outline = hinter->glyph;
+ FT_Int dimension;
+
+
+ edges = outline->horz_edges;
+ edge_limit = edges + outline->num_hedges;
+
+ for ( dimension = 1; dimension >= 0; dimension-- )
+ {
+ AH_Edge* edge;
+ AH_Edge* before = 0;
+ AH_Edge* after = 0;
+ AH_Edge* anchor = 0;
+ int has_serifs = 0;
+
+
+ if ( disable_vert_edges && !dimension )
+ goto Next_Dimension;
+
+ if ( disable_horz_edges && dimension )
+ goto Next_Dimension;
+
+ /* we begin by aligning all stems relative to the blue zone */
+ /* if needed -- that's only for horizontal edges */
+ if ( dimension )
+ {
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ FT_Pos* blue;
+ AH_Edge *edge1, *edge2;
+
+
+ if ( edge->flags & ah_edge_done )
+ continue;
+
+ blue = edge->blue_edge;
+ edge1 = 0;
+ edge2 = edge->link;
+
+ if ( blue )
+ {
+ edge1 = edge;
+ }
+ else if (edge2 && edge2->blue_edge)
+ {
+ blue = edge2->blue_edge;
+ edge1 = edge2;
+ edge2 = edge;
+ }
+
+ if ( !edge1 )
+ continue;
+
+ edge1->pos = blue[0];
+ edge1->flags |= ah_edge_done;
+
+ if ( edge2 && !edge2->blue_edge )
+ {
+ ah_align_linked_edge( hinter, edge1, edge2, dimension );
+ edge2->flags |= ah_edge_done;
+ }
+
+ if ( !anchor )
+ anchor = edge;
+ }
+ }
+
+ /* now, we will align all stem edges, trying to maintain the */
+ /* relative order of stems in the glyph.. */
+ before = 0;
+ after = 0;
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ AH_Edge *edge2;
+
+
+ if ( edge->flags & ah_edge_done )
+ continue;
+
+ /* skip all non-stem edges */
+ edge2 = edge->link;
+ if ( !edge2 )
+ {
+ has_serifs++;
+ continue;
+ }
+
+ /* now, align the stem */
+
+ /* this should not happen, but it's better to be safe.. */
+ if ( edge2->blue_edge || edge2 < edge )
+ {
+
+#if 0
+ printf( "strange blue alignement, edge %d to %d\n",
+ edge - edges, edge2 - edges );
+#endif
+
+ ah_align_linked_edge( hinter, edge2, edge, dimension );
+ edge->flags |= ah_edge_done;
+ continue;
+ }
+
+ {
+ FT_Bool min = 0;
+ FT_Pos delta;
+
+ if ( !anchor )
+ {
+ edge->pos = ( edge->opos + 32 ) & -64;
+ anchor = edge;
+ }
+ else
+ edge->pos = anchor->pos +
+ ( ( edge->opos - anchor->opos + 32 ) & -64 );
+
+ edge->flags |= ah_edge_done;
+
+ if ( edge > edges && edge->pos < edge[-1].pos )
+ {
+ edge->pos = edge[-1].pos;
+ min = 1;
+ }
+
+ ah_align_linked_edge( hinter, edge, edge2, dimension );
+ delta = 0;
+ if ( edge2 + 1 < edge_limit &&
+ edge2[1].flags & ah_edge_done )
+ delta = edge2[1].pos - edge2->pos;
+
+ if ( delta < 0 )
+ {
+ edge2->pos += delta;
+ if ( !min )
+ edge->pos += delta;
+ }
+ edge2->flags |= ah_edge_done;
+ }
+ }
+
+ if ( !has_serifs )
+ goto Next_Dimension;
+
+ /* now, hint the remaining edges (serifs and single) in order */
+ /* to complete our processing */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ if ( edge->flags & ah_edge_done )
+ continue;
+
+ if ( edge->serif )
+ {
+ ah_align_serif_edge( hinter, edge->serif, edge );
+ }
+ else if ( !anchor )
+ {
+ edge->pos = ( edge->opos + 32 ) & -64;
+ anchor = edge;
+ }
+ else
+ edge->pos = anchor->pos +
+ ( ( edge->opos-anchor->opos + 32 ) & -64 );
+
+ edge->flags |= ah_edge_done;
+
+ if ( edge > edges && edge->pos < edge[-1].pos )
+ edge->pos = edge[-1].pos;
+
+ if ( edge + 1 < edge_limit &&
+ edge[1].flags & ah_edge_done &&
+ edge->pos > edge[1].pos )
+ edge->pos = edge[1].pos;
+ }
+
+ Next_Dimension:
+ edges = outline->vert_edges;
+ edge_limit = edges + outline->num_vedges;
+ }
+ }
+
+
+ LOCAL_FUNC
+ void ah_hinter_hint_edges( AH_Hinter* hinter,
+ int no_horz_edges,
+ int no_vert_edges )
+ {
+ disable_horz_edges = no_horz_edges;
+ disable_vert_edges = no_vert_edges;
+
+ /* AH_Interpolate_Blue_Edges( hinter ); -- doesn't seem to help */
+ /* reduce the problem of the disappearing eye in the `e' of Times... */
+ /* also, creates some artifacts near the blue zones? */
+ {
+ ah_hint_edges_3( hinter );
+
+#if 0
+ /* outline optimizer removed temporarily */
+ if ( hinter->flags & ah_hinter_optimize )
+ {
+ AH_Optimizer opt;
+
+
+ if ( !AH_Optimizer_Init( &opt, hinter->glyph, hinter->memory ) )
+ {
+ AH_Optimizer_Compute( &opt );
+ AH_Optimizer_Done( &opt );
+ }
+ }
+#endif
+
+ }
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** P O I N T H I N T I N G ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static
+ void ah_hinter_align_edge_points( AH_Hinter* hinter )
+ {
+ AH_Outline* outline = hinter->glyph;
+ AH_Edge* edges;
+ AH_Edge* edge_limit;
+ FT_Int dimension;
+
+
+ edges = outline->horz_edges;
+ edge_limit = edges + outline->num_hedges;
+
+ for ( dimension = 1; dimension >= 0; dimension-- )
+ {
+ AH_Edge* edge;
+ AH_Edge* before;
+ AH_Edge* after;
+
+
+ before = 0;
+ after = 0;
+
+ edge = edges;
+ for ( ; edge < edge_limit; edge++ )
+ {
+ /* move the points of each segment */
+ /* in each edge to the edge's position */
+ AH_Segment* seg = edge->first;
+
+
+ do
+ {
+ AH_Point* point = seg->first;
+
+
+ for (;;)
+ {
+ if ( dimension )
+ {
+ point->y = edge->pos;
+ point->flags |= ah_flah_touch_y;
+ }
+ else
+ {
+ point->x = edge->pos;
+ point->flags |= ah_flah_touch_x;
+ }
+
+ if ( point == seg->last )
+ break;
+
+ point = point->next;
+ }
+
+ seg = seg->edge_next;
+
+ } while ( seg != edge->first );
+ }
+
+ edges = outline->vert_edges;
+ edge_limit = edges + outline->num_vedges;
+ }
+ }
+
+
+ /* hint the strong points -- this is equivalent to the TrueType `IP' */
+ static
+ void ah_hinter_align_strong_points( AH_Hinter* hinter )
+ {
+ AH_Outline* outline = hinter->glyph;
+ FT_Int dimension;
+ AH_Edge* edges;
+ AH_Edge* edge_limit;
+ AH_Point* points;
+ AH_Point* point_limit;
+ AH_Flags touch_flag;
+
+
+ points = outline->points;
+ point_limit = points + outline->num_points;
+
+ edges = outline->horz_edges;
+ edge_limit = edges + outline->num_hedges;
+ touch_flag = ah_flah_touch_y;
+
+ for ( dimension = 1; dimension >= 0; dimension-- )
+ {
+ AH_Point* point;
+ AH_Edge* edge;
+ AH_Edge* before;
+ AH_Edge* after;
+
+
+ before = 0;
+ after = 0;
+
+ if ( edges < edge_limit )
+ for ( point = points; point < point_limit; point++ )
+ {
+ FT_Pos u, ou, fu; /* point position */
+ FT_Pos delta;
+
+
+ if ( point->flags & touch_flag )
+ continue;
+
+#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
+ /* if this point is candidate to weak interpolation, we will */
+ /* interpolate it after all strong points have been processed */
+ if ( point->flags & ah_flah_weak_interpolation )
+ continue;
+#endif
+
+ if ( dimension )
+ {
+ 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;
+ }
+
+ /* otherwise, interpolate the point in between */
+ {
+ AH_Edge* before = 0;
+ AH_Edge* after = 0;
+
+
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ if ( u == edge->fpos )
+ {
+ u = edge->pos;
+ goto Store_Point;
+ }
+ if ( u < edge->fpos )
+ break;
+ before = edge;
+ }
+
+ for ( edge = edge_limit - 1; edge >= edges; edge-- )
+ {
+ if ( u == edge->fpos )
+ {
+ u = edge->pos;
+ goto Store_Point;
+ }
+ if ( u > edge->fpos )
+ break;
+ after = edge;
+ }
+
+ /* assert( before && after && before != after ) */
+ u = before->pos + FT_MulDiv( fu - before->fpos,
+ after->pos - before->pos,
+ after->fpos - before->fpos );
+ }
+
+ Store_Point:
+
+ /* save the point position */
+ if ( dimension )
+ point->y = u;
+ else
+ point->x = u;
+
+ point->flags |= touch_flag;
+ }
+
+ edges = outline->vert_edges;
+ edge_limit = edges + outline->num_vedges;
+ touch_flag = ah_flah_touch_x;
+ }
+ }
+
+
+#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
+
+ static
+ void ah_iup_shift( AH_Point* p1,
+ AH_Point* p2,
+ AH_Point* ref )
+ {
+ AH_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 ah_iup_interp( AH_Point* p1,
+ AH_Point* p2,
+ AH_Point* ref1,
+ AH_Point* ref2 )
+ {
+ AH_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++ )
+ {
+ FT_Pos 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;
+ }
+ }
+ }
+
+
+ /* interpolate weak points -- this is equivalent to the TrueType `IUP' */
+ static
+ void ah_hinter_align_weak_points( AH_Hinter* hinter )
+ {
+ AH_Outline* outline = hinter->glyph;
+ FT_Int dimension;
+ AH_Edge* edges;
+ AH_Edge* edge_limit;
+ AH_Point* points;
+ AH_Point* point_limit;
+ AH_Point** contour_limit;
+ AH_Flags touch_flag;
+
+
+ points = outline->points;
+ point_limit = points + outline->num_points;
+
+ /* PASS 1: Move segment points to edge positions */
+
+ edges = outline->horz_edges;
+ edge_limit = edges + outline->num_hedges;
+ touch_flag = ah_flah_touch_y;
+
+ contour_limit = outline->contours + outline->num_contours;
+
+ ah_setup_uv( outline, ah_uv_oy );
+
+ for ( dimension = 1; dimension >= 0; dimension-- )
+ {
+ AH_Point* point;
+ AH_Point* end_point;
+ AH_Point* first_point;
+ AH_Point** contour;
+
+
+ point = points;
+ contour = outline->contours;
+
+ 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 )
+ {
+ AH_Point* first_touched = point;
+ AH_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 */
+ ah_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 */
+ ah_iup_shift( first_point, end_point, cur_touched );
+ }
+ else
+ {
+ /* now interpolate after the last touched point to the end */
+ /* of the contour */
+ ah_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 )
+ ah_iup_interp( first_point, first_touched - 1,
+ cur_touched, first_touched );
+ }
+ }
+ }
+
+ /* now save the interpolated values back to x/y */
+ if ( dimension )
+ {
+ for ( point = points; point < point_limit; point++ )
+ point->y = point->u;
+
+ touch_flag = ah_flah_touch_x;
+ ah_setup_uv( outline, ah_uv_ox );
+ }
+ else
+ {
+ for ( point = points; point < point_limit; point++ )
+ point->x = point->u;
+
+ break; /* exit loop */
+ }
+ }
+ }
+
+#endif /* !AH_OPTION_NO_WEAK_INTERPOLATION */
+
+
+ LOCAL_FUNC
+ void ah_hinter_align_points( AH_Hinter* hinter )
+ {
+ ah_hinter_align_edge_points( hinter );
+
+#ifndef AH_OPTION_NO_STRONG_INTERPOLATION
+ ah_hinter_align_strong_points( hinter );
+#endif
+
+#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
+ ah_hinter_align_weak_points( hinter );
+#endif
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** H I N T E R O B J E C T M E T H O D S ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* scale and fit the global metrics */
+ static
+ void ah_hinter_scale_globals( AH_Hinter* hinter,
+ FT_Fixed x_scale,
+ FT_Fixed y_scale )
+ {
+ FT_Int n;
+ AH_Face_Globals* globals = hinter->globals;
+ AH_Globals* design = &globals->design;
+ AH_Globals* scaled = &globals->scaled;
+
+
+ /* copy content */
+ *scaled = *design;
+
+ /* scale the standard widths & heights */
+ for ( n = 0; n < design->num_widths; n++ )
+ scaled->widths[n] = FT_MulFix( design->widths[n], x_scale );
+
+ for ( n = 0; n < design->num_heights; n++ )
+ scaled->heights[n] = FT_MulFix( design->heights[n], y_scale );
+
+ /* scale the blue zones */
+ for ( n = 0; n < ah_blue_max; n++ )
+ {
+ FT_Pos delta, delta2;
+
+
+ delta = design->blue_shoots[n] - design->blue_refs[n];
+ delta2 = delta;
+ if ( delta < 0 )
+ delta2 = -delta2;
+ delta2 = FT_MulFix( delta2, y_scale );
+
+ if ( delta2 < 32 )
+ delta2 = 0;
+ else if ( delta2 < 64 )
+ delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & -32 );
+ else
+ delta2 = ( delta2 + 32 ) & -64;
+
+ if ( delta < 0 )
+ delta2 = -delta2;
+
+ scaled->blue_refs[n] =
+ ( FT_MulFix( design->blue_refs[n], y_scale ) + 32 ) & -64;
+ scaled->blue_shoots[n] = scaled->blue_refs[n] + delta2;
+ }
+
+ globals->x_scale = x_scale;
+ globals->y_scale = y_scale;
+ }
+
+
+ static
+ void ah_hinter_align( AH_Hinter* hinter )
+ {
+ ah_hinter_align_edge_points( hinter );
+ ah_hinter_align_points( hinter );
+ }
+
+
+ /* finalize a hinter object */
+ void ah_hinter_done( AH_Hinter* hinter )
+ {
+ if ( hinter )
+ {
+ FT_Memory memory = hinter->memory;
+
+
+ ah_loader_done( hinter->loader );
+ ah_outline_done( hinter->glyph );
+
+ /* note: the `globals' pointer is _not_ owned by the hinter */
+ /* but by the current face object, we don't need to */
+ /* release it */
+ hinter->globals = 0;
+ hinter->face = 0;
+
+ FREE( hinter );
+ }
+ }
+
+
+ /* create a new empty hinter object */
+ FT_Error ah_hinter_new( FT_Library library,
+ AH_Hinter** ahinter )
+ {
+ AH_Hinter* hinter = 0;
+ FT_Memory memory = library->memory;
+ FT_Error error;
+
+
+ *ahinter = 0;
+
+ /* allocate object */
+ if ( ALLOC( hinter, sizeof ( *hinter ) ) )
+ goto Exit;
+
+ hinter->memory = memory;
+ hinter->flags = 0;
+
+ /* allocate outline and loader */
+ error = ah_outline_new( memory, &hinter->glyph ) ||
+ ah_loader_new ( memory, &hinter->loader ) ||
+ ah_loader_create_extra( hinter->loader );
+ if ( error )
+ goto Exit;
+
+ *ahinter = hinter;
+
+ Exit:
+ if ( error )
+ ah_hinter_done( hinter );
+
+ return error;
+ }
+
+
+ /* create a face's autohint globals */
+ FT_Error ah_hinter_new_face_globals( AH_Hinter* hinter,
+ FT_Face face,
+ AH_Globals* globals )
+ {
+ FT_Error error;
+ FT_Memory memory = hinter->memory;
+ AH_Face_Globals* face_globals;
+
+
+ if ( ALLOC( face_globals, sizeof ( *face_globals ) ) )
+ goto Exit;
+
+ hinter->face = face;
+ hinter->globals = face_globals;
+
+ if ( globals )
+ face_globals->design = *globals;
+ else
+ ah_hinter_compute_globals( hinter );
+
+ face->autohint.data = face_globals;
+ face->autohint.finalizer = (FT_Generic_Finalizer)
+ ah_hinter_done_face_globals;
+ face_globals->face = face;
+
+ Exit:
+ return error;
+ }
+
+
+ /* discard a face's autohint globals */
+ void ah_hinter_done_face_globals( AH_Face_Globals* globals )
+ {
+ FT_Face face = globals->face;
+ FT_Memory memory = face->memory;
+
+
+ FREE( globals );
+ }
+
+
+ static
+ FT_Error ah_hinter_load( AH_Hinter* hinter,
+ FT_UInt glyph_index,
+ FT_UInt load_flags,
+ FT_UInt depth )
+ {
+ FT_Face face = hinter->face;
+ FT_GlyphSlot slot = face->glyph;
+ FT_Fixed x_scale = face->size->metrics.x_scale;
+ FT_Fixed y_scale = face->size->metrics.y_scale;
+ FT_Glyph_Metrics metrics; /* temporary metrics */
+ FT_Error error;
+ AH_Outline* outline = hinter->glyph;
+ AH_Loader* gloader = hinter->loader;
+ FT_Bool no_horz_hints =
+ ( load_flags & AH_HINT_NO_HORZ_EDGES ) != 0;
+ FT_Bool no_vert_hints =
+ ( load_flags & AH_HINT_NO_VERT_EDGES ) != 0;
+
+
+ /* load the glyph */
+ error = FT_Load_Glyph( face, glyph_index, load_flags );
+ if ( error )
+ goto Exit;
+
+ /* save current glyph metrics */
+ metrics = slot->metrics;
+
+ switch ( slot->format )
+ {
+ case ft_glyph_format_outline:
+ /* first of all, copy the outline points in the loader's current */
+ /* extra points, which is used to keep original glyph coordinates */
+ error = ah_loader_check_points( gloader, slot->outline.n_points + 2,
+ slot->outline.n_contours );
+ if ( error )
+ goto Exit;
+
+ MEM_Copy( gloader->current.extra_points, slot->outline.points,
+ slot->outline.n_points * sizeof ( FT_Vector ) );
+
+ MEM_Copy( gloader->current.outline.contours, slot->outline.contours,
+ slot->outline.n_contours * sizeof ( short ) );
+
+ MEM_Copy( gloader->current.outline.tags, slot->outline.tags,
+ slot->outline.n_points * sizeof ( char ) );
+
+ gloader->current.outline.n_points = slot->outline.n_points;
+ gloader->current.outline.n_contours = slot->outline.n_contours;
+
+ /* compute original phantom points */
+ hinter->pp1.x = 0;
+ hinter->pp1.y = 0;
+ hinter->pp2.x = FT_MulFix( slot->metrics.horiAdvance, x_scale );
+ hinter->pp2.y = 0;
+
+ /* 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 = ah_outline_load( outline, face ); /* XXX: change to slot */
+ if ( error )
+ goto Exit;
+
+ /* perform feature detection */
+ ah_outline_detect_features( outline );
+
+ if ( !no_horz_hints )
+ {
+ ah_outline_compute_blue_edges( outline, hinter->globals );
+ ah_outline_scale_blue_edges( outline, hinter->globals );
+ }
+
+ /* perform alignment control */
+ ah_hinter_hint_edges( hinter, no_horz_hints, no_vert_hints );
+ ah_hinter_align( hinter );
+
+ /* now save the current outline into the loader's current table */
+ ah_outline_save( outline, gloader );
+
+ /* we now need to hint the metrics according to the change in */
+ /* width/positioning that occured during the hinting process */
+ {
+ FT_Pos old_width, new_width;
+ FT_Pos old_advance, new_advance;
+ FT_Pos old_lsb, new_lsb;
+ AH_Edge* edge1 = outline->vert_edges; /* leftmost edge */
+ AH_Edge* edge2 = edge1 +
+ outline->num_vedges - 1; /* rightmost edge */
+
+
+ old_width = edge2->opos - edge1->opos;
+ new_width = edge2->pos - edge1->pos;
+
+ old_advance = hinter->pp2.x;
+ old_lsb = edge1->opos;
+ new_lsb = edge1->pos;
+
+ new_advance = old_advance +
+ ( new_width + new_lsb - old_width - old_lsb );
+
+ hinter->pp1.x = ( ( new_lsb - old_lsb ) + 32 ) & -64;
+ hinter->pp2.x = ( ( edge2->pos +
+ ( old_advance - edge2->opos ) ) + 32 ) & -64;
+ }
+
+ /* good, we simply add the glyph to our loader's base */
+ ah_loader_add( gloader );
+ break;
+
+ case ft_glyph_format_composite:
+ {
+ FT_UInt nn, num_subglyphs = slot->num_subglyphs;
+ FT_UInt num_base_subgs, start_point, start_contour;
+ FT_SubGlyph* subglyph;
+
+
+ start_point = gloader->base.outline.n_points;
+ start_contour = gloader->base.outline.n_contours;
+
+ /* first of all, copy the subglyph descriptors in the glyph loader */
+ error = ah_loader_check_subglyphs( gloader, num_subglyphs );
+ if ( error )
+ goto Exit;
+
+ MEM_Copy( gloader->current.subglyphs, slot->subglyphs,
+ num_subglyphs * sizeof ( FT_SubGlyph ) );
+
+ 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 = hinter->pp1;
+ pp2 = hinter->pp2;
+
+ num_base_points = gloader->base.outline.n_points;
+
+ error = ah_hinter_load( hinter, 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 = hinter->pp1;
+ pp2 = hinter->pp2;
+ }
+ else
+ {
+ hinter->pp1 = pp1;
+ hinter->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, x_scale );
+ y = FT_MulFix( subglyph->arg2, y_scale );
+
+ x = ( x + 32 ) & -64;
+ y = ( y + 32 ) & -64;
+ }
+
+ {
+ FT_Outline dummy = gloader->base.outline;
+
+
+ dummy.points += num_base_points;
+ dummy.n_points = 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;
+
+
+ /* we must translate our final outline by -pp1.x, and compute */
+ /* the new metrics */
+ if ( hinter->pp1.x )
+ FT_Outline_Translate( &gloader->base.outline, -hinter->pp1.x, 0 );
+
+ FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
+ bbox.xMin &= -64;
+ bbox.yMin &= -64;
+ bbox.xMax = ( bbox.xMax + 63 ) & -64;
+ bbox.yMax = ( bbox.yMax + 63 ) & -64;
+
+ slot->metrics.width = bbox.xMax - bbox.xMin;
+ slot->metrics.height = bbox.yMax - bbox.yMin;
+ slot->metrics.horiBearingX = bbox.xMin;
+ slot->metrics.horiBearingY = bbox.yMax;
+ slot->metrics.horiAdvance = hinter->pp2.x - hinter->pp1.x;
+ /* XXX: TO DO - slot->linearHoriAdvance */
+
+ /* now copy outline into glyph slot */
+ ah_loader_rewind( slot->loader );
+ error = ah_loader_copy_points( slot->loader, gloader );
+ if ( error )
+ goto Exit;
+
+ slot->outline = slot->loader->base.outline;
+ slot->format = ft_glyph_format_outline;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /* load and hint a given glyph */
+ FT_Error ah_hinter_load_glyph( AH_Hinter* hinter,
+ FT_GlyphSlot slot,
+ FT_Size size,
+ FT_UInt glyph_index,
+ FT_Int load_flags )
+ {
+ FT_Face face = slot->face;
+ FT_Error error;
+ FT_Fixed x_scale = size->metrics.x_scale;
+ FT_Fixed y_scale = size->metrics.y_scale;
+ AH_Face_Globals* face_globals = FACE_GLOBALS( face );
+
+
+ /* first of all, we need to check that we're using the correct face and */
+ /* global hints to load the glyph */
+ if ( hinter->face != face || hinter->globals != face_globals )
+ {
+ hinter->face = face;
+ if ( !face_globals )
+ {
+ error = ah_hinter_new_face_globals( hinter, face, 0 );
+ if ( error )
+ goto Exit;
+ }
+ hinter->globals = FACE_GLOBALS( face );
+ face_globals = FACE_GLOBALS( face );
+ }
+
+ /* now, we must check the current character pixel size to see if we */
+ /* need to rescale the global metrics */
+ if ( face_globals->x_scale != x_scale ||
+ face_globals->y_scale != y_scale )
+ ah_hinter_scale_globals( hinter, x_scale, y_scale );
+
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_RECURSE;
+
+ ah_loader_rewind( hinter->loader );
+
+ error = ah_hinter_load( hinter, glyph_index, load_flags, 0 );
+
+ Exit:
+ return error;
+ }
+
+
+ /* retrieve a face's autohint globals for client applications */
+ void ah_hinter_get_global_hints( AH_Hinter* hinter,
+ FT_Face face,
+ void** global_hints,
+ long* global_len )
+ {
+ AH_Globals* globals = 0;
+ FT_Memory memory = hinter->memory;
+ FT_Error error;
+
+
+ /* allocate new master globals */
+ if ( ALLOC( globals, sizeof ( *globals ) ) )
+ goto Fail;
+
+ /* compute face globals if needed */
+ if ( !FACE_GLOBALS( face ) )
+ {
+ error = ah_hinter_new_face_globals( hinter, face, 0 );
+ if ( error )
+ goto Fail;
+ }
+
+ *globals = FACE_GLOBALS( face )->design;
+ *global_hints = globals;
+ *global_len = sizeof( *globals );
+
+ return;
+
+ Fail:
+ FREE( globals );
+
+ *global_hints = 0;
+ *global_len = 0;
+ }
+
+
+ void ah_hinter_done_global_hints( AH_Hinter* hinter,
+ void* global_hints )
+ {
+ FT_Memory memory = hinter->memory;
+
+
+ FREE( global_hints );
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ahhint.h */
+/* */
+/* Glyph hinter (declaration). */
+/* */
+/* Copyright 2000 Catharon Productions Inc. */
+/* Author: David Turner */
+/* */
+/* This file is part of the Catharon Typography Project and shall only */
+/* be used, modified, and distributed under the terms of the Catharon */
+/* Open Source License that should come with this file under the name */
+/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* Note that this license is compatible with the FreeType license. */
+/* */
+/***************************************************************************/
+
+
+#ifndef AHHINT_H
+#define AHHINT_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahglobal.h"
+
+#else
+
+#include <autohint/ahglobal.h>
+
+#endif
+
+
+#define AH_HINT_DEFAULT 0
+#define AH_HINT_NO_ALIGNMENT 1
+#define AH_HINT_NO_HORZ_EDGES 0x20000L
+#define AH_HINT_NO_VERT_EDGES 0x40000L
+
+
+ /* create a new empty hinter object */
+ FT_Error ah_hinter_new( FT_Library library,
+ AH_Hinter** ahinter );
+
+ /* Load a hinted glyph in the hinter */
+ FT_Error ah_hinter_load_glyph( AH_Hinter* hinter,
+ FT_GlyphSlot slot,
+ FT_Size size,
+ FT_UInt glyph_index,
+ FT_Int load_flags );
+
+ /* finalize a hinter object */
+ void ah_hinter_done( AH_Hinter* hinter );
+
+ LOCAL_DEF
+ void ah_hinter_done_face_globals( AH_Face_Globals* globals );
+
+ void ah_hinter_get_global_hints( AH_Hinter* hinter,
+ FT_Face face,
+ void** global_hints,
+ long* global_len );
+
+ void ah_hinter_done_global_hints( AH_Hinter* hinter,
+ void* global_hints );
+
+
+#endif /* AHHINT_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ahloader.h */
+/* */
+/* Glyph loader for the auto-hinting module (declaration only). */
+/* */
+/* Copyright 2000 Catharon Productions Inc. */
+/* Author: David Turner */
+/* */
+/* This file is part of the Catharon Typography Project and shall only */
+/* be used, modified, and distributed under the terms of the Catharon */
+/* Open Source License that should come with this file under the name */
+/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* Note that this license is compatible with the FreeType license. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This defines the AH_GlyphLoader type in two different ways: */
+ /* */
+ /* - If the module is compiled within FreeType 2, the type is simply a */
+ /* typedef to FT_GlyphLoader. */
+ /* */
+ /* - If the module is compiled as a standalone object, AH_GlyphLoader */
+ /* has its own implementation. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef AHLOADER_H
+#define AHLOADER_H
+
+
+#ifdef _STANDALONE_
+
+ typedef struct AH_GlyphLoad_
+ {
+ FT_Outline outline; /* outline */
+ FT_UInt num_subglyphs; /* number of subglyphs */
+ FT_SubGlyph* subglyphs; /* subglyphs */
+ FT_Vector* extra_points; /* extra points table */
+
+ } AH_GlyphLoad;
+
+
+ struct AH_GlyphLoader_
+ {
+ FT_Memory memory;
+ FT_UInt max_points;
+ FT_UInt max_contours;
+ FT_UInt max_subglyphs;
+ FT_Bool use_extra;
+
+ AH_GlyphLoad base;
+ AH_GlyphLoad current;
+
+ void* other; /* for possible future extensions */
+ };
+
+
+ LOCAL_DEF
+ FT_Error AH_GlyphLoader_New( FT_Memory memory,
+ AH_GlyphLoader** aloader );
+
+ LOCAL_DEF
+ FT_Error AH_GlyphLoader_Create_Extra( AH_GlyphLoader* loader );
+
+ LOCAL_DEF
+ void AH_GlyphLoader_Done( AH_GlyphLoader* loader );
+
+ LOCAL_DEF
+ void AH_GlyphLoader_Reset( AH_GlyphLoader* loader );
+
+ LOCAL_DEF
+ void AH_GlyphLoader_Rewind( AH_GlyphLoader* loader );
+
+ LOCAL_DEF
+ FT_Error AH_GlyphLoader_Check_Points( AH_GlyphLoader* loader,
+ FT_UInt n_points,
+ FT_UInt n_contours );
+
+ LOCAL_DEF
+ FT_Error AH_GlyphLoader_Check_Subglyphs( AH_GlyphLoader* loader,
+ FT_UInt n_subs );
+
+ LOCAL_DEF
+ void AH_GlyphLoader_Prepare( AH_GlyphLoader* loader );
+
+ LOCAL_DEF
+ void AH_GlyphLoader_Add( AH_GlyphLoader* loader );
+
+ LOCAL_DEF
+ FT_Error AH_GlyphLoader_Copy_Points( AH_GlyphLoader* target,
+ FT_GlyphLoader* source );
+
+#else /* _STANDALONE */
+
+#include <freetype/internal/ftobjs.h>
+
+ #define AH_Load FT_GlyphLoad
+ #define AH_Loader FT_GlyphLoader
+
+ #define ah_loader_new FT_GlyphLoader_New
+ #define ah_loader_done FT_GlyphLoader_Done
+ #define ah_loader_reset FT_GlyphLoader_Reset
+ #define ah_loader_rewind FT_GlyphLoader_Rewind
+ #define ah_loader_create_extra FT_GlyphLoader_Create_Extra
+ #define ah_loader_check_points FT_GlyphLoader_Check_Points
+ #define ah_loader_check_subglyphs FT_GlyphLoader_Check_Subglyphs
+ #define ah_loader_prepare FT_GlyphLoader_Prepare
+ #define ah_loader_add FT_GlyphLoader_Add
+ #define ah_loader_copy_points FT_GlyphLoader_Copy_Points
+
+#endif /* _STANDALONE_ */
+
+#endif /* AHLOADER_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ahmodule.c */
+/* */
+/* Auto-hinting module implementation (declaration). */
+/* */
+/* Copyright 2000 Catharon Productions Inc. */
+/* Author: David Turner */
+/* */
+/* This file is part of the Catharon Typography Project and shall only */
+/* be used, modified, and distributed under the terms of the Catharon */
+/* Open Source License that should come with this file under the name */
+/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* Note that this license is compatible with the FreeType license. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/ftmodule.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahhint.h"
+
+#else
+
+#include <autohint/ahhint.h>
+
+#endif
+
+
+ typedef struct FT_AutoHinterRec_
+ {
+ FT_ModuleRec root;
+ AH_Hinter* hinter;
+
+ } FT_AutoHinterRec;
+
+
+ static
+ FT_Error ft_autohinter_init( FT_AutoHinter module )
+ {
+ return ah_hinter_new( module->root.library, &module->hinter );
+ }
+
+
+ static
+ void ft_autohinter_done( FT_AutoHinter module )
+ {
+ ah_hinter_done( module->hinter );
+ }
+
+
+ static
+ FT_Error ft_autohinter_load( FT_AutoHinter module,
+ FT_GlyphSlot slot,
+ FT_Size size,
+ FT_UInt glyph_index,
+ FT_ULong load_flags )
+ {
+ return ah_hinter_load_glyph( module->hinter,
+ slot, size, glyph_index, load_flags );
+ }
+
+
+ static
+ void ft_autohinter_reset( FT_AutoHinter module,
+ FT_Face face )
+ {
+ UNUSED( module );
+
+ if ( face->autohint.data )
+ ah_hinter_done_face_globals( (AH_Face_Globals*)(face->autohint.data) );
+ }
+
+
+ static
+ void ft_autohinter_get_globals( FT_AutoHinter module,
+ FT_Face face,
+ void** global_hints,
+ long* global_len )
+ {
+ ah_hinter_get_global_hints( module->hinter, face,
+ global_hints, global_len );
+ }
+
+
+ static
+ void ft_autohinter_done_globals( FT_AutoHinter module,
+ void* global_hints )
+ {
+ ah_hinter_done_global_hints( module->hinter, global_hints );
+ }
+
+
+ static
+ const FT_AutoHinter_Interface autohinter_interface =
+ {
+ ft_autohinter_reset,
+ ft_autohinter_load,
+ ft_autohinter_get_globals,
+ ft_autohinter_done_globals
+ };
+
+
+ const FT_Module_Class autohint_module_class =
+ {
+ ft_module_hinter,
+ sizeof ( FT_AutoHinterRec ),
+
+ "autohinter",
+ 0x10000L, /* version 1.0 of the autohinter */
+ 0x20000L, /* requires FreeType 2.0 or above */
+
+ (const void*)&autohinter_interface,
+
+ (FT_Module_Constructor)ft_autohinter_init,
+ (FT_Module_Destructor) ft_autohinter_done,
+ (FT_Module_Requester) 0
+ };
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ahmodule.h */
+/* */
+/* Auto-hinting module (declaration). */
+/* */
+/* Copyright 2000 Catharon Productions Inc. */
+/* Author: David Turner */
+/* */
+/* This file is part of the Catharon Typography Project and shall only */
+/* be used, modified, and distributed under the terms of the Catharon */
+/* Open Source License that should come with this file under the name */
+/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* Note that this license is compatible with the FreeType license. */
+/* */
+/***************************************************************************/
+
+
+#ifndef AHMODULE_H
+#define AHMODULE_H
+
+#include <freetype/ftmodule.h>
+
+ FT_EXPORT_VAR( const FT_Module_Class ) autohint_module_class;
+
+#endif /* AHMODULE_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ahoptim.c */
+/* */
+/* FreeType auto hinting outline optimization (body). */
+/* */
+/* Copyright 2000 Catharon Productions Inc. */
+/* Author: David Turner */
+/* */
+/* This file is part of the Catharon Typography Project and shall only */
+/* be used, modified, and distributed under the terms of the Catharon */
+/* Open Source License that should come with this file under the name */
+/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* Note that this license is compatible with the FreeType license. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This module is in charge of optimising the outlines produced by the */
+ /* auto-hinter in direct mode. This is required at small pixel sizes in */
+ /* order to ensure coherent spacing, among other things.. */
+ /* */
+ /* The technique used in this module is a simplified simulated */
+ /* annealing. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/internal/ftobjs.h> /* for ALLOC_ARRAY() and FREE() */
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahoptim.h"
+
+#else
+
+#include <autohint/ahoptim.h>
+
+#endif
+
+
+ /* define this macro to use brute force optimisation -- this is slow, */
+ /* but a good way to perfect the distortion function `by hand' through */
+ /* tweaking */
+#define AH_BRUTE_FORCE
+
+
+#define xxxAH_DEBUG_OPTIM
+
+
+#undef LOG
+#ifdef AH_DEBUG_OPTIM
+
+#define LOG( x ) optim_log##x
+
+#else
+
+#define LOG( x )
+
+#endif /* AH_DEBUG_OPTIM */
+
+
+#ifdef AH_DEBUG_OPTIM
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define FLOAT( x ) ( (float)( (x) / 64.0 ) )
+
+ static
+ void optim_log( const char* fmt, ... )
+ {
+ va_list ap;
+
+
+ va_start( ap, fmt );
+ vprintf( fmt, ap );
+ va_end( ap );
+ }
+
+
+ static
+ void AH_Dump_Stems( AH_Optimizer* optimizer )
+ {
+ int n;
+ AH_Stem* stem;
+
+
+ stem = optimizer->stems;
+ for ( n = 0; n < optimizer->num_stems; n++, stem++ )
+ {
+ LOG(( " %c%2d [%.1f:%.1f]={%.1f:%.1f}="
+ "<%1.f..%1.f> force=%.1f speed=%.1f\n",
+ optimizer->vertical ? 'V' : 'H', n,
+ FLOAT( stem->edge1->opos ), FLOAT( stem->edge2->opos ),
+ FLOAT( stem->edge1->pos ), FLOAT( stem->edge2->pos ),
+ FLOAT( stem->min_pos ), FLOAT( stem->max_pos ),
+ FLOAT( stem->force ), FLOAT( stem->velocity ) ));
+ }
+ }
+
+
+ static
+ void AH_Dump_Stems2( AH_Optimizer* optimizer )
+ {
+ int n;
+ AH_Stem* stem;
+
+
+ stem = optimizer->stems;
+ for ( n = 0; n < optimizer->num_stems; n++, stem++ )
+ {
+ LOG(( " %c%2d [%.1f]=<%1.f..%1.f> force=%.1f speed=%.1f\n",
+ optimizer->vertical ? 'V' : 'H', n,
+ FLOAT( stem->pos ),
+ FLOAT( stem->min_pos ), FLOAT( stem->max_pos ),
+ FLOAT( stem->force ), FLOAT( stem->velocity ) ));
+ }
+ }
+
+
+ static
+ void AH_Dump_Springs( AH_Optimizer* optimizer )
+ {
+ int n;
+ AH_Spring* spring;
+ AH_Stem* stems;
+
+
+ spring = optimizer->springs;
+ stems = optimizer->stems;
+ LOG(( "%cSprings ", optimizer->vertical ? 'V' : 'H' ));
+
+ for ( n = 0; n < optimizer->num_springs; n++, spring++ )
+ {
+ LOG(( " [%d-%d:%.1f:%1.f:%.1f]",
+ spring->stem1 - stems, spring->stem2 - stems,
+ FLOAT( spring->owidth ),
+ FLOAT( spring->stem2->pos -
+ ( spring->stem1->pos + spring->stem1->width ) ),
+ FLOAT( spring->tension ) ));
+ }
+
+ LOG(( "\n" ));
+ }
+
+#endif /* AH_DEBUG_OPTIM */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** COMPUTE STEMS AND SPRINGS IN AN OUTLINE ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static
+ int valid_stem_segments( AH_Segment* seg1,
+ AH_Segment* seg2 )
+ {
+ return seg1->serif == 0 &&
+ seg2 &&
+ seg2->link == seg1 &&
+ seg1->pos < seg2->pos &&
+ seg1->min_coord <= seg2->max_coord &&
+ seg2->min_coord <= seg1->max_coord;
+ }
+
+
+ /* compute all stems in an outline */
+ static
+ int optim_compute_stems( AH_Optimizer* optimizer )
+ {
+ AH_Outline* outline = optimizer->outline;
+ FT_Fixed scale;
+ FT_Memory memory = optimizer->memory;
+ FT_Error error = 0;
+ FT_Int dimension;
+ AH_Edge* edges;
+ AH_Edge* edge_limit;
+ AH_Stem** p_stems;
+ FT_Int* p_num_stems;
+
+
+ edges = outline->horz_edges;
+ edge_limit = edges + outline->num_hedges;
+ scale = outline->y_scale;
+
+ p_stems = &optimizer->horz_stems;
+ p_num_stems = &optimizer->num_hstems;
+
+ for ( dimension = 1; dimension >= 0; dimension-- )
+ {
+ AH_Stem* stems = 0;
+ FT_Int num_stems = 0;
+ AH_Edge* edge;
+
+
+ /* first of all, count the number of stems in this direction */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ AH_Segment* seg = edge->first;
+
+
+ do
+ {
+ if (valid_stem_segments( seg, seg->link ) )
+ num_stems++;
+
+ seg = seg->edge_next;
+
+ } while ( seg != edge->first );
+ }
+
+ /* now allocate the stems and build their table */
+ if ( num_stems > 0 )
+ {
+ AH_Stem* stem;
+
+
+ if ( ALLOC_ARRAY( stems, num_stems, AH_Stem ) )
+ goto Exit;
+
+ stem = stems;
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ AH_Segment* seg = edge->first;
+ AH_Segment* seg2;
+
+
+ do
+ {
+ seg2 = seg->link;
+ if ( valid_stem_segments( seg, seg2 ) )
+ {
+ AH_Edge* edge1 = seg->edge;
+ AH_Edge* edge2 = seg2->edge;
+
+
+ stem->edge1 = edge1;
+ stem->edge2 = edge2;
+ stem->opos = edge1->opos;
+ stem->pos = edge1->pos;
+ stem->owidth = edge2->opos - edge1->opos;
+ stem->width = edge2->pos - edge1->pos;
+
+ /* compute min_coord and max_coord */
+ {
+ FT_Pos min_coord = seg->min_coord;
+ FT_Pos max_coord = seg->max_coord;
+
+
+ if ( seg2->min_coord > min_coord )
+ min_coord = seg2->min_coord;
+
+ if ( seg2->max_coord < max_coord )
+ max_coord = seg2->max_coord;
+
+ stem->min_coord = min_coord;
+ stem->max_coord = max_coord;
+ }
+
+ /* compute minimum and maximum positions for stem -- */
+ /* note that the left-most/bottom-most stem has always */
+ /* a fixed position */
+ if ( stem == stems || edge1->blue_edge || edge2->blue_edge )
+ {
+ /* this stem cannot move; it is snapped to a blue edge */
+ stem->min_pos = stem->pos;
+ stem->max_pos = stem->pos;
+ }
+ else
+ {
+ /* this edge can move; compute its min and max positions */
+ FT_Pos pos1 = stem->opos;
+ FT_Pos pos2 = pos1 + stem->owidth - stem->width;
+ FT_Pos min1 = pos1 & -64;
+ FT_Pos min2 = pos2 & -64;
+
+
+ stem->min_pos = min1;
+ stem->max_pos = min1 + 64;
+ if ( min2 < min1 )
+ stem->min_pos = min2;
+ else
+ stem->max_pos = min2 + 64;
+
+ /* XXX: just to see what it does */
+ stem->max_pos += 64;
+
+ /* just for the case where direct hinting did some */
+ /* incredible things (e.g. blue edge shifts) */
+ if ( stem->min_pos > stem->pos )
+ stem->min_pos = stem->pos;
+
+ if ( stem->max_pos < stem->pos )
+ stem->max_pos = stem->pos;
+ }
+
+ stem->velocity = 0;
+ stem->force = 0;
+
+ stem++;
+ }
+ seg = seg->edge_next;
+
+ } while ( seg != edge->first );
+ }
+ }
+
+ *p_stems = stems;
+ *p_num_stems = num_stems;
+
+ edges = outline->vert_edges;
+ edge_limit = edges + outline->num_vedges;
+ scale = outline->x_scale;
+
+ p_stems = &optimizer->vert_stems;
+ p_num_stems = &optimizer->num_vstems;
+ }
+
+ Exit:
+
+#ifdef AH_DEBUG_OPTIM
+ AH_Dump_Stems( optimizer );
+#endif
+
+ return error;
+ }
+
+
+ /* returns the spring area between two stems, 0 if none */
+ static
+ FT_Pos stem_spring_area( AH_Stem* stem1,
+ AH_Stem* stem2 )
+ {
+ FT_Pos area1 = stem1->max_coord - stem1->min_coord;
+ FT_Pos area2 = stem2->max_coord - stem2->min_coord;
+ FT_Pos min = stem1->min_coord;
+ FT_Pos max = stem1->max_coord;
+ FT_Pos area;
+
+
+ /* order stems */
+ if ( stem2->opos <= stem1->opos + stem1->owidth )
+ return 0;
+
+ if ( min < stem2->min_coord )
+ min = stem2->min_coord;
+
+ if ( max < stem2->max_coord )
+ max = stem2->max_coord;
+
+ area = ( max-min );
+ if ( 2 * area < area1 && 2 * area < area2 )
+ area = 0;
+
+ return area;
+ }
+
+
+ /* compute all springs in an outline */
+ static
+ int optim_compute_springs( AH_Optimizer* optimizer )
+ {
+ /* basically, a spring exists between two stems if most of their */
+ /* surface is aligned */
+ FT_Memory memory = optimizer->memory;
+
+ AH_Stem* stems;
+ AH_Stem* stem_limit;
+ AH_Stem* stem;
+ int dimension;
+ int error = 0;
+
+ FT_Int* p_num_springs;
+ AH_Spring** p_springs;
+
+
+ stems = optimizer->horz_stems;
+ stem_limit = stems + optimizer->num_hstems;
+
+ p_springs = &optimizer->horz_springs;
+ p_num_springs = &optimizer->num_hsprings;
+
+ for ( dimension = 1; dimension >= 0; dimension-- )
+ {
+ FT_Int num_springs = 0;
+ AH_Spring* springs = 0;
+
+
+ /* first of all, count stem springs */
+ for ( stem = stems; stem + 1 < stem_limit; stem++ )
+ {
+ AH_Stem* stem2;
+
+
+ for ( stem2 = stem+1; stem2 < stem_limit; stem2++ )
+ if ( stem_spring_area( stem, stem2 ) )
+ num_springs++;
+ }
+
+ /* then allocate and build the springs table */
+ if ( num_springs > 0 )
+ {
+ AH_Spring* spring;
+
+
+ /* allocate table of springs */
+ if ( ALLOC_ARRAY( springs, num_springs, AH_Spring ) )
+ goto Exit;
+
+ /* fill the springs table */
+ spring = springs;
+ for ( stem = stems; stem+1 < stem_limit; stem++ )
+ {
+ AH_Stem* stem2;
+ FT_Pos area;
+
+
+ for ( stem2 = stem + 1; stem2 < stem_limit; stem2++ )
+ {
+ area = stem_spring_area( stem, stem2 );
+ if ( area )
+ {
+ /* add a new spring here */
+ spring->stem1 = stem;
+ spring->stem2 = stem2;
+ spring->owidth = stem2->opos - ( stem->opos + stem->owidth );
+ spring->tension = 0;
+
+ spring++;
+ }
+ }
+ }
+ }
+ *p_num_springs = num_springs;
+ *p_springs = springs;
+
+ stems = optimizer->vert_stems;
+ stem_limit = stems + optimizer->num_vstems;
+
+ p_springs = &optimizer->vert_springs;
+ p_num_springs = &optimizer->num_vsprings;
+ }
+
+ Exit:
+
+#ifdef AH_DEBUG_OPTIM
+ AH_Dump_Springs( optimizer );
+#endif
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** OPTIMIZE THROUGH MY STRANGE SIMULATED ANNEALING ALGO ;-) ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#ifndef AH_BRUTE_FORCE
+
+ /* compute all spring tensions */
+ static
+ void optim_compute_tensions( AH_Optimizer* optimizer )
+ {
+ AH_Spring* spring = optimizer->springs;
+ AH_Spring* limit = spring + optimizer->num_springs;
+
+
+ for ( ; spring < limit; spring++ )
+ {
+ AH_Stem* stem1 = spring->stem1;
+ AH_Stem* stem2 = spring->stem2;
+ FT_Int status;
+
+ FT_Pos width;
+ FT_Pos tension;
+ FT_Pos sign;
+
+
+ /* compute the tension; it simply is -K*(new_width-old_width) */
+ width = stem2->pos - ( stem1->pos + stem1->width );
+ tension = width - spring->owidth;
+
+ sign = 1;
+ if ( tension < 0 )
+ {
+ sign = -1;
+ tension = -tension;
+ }
+
+ if ( width <= 0 )
+ tension = 32000;
+ else
+ tension = ( tension << 10 ) / width;
+
+ tension = -sign * FT_MulFix( tension, optimizer->tension_scale );
+ spring->tension = tension;
+
+ /* now, distribute tension among the englobing stems, if they */
+ /* are able to move */
+ status = 0;
+ if ( stem1->pos <= stem1->min_pos )
+ status |= 1;
+ if ( stem2->pos >= stem2->max_pos )
+ status |= 2;
+
+ if ( !status )
+ tension /= 2;
+
+ if ( ( status & 1 ) == 0 )
+ stem1->force -= tension;
+
+ if ( ( status & 2 ) == 0 )
+ stem2->force += tension;
+ }
+ }
+
+
+ /* compute all stem movements -- returns 0 if nothing moved */
+ static
+ int optim_compute_stem_movements( AH_Optimizer* optimizer )
+ {
+ AH_Stem* stems = optimizer->stems;
+ AH_Stem* limit = stems + optimizer->num_stems;
+ AH_Stem* stem = stems;
+ int moved = 0;
+
+
+ /* set initial forces to velocity */
+ for ( stem = stems; stem < limit; stem++ )
+ {
+ stem->force = stem->velocity;
+ stem->velocity /= 2; /* XXX: Heuristics */
+ }
+
+ /* compute the sum of forces applied on each stem */
+ optim_compute_tensions( optimizer );
+
+#ifdef AH_DEBUG_OPTIM
+ AH_Dump_Springs( optimizer );
+ AH_Dump_Stems2( optimizer );
+#endif
+
+ /* now, see whether something can move */
+ for ( stem = stems; stem < limit; stem++ )
+ {
+ if ( stem->force > optimizer->tension_threshold )
+ {
+ /* there is enough tension to move the stem to the right */
+ if ( stem->pos < stem->max_pos )
+ {
+ stem->pos += 64;
+ stem->velocity = stem->force / 2;
+ moved = 1;
+ }
+ else
+ stem->velocity = 0;
+ }
+ else if ( stem->force < optimizer->tension_threshold )
+ {
+ /* there is enough tension to move the stem to the left */
+ if ( stem->pos > stem->min_pos )
+ {
+ stem->pos -= 64;
+ stem->velocity = stem->force / 2;
+ moved = 1;
+ }
+ else
+ stem->velocity = 0;
+ }
+ }
+
+ /* return 0 if nothing moved */
+ return moved;
+ }
+
+#endif /* AH_BRUTE_FORCE */
+
+
+ /* compute current global distortion from springs */
+ static
+ FT_Pos optim_compute_distortion( AH_Optimizer* optimizer )
+ {
+ AH_Spring* spring = optimizer->springs;
+ AH_Spring* limit = spring + optimizer->num_springs;
+ FT_Pos distortion = 0;
+
+
+ for ( ; spring < limit; spring++ )
+ {
+ AH_Stem* stem1 = spring->stem1;
+ AH_Stem* stem2 = spring->stem2;
+ FT_Pos width;
+
+ width = stem2->pos - ( stem1->pos + stem1->width );
+ width -= spring->owidth;
+ if ( width < 0 )
+ width = -width;
+
+ distortion += width;
+ }
+
+ return distortion;
+ }
+
+
+ /* record stems configuration in `best of' history */
+ static
+ void optim_record_configuration( AH_Optimizer* optimizer )
+ {
+ FT_Pos distortion;
+ AH_Configuration* configs = optimizer->configs;
+ AH_Configuration* limit = configs + optimizer->num_configs;
+ AH_Configuration* config;
+
+
+ distortion = optim_compute_distortion( optimizer );
+ LOG(( "config distortion = %.1f ", FLOAT( distortion * 64 ) ));
+
+ /* check that we really need to add this configuration to our */
+ /* sorted history */
+ if ( limit > configs && limit[-1].distortion < distortion )
+ {
+ LOG(( "ejected\n" ));
+ return;
+ }
+
+ /* add new configuration at the end of the table */
+ {
+ int n;
+
+
+ config = limit;
+ if ( optimizer->num_configs < AH_MAX_CONFIGS )
+ optimizer->num_configs++;
+ else
+ config--;
+
+ config->distortion = distortion;
+
+ for ( n = 0; n < optimizer->num_stems; n++ )
+ config->positions[n] = optimizer->stems[n].pos;
+ }
+
+ /* move the current configuration towards the front of the list */
+ /* when necessary -- yes this is slow bubble sort ;-) */
+ while ( config > configs && config[0].distortion < config[-1].distortion )
+ {
+ AH_Configuration temp;
+
+
+ config--;
+ temp = config[0];
+ config[0] = config[1];
+ config[1] = temp;
+ }
+ LOG(( "recorded!\n" ));
+ }
+
+
+#ifdef AH_BRUTE_FORCE
+
+ /* optimize outline in a single direction */
+ static
+ void optim_compute( AH_Optimizer* optimizer )
+ {
+ int n;
+ FT_Bool moved;
+
+ AH_Stem* stem = optimizer->stems;
+ AH_Stem* limit = stem + optimizer->num_stems;
+
+
+ /* empty, exit */
+ if ( stem >= limit )
+ return;
+
+ optimizer->num_configs = 0;
+
+ stem = optimizer->stems;
+ for ( ; stem < limit; stem++ )
+ stem->pos = stem->min_pos;
+
+ do
+ {
+ /* record current configuration */
+ optim_record_configuration( optimizer );
+
+ /* now change configuration */
+ moved = 0;
+ for ( stem = optimizer->stems; stem < limit; stem++ )
+ {
+ if ( stem->pos < stem->max_pos )
+ {
+ stem->pos += 64;
+ moved = 1;
+ break;
+ }
+
+ stem->pos = stem->min_pos;
+ }
+ } while ( moved );
+
+ /* now, set the best stem positions */
+ for ( n = 0; n < optimizer->num_stems; n++ )
+ {
+ AH_Stem* stem = optimizer->stems + n;
+ FT_Pos pos = optimizer->configs[0].positions[n];
+
+
+ stem->edge1->pos = pos;
+ stem->edge2->pos = pos + stem->width;
+
+ stem->edge1->flags |= ah_edge_done;
+ stem->edge2->flags |= ah_edge_done;
+ }
+ }
+
+#else /* AH_BRUTE_FORCE */
+
+ /* optimize outline in a single direction */
+ static
+ void optim_compute( AH_Optimizer* optimizer )
+ {
+ int n, counter, counter2;
+
+
+ optimizer->num_configs = 0;
+ optimizer->tension_scale = 0x80000L;
+ optimizer->tension_threshold = 64;
+
+ /* record initial configuration threshold */
+ optim_record_configuration( optimizer );
+
+ counter = 0;
+ for ( counter2 = optimizer->num_stems*8; counter2 >= 0; counter2-- )
+ {
+ if ( counter == 0 )
+ counter = 2 * optimizer->num_stems;
+
+ if ( !optim_compute_stem_movements( optimizer ) )
+ break;
+
+ optim_record_configuration( optimizer );
+
+ counter--;
+ if ( counter == 0 )
+ optimizer->tension_scale /= 2;
+ }
+
+ /* now, set the best stem positions */
+ for ( n = 0; n < optimizer->num_stems; n++ )
+ {
+ AH_Stem* stem = optimizer->stems + n;
+ FT_Pos pos = optimizer->configs[0].positions[n];
+
+
+ stem->edge1->pos = pos;
+ stem->edge2->pos = pos + stem->width;
+
+ stem->edge1->flags |= ah_edge_done;
+ stem->edge2->flags |= ah_edge_done;
+ }
+ }
+
+#endif /* AH_BRUTE_FORCE */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** HIGH-LEVEL OPTIMIZER API ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* releases the optimization data */
+ void AH_Optimizer_Done( AH_Optimizer* optimizer )
+ {
+ if ( optimizer )
+ {
+ FT_Memory memory = optimizer->memory;
+
+
+ FREE( optimizer->horz_stems );
+ FREE( optimizer->vert_stems );
+ FREE( optimizer->horz_springs );
+ FREE( optimizer->vert_springs );
+ FREE( optimizer->positions );
+ }
+ }
+
+
+ /* loads the outline into the optimizer */
+ int AH_Optimizer_Init( AH_Optimizer* optimizer,
+ AH_Outline* outline,
+ FT_Memory memory )
+ {
+ FT_Error error;
+
+
+ MEM_Set( optimizer, 0, sizeof ( *optimizer ) );
+ optimizer->outline = outline;
+ optimizer->memory = memory;
+
+ LOG(( "initializing new optimizer\n" ));
+ /* compute stems and springs */
+ error = optim_compute_stems ( optimizer ) ||
+ optim_compute_springs( optimizer );
+ if ( error )
+ goto Fail;
+
+ /* allocate stem positions history and configurations */
+ {
+ int n, max_stems;
+
+
+ max_stems = optimizer->num_hstems;
+ if ( max_stems < optimizer->num_vstems )
+ max_stems = optimizer->num_vstems;
+
+ if ( ALLOC_ARRAY( optimizer->positions,
+ max_stems * AH_MAX_CONFIGS, FT_Pos ) )
+ goto Fail;
+
+ optimizer->num_configs = 0;
+ for ( n = 0; n < AH_MAX_CONFIGS; n++ )
+ optimizer->configs[n].positions = optimizer->positions +
+ n * max_stems;
+ }
+
+ return error;
+
+ Fail:
+ AH_Optimizer_Done( optimizer );
+ return error;
+ }
+
+
+ /* compute optimal outline */
+ void AH_Optimizer_Compute( AH_Optimizer* optimizer )
+ {
+ optimizer->num_stems = optimizer->num_hstems;
+ optimizer->stems = optimizer->horz_stems;
+ optimizer->num_springs = optimizer->num_hsprings;
+ optimizer->springs = optimizer->horz_springs;
+
+ if ( optimizer->num_springs > 0 )
+ {
+ LOG(( "horizontal optimization ------------------------\n" ));
+ optim_compute( optimizer );
+ }
+
+ optimizer->num_stems = optimizer->num_vstems;
+ optimizer->stems = optimizer->vert_stems;
+ optimizer->num_springs = optimizer->num_vsprings;
+ optimizer->springs = optimizer->vert_springs;
+
+ if ( optimizer->num_springs )
+ {
+ LOG(( "vertical optimization --------------------------\n" ));
+ optim_compute( optimizer );
+ }
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ahoptim.h */
+/* */
+/* FreeType auto hinting outline optimization (declaration). */
+/* */
+/* Copyright 2000 Catharon Productions Inc. */
+/* Author: David Turner */
+/* */
+/* This file is part of the Catharon Typography Project and shall only */
+/* be used, modified, and distributed under the terms of the Catharon */
+/* Open Source License that should come with this file under the name */
+/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* Note that this license is compatible with the FreeType license. */
+/* */
+/***************************************************************************/
+
+
+#ifndef AHOPTIM_H
+#define AHOPTIM_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahtypes.h"
+
+#else
+
+#include <autohint/ahtypes.h>
+
+#endif
+
+
+ /* the maximal number of stem configurations to record */
+ /* during optimization */
+#define AH_MAX_CONFIGS 8
+
+
+ typedef struct AH_Stem_
+ {
+ FT_Pos pos; /* current position */
+ FT_Pos velocity; /* current velocity */
+ FT_Pos force; /* sum of current forces */
+ FT_Pos width; /* normalized width */
+
+ FT_Pos min_pos; /* minimum grid position */
+ FT_Pos max_pos; /* maximum grid position */
+
+ AH_Edge* edge1; /* left/bottom edge */
+ AH_Edge* edge2; /* right/top edge */
+
+ FT_Pos opos; /* original position */
+ FT_Pos owidth; /* original width */
+
+ FT_Pos min_coord; /* minimum coordinate */
+ FT_Pos max_coord; /* maximum coordinate */
+
+ } AH_Stem;
+
+
+ /* A spring between two stems */
+ typedef struct AH_Spring_
+ {
+ AH_Stem* stem1;
+ AH_Stem* stem2;
+ FT_Pos owidth; /* original width */
+ FT_Pos tension; /* current tension */
+
+ } AH_Spring;
+
+
+ /* A configuration records the position of each stem at a given time */
+ /* as well as the associated distortion */
+ typedef struct AH_Configuration_
+ {
+ FT_Pos* positions;
+ FT_Long distortion;
+
+ } AH_Configuration;
+
+
+ typedef struct AH_Optimizer_
+ {
+ FT_Memory memory;
+ AH_Outline* outline;
+
+ FT_Int num_hstems;
+ AH_Stem* horz_stems;
+
+ FT_Int num_vstems;
+ AH_Stem* vert_stems;
+
+ FT_Int num_hsprings;
+ FT_Int num_vsprings;
+ AH_Spring* horz_springs;
+ AH_Spring* vert_springs;
+
+ FT_Int num_configs;
+ AH_Configuration configs[AH_MAX_CONFIGS];
+ FT_Pos* positions;
+
+ /* during each pass, use these instead */
+ FT_Int num_stems;
+ AH_Stem* stems;
+
+ FT_Int num_springs;
+ AH_Spring* springs;
+ FT_Bool vertical;
+
+ FT_Fixed tension_scale;
+ FT_Pos tension_threshold;
+
+ } AH_Optimizer;
+
+
+ /* loads the outline into the optimizer */
+ int AH_Optimizer_Init( AH_Optimizer* optimizer,
+ AH_Outline* outline,
+ FT_Memory memory );
+
+
+ /* compute optimal outline */
+ void AH_Optimizer_Compute( AH_Optimizer* optimizer );
+
+
+ /* release the optimization data */
+ void AH_Optimizer_Done( AH_Optimizer* optimizer );
+
+
+#endif /* AHOPTIM_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ahtypes.h */
+/* */
+/* General types and definitions for the auto-hint module */
+/* (specification only). */
+/* */
+/* Copyright 2000 Catharon Productions Inc. */
+/* Author: David Turner */
+/* */
+/* This file is part of the Catharon Typography Project and shall only */
+/* be used, modified, and distributed under the terms of the Catharon */
+/* Open Source License that should come with this file under the name */
+/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* Note that this license is compatible with the FreeType license. */
+/* */
+/***************************************************************************/
+
+
+#ifndef AHTYPES_H
+#define AHTYPES_H
+
+
+#include <freetype/internal/ftobjs.h> /* for freetype.h + LOCAL_DEF etc. */
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahloader.h"
+
+#else
+
+#include <autohint/ahloader.h>
+
+#endif
+
+
+#define xxAH_DEBUG
+
+
+#ifdef AH_DEBUG
+
+#include <stdio.h>
+
+#define AH_LOG( x ) printf##x
+
+#else
+
+#define AH_LOG( x ) do ; while ( 0 ) /* nothing */
+
+#endif
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** COMPILE-TIME BUILD OPTIONS ****/
+ /**** ****/
+ /**** Toggle these configuration macros to experiment with `features' ****/
+ /**** of the auto-hinter. ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* If this option is defined, only strong interpolation will be used to */
+ /* place the points between edges. Otherwise, `smooth' points are */
+ /* detected and later hinted through weak interpolation to correct some */
+ /* unpleasant artefacts. */
+ /* */
+#undef AH_OPTION_NO_WEAK_INTERPOLATION
+
+
+ /*************************************************************************/
+ /* */
+ /* If this option is defined, only weak interpolation will be used to */
+ /* place the points between edges. Otherwise, `strong' points are */
+ /* detected and later hinted through strong interpolation to correct */
+ /* some unpleasant artefacts. */
+ /* */
+#undef AH_OPTION_NO_STRONG_INTERPOLATION
+
+
+ /*************************************************************************/
+ /* */
+ /* Undefine this macro if you don't want to hint the metrics. There is */
+ /* no reason to do this (at least for non-CJK scripts), except for */
+ /* experimentation. */
+ /* */
+#define AH_HINT_METRICS
+
+
+ /*************************************************************************/
+ /* */
+ /* Define this macro if you do not want to insert extra edges at a */
+ /* glyph's x and y extremum (if there isn't one already available). */
+ /* This helps to reduce a number of artefacts and allows hinting of */
+ /* metrics. */
+ /* */
+#undef AH_OPTION_NO_EXTREMUM_EDGES
+
+
+ /* don't touch for now */
+#define AH_MAX_WIDTHS 12
+#define AH_MAX_HEIGHTS 12
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** TYPE DEFINITIONS ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* see agangles.h */
+ typedef FT_Int AH_Angle;
+
+
+ /* hint flags */
+#define ah_flah_none 0
+
+ /* bezier control points flags */
+#define ah_flah_conic 1
+#define ah_flah_cubic 2
+#define ah_flah_control ( ah_flah_conic | ah_flah_cubic )
+
+ /* extrema flags */
+#define ah_flah_extrema_x 4
+#define ah_flah_extrema_y 8
+
+ /* roundness */
+#define ah_flah_round_x 16
+#define ah_flah_round_y 32
+
+ /* touched */
+#define ah_flah_touch_x 64
+#define ah_flah_touch_y 128
+
+ /* weak interpolation */
+#define ah_flah_weak_interpolation 256
+
+ typedef FT_Int AH_Flags;
+
+
+ /* edge hint flags */
+#define ah_edge_normal 0
+#define ah_edge_round 1
+#define ah_edge_serif 2
+#define ah_edge_done 4
+
+ typedef FT_Int AH_Edge_Flags;
+
+
+ /* hint directions -- the values are computed so that two vectors are */
+ /* in opposite directions iff `dir1+dir2 == 0' */
+#define ah_dir_none 4
+#define ah_dir_right 1
+#define ah_dir_left -1
+#define ah_dir_up 2
+#define ah_dir_down -2
+
+ typedef FT_Int AH_Direction;
+
+
+ typedef struct AH_Point AH_Point;
+ typedef struct AH_Segment AH_Segment;
+ typedef struct AH_Edge AH_Edge;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* AH_Point */
+ /* */
+ /* <Description> */
+ /* A structure used to model an outline point to the AH_Outline type. */
+ /* */
+ /* <Fields> */
+ /* flags :: The current point hint flags. */
+ /* */
+ /* ox, oy :: The current original scaled coordinates. */
+ /* */
+ /* fx, fy :: The current coordinates in font units. */
+ /* */
+ /* x, y :: The current hinter coordinates. */
+ /* */
+ /* u, v :: Point coordinates -- meaning varies with context. */
+ /* */
+ /* in_dir :: The direction of the inwards vector (prev->point). */
+ /* */
+ /* out_dir :: The direction of the outwards vector (point->next). */
+ /* */
+ /* in_angle :: The angle of the inwards vector. */
+ /* */
+ /* out_angle :: The angle of the outwards vector. */
+ /* */
+ /* next :: The next point in same contour. */
+ /* */
+ /* prev :: The previous point in same contour. */
+ /* */
+ struct AH_Point
+ {
+ AH_Flags flags; /* point flags used by hinter */
+ FT_Pos ox, oy;
+ FT_Pos fx, fy;
+ FT_Pos x, y;
+ FT_Pos u, v;
+
+ AH_Direction in_dir; /* direction of inwards vector */
+ AH_Direction out_dir; /* direction of outwards vector */
+
+ AH_Angle in_angle;
+ AH_Angle out_angle;
+
+ AH_Point* next; /* next point in contour */
+ AH_Point* prev; /* previous point in contour */
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* AH_Segment */
+ /* */
+ /* <Description> */
+ /* A structure used to describe an edge segment to the auto-hinter. */
+ /* A segment is simply a sequence of successive points located on the */
+ /* same horizontal or vertical `position', in a given direction. */
+ /* */
+ /* <Fields> */
+ /* flags :: The segment edge flags (straight, rounded, etc.). */
+ /* */
+ /* dir :: The segment direction. */
+ /* */
+ /* first :: The first point in the segment. */
+ /* */
+ /* last :: The last point in the segment. */
+ /* */
+ /* contour :: A pointer to the first point of the segment's */
+ /* contour. */
+ /* */
+ /* pos :: The segment position in font units. */
+ /* */
+ /* size :: The segment size. */
+ /* */
+ /* edge :: The edge of the current segment. */
+ /* */
+ /* edge_next :: The next segment on the same edge. */
+ /* */
+ /* link :: The pairing segment for this edge. */
+ /* */
+ /* serif :: The primary segment for serifs. */
+ /* */
+ /* num_linked :: The number of other segments that link to this one. */
+ /* */
+ /* score :: Used to score the segment when selecting them. */
+ /* */
+ struct AH_Segment
+ {
+ AH_Edge_Flags flags;
+ AH_Direction dir;
+
+ AH_Point* first; /* first point in edge segment */
+ AH_Point* last; /* last point in edge segment */
+ AH_Point** contour; /* ptr to first point of segment's contour */
+
+ FT_Pos pos; /* position of segment */
+ FT_Pos min_coord; /* minimum coordinate of segment */
+ FT_Pos max_coord; /* maximum coordinate of segment */
+
+ AH_Edge* edge;
+ AH_Segment* edge_next;
+
+ AH_Segment* link; /* link segment */
+ AH_Segment* serif; /* primary segment for serifs */
+ FT_Pos num_linked; /* number of linked segments */
+ FT_Int score;
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* AH_Edge */
+ /* */
+ /* <Description> */
+ /* A structure used to describe an edge, which really is a horizontal */
+ /* or vertical coordinate to be hinted depending on the segments */
+ /* located on it. */
+ /* */
+ /* <Fields> */
+ /* flags :: The segment edge flags (straight, rounded, etc.). */
+ /* */
+ /* dir :: The main segment direction on this edge. */
+ /* */
+ /* first :: The first edge segment. */
+ /* */
+ /* last :: The last edge segment. */
+ /* */
+ /* fpos :: The original edge position in font units. */
+ /* */
+ /* opos :: The original scaled edge position. */
+ /* */
+ /* pos :: The hinted edge position. */
+ /* */
+ /* link :: The linked edge. */
+ /* */
+ /* serif :: The serif edge. */
+ /* */
+ /* num_paired :: The number of other edges that pair to this one. */
+ /* */
+ /* score :: Used to score the edge when selecting them. */
+ /* */
+ /* blue_edge :: Indicate the blue zone edge this edge is related to. */
+ /* Only set for some of the horizontal edges in a Latin */
+ /* font. */
+ /* */
+ struct AH_Edge
+ {
+ AH_Edge_Flags flags;
+ AH_Direction dir;
+
+ AH_Segment* first;
+ AH_Segment* last;
+
+ FT_Pos fpos;
+ FT_Pos opos;
+ FT_Pos pos;
+
+ AH_Edge* link;
+ AH_Edge* serif;
+ FT_Int num_linked;
+
+ FT_Int score;
+ FT_Pos* blue_edge;
+ };
+
+
+ /* an outline as seen by the hinter */
+ typedef struct AH_Outline_
+ {
+ FT_Memory memory;
+
+ AH_Direction vert_major_dir; /* vertical major direction */
+ AH_Direction horz_major_dir; /* horizontal major direction */
+
+ FT_Fixed x_scale;
+ FT_Fixed y_scale;
+ FT_Pos edge_distance_threshold;
+
+ FT_Int max_points;
+ FT_Int num_points;
+ AH_Point* points;
+
+ FT_Int max_contours;
+ FT_Int num_contours;
+ AH_Point** contours;
+
+ FT_Int num_hedges;
+ AH_Edge* horz_edges;
+
+ FT_Int num_vedges;
+ AH_Edge* vert_edges;
+
+ FT_Int num_hsegments;
+ AH_Segment* horz_segments;
+
+ FT_Int num_vsegments;
+ AH_Segment* vert_segments;
+
+ } AH_Outline;
+
+
+#define ah_blue_capital_top 0 /* THEZOCQS */
+#define ah_blue_capital_bottom ( ah_blue_capital_top + 1 ) /* HEZLOCUS */
+#define ah_blue_small_top ( ah_blue_capital_bottom + 1 ) /* xzroesc */
+#define ah_blue_small_bottom ( ah_blue_small_top + 1 ) /* xzroesc */
+#define ah_blue_small_minor ( ah_blue_small_bottom + 1 ) /* pqgjy */
+#define ah_blue_max ( ah_blue_small_minor + 1 )
+
+ typedef FT_Int AH_Blue;
+
+
+#define ah_hinter_monochrome 1
+#define ah_hinter_optimize 2
+
+ typedef FT_Int AH_Hinter_Flags;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* AH_Globals */
+ /* */
+ /* <Description> */
+ /* Holds the global metrics for a given font face (be it in design */
+ /* units or scaled pixel values). */
+ /* */
+ /* <Fields> */
+ /* num_widths :: The number of widths. */
+ /* */
+ /* num_heights :: The number of heights. */
+ /* */
+ /* widths :: Snap widths, including standard one. */
+ /* */
+ /* heights :: Snap height, including standard one. */
+ /* */
+ /* blue_refs :: The reference positions of blue zones. */
+ /* */
+ /* blue_shoots :: The overshoot positions of blue zones. */
+ /* */
+ typedef struct AH_Globals_
+ {
+ FT_Int num_widths;
+ FT_Int num_heights;
+
+ FT_Pos widths [AH_MAX_WIDTHS];
+ FT_Pos heights[AH_MAX_HEIGHTS];
+
+ FT_Pos blue_refs [ah_blue_max];
+ FT_Pos blue_shoots[ah_blue_max];
+
+ } AH_Globals;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* AH_Face_Globals */
+ /* */
+ /* <Description> */
+ /* Holds the complete global metrics for a given font face (i.e., the */
+ /* design units version + a scaled version + the current scales */
+ /* used). */
+ /* */
+ /* <Fields> */
+ /* face :: A handle to the source face object */
+ /* */
+ /* design :: The globals in font design units. */
+ /* */
+ /* scaled :: Scaled globals in sub-pixel values. */
+ /* */
+ /* x_scale :: The current horizontal scale. */
+ /* */
+ /* y_scale :: The current vertical scale. */
+ /* */
+ typedef struct AH_Face_Globals_
+ {
+ FT_Face face;
+ AH_Globals design;
+ AH_Globals scaled;
+ FT_Fixed x_scale;
+ FT_Fixed y_scale;
+ FT_Bool control_overshoot;
+
+ } AH_Face_Globals;
+
+
+ typedef struct AH_Hinter
+ {
+ FT_Memory memory;
+ AH_Hinter_Flags flags;
+
+ FT_Int algorithm;
+ FT_Face face;
+
+ AH_Face_Globals* globals;
+
+ AH_Outline* glyph;
+
+ AH_Loader* loader;
+ FT_Vector pp1;
+ FT_Vector pp2;
+
+ } AH_Hinter;
+
+
+#endif /* AHTYPES_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* autohint.c */
+/* */
+/* Automatic Hinting wrapper (body only). */
+/* */
+/* Copyright 2000 Catharon Productions Inc. */
+/* Author: David Turner */
+/* */
+/* This file is part of the Catharon Typography Project and shall only */
+/* be used, modified, and distributed under the terms of the Catharon */
+/* Open Source License that should come with this file under the name */
+/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* Note that this license is compatible with the FreeType license. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahangles.c"
+#include "ahglyph.c"
+#include "ahglobal.c"
+#include "ahhint.c"
+#include "ahmodule.c"
+
+#else
+
+#include <autohint/ahangles.c>
+#include <autohint/ahglyph.c>
+#include <autohint/ahglobal.c>
+#include <autohint/ahhint.c>
+#include <autohint/ahmodule.c>
+
+#endif
+
+
+/* END */
--- /dev/null
+#!/usr/bin/env python
+#
+
+#
+# autohint math table builder
+#
+
+
+# Copyright 1996-2000 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+import math
+
+ag_pi = 256
+
+def print_arctan( atan_bits ):
+ atan_base = 1 << atan_bits
+
+ print " static AH_Angle ag_arctan[1L << AG_ATAN_BITS] ="
+ print " {"
+
+ count = 0
+ line = " "
+
+ for n in range( atan_base ):
+ comma = ","
+ if ( n == atan_base - 1 ):
+ comma = ""
+
+ angle = math.atan( n * 1.0 / atan_base ) / math.pi * ag_pi
+ line = line + " " + repr( int( angle + 0.5 ) ) + comma
+ count = count + 1;
+ if ( count == 8 ):
+ count = 0
+ print line
+ line = " "
+
+ if ( count > 0 ):
+ print line
+ print " };"
+
+
+# This routine is not used currently.
+#
+def print_sines():
+ print " static FT_Fixed ah_sines[AG_HALF_PI + 1] ="
+ print " {"
+
+ count = 0
+ line = " "
+
+ for n in range( ag_pi / 2 ):
+ sinus = math.sin( n * math.pi / ag_pi )
+ line = line + " " + repr( int( 65536.0 * sinus ) ) + ","
+ count = count + 1
+ if ( count == 8 ):
+ count = 0
+ print line
+ line = " "
+
+ if ( count > 0 ):
+ print line
+ print " 65536"
+ print " };"
+
+
+print_arctan( 8 )
+print
+
+
+# END
--- /dev/null
+make_module_list: add_autohint_module
+
+add_autohint_module:
+ $(OPEN_DRIVER)autohint_module_class$(CLOSE_DRIVER)
+ $(ECHO_DRIVER)autohint $(ECHO_DRIVER_DESC)automatic hinting module$(ECHO_DRIVER_DONE)
+
+# EOF
--- /dev/null
+#
+# FreeType 2 auto-hinter module configuration rules
+#
+
+
+# Copyright 2000 Catharon Productions Inc.
+# Author: David Turner
+#
+# This file is part of the Catharon Typography Project and shall only
+# be used, modified, and distributed under the terms of the Catharon
+# Open Source License that should come with this file under the name
+# `CatharonLicense.txt'. By continuing to use, modify, or distribute
+# this file you indicate that you have read the license and
+# understand and accept it fully.
+#
+# Note that this license is compatible with the FreeType license.
+
+
+# AUTO driver directory
+#
+AUTO_DIR := $(SRC_)autohint
+AUTO_DIR_ := $(AUTO_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+AUTO_COMPILE := $(FT_COMPILE)
+
+
+# AUTO driver sources (i.e., C files)
+#
+AUTO_DRV_SRC := $(AUTO_DIR_)ahangles.c \
+ $(AUTO_DIR_)ahglobal.c \
+ $(AUTO_DIR_)ahglyph.c \
+ $(AUTO_DIR_)ahhint.c \
+ $(AUTO_DIR_)ahmodule.c
+
+# AUTO driver headers
+#
+AUTO_DRV_H := $(AUTO_DRV_SRC:%c=%h) \
+ $(AUTO_DIR_)ahloader.h \
+ $(AUTO_DIR_)ahtypes.h
+
+
+# AUTO driver object(s)
+#
+# AUTO_DRV_OBJ_M is used during `multi' builds.
+# AUTO_DRV_OBJ_S is used during `single' builds.
+#
+AUTO_DRV_OBJ_M := $(AUTO_DRV_SRC:$(AUTO_DIR_)%.c=$(OBJ_)%.$O)
+AUTO_DRV_OBJ_S := $(OBJ_)autohint.$O
+
+# AUTO driver source file for single build
+#
+AUTO_DRV_SRC_S := $(AUTO_DIR_)autohint.c
+
+
+# AUTO driver - single object
+#
+$(AUTO_DRV_OBJ_S): $(AUTO_DRV_SRC_S) $(AUTO_DRV_SRC) \
+ $(FREETYPE_H) $(AUTO_DRV_H)
+ $(AUTO_COMPILE) $T$@ $(AUTO_DRV_SRC_S)
+
+
+# AUTO driver - multiple objects
+#
+$(OBJ_)%.$O: $(AUTO_DIR_)%.c $(FREETYPE_H) $(AUTO_DRV_H)
+ $(AUTO_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(AUTO_DRV_OBJ_S)
+DRV_OBJS_M += $(AUTO_DRV_OBJ_M)
+
+
+# EOF
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftbase.c */
+/* */
+/* Single object library component (body only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ftcalc.c"
+#include "ftobjs.c"
+#include "ftstream.c"
+#include "ftlist.c"
+#include "ftoutln.c"
+#include "ftextend.c"
+#include "ftnames.c"
+
+#else /* FT_FLAT_COMPILE */
+
+#include <base/ftcalc.c>
+#include <base/ftobjs.c>
+#include <base/ftstream.c>
+#include <base/ftlist.c>
+#include <base/ftoutln.c>
+#include <base/ftextend.c>
+#include <base/ftnames.c>
+
+#endif /* FT_FLAT_COMPILE */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftcalc.c */
+/* */
+/* Arithmetic computations (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* Support for 1-complement arithmetic has been totally dropped in this */
+ /* release. You can still write your own code if you need it. */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* Implementing basic computation routines. */
+ /* */
+ /* FT_MulDiv(), FT_MulFix(), and FT_DivFix() are declared in freetype.h. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftobjs.h> /* for ABS() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_calc
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+ static const FT_Long ft_square_roots[63] =
+ {
+ 1L, 1L, 2L, 3L, 4L, 5L, 8L, 11L,
+ 16L, 22L, 32L, 45L, 64L, 90L, 128L, 181L,
+ 256L, 362L, 512L, 724L, 1024L, 1448L, 2048L, 2896L,
+ 4096L, 5892L, 8192L, 11585L, 16384L, 23170L, 32768L, 46340L,
+
+ 65536L, 92681L, 131072L, 185363L, 262144L, 370727L,
+ 524288L, 741455L, 1048576L, 1482910L, 2097152L, 2965820L,
+ 4194304L, 5931641L, 8388608L, 11863283L, 16777216L, 23726566L,
+
+ 33554432L, 47453132L, 67108864L, 94906265L,
+ 134217728L, 189812531L, 268435456L, 379625062L,
+ 536870912L, 759250125L, 1073741824L, 1518500250L,
+ 2147483647L
+ };
+
+#else
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Sqrt32 */
+ /* */
+ /* <Description> */
+ /* Computes the square root of an Int32 integer (which will be */
+ /* handled as an unsigned long value). */
+ /* */
+ /* <Input> */
+ /* x :: The value to compute the root for. */
+ /* */
+ /* <Return> */
+ /* The result of `sqrt(x)'. */
+ /* */
+ FT_EXPORT_FUNC( FT_Int32 ) FT_Sqrt32( FT_Int32 x )
+ {
+ FT_ULong val, root, newroot, mask;
+
+
+ root = 0;
+ mask = 0x40000000L;
+ val = (FT_ULong)x;
+
+ do
+ {
+ newroot = root + mask;
+ if ( newroot <= val )
+ {
+ val -= newroot;
+ root = newroot + mask;
+ }
+
+ root >>= 1;
+ mask >>= 2;
+
+ } while ( mask != 0 );
+
+ return root;
+ }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+#ifdef FT_LONG64
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_MulDiv */
+ /* */
+ /* <Description> */
+ /* A very simple function used to perform the computation `(a*b)/c' */
+ /* with maximal accuracy (it uses a 64-bit intermediate integer */
+ /* whenever necessary). */
+ /* */
+ /* This function isn't necessarily as fast as some processor specific */
+ /* operations, but is at least completely portable. */
+ /* */
+ /* <Input> */
+ /* a :: The first multiplier. */
+ /* b :: The second multiplier. */
+ /* c :: The divisor. */
+ /* */
+ /* <Return> */
+ /* The result of `(a*b)/c'. This function never traps when trying to */
+ /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */
+ /* on the signs of `a' and `b'. */
+ /* */
+ FT_EXPORT_FUNC( FT_Long ) FT_MulDiv( FT_Long a,
+ FT_Long b,
+ FT_Long c )
+ {
+ FT_Int s;
+
+
+ s = 1;
+ if ( a < 0 ) { a = -a; s = -s; }
+ if ( b < 0 ) { b = -b; s = -s; }
+ if ( c < 0 ) { c = -c; s = -s; }
+
+ return s * ( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
+ : 0x7FFFFFFFL );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_MulFix */
+ /* */
+ /* <Description> */
+ /* A very simple function used to perform the computation */
+ /* `(a*b)/0x10000' with maximal accuracy. Most of the time this is */
+ /* used to multiply a given value by a 16.16 fixed float factor. */
+ /* */
+ /* <Input> */
+ /* a :: The first multiplier. */
+ /* b :: The second multiplier. Use a 16.16 factor here whenever */
+ /* possible (see note below). */
+ /* */
+ /* <Return> */
+ /* The result of `(a*b)/0x10000'. */
+ /* */
+ /* <Note> */
+ /* This function has been optimized for the case where the absolute */
+ /* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */
+ /* As this happens mainly when scaling from notional units to */
+ /* fractional pixels in FreeType, it resulted in noticeable speed */
+ /* improvements between versions 2.x and 1.x. */
+ /* */
+ /* As a conclusion, always try to place a 16.16 factor as the */
+ /* _second_ argument of this function; this can make a great */
+ /* difference. */
+ /* */
+ FT_EXPORT_FUNC( FT_Long ) FT_MulFix( FT_Long a,
+ FT_Long b )
+ {
+ FT_Int s;
+
+
+ s = 1;
+ if ( a < 0 ) { a = -a; s = -s; }
+ if ( b < 0 ) { b = -b; s = -s; }
+
+ return s * (FT_Long)( ( (FT_Int64)a * b + 0x8000 ) >> 16 );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_DivFix */
+ /* */
+ /* <Description> */
+ /* A very simple function used to perform the computation */
+ /* `(a*0x10000)/b' with maximal accuracy. Most of the time, this is */
+ /* used to divide a given value by a 16.16 fixed float factor. */
+ /* */
+ /* <Input> */
+ /* a :: The first multiplier. */
+ /* b :: The second multiplier. Use a 16.16 factor here whenever */
+ /* possible (see note below). */
+ /* */
+ /* <Return> */
+ /* The result of `(a*0x10000)/b'. */
+ /* */
+ /* <Note> */
+ /* The optimization for FT_DivFix() is simple: If (a << 16) fits in */
+ /* 32 bits, then the division is computed directly. Otherwise, we */
+ /* use a specialized version of the old FT_MulDiv64(). */
+ /* */
+ FT_EXPORT_FUNC( FT_Long ) FT_DivFix( FT_Long a,
+ FT_Long b )
+ {
+ FT_Int32 s;
+ FT_UInt32 q;
+
+
+ s = a; a = ABS(a);
+ s ^= b; b = ABS(b);
+
+ if ( b == 0 )
+ /* check for division by 0 */
+ q = 0x7FFFFFFFL;
+ else
+ /* compute result directly */
+ q = ( (FT_Int64)a << 16 ) / b;
+
+ return (FT_Int32)( s < 0 ? -q : q );
+ }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+ /* a helper function for FT_Sqrt64() */
+
+ static
+ int ft_order64( FT_Int64 z )
+ {
+ int j = 0;
+
+
+ while ( z )
+ {
+ z = (unsigned FT_INT64)z >> 1;
+ j++;
+ }
+ return j - 1;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Sqrt64 */
+ /* */
+ /* <Description> */
+ /* Computes the square root of a 64-bit value. That sounds stupid, */
+ /* but it is needed to obtain maximal accuracy in the TrueType */
+ /* bytecode interpreter. */
+ /* */
+ /* <Input> */
+ /* l :: A 64-bit integer. */
+ /* */
+ /* <Return> */
+ /* The 32-bit square-root. */
+ /* */
+ FT_EXPORT_FUNC( FT_Int32 ) FT_Sqrt64( FT_Int64 l )
+ {
+ FT_Int64 r, s;
+
+
+ if ( l <= 0 ) return 0;
+ if ( l == 1 ) return 1;
+
+ r = ft_square_roots[ft_order64( l )];
+
+ do
+ {
+ s = r;
+ r = ( r + l / r ) >> 1;
+
+ } while ( r > s || r * r > l );
+
+ return r;
+ }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+#else /* FT_LONG64 */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_MulDiv */
+ /* */
+ /* <Description> */
+ /* A very simple function used to perform the computation `(a*b)/c' */
+ /* with maximal accuracy (it uses a 64-bit intermediate integer */
+ /* whenever necessary). */
+ /* */
+ /* This function isn't necessarily as fast as some processor specific */
+ /* operations, but is at least completely portable. */
+ /* */
+ /* <Input> */
+ /* a :: The first multiplier. */
+ /* b :: The second multiplier. */
+ /* c :: The divisor. */
+ /* */
+ /* <Return> */
+ /* The result of `(a*b)/c'. This function never traps when trying to */
+ /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */
+ /* on the signs of `a' and `b'. */
+ /* */
+ /* <Note> */
+ /* The FT_MulDiv() function has been optimized thanks to ideas from */
+ /* Graham Asher. The trick is to optimize computation if everything */
+ /* fits within 32 bits (a rather common case). */
+ /* */
+ /* We compute `a*b+c/2', then divide it by `c' (positive values). */
+ /* */
+ /* 46340 is FLOOR(SQRT(2^31-1)). */
+ /* */
+ /* if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 ) */
+ /* */
+ /* 0x7FFFFFFF - 0x7FFEA810 = 0x157F0 */
+ /* */
+ /* if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF ) */
+ /* */
+ /* and 2*0x157F0 = 176096. */
+ /* */
+ FT_EXPORT_FUNC( FT_Long ) FT_MulDiv( FT_Long a,
+ FT_Long b,
+ FT_Long c )
+ {
+ long s;
+
+
+ if ( a == 0 || b == c )
+ return a;
+
+ s = a; a = ABS( a );
+ s ^= b; b = ABS( b );
+ s ^= c; c = ABS( c );
+
+ if ( a <= 46340 && b <= 46340 && c <= 176095L && c > 0 )
+ {
+ a = ( a * b + ( c >> 1 ) ) / c;
+ }
+ else if ( c > 0 )
+ {
+ FT_Int64 temp, temp2;
+
+
+ FT_MulTo64( a, b, &temp );
+ temp2.hi = (FT_Int32)( c >> 31 );
+ temp2.lo = (FT_UInt32)( c / 2 );
+ FT_Add64( &temp, &temp2, &temp );
+ a = FT_Div64by32( &temp, c );
+ }
+ else
+ a = 0x7FFFFFFFL;
+
+ return ( s < 0 ? -a : a );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_MulFix */
+ /* */
+ /* <Description> */
+ /* A very simple function used to perform the computation */
+ /* `(a*b)/0x10000' with maximal accuracy. Most of the time, this is */
+ /* used to multiply a given value by a 16.16 fixed float factor. */
+ /* */
+ /* <Input> */
+ /* a :: The first multiplier. */
+ /* b :: The second multiplier. Use a 16.16 factor here whenever */
+ /* possible (see note below). */
+ /* */
+ /* <Return> */
+ /* The result of `(a*b)/0x10000'. */
+ /* */
+ /* <Note> */
+ /* The optimization for FT_MulFix() is different. We could simply be */
+ /* happy by applying the same principles as with FT_MulDiv(), because */
+ /* */
+ /* c = 0x10000 < 176096 */
+ /* */
+ /* However, in most cases, we have a `b' with a value around 0x10000 */
+ /* which is greater than 46340. */
+ /* */
+ /* According to some testing, most cases have `a' < 2048, so a good */
+ /* idea is to use bounds like 2048 and 1048576 (=floor((2^31-1)/2048) */
+ /* for `a' and `b', respectively. */
+ /* */
+ FT_EXPORT_FUNC( FT_Long ) FT_MulFix( FT_Long a,
+ FT_Long b )
+ {
+ FT_Long s;
+ FT_ULong ua, ub;
+
+
+ if ( a == 0 || b == 0x10000L )
+ return a;
+
+ s = a; a = ABS(a);
+ s ^= b; b = ABS(b);
+
+ ua = (FT_ULong)a;
+ ub = (FT_ULong)b;
+
+ if ( ua <= 2048 && ub <= 1048576L )
+ {
+ ua = ( ua * ub + 0x8000 ) >> 16;
+ }
+ else
+ {
+ FT_ULong al = ua & 0xFFFF;
+
+
+ ua = ( ua >> 16 ) * ub +
+ al * ( ub >> 16 ) +
+ ( al * ( ub & 0xFFFF ) >> 16 );
+ }
+
+ return ( s < 0 ? -(FT_Long)ua : ua );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_DivFix */
+ /* */
+ /* <Description> */
+ /* A very simple function used to perform the computation */
+ /* `(a*0x10000)/b' with maximal accuracy. Most of the time, this is */
+ /* used to divide a given value by a 16.16 fixed float factor. */
+ /* */
+ /* <Input> */
+ /* a :: The first multiplier. */
+ /* b :: The second multiplier. Use a 16.16 factor here whenever */
+ /* possible (see note below). */
+ /* */
+ /* <Return> */
+ /* The result of `(a*0x10000)/b'. */
+ /* */
+ /* <Note> */
+ /* The optimization for FT_DivFix() is simple: If (a << 16) fits into */
+ /* 32 bits, then the division is computed directly. Otherwise, we */
+ /* use a specialized version of the old FT_MulDiv64(). */
+ /* */
+ FT_EXPORT_FUNC( FT_Long ) FT_DivFix( FT_Long a,
+ FT_Long b )
+ {
+ FT_Int32 s;
+ FT_UInt32 q;
+
+
+ s = a; a = ABS(a);
+ s ^= b; b = ABS(b);
+
+ if ( b == 0 )
+ {
+ /* check for division by 0 */
+ q = 0x7FFFFFFFL;
+ }
+ else if ( ( a >> 16 ) == 0 )
+ {
+ /* compute result directly */
+ q = (FT_UInt32)( a << 16 ) / (FT_UInt32)b;
+ }
+ else
+ {
+ /* we need more bits; we have to do it by hand */
+ FT_UInt32 c;
+
+
+ q = ( a / b ) << 16;
+ c = a % b;
+
+ /* we must compute C*0x10000/B: we simply shift C and B so */
+ /* C becomes smaller than 16 bits */
+ while ( c >> 16 )
+ {
+ c >>= 1;
+ b <<= 1;
+ }
+
+ q += ( c << 16 ) / b;
+ }
+
+ return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Add64 */
+ /* */
+ /* <Description> */
+ /* Add two Int64 values. */
+ /* */
+ /* <Input> */
+ /* x :: A pointer to the first value to be added. */
+ /* y :: A pointer to the second value to be added. */
+ /* */
+ /* <Output> */
+ /* z :: A pointer to the result of `x + y'. */
+ /* */
+ /* <Note> */
+ /* Will be wrapped by the ADD_64() macro. */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_Add64( FT_Int64* x,
+ FT_Int64* y,
+ FT_Int64* z )
+ {
+ register FT_UInt32 lo, hi;
+
+
+ lo = x->lo + y->lo;
+ hi = x->hi + y->hi + ( lo < x->lo );
+
+ z->lo = lo;
+ z->hi = hi;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_MulTo64 */
+ /* */
+ /* <Description> */
+ /* Multiplies two Int32 integers. Returns an Int64 integer. */
+ /* */
+ /* <Input> */
+ /* x :: The first multiplier. */
+ /* y :: The second multiplier. */
+ /* */
+ /* <Output> */
+ /* z :: A pointer to the result of `x * y'. */
+ /* */
+ /* <Note> */
+ /* Will be wrapped by the MUL_64() macro. */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_MulTo64( FT_Int32 x,
+ FT_Int32 y,
+ FT_Int64* z )
+ {
+ FT_Int32 s;
+
+
+ s = x; x = ABS( x );
+ s ^= y; y = ABS( y );
+
+ {
+ FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2;
+
+
+ lo1 = x & 0x0000FFFF; hi1 = x >> 16;
+ lo2 = y & 0x0000FFFF; hi2 = y >> 16;
+
+ lo = lo1 * lo2;
+ i1 = lo1 * hi2;
+ i2 = lo2 * hi1;
+ hi = hi1 * hi2;
+
+ /* Check carry overflow of i1 + i2 */
+ i1 += i2;
+ if ( i1 < i2 )
+ hi += 1L << 16;
+
+ hi += i1 >> 16;
+ i1 = i1 << 16;
+
+ /* Check carry overflow of i1 + lo */
+ lo += i1;
+ hi += ( lo < i1 );
+
+ z->lo = lo;
+ z->hi = hi;
+ }
+
+ if ( s < 0 )
+ {
+ z->lo = (FT_UInt32)-(FT_Int32)z->lo;
+ z->hi = ~z->hi + !( z->lo );
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Div64by32 */
+ /* */
+ /* <Description> */
+ /* Divides an Int64 value by an Int32 value. Returns an Int32 */
+ /* integer. */
+ /* */
+ /* <Input> */
+ /* x :: A pointer to the dividend. */
+ /* y :: The divisor. */
+ /* */
+ /* <Return> */
+ /* The result of `x / y'. */
+ /* */
+ /* <Note> */
+ /* Will be wrapped by the DIV_64() macro. */
+ /* */
+ FT_EXPORT_FUNC( FT_Int32 ) FT_Div64by32( FT_Int64* x,
+ FT_Int32 y )
+ {
+ FT_Int32 s;
+ FT_UInt32 q, r, i, lo;
+
+
+ s = x->hi;
+ if ( s < 0 )
+ {
+ x->lo = (FT_UInt32)-(FT_Int32)x->lo;
+ x->hi = ~x->hi + !( x->lo );
+ }
+ s ^= y; y = ABS( y );
+
+ /* Shortcut */
+ if ( x->hi == 0 )
+ {
+ if ( y > 0 )
+ q = x->lo / y;
+ else
+ q = 0x7FFFFFFFL;
+
+ return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+ }
+
+ r = x->hi;
+ lo = x->lo;
+
+ if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */
+ return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL );
+ /* Return Max/Min Int32 if division overflow. */
+ /* This includes division by zero! */
+ q = 0;
+ for ( i = 0; i < 32; i++ )
+ {
+ r <<= 1;
+ q <<= 1;
+ r |= lo >> 31;
+
+ if ( r >= (FT_UInt32)y )
+ {
+ r -= y;
+ q |= 1;
+ }
+ lo <<= 1;
+ }
+
+ return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+ }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+
+ /* two helper functions for FT_Sqrt64() */
+
+ static
+ void FT_Sub64( FT_Int64* x,
+ FT_Int64* y,
+ FT_Int64* z )
+ {
+ register FT_UInt32 lo, hi;
+
+
+ lo = x->lo - y->lo;
+ hi = x->hi - y->hi - ( (FT_Int32)lo < 0 );
+
+ z->lo = lo;
+ z->hi = hi;
+ }
+
+
+ static
+ int ft_order64( FT_Int64* z )
+ {
+ FT_UInt32 i;
+ int j;
+
+
+ i = z->lo;
+ j = 0;
+ if ( z->hi )
+ {
+ i = z->hi;
+ j = 32;
+ }
+
+ while ( i > 0 )
+ {
+ i >>= 1;
+ j++;
+ }
+ return j - 1;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Sqrt64 */
+ /* */
+ /* <Description> */
+ /* Computes the square root of a 64-bits value. That sounds stupid, */
+ /* but it is needed to obtain maximal accuracy in the TrueType */
+ /* bytecode interpreter. */
+ /* */
+ /* <Input> */
+ /* z :: A pointer to a 64-bit integer. */
+ /* */
+ /* <Return> */
+ /* The 32-bit square-root. */
+ /* */
+ FT_EXPORT_FUNC( FT_Int32 ) FT_Sqrt64( FT_Int64* l )
+ {
+ FT_Int64 l2;
+ FT_Int32 r, s;
+
+
+ if ( (FT_Int32)l->hi < 0 ||
+ ( l->hi == 0 && l->lo == 0 ) )
+ return 0;
+
+ s = ft_order64( l );
+ if ( s == 0 )
+ return 1;
+
+ r = ft_square_roots[s];
+ do
+ {
+ s = r;
+ r = ( r + FT_Div64by32( l, r ) ) >> 1;
+ FT_MulTo64( r, r, &l2 );
+ FT_Sub64 ( l, &l2, &l2 );
+
+ } while ( r > s || (FT_Int32)l2.hi < 0 );
+
+ return r;
+ }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+#endif /* FT_LONG64 */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftdebug.c */
+/* */
+/* Debugging and logging component (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This component contains various macros and functions used to ease the */
+ /* debugging of the FreeType engine. Its main purpose is in assertion */
+ /* checking, tracing, and error detection. */
+ /* */
+ /* There are now three debugging modes: */
+ /* */
+ /* - trace mode */
+ /* */
+ /* Error and trace messages are sent to the log file (which can be the */
+ /* standard error output). */
+ /* */
+ /* - error mode */
+ /* */
+ /* Only error messages are generated. */
+ /* */
+ /* - release mode: */
+ /* */
+ /* No error message is sent or generated. The code is free from any */
+ /* debugging parts. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ char ft_trace_levels[trace_max];
+#endif
+
+
+#if defined( FT_DEBUG_LEVEL_ERROR ) || defined( FT_DEBUG_LEVEL_TRACE )
+
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+ FT_EXPORT_FUNC( void ) FT_Message( const char* fmt, ... )
+ {
+ va_list ap;
+
+
+ va_start( ap, fmt );
+ vprintf( fmt, ap );
+ va_end( ap );
+ }
+
+
+ FT_EXPORT_FUNC( void ) FT_Panic( const char* fmt, ... )
+ {
+ va_list ap;
+
+
+ va_start( ap, fmt );
+ vprintf( fmt, ap );
+ va_end( ap );
+
+ exit( EXIT_FAILURE );
+ }
+
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_SetTraceLevel */
+ /* */
+ /* <Description> */
+ /* Sets the trace level for debugging. */
+ /* */
+ /* <Input> */
+ /* component :: The component which should be traced. See ftdebug.h */
+ /* for a complete list. If set to `trace_any', all */
+ /* components will be traced. */
+ /* level :: The tracing level. */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_SetTraceLevel( FT_Trace component,
+ char level )
+ {
+ if ( component >= trace_max )
+ return;
+
+ /* if component is `trace_any', change _all_ levels at once */
+ if ( component == trace_any )
+ {
+ int n;
+
+
+ for ( n = trace_any; n < trace_max; n++ )
+ ft_trace_levels[n] = level;
+ }
+ else /* otherwise, only change individual component */
+ ft_trace_levels[component] = level;
+ }
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+#endif /* FT_DEBUG_LEVEL_TRACE || FT_DEBUG_LEVEL_ERROR */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftextend.h */
+/* */
+/* FreeType extensions implementation (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* This is an updated version of the extension component, now located */
+ /* in the main library's source directory. It allows the dynamic */
+ /* registration/use of various face object extensions through a simple */
+ /* API. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/internal/ftextend.h>
+#include <freetype/internal/ftdebug.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_extend
+
+
+ typedef struct FT_Extension_Registry_
+ {
+ FT_Int num_extensions;
+ FT_Long cur_offset;
+ FT_Extension_Class classes[FT_MAX_EXTENSIONS];
+
+ } FT_Extension_Registry;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Init_Extensions */
+ /* */
+ /* <Description> */
+ /* Initializes the extension component. */
+ /* */
+ /* <InOut> */
+ /* driver :: A handle to the driver object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error FT_Init_Extensions( FT_Driver driver )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FT_Extension_Registry* registry;
+
+
+ memory = driver->root.library->memory;
+ if ( ALLOC( registry, sizeof ( *registry ) ) )
+ return error;
+
+ registry->num_extensions = 0;
+ registry->cur_offset = 0;
+ driver->extensions = registry;
+
+ FT_TRACE2(( "FT_Init_Extensions: success\n" ));
+
+ return FT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_Extensions */
+ /* */
+ /* <Description> */
+ /* Finalizes the extension component. */
+ /* */
+ /* <InOut> */
+ /* driver :: A handle to the driver object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error FT_Done_Extensions( FT_Driver driver )
+ {
+ FT_Memory memory = driver->root.memory;
+
+
+ FREE( driver->extensions );
+ return FT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Register_Extension */
+ /* */
+ /* <Description> */
+ /* Registers a new extension. */
+ /* */
+ /* <InOut> */
+ /* driver :: A handle to the driver object. */
+ /* class :: A pointer to a class describing the extension. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Register_Extension(
+ FT_Driver driver,
+ FT_Extension_Class* clazz )
+ {
+ FT_Extension_Registry* registry;
+
+
+ if ( !driver )
+ return FT_Err_Invalid_Driver_Handle;
+
+ if ( !clazz )
+ return FT_Err_Invalid_Argument;
+
+ registry = (FT_Extension_Registry*)driver->extensions;
+ if ( registry )
+ {
+ FT_Int n = registry->num_extensions;
+ FT_Extension_Class* cur = registry->classes + n;
+
+
+ if ( n >= FT_MAX_EXTENSIONS )
+ return FT_Err_Too_Many_Extensions;
+
+ *cur = *clazz;
+
+ cur->offset = registry->cur_offset;
+
+ registry->num_extensions++;
+ registry->cur_offset +=
+ ( cur->size + FT_ALIGNMENT - 1 ) & -FT_ALIGNMENT;
+
+ FT_TRACE1(( "FT_Register_Extension: `%s' successfully registered\n",
+ cur->id ));
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Extension */
+ /* */
+ /* <Description> */
+ /* Queries an extension block by an extension ID string. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the face object. */
+ /* extension_id :: An ID string identifying the extension. */
+ /* */
+ /* <Output> */
+ /* extension_interface :: A generic pointer, usually pointing to a */
+ /* table of functions implementing the */
+ /* extension interface. */
+ /* */
+ /* <Return> */
+ /* A generic pointer to the extension block. */
+ /* */
+ FT_EXPORT_FUNC( void* ) FT_Get_Extension(
+ FT_Face face,
+ const char* extension_id,
+ void** extension_interface )
+ {
+ FT_Extension_Registry* registry;
+
+
+ if ( !face || !extension_id || !extension_interface )
+ return 0;
+
+ registry = (FT_Extension_Registry*)face->driver->extensions;
+ if ( registry && face->extensions )
+ {
+ FT_Extension_Class* cur = registry->classes;
+ FT_Extension_Class* limit = cur + registry->num_extensions;
+
+
+ for ( ; cur < limit; cur++ )
+ if ( strcmp( cur->id, extension_id ) == 0 )
+ {
+ *extension_interface = cur->interface;
+
+ FT_TRACE1(( "FT_Get_Extension: got `%s'\n", extension_id ));
+
+ return (void*)((char*)face->extensions + cur->offset);
+ }
+ }
+
+ /* could not find the extension id */
+
+ FT_ERROR(( "FT_Get_Extension: couldn't find `%s'\n", extension_id ));
+
+ *extension_interface = 0;
+
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Destroy_Extensions */
+ /* */
+ /* <Description> */
+ /* Destroys all extensions within a face object. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Called by the face object destructor. */
+ /* */
+ LOCAL_FUNC
+ FT_Error FT_Destroy_Extensions( FT_Face face )
+ {
+ FT_Extension_Registry* registry;
+ FT_Memory memory;
+
+
+ registry = (FT_Extension_Registry*)face->driver->extensions;
+ if ( registry && face->extensions )
+ {
+ FT_Extension_Class* cur = registry->classes;
+ FT_Extension_Class* limit = cur + registry->num_extensions;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ char* ext = (char*)face->extensions + cur->offset;
+
+ if ( cur->finalize )
+ cur->finalize( ext, face );
+ }
+
+ memory = face->driver->root.memory;
+ FREE( face->extensions );
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Create_Extensions */
+ /* */
+ /* <Description> */
+ /* Creates an extension object within a face object for all */
+ /* registered extensions. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Called by the face object constructor. */
+ /* */
+ LOCAL_FUNC
+ FT_Error FT_Create_Extensions( FT_Face face )
+ {
+ FT_Extension_Registry* registry;
+ FT_Memory memory;
+ FT_Error error;
+
+
+ face->extensions = 0;
+
+ /* load extensions registry; exit successfully if none is there */
+
+ registry = (FT_Extension_Registry*)face->driver->extensions;
+ if ( !registry )
+ return FT_Err_Ok;
+
+ memory = face->driver->root.memory;
+ if ( ALLOC( face->extensions, registry->cur_offset ) )
+ return error;
+
+ {
+ FT_Extension_Class* cur = registry->classes;
+ FT_Extension_Class* limit = cur + registry->num_extensions;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ char* ext = (char*)face->extensions + cur->offset;
+
+ if ( cur->init )
+ {
+ error = cur->init( ext, face );
+ if ( error )
+ break;
+ }
+ }
+ }
+
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftglyph.c */
+/* */
+/* FreeType convenience functions to handle glyphs (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* This file contains the definition of several convenience functions */
+ /* that can be used by client applications to easily retrieve glyph */
+ /* bitmaps and outlines from a given face. */
+ /* */
+ /* These functions should be optional if you are writing a font server */
+ /* or text layout engine on top of FreeType. However, they are pretty */
+ /* handy for many other simple uses of the library. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/ftglyph.h>
+#include <freetype/ftoutln.h>
+#include <freetype/internal/ftobjs.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_glyph
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** Convenience functions ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Matrix_Multiply */
+ /* */
+ /* <Description> */
+ /* Performs the matrix operation `b = a*b'. */
+ /* */
+ /* <Input> */
+ /* a :: A pointer to matrix `a'. */
+ /* */
+ /* <InOut> */
+ /* b :: A pointer to matrix `b'. */
+ /* */
+ /* <MT-Note> */
+ /* Yes. */
+ /* */
+ /* <Note> */
+ /* The result is undefined if either `a' or `b' is zero. */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_Matrix_Multiply( FT_Matrix* a,
+ FT_Matrix* b )
+ {
+ FT_Fixed xx, xy, yx, yy;
+
+
+ if ( !a || !b )
+ return;
+
+ xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx );
+ xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy );
+ yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx );
+ yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy );
+
+ b->xx = xx; b->xy = xy;
+ b->yx = yx; b->yy = yy;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Matrix_Invert */
+ /* */
+ /* <Description> */
+ /* Inverts a 2x2 matrix. Returns an error if it can't be inverted. */
+ /* */
+ /* <InOut> */
+ /* matrix :: A pointer to the target matrix. Remains untouched in */
+ /* case of error. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <MT-Note> */
+ /* Yes. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Matrix_Invert( FT_Matrix* matrix )
+ {
+ FT_Pos delta, xx, yy;
+
+
+ if ( !matrix )
+ return FT_Err_Invalid_Argument;
+
+ /* compute discriminant */
+ delta = FT_MulFix( matrix->xx, matrix->yy ) -
+ FT_MulFix( matrix->xy, matrix->yx );
+
+ if ( !delta )
+ return FT_Err_Invalid_Argument; /* matrix can't be inverted */
+
+ matrix->xy = - FT_DivFix( matrix->xy, delta );
+ matrix->yx = - FT_DivFix( matrix->yx, delta );
+
+ xx = matrix->xx;
+ yy = matrix->yy;
+
+ matrix->xx = FT_DivFix( yy, delta );
+ matrix->yy = FT_DivFix( xx, delta );
+
+ return FT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** FT_BitmapGlyph support ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static
+ FT_Error ft_bitmap_copy( FT_Memory memory,
+ FT_Bitmap* source,
+ FT_Bitmap* target )
+ {
+ FT_Error error;
+ FT_Int pitch = source->pitch;
+ FT_ULong size;
+
+
+ *target = *source;
+
+ if ( pitch < 0 )
+ pitch = -pitch;
+
+ size = (FT_ULong)( pitch * source->rows );
+
+ if ( !ALLOC( target->buffer, size ) )
+ MEM_Copy( source->buffer, target->buffer, size );
+
+ return error;
+ }
+
+
+ static
+ FT_Error ft_bitmap_glyph_init( FT_BitmapGlyph glyph,
+ FT_GlyphSlot slot )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Library library = FT_GLYPH(glyph)->library;
+ FT_Memory memory = library->memory;
+
+
+ if ( slot->format != ft_glyph_format_bitmap )
+ {
+ error = FT_Err_Invalid_Glyph_Format;
+ goto Exit;
+ }
+
+ /* grab the bitmap in the slot - do lazy copying whenever possible */
+ glyph->bitmap = slot->bitmap;
+ glyph->left = slot->bitmap_left;
+ glyph->top = slot->bitmap_top;
+
+ if ( slot->flags & ft_glyph_own_bitmap )
+ slot->flags &= ~ft_glyph_own_bitmap;
+ else
+ {
+ /* copy the bitmap into a new buffer */
+ error = ft_bitmap_copy( memory, &slot->bitmap, &glyph->bitmap );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ FT_Error ft_bitmap_glyph_copy( FT_BitmapGlyph source,
+ FT_BitmapGlyph target )
+ {
+ FT_Memory memory = source->root.library->memory;
+
+
+ target->left = source->left;
+ target->top = source->top;
+
+ return ft_bitmap_copy( memory, &source->bitmap, &target->bitmap );
+ }
+
+
+ static
+ void ft_bitmap_glyph_done( FT_BitmapGlyph glyph )
+ {
+ FT_Memory memory = FT_GLYPH(glyph)->library->memory;
+
+
+ FREE( glyph->bitmap.buffer );
+ }
+
+
+ static
+ void ft_bitmap_glyph_bbox( FT_BitmapGlyph glyph,
+ FT_BBox* cbox )
+ {
+ cbox->xMin = glyph->left << 6;
+ cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 );
+ cbox->yMax = glyph->top << 6;
+ cbox->yMin = cbox->xMax - ( glyph->bitmap.rows << 6 );
+ }
+
+
+ const FT_Glyph_Class ft_bitmap_glyph_class =
+ {
+ sizeof( FT_BitmapGlyphRec ),
+ ft_glyph_format_bitmap,
+
+ (FT_Glyph_Init_Func) ft_bitmap_glyph_init,
+ (FT_Glyph_Done_Func) ft_bitmap_glyph_done,
+ (FT_Glyph_Copy_Func) ft_bitmap_glyph_copy,
+ (FT_Glyph_Transform_Func)0,
+ (FT_Glyph_BBox_Func) ft_bitmap_glyph_bbox,
+ (FT_Glyph_Prepare_Func) 0
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** FT_OutlineGlyph support ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static
+ FT_Error ft_outline_glyph_init( FT_OutlineGlyph glyph,
+ FT_GlyphSlot slot )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Library library = FT_GLYPH(glyph)->library;
+ FT_Outline* source = &slot->outline;
+ FT_Outline* target = &glyph->outline;
+
+
+ /* check format in glyph slot */
+ if ( slot->format != ft_glyph_format_outline )
+ {
+ error = FT_Err_Invalid_Glyph_Format;
+ goto Exit;
+ }
+
+ /* allocate new outline */
+ error = FT_Outline_New( library, source->n_points, source->n_contours,
+ &glyph->outline );
+ if ( error )
+ goto Exit;
+
+ /* copy it */
+ MEM_Copy( target->points, source->points,
+ source->n_points * sizeof ( FT_Vector ) );
+
+ MEM_Copy( target->tags, source->tags,
+ source->n_points * sizeof ( FT_Byte ) );
+
+ MEM_Copy( target->contours, source->contours,
+ source->n_contours * sizeof ( FT_Short ) );
+
+ /* copy all flags, except the `ft_outline_owner' one */
+ target->flags = source->flags | ft_outline_owner;
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ void ft_outline_glyph_done( FT_OutlineGlyph glyph )
+ {
+ FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );
+ }
+
+
+ static
+ FT_Error ft_outline_glyph_copy( FT_OutlineGlyph source,
+ FT_OutlineGlyph target )
+ {
+ FT_Error error;
+ FT_Library library = FT_GLYPH( source )->library;
+
+
+ error = FT_Outline_New( library, source->outline.n_points,
+ source->outline.n_contours, &target->outline );
+ if ( !error )
+ FT_Outline_Copy( &source->outline, &target->outline );
+
+ return error;
+ }
+
+
+ static
+ void ft_outline_glyph_transform( FT_OutlineGlyph glyph,
+ FT_Matrix* matrix,
+ FT_Vector* delta )
+ {
+ if ( matrix )
+ FT_Outline_Transform( &glyph->outline, matrix );
+
+ if ( delta )
+ FT_Outline_Translate( &glyph->outline, delta->x, delta->y );
+ }
+
+
+ static
+ void ft_outline_glyph_bbox( FT_OutlineGlyph glyph,
+ FT_BBox* bbox )
+ {
+ FT_Outline_Get_CBox( &glyph->outline, bbox );
+ }
+
+
+ static
+ FT_Error ft_outline_glyph_prepare( FT_OutlineGlyph glyph,
+ FT_GlyphSlot slot )
+ {
+ slot->format = ft_glyph_format_outline;
+ slot->outline = glyph->outline;
+ slot->outline.flags &= ~ft_outline_owner;
+
+ return FT_Err_Ok;
+ }
+
+
+ const FT_Glyph_Class ft_outline_glyph_class =
+ {
+ sizeof( FT_OutlineGlyphRec ),
+ ft_glyph_format_outline,
+
+ (FT_Glyph_Init_Func) ft_outline_glyph_init,
+ (FT_Glyph_Done_Func) ft_outline_glyph_done,
+ (FT_Glyph_Copy_Func) ft_outline_glyph_copy,
+ (FT_Glyph_Transform_Func)ft_outline_glyph_transform,
+ (FT_Glyph_BBox_Func) ft_outline_glyph_bbox,
+ (FT_Glyph_Prepare_Func) ft_outline_glyph_prepare
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** FT_Glyph class and API ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static
+ FT_Error ft_new_glyph( FT_Library library,
+ const FT_Glyph_Class* clazz,
+ FT_Glyph* aglyph )
+ {
+ FT_Memory memory = library->memory;
+ FT_Error error;
+ FT_Glyph glyph;
+
+
+ *aglyph = 0;
+
+ if ( !ALLOC( glyph, clazz->glyph_size ) )
+ {
+ glyph->library = library;
+ glyph->clazz = clazz;
+ glyph->format = clazz->glyph_format;
+
+ *aglyph = glyph;
+ }
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Glyph_Copy */
+ /* */
+ /* <Description> */
+ /* A function used to copy a glyph image. */
+ /* */
+ /* <Input> */
+ /* source :: A handle to the source glyph object. */
+ /* */
+ /* <Output> */
+ /* target :: A handle to the target glyph object. 0 in case of */
+ /* error. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Glyph_Copy( FT_Glyph source,
+ FT_Glyph* target )
+ {
+ FT_Glyph copy;
+ FT_Error error;
+ const FT_Glyph_Class* clazz;
+
+
+ /* check arguments */
+ if ( !target || !source || !source->clazz )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ *target = 0;
+
+ clazz = source->clazz;
+ error = ft_new_glyph( source->library, clazz, © );
+ if ( error )
+ goto Exit;
+
+ if ( clazz->glyph_copy )
+ error = clazz->glyph_copy( source, copy );
+
+ if ( error )
+ FT_Done_Glyph( copy );
+ else
+ *target = copy;
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Glyph */
+ /* */
+ /* <Description> */
+ /* A function used to extract a glyph image from a slot. */
+ /* */
+ /* <Input> */
+ /* slot :: A handle to the source glyph slot. */
+ /* */
+ /* <Output> */
+ /* aglyph :: A handle to the glyph object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Get_Glyph( FT_GlyphSlot slot,
+ FT_Glyph* aglyph )
+ {
+ FT_Library library = slot->library;
+ FT_Error error;
+ FT_Glyph glyph;
+
+ const FT_Glyph_Class* clazz = 0;
+
+
+ if ( !slot )
+ return FT_Err_Invalid_Slot_Handle;
+
+ if ( !aglyph )
+ return FT_Err_Invalid_Argument;
+
+ /* if it is a bitmap, that's easy :-) */
+ if ( slot->format == ft_glyph_format_bitmap )
+ clazz = &ft_bitmap_glyph_class;
+
+ /* it it is an outline too */
+ else if ( slot->format == ft_glyph_format_outline )
+ clazz = &ft_outline_glyph_class;
+
+ else
+ {
+ /* try to find a renderer that supports the glyph image format */
+ FT_Renderer render = FT_Lookup_Renderer( library, slot->format, 0 );
+
+
+ if ( render )
+ clazz = &render->glyph_class;
+ }
+
+ if ( !clazz )
+ {
+ error = FT_Err_Invalid_Glyph_Format;
+ goto Exit;
+ }
+
+ /* create FT_Glyph object */
+ error = ft_new_glyph( library, clazz, &glyph );
+ if ( error )
+ goto Exit;
+
+ /* copy advance while converting it to 16.16 format */
+ glyph->advance.x = slot->advance.x << 10;
+ glyph->advance.y = slot->advance.y << 10;
+
+ /* now import the image from the glyph slot */
+ error = clazz->glyph_init( glyph, slot );
+
+ /* if an error occurred, destroy the glyph */
+ if ( error )
+ FT_Done_Glyph( glyph );
+ else
+ *aglyph = glyph;
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Glyph_Transform */
+ /* */
+ /* <Description> */
+ /* Transforms a glyph image if its format is scalable. */
+ /* */
+ /* <Input> */
+ /* glyph :: A handle to the target glyph object. */
+ /* */
+ /* matrix :: A pointer to a 2x2 matrix to apply. */
+ /* */
+ /* delta :: A pointer to a 2d vector to apply. Coordinates are */
+ /* expressed in 1/64th of a pixel. */
+ /* */
+ /* <Return> */
+ /* FreeType error code (the glyph format is not scalable if it is */
+ /* not zero). */
+ /* */
+ /* <Note> */
+ /* The 2x2 transformation matrix is also applied to the glyph's */
+ /* advance vector. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Glyph_Transform( FT_Glyph glyph,
+ FT_Matrix* matrix,
+ FT_Vector* delta )
+ {
+ const FT_Glyph_Class* clazz;
+ FT_Error error = FT_Err_Ok;
+
+
+ if ( !glyph || !glyph->clazz )
+ error = FT_Err_Invalid_Argument;
+ else
+ {
+ clazz = glyph->clazz;
+ if ( clazz->glyph_transform )
+ {
+ /* transform glyph image */
+ clazz->glyph_transform( glyph, matrix, delta );
+
+ /* transform advance vector */
+ if ( matrix )
+ FT_Vector_Transform( &glyph->advance, matrix );
+ }
+ else
+ error = FT_Err_Invalid_Glyph_Format;
+ }
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Glyph_Get_CBox */
+ /* */
+ /* <Description> */
+ /* Returns the glyph image's bounding box. */
+ /* */
+ /* <Input> */
+ /* glyph :: A handle to the source glyph object. */
+ /* */
+ /* mode :: A set of bit flags that indicate how to interpret the */
+ /* returned bounding box values. */
+ /* */
+ /* <Output> */
+ /* box :: The glyph bounding box. Coordinates are expressed in */
+ /* 1/64th of pixels if it is grid-fitted. */
+ /* */
+ /* <Note> */
+ /* Coordinates are relative to the glyph origin, using the Y-upwards */
+ /* convention. */
+ /* */
+ /* If `ft_glyph_bbox_subpixels' is set in `mode', the bbox */
+ /* coordinates are returned in 26.6 pixels (i.e. 1/64th of pixels). */
+ /* Otherwise, coordinates are expressed in integer pixels. */
+ /* */
+ /* Note that the maximum coordinates are exclusive, which means that */
+ /* one can compute the width and height of the glyph image (be it in */
+ /* integer or 26.6 pixels) as: */
+ /* */
+ /* width = bbox.xMax - bbox.xMin; */
+ /* height = bbox.yMax - bbox.yMin; */
+ /* */
+ /* Note also that for 26.6 coordinates, if the */
+ /* `ft_glyph_bbox_gridfit' flag is set in `mode;, the coordinates */
+ /* will also be grid-fitted, which corresponds to: */
+ /* */
+ /* bbox.xMin = FLOOR(bbox.xMin); */
+ /* bbox.yMin = FLOOR(bbox.yMin); */
+ /* bbox.xMax = CEILING(bbox.xMax); */
+ /* bbox.yMax = CEILING(bbox.yMax); */
+ /* */
+ /* The default value (0) for `bbox_mode' is `ft_glyph_bbox_pixels'. */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_Glyph_Get_CBox( FT_Glyph glyph,
+ FT_UInt bbox_mode,
+ FT_BBox* cbox )
+ {
+ const FT_Glyph_Class* clazz;
+ FT_Error error = FT_Err_Ok;
+
+
+ if ( !cbox || !glyph || !glyph->clazz )
+ error = FT_Err_Invalid_Argument;
+ else
+ {
+ clazz = glyph->clazz;
+ if ( !clazz->glyph_bbox )
+ error = FT_Err_Invalid_Glyph_Format;
+ else
+ {
+ /* retrieve bbox in 26.6 coordinates */
+ clazz->glyph_bbox( glyph, cbox );
+
+ /* perform grid fitting if needed */
+ if ( bbox_mode & ft_glyph_bbox_gridfit )
+ {
+ cbox->xMin &= -64;
+ cbox->yMin &= -64;
+ cbox->xMax = ( cbox->xMax + 63 ) & -64;
+ cbox->yMax = ( cbox->yMax + 63 ) & -64;
+ }
+
+ /* convert to integer pixels if needed */
+ if ( !( bbox_mode & ft_glyph_bbox_subpixels ) )
+ {
+ cbox->xMin >>= 6;
+ cbox->yMin >>= 6;
+ cbox->xMax >>= 6;
+ cbox->yMax >>= 6;
+ }
+ }
+ }
+ return;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Glyph_To_Bitmap */
+ /* */
+ /* <Description> */
+ /* Converts a given glyph object to a bitmap glyph object. */
+ /* */
+ /* <InOut> */
+ /* glyph :: A pointer to a handle to the target glyph. */
+ /* */
+ /* <Input> */
+ /* render_mode :: A set of bit flags that describe how the data is */
+ /* */
+ /* */
+ /* origin :: A pointer to a vector used to translate the glyph */
+ /* image before rendering. Can be 0 (if no */
+ /* translation). The origin is expressed in */
+ /* 26.6 pixels. */
+ /* */
+ /* destroy :: A boolean that indicates that the original glyph */
+ /* image should be destroyed by this function. It is */
+ /* never destroyed in case of error. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The glyph image is translated with the `origin' vector before */
+ /* rendering. In case of error, it it translated back to its */
+ /* original position and the glyph is left untouched. */
+ /* */
+ /* The first parameter is a pointer to a FT_Glyph handle, that will */
+ /* be replaced by this function. Typically, you would use (omitting */
+ /* error handling): */
+ /* */
+ /* */
+ /* { */
+ /* FT_Glyph glyph; */
+ /* FT_BitmapGlyph glyph_bitmap; */
+ /* */
+ /* */
+ /* // load glyph */
+ /* error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT ); */
+ /* */
+ /* // extract glyph image */
+ /* error = FT_Get_Glyph( face->glyph, &glyph ); */
+ /* */
+ /* // convert to a bitmap (default render mode + destroy old) */
+ /* if ( glyph->format != ft_glyph_format_bitmap ) */
+ /* { */
+ /* error = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_default, */
+ /* 0, 1 ); */
+ /* if ( error ) // glyph unchanged */
+ /* ... */
+ /* } */
+ /* */
+ /* // access bitmap content by typecasting */
+ /* glyph_bitmap = (FT_BitmapGlyph)glyph; */
+ /* */
+ /* // do funny stuff with it, like blitting/drawing */
+ /* ... */
+ /* */
+ /* // discard glyph image (bitmap or not) */
+ /* FT_Done_Glyph( glyph ); */
+ /* } */
+ /* */
+ /* */
+ /* This function will always fail if the glyph's format isn't */
+ /* scalable. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Glyph_To_Bitmap( FT_Glyph* the_glyph,
+ FT_ULong render_mode,
+ FT_Vector* origin,
+ FT_Bool destroy )
+ {
+ FT_GlyphSlotRec dummy;
+ FT_Error error;
+ FT_Glyph glyph;
+ FT_BitmapGlyph bitmap;
+
+ const FT_Glyph_Class* clazz;
+
+
+ /* check argument */
+ if ( !the_glyph )
+ goto Bad;
+
+ /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
+ /* then calling FT_Render_Glyph_Internal() */
+
+ glyph = *the_glyph;
+ if ( !glyph )
+ goto Bad;
+
+ clazz = glyph->clazz;
+ if ( !clazz || !clazz->glyph_prepare )
+ goto Bad;
+
+ MEM_Set( &dummy, 0, sizeof ( dummy ) );
+ dummy.library = glyph->library;
+ dummy.format = clazz->glyph_format;
+
+ /* if `origin' is set, translate the glyph image */
+ if ( origin )
+ FT_Glyph_Transform( glyph, 0, origin );
+
+ /* create result bitmap glyph */
+ error = ft_new_glyph( glyph->library, &ft_bitmap_glyph_class,
+ (FT_Glyph*)&bitmap );
+ if ( error )
+ goto Exit;
+
+ /* prepare dummy slot for rendering */
+ error = clazz->glyph_prepare( glyph, &dummy ) ||
+ FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
+
+ if ( !destroy && origin )
+ {
+ FT_Vector v;
+
+
+ v.x = -origin->x;
+ v.y = -origin->y;
+ FT_Glyph_Transform( glyph, 0, &v );
+ }
+
+ /* in case of succes, copy the bitmap to the glyph bitmap */
+ if ( !error )
+ {
+ error = ft_bitmap_glyph_init( bitmap, &dummy );
+ if ( error )
+ {
+ /* this should never happen, but let's be safe */
+ FT_Done_Glyph( FT_GLYPH( bitmap ) );
+ goto Exit;
+ }
+
+ if ( destroy )
+ FT_Done_Glyph( glyph );
+
+ *the_glyph = FT_GLYPH( bitmap );
+ }
+
+ Exit:
+ return error;
+
+ Bad:
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_Glyph */
+ /* */
+ /* <Description> */
+ /* Destroys a given glyph. */
+ /* */
+ /* <Input> */
+ /* glyph :: A handle to the target glyph object. */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_Done_Glyph( FT_Glyph glyph )
+ {
+ if ( glyph )
+ {
+ FT_Memory memory = glyph->library->memory;
+ const FT_Glyph_Class* clazz = glyph->clazz;
+
+
+ if ( clazz->glyph_done )
+ clazz->glyph_done( glyph );
+
+ FREE( glyph );
+ }
+ }
+
+
+#if 0
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* Compute the norm of a vector */
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+ static
+ FT_Pos ft_norm( FT_Vector* vec )
+ {
+ FT_Int64 t1, t2;
+
+
+ MUL_64( vec->x, vec->x, t1 );
+ MUL_64( vec->y, vec->y, t2 );
+ ADD_64( t1, t2, t1 );
+
+ return (FT_Pos)SQRT_64( t1 );
+ }
+
+#else /* FT_CONFIG_OPTION_OLD_CALCS */
+
+ static
+ FT_Pos ft_norm( FT_Vector* vec )
+ {
+ FT_F26Dot6 u, v, d;
+ FT_Int shift;
+ FT_ULong H, L, L2, hi, lo, med;
+
+
+ u = vec->x; if ( u < 0 ) u = -u;
+ v = vec->y; if ( v < 0 ) v = -v;
+
+ if ( u < v )
+ {
+ d = u;
+ u = v;
+ v = d;
+ }
+
+ /* check that we are not trying to normalize zero! */
+ if ( u == 0 )
+ return 0;
+
+ /* compute (u*u + v*v) on 64 bits with two 32-bit registers [H:L] */
+ hi = (FT_ULong)u >> 16;
+ lo = (FT_ULong)u & 0xFFFF;
+ med = hi * lo;
+
+ H = hi * hi + ( med >> 15 );
+ med <<= 17;
+ L = lo * lo + med;
+ if ( L < med )
+ H++;
+
+ hi = (FT_ULong)v >> 16;
+ lo = (FT_ULong)v & 0xFFFF;
+ med = hi * lo;
+
+ H += hi * hi + ( med >> 15 );
+ med <<= 17;
+ L2 = lo * lo + med;
+ if ( L2 < med )
+ H++;
+
+ L += L2;
+ if ( L < L2 )
+ H++;
+
+ /* if the value is smaller than 32 bits */
+ shift = 0;
+ if ( H == 0 )
+ {
+ while ( ( L & 0xC0000000UL ) == 0 )
+ {
+ L <<= 2;
+ shift++;
+ }
+ return ( FT_Sqrt32( L ) >> shift );
+ }
+ else
+ {
+ while ( H )
+ {
+ L = ( L >> 2 ) | ( H << 30 );
+ H >>= 2;
+ shift++;
+ }
+ return ( FT_Sqrt32( L ) << shift );
+ }
+ }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+ static
+ int ft_test_extrema( FT_Outline* outline,
+ int n )
+ {
+ FT_Vector *prev, *cur, *next;
+ FT_Pos product;
+ FT_Int first, last;
+
+
+ /* we need to compute the `previous' and `next' point */
+ /* for these extrema. */
+ cur = outline->points + n;
+ prev = cur - 1;
+ next = cur + 1;
+
+ first = 0;
+ for ( c = 0; c < outline->n_contours; c++ )
+ {
+ last = outline->contours[c];
+
+ if ( n == first )
+ prev = outline->points + last;
+
+ if ( n == last )
+ next = outline->points + first;
+
+ first = last + 1;
+ }
+
+ product = FT_MulDiv( cur->x - prev->x, /* in.x */
+ next->y - cur->y, /* out.y */
+ 0x40 )
+ -
+ FT_MulDiv( cur->y - prev->y, /* in.y */
+ next->x - cur->x, /* out.x */
+ 0x40 );
+
+ if ( product )
+ product = product > 0 ? 1 : -1;
+
+ return product;
+ }
+
+
+ /* Compute the orientation of path filling. It differs between TrueType */
+ /* and Type1 formats. We could use the `ft_outline_reverse_fill' flag, */
+ /* but it is better to re-compute it directly (it seems that this flag */
+ /* isn't correctly set for some weird composite glyphs currently). */
+ /* */
+ /* We do this by computing bounding box points, and computing their */
+ /* curvature. */
+ /* */
+ /* The function returns either 1 or -1. */
+ /* */
+ static
+ int ft_get_orientation( FT_Outline* outline )
+ {
+ FT_BBox box;
+ FT_BBox indices;
+ int n, last;
+
+
+ indices.xMin = -1;
+ indices.yMin = -1;
+ indices.xMax = -1;
+ indices.yMax = -1;
+
+ box.xMin = box.yMin = 32767;
+ box.xMax = box.yMax = -32768;
+
+ /* is it empty ? */
+ if ( outline->n_contours < 1 )
+ return 1;
+
+ last = outline->contours[outline->n_contours - 1];
+
+ for ( n = 0; n <= last; n++ )
+ {
+ FT_Pos x, y;
+
+
+ x = outline->points[n].x;
+ if ( x < box.xMin )
+ {
+ box.xMin = x;
+ indices.xMin = n;
+ }
+ if ( x > box.xMax )
+ {
+ box.xMax = x;
+ indices.xMax = n;
+ }
+
+ y = outline->points[n].y;
+ if ( y < box.yMin )
+ {
+ box.yMin = y;
+ indices.yMin = n;
+ }
+ if ( y > box.yMax )
+ {
+ box.yMax = y;
+ indices.yMax = n;
+ }
+ }
+
+ /* test orientation of the xmin */
+ return ft_test_extrema( outline, indices.xMin ) ||
+ ft_test_extrema( outline, indices.yMin ) ||
+ ft_test_extrema( outline, indices.xMax ) ||
+ ft_test_extrema( outline, indices.yMax ) ||
+ 1; /* this is an empty glyph? */
+ }
+
+
+ static
+ FT_Error ft_embolden( FT_Face original,
+ FT_Outline* outline,
+ FT_Pos* advance )
+ {
+ FT_Vector u, v;
+ FT_Vector* points;
+ FT_Vector cur, prev, next;
+ FT_Pos distance;
+ int c, n, first, orientation;
+
+ FT_UNUSED( advance );
+
+
+ /* compute control distance */
+ distance = FT_MulFix( original->em_size / 60,
+ original->size->metrics.y_scale );
+
+ orientation = ft_get_orientation( &original->glyph->outline );
+
+ points = original->glyph->outline.points;
+
+ first = 0;
+ for ( c = 0; c < outline->n_contours; c++ )
+ {
+ int last = outline->contours[c];
+
+
+ prev = points[last];
+
+ for ( n = first; n <= last; n++ )
+ {
+ FT_Pos norm, delta, d;
+ FT_Vector in, out;
+
+
+ cur = points[n];
+ if ( n < last ) next = points[n + 1];
+ else next = points[first];
+
+ /* compute the in and out vectors */
+ in.x = cur.x - prev.x;
+ in.y = cur.y - prev.y;
+
+ out.x = next.x - cur.x;
+ out.y = next.y - cur.y;
+
+ /* compute U and V */
+ norm = ft_norm( &in );
+ u.x = orientation * FT_DivFix( in.y, norm );
+ u.y = orientation * -FT_DivFix( in.x, norm );
+
+ norm = ft_norm( &out );
+ v.x = orientation * FT_DivFix( out.y, norm );
+ v.y = orientation * -FT_DivFix( out.x, norm );
+
+ d = distance;
+
+ if ( ( outline->flags[n] & FT_Curve_Tag_On ) == 0 )
+ d *= 2;
+
+ /* Check discriminant for parallel vectors */
+ delta = FT_MulFix( u.x, v.y ) - FT_MulFix( u.y, v.x );
+ if ( delta > FT_BOLD_THRESHOLD || delta < -FT_BOLD_THRESHOLD )
+ {
+ /* Move point -- compute A and B */
+ FT_Pos x, y, A, B;
+
+
+ A = d + FT_MulFix( cur.x, u.x ) + FT_MulFix( cur.y, u.y );
+ B = d + FT_MulFix( cur.x, v.x ) + FT_MulFix( cur.y, v.y );
+
+ x = FT_MulFix( A, v.y ) - FT_MulFix( B, u.y );
+ y = FT_MulFix( B, u.x ) - FT_MulFix( A, v.x );
+
+ outline->points[n].x = distance + FT_DivFix( x, delta );
+ outline->points[n].y = distance + FT_DivFix( y, delta );
+ }
+ else
+ {
+ /* Vectors are nearly parallel */
+ FT_Pos x, y;
+
+
+ x = distance + cur.x + FT_MulFix( d, u.x + v.x ) / 2;
+ y = distance + cur.y + FT_MulFix( d, u.y + v.y ) / 2;
+
+ outline->points[n].x = x;
+ outline->points[n].y = y;
+ }
+
+ prev = cur;
+ }
+
+ first = last + 1;
+ }
+
+ if ( advance )
+ *advance = ( *advance + distance * 4 ) & -64;
+
+ return 0;
+ }
+
+#endif /* 0 -- EXPERIMENTAL STUFF! */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftinit.c */
+/* */
+/* FreeType initialization layer (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* The purpose of this file is to implement the following two */
+ /* functions: */
+ /* */
+ /* FT_Add_Default_Modules(): */
+ /* This function is used to add the set of default modules to a */
+ /* fresh new library object. The set is taken from the header file */
+ /* `freetype/config/ftmodule.h'. See the document `FreeType 2.0 */
+ /* Build System' for more information. */
+ /* */
+ /* FT_Init_FreeType(): */
+ /* This function creates a system object for the current platform, */
+ /* builds a library out of it, then calls FT_Default_Drivers(). */
+ /* */
+ /* Note that even if FT_Init_FreeType() uses the implementation of the */
+ /* system object defined at build time, client applications are still */
+ /* able to provide their own `ftsystem.c'. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/ftmodule.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_init
+
+#undef FT_USE_MODULE
+#define FT_USE_MODULE( x ) extern const FT_Module_Class* x;
+
+#ifdef macintosh
+ FT_USE_MODULE(fond_driver_class)
+#endif
+#include <freetype/config/ftmodule.h>
+
+#undef FT_USE_MODULE
+#define FT_USE_MODULE( x ) (const FT_Module_Class*)&x,
+
+static
+const FT_Module_Class* ft_default_modules[] =
+ {
+#ifdef macintosh
+ FT_USE_MODULE(fond_driver_class)
+#endif
+#include <freetype/config/ftmodule.h>
+ 0
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* <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_FUNC( void ) FT_Add_Default_Modules( FT_Library library )
+ {
+ FT_Error error;
+ const FT_Module_Class** cur;
+
+
+ /* test for valid `library' delayed to FT_Add_Module() */
+
+ cur = ft_default_modules;
+ while ( *cur )
+ {
+ error = FT_Add_Module( library, *cur );
+ /* notify errors, but don't stop */
+ if ( error )
+ {
+ FT_ERROR(( "FT_Add_Default_Module: Cannot install `%s', error = %x\n",
+ (*cur)->module_name, error ));
+ }
+ cur++;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Init_FreeType */
+ /* */
+ /* <Description> */
+ /* Initializes a new FreeType library object. The set of drivers */
+ /* that are registered by this function is determined at build time. */
+ /* */
+ /* <Output> */
+ /* library :: A handle to a new library object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Init_FreeType( FT_Library* library )
+ {
+ FT_Error error;
+ FT_Memory memory;
+
+
+ /* First of all, allocate a new system object -- this function is part */
+ /* of the system-specific component, i.e. `ftsystem.c'. */
+
+ memory = FT_New_Memory();
+ if ( !memory )
+ {
+ FT_ERROR(( "FT_Init_FreeType: cannot find memory manager\n" ));
+ return FT_Err_Unimplemented_Feature;
+ }
+
+ /* build a library out of it, then fill it with the set of */
+ /* default drivers. */
+
+ error = FT_New_Library( memory, library );
+ if ( !error )
+ FT_Add_Default_Modules( *library );
+
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftlist.c */
+/* */
+/* Generic list support for FreeType (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* This file implements functions relative to list processing. Its */
+ /* data structures are defined in `freetype/internal/ftlist.h'. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/internal/ftlist.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftobjs.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_list
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_List_Find */
+ /* */
+ /* <Description> */
+ /* Finds the list node for a given listed object. */
+ /* */
+ /* <Input> */
+ /* list :: A pointer to the parent list. */
+ /* data :: The address of the listed object. */
+ /* */
+ /* <Return> */
+ /* List node. NULL if it wasn't found. */
+ /* */
+ BASE_FUNC( FT_ListNode ) FT_List_Find( FT_List list,
+ void* data )
+ {
+ FT_ListNode cur;
+
+
+ cur = list->head;
+ while ( cur )
+ {
+ if ( cur->data == data )
+ return cur;
+
+ cur = cur->next;
+ }
+
+ return (FT_ListNode)0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_List_Add */
+ /* */
+ /* <Description> */
+ /* Appends an element to the end of a list. */
+ /* */
+ /* <InOut> */
+ /* list :: A pointer to the parent list. */
+ /* node :: The node to append. */
+ /* */
+ BASE_FUNC( void ) FT_List_Add( FT_List list,
+ FT_ListNode node )
+ {
+ FT_ListNode before = list->tail;
+
+
+ node->next = 0;
+ node->prev = before;
+
+ if ( before )
+ before->next = node;
+ else
+ list->head = node;
+
+ list->tail = node;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_List_Insert */
+ /* */
+ /* <Description> */
+ /* Inserts an element at the head of a list. */
+ /* */
+ /* <InOut> */
+ /* list :: A pointer to parent list. */
+ /* node :: The node to insert. */
+ /* */
+ BASE_FUNC( void ) FT_List_Insert( FT_List list,
+ FT_ListNode node )
+ {
+ FT_ListNode after = list->head;
+
+
+ node->next = after;
+ node->prev = 0;
+
+ if ( !after )
+ list->tail = node;
+ else
+ after->prev = node;
+
+ list->head = node;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_List_Remove */
+ /* */
+ /* <Description> */
+ /* Removes a node from a list. This function doesn't check whether */
+ /* the node is in the list! */
+ /* */
+ /* <Input> */
+ /* node :: The node to remove. */
+ /* */
+ /* <InOut> */
+ /* list :: A pointer to the parent list. */
+ /* */
+ BASE_FUNC( void ) FT_List_Remove( FT_List list,
+ FT_ListNode node )
+ {
+ FT_ListNode before, after;
+
+
+ before = node->prev;
+ after = node->next;
+
+ if ( before )
+ before->next = after;
+ else
+ list->head = after;
+
+ if ( after )
+ after->prev = before;
+ else
+ list->tail = before;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_List_Up */
+ /* */
+ /* <Description> */
+ /* Moves a node to the head/top of a list. Used to maintain LRU */
+ /* lists. */
+ /* */
+ /* <InOut> */
+ /* list :: A pointer to the parent list. */
+ /* node :: The node to move. */
+ /* */
+ BASE_FUNC( void ) FT_List_Up( FT_List list,
+ FT_ListNode node )
+ {
+ FT_ListNode before, after;
+
+
+ before = node->prev;
+ after = node->next;
+
+ /* check whether we are already on top of the list */
+ if ( !before )
+ return;
+
+ before->next = after;
+
+ if ( after )
+ after->prev = before;
+ else
+ list->tail = before;
+
+ node->prev = 0;
+ node->next = list->head;
+ list->head->prev = node;
+ list->head = node;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_List_Iterate */
+ /* */
+ /* <Description> */
+ /* Parses a list and calls a given iterator function on each element. */
+ /* Note that parsing is stopped as soon as one of the iterator calls */
+ /* returns a non-zero value. */
+ /* */
+ /* <Input> */
+ /* list :: A handle to the list. */
+ /* iterator :: An interator function, called on each node of the */
+ /* list. */
+ /* user :: A user-supplied field which is passed as the second */
+ /* argument to the iterator. */
+ /* */
+ /* <Return> */
+ /* The result (a FreeType error code) of the last iterator call. */
+ /* */
+ BASE_FUNC( FT_Error ) FT_List_Iterate( FT_List list,
+ FT_List_Iterator iterator,
+ void* user )
+ {
+ FT_ListNode cur = list->head;
+ FT_Error error = FT_Err_Ok;
+
+
+ while ( cur )
+ {
+ FT_ListNode next = cur->next;
+
+
+ error = iterator( cur, user );
+ if ( error )
+ break;
+
+ cur = next;
+ }
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_List_Finalize */
+ /* */
+ /* <Description> */
+ /* Destroys all elements in the list as well as the list itself. */
+ /* */
+ /* <Input> */
+ /* list :: A handle to the list. */
+ /* */
+ /* destroy :: A list destructor that will be applied to each element */
+ /* of the list. */
+ /* */
+ /* memory :: The current memory object which handles deallocation. */
+ /* */
+ /* user :: A user-supplied field which is passed as the last */
+ /* argument to the destructor. */
+ /* */
+ BASE_FUNC( void ) FT_List_Finalize( FT_List list,
+ FT_List_Destructor destroy,
+ FT_Memory memory,
+ void* user )
+ {
+ FT_ListNode cur;
+
+
+ cur = list->head;
+ while ( cur )
+ {
+ FT_ListNode next = cur->next;
+ void* data = cur->data;
+
+
+ if ( destroy )
+ destroy( memory, data, user );
+
+ FREE( cur );
+ cur = next;
+ }
+
+ list->head = 0;
+ list->tail = 0;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftmm.c */
+/* */
+/* Multiple Master font support (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/ftmm.h>
+#include <freetype/internal/ftobjs.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_mm
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Multi_Master */
+ /* */
+ /* <Description> */
+ /* Retrieves the Multiple Master descriptor of a given font. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face. */
+ /* */
+ /* <Output> */
+ /* master :: The Multiple Masters descriptor. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Get_Multi_Master( FT_Face face,
+ FT_Multi_Master* master )
+ {
+ FT_Error error;
+
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ error = FT_Err_Invalid_Argument;
+
+ if ( FT_HAS_MULTIPLE_MASTERS( face ) )
+ {
+ FT_Driver driver = face->driver;
+ FT_Get_MM_Func func;
+
+
+ func = (FT_Get_MM_Func)driver->root.clazz->get_interface(
+ FT_MODULE( driver ), "get_mm" );
+ if ( func )
+ error = func( face, master );
+ }
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_MM_Design_Coordinates */
+ /* */
+ /* <Description> */
+ /* For Multiple Masters fonts, choose an interpolated font design */
+ /* through design coordinates. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face. */
+ /* */
+ /* num_coords :: The number of design coordinates (must be equal to */
+ /* the number of axes in the font). */
+ /* */
+ /* coords :: The design coordinates. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Set_MM_Design_Coordinates(
+ FT_Face face,
+ FT_UInt num_coords,
+ FT_Long* coords )
+ {
+ FT_Error error;
+
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ error = FT_Err_Invalid_Argument;
+
+ if ( FT_HAS_MULTIPLE_MASTERS( face ) )
+ {
+ FT_Driver driver = face->driver;
+ FT_Set_MM_Design_Func func;
+
+
+ func = (FT_Set_MM_Design_Func)driver->root.clazz->get_interface(
+ FT_MODULE( driver ), "set_mm_design" );
+ if ( func )
+ error = func( face, num_coords, coords );
+ }
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_MM_Blend_Coordinates */
+ /* */
+ /* <Description> */
+ /* For Multiple Masters fonts, choose an interpolated font design */
+ /* through normalized blend coordinates. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face. */
+ /* */
+ /* num_coords :: The number of design coordinates (must be equal to */
+ /* the number of axes in the font). */
+ /* */
+ /* coords :: The design coordinates (each one must be between 0 */
+ /* and 1.0). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Set_MM_Blend_Coordinates(
+ FT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ FT_Error error;
+
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ error = FT_Err_Invalid_Argument;
+
+ if ( FT_HAS_MULTIPLE_MASTERS( face ) )
+ {
+ FT_Driver driver = face->driver;
+ FT_Set_MM_Blend_Func func;
+
+
+ func = (FT_Set_MM_Blend_Func)driver->root.clazz->get_interface(
+ FT_MODULE( driver ), "set_mm_blend" );
+ if ( func )
+ error = func( face, num_coords, coords );
+ }
+
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftnames.c */
+/* */
+/* Simple interface to access SFNT name tables (which are used */
+/* to hold font names, copyright info, notices, etc.). */
+/* */
+/* This is _not_ used to retrieve glyph names! */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/ftnames.h>
+#include <freetype/internal/tttypes.h>
+
+
+#ifdef FT_CONFIG_OPTION_SFNT_NAMES
+
+
+ FT_EXPORT_FUNC( FT_UInt ) FT_Get_Sfnt_Name_Count( FT_Face face )
+ {
+ return face && ( FT_IS_SFNT( face ) ? ((TT_Face)face)->num_names : 0 );
+ }
+
+
+ FT_EXPORT_FUNC( FT_Error ) FT_Get_Sfnt_Name( FT_Face face,
+ FT_UInt index,
+ FT_SfntName* aname )
+ {
+ FT_Error error = FT_Err_Invalid_Argument;
+
+
+ if ( aname && face && FT_IS_SFNT( face ) )
+ {
+ TT_Face ttface = (TT_Face)face;
+
+
+ if ( index < ttface->num_names )
+ {
+ TT_NameRec* name = ttface->name_table.names + index;
+
+
+ aname->platform_id = name->platformID;
+ aname->encoding_id = name->encodingID;
+ aname->language_id = name->languageID;
+ aname->name_id = name->nameID;
+ aname->string = (FT_Byte*)name->string;
+ aname->string_len = name->stringLength;
+
+ error = FT_Err_Ok;
+ }
+ }
+
+ return error;
+ }
+
+
+#endif /* FT_CONFIG_OPTION_SFNT_NAMES */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftobjs.c */
+/* */
+/* The FreeType private base classes (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftlist.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+
+#include <freetype/tttables.h>
+
+#include <string.h> /* for strcmp() */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** M E M O R Y ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_memory
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Alloc */
+ /* */
+ /* <Description> */
+ /* Allocates a new block of memory. The returned area is always */
+ /* zero-filled; this is a strong convention in many FreeType parts. */
+ /* */
+ /* <Input> */
+ /* memory :: A handle to a given `memory object' which handles */
+ /* allocation. */
+ /* */
+ /* size :: The size in bytes of the block to allocate. */
+ /* */
+ /* <Output> */
+ /* P :: A pointer to the fresh new block. It should be set to */
+ /* NULL if `size' is 0, or in case of error. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ BASE_FUNC( FT_Error ) FT_Alloc( FT_Memory memory,
+ FT_Long size,
+ void** P )
+ {
+ FT_Assert( P != 0 );
+
+ if ( size > 0 )
+ {
+ *P = memory->alloc( memory, size );
+ if ( !*P )
+ {
+ FT_ERROR(( "FT_Alloc:" ));
+ FT_ERROR(( " Out of memory? (%ld requested)\n",
+ size ));
+
+ return FT_Err_Out_Of_Memory;
+ }
+ MEM_Set( *P, 0, size );
+ }
+ else
+ *P = NULL;
+
+ FT_TRACE7(( "FT_Alloc:" ));
+ FT_TRACE7(( " size = %ld, block = 0x%08p, ref = 0x%08p\n",
+ size, *P, P ));
+
+ return FT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Realloc */
+ /* */
+ /* <Description> */
+ /* Reallocates a block of memory pointed to by `*P' to `Size' bytes */
+ /* from the heap, possibly changing `*P'. */
+ /* */
+ /* <Input> */
+ /* memory :: A handle to a given `memory object' which handles */
+ /* reallocation. */
+ /* */
+ /* current :: The current block size in bytes. */
+ /* */
+ /* size :: The new block size in bytes. */
+ /* */
+ /* <InOut> */
+ /* P :: A pointer to the fresh new block. It should be set to */
+ /* NULL if `size' is 0, or in case of error. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* All callers of FT_Realloc() _must_ provide the current block size */
+ /* as well as the new one. */
+ /* */
+ BASE_FUNC( FT_Error ) FT_Realloc( FT_Memory memory,
+ FT_Long current,
+ FT_Long size,
+ void** P )
+ {
+ void* Q;
+
+
+ FT_Assert( P != 0 );
+
+ /* if the original pointer is NULL, call FT_Alloc() */
+ if ( !*P )
+ return FT_Alloc( memory, size, P );
+
+ /* if the new block if zero-sized, clear the current one */
+ if ( size <= 0 )
+ {
+ FT_Free( memory, P );
+ return FT_Err_Ok;
+ }
+
+ Q = memory->realloc( memory, current, size, *P );
+ if ( !Q )
+ goto Fail;
+
+ *P = Q;
+ return FT_Err_Ok;
+
+ Fail:
+ FT_ERROR(( "FT_Realloc:" ));
+ FT_ERROR(( " Failed (current %ld, requested %ld)\n",
+ current, size ));
+ return FT_Err_Out_Of_Memory;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Free */
+ /* */
+ /* <Description> */
+ /* Releases a given block of memory allocated through FT_Alloc(). */
+ /* */
+ /* <Input> */
+ /* memory :: A handle to a given `memory object' which handles */
+ /* memory deallocation */
+ /* */
+ /* P :: This is the _address_ of a _pointer_ which points to the */
+ /* allocated block. It is always set to NULL on exit. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* If P or *P are NULL, this function should return successfully. */
+ /* This is a strong convention within all of FreeType and its */
+ /* drivers. */
+ /* */
+ BASE_FUNC( void ) FT_Free( FT_Memory memory,
+ void** P )
+ {
+ FT_TRACE7(( "FT_Free:" ));
+ FT_TRACE7(( " Freeing block 0x%08p, ref 0x%08p\n",
+ P, P ? *P : (void*)0 ));
+
+ if ( P && *P )
+ {
+ memory->free( memory, *P );
+ *P = 0;
+ }
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** S T R E A M ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_new_input_stream */
+ /* */
+ /* <Description> */
+ /* Creates a new input stream object from an FT_Open_Args structure. */
+ /* */
+ /* <Note> */
+ /* The function expects a valid `astream' parameter. */
+ /* */
+ static
+ FT_Error ft_new_input_stream( FT_Library library,
+ FT_Open_Args* args,
+ FT_Stream* astream )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FT_Stream stream;
+
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ if ( !args )
+ return FT_Err_Invalid_Argument;
+
+ *astream = 0;
+ memory = library->memory;
+ if ( ALLOC( stream, sizeof ( *stream ) ) )
+ goto Exit;
+
+ stream->memory = memory;
+
+ /* now, look at the stream flags */
+ if ( args->flags & ft_open_memory )
+ {
+ error = 0;
+ FT_New_Memory_Stream( library,
+ args->memory_base,
+ args->memory_size,
+ stream );
+ }
+ else if ( args->flags & ft_open_pathname )
+ {
+ error = FT_New_Stream( args->pathname, stream );
+ stream->pathname.pointer = args->pathname;
+ }
+ else if ( args->flags & ft_open_stream && args->stream )
+ {
+ *stream = *(args->stream);
+ stream->memory = memory;
+ }
+ else
+ error = FT_Err_Invalid_Argument;
+
+ if ( error )
+ FREE( stream );
+
+ *astream = stream;
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_Stream */
+ /* */
+ /* <Description> */
+ /* Closes and destroys a stream object. */
+ /* */
+ /* <Input> */
+ /* stream :: The stream to be closed and destroyed. */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_Done_Stream( FT_Stream stream )
+ {
+ if ( stream && stream->close )
+ stream->close( stream );
+ }
+
+
+ static
+ void ft_done_stream( FT_Stream* astream )
+ {
+ FT_Stream stream = *astream;
+ FT_Memory memory = stream->memory;
+
+
+ if ( stream->close )
+ stream->close( stream );
+
+ FREE( stream );
+ *astream = 0;
+ }
+
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_objs
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** G L Y P H L O A D E R ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* The glyph loader is a simple object which is used to load a set of */
+ /* glyphs easily. It is critical for the correct loading of composites. */
+ /* */
+ /* Ideally, one can see it as a stack of abstract `glyph' objects. */
+ /* */
+ /* loader.base Is really the bottom of the stack. It describes a */
+ /* single glyph image made of the juxtaposition of */
+ /* several glyphs (those `in the stack'). */
+ /* */
+ /* loader.current Describes the top of the stack, on which a new */
+ /* glyph can be loaded. */
+ /* */
+ /* Rewind Clears the stack. */
+ /* Prepare Set up `loader.current' for addition of a new glyph */
+ /* image. */
+ /* Add Add the `current' glyph image to the `base' one, */
+ /* and prepare for another one. */
+ /* */
+ /* The glyph loader is now a base object. Each driver used to */
+ /* re-implement it in one way or the other, which wasted code and */
+ /* energy. */
+ /* */
+ /*************************************************************************/
+
+
+ /* create a new glyph loader */
+ BASE_FUNC( FT_Error ) FT_GlyphLoader_New( FT_Memory memory,
+ FT_GlyphLoader** aloader )
+ {
+ FT_GlyphLoader* loader;
+ FT_Error error;
+
+
+ if ( !ALLOC( loader, sizeof ( *loader ) ) )
+ {
+ loader->memory = memory;
+ *aloader = loader;
+ }
+ return error;
+ }
+
+
+ /* rewind the glyph loader - reset counters to 0 */
+ BASE_FUNC( void ) FT_GlyphLoader_Rewind( FT_GlyphLoader* loader )
+ {
+ FT_GlyphLoad* base = &loader->base;
+ FT_GlyphLoad* current = &loader->current;
+
+
+ base->outline.n_points = 0;
+ base->outline.n_contours = 0;
+ base->num_subglyphs = 0;
+
+ *current = *base;
+ }
+
+
+ /* reset the glyph loader, frees all allocated tables */
+ /* and starts from zero */
+ BASE_FUNC( void ) FT_GlyphLoader_Reset( FT_GlyphLoader* loader )
+ {
+ FT_Memory memory = loader->memory;
+
+
+ FREE( loader->base.outline.points );
+ FREE( loader->base.outline.tags );
+ FREE( loader->base.outline.contours );
+ FREE( loader->base.extra_points );
+ FREE( loader->base.subglyphs );
+
+ loader->max_points = 0;
+ loader->max_contours = 0;
+ loader->max_subglyphs = 0;
+
+ FT_GlyphLoader_Rewind( loader );
+ }
+
+
+ /* delete a glyph loader */
+ BASE_FUNC( void ) FT_GlyphLoader_Done( FT_GlyphLoader* loader )
+ {
+ if ( loader )
+ {
+ FT_Memory memory = loader->memory;
+
+
+ FT_GlyphLoader_Reset( loader );
+ FREE( loader );
+ }
+ }
+
+
+ /* re-adjust the `current' outline fields */
+ static
+ void FT_GlyphLoader_Adjust_Points( FT_GlyphLoader* loader )
+ {
+ FT_Outline* base = &loader->base.outline;
+ FT_Outline* current = &loader->current.outline;
+
+
+ current->points = base->points + base->n_points;
+ current->tags = base->tags + base->n_points;
+ current->contours = base->contours + base->n_contours;
+
+ /* handle extra points table - if any */
+ if ( loader->use_extra )
+ loader->current.extra_points =
+ loader->base.extra_points + base->n_points;
+ }
+
+
+ BASE_FUNC( FT_Error ) FT_GlyphLoader_Create_Extra(
+ FT_GlyphLoader* loader )
+ {
+ FT_Error error;
+ FT_Memory memory = loader->memory;
+
+
+ if ( !ALLOC_ARRAY( loader->base.extra_points,
+ loader->max_points, FT_Vector ) )
+ {
+ loader->use_extra = 1;
+ FT_GlyphLoader_Adjust_Points( loader );
+ }
+ return error;
+ }
+
+
+ /* re-adjust the `current' subglyphs field */
+ static
+ void FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader* loader )
+ {
+ FT_GlyphLoad* base = &loader->base;
+ FT_GlyphLoad* current = &loader->current;
+
+
+ current->subglyphs = base->subglyphs + base->num_subglyphs;
+ }
+
+
+ /* Ensure that we can add `n_points' and `n_contours' to our glyph. this */
+ /* function reallocates its outline tables if necessary. Note that it */
+ /* DOESN'T change the number of points within the loader! */
+ /* */
+ BASE_FUNC( FT_Error ) FT_GlyphLoader_Check_Points(
+ FT_GlyphLoader* loader,
+ FT_UInt n_points,
+ FT_UInt n_contours )
+ {
+ FT_Memory memory = loader->memory;
+ FT_Error error = FT_Err_Ok;
+ FT_Outline* base = &loader->base.outline;
+ FT_Outline* current = &loader->current.outline;
+ FT_Bool adjust = 1;
+
+ FT_UInt new_max;
+
+
+ /* check points & tags */
+ new_max = base->n_points + current->n_points + n_points;
+ if ( new_max > loader->max_points )
+ {
+ new_max = ( new_max + 7 ) & -8;
+ if ( REALLOC_ARRAY( base->points, base->n_points,
+ new_max, FT_Vector ) ||
+ REALLOC_ARRAY( base->tags, base->n_points,
+ new_max, FT_Byte ) )
+ goto Exit;
+
+ if ( loader->use_extra &&
+ REALLOC_ARRAY( loader->base.extra_points, base->n_points,
+ new_max, FT_Vector ) )
+ goto Exit;
+
+ adjust = 1;
+ loader->max_points = new_max;
+ }
+
+ /* check contours */
+ new_max = base->n_contours + current->n_contours +
+ n_contours;
+ if ( new_max > loader->max_contours )
+ {
+ new_max = ( new_max + 3 ) & -4;
+ if ( REALLOC_ARRAY( base->contours, base->n_contours,
+ new_max, FT_Short ) )
+ goto Exit;
+
+ adjust = 1;
+ loader->max_contours = new_max;
+ }
+
+ if ( adjust )
+ FT_GlyphLoader_Adjust_Points( loader );
+
+ Exit:
+ return error;
+ }
+
+
+ /* Ensure that we can add `n_subglyphs' to our glyph. this function */
+ /* reallocates its subglyphs table if necessary. Note that it DOES */
+ /* NOT change the number of subglyphs within the loader! */
+ /* */
+ BASE_FUNC( FT_Error ) FT_GlyphLoader_Check_Subglyphs(
+ FT_GlyphLoader* loader,
+ FT_UInt n_subs )
+ {
+ FT_Memory memory = loader->memory;
+ FT_Error error = FT_Err_Ok;
+ FT_UInt new_max;
+
+ FT_GlyphLoad* base = &loader->base;
+ FT_GlyphLoad* current = &loader->current;
+
+
+ new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
+ if ( new_max > loader->max_subglyphs )
+ {
+ new_max = ( new_max + 1 ) & -2;
+ if ( REALLOC_ARRAY( base->subglyphs, base->num_subglyphs,
+ new_max, FT_SubGlyph ) )
+ goto Exit;
+
+ loader->max_subglyphs = new_max;
+
+ FT_GlyphLoader_Adjust_Subglyphs( loader );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /* prepare loader for the addition of a new glyph on top of the base one */
+ BASE_FUNC( void ) FT_GlyphLoader_Prepare( FT_GlyphLoader* loader )
+ {
+ FT_GlyphLoad* current = &loader->current;
+
+
+ current->outline.n_points = 0;
+ current->outline.n_contours = 0;
+ current->num_subglyphs = 0;
+
+ FT_GlyphLoader_Adjust_Points ( loader );
+ FT_GlyphLoader_Adjust_Subglyphs( loader );
+ }
+
+
+ /* add current glyph to the base image - and prepare for another */
+ BASE_FUNC( void ) FT_GlyphLoader_Add( FT_GlyphLoader* loader )
+ {
+ FT_GlyphLoad* base = &loader->base;
+ FT_GlyphLoad* current = &loader->current;
+
+ FT_UInt n_curr_contours = current->outline.n_contours;
+ FT_UInt n_base_points = base->outline.n_points;
+ FT_UInt n;
+
+
+ base->outline.n_points += current->outline.n_points;
+ base->outline.n_contours += current->outline.n_contours;
+ base->num_subglyphs += current->num_subglyphs;
+
+ /* adjust contours count in newest outline */
+ for ( n = 0; n < n_curr_contours; n++ )
+ current->outline.contours[n] += n_base_points;
+
+ /* prepare for another new glyph image */
+ FT_GlyphLoader_Prepare( loader );
+ }
+
+
+ BASE_FUNC( FT_Error ) FT_GlyphLoader_Copy_Points( FT_GlyphLoader* target,
+ FT_GlyphLoader* source )
+ {
+ FT_Error error;
+ FT_UInt num_points = source->base.outline.n_points;
+ FT_UInt num_contours = source->base.outline.n_contours;
+
+
+ error = FT_GlyphLoader_Check_Points( target, num_points, num_contours );
+ if ( !error )
+ {
+ FT_Outline* out = &target->base.outline;
+ FT_Outline* in = &source->base.outline;
+
+
+ MEM_Copy( out->points, in->points,
+ num_points * sizeof ( FT_Vector ) );
+ MEM_Copy( out->tags, in->tags,
+ num_points * sizeof ( char ) );
+ MEM_Copy( out->contours, in->contours,
+ num_contours * sizeof ( short ) );
+
+ /* do we need to copy the extra points? */
+ if ( target->use_extra && source->use_extra )
+ MEM_Copy( target->base.extra_points, source->base.extra_points,
+ num_points * sizeof ( FT_Vector ) );
+
+ out->n_points = num_points;
+ out->n_contours = num_contours;
+
+ FT_GlyphLoader_Adjust_Points( target );
+ }
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static
+ FT_Error ft_glyphslot_init( FT_GlyphSlot slot )
+ {
+ FT_Driver driver = slot->face->driver;
+ FT_Driver_Class* clazz = driver->clazz;
+ FT_Memory memory = driver->root.memory;
+ FT_Error error = FT_Err_Ok;
+
+
+ slot->library = driver->root.library;
+
+ if ( FT_DRIVER_USES_OUTLINES( driver ) )
+ error = FT_GlyphLoader_New( memory, &slot->loader );
+
+ if ( !error && clazz->init_slot )
+ error = clazz->init_slot( slot );
+
+ return error;
+ }
+
+
+ static
+ void ft_glyphslot_clear( FT_GlyphSlot slot )
+ {
+ /* free bitmap if needed */
+ if ( slot->flags & ft_glyph_own_bitmap )
+ {
+ FT_Memory memory = FT_FACE_MEMORY( slot->face );
+
+
+ FREE( slot->bitmap.buffer );
+ slot->flags &= ~ft_glyph_own_bitmap;
+ }
+
+ /* clear all public fields in the glyph slot */
+ MEM_Set( &slot->metrics, 0, sizeof ( slot->metrics ) );
+ MEM_Set( &slot->outline, 0, sizeof ( slot->outline ) );
+ MEM_Set( &slot->bitmap, 0, sizeof ( slot->bitmap ) );
+
+ slot->bitmap_left = 0;
+ slot->bitmap_top = 0;
+ slot->num_subglyphs = 0;
+ slot->subglyphs = 0;
+ slot->control_data = 0;
+ slot->control_len = 0;
+ slot->other = 0;
+ slot->format = ft_glyph_format_none;
+
+ slot->linearHoriAdvance = 0;
+ slot->linearVertAdvance = 0;
+ }
+
+
+ static
+ void ft_glyphslot_done( FT_GlyphSlot slot )
+ {
+ FT_Driver driver = slot->face->driver;
+ FT_Driver_Class* clazz = driver->clazz;
+ FT_Memory memory = driver->root.memory;
+
+
+ /* free bitmap buffer if needed */
+ if ( slot->flags & ft_glyph_own_bitmap )
+ FREE( slot->bitmap.buffer );
+
+ /* free glyph loader */
+ if ( FT_DRIVER_USES_OUTLINES( driver ) )
+ {
+ FT_GlyphLoader_Done( slot->loader );
+ slot->loader = 0;
+ }
+
+ if ( clazz->done_slot )
+ clazz->done_slot( slot );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* It is sometimes useful to have more than one glyph slot for a */
+ /* given face object. This function is used to create additional */
+ /* slots. All of them are automatically discarded when the face is */
+ /* destroyed. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a parent face object. */
+ /* */
+ /* <Output> */
+ /* aslot :: A handle to a new glyph slot object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_New_GlyphSlot( FT_Face face,
+ FT_GlyphSlot* aslot )
+ {
+ FT_Error error;
+ FT_Driver driver;
+ FT_Driver_Class* clazz;
+ FT_Memory memory;
+ FT_GlyphSlot slot;
+
+
+ if ( !face || !aslot || !face->driver )
+ return FT_Err_Invalid_Argument;
+
+ *aslot = 0;
+
+ driver = face->driver;
+ clazz = driver->clazz;
+ memory = driver->root.memory;
+
+ FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
+ if ( !ALLOC( slot, clazz->slot_object_size ) )
+ {
+ slot->face = face;
+
+ error = ft_glyphslot_init( slot );
+ if ( error )
+ {
+ ft_glyphslot_done( slot );
+ FREE( slot );
+ goto Exit;
+ }
+
+ *aslot = slot;
+ }
+
+ Exit:
+ FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* Destroys a given glyph slot. Remember however that all slots are */
+ /* automatically destroyed with its parent. Using this function is */
+ /* not always mandatory. */
+ /* */
+ /* <Input> */
+ /* slot :: A handle to a target glyph slot. */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_Done_GlyphSlot( FT_GlyphSlot slot )
+ {
+ if ( slot )
+ {
+ FT_Driver driver = slot->face->driver;
+ FT_Memory memory = driver->root.memory;
+ FT_GlyphSlot* parent;
+ FT_GlyphSlot cur;
+
+
+ /* Remove slot from its parent face's list */
+ parent = &slot->face->glyph;
+ cur = *parent;
+
+ while ( cur )
+ {
+ if ( cur == slot )
+ {
+ *parent = cur->next;
+ ft_glyphslot_done( slot );
+ FREE( slot );
+ break;
+ }
+ cur = cur->next;
+ }
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Transform */
+ /* */
+ /* <Description> */
+ /* A function used to set the transformation that is applied to glyph */
+ /* images just before they are converted to bitmaps in a glyph slot */
+ /* when FT_Render_Glyph() is called. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* <Input> */
+ /* matrix :: A pointer to the transformation's 2x2 matrix. Use 0 for */
+ /* the identity matrix. */
+ /* delta :: A pointer to the translation vector. Use 0 for the null */
+ /* vector. */
+ /* */
+ /* <Note> */
+ /* The transformation is only applied to scalable image formats after */
+ /* the glyph has been loaded. It means that hinting is unaltered by */
+ /* the transformation and is performed on the character size given in */
+ /* the last call to FT_Set_Char_Sizes() or FT_Set_Pixel_Sizes(). */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_Set_Transform( FT_Face face,
+ FT_Matrix* matrix,
+ FT_Vector* delta )
+ {
+ if ( !face )
+ return;
+
+ face->transform_flags = 0;
+
+ if ( !matrix )
+ {
+ face->transform_matrix.xx = 0x10000L;
+ face->transform_matrix.xy = 0;
+ face->transform_matrix.yx = 0;
+ face->transform_matrix.yy = 0x10000L;
+ matrix = &face->transform_matrix;
+ }
+ else
+ face->transform_matrix = *matrix;
+
+ /* set transform_flags bit flag 0 if `matrix' isn't the identity */
+ if ( ( matrix->xy | matrix->yx ) ||
+ matrix->xx != 0x10000L ||
+ matrix->yy != 0x10000L )
+ face->transform_flags |= 1;
+
+ if ( !delta )
+ {
+ face->transform_delta.x = 0;
+ face->transform_delta.y = 0;
+ delta = &face->transform_delta;
+ }
+ else
+ face->transform_delta = *delta;
+
+ /* set transform_flags bit flag 1 if `delta' isn't the null vector */
+ if ( delta->x | delta->y )
+ face->transform_flags |= 2;
+ }
+
+
+ static FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Load_Glyph */
+ /* */
+ /* <Description> */
+ /* A function used to load a single glyph within a given glyph slot, */
+ /* for a given size. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object where the glyph */
+ /* will be loaded. */
+ /* */
+ /* glyph_index :: The index of the glyph in the font file. */
+ /* */
+ /* load_flags :: A flag indicating what to load for this glyph. The */
+ /* FT_LOAD_XXX constants can be used to control the */
+ /* glyph loading process (e.g., whether the outline */
+ /* should be scaled, whether to load bitmaps or not, */
+ /* whether to hint the outline, etc). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* If the glyph image is not a bitmap, and if the bit flag */
+ /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */
+ /* transformed with the information passed to a previous call to */
+ /* FT_Set_Transform. */
+ /* */
+ /* Note that this also transforms the `face.glyph.advance' field, but */
+ /* *not* the values in `face.glyph.metrics'. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Load_Glyph( FT_Face face,
+ FT_UInt glyph_index,
+ FT_Int load_flags )
+ {
+ FT_Error error;
+ FT_Driver driver;
+ FT_GlyphSlot slot;
+ FT_Library library;
+ FT_Bool autohint;
+ FT_Module hinter;
+
+
+ if ( !face || !face->size || !face->glyph )
+ return FT_Err_Invalid_Face_Handle;
+
+ if ( glyph_index >= (FT_UInt)face->num_glyphs )
+ return FT_Err_Invalid_Argument;
+
+ slot = face->glyph;
+ ft_glyphslot_clear( slot );
+
+ driver = face->driver;
+
+ /* when the flag NO_RECURSE is set, we disable hinting and scaling */
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+ /* do we need to load the glyph through the auto-hinter? */
+ library = driver->root.library;
+ hinter = library->auto_hinter;
+ autohint = hinter &&
+ !( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) );
+ if ( autohint )
+ {
+ if ( FT_DRIVER_HAS_HINTER( driver ) &&
+ !( load_flags & FT_LOAD_FORCE_AUTOHINT ) )
+ autohint = 0;
+ }
+
+ if ( autohint )
+ {
+ FT_AutoHinter_Interface* hinting;
+
+
+ hinting = (FT_AutoHinter_Interface*)hinter->clazz->module_interface;
+ error = hinting->load_glyph( (FT_AutoHinter)hinter, slot, face->size,
+ glyph_index, load_flags );
+ }
+ else
+ error = driver->clazz->load_glyph( slot,
+ face->size,
+ glyph_index,
+ load_flags );
+ if ( error )
+ goto Exit;
+
+ /* compute the advance */
+ if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
+ {
+ slot->advance.x = 0;
+ slot->advance.y = slot->metrics.vertAdvance;
+ }
+ else
+ {
+ slot->advance.x = slot->metrics.horiAdvance;
+ slot->advance.y = 0;
+ }
+
+ /* now, transform the glyph image when needed */
+ if ( face->transform_flags )
+ {
+ /* get renderer */
+ FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
+
+
+ if ( renderer )
+ error = renderer->clazz->transform_glyph( renderer, slot,
+ &face->transform_matrix,
+ &face->transform_delta );
+ /* transform advance */
+ FT_Vector_Transform( &slot->advance, &face->transform_matrix );
+ }
+
+ /* do we need to render the image now? */
+ if ( !error &&
+ slot->format != ft_glyph_format_bitmap &&
+ slot->format != ft_glyph_format_composite &&
+ load_flags & FT_LOAD_RENDER )
+ {
+ error = FT_Render_Glyph( slot,
+ ( load_flags & FT_LOAD_MONOCHROME )
+ ? ft_render_mode_mono
+ : ft_render_mode_normal );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Load_Char */
+ /* */
+ /* <Description> */
+ /* A function used to load a single glyph within a given glyph slot, */
+ /* for a given size, according to its character code. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a target face object where the glyph */
+ /* will be loaded. */
+ /* */
+ /* char_code :: The glyph's character code, according to the */
+ /* current charmap used in the face. */
+ /* */
+ /* load_flags :: A flag indicating what to load for this glyph. The */
+ /* FT_LOAD_XXX constants can be used to control the */
+ /* glyph loading process (e.g., whether the outline */
+ /* should be scaled, whether to load bitmaps or not, */
+ /* whether to hint the outline, etc). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* If the face has no current charmap, or if the character code */
+ /* is not defined in the charmap, this function will return an */
+ /* error. */
+ /* */
+ /* If the glyph image is not a bitmap, and if the bit flag */
+ /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */
+ /* transformed with the information passed to a previous call to */
+ /* FT_Set_Transform(). */
+ /* */
+ /* Note that this also transforms the `face.glyph.advance' field, but */
+ /* *not* the values in `face.glyph.metrics'. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Load_Char( FT_Face face,
+ FT_ULong char_code,
+ FT_Int load_flags )
+ {
+ FT_UInt glyph_index;
+
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ glyph_index = (FT_UInt)char_code;
+ if ( face->charmap )
+ glyph_index = FT_Get_Char_Index( face, char_code );
+
+ return FT_Load_Glyph( face, glyph_index, load_flags );
+ }
+
+
+ /* destructor for sizes list */
+ static
+ void destroy_size( FT_Memory memory,
+ FT_Size size,
+ FT_Driver driver )
+ {
+ /* finalize client-specific data */
+ if ( size->generic.finalizer )
+ size->generic.finalizer( size );
+
+ /* finalize format-specific stuff */
+ if ( driver->clazz->done_size )
+ driver->clazz->done_size( size );
+
+ FREE( size );
+ }
+
+
+ /* destructor for faces list */
+ static
+ void destroy_face( FT_Memory memory,
+ FT_Face face,
+ FT_Driver driver )
+ {
+ FT_Driver_Class* clazz = driver->clazz;
+
+
+ /* discard auto-hinting data */
+ if ( face->autohint.finalizer )
+ face->autohint.finalizer( face->autohint.data );
+
+ /* Discard glyph slots for this face */
+ /* Beware! FT_Done_GlyphSlot() changes the field `face->slot' */
+ while ( face->glyph )
+ FT_Done_GlyphSlot( face->glyph );
+
+ /* Discard all sizes for this face */
+ FT_List_Finalize( &face->sizes_list,
+ (FT_List_Destructor)destroy_size,
+ memory,
+ driver );
+ face->size = 0;
+
+ /* Now discard client data */
+ if ( face->generic.finalizer )
+ face->generic.finalizer( face );
+
+ /* finalize format-specific stuff */
+ if ( clazz->done_face )
+ clazz->done_face( face );
+
+ /* close the stream for this face if needed */
+ if ( ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) == 0 )
+ ft_done_stream( &face->stream );
+
+ /* get rid of it */
+ FREE( face );
+ }
+
+
+ static
+ void Destroy_Driver( FT_Driver driver )
+ {
+ FT_List_Finalize( &driver->faces_list,
+ (FT_List_Destructor)destroy_face,
+ driver->root.memory,
+ driver );
+
+ /* check whether we need to drop the driver's glyph loader */
+ if ( FT_DRIVER_USES_OUTLINES( driver ) )
+ FT_GlyphLoader_Done( driver->glyph_loader );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* open_face */
+ /* */
+ /* <Description> */
+ /* This function does some work for FT_Open_Face(). */
+ /* */
+ static
+ FT_Error open_face( FT_Driver driver,
+ FT_Stream stream,
+ FT_Long face_index,
+ FT_Int num_params,
+ FT_Parameter* params,
+ FT_Face* aface )
+ {
+ FT_Memory memory;
+ FT_Driver_Class* clazz;
+ FT_Face face = 0;
+ FT_Error error;
+
+
+ clazz = driver->clazz;
+ memory = driver->root.memory;
+
+ /* allocate the face object and perform basic initialization */
+ if ( ALLOC( face, clazz->face_object_size ) )
+ goto Fail;
+
+ face->driver = driver;
+ face->memory = memory;
+ face->stream = stream;
+
+ error = clazz->init_face( stream,
+ face,
+ face_index,
+ num_params,
+ params );
+ if ( error )
+ goto Fail;
+
+ *aface = face;
+
+ Fail:
+ if ( error )
+ {
+ clazz->done_face( face );
+ FREE( face );
+ *aface = 0;
+ }
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Face */
+ /* */
+ /* <Description> */
+ /* Creates a new face object from a given resource and typeface index */
+ /* using a pathname to the font file. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to the library resource. */
+ /* */
+ /* <Input> */
+ /* pathname :: A path to the font file. */
+ /* */
+ /* face_index :: The index of the face within the resource. The */
+ /* first face has index 0. */
+ /* <Output> */
+ /* aface :: A handle to a new face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Unlike FreeType 1.x, this function automatically creates a glyph */
+ /* slot for the face object which can be accessed directly through */
+ /* `face->glyph'. */
+ /* */
+ /* Note that additional slots can be added to each face with the */
+ /* FT_New_GlyphSlot() API function. Slots are linked in a single */
+ /* list through their `next' field. */
+ /* */
+ /* FT_New_Face() can be used to determine and/or check the font */
+ /* format of a given font resource. If the `face_index' field is */
+ /* negative, the function will _not_ return any face handle in */
+ /* `*face'. Its return value should be 0 if the resource is */
+ /* recognized, or non-zero if not. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_New_Face( FT_Library library,
+ const char* pathname,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ FT_Open_Args args;
+
+
+ /* test for valid `library' and `aface' delayed to FT_Open_Face() */
+ if ( !pathname )
+ return FT_Err_Invalid_Argument;
+
+ args.flags = ft_open_pathname;
+ args.pathname = (char*)pathname;
+
+ return FT_Open_Face( library, &args, face_index, aface );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Memory_Face */
+ /* */
+ /* <Description> */
+ /* Creates a new face object from a given resource and typeface index */
+ /* using a font file already loaded into memory. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to the library resource. */
+ /* */
+ /* <Input> */
+ /* file_base :: A pointer to the beginning of the font data. */
+ /* */
+ /* file_size :: The size of the memory chunk used by the font data. */
+ /* */
+ /* face_index :: The index of the face within the resource. The */
+ /* first face has index 0. */
+ /* <Output> */
+ /* face :: A handle to a new face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Unlike FreeType 1.x, this function automatically creates a glyph */
+ /* slot for the face object which can be accessed directly through */
+ /* `face->glyph'. */
+ /* */
+ /* Note that additional slots can be added to each face with the */
+ /* FT_New_GlyphSlot() API function. Slots are linked in a single */
+ /* list through their `next' field. */
+ /* */
+ /* FT_New_Memory_Face() can be used to determine and/or check the */
+ /* font format of a given font resource. If the `face_index' field */
+ /* is negative, the function will _not_ return any face handle in */
+ /* `*face'. Its return value should be 0 if the resource is */
+ /* recognized, or non-zero if not. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_New_Memory_Face( FT_Library library,
+ FT_Byte* file_base,
+ FT_Long file_size,
+ FT_Long face_index,
+ FT_Face* face )
+ {
+ FT_Open_Args args;
+
+
+ /* test for valid `library' and `face' delayed to FT_Open_Face() */
+ if ( !file_base )
+ return FT_Err_Invalid_Argument;
+
+ args.flags = ft_open_memory;
+ args.memory_base = file_base;
+ args.memory_size = file_size;
+
+ return FT_Open_Face( library, &args, face_index, face );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Open_Face */
+ /* */
+ /* <Description> */
+ /* Opens a face object from a given resource and typeface index using */
+ /* an `FT_Open_Args' structure. If the face object doesn't exist, it */
+ /* will be created. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to the library resource. */
+ /* */
+ /* <Input> */
+ /* args :: A pointer to an `FT_Open_Args' structure which must */
+ /* be filled by the caller. */
+ /* */
+ /* face_index :: The index of the face within the resource. The */
+ /* first face has index 0. */
+ /* <Output> */
+ /* aface :: A handle to a new face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Unlike FreeType 1.x, this function automatically creates a glyph */
+ /* slot for the face object which can be accessed directly through */
+ /* `face->glyph'. */
+ /* */
+ /* Note that additional slots can be added to each face with the */
+ /* FT_New_GlyphSlot() API function. Slots are linked in a single */
+ /* list through their `next' field. */
+ /* */
+ /* FT_Open_Face() can be used to determine and/or check the font */
+ /* format of a given font resource. If the `face_index' field is */
+ /* negative, the function will _not_ return any face handle in */
+ /* `*face'. Its return value should be 0 if the resource is */
+ /* recognized, or non-zero if not. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Open_Face( FT_Library library,
+ FT_Open_Args* args,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ FT_Error error;
+ FT_Driver driver;
+ FT_Memory memory;
+ FT_Stream stream;
+ FT_Face face = 0;
+ FT_ListNode node = 0;
+
+
+ /* test for valid `library' and `args' delayed to */
+ /* ft_new_input_stream() */
+
+ if ( !aface )
+ return FT_Err_Invalid_Argument;
+
+ *aface = 0;
+
+ /* create input stream */
+ error = ft_new_input_stream( library, args, &stream );
+ if ( error )
+ goto Exit;
+
+ memory = library->memory;
+
+ /* If the font driver is specified in the `args' structure, use */
+ /* it. Otherwise, we scan the list of registered drivers. */
+ if ( args->flags & ft_open_driver && args->driver )
+ {
+ driver = FT_DRIVER( args->driver );
+
+ /* not all modules are drivers, so check... */
+ if ( FT_MODULE_IS_DRIVER( driver ) )
+ {
+ FT_Int num_params = 0;
+ FT_Parameter* params = 0;
+
+
+ if ( args->flags & ft_open_params )
+ {
+ num_params = args->num_params;
+ params = args->params;
+ }
+
+ error = open_face( driver, stream, face_index,
+ num_params, params, &face );
+ if ( !error )
+ goto Success;
+ }
+ else
+ error = FT_Err_Invalid_Handle;
+
+ ft_done_stream( &stream );
+ goto Fail;
+ }
+ else
+ {
+ /* check each font driver for an appropriate format */
+ FT_Module* cur = library->modules;
+ FT_Module* limit = cur + library->num_modules;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ /* not all modules are font drivers, so check... */
+ if ( FT_MODULE_IS_DRIVER( cur[0] ) )
+ {
+ FT_Int num_params = 0;
+ FT_Parameter* params = 0;
+
+
+ driver = FT_DRIVER( cur[0] );
+
+ if ( args->flags & ft_open_params )
+ {
+ num_params = args->num_params;
+ params = args->params;
+ }
+
+ error = open_face( driver, stream, face_index,
+ num_params, params, &face );
+ if ( !error )
+ goto Success;
+
+ if ( error != FT_Err_Unknown_File_Format )
+ goto Fail;
+ }
+ }
+
+ ft_done_stream( &stream );
+
+ /* no driver is able to handle this format */
+ error = FT_Err_Unknown_File_Format;
+ goto Fail;
+ }
+
+ Success:
+ FT_TRACE4(( "FT_New_Face: New face object, adding to list\n" ));
+
+ /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
+ if ( args->flags & ft_open_stream && args->stream )
+ face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
+
+ /* add the face object to its driver's list */
+ if ( ALLOC( node, sizeof ( *node ) ) )
+ goto Fail;
+
+ node->data = face;
+ /* don't assume driver is the same as face->driver, so use */
+ /* face->driver instead. */
+ FT_List_Add( &face->driver->faces_list, node );
+
+ /* now allocate a glyph slot object for the face */
+ {
+ FT_GlyphSlot slot;
+
+
+ FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
+
+ error = FT_New_GlyphSlot( face, &slot );
+ if ( error )
+ goto Fail;
+
+ face->glyph = slot;
+ }
+
+ /* finally, allocate a size object for the face */
+ {
+ FT_Size size;
+
+
+ FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
+
+ error = FT_New_Size( face, &size );
+ if ( error )
+ goto Fail;
+
+ face->size = size;
+ }
+
+ /* initialize transformation for convenience functions */
+ face->transform_matrix.xx = 0x10000L;
+ face->transform_matrix.xy = 0;
+ face->transform_matrix.yx = 0;
+ face->transform_matrix.yy = 0x10000L;
+
+ face->transform_delta.x = 0;
+ face->transform_delta.y = 0;
+
+ *aface = face;
+ goto Exit;
+
+ Fail:
+ FT_Done_Face( face );
+
+ Exit:
+ FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Attach_File */
+ /* */
+ /* <Description> */
+ /* `Attaches' a given font file to an existing face. This is usually */
+ /* to read additional information for a single face object. For */
+ /* example, it is used to read the AFM files that come with Type 1 */
+ /* fonts in order to add kerning data and other metrics. */
+ /* */
+ /* <InOut> */
+ /* face :: The target face object. */
+ /* */
+ /* <Input> */
+ /* filepathname :: An 8-bit pathname naming the `metrics' file. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* If your font file is in memory, or if you want to provide your */
+ /* own input stream object, use FT_Attach_Stream(). */
+ /* */
+ /* The meaning of the `attach' action (i.e., what really happens when */
+ /* the new file is read) is not fixed by FreeType itself. It really */
+ /* depends on the font format (and thus the font driver). */
+ /* */
+ /* Client applications are expected to know what they are doing */
+ /* when invoking this function. Most drivers simply do not implement */
+ /* file attachments. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Attach_File( FT_Face face,
+ const char* filepathname )
+ {
+ FT_Open_Args open;
+
+
+ /* test for valid `face' delayed to FT_Attach_Stream() */
+
+ if ( !filepathname )
+ return FT_Err_Invalid_Argument;
+
+ open.flags = ft_open_pathname;
+ open.pathname = (char*)filepathname;
+
+ return FT_Attach_Stream( face, &open );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Attach_Stream */
+ /* */
+ /* <Description> */
+ /* This function is similar to FT_Attach_File() with the exception */
+ /* that it reads the attachment from an arbitrary stream. */
+ /* */
+ /* <Input> */
+ /* face :: The target face object. */
+ /* */
+ /* parameters :: A pointer to an FT_Open_Args structure used to */
+ /* describe the input stream to FreeType. */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The meaning of the `attach' (i.e. what really happens when the */
+ /* new file is read) is not fixed by FreeType itself. It really */
+ /* depends on the font format (and thus the font driver). */
+ /* */
+ /* Client applications are expected to know what they are doing */
+ /* when invoking this function. Most drivers simply do not implement */
+ /* file attachments. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Attach_Stream( FT_Face face,
+ FT_Open_Args* parameters )
+ {
+ FT_Stream stream;
+ FT_Error error;
+ FT_Driver driver;
+
+ FT_Driver_Class* clazz;
+
+
+ /* test for valid `parameters' delayed to ft_new_input_stream() */
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ driver = face->driver;
+ if ( !driver )
+ return FT_Err_Invalid_Driver_Handle;
+
+ error = ft_new_input_stream( driver->root.library, parameters, &stream );
+ if ( error )
+ goto Exit;
+
+ /* we implement FT_Attach_Stream in each driver through the */
+ /* `attach_file' interface */
+
+ error = FT_Err_Unimplemented_Feature;
+ clazz = driver->clazz;
+ if ( clazz->attach_file )
+ error = clazz->attach_file( face, stream );
+
+ /* close the attached stream */
+ if ( !parameters->stream || ( parameters->flags & ft_open_stream ) )
+ ft_done_stream( &stream );
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_Face */
+ /* */
+ /* <Description> */
+ /* Discards a given face object, as well as all of its child slots */
+ /* and sizes. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a target face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Done_Face( FT_Face face )
+ {
+ FT_Error error;
+ FT_Driver driver;
+ FT_Memory memory;
+ FT_ListNode node;
+
+
+ error = FT_Err_Invalid_Face_Handle;
+ if ( face && face->driver )
+ {
+ driver = face->driver;
+ memory = driver->root.memory;
+
+ /* find face in driver's list */
+ node = FT_List_Find( &driver->faces_list, face );
+ if ( node )
+ {
+ /* remove face object from the driver's list */
+ FT_List_Remove( &driver->faces_list, node );
+ FREE( node );
+
+ /* now destroy the object proper */
+ destroy_face( memory, face, driver );
+ error = FT_Err_Ok;
+ }
+ }
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Size */
+ /* */
+ /* <Description> */
+ /* Creates a new size object from a given face object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a parent face object. */
+ /* */
+ /* <Output> */
+ /* asize :: A handle to a new size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_New_Size( FT_Face face,
+ FT_Size* asize )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FT_Driver driver;
+ FT_Driver_Class* clazz;
+
+ FT_Size size = 0;
+ FT_ListNode node = 0;
+
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ if ( !asize )
+ return FT_Err_Invalid_Size_Handle;
+
+ if ( !face->driver )
+ return FT_Err_Invalid_Driver_Handle;
+
+ *asize = 0;
+
+ driver = face->driver;
+ clazz = driver->clazz;
+ memory = face->memory;
+
+ /* Allocate new size object and perform basic initialisation */
+ if ( ALLOC( size, clazz->size_object_size ) ||
+ ALLOC( node, sizeof ( FT_ListNodeRec ) ) )
+ goto Exit;
+
+ size->face = face;
+
+ if ( clazz->init_size )
+ error = clazz->init_size( size );
+
+ /* in case of success, add to the face's list */
+ if ( !error )
+ {
+ *asize = size;
+ node->data = size;
+ FT_List_Add( &face->sizes_list, node );
+ }
+
+ Exit:
+ if ( error )
+ {
+ FREE( node );
+ FREE( size );
+ }
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_Size */
+ /* */
+ /* <Description> */
+ /* Discards a given size object. */
+ /* */
+ /* <Input> */
+ /* size :: A handle to a target size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Done_Size( FT_Size size )
+ {
+ FT_Error error;
+ FT_Driver driver;
+ FT_Memory memory;
+ FT_Face face;
+ FT_ListNode node;
+
+
+ if ( !size )
+ return FT_Err_Invalid_Size_Handle;
+
+ face = size->face;
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ driver = face->driver;
+ if ( !driver )
+ return FT_Err_Invalid_Driver_Handle;
+
+ memory = driver->root.memory;
+
+ error = FT_Err_Ok;
+ node = FT_List_Find( &face->sizes_list, size );
+ if ( node )
+ {
+ FT_List_Remove( &face->sizes_list, node );
+ FREE( node );
+
+ if ( face->size == size )
+ {
+ face->size = 0;
+ if ( face->sizes_list.head )
+ face->size = (FT_Size)(face->sizes_list.head->data);
+ }
+
+ destroy_size( memory, size, driver );
+ }
+ else
+ error = FT_Err_Invalid_Size_Handle;
+
+ return FT_Err_Ok;
+ }
+
+
+ static
+ void ft_recompute_scaled_metrics( FT_Face face,
+ FT_Size_Metrics* metrics )
+ {
+ /* Compute root ascender, descender, test height, and max_advance */
+
+ metrics->ascender = ( FT_MulFix( face->ascender,
+ metrics->y_scale ) + 32 ) & -64;
+
+ metrics->descender = ( FT_MulFix( face->descender,
+ metrics->y_scale ) + 32 ) & -64;
+
+ metrics->height = ( FT_MulFix( face->height,
+ metrics->y_scale ) + 32 ) & -64;
+
+ metrics->max_advance = ( FT_MulFix( face->max_advance_width,
+ metrics->x_scale ) + 32 ) & -64;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Char_Size */
+ /* */
+ /* <Description> */
+ /* Sets the character dimensions of a given face object. The */
+ /* `char_width' and `char_height' values are used for the width and */
+ /* height, respectively, expressed in 26.6 fractional points. */
+ /* */
+ /* If the horizontal or vertical resolution values are zero, a */
+ /* default value of 72dpi is used. Similarly, if one of the */
+ /* character dimensions is zero, its value is set equal to the other. */
+ /* */
+ /* <InOut> */
+ /* size :: A handle to a target size object. */
+ /* */
+ /* <Input> */
+ /* char_width :: The character width, in 26.6 fractional points. */
+ /* */
+ /* char_height :: The character height, in 26.6 fractional */
+ /* points. */
+ /* */
+ /* horz_resolution :: The horizontal resolution. */
+ /* */
+ /* vert_resolution :: The vertical resolution. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* When dealing with fixed-size faces (i.e., non-scalable formats), */
+ /* use the function FT_Set_Pixel_Sizes(). */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Set_Char_Size( FT_Face face,
+ FT_F26Dot6 char_width,
+ FT_F26Dot6 char_height,
+ FT_UInt horz_resolution,
+ FT_UInt vert_resolution )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Driver driver;
+ FT_Memory memory;
+ FT_Driver_Class* clazz;
+ FT_Size_Metrics* metrics;
+ FT_Long dim_x, dim_y;
+
+
+ if ( !face || !face->size || !face->driver )
+ return FT_Err_Invalid_Face_Handle;
+
+ driver = face->driver;
+ metrics = &face->size->metrics;
+
+ if ( !char_width )
+ char_width = char_height;
+
+ else if ( !char_height )
+ char_height = char_width;
+
+ if ( !horz_resolution )
+ horz_resolution = 72;
+
+ if ( !vert_resolution )
+ vert_resolution = 72;
+
+ driver = face->driver;
+ clazz = driver->clazz;
+ memory = driver->root.memory;
+
+ /* default processing -- this can be overridden by the driver */
+ if ( char_width < 1 * 64 )
+ char_width = 1 * 64;
+ if ( char_height < 1 * 64 )
+ char_height = 1 * 64;
+
+ /* Compute pixel sizes in 26.6 units */
+ dim_x = ( ( ( char_width * horz_resolution ) / 72 ) + 32 ) & -64;
+ dim_y = ( ( ( char_height * vert_resolution ) / 72 ) + 32 ) & -64;
+
+ metrics->x_ppem = (FT_UShort)( dim_x >> 6 );
+ metrics->y_ppem = (FT_UShort)( dim_y >> 6 );
+
+ metrics->x_scale = 0x10000L;
+ metrics->y_scale = 0x10000L;
+
+ if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+ {
+ metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM );
+ metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM );
+
+ ft_recompute_scaled_metrics( face, metrics );
+ }
+
+ if ( clazz->set_char_sizes )
+ error = clazz->set_char_sizes( face->size,
+ char_width,
+ char_height,
+ horz_resolution,
+ vert_resolution );
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Pixel_Sizes */
+ /* */
+ /* <Description> */
+ /* Sets the character dimensions of a given face object. The width */
+ /* and height are expressed in integer pixels. */
+ /* */
+ /* If one of the character dimensions is zero, its value is set equal */
+ /* to the other. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* <Input> */
+ /* pixel_width :: The character width, in integer pixels. */
+ /* */
+ /* pixel_height :: The character height, in integer pixels. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Set_Pixel_Sizes( FT_Face face,
+ FT_UInt pixel_width,
+ FT_UInt pixel_height )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Driver driver;
+ FT_Memory memory;
+ FT_Driver_Class* clazz;
+ FT_Size_Metrics* metrics = &face->size->metrics;
+
+
+ if ( !face || !face->size || !face->driver )
+ return FT_Err_Invalid_Face_Handle;
+
+ driver = face->driver;
+ clazz = driver->clazz;
+ memory = driver->root.memory;
+
+ /* default processing -- this can be overridden by the driver */
+ if ( pixel_width == 0 )
+ pixel_width = pixel_height;
+
+ else if ( pixel_height == 0 )
+ pixel_height = pixel_width;
+
+ if ( pixel_width < 1 )
+ pixel_width = 1;
+ if ( pixel_height < 1 )
+ pixel_height = 1;
+
+ metrics->x_ppem = pixel_width;
+ metrics->y_ppem = pixel_height;
+
+ if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+ {
+ metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,
+ face->units_per_EM );
+
+ metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,
+ face->units_per_EM );
+
+ ft_recompute_scaled_metrics( face, metrics );
+ }
+
+ if ( clazz->set_pixel_sizes )
+ error = clazz->set_pixel_sizes( face->size,
+ pixel_width,
+ pixel_height );
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Kerning */
+ /* */
+ /* <Description> */
+ /* Returns the kerning vector between two glyphs of a same face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a source face object. */
+ /* */
+ /* left_glyph :: The index of the left glyph in the kern pair. */
+ /* */
+ /* right_glyph :: The index of the right glyph in the kern pair. */
+ /* */
+ /* kern_mode :: See FT_Kerning_Mode() for more information. */
+ /* Determines the scale/dimension of the returned */
+ /* kerning vector. */
+ /* */
+ /* <Output> */
+ /* kerning :: The kerning vector. This is in font units for */
+ /* scalable formats, and in pixels for fixed-sizes */
+ /* formats. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only horizontal layouts (left-to-right & right-to-left) are */
+ /* supported by this method. Other layouts, or more sophisticated */
+ /* kernings, are out of the scope of this API function -- they can be */
+ /* implemented through format-specific interfaces. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Get_Kerning( FT_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_UInt kern_mode,
+ FT_Vector* kerning )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Driver driver;
+ FT_Memory memory;
+
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ if ( !kerning )
+ return FT_Err_Invalid_Argument;
+
+ driver = face->driver;
+ memory = driver->root.memory;
+
+ kerning->x = 0;
+ kerning->y = 0;
+
+ if ( driver->clazz->get_kerning )
+ {
+ error = driver->clazz->get_kerning( face,
+ left_glyph,
+ right_glyph,
+ kerning );
+ if ( !error )
+ {
+ if ( kern_mode != ft_kerning_unscaled )
+ {
+ kerning->x = FT_MulFix( kerning->x, face->size->metrics.x_scale );
+ kerning->y = FT_MulFix( kerning->y, face->size->metrics.y_scale );
+
+ if ( kern_mode != ft_kerning_unfitted )
+ {
+ kerning->x = ( kerning->x + 32 ) & -64;
+ kerning->y = ( kerning->y + 32 ) & -64;
+ }
+ }
+ }
+ }
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Select_Charmap */
+ /* */
+ /* <Description> */
+ /* Selects a given charmap by its encoding tag (as listed in */
+ /* `freetype.h'). */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* encoding :: A handle to the selected charmap. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function will return an error if no charmap in the face */
+ /* corresponds to the encoding queried here. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Select_Charmap( FT_Face face,
+ FT_Encoding encoding )
+ {
+ FT_CharMap* cur;
+ FT_CharMap* limit;
+
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ cur = face->charmaps;
+ if ( !cur )
+ return FT_Err_Invalid_CharMap_Handle;
+
+ limit = cur + face->num_charmaps;
+
+ for ( ; cur < limit; cur++ )
+ {
+ if ( cur[0]->encoding == encoding )
+ {
+ face->charmap = cur[0];
+ return 0;
+ }
+ }
+
+ return FT_Err_Invalid_Argument;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Charmap */
+ /* */
+ /* <Description> */
+ /* Selects a given charmap for character code to glyph index */
+ /* decoding. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* charmap :: A handle to the selected charmap. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function will return an error if the charmap is not part of */
+ /* the face (i.e., if it is not listed in the face->charmaps[] */
+ /* table). */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Set_Charmap( FT_Face face,
+ FT_CharMap charmap )
+ {
+ FT_CharMap* cur;
+ FT_CharMap* limit;
+
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ cur = face->charmaps;
+ if ( !cur )
+ return FT_Err_Invalid_CharMap_Handle;
+
+ limit = cur + face->num_charmaps;
+
+ for ( ; cur < limit; cur++ )
+ {
+ if ( cur[0] == charmap )
+ {
+ face->charmap = cur[0];
+ return 0;
+ }
+ }
+ return FT_Err_Invalid_Argument;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Char_Index */
+ /* */
+ /* <Description> */
+ /* Returns the glyph index of a given character code. This function */
+ /* uses a charmap object to do the translation. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* charcode :: The character code. */
+ /* */
+ /* <Return> */
+ /* The glyph index. 0 means `undefined character code'. */
+ /* */
+ FT_EXPORT_FUNC( FT_UInt ) FT_Get_Char_Index( FT_Face face,
+ FT_ULong charcode )
+ {
+ FT_UInt result;
+ FT_Driver driver;
+
+
+ result = 0;
+ if ( face && face->charmap )
+ {
+ driver = face->driver;
+ result = driver->clazz->get_char_index( face->charmap, charcode );
+ }
+ return result;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Glyph_Name */
+ /* */
+ /* <Description> */
+ /* Retrieves the ASCII name of a given glyph in a face. This only */
+ /* works for those faces where FT_HAS_GLYPH_NAME(face) returns true. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a source face object. */
+ /* */
+ /* glyph_index :: The glyph index. */
+ /* */
+ /* buffer :: A pointer to a target buffer where the name will be */
+ /* copied to. */
+ /* */
+ /* buffer_max :: The maximal number of bytes available in the */
+ /* buffer. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* An error is returned if the face doesn't provide glyph names or if */
+ /* the glyph index is invalid. In all cases of failure, the first */
+ /* byte of `buffer' will be set to 0 to indicate an empty name. */
+ /* */
+ /* The glyph name is truncated to fit within the buffer if it is too */
+ /* long. The returned string is always zero-terminated. */
+ /* */
+ /* This function is not compiled within the library if the config */
+ /* macro FT_CONFIG_OPTION_NO_GLYPH_NAMES is defined in */
+ /* `include/freetype/config/ftoptions.h' */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Get_Glyph_Name( FT_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max )
+ {
+ FT_Error error = FT_Err_Invalid_Argument;
+
+
+ /* clean up buffer */
+ if ( buffer && buffer_max > 0 )
+ ((FT_Byte*)buffer)[0] = 0;
+
+ if ( face &&
+ glyph_index < (FT_UInt)face->num_glyphs &&
+ FT_HAS_GLYPH_NAMES( face ) )
+ {
+ /* now, lookup for glyph name */
+ FT_Driver driver = face->driver;
+ FT_Module_Class* clazz = FT_MODULE_CLASS( driver );
+
+
+ if ( clazz->get_interface )
+ {
+ FT_Glyph_Name_Requester requester;
+
+
+ requester = (FT_Glyph_Name_Requester)clazz->get_interface(
+ FT_MODULE( driver ), "glyph_name" );
+ if ( requester )
+ error = requester( face, glyph_index, buffer, buffer_max );
+ }
+ }
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Sfnt_Table */
+ /* */
+ /* <Description> */
+ /* Returns a pointer to a given SFNT table within a face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* tag :: An index of an SFNT table. */
+ /* */
+ /* <Return> */
+ /* A type-less pointer to the table. This will be 0 in case of */
+ /* error, or if the corresponding table was not found *OR* loaded */
+ /* from the file. */
+ /* */
+ /* <Note> */
+ /* The table is owned by the face object, and disappears with it. */
+ /* */
+ /* This function is only useful to access SFNT tables that are loaded */
+ /* by the sfnt/truetype/opentype drivers. See the FT_Sfnt_Tag */
+ /* enumeration in `tttables.h' for a list. */
+ /* */
+ /* You can load any table with a different function.. XXX */
+ /* */
+ FT_EXPORT_FUNC( void* ) FT_Get_Sfnt_Table( FT_Face face,
+ FT_Sfnt_Tag tag )
+ {
+ void* table = 0;
+ FT_Get_Sfnt_Table_Func func;
+ FT_Driver driver;
+
+
+ if ( !face || !FT_IS_SFNT( face ) )
+ goto Exit;
+
+ driver = face->driver;
+ func = (FT_Get_Sfnt_Table_Func)driver->root.clazz->get_interface(
+ FT_MODULE( driver ), "get_sfnt" );
+ if ( func )
+ table = func( face, tag );
+
+ Exit:
+ return table;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** R E N D E R E R S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* lookup a renderer by glyph format in the library's list */
+ BASE_FUNC( FT_Renderer ) FT_Lookup_Renderer( FT_Library library,
+ FT_Glyph_Format format,
+ FT_ListNode* node )
+ {
+ FT_ListNode cur;
+ FT_Renderer result = 0;
+
+
+ if ( !library )
+ goto Exit;
+
+ cur = library->renderers.head;
+
+ if ( node )
+ {
+ if ( *node )
+ cur = (*node)->next;
+ *node = 0;
+ }
+
+ while ( cur )
+ {
+ FT_Renderer renderer = FT_RENDERER( cur->data );
+
+
+ if ( renderer->glyph_format == format )
+ {
+ if ( node )
+ *node = cur;
+
+ result = renderer;
+ break;
+ }
+ cur = cur->next;
+ }
+
+ Exit:
+ return result;
+ }
+
+
+ static
+ FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot )
+ {
+ FT_Face face = slot->face;
+ FT_Library library = FT_FACE_LIBRARY( face );
+ FT_Renderer result = library->cur_renderer;
+
+
+ if ( !result || result->glyph_format != slot->format )
+ result = FT_Lookup_Renderer( library, slot->format, 0 );
+
+ return result;
+ }
+
+
+ static
+ void ft_set_current_renderer( FT_Library library )
+ {
+ FT_Renderer renderer;
+
+
+ renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline, 0 );
+ library->cur_renderer = renderer;
+ }
+
+
+ static
+ FT_Error ft_add_renderer( FT_Module module )
+ {
+ FT_Library library = module->library;
+ FT_Memory memory = library->memory;
+ FT_Error error;
+ FT_ListNode node;
+
+
+ if ( ALLOC( node, sizeof ( *node ) ) )
+ goto Exit;
+
+ {
+ FT_Renderer render = FT_RENDERER( module );
+ FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
+
+
+ render->clazz = clazz;
+ render->glyph_format = clazz->glyph_format;
+
+ /* allocate raster object if needed */
+ if ( clazz->glyph_format == ft_glyph_format_outline &&
+ clazz->raster_class->raster_new )
+ {
+ error = clazz->raster_class->raster_new( memory, &render->raster );
+ if ( error )
+ goto Fail;
+
+ render->raster_render = clazz->raster_class->raster_render;
+ render->render = clazz->render_glyph;
+ }
+
+ /* add to list */
+ node->data = module;
+ FT_List_Add( &library->renderers, node );
+
+ ft_set_current_renderer( library );
+ }
+
+ Fail:
+ if ( error )
+ FREE( node );
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ void ft_remove_renderer( FT_Module module )
+ {
+ FT_Library library = module->library;
+ FT_Memory memory = library->memory;
+ FT_ListNode node;
+
+
+ node = FT_List_Find( &library->renderers, module );
+ if ( node )
+ {
+ FT_Renderer render = FT_RENDERER( module );
+
+
+ /* release raster object, if any */
+ if ( render->raster )
+ render->clazz->raster_class->raster_done( render->raster );
+
+ /* remove from list */
+ FT_List_Remove( &library->renderers, node );
+ FREE( node );
+
+ ft_set_current_renderer( library );
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Renderer */
+ /* */
+ /* <Description> */
+ /* Retrieves the current renderer for a given glyph format. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* format :: The glyph format. */
+ /* */
+ /* <Return> */
+ /* A renderer handle. 0 if none found. */
+ /* */
+ /* <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. */
+ /* */
+ /* To add a new renderer, simply use FT_Add_Module(). To retrieve a */
+ /* renderer by its name, use FT_Get_Module(). */
+ /* */
+ FT_EXPORT_FUNC( FT_Renderer ) FT_Get_Renderer( FT_Library library,
+ FT_Glyph_Format format )
+ {
+ /* test for valid `library' delayed to FT_Lookup_Renderer() */
+
+ return FT_Lookup_Renderer( library, format, 0 );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Renderer */
+ /* */
+ /* <Description> */
+ /* Sets the current renderer to use, and set additional mode. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* renderer :: A handle to the renderer object. */
+ /* */
+ /* num_params :: The number of additional parameters. */
+ /* */
+ /* parameters :: Additional parameters. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* In case of success, the renderer will be used to convert glyph */
+ /* images in the renderer's known format into bitmaps. */
+ /* */
+ /* This doesn't change the current renderer for other formats. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Set_Renderer( FT_Library library,
+ FT_Renderer renderer,
+ FT_UInt num_params,
+ FT_Parameter* parameters )
+ {
+ FT_ListNode node;
+ FT_Error error = FT_Err_Ok;
+
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ if ( !renderer )
+ return FT_Err_Invalid_Argument;
+
+ node = FT_List_Find( &library->renderers, renderer );
+ if ( !node )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ FT_List_Up( &library->renderers, node );
+
+ if ( renderer->glyph_format == ft_glyph_format_outline )
+ library->cur_renderer = renderer;
+
+ if ( num_params > 0 )
+ {
+ FTRenderer_setMode set_mode = renderer->clazz->set_mode;
+
+
+ for ( ; num_params > 0; num_params-- )
+ {
+ error = set_mode( renderer, parameters->tag, parameters->data );
+ if ( error )
+ break;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ FT_Error FT_Render_Glyph_Internal( FT_Library library,
+ FT_GlyphSlot slot,
+ FT_UInt render_mode )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Renderer renderer;
+
+
+ /* if it is already a bitmap, no need to do anything */
+ switch ( slot->format )
+ {
+ case ft_glyph_format_bitmap: /* already a bitmap, don't do anything */
+ break;
+
+ default:
+ {
+ FT_ListNode node = 0;
+ FT_Bool update = 0;
+
+
+ /* small shortcut for the very common case */
+ if ( slot->format == ft_glyph_format_outline )
+ {
+ renderer = library->cur_renderer;
+ node = library->renderers.head;
+ }
+ else
+ renderer = FT_Lookup_Renderer( library, slot->format, &node );
+
+ error = FT_Err_Unimplemented_Feature;
+ while ( renderer )
+ {
+ error = renderer->render( renderer, slot, render_mode, 0 );
+ if ( !error || error != FT_Err_Cannot_Render_Glyph )
+ break;
+
+ /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
+ /* is unsupported by the current renderer for this glyph image */
+ /* format. */
+
+ /* now, look for another renderer that supports the same */
+ /* format. */
+ renderer = FT_Lookup_Renderer( library, slot->format, &node );
+ update = 1;
+ }
+
+ /* if we changed the current renderer for the glyph image format */
+ /* we need to select it as the next current one */
+ if ( !error && update && renderer )
+ FT_Set_Renderer( library, renderer, 0, 0 );
+ }
+ }
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Render_Glyph */
+ /* */
+ /* <Description> */
+ /* Converts a given glyph image to a bitmap. It does so by */
+ /* inspecting the glyph image format, find the relevant renderer, and */
+ /* invoke it. */
+ /* */
+ /* <Input> */
+ /* slot :: A handle to the glyph slot containing the image to */
+ /* convert. */
+ /* */
+ /* render_mode :: This is the render mode used to render the glyph */
+ /* image into a bitmap. See FT_Render_Mode for a list */
+ /* of possible values. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Render_Glyph( FT_GlyphSlot slot,
+ FT_UInt render_mode )
+ {
+ FT_Library library;
+
+
+ if ( !slot )
+ return FT_Err_Invalid_Argument;
+
+ library = FT_FACE_LIBRARY( slot->face );
+
+ return FT_Render_Glyph_Internal( library, slot, render_mode );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** M O D U L E S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Destroy_Module */
+ /* */
+ /* <Description> */
+ /* Destroys a given module object. For drivers, this also destroys */
+ /* all child faces. */
+ /* */
+ /* <InOut> */
+ /* module :: A handle to the target driver object. */
+ /* */
+ /* <Note> */
+ /* The driver _must_ be LOCKED! */
+ /* */
+ static
+ void Destroy_Module( FT_Module module )
+ {
+ FT_Memory memory = module->memory;
+ FT_Module_Class* clazz = module->clazz;
+ FT_Library library = module->library;
+
+
+ /* finalize client-data - before anything else */
+ if ( module->generic.finalizer )
+ module->generic.finalizer( module );
+
+ if ( library && library->auto_hinter == module )
+ library->auto_hinter = 0;
+
+ /* if the module is a renderer */
+ if ( FT_MODULE_IS_RENDERER( module ) )
+ ft_remove_renderer( module );
+
+ /* if the module is a font driver, add some steps */
+ if ( FT_MODULE_IS_DRIVER( module ) )
+ Destroy_Driver( FT_DRIVER( module ) );
+
+ /* finalize the module object */
+ if ( clazz->module_done )
+ clazz->module_done( module );
+
+ /* discard it */
+ FREE( module );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Add_Module */
+ /* */
+ /* <Description> */
+ /* Adds a new module to a given library instance. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* 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_FUNC( FT_Error ) FT_Add_Module( FT_Library library,
+ const FT_Module_Class* clazz )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FT_Module module;
+ FT_UInt nn;
+
+
+#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
+ FREETYPE_MINOR )
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ if ( !clazz )
+ return FT_Err_Invalid_Argument;
+
+ /* check freetype version */
+ if ( clazz->module_requires > FREETYPE_VER_FIXED )
+ return FT_Err_Invalid_Version;
+
+ /* look for a module with the same name in the library's table */
+ for ( nn = 0; nn < library->num_modules; nn++ )
+ {
+ module = library->modules[nn];
+ if ( strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
+ {
+ /* this installed module has the same name, compare their versions */
+ if ( clazz->module_version <= module->clazz->module_version )
+ return FT_Err_Lower_Module_Version;
+
+ /* remove the module from our list, then exit the loop to replace */
+ /* it by our new version.. */
+ FT_Remove_Module( library, module );
+ break;
+ }
+ }
+
+ memory = library->memory;
+ error = FT_Err_Ok;
+
+ if ( library->num_modules >= FT_MAX_MODULES )
+ {
+ error = FT_Err_Too_Many_Drivers;
+ goto Exit;
+ }
+
+ /* allocate module object */
+ if ( ALLOC( module,clazz->module_size ) )
+ goto Exit;
+
+ /* base initialization */
+ module->library = library;
+ module->memory = memory;
+ module->clazz = (FT_Module_Class*)clazz;
+
+ /* check whether the module is a renderer - this must be performed */
+ /* before the normal module initialization */
+ if ( FT_MODULE_IS_RENDERER( module ) )
+ {
+ /* add to the renderers list */
+ error = ft_add_renderer( module );
+ if ( error )
+ goto Fail;
+ }
+
+ /* is the module a auto-hinter? */
+ if ( FT_MODULE_IS_HINTER( module ) )
+ library->auto_hinter = module;
+
+ /* if the module is a font driver */
+ if ( FT_MODULE_IS_DRIVER( module ) )
+ {
+ /* allocate glyph loader if needed */
+ FT_Driver driver = FT_DRIVER( module );
+
+
+ driver->clazz = (FT_Driver_Class*)module->clazz;
+ if ( FT_DRIVER_USES_OUTLINES( driver ) )
+ {
+ error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
+ if ( error )
+ goto Fail;
+ }
+ }
+
+ if ( clazz->module_init )
+ {
+ error = clazz->module_init( module );
+ if ( error )
+ goto Fail;
+ }
+
+ /* add module to the library's table */
+ library->modules[library->num_modules++] = module;
+
+ Exit:
+ return error;
+
+ Fail:
+ if ( FT_MODULE_IS_DRIVER( module ) )
+ {
+ FT_Driver driver = FT_DRIVER( module );
+
+
+ if ( FT_DRIVER_USES_OUTLINES( driver ) )
+ FT_GlyphLoader_Done( driver->glyph_loader );
+ }
+
+ if ( FT_MODULE_IS_RENDERER( module ) )
+ {
+ FT_Renderer renderer = FT_RENDERER( module );
+
+
+ if ( renderer->raster )
+ renderer->clazz->raster_class->raster_done( renderer->raster );
+ }
+
+ FREE( module );
+ goto Exit;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <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_FUNC( FT_Module ) FT_Get_Module( FT_Library library,
+ const char* module_name )
+ {
+ FT_Module result = 0;
+ FT_Module* cur;
+ FT_Module* limit;
+
+
+ if ( !library || !module_name )
+ return result;
+
+ cur = library->modules;
+ limit = cur + library->num_modules;
+
+ for ( ; cur < limit; cur++ )
+ if ( strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
+ {
+ result = cur[0];
+ break;
+ }
+
+ return result;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Module_Interface */
+ /* */
+ /* <Description> */
+ /* Finds a module and returns its specific interface as a typeless */
+ /* pointer. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* module_name :: The module's name (as an ASCII string). */
+ /* */
+ /* <Return> */
+ /* A module-specific interface if available, 0 otherwise. */
+ /* */
+ /* <Note> */
+ /* You should better be familiar with FreeType internals to know */
+ /* which module to look for, and what its interface is :-) */
+ /* */
+ BASE_FUNC( const void* ) FT_Get_Module_Interface( FT_Library library,
+ const char* mod_name )
+ {
+ FT_Module module;
+
+
+ /* test for valid `library' delayed to FT_Get_Module() */
+
+ module = FT_Get_Module( library, mod_name );
+
+ return module ? module->clazz->module_interface : 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Remove_Module */
+ /* */
+ /* <Description> */
+ /* Removes a given module from a library instance. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to a library object. */
+ /* */
+ /* 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_FUNC( FT_Error ) FT_Remove_Module( FT_Library library,
+ FT_Module module )
+ {
+ /* try to find the module from the table, then remove it from there */
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ if ( module )
+ {
+ FT_Module* cur = library->modules;
+ FT_Module* limit = cur + library->num_modules;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ if ( cur[0] == module )
+ {
+ /* remove it from the table */
+ library->num_modules--;
+ limit--;
+ while ( cur < limit )
+ {
+ cur[0] = cur[1];
+ cur++;
+ }
+ limit[0] = 0;
+
+ /* destroy the module */
+ Destroy_Module( module );
+
+ return FT_Err_Ok;
+ }
+ }
+ }
+ return FT_Err_Invalid_Driver_Handle;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** L I B R A R Y ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <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_FUNC( FT_Error ) FT_New_Library( FT_Memory memory,
+ FT_Library* alibrary )
+ {
+ FT_Library library = 0;
+ FT_Error error;
+
+
+ if ( !memory )
+ return FT_Err_Invalid_Argument;
+
+ /* first of all, allocate the library object */
+ if ( ALLOC( library, sizeof ( *library ) ) )
+ return error;
+
+ library->memory = memory;
+
+ /* allocate the render pool */
+ library->raster_pool_size = FT_RENDER_POOL_SIZE;
+ if ( ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
+ goto Fail;
+
+ /* That's ok now */
+ *alibrary = library;
+
+ return FT_Err_Ok;
+
+ Fail:
+ FREE( library );
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <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_FUNC( FT_Error ) FT_Done_Library( FT_Library library )
+ {
+ FT_Memory memory;
+ FT_UInt n;
+
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ memory = library->memory;
+
+ /* Discard client-data */
+ if ( library->generic.finalizer )
+ library->generic.finalizer( library );
+
+ /* Close all modules in the library */
+ for ( n = 0; n < library->num_modules; n++ )
+ {
+ FT_Module module = library->modules[n];
+
+
+ if ( module )
+ {
+ Destroy_Module( module );
+ library->modules[n] = 0;
+ }
+ }
+
+ /* Destroy raster objects */
+ FREE( library->raster_pool );
+ library->raster_pool_size = 0;
+
+ FREE( library );
+ return FT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Debug_Hook */
+ /* */
+ /* <Description> */
+ /* Sets a debug hook function for debugging the interpreter of a font */
+ /* format. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* 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_FUNC( void ) FT_Set_Debug_Hook( FT_Library library,
+ FT_UInt hook_index,
+ FT_DebugHook_Func debug_hook )
+ {
+ if ( library && debug_hook &&
+ hook_index <
+ ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
+ library->debug_hooks[hook_index] = debug_hook;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_FreeType */
+ /* */
+ /* <Description> */
+ /* Destroys a given FreeType library object and all of its childs, */
+ /* including resources, drivers, faces, sizes, etc. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the target library object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Done_FreeType( FT_Library library )
+ {
+ /* test for valid `library' delayed to FT_Done_Library() */
+
+ /* Discard the library object */
+ FT_Done_Library( library );
+
+ return FT_Err_Ok;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftoutln.c */
+/* */
+/* FreeType outline management (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* All functions are declared in freetype.h. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/ftoutln.h>
+#include <freetype/internal/ftobjs.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_outline
+
+
+ static
+ const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 };
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Decompose */
+ /* */
+ /* <Description> */
+ /* Walks over an outline's structure to decompose it into individual */
+ /* segments and Bezier arcs. This function is also able to emit */
+ /* `move to' and `close to' operations to indicate the start and end */
+ /* of new contours in the outline. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the source target. */
+ /* */
+ /* interface :: A table of `emitters', i.e,. function pointers called */
+ /* during decomposition to indicate path operations. */
+ /* */
+ /* user :: A typeless pointer which is passed to each emitter */
+ /* during the decomposition. It can be used to store */
+ /* the state during the decomposition. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means sucess. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Outline_Decompose(
+ FT_Outline* outline,
+ FT_Outline_Funcs* interface,
+ void* user )
+ {
+#undef SCALED
+#define SCALED( x ) ( ( (x) << shift ) - delta )
+
+ FT_Vector v_last;
+ FT_Vector v_control;
+ FT_Vector v_start;
+
+ FT_Vector* point;
+ FT_Vector* limit;
+ char* tags;
+
+ FT_Error error;
+
+ FT_Int n; /* index of contour in outline */
+ FT_UInt first; /* index of first point in contour */
+ char tag; /* current point's state */
+
+ FT_Int shift;
+ FT_Pos delta;
+
+
+ if ( !outline || !interface )
+ return FT_Err_Invalid_Argument;
+
+ shift = interface->shift;
+ delta = interface->delta;
+ first = 0;
+
+ for ( n = 0; n < outline->n_contours; n++ )
+ {
+ FT_Int last; /* index of last point in contour */
+
+
+ last = outline->contours[n];
+ limit = outline->points + last;
+
+ v_start = outline->points[first];
+ v_last = outline->points[last];
+
+ v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
+ v_last.x = SCALED( v_last.x ); v_last.y = SCALED( v_last.y );
+
+ v_control = v_start;
+
+ point = outline->points + first;
+ tags = outline->tags + first;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ /* A contour cannot start with a cubic control point! */
+ if ( tag == FT_Curve_Tag_Cubic )
+ goto Invalid_Outline;
+
+ /* check first point to determine origin */
+ if ( tag == FT_Curve_Tag_Conic )
+ {
+ /* first point is conic control. Yes, this happens. */
+ if ( FT_CURVE_TAG( outline->tags[last] ) == FT_Curve_Tag_On )
+ {
+ /* start at last point if it is on the curve */
+ v_start = v_last;
+ limit--;
+ }
+ else
+ {
+ /* if both first and last points are conic, */
+ /* start at their middle and record its position */
+ /* for closure */
+ v_start.x = ( v_start.x + v_last.x ) / 2;
+ v_start.y = ( v_start.y + v_last.y ) / 2;
+
+ v_last = v_start;
+ }
+ point--;
+ tags--;
+ }
+
+ error = interface->move_to( &v_start, user );
+ if ( error )
+ goto Exit;
+
+ while ( point < limit )
+ {
+ point++;
+ tags++;
+
+ tag = FT_CURVE_TAG( tags[0] );
+ switch ( tag )
+ {
+ case FT_Curve_Tag_On: /* emit a single line_to */
+ {
+ FT_Vector vec;
+
+
+ vec.x = SCALED( point->x );
+ vec.y = SCALED( point->y );
+
+ error = interface->line_to( &vec, user );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ case FT_Curve_Tag_Conic: /* consume conic arcs */
+ v_control.x = SCALED( point->x );
+ v_control.y = SCALED( point->y );
+
+ Do_Conic:
+ if ( point < limit )
+ {
+ FT_Vector vec;
+ FT_Vector v_middle;
+
+
+ point++;
+ tags++;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ vec.x = SCALED( point->x );
+ vec.y = SCALED( point->y );
+
+ if ( tag == FT_Curve_Tag_On )
+ {
+ error = interface->conic_to( &v_control, &vec, user );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ if ( tag != FT_Curve_Tag_Conic )
+ goto Invalid_Outline;
+
+ v_middle.x = ( v_control.x + vec.x ) / 2;
+ v_middle.y = ( v_control.y + vec.y ) / 2;
+
+ error = interface->conic_to( &v_control, &v_middle, user );
+ if ( error )
+ goto Exit;
+
+ v_control = vec;
+ goto Do_Conic;
+ }
+
+ error = interface->conic_to( &v_control, &v_start, user );
+ goto Close;
+
+ default: /* FT_Curve_Tag_Cubic */
+ {
+ FT_Vector vec1, vec2;
+
+
+ if ( point + 1 > limit ||
+ FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
+ goto Invalid_Outline;
+
+ point += 2;
+ tags += 2;
+
+ vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
+ vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
+
+ if ( point <= limit )
+ {
+ FT_Vector vec;
+
+
+ vec.x = SCALED( point->x );
+ vec.y = SCALED( point->y );
+
+ error = interface->cubic_to( &vec1, &vec2, &vec, user );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ error = interface->cubic_to( &vec1, &vec2, &v_start, user );
+ goto Close;
+ }
+ }
+ }
+
+ /* close the contour with a line segment */
+ error = interface->line_to( &v_start, user );
+
+ Close:
+ if ( error )
+ goto Exit;
+
+ first = last + 1;
+ }
+
+ return 0;
+
+ Exit:
+ return error;
+
+ Invalid_Outline:
+ return FT_Err_Invalid_Outline;
+ }
+
+
+ FT_EXPORT_FUNC( FT_Error ) FT_Outline_New_Internal(
+ FT_Memory memory,
+ FT_UInt numPoints,
+ FT_Int numContours,
+ FT_Outline* outline )
+ {
+ FT_Error error;
+
+
+ if ( !outline || !memory )
+ return FT_Err_Invalid_Argument;
+
+ *outline = null_outline;
+
+ if ( ALLOC_ARRAY( outline->points, numPoints * 2L, FT_Pos ) ||
+ ALLOC_ARRAY( outline->tags, numPoints, FT_Byte ) ||
+ ALLOC_ARRAY( outline->contours, numContours, FT_UShort ) )
+ goto Fail;
+
+ outline->n_points = (FT_UShort)numPoints;
+ outline->n_contours = (FT_Short)numContours;
+ outline->flags |= ft_outline_owner;
+
+ return FT_Err_Ok;
+
+ Fail:
+ outline->flags |= ft_outline_owner;
+ FT_Outline_Done_Internal( memory, outline );
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_New */
+ /* */
+ /* <Description> */
+ /* Creates a new outline of a given size. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object from where the */
+ /* outline is allocated. Note however that the new */
+ /* outline will NOT necessarily be FREED, when */
+ /* destroying the library, by FT_Done_FreeType(). */
+ /* */
+ /* numPoints :: The maximal number of points within the outline. */
+ /* */
+ /* numContours :: The maximal number of contours within the outline. */
+ /* */
+ /* <Output> */
+ /* outline :: A handle to the new outline. NULL in case of */
+ /* error. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <MT-Note> */
+ /* No. */
+ /* */
+ /* <Note> */
+ /* The reason why this function takes a `library' parameter is simply */
+ /* to use the library's memory allocator. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Outline_New( FT_Library library,
+ FT_UInt numPoints,
+ FT_Int numContours,
+ FT_Outline* outline )
+ {
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ return FT_Outline_New_Internal( library->memory, numPoints,
+ numContours, outline );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Copy */
+ /* */
+ /* <Description> */
+ /* Copies an outline into another one. Both objects must have the */
+ /* same sizes (number of points & number of contours) when this */
+ /* function is called. */
+ /* */
+ /* <Input> */
+ /* source :: A handle to the source outline. */
+ /* */
+ /* <Output> */
+ /* target :: A handle to the target outline. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Outline_Copy( FT_Outline* source,
+ FT_Outline* target )
+ {
+ FT_Int is_owner;
+
+
+ if ( !source || !target ||
+ source->n_points != target->n_points ||
+ source->n_contours != target->n_contours )
+ return FT_Err_Invalid_Argument;
+
+ MEM_Copy( target->points, source->points,
+ source->n_points * sizeof ( FT_Vector ) );
+
+ MEM_Copy( target->tags, source->tags,
+ source->n_points * sizeof ( FT_Byte ) );
+
+ MEM_Copy( target->contours, source->contours,
+ source->n_contours * sizeof ( FT_Short ) );
+
+ /* copy all flags, except the `ft_outline_owner' one */
+ is_owner = target->flags & ft_outline_owner;
+ target->flags = source->flags;
+
+ target->flags &= ~ft_outline_owner;
+ target->flags |= is_owner;
+
+ return FT_Err_Ok;
+ }
+
+
+ FT_EXPORT_FUNC( FT_Error ) FT_Outline_Done_Internal( FT_Memory memory,
+ FT_Outline* outline )
+ {
+ if ( outline )
+ {
+ if ( outline->flags & ft_outline_owner )
+ {
+ FREE( outline->points );
+ FREE( outline->tags );
+ FREE( outline->contours );
+ }
+ *outline = null_outline;
+
+ return FT_Err_Ok;
+ }
+ else
+ return FT_Err_Invalid_Argument;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Done */
+ /* */
+ /* <Description> */
+ /* Destroys an outline created with FT_Outline_New(). */
+ /* */
+ /* <Input> */
+ /* library :: A handle of the library object used to allocate the */
+ /* outline. */
+ /* */
+ /* outline :: A pointer to the outline object to be discarded. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <MT-Note> */
+ /* No. */
+ /* */
+ /* <Note> */
+ /* If the outline's `owner' field is not set, only the outline */
+ /* descriptor will be released. */
+ /* */
+ /* The reason why this function takes an `outline' parameter is */
+ /* simply to use FT_Free(). */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Outline_Done( FT_Library library,
+ FT_Outline* outline )
+ {
+ /* check for valid `outline' in FT_Outline_Done_Internal() */
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ return FT_Outline_Done_Internal( library->memory, outline );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Get_CBox */
+ /* */
+ /* <Description> */
+ /* Returns an outline's `control box'. The control box encloses all */
+ /* the outline's points, including Bezier control points. Though it */
+ /* coincides with the exact bounding box for most glyphs, it can be */
+ /* slightly larger in some situations (like when rotating an outline */
+ /* which contains Bezier outside arcs). */
+ /* */
+ /* Computing the control box is very fast, while getting the bounding */
+ /* box can take much more time as it needs to walk over all segments */
+ /* and arcs in the outline. To get the latter, you can use the */
+ /* `ftbbox' component which is dedicated to this single task. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the source outline descriptor. */
+ /* */
+ /* <Output> */
+ /* cbox :: The outline's control box. */
+ /* */
+ /* <MT-Note> */
+ /* Yes. */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_Outline_Get_CBox( FT_Outline* outline,
+ FT_BBox* cbox )
+ {
+ FT_Pos xMin, yMin, xMax, yMax;
+
+
+ if ( outline && cbox )
+ {
+ if ( outline->n_points == 0 )
+ {
+ xMin = 0;
+ yMin = 0;
+ xMax = 0;
+ yMax = 0;
+ }
+ else
+ {
+ FT_Vector* vec = outline->points;
+ FT_Vector* limit = vec + outline->n_points;
+
+
+ xMin = xMax = vec->x;
+ yMin = yMax = vec->y;
+ vec++;
+
+ for ( ; vec < limit; vec++ )
+ {
+ FT_Pos x, y;
+
+
+ x = vec->x;
+ if ( x < xMin ) xMin = x;
+ if ( x > xMax ) xMax = x;
+
+ y = vec->y;
+ if ( y < yMin ) yMin = y;
+ if ( y > yMax ) yMax = y;
+ }
+ }
+ cbox->xMin = xMin;
+ cbox->xMax = xMax;
+ cbox->yMin = yMin;
+ cbox->yMax = yMax;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Translate */
+ /* */
+ /* <Description> */
+ /* Applies a simple translation to the points of an outline. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the target outline descriptor. */
+ /* */
+ /* xOffset :: The horizontal offset. */
+ /* */
+ /* yOffset :: The vertical offset. */
+ /* */
+ /* <MT-Note> */
+ /* Yes. */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_Outline_Translate( FT_Outline* outline,
+ FT_Pos xOffset,
+ FT_Pos yOffset )
+ {
+ FT_UShort n;
+ FT_Vector* vec = outline->points;
+
+
+ for ( n = 0; n < outline->n_points; n++ )
+ {
+ vec->x += xOffset;
+ vec->y += yOffset;
+ vec++;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Reverse */
+ /* */
+ /* <Description> */
+ /* Reverses the drawing direction of an outline. This is used to */
+ /* ensure consistent fill conventions for mirrored glyphs. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the target outline descriptor. */
+ /* */
+ /* <Note> */
+ /* This functions toggles the bit flag `ft_outline_reverse_fill' in */
+ /* the outline's `flags' field. */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_Outline_Reverse( FT_Outline* outline )
+ {
+ FT_UShort n;
+ FT_Int first, last;
+
+
+ first = 0;
+
+ for ( n = 0; n < outline->n_contours; n++ )
+ {
+ last = outline->contours[n];
+
+ /* reverse point table */
+ {
+ FT_Vector* p = outline->points + first;
+ FT_Vector* q = outline->points + last;
+ FT_Vector swap;
+
+
+ while ( p < q )
+ {
+ swap = *p;
+ *p = *q;
+ *q = swap;
+ p++;
+ q--;
+ }
+ }
+
+ /* reverse tags table */
+ {
+ char* p = outline->tags + first;
+ char* q = outline->tags + last;
+ char swap;
+
+
+ while ( p < q )
+ {
+ swap = *p;
+ *p = *q;
+ *q = swap;
+ p++;
+ q--;
+ }
+ }
+
+ first = last + 1;
+ }
+
+ outline->flags ^= ft_outline_reverse_fill;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Render */
+ /* */
+ /* <Description> */
+ /* Renders an outline within a bitmap using the current scan-convert. */
+ /* This functions uses an FT_Raster_Params structure as an argument, */
+ /* allowing advanced features like direct composition, translucency, */
+ /* etc. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to a FreeType library object. */
+ /* */
+ /* outline :: A pointer to the source outline descriptor. */
+ /* */
+ /* params :: A pointer to a FT_Raster_Params structure used to */
+ /* describe the rendering operation. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <MT-Note> */
+ /* YES. Rendering is synchronized, so that concurrent calls to the */
+ /* scan-line converter will be serialized. */
+ /* */
+ /* <Note> */
+ /* You should know what you are doing and how FT_Raster_Params works */
+ /* to use this function. */
+ /* */
+ /* The field `params.source' will be set to `outline' before the scan */
+ /* converter is called, which means that the value you give to it is */
+ /* actually ignored. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Outline_Render( FT_Library library,
+ FT_Outline* outline,
+ FT_Raster_Params* params )
+ {
+ FT_Error error;
+ FT_Bool update = 0;
+ FT_Renderer renderer;
+ FT_ListNode node;
+
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ if ( !params )
+ return FT_Err_Invalid_Argument;
+
+ renderer = library->cur_renderer;
+ node = library->renderers.head;
+
+ params->source = (void*)outline;
+
+ error = FT_Err_Cannot_Render_Glyph;
+ while ( renderer )
+ {
+ error = renderer->raster_render( renderer->raster, params );
+ if ( !error || error != FT_Err_Cannot_Render_Glyph )
+ break;
+
+ /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
+ /* is unsupported by the current renderer for this glyph image */
+ /* format */
+
+ /* now, look for another renderer that supports the same */
+ /* format */
+ renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline,
+ &node );
+ update = 1;
+ }
+
+ /* if we changed the current renderer for the glyph image format */
+ /* we need to select it as the next current one */
+ if ( !error && update && renderer )
+ FT_Set_Renderer( library, renderer, 0, 0 );
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Get_Bitmap */
+ /* */
+ /* <Description> */
+ /* Renders an outline within a bitmap. The outline's image is simply */
+ /* OR-ed to the target bitmap. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to a FreeType library object. */
+ /* */
+ /* outline :: A pointer to the source outline descriptor. */
+ /* */
+ /* map :: A pointer to the target bitmap descriptor. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <MT-Note> */
+ /* YES. Rendering is synchronized, so that concurrent calls to the */
+ /* scan-line converter will be serialized. */
+ /* */
+ /* <Note> */
+ /* This function does NOT CREATE the bitmap, it only renders an */
+ /* outline image within the one you pass to it! */
+ /* */
+ /* It will use the raster correponding to the default glyph format. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Outline_Get_Bitmap( FT_Library library,
+ FT_Outline* outline,
+ FT_Bitmap* bitmap )
+ {
+ FT_Raster_Params params;
+
+
+ if ( !bitmap )
+ return FT_Err_Invalid_Argument;
+
+ /* other checks are delayed to FT_Outline_Render() */
+
+ params.target = bitmap;
+ params.flags = 0;
+
+ if ( bitmap->pixel_mode == ft_pixel_mode_grays )
+ params.flags |= ft_raster_flag_aa;
+
+ return FT_Outline_Render( library, outline, ¶ms );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Vector_Transform */
+ /* */
+ /* <Description> */
+ /* Transforms a single vector through a 2x2 matrix. */
+ /* */
+ /* <InOut> */
+ /* vector :: The target vector to transform. */
+ /* */
+ /* <Input> */
+ /* matrix :: A pointer to the source 2x2 matrix. */
+ /* */
+ /* <MT-Note> */
+ /* Yes. */
+ /* */
+ /* <Note> */
+ /* The result is undefined if either `vector' or `matrix' is invalid. */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_Vector_Transform( FT_Vector* vector,
+ FT_Matrix* matrix )
+ {
+ FT_Pos xz, yz;
+
+
+ if ( !vector || !matrix )
+ return;
+
+ xz = FT_MulFix( vector->x, matrix->xx ) +
+ FT_MulFix( vector->y, matrix->xy );
+
+ yz = FT_MulFix( vector->x, matrix->yx ) +
+ FT_MulFix( vector->y, matrix->yy );
+
+ vector->x = xz;
+ vector->y = yz;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Transform */
+ /* */
+ /* <Description> */
+ /* Applies a simple 2x2 matrix to all of an outline's points. Useful */
+ /* for applying rotations, slanting, flipping, etc. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the target outline descriptor. */
+ /* */
+ /* matrix :: A pointer to the transformation matrix. */
+ /* */
+ /* <MT-Note> */
+ /* Yes. */
+ /* */
+ /* <Note> */
+ /* You can use FT_Outline_Translate() if you need to translate the */
+ /* outline's points. */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_Outline_Transform( FT_Outline* outline,
+ FT_Matrix* matrix )
+ {
+ FT_Vector* vec = outline->points;
+ FT_Vector* limit = vec + outline->n_points;
+
+
+ for ( ; vec < limit; vec++ )
+ FT_Vector_Transform( vec, matrix );
+ }
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftstream.c */
+/* */
+/* I/O stream support (body). */
+/* */
+/* Copyright 2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/ftdebug.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_stream
+
+
+ BASE_FUNC( void ) FT_New_Memory_Stream( FT_Library library,
+ FT_Byte* base,
+ FT_ULong size,
+ FT_Stream stream )
+ {
+ stream->memory = library->memory;
+ stream->base = base;
+ stream->size = size;
+ stream->pos = 0;
+ stream->cursor = 0;
+ stream->read = 0;
+ stream->close = 0;
+ }
+
+
+ BASE_FUNC( FT_Error ) FT_Seek_Stream( FT_Stream stream,
+ FT_ULong pos )
+ {
+ FT_Error error;
+
+
+ stream->pos = pos;
+
+ if ( stream->read )
+ {
+ if ( stream->read( stream, pos, 0, 0 ) )
+ {
+ FT_ERROR(( "FT_Seek_Stream:" ));
+ FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ pos, stream->size ));
+
+ error = FT_Err_Invalid_Stream_Operation;
+ }
+ else
+ error = FT_Err_Ok;
+ }
+ /* note that seeking to the first position after the file is valid */
+ else if ( pos > stream->size )
+ {
+ FT_ERROR(( "FT_Seek_Stream:" ));
+ FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ pos, stream->size ));
+
+ error = FT_Err_Invalid_Stream_Operation;
+ }
+
+ else
+ error = FT_Err_Ok;
+
+ return error;
+ }
+
+
+ BASE_FUNC( FT_Error ) FT_Skip_Stream( FT_Stream stream,
+ FT_Long distance )
+ {
+ return FT_Seek_Stream( stream, (FT_ULong)( stream->pos + distance ) );
+ }
+
+
+ BASE_FUNC( FT_Long ) FT_Stream_Pos( FT_Stream stream )
+ {
+ return stream->pos;
+ }
+
+
+ BASE_FUNC( FT_Error ) FT_Read_Stream( FT_Stream stream,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ return FT_Read_Stream_At( stream, stream->pos, buffer, count );
+ }
+
+
+ BASE_FUNC( FT_Error ) FT_Read_Stream_At( FT_Stream stream,
+ FT_ULong pos,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_ULong read_bytes;
+
+
+ if ( pos >= stream->size )
+ {
+ FT_ERROR(( "FT_Read_Stream_At:" ));
+ FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ pos, stream->size ));
+
+ return FT_Err_Invalid_Stream_Operation;
+ }
+
+ if ( stream->read )
+ read_bytes = stream->read( stream, pos, buffer, count );
+ else
+ {
+ read_bytes = stream->size - pos;
+ if ( read_bytes > count )
+ read_bytes = count;
+
+ MEM_Copy( buffer, stream->base + pos, read_bytes );
+ }
+
+ stream->pos = pos + read_bytes;
+
+ if ( read_bytes < count )
+ {
+ FT_ERROR(( "FT_Read_Stream_At:" ));
+ FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
+ count, read_bytes ));
+
+ error = FT_Err_Invalid_Stream_Operation;
+ }
+
+ return error;
+ }
+
+
+ BASE_FUNC( FT_Error ) FT_Extract_Frame( FT_Stream stream,
+ FT_ULong count,
+ FT_Byte** pbytes )
+ {
+ FT_Error error;
+
+
+ error = FT_Access_Frame( stream, count );
+ if ( !error )
+ {
+ *pbytes = (FT_Byte*)stream->cursor;
+
+ /* equivalent to FT_Forget_Frame(), with no memory block release */
+ stream->cursor = 0;
+ stream->limit = 0;
+ }
+
+ return error;
+ }
+
+
+ BASE_FUNC( void ) FT_Release_Frame( FT_Stream stream,
+ FT_Byte** pbytes )
+ {
+ if ( stream->read )
+ {
+ FT_Memory memory = stream->memory;
+
+
+ FREE( *pbytes );
+ }
+ *pbytes = 0;
+ }
+
+
+ BASE_FUNC( FT_Error ) FT_Access_Frame( FT_Stream stream,
+ FT_ULong count )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_ULong read_bytes;
+
+
+ /* check for nested frame access */
+ FT_Assert( stream && stream->cursor == 0 );
+
+ if ( stream->read )
+ {
+ /* allocate the frame in memory */
+ FT_Memory memory = stream->memory;
+
+
+ if ( ALLOC( stream->base, count ) )
+ goto Exit;
+
+ /* read it */
+ read_bytes = stream->read( stream, stream->pos,
+ stream->base, count );
+ if ( read_bytes < count )
+ {
+ FT_ERROR(( "FT_Access_Frame:" ));
+ FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
+ count, read_bytes ));
+
+ FREE( stream->base );
+ error = FT_Err_Invalid_Stream_Operation;
+ }
+ stream->cursor = stream->base;
+ stream->limit = stream->cursor + count;
+ stream->pos += read_bytes;
+ }
+ else
+ {
+ /* check current and new position */
+ if ( stream->pos >= stream->size ||
+ stream->pos + count > stream->size )
+ {
+ FT_ERROR(( "FT_Access_Frame:" ));
+ FT_ERROR(( " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
+ stream->pos, count, stream->size ));
+
+ error = FT_Err_Invalid_Stream_Operation;
+ goto Exit;
+ }
+
+ /* set cursor */
+ stream->cursor = stream->base + stream->pos;
+ stream->limit = stream->cursor + count;
+ stream->pos += count;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ BASE_FUNC( void ) FT_Forget_Frame( FT_Stream stream )
+ {
+ /* IMPORTANT: The assertion stream->cursor != 0 was removed, given */
+ /* that it is possible to access a frame of length 0 in */
+ /* some weird fonts (usually, when accessing an array of */
+ /* 0 records, like in some strange kern tables). */
+ /* */
+ /* In this case, the loader code handles the 0-length table */
+ /* gracefully; however, stream.cursor is really set to 0 by the */
+ /* FT_Access_Frame() call, and this is not an error. */
+ /* */
+ FT_Assert( stream );
+
+ if ( stream->read )
+ {
+ FT_Memory memory = stream->memory;
+
+
+ FREE( stream->base );
+ }
+ stream->cursor = 0;
+ stream->limit = 0;
+ }
+
+
+ BASE_FUNC( FT_Char ) FT_Get_Char( FT_Stream stream )
+ {
+ FT_Char result;
+
+
+ FT_Assert( stream && stream->cursor );
+
+ result = 0;
+ if ( stream->cursor < stream->limit )
+ result = *stream->cursor++;
+
+ return result;
+ }
+
+
+ BASE_FUNC( FT_Short ) FT_Get_Short( FT_Stream stream )
+ {
+ FT_Byte* p;
+ FT_Short result;
+
+
+ FT_Assert( stream && stream->cursor );
+
+ result = 0;
+ p = stream->cursor;
+ if ( p + 1 < stream->limit )
+ result = NEXT_Short( p );
+ stream->cursor = p;
+
+ return result;
+ }
+
+
+ BASE_FUNC( FT_Short ) FT_Get_ShortLE( FT_Stream stream )
+ {
+ FT_Byte* p;
+ FT_Short result;
+
+
+ FT_Assert( stream && stream->cursor );
+
+ result = 0;
+ p = stream->cursor;
+ if ( p + 1 < stream->limit )
+ result = NEXT_ShortLE( p );
+ stream->cursor = p;
+
+ return result;
+ }
+
+
+ BASE_FUNC( FT_Long ) FT_Get_Offset( FT_Stream stream )
+ {
+ FT_Byte* p;
+ FT_Long result;
+
+
+ FT_Assert( stream && stream->cursor );
+
+ result = 0;
+ p = stream->cursor;
+ if ( p + 2 < stream->limit )
+ result = NEXT_Offset( p );
+ stream->cursor = p;
+ return result;
+ }
+
+
+ BASE_FUNC( FT_Long ) FT_Get_Long( FT_Stream stream )
+ {
+ FT_Byte* p;
+ FT_Long result;
+
+
+ FT_Assert( stream && stream->cursor );
+
+ result = 0;
+ p = stream->cursor;
+ if ( p + 3 < stream->limit )
+ result = NEXT_Long( p );
+ stream->cursor = p;
+ return result;
+ }
+
+
+ BASE_FUNC( FT_Long ) FT_Get_LongLE( FT_Stream stream )
+ {
+ FT_Byte* p;
+ FT_Long result;
+
+
+ FT_Assert( stream && stream->cursor );
+
+ result = 0;
+ p = stream->cursor;
+ if ( p + 3 < stream->limit )
+ result = NEXT_LongLE( p );
+ stream->cursor = p;
+ return result;
+ }
+
+
+ BASE_FUNC( FT_Char ) FT_Read_Char( FT_Stream stream,
+ FT_Error* error )
+ {
+ FT_Byte result = 0;
+
+
+ FT_Assert( stream );
+
+ *error = FT_Err_Ok;
+
+ if ( stream->read )
+ {
+ if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
+ goto Fail;
+ }
+ else
+ {
+ if ( stream->pos < stream->size )
+ result = stream->base[stream->pos];
+ else
+ goto Fail;
+ }
+ stream->pos++;
+
+ return result;
+
+ Fail:
+ *error = FT_Err_Invalid_Stream_Operation;
+ FT_ERROR(( "FT_Read_Char:" ));
+ FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ stream->pos, stream->size ));
+
+ return 0;
+ }
+
+
+ BASE_FUNC( FT_Short ) FT_Read_Short( FT_Stream stream,
+ FT_Error* error )
+ {
+ FT_Byte reads[2];
+ FT_Byte* p = 0;
+ FT_Short result = 0;
+
+
+ FT_Assert( stream );
+
+ *error = FT_Err_Ok;
+
+ if ( stream->pos + 1 < stream->size )
+ {
+ if ( stream->read )
+ {
+ if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
+ goto Fail;
+
+ p = reads;
+ }
+ else
+ {
+ p = stream->base + stream->pos;
+ }
+
+ if ( p )
+ result = NEXT_Short( p );
+ }
+ else
+ goto Fail;
+
+ stream->pos += 2;
+
+ return result;
+
+ Fail:
+ *error = FT_Err_Invalid_Stream_Operation;
+ FT_ERROR(( "FT_Read_Short:" ));
+ FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ stream->pos, stream->size ));
+
+ return 0;
+ }
+
+
+ BASE_FUNC( FT_Short ) FT_Read_ShortLE( FT_Stream stream,
+ FT_Error* error )
+ {
+ FT_Byte reads[2];
+ FT_Byte* p = 0;
+ FT_Short result = 0;
+
+
+ FT_Assert( stream );
+
+ *error = FT_Err_Ok;
+
+ if ( stream->pos + 1 < stream->size )
+ {
+ if ( stream->read )
+ {
+ if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
+ goto Fail;
+
+ p = reads;
+ }
+ else
+ {
+ p = stream->base + stream->pos;
+ }
+
+ if ( p )
+ result = NEXT_ShortLE( p );
+ }
+ else
+ goto Fail;
+
+ stream->pos += 2;
+
+ return result;
+
+ Fail:
+ *error = FT_Err_Invalid_Stream_Operation;
+ FT_ERROR(( "FT_Read_Short:" ));
+ FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ stream->pos, stream->size ));
+
+ return 0;
+ }
+
+
+ BASE_FUNC( FT_Long ) FT_Read_Offset( FT_Stream stream,
+ FT_Error* error )
+ {
+ FT_Byte reads[3];
+ FT_Byte* p = 0;
+ FT_Long result = 0;
+
+
+ FT_Assert( stream );
+
+ *error = FT_Err_Ok;
+
+ if ( stream->pos + 2 < stream->size )
+ {
+ if ( stream->read )
+ {
+ if (stream->read( stream, stream->pos, reads, 3L ) != 3L )
+ goto Fail;
+
+ p = reads;
+ }
+ else
+ {
+ p = stream->base + stream->pos;
+ }
+
+ if ( p )
+ result = NEXT_Offset( p );
+ }
+ else
+ goto Fail;
+
+ stream->pos += 3;
+
+ return result;
+
+ Fail:
+ *error = FT_Err_Invalid_Stream_Operation;
+ FT_ERROR(( "FT_Read_Offset:" ));
+ FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ stream->pos, stream->size ));
+
+ return 0;
+ }
+
+
+ BASE_FUNC( FT_Long ) FT_Read_Long( FT_Stream stream,
+ FT_Error* error )
+ {
+ FT_Byte reads[4];
+ FT_Byte* p = 0;
+ FT_Long result = 0;
+
+
+ FT_Assert( stream );
+
+ *error = FT_Err_Ok;
+
+ if ( stream->pos + 3 < stream->size )
+ {
+ if ( stream->read )
+ {
+ if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
+ goto Fail;
+
+ p = reads;
+ }
+ else
+ {
+ p = stream->base + stream->pos;
+ }
+
+ if ( p )
+ result = NEXT_Long( p );
+ }
+ else
+ goto Fail;
+
+ stream->pos += 4;
+
+ return result;
+
+ Fail:
+ FT_ERROR(( "FT_Read_Long:" ));
+ FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ stream->pos, stream->size ));
+ *error = FT_Err_Invalid_Stream_Operation;
+
+ return 0;
+ }
+
+
+ BASE_FUNC( FT_Long ) FT_Read_LongLE( FT_Stream stream,
+ FT_Error* error )
+ {
+ FT_Byte reads[4];
+ FT_Byte* p = 0;
+ FT_Long result = 0;
+
+
+ FT_Assert( stream );
+
+ *error = FT_Err_Ok;
+
+ if ( stream->pos + 3 < stream->size )
+ {
+ if ( stream->read )
+ {
+ if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
+ goto Fail;
+
+ p = reads;
+ }
+ else
+ {
+ p = stream->base + stream->pos;
+ }
+
+ if ( p )
+ result = NEXT_LongLE( p );
+ }
+ else
+ goto Fail;
+
+ stream->pos += 4;
+
+ return result;
+
+ Fail:
+ FT_ERROR(( "FT_Read_Long:" ));
+ FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ stream->pos, stream->size ));
+ *error = FT_Err_Invalid_Stream_Operation;
+
+ return 0;
+ }
+
+
+ BASE_FUNC( FT_Error ) FT_Read_Fields( FT_Stream stream,
+ const FT_Frame_Field* fields,
+ void* structure )
+ {
+ FT_Error error;
+ FT_Bool frame_accessed = 0;
+
+
+ if ( !fields || !stream )
+ return FT_Err_Invalid_Argument;
+
+ error = FT_Err_Ok;
+ do
+ {
+ FT_ULong value;
+ FT_Int sign_shift;
+ FT_Byte* p;
+
+
+ switch ( fields->value )
+ {
+ case ft_frame_start: /* access a new frame */
+ error = FT_Access_Frame( stream, fields->offset );
+ if ( error )
+ goto Exit;
+
+ frame_accessed = 1;
+ fields++;
+ continue; /* loop! */
+
+ case ft_frame_bytes: /* read a byte sequence */
+ case ft_frame_skip: /* skip some bytes */
+ {
+ FT_Int len = fields->size;
+
+
+ if ( stream->cursor + len > stream->limit )
+ {
+ error = FT_Err_Invalid_Stream_Operation;
+ goto Exit;
+ }
+
+ if ( fields->value == ft_frame_bytes )
+ {
+ p = (FT_Byte*)structure + fields->offset;
+ MEM_Copy( p, stream->cursor, len );
+ }
+ stream->cursor += len;
+ fields++;
+ continue;
+ }
+
+ case ft_frame_byte:
+ case ft_frame_schar: /* read a single byte */
+ value = GET_Byte();
+ sign_shift = 24;
+ break;
+
+ case ft_frame_short_be:
+ case ft_frame_ushort_be: /* read a 2-byte big-endian short */
+ value = GET_UShort();
+ sign_shift = 16;
+ break;
+
+ case ft_frame_short_le:
+ case ft_frame_ushort_le: /* read a 2-byte little-endian short */
+ {
+ FT_Byte* p;
+
+
+ value = 0;
+ p = stream->cursor;
+
+ if ( p + 1 < stream->limit )
+ {
+ value = ( FT_UShort)p[0] | ((FT_UShort)p[1] << 8 );
+ stream->cursor += 2;
+ }
+ sign_shift = 16;
+ break;
+ }
+
+ case ft_frame_long_be:
+ case ft_frame_ulong_be: /* read a 4-byte big-endian long */
+ value = GET_ULong();
+ sign_shift = 0;
+ break;
+
+ case ft_frame_long_le:
+ case ft_frame_ulong_le: /* read a 4-byte little-endian long */
+ {
+ FT_Byte* p;
+
+
+ value = 0;
+ p = stream->cursor;
+
+ if ( p + 3 < stream->limit )
+ {
+ value = (FT_ULong)p[0] |
+ ( (FT_ULong)p[1] << 8 ) |
+ ( (FT_ULong)p[2] << 16 ) |
+ ( (FT_ULong)p[3] << 24 );
+ stream->cursor += 4;
+ }
+ sign_shift = 0;
+ break;
+ }
+
+ case ft_frame_off3_be:
+ case ft_frame_uoff3_be: /* read a 3-byte big-endian long */
+ value = GET_UOffset();
+ sign_shift = 8;
+ break;
+
+ case ft_frame_off3_le:
+ case ft_frame_uoff3_le: /* read a 3-byte little-endian long */
+ {
+ FT_Byte* p;
+
+
+ value = 0;
+ p = stream->cursor;
+
+ if ( p + 2 < stream->limit )
+ {
+ value = (FT_ULong)p[0] |
+ ( (FT_ULong)p[1] << 8 ) |
+ ( (FT_ULong)p[2] << 16 );
+ stream->cursor += 3;
+ }
+ sign_shift = 8;
+ break;
+ }
+
+ default:
+ /* otherwise, exit the loop */
+ goto Exit;
+ }
+
+ /* now, compute the signed value is necessary */
+ if ( fields->value & FT_FRAME_OP_SIGNED )
+ value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
+
+ /* finally, store the value in the object */
+
+ p = (FT_Byte*)structure + fields->offset;
+ switch ( fields->size )
+ {
+ case 1:
+ *(FT_Byte*)p = (FT_Byte)value;
+ break;
+
+ case 2:
+ *(FT_UShort*)p = (FT_UShort)value;
+ break;
+
+ case 4:
+ *(FT_UInt32*)p = (FT_UInt32)value;
+ break;
+
+ default: /* for 64-bit systems */
+ *(FT_ULong*)p = (FT_ULong)value;
+ }
+
+ /* go to next field */
+ fields++;
+ }
+ while ( 1 );
+
+ Exit:
+ /* close the frame if it was opened by this read */
+ if ( frame_accessed )
+ FT_Forget_Frame( stream );
+
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftsystem.c */
+/* */
+/* ANSI-specific FreeType low-level system interface (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* This file contains the default interface used by FreeType to access */
+ /* low-level, i.e. memory management, i/o access as well as thread */
+ /* synchronisation. It can be replaced by user-specific routines if */
+ /* necessary. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/ftsystem.h>
+#include <freetype/fterrors.h>
+#include <freetype/fttypes.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* MEMORY MANAGEMENT INTERFACE */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* It is not necessary to do any error checking for the */
+ /* allocation-related functions. This will be done by the higher level */
+ /* routines like FT_Alloc() or FT_Realloc(). */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_alloc */
+ /* */
+ /* <Description> */
+ /* The memory allocation function. */
+ /* */
+ /* <Input> */
+ /* memory :: A pointer to the memory object. */
+ /* */
+ /* size :: The requested size in bytes. */
+ /* */
+ /* <Return> */
+ /* block :: The address of newly allocated block. */
+ /* */
+ static
+ void* ft_alloc( FT_Memory memory,
+ long size )
+ {
+ FT_UNUSED( memory );
+
+ return malloc( size );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_realloc */
+ /* */
+ /* <Description> */
+ /* The memory reallocation function. */
+ /* */
+ /* <Input> */
+ /* memory :: A pointer to the memory object. */
+ /* */
+ /* cur_size :: The current size of the allocated memory block. */
+ /* */
+ /* new_size :: The newly requested size in bytes. */
+ /* */
+ /* block :: The current address of the block in memory. */
+ /* */
+ /* <Return> */
+ /* The address of the reallocated memory block. */
+ /* */
+ static
+ void* ft_realloc( FT_Memory memory,
+ long cur_size,
+ long new_size,
+ void* block )
+ {
+ FT_UNUSED( memory );
+ FT_UNUSED( cur_size );
+
+ return realloc( block, new_size );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_free */
+ /* */
+ /* <Description> */
+ /* The memory release function. */
+ /* */
+ /* <Input> */
+ /* memory :: A pointer to the memory object. */
+ /* */
+ /* block :: The address of block in memory to be freed. */
+ /* */
+ static
+ void ft_free( FT_Memory memory,
+ void* block )
+ {
+ FT_UNUSED( memory );
+
+ free( block );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RESOURCE MANAGEMENT INTERFACE */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_io
+
+ /* We use the macro STREAM_FILE for convenience to extract the */
+ /* system-specific stream handle from a given FreeType stream object */
+#define STREAM_FILE( stream ) ( (FILE*)stream->descriptor.pointer )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_close_stream */
+ /* */
+ /* <Description> */
+ /* The function to close a stream. */
+ /* */
+ /* <Input> */
+ /* stream :: A pointer to the stream object. */
+ /* */
+ static
+ void ft_close_stream( FT_Stream stream )
+ {
+ fclose( STREAM_FILE( stream ) );
+
+ stream->descriptor.pointer = NULL;
+ stream->size = 0;
+ stream->base = 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_io_stream */
+ /* */
+ /* <Description> */
+ /* The function to open a stream. */
+ /* */
+ /* <Input> */
+ /* stream :: A pointer to the stream object. */
+ /* */
+ /* offset :: The position in the data stream to start reading. */
+ /* */
+ /* buffer :: The address of buffer to store the read data. */
+ /* */
+ /* count :: The number of bytes to read from the stream. */
+ /* */
+ /* <Return> */
+ /* The number of bytes actually read. */
+ /* */
+ static
+ unsigned long ft_io_stream( FT_Stream stream,
+ unsigned long offset,
+ unsigned char* buffer,
+ unsigned long count )
+ {
+ FILE* file;
+
+
+ file = STREAM_FILE( stream );
+
+ fseek( file, offset, SEEK_SET );
+
+ return (unsigned long)fread( buffer, 1, count, file );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Stream */
+ /* */
+ /* <Description> */
+ /* Creates a new stream object. */
+ /* */
+ /* <Input> */
+ /* filepathname :: The name of the stream (usually a file) to be */
+ /* opened. */
+ /* */
+ /* stream :: A pointer to the stream object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_New_Stream( const char* filepathname,
+ FT_Stream stream )
+ {
+ FILE* file;
+
+
+ if ( !stream )
+ return FT_Err_Invalid_Stream_Handle;
+
+ file = fopen( filepathname, "rb" );
+ if ( !file )
+ {
+ FT_ERROR(( "FT_New_Stream:" ));
+ FT_ERROR(( " could not open `%s'\n", filepathname ));
+
+ return FT_Err_Cannot_Open_Resource;
+ }
+
+ fseek( file, 0, SEEK_END );
+ stream->size = ftell( file );
+ fseek( file, 0, SEEK_SET );
+
+ stream->descriptor.pointer = file;
+ stream->pathname.pointer = (char*)filepathname;
+ stream->pos = 0;
+
+ stream->read = ft_io_stream;
+ stream->close = ft_close_stream;
+
+ FT_TRACE1(( "FT_New_Stream:" ));
+ FT_TRACE1(( " opened `%s' (%d bytes) successfully\n",
+ filepathname, stream->size ));
+
+ return FT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Memory */
+ /* */
+ /* <Description> */
+ /* Creates a new memory object. */
+ /* */
+ /* <Return> */
+ /* A pointer to the new memory object. 0 in case of error. */
+ /* */
+ FT_EXPORT_FUNC( FT_Memory ) FT_New_Memory( void )
+ {
+ FT_Memory memory;
+
+
+ memory = (FT_Memory)malloc( sizeof ( *memory ) );
+ if ( memory )
+ {
+ memory->user = 0;
+ memory->alloc = ft_alloc;
+ memory->realloc = ft_realloc;
+ memory->free = ft_free;
+ }
+
+ return memory;
+ }
+
+
+/* END */
--- /dev/null
+#
+# FreeType 2 base layer configuration rules
+#
+
+
+# Copyright 1996-2000 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# It sets the following variables which are used by the master Makefile
+# after the call:
+#
+# BASE_OBJ_S: The single-object base layer.
+# BASE_OBJ_M: A list of all objects for a multiple-objects build.
+# BASE_EXT_OBJ: A list of base layer extensions, i.e., components found
+# in `freetype/src/base' which are not compiled within the
+# base layer proper.
+#
+# BASE_H is defined in freetype.mk to simplify the dependency rules.
+
+
+BASE_COMPILE := $(FT_COMPILE) $I$(SRC_)base
+
+
+# Base layer sources
+#
+# ftsystem, ftinit, and ftdebug are handled by freetype.mk
+#
+BASE_SRC := $(BASE_)ftcalc.c \
+ $(BASE_)ftextend.c \
+ $(BASE_)ftlist.c \
+ $(BASE_)ftobjs.c \
+ $(BASE_)ftstream.c \
+ $(BASE_)ftoutln.c
+
+# Base layer `extensions' sources
+#
+# An extension is added to the library file (.a or .lib) as a separate
+# object. It will then be linked to the final executable only if one of its
+# symbols is used by the application.
+#
+BASE_EXT_SRC := $(BASE_)ftglyph.c \
+ $(BASE_)ftmm.c
+
+# Default extensions objects
+#
+BASE_EXT_OBJ := $(BASE_EXT_SRC:$(BASE_)%.c=$(OBJ_)%.$O)
+
+
+# Base layer object(s)
+#
+# BASE_OBJ_M is used during `multi' builds (each base source file compiles
+# to a single object file).
+#
+# BASE_OBJ_S is used during `single' builds (the whole base layer is
+# compiled as a single object file using ftbase.c).
+#
+BASE_OBJ_M := $(BASE_SRC:$(BASE_)%.c=$(OBJ_)%.$O)
+BASE_OBJ_S := $(OBJ_)ftbase.$O
+
+# Base layer root source file for single build
+#
+BASE_SRC_S := $(BASE_)ftbase.c
+
+
+# Base layer - single object build
+#
+$(BASE_OBJ_S): $(BASE_SRC_S) $(BASE_SRC) $(FREETYPE_H)
+ $(BASE_COMPILE) $T$@ $(BASE_SRC_S)
+
+
+# Multiple objects build + extensions
+#
+$(OBJ_)%.$O: $(BASE_)%.c $(FREETYPE_H)
+ $(BASE_COMPILE) $T$@ $<
+
+# EOF
--- /dev/null
+/***************************************************************************/
+/* */
+/* cff.c */
+/* */
+/* FreeType OpenType driver component (body only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2driver.c" /* driver interface */
+#include "t2parse.c" /* token parser */
+#include "t2load.c" /* tables loader */
+#include "t2objs.c" /* object management */
+#include "t2gload.c" /* glyph loader */
+
+#else
+
+#include <cff/t2driver.c> /* driver interface */
+#include <cff/t2parse.c> /* token parser */
+#include <cff/t2load.c> /* tables loader */
+#include <cff/t2objs.c> /* object management */
+#include <cff/t2gload.c> /* glyph loader */
+
+#endif
+
+
+/* END */
--- /dev/null
+make_module_list: add_cff_driver
+
+add_cff_driver:
+ $(OPEN_DRIVER)cff_driver_class$(CLOSE_DRIVER)
+ $(ECHO_DRIVER)cff $(ECHO_DRIVER_DESC)OpenType fonts with extension *.otf$(ECHO_DRIVER_DONE)
+
+# EOF
--- /dev/null
+#
+# FreeType 2 OpenType/CFF driver configuration rules
+#
+
+
+# Copyright 1996-2000 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# OpenType driver directory
+#
+T2_DIR := $(SRC_)cff
+T2_DIR_ := $(T2_DIR)$(SEP)
+
+
+T2_COMPILE := $(FT_COMPILE)
+
+
+# T2 driver sources (i.e., C files)
+#
+T2_DRV_SRC := $(T2_DIR_)t2objs.c \
+ $(T2_DIR_)t2load.c \
+ $(T2_DIR_)t2gload.c \
+ $(T2_DIR_)t2parse.c \
+ $(T2_DIR_)t2driver.c
+
+# T2 driver headers
+#
+T2_DRV_H := $(T2_DRV_SRC:%.c=%.h) \
+ $(T2_DIR_)t2tokens.h
+
+
+# T2 driver object(s)
+#
+# T2_DRV_OBJ_M is used during `multi' builds
+# T2_DRV_OBJ_S is used during `single' builds
+#
+T2_DRV_OBJ_M := $(T2_DRV_SRC:$(T2_DIR_)%.c=$(OBJ_)%.$O)
+T2_DRV_OBJ_S := $(OBJ_)cff.$O
+
+# T2 driver source file for single build
+#
+T2_DRV_SRC_S := $(T2_DIR_)cff.c
+
+
+# T2 driver - single object
+#
+$(T2_DRV_OBJ_S): $(T2_DRV_SRC_S) $(T2_DRV_SRC) $(FREETYPE_H) $(T2_DRV_H)
+ $(T2_COMPILE) $T$@ $(T2_DRV_SRC_S)
+
+
+# T2 driver - multiple objects
+#
+$(OBJ_)%.$O: $(T2_DIR_)%.c $(FREETYPE_H) $(T2_DRV_H)
+ $(T2_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(T2_DRV_OBJ_S)
+DRV_OBJS_M += $(T2_DRV_OBJ_M)
+
+# EOF
--- /dev/null
+/***************************************************************************/
+/* */
+/* t2driver.c */
+/* */
+/* OpenType font driver implementation (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/freetype.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/sfnt.h>
+#include <freetype/ttnameid.h>
+
+#include <freetype/internal/t2errors.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2driver.h"
+#include "t2gload.h"
+
+#else
+
+#include <cff/t2driver.h>
+#include <cff/t2gload.h>
+
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t2driver
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** F A C E S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#undef PAIR_TAG
+#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \
+ (FT_ULong)right )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Kerning */
+ /* */
+ /* <Description> */
+ /* A driver method used to return the kerning vector between two */
+ /* glyphs of the same face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* left_glyph :: The index of the left glyph in the kern pair. */
+ /* */
+ /* right_glyph :: The index of the right glyph in the kern pair. */
+ /* */
+ /* <Output> */
+ /* kerning :: The kerning vector. This is in font units for */
+ /* scalable formats, and in pixels for fixed-sizes */
+ /* formats. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only horizontal layouts (left-to-right & right-to-left) are */
+ /* supported by this function. Other layouts, or more sophisticated */
+ /* kernings, are out of scope of this method (the basic driver */
+ /* interface is meant to be simple). */
+ /* */
+ /* They can be implemented by format-specific interfaces. */
+ /* */
+ static
+ FT_Error Get_Kerning( TT_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_Vector* kerning )
+ {
+ TT_Kern_0_Pair* pair;
+
+
+ if ( !face )
+ return T2_Err_Invalid_Face_Handle;
+
+ kerning->x = 0;
+ kerning->y = 0;
+
+ if ( face->kern_pairs )
+ {
+ /* there are some kerning pairs in this font file! */
+ FT_ULong search_tag = PAIR_TAG( left_glyph, right_glyph );
+ FT_Long left, right;
+
+
+ left = 0;
+ right = face->num_kern_pairs - 1;
+
+ while ( left <= right )
+ {
+ FT_Int middle = left + ( ( right - left ) >> 1 );
+ FT_ULong cur_pair;
+
+
+ pair = face->kern_pairs + middle;
+ cur_pair = PAIR_TAG( pair->left, pair->right );
+
+ if ( cur_pair == search_tag )
+ goto Found;
+
+ if ( cur_pair < search_tag )
+ left = middle + 1;
+ else
+ right = middle - 1;
+ }
+ }
+
+ Exit:
+ return T2_Err_Ok;
+
+ Found:
+ kerning->x = pair->value;
+ goto Exit;
+ }
+
+
+#undef PAIR_TAG
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Load_Glyph */
+ /* */
+ /* <Description> */
+ /* A driver method used to load a glyph within a given glyph slot. */
+ /* */
+ /* <Input> */
+ /* slot :: A handle to the target slot object where the glyph */
+ /* will be loaded. */
+ /* */
+ /* size :: A handle to the source face size at which the glyph */
+ /* must be scaled, loaded, etc. */
+ /* */
+ /* glyph_index :: The index of the glyph in the font file. */
+ /* */
+ /* load_flags :: A flag indicating what to load for this glyph. The */
+ /* FTLOAD_??? constants can be used to control the */
+ /* glyph loading process (e.g., whether the outline */
+ /* should be scaled, whether to load bitmaps or not, */
+ /* whether to hint the outline, etc). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Load_Glyph( T2_GlyphSlot slot,
+ T2_Size size,
+ FT_UShort glyph_index,
+ FT_UInt load_flags )
+ {
+ FT_Error error;
+
+
+ if ( !slot )
+ return T2_Err_Invalid_Glyph_Handle;
+
+ /* check whether we want a scaled outline or bitmap */
+ if ( !size )
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+ if ( load_flags & FT_LOAD_NO_SCALE )
+ size = NULL;
+
+ /* reset the size object if necessary */
+ if ( size )
+ {
+ /* these two object must have the same parent */
+ if ( size->face != slot->root.face )
+ return T2_Err_Invalid_Face_Handle;
+ }
+
+ /* now load the glyph outline if necessary */
+ error = T2_Load_Glyph( slot, size, glyph_index, load_flags );
+
+ /* force drop-out mode to 2 - irrelevant now */
+ /* slot->outline.dropout_mode = 2; */
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** C H A R A C T E R M A P P I N G S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Char_Index */
+ /* */
+ /* <Description> */
+ /* Uses a charmap to return a given character code's glyph index. */
+ /* */
+ /* <Input> */
+ /* charmap :: A handle to the source charmap object. */
+ /* charcode :: The character code. */
+ /* */
+ /* <Return> */
+ /* Glyph index. 0 means `undefined character code'. */
+ /* */
+ static
+ FT_UInt t2_get_char_index( TT_CharMap charmap,
+ FT_Long charcode )
+ {
+ FT_Error error;
+ T2_Face face;
+ TT_CMapTable* cmap;
+
+
+ cmap = &charmap->cmap;
+ face = (T2_Face)charmap->root.face;
+
+ /* Load table if needed */
+ if ( !cmap->loaded )
+ {
+ SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt;
+
+
+ error = sfnt->load_charmap( face, cmap, face->root.stream );
+ if ( error )
+ return 0;
+
+ cmap->loaded = TRUE;
+ }
+
+ return ( cmap->get_index ? cmap->get_index( cmap, charcode ) : 0 );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** D R I V E R I N T E R F A C E ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static
+ FT_Module_Interface t2_get_interface( T2_Driver driver,
+ const char* interface )
+ {
+ FT_Module sfnt;
+
+
+ /* we simply pass our request to the `sfnt' module */
+ sfnt = FT_Get_Module( driver->root.root.library, "sfnt" );
+
+ return sfnt ? sfnt->clazz->get_interface( sfnt, interface ) : 0;
+ }
+
+
+ /* The FT_DriverInterface structure is defined in ftdriver.h. */
+
+ const FT_Driver_Class cff_driver_class =
+ {
+ /* begin with the FT_Module_Class fields */
+ {
+ ft_module_font_driver | ft_module_driver_scalable,
+ sizeof( T2_DriverRec ),
+ "cff",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* module-specific interface */
+
+ (FT_Module_Constructor)T2_Init_Driver,
+ (FT_Module_Destructor) T2_Done_Driver,
+ (FT_Module_Requester) t2_get_interface,
+ },
+
+ /* now the specific driver fields */
+ sizeof( TT_FaceRec ),
+ sizeof( FT_SizeRec ),
+ sizeof( T2_GlyphSlotRec ),
+
+ (FTDriver_initFace) T2_Init_Face,
+ (FTDriver_doneFace) T2_Done_Face,
+ (FTDriver_initSize) 0,
+ (FTDriver_doneSize) 0,
+ (FTDriver_initGlyphSlot)0,
+ (FTDriver_doneGlyphSlot)0,
+
+ (FTDriver_setCharSizes) 0,
+ (FTDriver_setPixelSizes)0,
+
+ (FTDriver_loadGlyph) Load_Glyph,
+ (FTDriver_getCharIndex) t2_get_char_index,
+
+ (FTDriver_getKerning) Get_Kerning,
+ (FTDriver_attachFile) 0,
+ (FTDriver_getAdvances) 0
+ };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* getDriverClass */
+ /* */
+ /* <Description> */
+ /* This function is used when compiling the TrueType driver as a */
+ /* shared library (`.DLL' or `.so'). It will be used by the */
+ /* high-level library of FreeType to retrieve the address of the */
+ /* driver's generic interface. */
+ /* */
+ /* It shouldn't be implemented in a static build, as each driver must */
+ /* have the same function as an exported entry point. */
+ /* */
+ /* <Return> */
+ /* The address of the TrueType's driver generic interface. The */
+ /* format-specific interface can then be retrieved through the method */
+ /* interface->get_format_interface. */
+ /* */
+ EXPORT_FUNC( FT_Driver_Class* ) getDriverClass( void )
+ {
+ return &cff_driver_class;
+ }
+
+
+#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t2driver.h */
+/* */
+/* High-level OpenType driver interface (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T2DRIVER_H
+#define T2DRIVER_H
+
+#include <freetype/internal/ftdriver.h>
+
+ FT_EXPORT_VAR( const FT_Driver_Class ) cff_driver_class;
+
+
+#endif /* T2DRIVER_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t2gload.c */
+/* */
+/* OpenType Glyph Loader (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/sfnt.h>
+#include <freetype/ftoutln.h>
+#include <freetype/tttags.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2load.h"
+#include "t2gload.h"
+
+#else
+
+#include <cff/t2load.h>
+#include <cff/t2gload.h>
+
+#endif
+
+
+#include <freetype/internal/t2errors.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t2gload
+
+
+ typedef enum T2_Operator_
+ {
+ t2_op_unknown = 0,
+
+ t2_op_rmoveto,
+ t2_op_hmoveto,
+ t2_op_vmoveto,
+
+ t2_op_rlineto,
+ t2_op_hlineto,
+ t2_op_vlineto,
+
+ t2_op_rrcurveto,
+ t2_op_hhcurveto,
+ t2_op_hvcurveto,
+ t2_op_rcurveline,
+ t2_op_rlinecurve,
+ t2_op_vhcurveto,
+ t2_op_vvcurveto,
+
+ t2_op_flex,
+ t2_op_hflex,
+ t2_op_hflex1,
+ t2_op_flex1,
+
+ t2_op_endchar,
+
+ t2_op_hstem,
+ t2_op_vstem,
+ t2_op_hstemhm,
+ t2_op_vstemhm,
+
+ t2_op_hintmask,
+ t2_op_cntrmask,
+
+ t2_op_abs,
+ t2_op_add,
+ t2_op_sub,
+ t2_op_div,
+ t2_op_neg,
+ t2_op_random,
+ t2_op_mul,
+ t2_op_sqrt,
+
+ t2_op_blend,
+
+ t2_op_drop,
+ t2_op_exch,
+ t2_op_index,
+ t2_op_roll,
+ t2_op_dup,
+
+ t2_op_put,
+ t2_op_get,
+ t2_op_store,
+ t2_op_load,
+
+ t2_op_and,
+ t2_op_or,
+ t2_op_not,
+ t2_op_eq,
+ t2_op_ifelse,
+
+ t2_op_callsubr,
+ t2_op_callgsubr,
+ t2_op_return,
+
+ /* do not remove */
+ t2_op_max
+
+ } T2_Operator;
+
+
+#define T2_COUNT_CHECK_WIDTH 0x80
+#define T2_COUNT_EXACT 0x40
+#define T2_COUNT_CLEAR_STACK 0x20
+
+
+ static const FT_Byte t2_argument_counts[] =
+ {
+ 0, /* unknown */
+
+ 2 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, /* rmoveto */
+ 1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT,
+ 1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT,
+
+ 0 | T2_COUNT_CLEAR_STACK, /* rlineto */
+ 0 | T2_COUNT_CLEAR_STACK,
+ 0 | T2_COUNT_CLEAR_STACK,
+
+ 0 | T2_COUNT_CLEAR_STACK, /* rrcurveto */
+ 0 | T2_COUNT_CLEAR_STACK,
+ 0 | T2_COUNT_CLEAR_STACK,
+ 0 | T2_COUNT_CLEAR_STACK,
+ 0 | T2_COUNT_CLEAR_STACK,
+ 0 | T2_COUNT_CLEAR_STACK,
+ 0 | T2_COUNT_CLEAR_STACK,
+
+ 13, /* flex */
+ 7,
+ 9,
+ 11,
+
+ 0, /* endchar */
+
+ 2 | T2_COUNT_CHECK_WIDTH, /* hstem */
+ 2 | T2_COUNT_CHECK_WIDTH,
+ 2 | T2_COUNT_CHECK_WIDTH,
+ 2 | T2_COUNT_CHECK_WIDTH,
+
+ 0, /* hintmask */
+ 0, /* cntrmask */
+
+ 1, /* abs */
+ 2,
+ 2,
+ 2,
+ 1,
+ 0,
+ 2,
+ 1,
+
+ 1, /* blend */
+
+ 1, /* drop */
+ 2,
+ 1,
+ 2,
+ 1,
+
+ 2, /* put */
+ 1,
+ 4,
+ 3,
+
+ 2, /* and */
+ 2,
+ 1,
+ 2,
+ 4,
+
+ 1, /* callsubr */
+ 1,
+ 0
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** GENERIC CHARSTRING PARSING *********/
+ /********** *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T2_Init_Builder */
+ /* */
+ /* <Description> */
+ /* Initializes a given glyph builder. */
+ /* */
+ /* <InOut> */
+ /* builder :: A pointer to the glyph builder to initialize. */
+ /* */
+ /* <Input> */
+ /* face :: The current face object. */
+ /* */
+ /* size :: The current size object. */
+ /* */
+ /* glyph :: The current glyph object. */
+ /* */
+ static
+ void T2_Init_Builder( T2_Builder* builder,
+ TT_Face face,
+ T2_Size size,
+ T2_GlyphSlot glyph )
+ {
+ builder->path_begun = 0;
+ builder->load_points = 1;
+
+ builder->face = face;
+ builder->glyph = glyph;
+ builder->memory = face->root.memory;
+
+ if ( glyph )
+ {
+ FT_GlyphLoader* loader = glyph->root.loader;
+
+
+ builder->loader = loader;
+ builder->base = &loader->base.outline;
+ builder->current = &loader->current.outline;
+ FT_GlyphLoader_Rewind( loader );
+ }
+
+ if ( size )
+ {
+ builder->scale_x = size->metrics.x_scale;
+ builder->scale_y = size->metrics.y_scale;
+ }
+
+ builder->pos_x = 0;
+ builder->pos_y = 0;
+
+ builder->left_bearing.x = 0;
+ builder->left_bearing.y = 0;
+ builder->advance.x = 0;
+ builder->advance.y = 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T2_Done_Builder */
+ /* */
+ /* <Description> */
+ /* Finalizes a given glyph builder. Its contents can still be used */
+ /* after the call, but the function saves important information */
+ /* within the corresponding glyph slot. */
+ /* */
+ /* <Input> */
+ /* builder :: A pointer to the glyph builder to finalize. */
+ /* */
+ static
+ void T2_Done_Builder( T2_Builder* builder )
+ {
+ T2_GlyphSlot glyph = builder->glyph;
+
+
+ if ( glyph )
+ glyph->root.outline = *builder->base;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t2_compute_bias */
+ /* */
+ /* <Description> */
+ /* Computes the bias value in dependence of the number of glyph */
+ /* subroutines. */
+ /* */
+ /* <Input> */
+ /* num_subrs :: The number of glyph subroutines. */
+ /* */
+ /* <Return> */
+ /* The bias value. */
+ static
+ FT_Int t2_compute_bias( FT_UInt num_subrs )
+ {
+ FT_Int result;
+
+
+ if ( num_subrs < 1240 )
+ result = 107;
+ else if ( num_subrs < 33900 )
+ result = 1131;
+ else
+ result = 32768;
+
+ return result;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T2_Init_Decoder */
+ /* */
+ /* <Description> */
+ /* Initializes a given glyph decoder. */
+ /* */
+ /* <InOut> */
+ /* decoder :: A pointer to the glyph builder to initialize. */
+ /* */
+ /* <Input> */
+ /* face :: The current face object. */
+ /* */
+ /* size :: The current size object. */
+ /* */
+ /* slot :: The current glyph object. */
+ /* */
+ LOCAL_FUNC
+ void T2_Init_Decoder( T2_Decoder* decoder,
+ TT_Face face,
+ T2_Size size,
+ T2_GlyphSlot slot )
+ {
+ CFF_Font* cff = (CFF_Font*)face->extra.data;
+
+
+ /* clear everything */
+ MEM_Set( decoder, 0, sizeof ( *decoder ) );
+
+ /* initialize builder */
+ T2_Init_Builder( &decoder->builder, face, size, slot );
+
+ /* initialize Type2 decoder */
+ decoder->num_globals = cff->num_global_subrs;
+ decoder->globals = cff->global_subrs;
+ decoder->globals_bias = t2_compute_bias( decoder->num_globals );
+ }
+
+
+ /* this function is used to select the locals subrs array */
+ LOCAL_DEF
+ void T2_Prepare_Decoder( T2_Decoder* decoder,
+ FT_UInt glyph_index )
+ {
+ CFF_Font* cff = (CFF_Font*)decoder->builder.face->extra.data;
+ CFF_SubFont* sub = &cff->top_font;
+
+
+ /* manage CID fonts */
+ if ( cff->num_subfonts >= 1 )
+ {
+ FT_Byte fd_index = CFF_Get_FD( &cff->fd_select, glyph_index );
+
+
+ sub = cff->subfonts[fd_index];
+ }
+
+ decoder->num_locals = sub->num_local_subrs;
+ decoder->locals = sub->local_subrs;
+ decoder->locals_bias = t2_compute_bias( decoder->num_locals );
+
+ decoder->glyph_width = sub->private_dict.default_width;
+ decoder->nominal_width = sub->private_dict.nominal_width;
+ }
+
+
+ /* check that there is enough room for `count' more points */
+ static
+ FT_Error check_points( T2_Builder* builder,
+ FT_Int count )
+ {
+ return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
+ }
+
+
+ /* add a new point, do not check space */
+ static
+ void add_point( T2_Builder* builder,
+ FT_Pos x,
+ FT_Pos y,
+ FT_Byte flag )
+ {
+ FT_Outline* outline = builder->current;
+
+
+ if ( builder->load_points )
+ {
+ FT_Vector* point = outline->points + outline->n_points;
+ FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
+
+
+ point->x = x >> 16;
+ point->y = y >> 16;
+ *control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic;
+
+ builder->last = *point;
+ }
+ outline->n_points++;
+ }
+
+
+ /* check space for a new on-curve point, then add it */
+ static
+ FT_Error add_point1( T2_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ FT_Error error;
+
+
+ error = check_points( builder, 1 );
+ if ( !error )
+ add_point( builder, x, y, 1 );
+
+ return error;
+ }
+
+
+ /* check room for a new contour, then add it */
+ static
+ FT_Error add_contour( T2_Builder* builder )
+ {
+ FT_Outline* outline = builder->current;
+ FT_Error error;
+
+
+ if ( !builder->load_points )
+ {
+ outline->n_contours++;
+ return T2_Err_Ok;
+ }
+
+ error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
+ if ( !error )
+ {
+ if ( outline->n_contours > 0 )
+ outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+
+ outline->n_contours++;
+ }
+
+ return error;
+ }
+
+
+ /* if a path was begun, add its first on-curve point */
+ static
+ FT_Error start_point( T2_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ FT_Error error = 0;
+
+
+ /* test whether we are building a new contour */
+ if ( !builder->path_begun )
+ {
+ builder->path_begun = 1;
+ error = add_contour( builder );
+ if ( !error )
+ error = add_point1( builder, x, y );
+ }
+ return error;
+ }
+
+
+ /* close the current contour */
+ static
+ void close_contour( T2_Builder* builder )
+ {
+ FT_Outline* outline = builder->current;
+
+ /* XXXX: We must not include the last point in the path if it */
+ /* is located on the first point. */
+ if ( outline->n_points > 1 )
+ {
+ FT_Int first = 0;
+ FT_Vector* p1 = outline->points + first;
+ FT_Vector* p2 = outline->points + outline->n_points - 1;
+
+ if ( outline->n_contours > 1 )
+ {
+ first = outline->contours[outline->n_contours - 2] + 1;
+ p1 = outline->points + first;
+ }
+
+ if ( p1->x == p2->x && p1->y == p2->y )
+ outline->n_points--;
+ }
+
+ if ( outline->n_contours > 0 )
+ outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+ }
+
+
+#define USE_ARGS( n ) do \
+ { \
+ top -= n; \
+ if ( top < decoder->stack ) \
+ goto Stack_Underflow; \
+ } while ( 0 )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T2_Parse_CharStrings */
+ /* */
+ /* <Description> */
+ /* Parses a given Type 2 charstrings program. */
+ /* */
+ /* <InOut> */
+ /* decoder :: The current Type 1 decoder. */
+ /* */
+ /* <Input> */
+ /* charstring_base :: The base of the charstring stream. */
+ /* */
+ /* charstring_len :: The length in bytes of the charstring stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error T2_Parse_CharStrings( T2_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_Int charstring_len )
+ {
+ FT_Error error;
+ T2_Decoder_Zone* zone;
+ FT_Byte* ip;
+ FT_Byte* limit;
+ T2_Builder* builder = &decoder->builder;
+ FT_Outline* outline;
+ FT_Pos x, y;
+ FT_Fixed seed;
+ FT_Fixed* stack;
+
+
+ /* set default width */
+ decoder->num_hints = 0;
+ decoder->read_width = 1;
+
+ /* compute random seed from stack address of parameter */
+ seed = (FT_Fixed)(char*)&seed ^
+ (FT_Fixed)(char*)&decoder ^
+ (FT_Fixed)(char*)&charstring_base;
+ seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFF;
+ if ( seed == 0 )
+ seed = 0x7384;
+
+ /* initialize the decoder */
+ decoder->top = decoder->stack;
+ decoder->zone = decoder->zones;
+ zone = decoder->zones;
+ stack = decoder->top;
+
+ builder->path_begun = 0;
+
+ zone->base = charstring_base;
+ limit = zone->limit = charstring_base + charstring_len;
+ ip = zone->cursor = zone->base;
+
+ error = T2_Err_Ok;
+ outline = builder->current;
+
+ x = builder->pos_x;
+ y = builder->pos_y;
+
+ /* now, execute loop */
+ while ( ip < limit )
+ {
+ T2_Operator op;
+ FT_Byte v;
+ FT_Byte count;
+
+
+ /********************************************************************/
+ /* */
+ /* Decode operator or operand */
+ /* */
+ v = *ip++;
+ if ( v >= 32 || v == 28 )
+ {
+ FT_Int shift = 16;
+ FT_Int32 val;
+
+
+ /* this is an operand, push it on the stack */
+ if ( v == 28 )
+ {
+ if ( ip + 1 >= limit )
+ goto Syntax_Error;
+ val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
+ ip += 2;
+ }
+ else if ( v < 247 )
+ val = (FT_Long)v - 139;
+ else if ( v < 251 )
+ {
+ if ( ip >= limit )
+ goto Syntax_Error;
+ val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108;
+ }
+ else if ( v < 255 )
+ {
+ if ( ip >= limit )
+ goto Syntax_Error;
+ val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108;
+ }
+ else
+ {
+ if ( ip + 3 >= limit )
+ goto Syntax_Error;
+ val = ( (FT_Int32)ip[0] << 24 ) |
+ ( (FT_Int32)ip[1] << 16 ) |
+ ( (FT_Int32)ip[2] << 8 ) |
+ ip[3];
+ ip += 4;
+ shift = 0;
+ }
+ if ( decoder->top - stack >= T2_MAX_OPERANDS )
+ goto Stack_Overflow;
+
+ val <<= shift;
+ *decoder->top++ = val;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !( val & 0xFFFF ) )
+ FT_TRACE4(( " %d", (FT_Int32)( val >> 16 ) ));
+ else
+ FT_TRACE4(( " %.2f", val/65536.0 ));
+#endif
+
+ }
+ else
+ {
+ FT_Fixed* args = decoder->top;
+ FT_Int num_args = args - decoder->stack;
+ FT_Int req_args;
+
+
+ /* find operator */
+ op = t2_op_unknown;
+
+ switch ( v )
+ {
+ case 1:
+ op = t2_op_hstem;
+ break;
+ case 3:
+ op = t2_op_vstem;
+ break;
+ case 4:
+ op = t2_op_vmoveto;
+ break;
+ case 5:
+ op = t2_op_rlineto;
+ break;
+ case 6:
+ op = t2_op_hlineto;
+ break;
+ case 7:
+ op = t2_op_vlineto;
+ break;
+ case 8:
+ op = t2_op_rrcurveto;
+ break;
+ case 10:
+ op = t2_op_callsubr;
+ break;
+ case 11:
+ op = t2_op_return;
+ break;
+ case 12:
+ {
+ if ( ip >= limit )
+ goto Syntax_Error;
+ v = *ip++;
+
+ switch ( v )
+ {
+ case 3:
+ op = t2_op_and;
+ break;
+ case 4:
+ op = t2_op_or;
+ break;
+ case 5:
+ op = t2_op_not;
+ break;
+ case 8:
+ op = t2_op_store;
+ break;
+ case 9:
+ op = t2_op_abs;
+ break;
+ case 10:
+ op = t2_op_add;
+ break;
+ case 11:
+ op = t2_op_sub;
+ break;
+ case 12:
+ op = t2_op_div;
+ break;
+ case 13:
+ op = t2_op_load;
+ break;
+ case 14:
+ op = t2_op_neg;
+ break;
+ case 15:
+ op = t2_op_eq;
+ break;
+ case 18:
+ op = t2_op_drop;
+ break;
+ case 20:
+ op = t2_op_put;
+ break;
+ case 21:
+ op = t2_op_get;
+ break;
+ case 22:
+ op = t2_op_ifelse;
+ break;
+ case 23:
+ op = t2_op_random;
+ break;
+ case 24:
+ op = t2_op_mul;
+ break;
+ case 26:
+ op = t2_op_sqrt;
+ break;
+ case 27:
+ op = t2_op_dup;
+ break;
+ case 28:
+ op = t2_op_exch;
+ break;
+ case 29:
+ op = t2_op_index;
+ break;
+ case 30:
+ op = t2_op_roll;
+ break;
+ case 34:
+ op = t2_op_hflex;
+ break;
+ case 35:
+ op = t2_op_flex;
+ break;
+ case 36:
+ op = t2_op_hflex1;
+ break;
+ case 37:
+ op = t2_op_flex1;
+ break;
+ default:
+ /* decrement ip for syntax error message */
+ ip--;
+ }
+ }
+ break;
+ case 14:
+ op = t2_op_endchar;
+ break;
+ case 16:
+ op = t2_op_blend;
+ break;
+ case 18:
+ op = t2_op_hstemhm;
+ break;
+ case 19:
+ op = t2_op_hintmask;
+ break;
+ case 20:
+ op = t2_op_cntrmask;
+ break;
+ case 21:
+ op = t2_op_rmoveto;
+ break;
+ case 22:
+ op = t2_op_hmoveto;
+ break;
+ case 23:
+ op = t2_op_vstemhm;
+ break;
+ case 24:
+ op = t2_op_rcurveline;
+ break;
+ case 25:
+ op = t2_op_rlinecurve;
+ break;
+ case 26:
+ op = t2_op_vvcurveto;
+ break;
+ case 27:
+ op = t2_op_hhcurveto;
+ break;
+ case 29:
+ op = t2_op_callgsubr;
+ break;
+ case 30:
+ op = t2_op_vhcurveto;
+ break;
+ case 31:
+ op = t2_op_hvcurveto;
+ break;
+ default:
+ ;
+ }
+ if ( op == t2_op_unknown )
+ goto Syntax_Error;
+
+ /* check arguments */
+ req_args = count = t2_argument_counts[op];
+ if ( req_args & T2_COUNT_CHECK_WIDTH )
+ {
+ args = stack;
+ if ( num_args & 1 && decoder->read_width )
+ {
+ decoder->glyph_width = decoder->nominal_width +
+ ( stack[0] >> 16 );
+ num_args--;
+ args++;
+ }
+ decoder->read_width = 0;
+ req_args = 0;
+ }
+
+ req_args &= 15;
+ if ( num_args < req_args )
+ goto Stack_Underflow;
+ args -= req_args;
+ num_args -= req_args;
+
+ switch ( op )
+ {
+ case t2_op_hstem:
+ case t2_op_vstem:
+ case t2_op_hstemhm:
+ case t2_op_vstemhm:
+ /* if the number of arguments is not even, the first one */
+ /* is simply the glyph width, encoded as the difference */
+ /* to nominalWidthX */
+ FT_TRACE4(( op == t2_op_hstem ? " hstem" :
+ op == t2_op_vstem ? " vstem" :
+ op == t2_op_hstemhm ? " hstemhm" :
+ " vstemhm" ));
+ decoder->num_hints += num_args / 2;
+ args = stack;
+ break;
+
+ case t2_op_hintmask:
+ case t2_op_cntrmask:
+ FT_TRACE4(( op == t2_op_hintmask ? " hintmask"
+ : " cntrmask" ));
+
+ decoder->num_hints += num_args / 2;
+ ip += ( decoder->num_hints + 7 ) >> 3;
+ if ( ip >= limit )
+ goto Syntax_Error;
+ args = stack;
+ break;
+
+ case t2_op_rmoveto:
+ FT_TRACE4(( " rmoveto" ));
+
+ close_contour( builder );
+ builder->path_begun = 0;
+ x += args[0];
+ y += args[1];
+ args = stack;
+ break;
+
+ case t2_op_vmoveto:
+ FT_TRACE4(( " vmoveto" ));
+
+ close_contour( builder );
+ builder->path_begun = 0;
+ y += args[0];
+ args = stack;
+ break;
+
+ case t2_op_hmoveto:
+ FT_TRACE4(( " hmoveto" ));
+
+ close_contour( builder );
+ builder->path_begun = 0;
+ x += args[0];
+ args = stack;
+ break;
+
+ case t2_op_rlineto:
+ FT_TRACE4(( " rlineto" ));
+
+ if ( start_point ( builder, x, y ) ||
+ check_points( builder, num_args / 2 ) )
+ goto Memory_Error;
+
+ if ( num_args < 2 || num_args & 1 )
+ goto Stack_Underflow;
+
+ args = stack;
+ while ( args < decoder->top )
+ {
+ x += args[0];
+ y += args[1];
+ add_point( builder, x, y, 1 );
+ args += 2;
+ }
+ args = stack;
+ break;
+
+ case t2_op_hlineto:
+ case t2_op_vlineto:
+ {
+ FT_Int phase = ( op == t2_op_hlineto );
+
+
+ FT_TRACE4(( op == t2_op_hlineto ? " hlineto"
+ : " vlineto" ));
+
+ if ( start_point ( builder, x, y ) ||
+ check_points( builder, num_args ) )
+ goto Memory_Error;
+
+ args = stack;
+ while (args < decoder->top )
+ {
+ if ( phase )
+ x += args[0];
+ else
+ y += args[0];
+
+ if ( add_point1( builder, x, y ) )
+ goto Memory_Error;
+
+ args++;
+ phase ^= 1;
+ }
+ args = stack;
+ }
+ break;
+
+ case t2_op_rrcurveto:
+ FT_TRACE4(( " rrcurveto" ));
+
+ /* check number of arguments; must be a multiple of 6 */
+ if ( num_args % 6 != 0 )
+ goto Stack_Underflow;
+
+ if ( start_point ( builder, x, y ) ||
+ check_points( builder, num_args / 2 ) )
+ goto Memory_Error;
+
+ args = stack;
+ while ( args < decoder->top )
+ {
+ x += args[0];
+ y += args[1];
+ add_point( builder, x, y, 0 );
+ x += args[2];
+ y += args[3];
+ add_point( builder, x, y, 0 );
+ x += args[4];
+ y += args[5];
+ add_point( builder, x, y, 1 );
+ args += 6;
+ }
+ args = stack;
+ break;
+
+ case t2_op_vvcurveto:
+ FT_TRACE4(( " vvcurveto" ));
+
+ if ( start_point ( builder, x, y ) )
+ goto Memory_Error;
+
+ args = stack;
+ if ( num_args & 1 )
+ {
+ x += args[0];
+ args++;
+ num_args--;
+ }
+
+ if ( num_args % 4 != 0 )
+ goto Stack_Underflow;
+
+ if ( check_points( builder, 3 * ( num_args / 4 ) ) )
+ goto Memory_Error;
+
+ while ( args < decoder->top )
+ {
+ y += args[0];
+ add_point( builder, x, y, 0 );
+ x += args[1];
+ y += args[2];
+ add_point( builder, x, y, 0 );
+ y += args[3];
+ add_point( builder, x, y, 1 );
+ args += 4;
+ }
+ args = stack;
+ break;
+
+ case t2_op_hhcurveto:
+ FT_TRACE4(( " hhcurveto" ));
+
+ if ( start_point ( builder, x, y ) )
+ goto Memory_Error;
+
+ args = stack;
+ if ( num_args & 1 )
+ {
+ y += args[0];
+ args++;
+ num_args--;
+ }
+
+ if ( num_args % 4 != 0 )
+ goto Stack_Underflow;
+
+ if ( check_points( builder, 3 * ( num_args / 4 ) ) )
+ goto Memory_Error;
+
+ while ( args < decoder->top )
+ {
+ x += args[0];
+ add_point( builder, x, y, 0 );
+ x += args[1];
+ y += args[2];
+ add_point( builder, x, y, 0 );
+ x += args[3];
+ add_point( builder, x, y, 1 );
+ args += 4;
+ }
+ args = stack;
+ break;
+
+ case t2_op_vhcurveto:
+ case t2_op_hvcurveto:
+ {
+ FT_Int phase;
+
+
+ FT_TRACE4(( op == t2_op_vhcurveto ? " vhcurveto"
+ : " hvcurveto" ));
+
+ if ( start_point ( builder, x, y ) )
+ goto Memory_Error;
+
+ args = stack;
+ if (num_args < 4 || ( num_args % 4 ) > 1 )
+ goto Stack_Underflow;
+
+ if ( check_points( builder, ( num_args / 4 ) * 3 ) )
+ goto Stack_Underflow;
+
+ phase = ( op == t2_op_hvcurveto );
+
+ while ( num_args >= 4 )
+ {
+ num_args -= 4;
+ if ( phase )
+ {
+ x += args[0];
+ add_point( builder, x, y, 0 );
+ x += args[1];
+ y += args[2];
+ add_point( builder, x, y, 0 );
+ y += args[3];
+ if ( num_args == 1 )
+ x += args[4];
+ add_point( builder, x, y, 1 );
+ }
+ else
+ {
+ y += args[0];
+ add_point( builder, x, y, 0 );
+ x += args[1];
+ y += args[2];
+ add_point( builder, x, y, 0 );
+ x += args[3];
+ if ( num_args == 1 )
+ y += args[4];
+ add_point( builder, x, y, 1 );
+ }
+ args += 4;
+ phase ^= 1;
+ }
+ args = stack;
+ }
+ break;
+
+ case t2_op_rlinecurve:
+ {
+ FT_Int num_lines = ( num_args - 6 ) / 2;
+
+
+ FT_TRACE4(( " rlinecurve" ));
+
+ if ( num_args < 8 || ( num_args - 6 ) & 1 )
+ goto Stack_Underflow;
+
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, num_lines + 3 ) )
+ goto Memory_Error;
+
+ args = stack;
+
+ /* first, add the line segments */
+ while ( num_lines > 0 )
+ {
+ x += args[0];
+ y += args[1];
+ add_point( builder, x, y, 1 );
+ args += 2;
+ num_lines--;
+ }
+
+ /* then the curve */
+ x += args[0];
+ y += args[1];
+ add_point( builder, x, y, 0 );
+ x += args[2];
+ y += args[3];
+ add_point( builder, x, y, 0 );
+ x += args[4];
+ y += args[5];
+ add_point( builder, x, y, 1 );
+ args = stack;
+ }
+ break;
+
+ case t2_op_rcurveline:
+ {
+ FT_Int num_curves = ( num_args - 2 ) / 6;
+
+
+ FT_TRACE4(( " rcurveline" ));
+
+ if ( num_args < 8 || ( num_args - 2 ) % 6 )
+ goto Stack_Underflow;
+
+ if ( start_point ( builder, x, y ) ||
+ check_points( builder, num_curves*3 + 2 ) )
+ goto Memory_Error;
+
+ args = stack;
+
+ /* first, add the curves */
+ while ( num_curves > 0 )
+ {
+ x += args[0];
+ y += args[1];
+ add_point( builder, x, y, 0 );
+ x += args[2];
+ y += args[3];
+ add_point( builder, x, y, 0 );
+ x += args[4];
+ y += args[5];
+ add_point( builder, x, y, 1 );
+ args += 6;
+ num_curves--;
+ }
+
+ /* then the final line */
+ x += args[0];
+ y += args[1];
+ add_point( builder, x, y, 1 );
+ args = stack;
+ }
+ break;
+
+ case t2_op_hflex1:
+ {
+ FT_Pos start_y;
+
+
+ FT_TRACE4(( " hflex1" ));
+
+ args = stack;
+
+ /* adding five more points; 4 control points, 1 on-curve point */
+ /* make sure we have enough space for the start point if it */
+ /* needs to be added.. */
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, 6 ) )
+ goto Memory_Error;
+
+ /* Record the starting point's y postion for later use */
+ start_y = y;
+
+ /* first control point */
+ x += args[0];
+ y += args[1];
+ add_point( builder, x, y, 0 );
+
+ /* second control point */
+ x += args[2];
+ y += args[3];
+ add_point( builder, x, y, 0 );
+
+ /* join point; on curve, with y-value the same as the last */
+ /* control point's y-value */
+ x += args[4];
+ add_point( builder, x, y, 1 );
+
+ /* third control point, with y-value the same as the join */
+ /* point's y-value */
+ x += args[5];
+ add_point( builder, x, y, 0 );
+
+ /* fourth control point */
+ x += args[6];
+ y += args[7];
+ add_point( builder, x, y, 0 );
+
+ /* ending point, with y-value the same as the start */
+ x += args[8];
+ y = start_y;
+ add_point( builder, x, y, 1 );
+
+ args = stack;
+ break;
+ }
+
+ case t2_op_hflex:
+ {
+ FT_Pos start_y;
+
+
+ FT_TRACE4(( " hflex" ));
+
+ args = stack;
+
+ /* adding six more points; 4 control points, 2 on-curve points */
+ if ( start_point( builder, x, y ) ||
+ check_points ( builder, 6 ) )
+ goto Memory_Error;
+
+ /* record the starting point's y-position for later use */
+ start_y = y;
+
+ /* first control point */
+ x += args[0];
+ add_point( builder, x, y, 0 );
+
+ /* second control point */
+ x += args[1];
+ y += args[2];
+ add_point( builder, x, y, 0 );
+
+ /* join point; on curve, with y-value the same as the last */
+ /* control point's y-value */
+ x += args[3];
+ add_point( builder, x, y, 1 );
+
+ /* third control point, with y-value the same as the join */
+ /* point's y-value */
+ x += args[4];
+ add_point( builder, x, y, 0 );
+
+ /* fourth control point */
+ x += args[5];
+ y = start_y;
+ add_point( builder, x, y, 0 );
+
+ /* ending point, with y-value the same as the start point's */
+ /* y-value -- we don't add this point, though */
+ x += args[6];
+ add_point( builder, x, y, 1 );
+
+ args = stack;
+ break;
+ }
+
+ case t2_op_flex1:
+ {
+ FT_Pos start_x, start_y; /* record start x, y values for alter */
+ /* use */
+ FT_Int dx = 0, dy = 0; /* used in horizontal/vertical */
+ /* algorithm below */
+ FT_Int horizontal, count;
+
+
+ FT_TRACE4(( " flex1" ));
+
+ /* adding six more points; 4 control points, 2 on-curve points */
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, 6 ) )
+ goto Memory_Error;
+
+ /* record the starting point's x, y postion for later use */
+ start_x = x;
+ start_y = y;
+
+ /* XXX: figure out whether this is supposed to be a horizontal */
+ /* or vertical flex; the Type 2 specification is vague... */
+
+ args = stack;
+
+ /* grab up to the last argument */
+ for ( count = 5; count > 0; count-- )
+ {
+ dx += args[0];
+ dy += args[1];
+ args += 2;
+ }
+
+ /* rewind */
+ args = stack;
+
+ if ( dx < 0 ) dx = -dx;
+ if ( dy < 0 ) dy = -dy;
+
+ /* strange test, but here it is... */
+ horizontal = ( dx > dy );
+
+ for ( count = 5; count > 0; count-- )
+ {
+ x += args[0];
+ y += args[1];
+ add_point( builder, x, y, (FT_Bool)( count == 3 ) );
+ args += 2;
+ }
+
+ /* is last operand an x- or y-delta? */
+ if ( horizontal )
+ {
+ x += args[0];
+ y = start_y;
+ }
+ else
+ {
+ x = start_x;
+ y += args[0];
+ }
+
+ add_point( builder, x, y, 1 );
+
+ args = stack;
+ break;
+ }
+
+ case t2_op_flex:
+ {
+ FT_UInt count;
+
+
+ FT_TRACE4(( " flex" ));
+
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, 6 ) )
+ goto Memory_Error;
+
+ args = stack;
+ for ( count = 6; count > 0; count-- )
+ {
+ x += args[0];
+ y += args[1];
+ add_point( builder, x, y,
+ (FT_Bool)( count == 3 || count == 0 ) );
+ args += 2;
+ }
+
+ args = stack;
+ }
+ break;
+
+ case t2_op_endchar:
+ FT_TRACE4(( " endchar" ));
+
+ close_contour( builder );
+
+ /* add current outline to the glyph slot */
+ FT_GlyphLoader_Add( builder->loader );
+
+ /* return now! */
+ FT_TRACE4(( "\n\n" ));
+ return T2_Err_Ok;
+
+ case t2_op_abs:
+ FT_TRACE4(( " abs" ));
+
+ if ( args[0] < 0 )
+ args[0] = -args[0];
+ args++;
+ break;
+
+ case t2_op_add:
+ FT_TRACE4(( " add" ));
+
+ args[0] += args[1];
+ args++;
+ break;
+
+ case t2_op_sub:
+ FT_TRACE4(( " sub" ));
+
+ args[0] -= args[1];
+ args++;
+ break;
+
+ case t2_op_div:
+ FT_TRACE4(( " div" ));
+
+ args[0] = FT_DivFix( args[0], args[1] );
+ args++;
+ break;
+
+ case t2_op_neg:
+ FT_TRACE4(( " neg" ));
+
+ args[0] = -args[0];
+ args++;
+ break;
+
+ case t2_op_random:
+ {
+ FT_Fixed rand;
+
+
+ FT_TRACE4(( " rand" ));
+
+ rand = seed;
+ if ( rand >= 0x8000 )
+ rand++;
+
+ args[0] = rand;
+ seed = FT_MulFix( seed, 0x10000L - seed );
+ if ( seed == 0 )
+ seed += 0x2873;
+ args++;
+ }
+ break;
+
+ case t2_op_mul:
+ FT_TRACE4(( " mul" ));
+
+ args[0] = FT_MulFix( args[0], args[1] );
+ args++;
+ break;
+
+ case t2_op_sqrt:
+ FT_TRACE4(( " sqrt" ));
+
+ if ( args[0] > 0 )
+ {
+ FT_Int count = 9;
+ FT_Fixed root = args[0];
+ FT_Fixed new_root;
+
+
+ for (;;)
+ {
+ new_root = ( root + FT_DivFix(args[0],root) + 1 ) >> 1;
+ if ( new_root == root || count <= 0 )
+ break;
+ root = new_root;
+ }
+ args[0] = new_root;
+ }
+ else
+ args[0] = 0;
+ args++;
+ break;
+
+ case t2_op_drop:
+ /* nothing */
+ FT_TRACE4(( " drop" ));
+
+ break;
+
+ case t2_op_exch:
+ {
+ FT_Fixed tmp;
+
+
+ FT_TRACE4(( " exch" ));
+
+ tmp = args[0];
+ args[0] = args[1];
+ args[1] = tmp;
+ args += 2;
+ }
+ break;
+
+ case t2_op_index:
+ {
+ FT_Int index = args[0] >> 16;
+
+
+ FT_TRACE4(( " index" ));
+
+ if ( index < 0 )
+ index = 0;
+ else if ( index > num_args - 2 )
+ index = num_args - 2;
+ args[0] = args[-( index + 1 )];
+ args++;
+ }
+ break;
+
+ case t2_op_roll:
+ {
+ FT_Int count = (FT_Int)( args[0] >> 16 );
+ FT_Int index = (FT_Int)( args[1] >> 16 );
+
+
+ FT_TRACE4(( " roll" ));
+
+ if ( count <= 0 )
+ count = 1;
+
+ args -= count;
+ if ( args < stack )
+ goto Stack_Underflow;
+
+ if ( index >= 0 )
+ {
+ while ( index > 0 )
+ {
+ FT_Fixed tmp = args[count - 1];
+ FT_Int i;
+
+
+ for ( i = count - 2; i >= 0; i-- )
+ args[i + 1] = args[i];
+ args[0] = tmp;
+ index--;
+ }
+ }
+ else
+ {
+ while ( index < 0 )
+ {
+ FT_Fixed tmp = args[0];
+ FT_Int i;
+
+
+ for ( i = 0; i < count - 1; i++ )
+ args[i] = args[i + 1];
+ args[count - 1] = tmp;
+ index++;
+ }
+ }
+ args += count;
+ }
+ break;
+
+ case t2_op_dup:
+ FT_TRACE4(( " dup" ));
+
+ args[1] = args[0];
+ args++;
+ break;
+
+ case t2_op_put:
+ {
+ FT_Fixed val = args[0];
+ FT_Int index = (FT_Int)( args[1] >> 16 );
+
+
+ FT_TRACE4(( " put" ));
+
+ if ( index >= 0 && index < decoder->len_buildchar )
+ decoder->buildchar[index] = val;
+ }
+ break;
+
+ case t2_op_get:
+ {
+ FT_Int index = (FT_Int)( args[0] >> 16 );
+ FT_Fixed val = 0;
+
+
+ FT_TRACE4(( " get" ));
+
+ if ( index >= 0 && index < decoder->len_buildchar )
+ val = decoder->buildchar[index];
+
+ args[0] = val;
+ args++;
+ }
+ break;
+
+ case t2_op_store:
+ FT_TRACE4(( " store "));
+
+ goto Unimplemented;
+
+ case t2_op_load:
+ FT_TRACE4(( " load" ));
+
+ goto Unimplemented;
+
+ case t2_op_and:
+ {
+ FT_Fixed cond = args[0] && args[1];
+
+
+ FT_TRACE4(( " and" ));
+
+ args[0] = cond ? 0x10000L : 0;
+ args++;
+ }
+ break;
+
+ case t2_op_or:
+ {
+ FT_Fixed cond = args[0] || args[1];
+
+
+ FT_TRACE4(( " or" ));
+
+ args[0] = cond ? 0x10000L : 0;
+ args++;
+ }
+ break;
+
+ case t2_op_eq:
+ {
+ FT_Fixed cond = !args[0];
+
+
+ FT_TRACE4(( " eq" ));
+
+ args[0] = cond ? 0x10000L : 0;
+ args++;
+ }
+ break;
+
+ case t2_op_ifelse:
+ {
+ FT_Fixed cond = (args[2] <= args[3]);
+
+
+ FT_TRACE4(( " ifelse" ));
+
+ if ( !cond )
+ args[0] = args[1];
+ args++;
+ }
+ break;
+
+ case t2_op_callsubr:
+ {
+ FT_UInt index = (FT_UInt)( ( args[0] >> 16 ) +
+ decoder->locals_bias );
+
+
+ FT_TRACE4(( " callsubr(%d)", index ));
+
+ if ( index >= decoder->num_locals )
+ {
+ FT_ERROR(( "T2_Parse_CharStrings:" ));
+ FT_ERROR(( " invalid local subr index\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( zone - decoder->zones >= T2_MAX_SUBRS_CALLS )
+ {
+ FT_ERROR(( "T2_Parse_CharStrings: too many nested subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ zone->cursor = ip; /* save current instruction pointer */
+
+ zone++;
+ zone->base = decoder->locals[index];
+ zone->limit = decoder->locals[index+1];
+ zone->cursor = zone->base;
+
+ if ( !zone->base )
+ {
+ FT_ERROR(( "T2_Parse_CharStrings: invoking empty subrs!\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone = zone;
+ ip = zone->base;
+ limit = zone->limit;
+ }
+ break;
+
+ case t2_op_callgsubr:
+ {
+ FT_UInt index = (FT_UInt)( ( args[0] >> 16 ) +
+ decoder->globals_bias );
+
+
+ FT_TRACE4(( " callgsubr(%d)", index ));
+
+ if ( index >= decoder->num_globals )
+ {
+ FT_ERROR(( "T2_Parse_CharStrings:" ));
+ FT_ERROR(( " invalid global subr index\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( zone - decoder->zones >= T2_MAX_SUBRS_CALLS )
+ {
+ FT_ERROR(( "T2_Parse_CharStrings: too many nested subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ zone->cursor = ip; /* save current instruction pointer */
+
+ zone++;
+ zone->base = decoder->globals[index];
+ zone->limit = decoder->globals[index+1];
+ zone->cursor = zone->base;
+
+ if ( !zone->base )
+ {
+ FT_ERROR(( "T2_Parse_CharStrings: invoking empty subrs!\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone = zone;
+ ip = zone->base;
+ limit = zone->limit;
+ }
+ break;
+
+ case t2_op_return:
+ FT_TRACE4(( " return" ));
+
+ if ( decoder->zone <= decoder->zones )
+ {
+ FT_ERROR(( "T2_Parse_CharStrings: unexpected return\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone--;
+ zone = decoder->zone;
+ ip = zone->cursor;
+ limit = zone->limit;
+ break;
+
+ default:
+ Unimplemented:
+ FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
+
+ if ( ip[-1] == 12 )
+ FT_ERROR(( " %d", ip[0] ));
+ FT_ERROR(( "\n" ));
+
+ return T2_Err_Unimplemented_Feature;
+ }
+
+ decoder->top = args;
+
+ } /* general operator processing */
+
+ } /* while ip < limit */
+
+ FT_TRACE4(( "..end..\n\n" ));
+
+ return error;
+
+ Syntax_Error:
+ FT_TRACE4(( "T2_Parse_CharStrings: syntax error!" ));
+ return T2_Err_Invalid_File_Format;
+
+ Stack_Underflow:
+ FT_TRACE4(( "T2_Parse_CharStrings: stack underflow!" ));
+ return T2_Err_Too_Few_Arguments;
+
+ Stack_Overflow:
+ FT_TRACE4(( "T2_Parse_CharStrings: stack overflow!" ));
+ return T2_Err_Stack_Overflow;
+
+ Memory_Error:
+ return builder->error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
+ /********** *********/
+ /********** The following code is in charge of computing *********/
+ /********** the maximum advance width of the font. It *********/
+ /********** quickly processes each glyph charstring to *********/
+ /********** extract the value from either a `sbw' or `seac' *********/
+ /********** operator. *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#if 0 /* unused until we support pure CFF fonts */
+
+
+ LOCAL_FUNC
+ FT_Error T2_Compute_Max_Advance( TT_Face face,
+ FT_Int* max_advance )
+ {
+ FT_Error error = 0;
+ T2_Decoder decoder;
+ FT_Int glyph_index;
+ CFF_Font* cff = (CFF_Font*)face->other;
+
+
+ *max_advance = 0;
+
+ /* Initialize load decoder */
+ T2_Init_Decoder( &decoder, face, 0, 0 );
+
+ decoder.builder.metrics_only = 1;
+ decoder.builder.load_points = 0;
+
+ /* For each glyph, parse the glyph charstring and extract */
+ /* the advance width. */
+ for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
+ glyph_index++ )
+ {
+ FT_Byte* charstring;
+ FT_ULong charstring_len;
+
+
+ /* now get load the unscaled outline */
+ error = T2_Access_Element( &cff->charstrings_index, glyph_index,
+ &charstring, &charstring_len );
+ if ( !error )
+ {
+ T2_Prepare_Decoder( &decoder, glyph_index );
+ error = T2_Parse_CharStrings( &decoder, charstring, charstring_len );
+
+ T2_Forget_Element( &cff->charstrings_index, &charstring );
+ }
+
+ /* ignore the error if one has occurred -- skip to next glyph */
+ error = 0;
+ }
+
+ *max_advance = decoder.builder.advance.x;
+
+ return T2_Err_Ok;
+ }
+
+
+#endif /* 0 */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** UNHINTED GLYPH LOADER *********/
+ /********** *********/
+ /********** The following code is in charge of loading a *********/
+ /********** single outline. It completely ignores hinting *********/
+ /********** and is used when FT_LOAD_NO_HINTING is set. *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ LOCAL_FUNC
+ FT_Error T2_Load_Glyph( T2_GlyphSlot glyph,
+ T2_Size size,
+ FT_Int glyph_index,
+ FT_Int load_flags )
+ {
+ FT_Error error;
+ T2_Decoder decoder;
+ TT_Face face = (TT_Face)glyph->root.face;
+ FT_Bool hinting;
+ CFF_Font* cff = (CFF_Font*)face->extra.data;
+
+
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+ glyph->x_scale = 0x10000L;
+ glyph->y_scale = 0x10000L;
+ if ( size )
+ {
+ glyph->x_scale = size->metrics.x_scale;
+ glyph->y_scale = size->metrics.y_scale;
+ }
+
+ glyph->root.outline.n_points = 0;
+ glyph->root.outline.n_contours = 0;
+
+ hinting = ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
+ ( load_flags & FT_LOAD_NO_HINTING ) == 0;
+
+ glyph->root.format = ft_glyph_format_outline; /* by default */
+
+ {
+ FT_Byte* charstring;
+ FT_ULong charstring_len;
+
+
+ T2_Init_Decoder( &decoder, face, size, glyph );
+
+ decoder.builder.no_recurse =
+ (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
+
+ /* now load the unscaled outline */
+ error = T2_Access_Element( &cff->charstrings_index, glyph_index,
+ &charstring, &charstring_len );
+ if ( !error )
+ {
+ T2_Prepare_Decoder( &decoder, glyph_index );
+ error = T2_Parse_CharStrings( &decoder, charstring, charstring_len );
+
+ T2_Forget_Element( &cff->charstrings_index, &charstring );
+ }
+
+ /* save new glyph tables */
+ T2_Done_Builder( &decoder.builder );
+ }
+
+ /* Now, set the metrics -- this is rather simple, as */
+ /* the left side bearing is the xMin, and the top side */
+ /* bearing the yMax. */
+ if ( !error )
+ {
+ /* for composite glyphs, return only left side bearing and */
+ /* advance width */
+ if ( glyph->root.format == ft_glyph_format_composite )
+ {
+ glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+ glyph->root.metrics.horiAdvance = decoder.glyph_width;
+ }
+ else
+ {
+ FT_BBox cbox;
+ FT_Glyph_Metrics* metrics = &glyph->root.metrics;
+
+
+ /* copy the _unscaled_ advance width */
+ metrics->horiAdvance = decoder.glyph_width;
+
+ /* make up vertical metrics */
+ metrics->vertBearingX = 0;
+ metrics->vertBearingY = 0;
+ metrics->vertAdvance = 0;
+
+ glyph->root.format = ft_glyph_format_outline;
+
+ glyph->root.outline.flags = 0;
+ if ( size && size->metrics.y_ppem < 24 )
+ glyph->root.outline.flags |= ft_outline_high_precision;
+
+ glyph->root.outline.flags |= ft_outline_reverse_fill;
+
+ if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ /* scale the outline and the metrics */
+ FT_Int n;
+ FT_Outline* cur = &glyph->root.outline;
+ FT_Vector* vec = cur->points;
+ FT_Fixed x_scale = glyph->x_scale;
+ FT_Fixed y_scale = glyph->y_scale;
+
+
+ /* First of all, scale the points */
+ for ( n = cur->n_points; n > 0; n--, vec++ )
+ {
+ vec->x = FT_MulFix( vec->x, x_scale );
+ vec->y = FT_MulFix( vec->y, y_scale );
+ }
+
+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+ /* Then scale the metrics */
+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
+
+ metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+ metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+ }
+
+#if 0
+ /* apply the font matrix */
+ FT_Outline_Transform( &glyph->root.outline, cff->font_matrix );
+#endif
+
+ /* compute the other metrics */
+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+ /* grid fit the bounding box if necessary */
+ if ( hinting )
+ {
+ cbox.xMin &= -64;
+ cbox.yMin &= -64;
+ cbox.xMax = ( cbox.xMax + 63 ) & -64;
+ cbox.yMax = ( cbox.yMax + 63 ) & -64;
+ }
+
+ metrics->width = cbox.xMax - cbox.xMin;
+ metrics->height = cbox.yMax - cbox.yMin;
+
+ metrics->horiBearingX = cbox.xMin;
+ metrics->horiBearingY = cbox.yMax;
+ }
+ }
+
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t2gload.h */
+/* */
+/* OpenType Glyph Loader (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T2GLOAD_H
+#define T2GLOAD_H
+
+#include <freetype/freetype.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2objs.h"
+
+#else
+
+#include <cff/t2objs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+#define T2_MAX_OPERANDS 48
+#define T2_MAX_SUBRS_CALLS 32
+
+
+ /*************************************************************************/
+ /* */
+ /* <Structure> */
+ /* T2_Builder */
+ /* */
+ /* <Description> */
+ /* A structure used during glyph loading to store its outline. */
+ /* */
+ /* <Fields> */
+ /* memory :: The current memory object. */
+ /* */
+ /* face :: The current face object. */
+ /* */
+ /* glyph :: The current glyph slot. */
+ /* */
+ /* current :: The current glyph outline. */
+ /* */
+ /* base :: The base glyph outline. */
+ /* */
+ /* max_points :: maximum points in builder outline */
+ /* */
+ /* max_contours :: Maximal number of contours in builder outline. */
+ /* */
+ /* last :: The last point position. */
+ /* */
+ /* scale_x :: The horizontal scale (FUnits to sub-pixels). */
+ /* */
+ /* scale_y :: The vertical scale (FUnits to sub-pixels). */
+ /* */
+ /* pos_x :: The horizontal translation (if composite glyph). */
+ /* */
+ /* pos_y :: The vertical translation (if composite glyph). */
+ /* */
+ /* left_bearing :: The left side bearing point. */
+ /* */
+ /* advance :: The horizontal advance vector. */
+ /* */
+ /* bbox :: Unused. */
+ /* */
+ /* path_begun :: A flag which indicates that a new path has begun. */
+ /* */
+ /* load_points :: If this flag is not set, no points are loaded. */
+ /* */
+ /* no_recurse :: Set but not used. */
+ /* */
+ /* error :: An error code that is only used to report memory */
+ /* allocation problems. */
+ /* */
+ /* metrics_only :: A boolean indicating that we only want to compute */
+ /* the metrics of a given glyph, not load all of its */
+ /* points. */
+ /* */
+ typedef struct T2_Builder_
+ {
+ FT_Memory memory;
+ TT_Face face;
+ T2_GlyphSlot glyph;
+ FT_GlyphLoader* loader;
+ FT_Outline* base;
+ FT_Outline* current;
+
+ FT_Vector last;
+
+ FT_Fixed scale_x;
+ FT_Fixed scale_y;
+
+ FT_Pos pos_x;
+ FT_Pos pos_y;
+
+ FT_Vector left_bearing;
+ FT_Vector advance;
+
+ FT_BBox bbox; /* bounding box */
+ FT_Bool path_begun;
+ FT_Bool load_points;
+ FT_Bool no_recurse;
+
+ FT_Error error; /* only used for memory errors */
+ FT_Bool metrics_only;
+
+ } T2_Builder;
+
+
+ /* execution context charstring zone */
+
+ typedef struct T2_Decoder_Zone_
+ {
+ FT_Byte* base;
+ FT_Byte* limit;
+ FT_Byte* cursor;
+
+ } T2_Decoder_Zone;
+
+
+ typedef struct T2_Decoder_
+ {
+ T2_Builder builder;
+ CFF_Font* cff;
+
+ FT_Fixed stack[T2_MAX_OPERANDS + 1];
+ FT_Fixed* top;
+
+ T2_Decoder_Zone zones[T2_MAX_SUBRS_CALLS + 1];
+ T2_Decoder_Zone* zone;
+
+ FT_Int flex_state;
+ FT_Int num_flex_vectors;
+ FT_Vector flex_vectors[7];
+
+ FT_Pos glyph_width;
+ FT_Pos nominal_width;
+
+ FT_Bool read_width;
+ FT_Int num_hints;
+ FT_Fixed* buildchar;
+ FT_Int len_buildchar;
+
+ FT_UInt num_locals;
+ FT_UInt num_globals;
+
+ FT_Int locals_bias;
+ FT_Int globals_bias;
+
+ FT_Byte** locals;
+ FT_Byte** globals;
+
+ } T2_Decoder;
+
+
+ LOCAL_DEF
+ void T2_Init_Decoder( T2_Decoder* decoder,
+ TT_Face face,
+ T2_Size size,
+ T2_GlyphSlot slot );
+
+ LOCAL_DEF
+ void T2_Prepare_Decoder( T2_Decoder* decoder,
+ FT_UInt glyph_index );
+
+#if 0 /* unused until we support pure CFF fonts */
+
+ /* Compute the maximum advance width of a font through quick parsing */
+ LOCAL_DEF
+ FT_Error T2_Compute_Max_Advance( TT_Face face,
+ FT_Int* max_advance );
+
+#endif /* 0 */
+
+ LOCAL_DEF
+ FT_Error T2_Parse_CharStrings( T2_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_Int charstring_len );
+
+ LOCAL_DEF
+ FT_Error T2_Load_Glyph( T2_GlyphSlot glyph,
+ T2_Size size,
+ FT_Int glyph_index,
+ FT_Int load_flags );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* T2GLOAD_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t2load.c */
+/* */
+/* TrueType glyph data/program tables loader (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/psnames.h>
+
+#include <freetype/internal/t2errors.h>
+#include <freetype/tttags.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2load.h"
+#include "t2parse.h"
+
+#else
+
+#include <cff/t2load.h>
+#include <cff/t2parse.h>
+
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t2load
+
+
+ /* read a CFF offset from memory */
+ static
+ FT_ULong t2_get_offset( FT_Byte* p,
+ FT_Byte off_size )
+ {
+ FT_ULong result;
+
+
+ for ( result = 0; off_size > 0; off_size-- )
+ {
+ result <<= 8;
+ result |= *p++;
+ }
+
+ return result;
+ }
+
+
+ static
+ FT_Error t2_new_cff_index( CFF_Index* index,
+ FT_Stream stream,
+ FT_Bool load )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_UShort count;
+
+
+ MEM_Set( index, 0, sizeof ( *index ) );
+
+ index->stream = stream;
+ if ( !READ_UShort( count ) &&
+ count > 0 )
+ {
+ FT_Byte* p;
+ FT_Byte offsize;
+ FT_ULong data_size;
+ FT_ULong* poff;
+
+
+ /* there is at least one element; read the offset size, */
+ /* then access the offset table to compute the index's total size */
+ if ( READ_Byte( offsize ) )
+ goto Exit;
+
+ index->stream = stream;
+ index->count = count;
+ index->off_size = offsize;
+ data_size = (FT_ULong)( count + 1 ) * offsize;
+
+ if ( ALLOC_ARRAY( index->offsets, count + 1, FT_ULong ) ||
+ ACCESS_Frame( data_size ) )
+ goto Exit;
+
+ poff = index->offsets;
+ p = (FT_Byte*)stream->cursor;
+
+ for ( ; (FT_Short)count >= 0; count-- )
+ {
+ poff[0] = t2_get_offset( p, offsize );
+ poff++;
+ p += offsize;
+ }
+
+ FORGET_Frame();
+
+ index->data_offset = FILE_Pos();
+ data_size = poff[-1] - 1;
+
+ if ( load )
+ {
+ /* load the data */
+ if ( EXTRACT_Frame( data_size, index->bytes ) )
+ goto Exit;
+ }
+ else
+ {
+ /* skip the data */
+ (void)FILE_Skip( data_size );
+ }
+ }
+
+ Exit:
+ if ( error )
+ FREE( index->offsets );
+
+ return error;
+ }
+
+
+ static
+ void t2_done_cff_index( CFF_Index* index )
+ {
+ if ( index->stream )
+ {
+ FT_Stream stream = index->stream;
+ FT_Memory memory = stream->memory;
+
+
+ if ( index->bytes )
+ RELEASE_Frame( index->bytes );
+
+ FREE( index->offsets );
+ MEM_Set( index, 0, sizeof ( *index ) );
+ }
+ }
+
+
+ static
+ FT_Error t2_explicit_cff_index( CFF_Index* index,
+ FT_Byte*** table )
+ {
+ FT_Error error = 0;
+ FT_Memory memory = index->stream->memory;
+ FT_UInt n, offset, old_offset;
+ FT_Byte** t;
+
+
+ *table = 0;
+
+ if ( index->count > 0 && !ALLOC_ARRAY( t, index->count + 1, FT_Byte* ) )
+ {
+ old_offset = 1;
+ for ( n = 0; n <= index->count; n++ )
+ {
+ offset = index->offsets[n];
+ if ( !offset )
+ offset = old_offset;
+
+ t[n] = index->bytes + offset - 1;
+
+ old_offset = offset;
+ }
+ *table = t;
+ }
+
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ FT_Error T2_Access_Element( CFF_Index* index,
+ FT_UInt element,
+ FT_Byte** pbytes,
+ FT_ULong* pbyte_len )
+ {
+ FT_Error error = 0;
+
+
+ if ( index && index->count > element )
+ {
+ /* compute start and end offsets */
+ FT_ULong off1, off2;
+
+
+ off1 = index->offsets[element];
+ if ( off1 )
+ {
+ do
+ {
+ element++;
+ off2 = index->offsets[element];
+
+ } while ( off2 == 0 && element < index->count );
+
+ if ( !off2 )
+ off1 = 0;
+ }
+
+ /* access element */
+ if ( off1 )
+ {
+ *pbyte_len = off2 - off1;
+
+ if ( index->bytes )
+ {
+ /* this index was completely loaded in memory, that's easy */
+ *pbytes = index->bytes + off1 - 1;
+ }
+ else
+ {
+ /* this index is still on disk/file, access it through a frame */
+ FT_Stream stream = index->stream;
+
+
+ if ( FILE_Seek( index->data_offset + off1 - 1 ) ||
+ EXTRACT_Frame( off2 - off1, *pbytes ) )
+ goto Exit;
+ }
+ }
+ else
+ {
+ /* empty index element */
+ *pbytes = 0;
+ *pbyte_len = 0;
+ }
+ }
+ else
+ error = T2_Err_Invalid_Argument;
+
+ Exit:
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ void T2_Forget_Element( CFF_Index* index,
+ FT_Byte** pbytes )
+ {
+ if ( index->bytes == 0 )
+ {
+ FT_Stream stream = index->stream;
+
+
+ RELEASE_Frame( *pbytes );
+ }
+ }
+
+
+ LOCAL_FUNC
+ FT_String* T2_Get_Name( CFF_Index* index,
+ FT_UInt element )
+ {
+ FT_Memory memory = index->stream->memory;
+ FT_Byte* bytes;
+ FT_ULong byte_len;
+ FT_Error error;
+ FT_String* name = 0;
+
+
+ error = T2_Access_Element( index, element, &bytes, &byte_len );
+ if ( error )
+ goto Exit;
+
+ if ( !ALLOC( name, byte_len + 1 ) )
+ {
+ MEM_Copy( name, bytes, byte_len );
+ name[byte_len] = 0;
+ }
+ T2_Forget_Element( index, &bytes );
+
+ Exit:
+ return name;
+ }
+
+
+ LOCAL_FUNC
+ FT_String* T2_Get_String( CFF_Index* index,
+ FT_UInt sid,
+ PSNames_Interface* interface )
+ {
+ /* if it is not a standard string, return it */
+ if ( sid > 390 )
+ return T2_Get_Name( index, sid - 390 );
+
+ /* that's a standard string, fetch a copy from the PSName module */
+ {
+ FT_String* name = 0;
+ const char* adobe_name = interface->adobe_std_strings( sid );
+ FT_UInt len;
+
+
+ if ( adobe_name )
+ {
+ FT_Memory memory = index->stream->memory;
+ FT_Error error;
+
+
+ len = (FT_UInt)strlen( adobe_name );
+ if ( !ALLOC( name, len + 1 ) )
+ {
+ MEM_Copy( name, adobe_name, len );
+ name[len] = 0;
+ }
+ }
+
+ return name;
+ }
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** FD Select table support ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static
+ void CFF_Done_FD_Select( CFF_FD_Select* select,
+ FT_Stream stream )
+ {
+ if ( select->data )
+ RELEASE_Frame( select->data );
+
+ select->data_size = 0;
+ select->format = 0;
+ select->range_count = 0;
+ }
+
+
+ static
+ FT_Error CFF_Load_FD_Select( CFF_FD_Select* select,
+ FT_UInt num_glyphs,
+ FT_Stream stream,
+ FT_ULong offset )
+ {
+ FT_Error error;
+ FT_Byte format;
+ FT_UInt num_ranges;
+
+
+ /* read format */
+ if ( FILE_Seek( offset ) || READ_Byte( format ) )
+ goto Exit;
+
+ select->format = format;
+ select->cache_count = 0; /* clear cache */
+
+ switch ( format )
+ {
+ case 0: /* format 0, that's simple */
+ select->data_size = num_glyphs;
+ goto Load_Data;
+
+ case 3: /* format 3, a tad more complex */
+ if ( READ_UShort( num_ranges ) )
+ goto Exit;
+
+ select->data_size = num_ranges * 3 + 2;
+
+ Load_Data:
+ if ( EXTRACT_Frame( select->data_size, select->data ) )
+ goto Exit;
+ break;
+
+ default: /* hmm... that's wrong */
+ error = T2_Err_Invalid_File_Format;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ FT_Byte CFF_Get_FD( CFF_FD_Select* select,
+ FT_UInt glyph_index )
+ {
+ FT_Byte fd = 0;
+
+
+ switch ( select->format )
+ {
+ case 0:
+ fd = select->data[glyph_index];
+ break;
+
+ case 3:
+ /* first, compare to cache */
+ if ( (FT_UInt)(glyph_index-select->cache_first) < select->cache_count )
+ {
+ fd = select->cache_fd;
+ break;
+ }
+
+ /* then, lookup the ranges array */
+ {
+ FT_Byte* p = select->data;
+ FT_Byte* p_limit = p + select->data_size;
+ FT_Byte fd2;
+ FT_UInt first, limit;
+
+
+ first = NEXT_UShort( p );
+ do
+ {
+ if ( glyph_index < first )
+ break;
+
+ fd2 = *p++;
+ limit = NEXT_UShort( p );
+
+ if ( glyph_index < limit )
+ {
+ fd = fd2;
+
+ /* update cache */
+ select->cache_first = first;
+ select->cache_count = limit-first;
+ select->cache_fd = fd2;
+ break;
+ }
+ first = limit;
+
+ } while ( p < p_limit );
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ return fd;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** CFF font support ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static
+ FT_Error CFF_Load_SubFont( CFF_SubFont* font,
+ CFF_Index* index,
+ FT_UInt font_index,
+ FT_Stream stream,
+ FT_ULong base_offset )
+ {
+ FT_Error error;
+ T2_Parser parser;
+ FT_Byte* dict;
+ FT_ULong dict_len;
+ CFF_Font_Dict* top = &font->font_dict;
+ CFF_Private* priv = &font->private_dict;
+
+
+ T2_Parser_Init( &parser, T2CODE_TOPDICT, &font->font_dict );
+
+ /* set defaults */
+ MEM_Set( top, 0, sizeof ( *top ) );
+
+ top->underline_position = -100;
+ top->underline_thickness = 50;
+ top->charstring_type = 2;
+ top->font_matrix.xx = 0x10000L;
+ top->font_matrix.yy = 0x10000L;
+ top->cid_count = 8720;
+
+ error = T2_Access_Element( index, font_index, &dict, &dict_len ) ||
+ T2_Parser_Run( &parser, dict, dict + dict_len );
+
+ T2_Forget_Element( index, &dict );
+
+ if ( error )
+ goto Exit;
+
+ /* if it is a CID font, we stop there */
+ if ( top->cid_registry )
+ goto Exit;
+
+ /* parse the private dictionary, if any */
+ if ( top->private_offset && top->private_size )
+ {
+ /* set defaults */
+ MEM_Set( priv, 0, sizeof ( *priv ) );
+
+ priv->blue_shift = 7;
+ priv->blue_fuzz = 1;
+ priv->lenIV = -1;
+ priv->expansion_factor = (FT_Fixed)0.06 * 0x10000L;
+ priv->blue_scale = (FT_Fixed)0.039625 * 0x10000L;
+
+ T2_Parser_Init( &parser, T2CODE_PRIVATE, priv );
+
+ if ( FILE_Seek( base_offset + font->font_dict.private_offset ) ||
+ ACCESS_Frame( font->font_dict.private_size ) )
+ goto Exit;
+
+ error = T2_Parser_Run( &parser,
+ (FT_Byte*)stream->cursor,
+ (FT_Byte*)stream->limit );
+ FORGET_Frame();
+ if ( error )
+ goto Exit;
+ }
+
+ /* read the local subrs, if any */
+ if ( priv->local_subrs_offset )
+ {
+ if ( FILE_Seek( base_offset + top->private_offset +
+ priv->local_subrs_offset ) )
+ goto Exit;
+
+ error = t2_new_cff_index( &font->local_subrs_index, stream, 1 );
+ if ( error )
+ goto Exit;
+
+ font->num_local_subrs = font->local_subrs_index.count;
+ error = t2_explicit_cff_index( &font->local_subrs_index,
+ &font->local_subrs );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ void CFF_Done_SubFont( FT_Memory memory,
+ CFF_SubFont* subfont )
+ {
+ if ( subfont )
+ {
+ t2_done_cff_index( &subfont->local_subrs_index );
+ FREE( subfont->local_subrs );
+ }
+ }
+
+
+ LOCAL_FUNC
+ FT_Error T2_Load_CFF_Font( FT_Stream stream,
+ FT_Int face_index,
+ CFF_Font* font )
+ {
+ static const FT_Frame_Field cff_header_fields[] =
+ {
+ FT_FRAME_START( 4 ),
+ FT_FRAME_BYTE( CFF_Font, version_major ),
+ FT_FRAME_BYTE( CFF_Font, version_minor ),
+ FT_FRAME_BYTE( CFF_Font, header_size ),
+ FT_FRAME_BYTE( CFF_Font, absolute_offsize ),
+ FT_FRAME_END
+ };
+
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_ULong base_offset;
+ CFF_Font_Dict* dict;
+
+
+ MEM_Set( font, 0, sizeof ( *font ) );
+ font->stream = stream;
+ font->memory = memory;
+ dict = &font->top_font.font_dict;
+ base_offset = FILE_Pos();
+
+ /* read CFF font header */
+ if ( READ_Fields( cff_header_fields, font ) )
+ goto Exit;
+
+ /* check format */
+ if ( font->version_major != 1 ||
+ font->header_size < 4 ||
+ font->absolute_offsize > 4 )
+ {
+ FT_TRACE2(( "[not a CFF font header!]\n" ));
+ error = FT_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ /* skip the rest of the header */
+ (void)FILE_Skip( font->header_size - 4 );
+
+ /* read the name, top dict, string and global subrs index */
+ error = t2_new_cff_index( &font->name_index, stream, 0 ) ||
+ t2_new_cff_index( &font->font_dict_index, stream, 0 ) ||
+ t2_new_cff_index( &font->string_index, stream, 0 ) ||
+ t2_new_cff_index( &font->global_subrs_index, stream, 1 );
+ if ( error )
+ goto Exit;
+
+ /* well, we don't really forget the `disabled' fonts... */
+ font->num_faces = font->name_index.count;
+ if ( face_index >= (FT_Int)font->num_faces )
+ {
+ FT_ERROR(( "T2_Load_CFF_Font: incorrect face index = %d\n",
+ face_index ));
+ error = T2_Err_Invalid_Argument;
+ }
+
+ /* in case of a font format check, simply exit now */
+ if ( face_index < 0 )
+ goto Exit;
+
+ /* now, parse the top-level font dictionary */
+ error = CFF_Load_SubFont( &font->top_font,
+ &font->font_dict_index,
+ face_index,
+ stream,
+ base_offset );
+ if ( error )
+ goto Exit;
+
+ /* now, check for a CID font */
+ if ( dict->cid_registry )
+ {
+ CFF_Index fd_index;
+ CFF_SubFont* sub;
+ FT_UInt index;
+
+
+ /* this is a CID-keyed font, we must now allocate a table of */
+ /* sub-fonts, then load each of them separately */
+ if ( FILE_Seek( base_offset + dict->cid_fd_array_offset ) )
+ goto Exit;
+
+ error = t2_new_cff_index( &fd_index, stream, 0 );
+ if ( error )
+ goto Exit;
+
+ if ( fd_index.count > CFF_MAX_CID_FONTS )
+ {
+ FT_ERROR(( "T2_Load_CFF_Font: FD array too large in CID font\n" ));
+ goto Fail_CID;
+ }
+
+ /* allocate & read each font dict independently */
+ font->num_subfonts = fd_index.count;
+ if ( ALLOC_ARRAY( sub, fd_index.count, CFF_SubFont ) )
+ goto Fail_CID;
+
+ /* setup pointer table */
+ for ( index = 0; index < fd_index.count; index++ )
+ font->subfonts[index] = sub + index;
+
+ /* now load each sub font independently */
+ for ( index = 0; index < fd_index.count; index++ )
+ {
+ sub = font->subfonts[index];
+ error = CFF_Load_SubFont( sub, &fd_index, index,
+ stream, base_offset );
+ if ( error )
+ goto Fail_CID;
+ }
+
+ /* now load the FD Select array */
+ error = CFF_Load_FD_Select( &font->fd_select,
+ dict->cid_count,
+ stream,
+ base_offset + dict->cid_fd_select_offset );
+
+ Fail_CID:
+ t2_done_cff_index( &fd_index );
+
+ if ( error )
+ goto Exit;
+ }
+ else
+ font->num_subfonts = 0;
+
+ /* read the charstrings index now */
+ if ( dict->charstrings_offset == 0 )
+ {
+ FT_ERROR(( "T2_Load_CFF_Font: no charstrings offset!\n" ));
+ error = FT_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ if ( FILE_Seek( base_offset + dict->charstrings_offset ) )
+ goto Exit;
+
+ error = t2_new_cff_index( &font->charstrings_index, stream, 0 );
+ if ( error )
+ goto Exit;
+
+ /* explicit the global subrs */
+ font->num_global_subrs = font->global_subrs_index.count;
+ font->num_glyphs = font->charstrings_index.count;
+
+ error = t2_explicit_cff_index( &font->global_subrs_index,
+ &font->global_subrs ) ;
+
+ if ( error )
+ goto Exit;
+
+ /* get the font name */
+ font->font_name = T2_Get_Name( &font->name_index, face_index );
+
+ Exit:
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ void T2_Done_CFF_Font( CFF_Font* font )
+ {
+ FT_Memory memory = font->memory;
+ FT_UInt index;
+
+
+ t2_done_cff_index( &font->global_subrs_index );
+ t2_done_cff_index( &font->string_index );
+ t2_done_cff_index( &font->font_dict_index );
+ t2_done_cff_index( &font->name_index );
+ t2_done_cff_index( &font->charstrings_index );
+
+ /* release font dictionaries */
+ for ( index = 0; index < font->num_subfonts; index++ )
+ CFF_Done_SubFont( memory, font->subfonts[index] );
+
+ CFF_Done_SubFont( memory, &font->top_font );
+
+ CFF_Done_FD_Select( &font->fd_select, font->stream );
+
+ FREE( font->global_subrs );
+ FREE( font->font_name );
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t2load.h */
+/* */
+/* OpenType glyph data/program tables loader (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T2LOAD_H
+#define T2LOAD_H
+
+#include <freetype/internal/t2types.h>
+#include <freetype/internal/psnames.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+ LOCAL_DEF
+ FT_String* T2_Get_Name( CFF_Index* index,
+ FT_UInt element );
+
+ LOCAL_DEF
+ FT_String* T2_Get_String( CFF_Index* index,
+ FT_UInt sid,
+ PSNames_Interface* interface );
+
+ LOCAL_DEF
+ FT_Error T2_Access_Element( CFF_Index* index,
+ FT_UInt element,
+ FT_Byte** pbytes,
+ FT_ULong* pbyte_len );
+
+ LOCAL_DEF
+ void T2_Forget_Element( CFF_Index* index,
+ FT_Byte** pbytes );
+
+ LOCAL_DEF
+ FT_Error T2_Load_CFF_Font( FT_Stream stream,
+ FT_Int face_index,
+ CFF_Font* font );
+
+ LOCAL_DEF
+ void T2_Done_CFF_Font( CFF_Font* font );
+
+ LOCAL_DEF
+ FT_Byte CFF_Get_FD( CFF_FD_Select* select,
+ FT_UInt glyph_index );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* T2LOAD_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t2objs.c */
+/* */
+/* OpenType objects manager (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/fterrors.h>
+#include <freetype/ttnameid.h>
+#include <freetype/tttags.h>
+
+#include <freetype/internal/sfnt.h>
+#include <freetype/internal/psnames.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2objs.h"
+#include "t2load.h"
+
+#else
+
+#include <cff/t2objs.h>
+#include <cff/t2load.h>
+
+#endif
+
+
+#include <freetype/internal/t2errors.h>
+
+#include <string.h> /* for strlen() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t2objs
+
+
+ /*************************************************************************/
+ /* */
+ /* FACE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+ static
+ FT_String* T2_StrCopy( FT_Memory memory,
+ const FT_String* source )
+ {
+ FT_Error error;
+ FT_String* result = 0;
+ FT_Int len = (FT_Int)strlen( source );
+
+
+ if ( !ALLOC( result, len + 1 ) )
+ {
+ MEM_Copy( result, source, len );
+ result[len] = 0;
+ }
+ return result;
+ }
+
+
+#if 0
+
+ /* this function is used to build a Unicode charmap from the glyph names */
+ /* in a file */
+ static
+ FT_Error CFF_Build_Unicode_Charmap( T2_Face face,
+ FT_ULong base_offset,
+ PSNames_Interface* psnames )
+ {
+ CFF_Font* font = (CFF_Font*)face->extra.data;
+ FT_Memory memory = FT_FACE_MEMORY(face);
+ FT_UInt n, num_glyphs = face->root.num_glyphs;
+ const char** glyph_names;
+ FT_Error error;
+ CFF_Font_Dict* dict = &font->top_font.font_dict;
+ FT_ULong charset_offset;
+ FT_Byte format;
+ FT_Stream stream = face->root.stream;
+
+
+ charset_offset = dict->charset_offset;
+ if ( !charset_offset )
+ {
+ FT_ERROR(( "CFF.Build_Unicode_Charmap: charset table is missing\n" ));
+ error = T2_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* allocate the charmap */
+ if ( ALLOC( face->charmap, ...
+
+ /* seek to charset table and allocate glyph names table */
+ if ( FILE_Seek( base_offset + charset_offset ) ||
+ ALLOC_ARRAY( glyph_names, num_glyphs, const char* ) )
+ goto Exit;
+
+ /* now, read each glyph name and store it in the glyph name table */
+ if ( READ_Byte( format ) )
+ goto Fail;
+
+ switch ( format )
+ {
+ case 0: /* format 0 - one SID per glyph */
+ {
+ const char** gname = glyph_names;
+ const char** limit = gname + num_glyphs;
+
+ if ( ACCESS_Frame( num_glyphs*2 ) )
+ goto Fail;
+
+ for ( ; gname < limit; gname++ )
+ gname[0] = T2_Get_String( &font->string_index,
+ GET_UShort(),
+ psnames );
+ FORGET_Frame();
+ break;
+ }
+
+ case 1: /* format 1 - sequential ranges */
+ case 2: /* format 2 - sequential ranges with 16-bit counts */
+ {
+ const char** gname = glyph_names;
+ const char** limit = gname + num_glyphs;
+ FT_UInt len = 3;
+
+ if (format == 2)
+ len++;
+
+ while (gname < limit)
+ {
+ FT_UInt first;
+ FT_UInt count;
+
+ if ( ACCESS_Frame( len ) )
+ goto Fail;
+
+ first = GET_UShort();
+ if (format == 3)
+ count = GET_UShort();
+ else
+ count = GET_Byte();
+
+ FORGET_Frame();
+
+ for ( ; count > 0; count-- )
+ {
+ gname[0] = T2_Get_String( &font->string_index,
+ first,
+ psnames );
+ gname++;
+ first++;
+ }
+ }
+ break;
+ }
+
+ default: /* unknown charset format! */
+ FT_ERROR(( "CFF: unknown charset format!\n" ));
+ error = T2_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ /* all right, the glyph names were loaded, we now need to create */
+ /* the corresponding unicode charmap.. */
+
+ Fail:
+ for ( n = 0; n < num_glyphs; n++ )
+ FREE( glyph_names[n] );
+
+ FREE( glyph_names );
+
+ Exit:
+ return error;
+ }
+
+#endif /* 0 */
+
+
+ static
+ FT_Encoding find_encoding( int platform_id,
+ int encoding_id )
+ {
+ typedef struct TEncoding
+ {
+ int platform_id;
+ int encoding_id;
+ FT_Encoding encoding;
+
+ } TEncoding;
+
+ static
+ const TEncoding tt_encodings[] =
+ {
+ { TT_PLATFORM_ISO, -1, ft_encoding_unicode },
+
+ { TT_PLATFORM_APPLE_UNICODE, -1, ft_encoding_unicode },
+
+ { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, ft_encoding_apple_roman },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, ft_encoding_unicode },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, ft_encoding_sjis },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, ft_encoding_gb2312 },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, ft_encoding_big5 },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, ft_encoding_wansung },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, ft_encoding_johab }
+ };
+
+ const TEncoding *cur, *limit;
+
+
+ cur = tt_encodings;
+ limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
+
+ for ( ; cur < limit; cur++ )
+ {
+ if ( cur->platform_id == platform_id )
+ {
+ if ( cur->encoding_id == encoding_id ||
+ cur->encoding_id == -1 )
+ return cur->encoding;
+ }
+ }
+
+ return ft_encoding_none;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T2_Init_Face */
+ /* */
+ /* <Description> */
+ /* Initializes a given OpenType face object. */
+ /* */
+ /* <Input> */
+ /* stream :: The source font stream. */
+ /* */
+ /* face_index :: The index of the font face in the resource. */
+ /* */
+ /* num_params :: Number of additional generic parameters. Ignored. */
+ /* */
+ /* params :: Additional generic parameters. Ignored. */
+ /* */
+ /* <InOut> */
+ /* face :: The newly built face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_DEF
+ FT_Error T2_Init_Face( FT_Stream stream,
+ T2_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error;
+ SFNT_Interface* sfnt;
+ PSNames_Interface* psnames;
+ FT_Bool pure_cff = 1;
+ FT_Bool sfnt_format = 0;
+
+
+ sfnt = (SFNT_Interface*)FT_Get_Module_Interface(
+ face->root.driver->root.library, "sfnt" );
+ if ( !sfnt )
+ goto Bad_Format;
+
+ psnames = (PSNames_Interface*)FT_Get_Module_Interface(
+ face->root.driver->root.library, "psnames" );
+
+ /* create input stream from resource */
+ if ( FILE_Seek( 0 ) )
+ goto Exit;
+
+ /* check that we have a valid OpenType file */
+ error = sfnt->init_face( stream, face, face_index, num_params, params );
+ if ( !error )
+ {
+ if ( face->format_tag != 0x4F54544FL ) /* `OTTO'; OpenType/CFF font */
+ {
+ FT_TRACE2(( "[not a valid OpenType/CFF font]\n" ));
+ goto Bad_Format;
+ }
+
+ /* If we are performing a simple font format check, exit immediately */
+ if ( face_index < 0 )
+ return T2_Err_Ok;
+
+ sfnt_format = 1;
+
+ /* now, the font can be either an OpenType/CFF font, or a SVG CEF */
+ /* font in the later case; it doesn't have a `head' table */
+ error = face->goto_table( face, TTAG_head, stream, 0 );
+ if ( !error )
+ {
+ pure_cff = 0;
+
+ /* Load font directory */
+ error = sfnt->load_face( stream, face,
+ face_index, num_params, params );
+ if ( error )
+ goto Exit;
+ }
+ else
+ {
+ /* load the `cmap' table by hand */
+ error = sfnt->load_charmaps( face, stream );
+ if ( error )
+ goto Exit;
+
+ /* XXX: for now, we don't load the GPOS table, as OpenType Layout */
+ /* support will be added later to FreeType 2 as a separate module */
+ }
+
+ /* now, load the CFF part of the file */
+ error = face->goto_table( face, TTAG_CFF, stream, 0 );
+ if ( error )
+ goto Exit;
+ }
+ else
+ {
+ /* rewind to start of file; we are going to load a pure-CFF font */
+ (void)FILE_Seek( 0 );
+ error = FT_Err_Ok;
+ }
+
+ /* now load and parse the CFF table in the file */
+ {
+ CFF_Font* cff;
+ FT_Memory memory = face->root.memory;
+ FT_Face root;
+ FT_UInt flags;
+ FT_ULong base_offset;
+
+
+ if ( ALLOC( cff, sizeof ( *cff ) ) )
+ goto Exit;
+
+ base_offset = FILE_Pos();
+
+ face->extra.data = cff;
+ error = T2_Load_CFF_Font( stream, face_index, cff );
+ if ( error )
+ goto Exit;
+
+ /* Complement the root flags with some interesting information. */
+ /* Note that this is only necessary for pure CFF and CEF fonts */
+
+ root = &face->root;
+ if ( pure_cff )
+ {
+ CFF_Font_Dict* dict = &cff->top_font.font_dict;
+
+
+ /* we need the `PSNames' module for pure-CFF and CEF formats */
+ if ( !psnames )
+ {
+ FT_ERROR(( "T2_Init_Face:" ));
+ FT_ERROR(( " cannot open CFF & CEF fonts\n" ));
+ FT_ERROR(( " " ));
+ FT_ERROR(( " without the `PSNames' module\n" ));
+ goto Bad_Format;
+ }
+
+ /* compute number of glyphs */
+ if ( dict->cid_registry )
+ root->num_glyphs = dict->cid_count;
+ else
+ root->num_glyphs = cff->charstrings_index.count;
+
+ /* set global bbox, as well as EM size */
+ root->units_per_EM = (FT_UInt)FT_DivFix( 1000L << 16,
+ dict->font_matrix.yy ) >> 16;
+ root->bbox = dict->font_bbox;
+ root->ascender = (FT_Short)root->bbox.yMax;
+ root->descender = (FT_Short)root->bbox.yMin;
+
+ /* retrieve font family & style name */
+ root->family_name = T2_Get_Name( &cff->name_index, face_index );
+ if ( dict->cid_registry )
+ {
+ root->style_name = T2_StrCopy( memory, "Regular" ); /* XXXX */
+ }
+ else
+ {
+ root->style_name = T2_Get_String( &cff->string_index,
+ dict->weight,
+ psnames );
+ }
+
+ /*******************************************************************/
+ /* */
+ /* Compute face flags. */
+ /* */
+ flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */
+ FT_FACE_FLAG_HORIZONTAL; /* horizontal data */
+
+ if ( sfnt_format )
+ flags |= FT_FACE_FLAG_SFNT;
+
+ /* fixed width font? */
+ if ( dict->is_fixed_pitch )
+ flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+/* XXXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */
+#if 0
+ /* kerning available? */
+ if ( face->kern_pairs )
+ flags |= FT_FACE_FLAG_KERNING;
+#endif
+
+ root->face_flags = flags;
+
+ /*******************************************************************/
+ /* */
+ /* Compute style flags. */
+ /* */
+ flags = 0;
+
+ if ( dict->italic_angle )
+ flags |= FT_STYLE_FLAG_ITALIC;
+
+ /* XXX: may not be correct */
+ if ( cff->top_font.private_dict.force_bold )
+ flags |= FT_STYLE_FLAG_BOLD;
+
+ root->style_flags = flags;
+
+ /* set the charmaps if any */
+ if ( sfnt_format )
+ {
+ /*****************************************************************/
+ /* */
+ /* Polish the charmaps. */
+ /* */
+ /* Try to set the charmap encoding according to the platform & */
+ /* encoding ID of each charmap. */
+ /* */
+ TT_CharMap charmap;
+ FT_Int n;
+
+
+ charmap = face->charmaps;
+ root->num_charmaps = face->num_charmaps;
+
+ /* allocate table of pointers */
+ if ( ALLOC_ARRAY( root->charmaps, root->num_charmaps, FT_CharMap ) )
+ goto Exit;
+
+ for ( n = 0; n < root->num_charmaps; n++, charmap++ )
+ {
+ FT_Int platform = charmap->cmap.platformID;
+ FT_Int encoding = charmap->cmap.platformEncodingID;
+
+
+ charmap->root.face = (FT_Face)face;
+ charmap->root.platform_id = platform;
+ charmap->root.encoding_id = encoding;
+ charmap->root.encoding = find_encoding( platform, encoding );
+
+ /* now, set root->charmap with a unicode charmap */
+ /* wherever available */
+ if ( !root->charmap &&
+ charmap->root.encoding == ft_encoding_unicode )
+ root->charmap = (FT_CharMap)charmap;
+
+ root->charmaps[n] = (FT_CharMap)charmap;
+ }
+ }
+ }
+ }
+
+ Exit:
+ return error;
+
+ Bad_Format:
+ error = FT_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T2_Done_Face */
+ /* */
+ /* <Description> */
+ /* Finalizes a given face object. */
+ /* */
+ /* <Input> */
+ /* face :: A pointer to the face object to destroy. */
+ /* */
+ LOCAL_DEF
+ void T2_Done_Face( T2_Face face )
+ {
+ FT_Memory memory = face->root.memory;
+ SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt;
+
+
+ if ( sfnt )
+ sfnt->done_face( face );
+
+ {
+ CFF_Font* cff = (CFF_Font*)face->extra.data;
+
+
+ if ( cff )
+ {
+ T2_Done_CFF_Font( cff );
+ FREE( face->extra.data );
+ }
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T2_Init_Driver */
+ /* */
+ /* <Description> */
+ /* Initializes a given OpenType driver object. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target driver object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error T2_Init_Driver( T2_Driver driver )
+ {
+ /* init extension registry if needed */
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+
+ return TT_Init_Extensions( driver );
+
+#else
+
+ FT_UNUSED( driver );
+
+ return T2_Err_Ok;
+
+#endif
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T2_Done_Driver */
+ /* */
+ /* <Description> */
+ /* Finalizes a given OpenType driver. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target OpenType driver. */
+ /* */
+ LOCAL_FUNC
+ void T2_Done_Driver( T2_Driver driver )
+ {
+ /* destroy extensions registry if needed */
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+
+ TT_Done_Extensions( driver );
+
+#else
+
+ FT_UNUSED( driver );
+
+#endif
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t2objs.h */
+/* */
+/* OpenType objects manager (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T2OBJS_H
+#define T2OBJS_H
+
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/t2types.h>
+#include <freetype/internal/t2errors.h>
+#include <freetype/internal/psnames.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T2_Driver */
+ /* */
+ /* <Description> */
+ /* A handle to an OpenType driver object. */
+ /* */
+ typedef struct T2_DriverRec_* T2_Driver;
+
+ typedef TT_Face T2_Face;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T2_Size */
+ /* */
+ /* <Description> */
+ /* A handle to an OpenType size object. */
+ /* */
+ typedef FT_Size T2_Size;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T2_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* A handle to an OpenType glyph slot object. */
+ /* */
+ typedef struct T2_GlyphSlotRec_
+ {
+ FT_GlyphSlotRec root;
+
+ FT_Bool hint;
+ FT_Bool scaled;
+
+ FT_Fixed x_scale;
+ FT_Fixed y_scale;
+
+ } T2_GlyphSlotRec, *T2_GlyphSlot;
+
+
+
+ /*************************************************************************/
+ /* */
+ /* Subglyph transformation record. */
+ /* */
+ typedef struct T2_Transform_
+ {
+ FT_Fixed xx, xy; /* transformation matrix coefficients */
+ FT_Fixed yx, yy;
+ FT_F26Dot6 ox, oy; /* offsets */
+
+ } T2_Transform;
+
+
+ /* this is only used in the case of a pure CFF font with no charmap */
+ typedef struct T2_CharMapRec_
+ {
+ TT_CharMapRec root;
+ PS_Unicodes unicodes;
+
+ } T2_CharMapRec, *T2_CharMap;
+
+
+ /***********************************************************************/
+ /* */
+ /* TrueType driver class. */
+ /* */
+ typedef struct T2_DriverRec_
+ {
+ FT_DriverRec root;
+
+ void* extension_component;
+
+ } T2_DriverRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* Face functions */
+ /* */
+ LOCAL_DEF
+ FT_Error T2_Init_Face( FT_Stream stream,
+ T2_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+ LOCAL_DEF
+ void T2_Done_Face( T2_Face face );
+
+
+ /*************************************************************************/
+ /* */
+ /* Driver functions */
+ /* */
+ LOCAL_DEF
+ FT_Error T2_Init_Driver( T2_Driver driver );
+
+ LOCAL_DEF
+ void T2_Done_Driver( T2_Driver driver );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* T2OBJS_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t2parse.c */
+/* */
+/* OpenType parser (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2parse.h"
+
+#else
+
+#include <cff/t2parse.h>
+
+#endif
+
+
+#include <freetype/internal/t2errors.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t2parse
+
+
+#define T2_Err_Stack_Underflow FT_Err_Invalid_Argument
+#define T2_Err_Syntax_Error FT_Err_Invalid_Argument
+
+
+ enum
+ {
+ t2_kind_none = 0,
+ t2_kind_num,
+ t2_kind_fixed,
+ t2_kind_string,
+ t2_kind_bool,
+ t2_kind_delta,
+ t2_kind_callback,
+
+ t2_kind_max /* do not remove */
+ };
+
+
+ /* now generate handlers for the most simple fields */
+ typedef FT_Error (*T2_Field_Reader)( T2_Parser* parser );
+
+ typedef struct T2_Field_Handler_
+ {
+ int kind;
+ int code;
+ FT_UInt offset;
+ FT_Byte size;
+ T2_Field_Reader reader;
+ FT_UInt array_max;
+ FT_UInt count_offset;
+
+ } T2_Field_Handler;
+
+
+ LOCAL_FUNC
+ void T2_Parser_Init( T2_Parser* parser,
+ FT_UInt code,
+ void* object )
+ {
+ MEM_Set( parser, 0, sizeof ( *parser ) );
+
+ parser->top = parser->stack;
+ parser->object_code = code;
+ parser->object = object;
+ }
+
+
+ /* reads an integer */
+ static
+ FT_Long parse_t2_integer( FT_Byte* start,
+ FT_Byte* limit )
+ {
+ FT_Byte* p = start;
+ FT_Int v = *p++;
+ FT_Long val = 0;
+
+
+ if ( v == 28 )
+ {
+ if ( p + 2 > limit )
+ goto Bad;
+
+ val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] );
+ p += 2;
+ }
+ else if ( v == 29 )
+ {
+ if ( p + 4 > limit )
+ goto Bad;
+
+ val = ( (FT_Long)p[0] << 24 ) |
+ ( (FT_Long)p[1] << 16 ) |
+ ( (FT_Long)p[2] << 8 ) |
+ p[3];
+ p += 4;
+ }
+ else if ( v < 247 )
+ {
+ val = v - 139;
+ }
+ else if ( v < 251 )
+ {
+ if ( p + 1 > limit )
+ goto Bad;
+
+ val = ( v - 247 ) * 256 + p[0] + 108;
+ p++;
+ }
+ else
+ {
+ if ( p + 1 > limit )
+ goto Bad;
+
+ val = -( v - 251 ) * 256 - p[0] - 108;
+ p++;
+ }
+
+ Exit:
+ return val;
+
+ Bad:
+ val = 0;
+ goto Exit;
+ }
+
+
+ /* read a real */
+ static
+ FT_Fixed parse_t2_real( FT_Byte* start,
+ FT_Byte* limit,
+ FT_Int power_ten )
+ {
+ FT_Byte* p = start;
+ FT_Long num, divider, result, exp;
+ FT_Int sign = 0, exp_sign = 0;
+ FT_Byte nib;
+ FT_Byte phase;
+
+
+ result = 0;
+ num = 0;
+ divider = 1;
+
+ /* first of all, read the integer part */
+ phase = 4;
+ p--;
+
+ for (;;)
+ {
+ /* read one nibble at a time */
+ if ( phase && ++p >= limit )
+ goto Bad;
+
+ nib = ( p[0] >> phase ) & 0xF;
+ phase = 4 - phase;
+
+ if ( nib == 0xE )
+ sign = 1;
+ else if ( nib > 9 )
+ break;
+ else
+ result = result * 10 + nib;
+ }
+
+ /* read decimal part, if any */
+ if ( nib == 0xa )
+ for (;;)
+ {
+ /* read one nibble at a time */
+ if ( !phase && ++p >= limit )
+ goto Bad;
+
+ phase = 4 - phase;
+ nib = ( p[0] >> phase ) & 0xF;
+
+ if ( nib >= 10 )
+ break;
+
+ if (divider < 10000000L)
+ {
+ num = num * 10 + nib;
+ divider *= 10;
+ }
+ }
+
+ /* read exponent, if any */
+ if ( nib == 12 )
+ {
+ exp_sign = 1;
+ nib = 11;
+ }
+
+ if ( nib == 11 )
+ {
+ exp = 0;
+
+ for (;;)
+ {
+ /* read one nibble at a time */
+ if ( !phase && ++p >= limit )
+ goto Bad;
+
+ phase = 4 - phase;
+ nib = ( p[0] >> phase ) & 0xF;
+
+ if ( nib >= 10 )
+ break;
+
+ exp = exp * 10 + nib;
+ }
+
+ if ( exp_sign )
+ exp = -exp;
+
+ power_ten += exp;
+ }
+
+ /* raise to power of ten if needed */
+ while ( power_ten > 0 )
+ {
+ result = result * 10;
+ num = num * 10;
+
+ power_ten--;
+ }
+
+ while ( power_ten < 0 )
+ {
+ result = result / 10;
+ divider = divider * 10;
+
+ power_ten++;
+ }
+
+ if ( num )
+ result += FT_DivFix( num, divider );
+
+ if ( sign )
+ result = -result;
+
+ Exit:
+ return result;
+
+ Bad:
+ result = 0;
+ goto Exit;
+ }
+
+
+ /* read a number, either integer or real */
+ static
+ FT_Long t2_parse_num( FT_Byte** d )
+ {
+ return ( **d == 30 ? ( parse_t2_real( d[0], d[1], 0 ) >> 16 )
+ : parse_t2_integer( d[0], d[1] ) );
+ }
+
+
+ /* reads a floating point number, either integer or real */
+ static
+ FT_Fixed t2_parse_fixed( FT_Byte** d )
+ {
+ return ( **d == 30 ? parse_t2_real( d[0], d[1], 0 )
+ : parse_t2_integer( d[0], d[1] ) << 16 );
+ }
+
+
+ static
+ FT_Error parse_font_matrix( T2_Parser* parser )
+ {
+ CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object;
+ FT_Matrix* matrix = &dict->font_matrix;
+ FT_Byte** data = parser->stack;
+ FT_Error error;
+
+
+ error = T2_Err_Stack_Underflow;
+
+ if ( parser->top >= parser->stack + 4 )
+ {
+ matrix->xx = t2_parse_fixed( data++ );
+ matrix->yx = t2_parse_fixed( data++ );
+ matrix->xy = t2_parse_fixed( data++ );
+ matrix->yy = t2_parse_fixed( data );
+ error = T2_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+ static
+ FT_Error parse_font_bbox( T2_Parser* parser )
+ {
+ CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object;
+ FT_BBox* bbox = &dict->font_bbox;
+ FT_Byte** data = parser->stack;
+ FT_Error error;
+
+
+ error = T2_Err_Stack_Underflow;
+
+ if ( parser->top >= parser->stack + 4 )
+ {
+ bbox->xMin = t2_parse_num( data++ );
+ bbox->yMin = t2_parse_num( data++ );
+ bbox->xMax = t2_parse_num( data++ );
+ bbox->yMax = t2_parse_num( data );
+ error = T2_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+ static
+ FT_Error parse_private_dict( T2_Parser* parser )
+ {
+ CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object;
+ FT_Byte** data = parser->stack;
+ FT_Error error;
+
+
+ error = T2_Err_Stack_Underflow;
+
+ if ( parser->top >= parser->stack + 2 )
+ {
+ dict->private_size = t2_parse_num( data++ );
+ dict->private_offset = t2_parse_num( data );
+ error = T2_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+ static
+ FT_Error parse_cid_ros( T2_Parser* parser )
+ {
+ CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object;
+ FT_Byte** data = parser->stack;
+ FT_Error error;
+
+
+ error = T2_Err_Stack_Underflow;
+
+ if ( parser->top >= parser->stack + 3 )
+ {
+ dict->cid_registry = (FT_UInt)t2_parse_num( data++ );
+ dict->cid_ordering = (FT_UInt)t2_parse_num( data++ );
+ dict->cid_supplement = (FT_ULong)t2_parse_num( data );
+ error = T2_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+#define T2_FIELD_NUM( code, name ) \
+ T2_FIELD( code, name, t2_kind_num )
+#define T2_FIELD_FIXED( code, name ) \
+ T2_FIELD( code, name, t2_kind_fixed )
+#define T2_FIELD_STRING( code, name ) \
+ T2_FIELD( code, name, t2_kind_string )
+#define T2_FIELD_BOOL( code, name ) \
+ T2_FIELD( code, name, t2_kind_bool )
+#define T2_FIELD_DELTA( code, name,max ) \
+ T2_FIELD( code, name, t2_kind_delta )
+
+#define T2_REF( s, f ) ( ((s*)0)->f )
+
+#define T2_FIELD_CALLBACK( code, name ) \
+ { \
+ t2_kind_callback, \
+ code | T2CODE, \
+ 0, 0, \
+ parse_ ## name, \
+ 0, 0 \
+ },
+
+#undef T2_FIELD
+#define T2_FIELD( code, name, kind ) \
+ { \
+ kind, \
+ code | T2CODE, \
+ (FT_UInt)(char*)&T2_REF( T2TYPE, name ), \
+ sizeof( T2_REF( T2TYPE, name ) ), \
+ 0, 0, 0 \
+ },
+
+#undef T2_FIELD_DELTA
+#define T2_FIELD_DELTA( code, name, max ) \
+ { \
+ t2_kind_delta, \
+ code | T2CODE, \
+ (FT_UInt)(char*)&T2_REF( T2TYPE, name ), \
+ sizeof( T2_REF( T2TYPE, name )[0] ), \
+ 0, \
+ max, \
+ (FT_UInt)(char*)&T2_REF( T2TYPE, num_ ## name ) \
+ },
+
+#define T2CODE_TOPDICT 0x1000
+#define T2CODE_PRIVATE 0x2000
+
+ static const T2_Field_Handler t2_field_handlers[] =
+ {
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2tokens.h"
+
+#else
+
+#include <cff/t2tokens.h>
+
+#endif
+
+ { 0, 0, 0, 0, 0, 0, 0 }
+ };
+
+
+ LOCAL_FUNC
+ FT_Error T2_Parser_Run( T2_Parser* parser,
+ FT_Byte* start,
+ FT_Byte* limit )
+ {
+ FT_Byte* p = start;
+ FT_Error error = T2_Err_Ok;
+
+
+ parser->top = parser->stack;
+ parser->start = start;
+ parser->limit = limit;
+ parser->cursor = start;
+
+ while ( p < limit )
+ {
+ FT_Byte v = *p;
+
+
+ if ( v >= 27 && v != 31 )
+ {
+ /* it's a number; we will push its position on the stack */
+ if ( parser->top - parser->stack >= T2_MAX_STACK_DEPTH )
+ goto Stack_Overflow;
+
+ *parser->top ++ = p;
+
+ /* now, skip it */
+ if ( v == 30 )
+ {
+ /* skip real number */
+ for (;;)
+ {
+ if ( p >= limit )
+ goto Syntax_Error;
+ v = p[0] >> 4;
+ if ( v == 15 )
+ break;
+ v = p[0] & 0xF;
+ if ( v == 15 )
+ break;
+ p++;
+ }
+ p++;
+ }
+ else if ( v == 28 )
+ p += 2;
+ else if ( v == 29 )
+ p += 4;
+ else if ( v > 246 )
+ p += 1;
+ }
+ else
+ {
+ /* This is not a number, hence it's an operator. Compute its code */
+ /* and look for it in our current list. */
+
+ FT_UInt code;
+ FT_UInt num_args = (FT_UInt)
+ ( parser->top - parser->stack );
+ const T2_Field_Handler* field;
+
+
+ /* first of all, a trivial check */
+ if ( num_args < 1 )
+ goto Stack_Underflow;
+
+ *parser->top = p;
+ code = v;
+ if ( v == 12 )
+ {
+ /* two byte operator */
+ p++;
+ code = 0x100 | p[0];
+ }
+ code = code | parser->object_code;
+
+ for ( field = t2_field_handlers; field->kind; field++ )
+ {
+ if ( field->code == (FT_Int)code )
+ {
+ /* we found our field's handler; read it */
+ FT_Long val;
+ FT_Byte* q = (FT_Byte*)parser->object + field->offset;
+
+
+ switch ( field->kind )
+ {
+ case t2_kind_bool:
+ case t2_kind_string:
+ case t2_kind_num:
+ val = t2_parse_num( parser->stack );
+ goto Store_Number;
+
+ case t2_kind_fixed:
+ val = t2_parse_fixed( parser->stack );
+
+ Store_Number:
+ switch ( field->size )
+ {
+ case 1:
+ *(FT_Byte*)q = (FT_Byte)val;
+ break;
+
+ case 2:
+ *(FT_Short*)q = (FT_Short)val;
+ break;
+
+ case 4:
+ *(FT_Int32*)q = (FT_Int)val;
+ break;
+
+ default: /* for 64-bit systems where long is 8 bytes */
+ *(FT_Long*)q = val;
+ }
+ break;
+
+ case t2_kind_delta:
+ {
+ FT_Byte* qcount = (FT_Byte*)parser->object +
+ field->count_offset;
+
+ FT_Long val;
+ FT_Byte** data = parser->stack;
+
+
+ if ( num_args > field->array_max )
+ num_args = field->array_max;
+
+ /* store count */
+ *qcount = (FT_Byte)num_args;
+
+ val = 0;
+ while ( num_args > 0 )
+ {
+ val += t2_parse_num( data++ );
+ switch ( field->size )
+ {
+ case 1:
+ *(FT_Byte*)q = (FT_Byte)val;
+ break;
+
+ case 2:
+ *(FT_Short*)q = (FT_Short)val;
+ break;
+
+ case 4:
+ *(FT_Int32*)q = (FT_Int)val;
+ break;
+
+ default: /* for 64-bit systems */
+ *(FT_Long*)q = val;
+ }
+
+ q += field->size;
+ num_args--;
+ }
+ }
+ break;
+
+ default: /* callback */
+ error = field->reader( parser );
+ if ( error )
+ goto Exit;
+ }
+ goto Found;
+ }
+ }
+
+ /* this is an unknown operator, or it is unsupported; */
+ /* we will ignore it for now. */
+
+ Found:
+ /* clear stack */
+ parser->top = parser->stack;
+ }
+ p++;
+ }
+
+ Exit:
+ return error;
+
+ Stack_Overflow:
+ error = T2_Err_Invalid_Argument;
+ goto Exit;
+
+ Stack_Underflow:
+ error = T2_Err_Invalid_Argument;
+ goto Exit;
+
+ Syntax_Error:
+ error = T2_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t2parse.h */
+/* */
+/* OpenType parser (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T2PARSE_H
+#define T2PARSE_H
+
+#include <freetype/internal/t2types.h>
+#include <freetype/internal/ftobjs.h>
+
+#define T2_MAX_STACK_DEPTH 96
+
+#define T2CODE_TOPDICT 0x1000
+#define T2CODE_PRIVATE 0x2000
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ typedef struct T2_Parser_
+ {
+ FT_Byte* start;
+ FT_Byte* limit;
+ FT_Byte* cursor;
+
+ FT_Byte* stack[T2_MAX_STACK_DEPTH + 1];
+ FT_Byte** top;
+
+ FT_UInt object_code;
+ void* object;
+
+ } T2_Parser;
+
+
+ LOCAL_DEF
+ void T2_Parser_Init( T2_Parser* parser,
+ FT_UInt code,
+ void* object );
+
+ LOCAL_DEF
+ FT_Error T2_Parser_Run( T2_Parser* parser,
+ FT_Byte* start,
+ FT_Byte* limit );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* T2PARSE_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t2tokens.h */
+/* */
+/* OpenType token definitions (specification only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#undef T2TYPE
+#undef T2CODE
+#define T2TYPE CFF_Font_Dict
+#define T2CODE T2CODE_TOPDICT
+
+ T2_FIELD_STRING ( 0, version )
+ T2_FIELD_STRING ( 1, notice )
+ T2_FIELD_STRING ( 0x100, copyright )
+ T2_FIELD_STRING ( 2, full_name )
+ T2_FIELD_STRING ( 3, family_name )
+ T2_FIELD_STRING ( 4, weight )
+ T2_FIELD_BOOL ( 0x101, is_fixed_pitch )
+ T2_FIELD_FIXED ( 0x102, italic_angle )
+ T2_FIELD_NUM ( 0x103, underline_position )
+ T2_FIELD_NUM ( 0x104, underline_thickness )
+ T2_FIELD_NUM ( 0x105, paint_type )
+ T2_FIELD_NUM ( 0x106, charstring_type )
+ T2_FIELD_CALLBACK( 0x107, font_matrix )
+ T2_FIELD_NUM ( 13, unique_id )
+ T2_FIELD_CALLBACK( 5, font_bbox )
+ T2_FIELD_NUM ( 0x108, stroke_width )
+ T2_FIELD_NUM ( 15, charset_offset )
+ T2_FIELD_NUM ( 16, encoding_offset )
+ T2_FIELD_NUM ( 17, charstrings_offset )
+ T2_FIELD_CALLBACK( 18, private_dict )
+ T2_FIELD_NUM ( 0x114, synthetic_base )
+ T2_FIELD_STRING ( 0x115, postscript )
+ T2_FIELD_STRING ( 0x116, base_font_name )
+
+#if 0
+ T2_FIELD_DELTA ( 0x117, base_font_blend, 16 )
+ T2_FIELD_CALLBACK( 0x118, multiple_master )
+ T2_FIELD_CALLBACK( 0x119, blend_axit_types )
+#endif
+
+ T2_FIELD_CALLBACK( 0x11E, cid_ros )
+ T2_FIELD_NUM ( 0x11F, cid_font_version )
+ T2_FIELD_NUM ( 0x120, cid_font_revision )
+ T2_FIELD_NUM ( 0x121, cid_font_type )
+ T2_FIELD_NUM ( 0x122, cid_count )
+ T2_FIELD_NUM ( 0x123, cid_uid_base )
+ T2_FIELD_NUM ( 0x124, cid_fd_array_offset )
+ T2_FIELD_NUM ( 0x125, cid_fd_select_offset )
+ T2_FIELD_STRING ( 0x126, cid_font_name )
+
+#if 0
+ T2_FIELD_NUM ( 0x127, chameleon )
+#endif
+
+
+#undef T2TYPE
+#undef T2CODE
+#define T2TYPE CFF_Private
+#define T2CODE T2CODE_PRIVATE
+
+ T2_FIELD_DELTA( 6, blue_values, 14 )
+ T2_FIELD_DELTA( 7, other_blues, 10 )
+ T2_FIELD_DELTA( 8, family_blues, 14 )
+ T2_FIELD_DELTA( 9, family_other_blues, 10 )
+ T2_FIELD_FIXED( 0x109, blue_scale )
+ T2_FIELD_NUM ( 0x10A, blue_shift )
+ T2_FIELD_NUM ( 0x10B, blue_fuzz )
+ T2_FIELD_NUM ( 10, standard_width )
+ T2_FIELD_NUM ( 11, standard_height )
+ T2_FIELD_DELTA( 0x10C, snap_widths, 13 )
+ T2_FIELD_DELTA( 0x10D, snap_heights, 13 )
+ T2_FIELD_BOOL ( 0x10E, force_bold )
+ T2_FIELD_FIXED( 0x10F, force_bold_threshold )
+ T2_FIELD_NUM ( 0x110, lenIV )
+ T2_FIELD_NUM ( 0x111, language_group )
+ T2_FIELD_FIXED( 0x112, expansion_factor )
+ T2_FIELD_NUM ( 0x113, initial_random_seed )
+ T2_FIELD_NUM ( 19, local_subrs_offset )
+ T2_FIELD_NUM ( 20, default_width )
+ T2_FIELD_NUM ( 21, nominal_width )
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* cidafm.c */
+/* */
+/* AFM support for CID-keyed fonts (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidafm.h"
+
+#else
+
+#include <cid/cidafm.h>
+
+#endif
+
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1types.h>
+#include <freetype/internal/t1errors.h>
+
+#include <stdlib.h> /* for qsort() */
+#include <string.h> /* for strcmp() */
+#include <ctype.h> /* for isalnum() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cidafm
+
+
+ LOCAL_FUNC
+ void CID_Done_AFM( FT_Memory memory,
+ CID_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 ) ( isalnum( c ) || \
+ 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 && !isdigit( *p ) )
+ {
+ sign = 1;
+ if ( *p == '-' )
+ sign = -1;
+
+ p++;
+ }
+
+ while ( p < limit && isdigit( *p ) )
+ {
+ 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 )
+ {
+ CID_Kern_Pair* pair1 = (CID_Kern_Pair*)a;
+ CID_Kern_Pair* pair2 = (CID_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 cid_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;
+ CID_Kern_Pair* pair;
+ T1_Font* type1 = &((T1_Face)t1_face)->type1;
+ CID_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 occurrences 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, CID_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 ( CID_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( CID_AFM* afm,
+ FT_UInt glyph1,
+ FT_UInt glyph2,
+ FT_Vector* kerning )
+ {
+ CID_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;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* cidafm.h */
+/* */
+/* AFM support for CID-keyed fonts (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef CIDAFM_H
+#define CIDAFM_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidobjs.h"
+
+#else
+
+#include <cid/cidobjs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ typedef struct CID_Kern_Pair_
+ {
+ FT_UInt glyph1;
+ FT_UInt glyph2;
+ FT_Vector kerning;
+
+ } CID_Kern_Pair;
+
+ typedef struct CID_AFM_
+ {
+ FT_UInt num_pairs;
+ CID_Kern_Pair* kern_pairs;
+
+ } CID_AFM;
+
+
+ LOCAL_DEF
+ FT_Error CID_Read_AFM( FT_Face cid_face,
+ FT_Stream stream );
+
+ LOCAL_DEF
+ void CID_Done_AFM( FT_Memory memory,
+ CID_AFM* afm );
+
+ LOCAL_DEF
+ void CID_Get_Kerning( CID_AFM* afm,
+ FT_UInt glyph1,
+ FT_UInt glyph2,
+ FT_Vector* kerning );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* CIDAFM_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* cidgload.c */
+/* */
+/* CID-keyed Type1 Glyph Loader (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidload.h"
+#include "cidgload.h"
+
+#else
+
+#include <cid/cidload.h>
+#include <cid/cidgload.h>
+
+#endif
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/ftoutln.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cidgload
+
+
+ /* forward */
+ static
+ FT_Error cid_load_glyph( CID_Decoder* decoder,
+ FT_UInt glyph_index );
+
+
+ typedef enum CID_Operator_
+ {
+ op_none = 0,
+
+ op_endchar,
+ op_hsbw,
+ op_seac,
+ op_sbw,
+ op_closepath,
+
+ op_hlineto,
+ op_hmoveto,
+ op_hvcurveto,
+ op_rlineto,
+ op_rmoveto,
+ op_rrcurveto,
+ op_vhcurveto,
+ op_vlineto,
+ op_vmoveto,
+
+ op_dotsection,
+
+ op_hstem,
+ op_hstem3,
+ op_vstem,
+ op_vstem3,
+
+ op_div,
+ op_callothersubr,
+ op_callsubr,
+ op_pop,
+ op_return,
+ op_setcurrentpoint,
+
+ op_max /* never remove this one */
+
+ } CID_Operator;
+
+ static
+ const FT_Int t1_args_count[op_max] =
+ {
+ 0, /* none */
+ 0, /* endchar */
+ 2, /* hsbw */
+ 5, /* seac */
+ 4, /* sbw */
+ 0, /* closepath */
+
+ 1, /* hlineto */
+ 1, /* hmoveto */
+ 4, /* hvcurveto */
+ 2, /* rlineto */
+ 2, /* rmoveto */
+ 6, /* rrcurveto */
+ 4, /* vhcurveto */
+ 1, /* vlineto */
+ 1, /* vmoveto */
+
+ 0, /* dotsection */
+
+ 2, /* hstem */
+ 6, /* hstem3 */
+ 2, /* vstem */
+ 6, /* vstem3 */
+
+ 2, /* div */
+ -1, /* callothersubr */
+ 1, /* callsubr */
+ 0, /* pop */
+ 0, /* return */
+ 2 /* setcurrentpoint */
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** GENERIC CHARSTRING PARSING *********/
+ /********** *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* CID_Init_Builder */
+ /* */
+ /* <Description> */
+ /* Initializes a given glyph builder. */
+ /* */
+ /* <InOut> */
+ /* builder :: A pointer to the glyph builder to initialize. */
+ /* */
+ /* <Input> */
+ /* face :: The current face object. */
+ /* */
+ /* size :: The current size object. */
+ /* */
+ /* glyph :: The current glyph object. */
+ /* */
+ LOCAL_FUNC
+ void CID_Init_Builder( CID_Builder* builder,
+ CID_Face face,
+ CID_Size size,
+ CID_GlyphSlot glyph )
+ {
+ builder->path_begun = 0;
+ builder->load_points = 1;
+
+ builder->face = face;
+ builder->glyph = glyph;
+ builder->memory = face->root.memory;
+
+ if ( glyph )
+ {
+ FT_GlyphLoader* loader = glyph->root.loader;
+
+
+ builder->loader = loader;
+ builder->base = &loader->base.outline;
+ builder->current = &loader->current.outline;
+
+ FT_GlyphLoader_Rewind( loader );
+ }
+
+ if ( size )
+ {
+ builder->scale_x = size->root.metrics.x_scale;
+ builder->scale_y = size->root.metrics.y_scale;
+ }
+
+ builder->pos_x = 0;
+ builder->pos_y = 0;
+
+ builder->left_bearing.x = 0;
+ builder->left_bearing.y = 0;
+ builder->advance.x = 0;
+ builder->advance.y = 0;
+
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* CID_Done_Builder */
+ /* */
+ /* <Description> */
+ /* Finalizes a given glyph builder. Its contents can still be used */
+ /* after the call, but the function saves important information */
+ /* within the corresponding glyph slot. */
+ /* */
+ /* <Input> */
+ /* builder :: A pointer to the glyph builder to finalize. */
+ /* */
+ LOCAL_FUNC
+ void CID_Done_Builder( CID_Builder* builder )
+ {
+ CID_GlyphSlot glyph = builder->glyph;
+
+
+ if ( glyph )
+ glyph->root.outline = *builder->base;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* CID_Init_Decoder */
+ /* */
+ /* <Description> */
+ /* Initializes a given glyph decoder. */
+ /* */
+ /* <InOut> */
+ /* decoder :: A pointer to the glyph builder to initialize. */
+ /* */
+ LOCAL_FUNC
+ void CID_Init_Decoder( CID_Decoder* decoder )
+ {
+ MEM_Set( decoder, 0, sizeof ( *decoder ) );
+
+ decoder->font_matrix.xx = 0x10000L;
+ decoder->font_matrix.yy = 0x10000L;
+ }
+
+
+ /* check that there is enough space for `count' more points */
+ static
+ FT_Error check_points( CID_Builder* builder,
+ FT_Int count )
+ {
+ return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
+ }
+
+
+ /* add a new point, but do not check space */
+ static
+ void add_point( CID_Builder* builder,
+ FT_Pos x,
+ FT_Pos y,
+ FT_Byte flag )
+ {
+ FT_Outline* outline = builder->current;
+
+
+ if ( builder->load_points )
+ {
+ FT_Vector* point = outline->points + outline->n_points;
+ FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
+
+
+ point->x = x;
+ point->y = y;
+ *control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic;
+
+ builder->last = *point;
+ }
+
+ outline->n_points++;
+ }
+
+
+ /* check space for a new on-curve point, then add it */
+ static
+ FT_Error add_point1( CID_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ FT_Error error;
+
+
+ error = check_points( builder, 1 );
+ if ( !error )
+ add_point( builder, x, y, 1 );
+
+ return error;
+ }
+
+
+ /* check room for a new contour, then add it */
+ static
+ FT_Error add_contour( CID_Builder* builder )
+ {
+ FT_Outline* outline = builder->current;
+ FT_Error error;
+
+
+ if ( !builder->load_points )
+ {
+ outline->n_contours++;
+ return T1_Err_Ok;
+ }
+
+ error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
+ if ( !error )
+ {
+ if ( outline->n_contours > 0 )
+ outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+
+ outline->n_contours++;
+ }
+ return error;
+ }
+
+
+ /* if a path has been started, add its first on-curve point */
+ static
+ FT_Error start_point( CID_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ /* test whether we are building a new contour */
+ if ( !builder->path_begun )
+ {
+ FT_Error error;
+
+
+ builder->path_begun = 1;
+ error = add_contour( builder );
+ if ( error )
+ return error;
+ }
+
+ return add_point1( builder, x, y );
+ }
+
+
+ /* close the current contour */
+ static
+ void close_contour( CID_Builder* builder )
+ {
+ FT_Outline* outline = builder->current;
+
+
+ /* XXX: We must not include the last point in the path if it */
+ /* is located on the first point. */
+ if ( outline->n_points > 1 )
+ {
+ FT_Int first = 0;
+ FT_Vector* p1 = outline->points + first;
+ FT_Vector* p2 = outline->points + outline->n_points - 1;
+
+
+ if ( outline->n_contours > 1 )
+ {
+ first = outline->contours[outline->n_contours - 2] + 1;
+ p1 = outline->points + first;
+ }
+
+ if ( p1->x == p2->x && p1->y == p2->y )
+ outline->n_points--;
+ }
+
+ if ( outline->n_contours > 0 )
+ outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+ }
+
+
+#if 0
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* lookup_glyph_by_stdcharcode */
+ /* */
+ /* <Description> */
+ /* Looks up a given glyph by its StandardEncoding charcode. Used */
+ /* to implement the SEAC Type 1 operator. */
+ /* */
+ /* <Input> */
+ /* face :: The current face object. */
+ /* */
+ /* charcode :: The character code to look for. */
+ /* */
+ /* <Return> */
+ /* A glyph index in the font face. Returns -1 if the corresponding */
+ /* glyph wasn't found. */
+ /* */
+ static
+ FT_Int lookup_glyph_by_stdcharcode( CID_Face face,
+ FT_Int charcode )
+ {
+ FT_Int n;
+ const FT_String* glyph_name;
+ PSNames_Interface* psnames = (PSNames_Interface*)face->psnames;
+
+
+ /* check range of standard char code */
+ if ( charcode < 0 || charcode > 255 )
+ return -1;
+
+ glyph_name = psnames->adobe_std_strings(
+ psnames->adobe_std_encoding[charcode]);
+
+ for ( n = 0; n < face->cid.cid_count; n++ )
+ {
+ FT_String* name = (FT_String*)face->type1.glyph_names[n];
+
+
+ if ( name && strcmp( name, glyph_name ) == 0 )
+ return n;
+ }
+
+ return -1;
+ }
+
+
+#endif /* 0 */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1operator_seac */
+ /* */
+ /* <Description> */
+ /* Implements the `seac' Type 1 operator for a Type 1 decoder. */
+ /* */
+ /* <Input> */
+ /* decoder :: The current CID decoder. */
+ /* */
+ /* asb :: The accent's side bearing. */
+ /* */
+ /* adx :: The horizontal offset of the accent. */
+ /* */
+ /* ady :: The vertical offset of the accent. */
+ /* */
+ /* bchar :: The base character's StandardEncoding charcode. */
+ /* */
+ /* achar :: The accent character's StandardEncoding charcode. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error t1operator_seac( CID_Decoder* decoder,
+ FT_Pos asb,
+ FT_Pos adx,
+ FT_Pos ady,
+ FT_Int bchar,
+ FT_Int achar )
+ {
+ FT_Error error;
+ FT_Int bchar_index, achar_index, n_base_points;
+ FT_Outline* base = decoder->builder.base;
+ FT_Vector left_bearing, advance;
+
+
+ bchar_index = bchar;
+ achar_index = achar;
+
+ if ( bchar_index < 0 || achar_index < 0 )
+ {
+ FT_ERROR(( "t1operator_seac:" ));
+ FT_ERROR(( " invalid seac character code arguments\n" ));
+ return T1_Err_Syntax_Error;
+ }
+
+ /* if we are trying to load a composite glyph, do not load the */
+ /* accent character and return the array of subglyphs. */
+ if ( decoder->builder.no_recurse )
+ {
+ FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
+ FT_GlyphLoader* loader = glyph->loader;
+ FT_SubGlyph* subg;
+
+
+ /* reallocate subglyph array if necessary */
+ error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
+ if ( error )
+ goto Exit;
+
+ subg = loader->current.subglyphs;
+
+ /* subglyph 0 = base character */
+ subg->index = bchar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+ FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+ subg->arg1 = 0;
+ subg->arg2 = 0;
+ subg++;
+
+ /* subglyph 1 = accent character */
+ subg->index = achar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+ subg->arg1 = adx - asb;
+ subg->arg2 = ady;
+
+ /* set up remaining glyph fields */
+ glyph->num_subglyphs = 2;
+ glyph->subglyphs = loader->current.subglyphs;
+ glyph->format = ft_glyph_format_composite;
+
+ loader->current.num_subglyphs = 2;
+ }
+
+ /* First load `bchar' in builder */
+ /* now load the unscaled outline */
+ if ( decoder->builder.loader )
+ FT_GlyphLoader_Prepare( decoder->builder.loader );
+
+ error = cid_load_glyph( decoder, bchar_index ); /* load one glyph */
+ if ( error )
+ goto Exit;
+
+ n_base_points = base->n_points;
+
+ {
+ /* save the left bearing and width of the base character */
+ /* as they will be erased by the next load. */
+
+ left_bearing = decoder->builder.left_bearing;
+ advance = decoder->builder.advance;
+
+ decoder->builder.left_bearing.x = 0;
+ decoder->builder.left_bearing.y = 0;
+
+ /* Now load `achar' on top of */
+ /* the base outline */
+ error = cid_load_glyph( decoder, achar_index );
+ if ( error )
+ return error;
+
+ /* restore the left side bearing and */
+ /* advance width of the base character */
+
+ decoder->builder.left_bearing = left_bearing;
+ decoder->builder.advance = advance;
+
+ /* Finally, move the accent */
+ if ( decoder->builder.load_points )
+ {
+ FT_Outline dummy;
+
+
+ dummy.n_points = base->n_points - n_base_points;
+ dummy.points = base->points + n_base_points;
+ FT_Outline_Translate( &dummy, adx - asb, ady );
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+#define USE_ARGS( n ) do \
+ { \
+ top -= n; \
+ if ( top < decoder->stack ) \
+ goto Stack_Underflow; \
+ } while ( 0 )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* CID_Parse_CharStrings */
+ /* */
+ /* <Description> */
+ /* Parses a given CID charstrings program. */
+ /* */
+ /* <InOut> */
+ /* decoder :: The current CID decoder. */
+ /* */
+ /* <Input> */
+ /* charstring_base :: The base of the charstring stream. */
+ /* */
+ /* charstring_len :: The length in bytes of the charstring stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error CID_Parse_CharStrings( CID_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_Int charstring_len )
+ {
+ FT_Error error;
+ CID_Decoder_Zone* zone;
+ FT_Byte* ip;
+ FT_Byte* limit;
+ CID_Builder* builder = &decoder->builder;
+ FT_Outline* outline;
+ FT_Pos x, y;
+
+
+ /* First of all, initialize the decoder */
+ decoder->top = decoder->stack;
+ decoder->zone = decoder->zones;
+ zone = decoder->zones;
+
+ builder->path_begun = 0;
+
+ zone->base = charstring_base;
+ limit = zone->limit = charstring_base + charstring_len;
+ ip = zone->cursor = zone->base;
+
+ error = T1_Err_Ok;
+ outline = builder->current;
+
+ x = builder->pos_x;
+ y = builder->pos_y;
+
+ /* now, execute loop */
+ while ( ip < limit )
+ {
+ FT_Int* top = decoder->top;
+ CID_Operator op = op_none;
+ FT_Long value = 0;
+
+
+ /********************************************************************/
+ /* */
+ /* Decode operator or operand */
+ /* */
+
+ /* First of all, decompress operator or value */
+ switch ( *ip++ )
+ {
+ case 1:
+ op = op_hstem;
+ break;
+
+ case 3:
+ op = op_vstem;
+ break;
+ case 4:
+ op = op_vmoveto;
+ break;
+ case 5:
+ op = op_rlineto;
+ break;
+ case 6:
+ op = op_hlineto;
+ break;
+ case 7:
+ op = op_vlineto;
+ break;
+ case 8:
+ op = op_rrcurveto;
+ break;
+ case 9:
+ op = op_closepath;
+ break;
+ case 10:
+ op = op_callsubr;
+ break;
+ case 11:
+ op = op_return;
+ break;
+
+ case 13:
+ op = op_hsbw;
+ break;
+ case 14:
+ op = op_endchar;
+ break;
+
+ case 21:
+ op = op_rmoveto;
+ break;
+ case 22:
+ op = op_hmoveto;
+ break;
+
+ case 30:
+ op = op_vhcurveto;
+ break;
+ case 31:
+ op = op_hvcurveto;
+ break;
+
+ case 12:
+ if ( ip > limit )
+ {
+ FT_ERROR(( "CID_Parse_CharStrings: invalid escape (12+EOF)\n" ));
+ goto Syntax_Error;
+ }
+
+ switch ( *ip++ )
+ {
+ case 0:
+ op = op_dotsection;
+ break;
+ case 1:
+ op = op_vstem3;
+ break;
+ case 2:
+ op = op_hstem3;
+ break;
+ case 6:
+ op = op_seac;
+ break;
+ case 7:
+ op = op_sbw;
+ break;
+ case 12:
+ op = op_div;
+ break;
+ case 16:
+ op = op_callothersubr;
+ break;
+ case 17:
+ op = op_pop;
+ break;
+ case 33:
+ op = op_setcurrentpoint;
+ break;
+
+ default:
+ FT_ERROR(( "CID_Parse_CharStrings: invalid escape (12+%d)\n",
+ ip[-1] ));
+ goto Syntax_Error;
+ }
+ break;
+
+ case 255: /* four bytes integer */
+ if ( ip + 4 > limit )
+ {
+ FT_ERROR(( "CID_Parse_CharStrings: unexpected EOF in integer\n" ));
+ goto Syntax_Error;
+ }
+
+ value = ( (long)ip[0] << 24 ) |
+ ( (long)ip[1] << 16 ) |
+ ( (long)ip[2] << 8 ) |
+ ip[3];
+ ip += 4;
+ break;
+
+ default:
+ if ( ip[-1] >= 32 )
+ {
+ if ( ip[-1] < 247 )
+ value = (long)ip[-1] - 139;
+ else
+ {
+ if ( ++ip > limit )
+ {
+ FT_ERROR(( "CID_Parse_CharStrings:" ));
+ FT_ERROR(( " unexpected EOF in integer\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( ip[-2] < 251 )
+ value = ( (long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
+ else
+ value = -( ( ( (long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
+ }
+ }
+ else
+ {
+ FT_ERROR(( "CID_Parse_CharStrings: invalid byte (%d)\n",
+ ip[-1] ));
+ goto Syntax_Error;
+ }
+ }
+
+ /********************************************************************/
+ /* */
+ /* Push value on stack, or process operator */
+ /* */
+ if ( op == op_none )
+ {
+ if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
+ {
+ FT_ERROR(( "CID_Parse_CharStrings: Stack overflow!\n" ));
+ goto Syntax_Error;
+ }
+
+ FT_TRACE4(( " %ld", value ));
+ *top++ = value;
+ decoder->top = top;
+ }
+ else if ( op == op_callothersubr ) /* callothersubr */
+ {
+ FT_TRACE4(( " callothersubr" ));
+
+ if ( top - decoder->stack < 2 )
+ goto Stack_Underflow;
+
+ top -= 2;
+ switch ( top[1] )
+ {
+ case 1: /* start flex feature ---------------------- */
+ if ( top[0] != 0 )
+ goto Unexpected_OtherSubr;
+
+ decoder->flex_state = 1;
+ decoder->num_flex_vectors = 0;
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, 6 ) )
+ goto Memory_Error;
+ break;
+
+ case 2: /* add flex vectors ------------------------ */
+ {
+ FT_Int index;
+
+
+ if ( top[0] != 0 )
+ goto Unexpected_OtherSubr;
+
+ /* note that we should not add a point for index 0. */
+ /* this will move our current position to the flex */
+ /* point without adding any point to the outline */
+ index = decoder->num_flex_vectors++;
+ if ( index > 0 && index < 7 )
+ add_point( builder,
+ x,
+ y,
+ (FT_Byte)( index==3 || index==6 ) );
+ }
+ break;
+
+ case 0: /* end flex feature ------------------------- */
+ if ( top[0] != 3 )
+ goto Unexpected_OtherSubr;
+
+ if ( decoder->flex_state == 0 ||
+ decoder->num_flex_vectors != 7 )
+ {
+ FT_ERROR(( "CID_Parse_CharStrings: unexpected flex end\n" ));
+ goto Syntax_Error;
+ }
+
+ /* now consume the remaining `pop pop setcurpoint' */
+ if ( ip + 6 > limit ||
+ ip[0] != 12 || ip[1] != 17 || /* pop */
+ ip[2] != 12 || ip[3] != 17 || /* pop */
+ ip[4] != 12 || ip[5] != 33 ) /* setcurpoint */
+ {
+ FT_ERROR(( "CID_Parse_CharStrings: invalid flex charstring\n" ));
+ goto Syntax_Error;
+ }
+
+ ip += 6;
+ decoder->flex_state = 0;
+ break;
+
+ case 3: /* change hints ---------------------------- */
+ if ( top[0] != 1 )
+ goto Unexpected_OtherSubr;
+
+ /* eat the following `pop' */
+ if ( ip + 2 > limit )
+ {
+ FT_ERROR(( "CID_Parse_CharStrings: invalid escape (12+%d)\n",
+ ip[-1] ));
+ goto Syntax_Error;
+ }
+
+ if ( ip[0] != 12 || ip[1] != 17 )
+ {
+ FT_ERROR(( "CID_Parse_CharStrings:" ));
+ FT_ERROR(( " `pop' expected, found (%d %d)\n",
+ ip[0], ip[1] ));
+ goto Syntax_Error;
+ }
+ ip += 2;
+ break;
+
+ case 12:
+ case 13:
+ /* counter control hints, clear stack */
+ top = decoder->stack;
+ break;
+
+#if 0
+
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18: /* multiple masters */
+ {
+ T1_Blend* blend = decoder->blend;
+ FT_UInt num_points, nn, mm;
+ FT_Int* delta;
+ FT_Int* values;
+
+
+ if ( !blend )
+ {
+ FT_ERROR(( "CID_Parse_CharStrings:" ));
+ FT_ERROR(( " unexpected multiple masters operator!\n" ));
+ goto Syntax_Error;
+ }
+
+ num_points = top[1] - 13 + ( top[1] == 18 );
+ if ( top[0] != num_points * blend->num_designs )
+ {
+ FT_ERROR(( "CID_Parse_CharStrings:" ));
+ FT_ERROR(( " incorrect number of mm arguments\n" ));
+ goto Syntax_Error;
+ }
+
+ top -= blend->num_designs * num_points;
+ if ( top < decoder->stack )
+ goto Stack_Underflow;
+
+ /* We want to compute: */
+ /* */
+ /* a0*w0 + a1*w1 + ... + ak*wk */
+ /* */
+ /* but we only have the a0, a1-a0, a2-a0, .. ak-a0. */
+ /* However, given that w0 + w1 + ... + wk == 1, we can */
+ /* rewrite it easily as: */
+ /* */
+ /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */
+ /* */
+ /* where k == num_designs-1 */
+ /* */
+ /* I guess that's why it's written in this `compact' */
+ /* form... */
+ /* */
+ delta = top + num_points;
+ values = top;
+ for ( nn = 0; nn < num_points; nn++ )
+ {
+ FT_Int x = values[0];
+
+
+ for ( mm = 1; mm < blend->num_designs; mm++ )
+ x += FT_MulFix( *delta++, blend->weight_vector[mm] );
+
+ *values++ = x;
+ }
+ /* note that `top' will be incremented later by calls to `pop' */
+ }
+ break;
+
+#endif
+
+ default:
+ Unexpected_OtherSubr:
+ FT_ERROR(( "CID_Parse_CharStrings: invalid othersubr [%d %d]!\n",
+ top[0], top[1] ));
+ goto Syntax_Error;
+ }
+ decoder->top = top;
+ }
+ else /* general operator */
+ {
+ FT_Int num_args = t1_args_count[op];
+
+
+ if ( top - decoder->stack < num_args )
+ goto Stack_Underflow;
+
+ top -= num_args;
+
+ switch ( op )
+ {
+ case op_endchar:
+ FT_TRACE4(( " endchar" ));
+
+ close_contour( builder );
+
+ /* add current outline to the glyph slot */
+ FT_GlyphLoader_Add( builder->loader );
+
+ /* return now! */
+ FT_TRACE4(( "\n\n" ));
+ return T1_Err_Ok;
+
+ case op_hsbw:
+ FT_TRACE4(( " hsbw" ));
+
+ builder->left_bearing.x += top[0];
+ builder->advance.x = top[1];
+ builder->advance.y = 0;
+
+ builder->last.x = x = top[0];
+ builder->last.y = y = 0;
+
+ /* The `metrics_only' indicates that we only want to compute */
+ /* the glyph's metrics (lsb + advance width), not load the */
+ /* rest of it. So exit immediately. */
+ if ( builder->metrics_only )
+ return T1_Err_Ok;
+
+ break;
+
+ case op_seac:
+ /* return immediately after processing */
+ return t1operator_seac( decoder, top[0], top[1],
+ top[2], top[3], top[4] );
+
+ case op_sbw:
+ FT_TRACE4(( " sbw" ));
+
+ builder->left_bearing.x += top[0];
+ builder->left_bearing.y += top[1];
+ builder->advance.x = top[2];
+ builder->advance.y = top[3];
+
+ builder->last.x = x = top[0];
+ builder->last.y = y = top[1];
+
+ /* The `metrics_only' indicates that we only want to compute */
+ /* the glyph's metrics (lsb + advance width), not load the */
+ /* rest of it. So exit immediately. */
+ if ( builder->metrics_only )
+ return T1_Err_Ok;
+
+ break;
+
+ case op_closepath:
+ FT_TRACE4(( " closepath" ));
+
+ close_contour( builder );
+ builder->path_begun = 0;
+ break;
+
+ case op_hlineto:
+ FT_TRACE4(( " hlineto" ));
+
+ if ( start_point( builder, x, y ) )
+ goto Memory_Error;
+
+ x += top[0];
+ goto Add_Line;
+
+ case op_hmoveto:
+ FT_TRACE4(( " hmoveto" ));
+
+ x += top[0];
+ break;
+
+ case op_hvcurveto:
+ FT_TRACE4(( " hvcurveto" ));
+
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, 3 ) )
+ goto Memory_Error;
+
+ x += top[0];
+ add_point( builder, x, y, 0 );
+
+ x += top[1];
+ y += top[2];
+ add_point( builder, x, y, 0 );
+
+ y += top[3];
+ add_point( builder, x, y, 1 );
+
+ break;
+
+ case op_rlineto:
+ FT_TRACE4(( " rlineto" ));
+
+ if ( start_point( builder, x, y ) )
+ goto Memory_Error;
+
+ x += top[0];
+ y += top[1];
+
+ Add_Line:
+ if ( add_point1( builder, x, y ) )
+ goto Memory_Error;
+ break;
+
+ case op_rmoveto:
+ FT_TRACE4(( " rmoveto" ));
+
+ x += top[0];
+ y += top[1];
+ break;
+
+ case op_rrcurveto:
+ FT_TRACE4(( " rcurveto" ));
+
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, 3 ) )
+ goto Memory_Error;
+
+ x += top[0];
+ y += top[1];
+ add_point( builder, x, y, 0 );
+
+ x += top[2];
+ y += top[3];
+ add_point( builder, x, y, 0 );
+
+ x += top[4];
+ y += top[5];
+ add_point( builder, x, y, 1 );
+
+ break;
+
+ case op_vhcurveto:
+ FT_TRACE4(( " vhcurveto" ));
+
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, 3 ) )
+ goto Memory_Error;
+
+ y += top[0];
+ add_point( builder, x, y, 0 );
+
+ x += top[1];
+ y += top[2];
+ add_point( builder, x, y, 0 );
+
+ x += top[3];
+ add_point( builder, x, y, 1 );
+
+ break;
+
+ case op_vlineto:
+ FT_TRACE4(( " vlineto" ));
+
+ if ( start_point( builder, x, y ) )
+ goto Memory_Error;
+
+ y += top[0];
+ goto Add_Line;
+
+ case op_vmoveto:
+ FT_TRACE4(( " vmoveto" ));
+
+ y += top[0];
+ break;
+
+ case op_div:
+ FT_TRACE4(( " div" ));
+
+ if ( top[1] )
+ {
+ *top = top[0] / top[1];
+ top++;
+ }
+ else
+ {
+ FT_ERROR(( "CID_Parse_CharStrings: division by 0\n" ));
+ goto Syntax_Error;
+ }
+ break;
+
+ case op_callsubr:
+ {
+ FT_Int index;
+
+
+ FT_TRACE4(( " callsubr" ));
+
+ index = top[0];
+ if ( index < 0 || index >= (FT_Int)decoder->subrs->num_subrs )
+ {
+ FT_ERROR(( "CID_Parse_CharStrings: invalid subrs index\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
+ {
+ FT_ERROR(( "CID_Parse_CharStrings: too many nested subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ zone->cursor = ip; /* save current instruction pointer */
+
+ zone++;
+ zone->base = decoder->subrs->code[index] + decoder->lenIV;
+ zone->limit = decoder->subrs->code[index + 1];
+ zone->cursor = zone->base;
+
+ if ( !zone->base )
+ {
+ FT_ERROR(( "CID_Parse_CharStrings: invoking empty subrs!\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone = zone;
+ ip = zone->base;
+ limit = zone->limit;
+ }
+ break;
+
+ case op_pop:
+ FT_TRACE4(( " pop" ));
+
+ /* theoretically, the arguments are already on the stack */
+ top++;
+ break;
+
+ case op_return:
+ FT_TRACE4(( " return" ));
+
+ if ( zone <= decoder->zones )
+ {
+ FT_ERROR(( "CID_Parse_CharStrings: unexpected return\n" ));
+ goto Syntax_Error;
+ }
+
+ zone--;
+ ip = zone->cursor;
+ limit = zone->limit;
+ decoder->zone = zone;
+
+ break;
+
+ case op_dotsection:
+ FT_TRACE4(( " dotsection" ));
+
+ break;
+
+ case op_hstem:
+ FT_TRACE4(( " hstem" ));
+
+ break;
+
+ case op_hstem3:
+ FT_TRACE4(( " hstem3" ));
+
+ break;
+
+ case op_vstem:
+ FT_TRACE4(( " vstem" ));
+
+ break;
+
+ case op_vstem3:
+ FT_TRACE4(( " vstem3" ));
+
+ break;
+
+ case op_setcurrentpoint:
+ FT_TRACE4(( " setcurrentpoint" ));
+
+ FT_ERROR(( "CID_Parse_CharStrings:" ));
+ FT_ERROR(( " unexpected `setcurrentpoint'\n" ));
+ goto Syntax_Error;
+
+ default:
+ FT_ERROR(( "CID_Parse_CharStrings: unhandled opcode %d\n", op ));
+ goto Syntax_Error;
+ }
+
+ decoder->top = top;
+
+ } /* general operator processing */
+
+ } /* while ip < limit */
+
+ FT_TRACE4(( "..end..\n\n" ));
+
+ return error;
+
+ Syntax_Error:
+ return T1_Err_Syntax_Error;
+
+ Stack_Underflow:
+ return T1_Err_Stack_Underflow;
+
+ Memory_Error:
+ return builder->error;
+ }
+
+
+#if 0
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
+ /********** *********/
+ /********** The following code is in charge of computing *********/
+ /********** the maximum advance width of the font. It *********/
+ /********** quickly processes each glyph charstring to *********/
+ /********** extract the value from either a `sbw' or `seac' *********/
+ /********** operator. *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ LOCAL_FUNC
+ FT_Error CID_Compute_Max_Advance( CID_Face face,
+ FT_Int* max_advance )
+ {
+ FT_Error error;
+ CID_Decoder decoder;
+ FT_Int glyph_index;
+
+
+ *max_advance = 0;
+
+ /* Initialize load decoder */
+ CID_Init_Decoder( &decoder );
+ CID_Init_Builder( &decoder.builder, face, 0, 0 );
+
+ decoder.builder.metrics_only = 1;
+ decoder.builder.load_points = 0;
+
+ /* for each glyph, parse the glyph charstring and extract */
+ /* the advance width */
+ for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
+ glyph_index++ )
+ {
+ /* now get load the unscaled outline */
+ error = cid_load_glyph( &decoder, glyph_index );
+ /* ignore the error if one occurred - skip to next glyph */
+ }
+
+ *max_advance = decoder.builder.advance.x;
+
+ return T1_Err_Ok;
+ }
+
+
+#endif /* 0 */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** UNHINTED GLYPH LOADER *********/
+ /********** *********/
+ /********** The following code is in charge of loading a *********/
+ /********** single outline. It completely ignores hinting *********/
+ /********** and is used when FT_LOAD_NO_HINTING is set. *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static
+ FT_Error cid_load_glyph( CID_Decoder* decoder,
+ FT_UInt glyph_index )
+ {
+ CID_Face face = decoder->builder.face;
+ CID_Info* cid = &face->cid;
+ FT_Byte* p;
+ FT_UInt entry_len = cid->fd_bytes + cid->gd_bytes;
+ FT_UInt fd_select;
+ FT_ULong off1, glyph_len;
+ FT_Stream stream = face->root.stream;
+ FT_Error error = 0;
+
+
+ /* read the CID font dict index and charstring offset from the CIDMap */
+ if ( FILE_Seek( cid->data_offset + cid->cidmap_offset +
+ glyph_index * entry_len) ||
+ ACCESS_Frame( 2 * entry_len ) )
+ goto Exit;
+
+ p = (FT_Byte*)stream->cursor;
+ fd_select = (FT_UInt) cid_get_offset( &p, (FT_Byte)cid->fd_bytes );
+ off1 = (FT_ULong)cid_get_offset( &p, (FT_Byte)cid->gd_bytes );
+ p += cid->fd_bytes;
+ glyph_len = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1;
+
+ FORGET_Frame();
+
+ /* now, if the glyph is not empty, set up the subrs array, and parse */
+ /* the charstrings */
+ if ( glyph_len > 0 )
+ {
+ CID_FontDict* dict;
+ FT_Byte* charstring;
+ FT_UInt lenIV;
+ FT_Memory memory = face->root.memory;
+
+
+ /* setup subrs */
+ decoder->subrs = face->subrs + fd_select;
+
+ /* setup font matrix */
+ dict = cid->font_dicts + fd_select;
+ decoder->font_matrix = dict->font_matrix;
+ lenIV = dict->private_dict.lenIV;
+ decoder->lenIV = lenIV;
+
+ /* the charstrings are encoded (stupid!) */
+ /* load the charstrings, then execute it */
+
+ if ( ALLOC( charstring, glyph_len ) )
+ goto Exit;
+
+ if ( !FILE_Read_At( cid->data_offset + off1, charstring, glyph_len ) )
+ {
+ cid_decrypt( charstring, glyph_len, 4330 );
+ error = CID_Parse_CharStrings( decoder,
+ charstring + lenIV,
+ glyph_len - lenIV );
+ }
+
+ FREE( charstring );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ FT_Error CID_Load_Glyph( CID_GlyphSlot glyph,
+ CID_Size size,
+ FT_Int glyph_index,
+ FT_Int load_flags )
+ {
+ FT_Error error;
+ CID_Decoder decoder;
+ CID_Face face = (CID_Face)glyph->root.face;
+ FT_Bool hinting;
+
+
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+ glyph->x_scale = size->root.metrics.x_scale;
+ glyph->y_scale = size->root.metrics.y_scale;
+
+ glyph->root.outline.n_points = 0;
+ glyph->root.outline.n_contours = 0;
+
+ hinting = ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
+ ( load_flags & FT_LOAD_NO_HINTING ) == 0;
+
+ glyph->root.format = ft_glyph_format_outline;
+
+ {
+ CID_Init_Decoder( &decoder );
+ CID_Init_Builder( &decoder.builder, face, size, glyph );
+
+ /* set up the decoder */
+ decoder.builder.no_recurse =
+ (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE );
+
+ error = cid_load_glyph( &decoder, glyph_index );
+
+ /* save new glyph tables */
+ CID_Done_Builder( &decoder.builder );
+ }
+
+ /* Now, set the metrics - this is rather simple, as */
+ /* the left side bearing is the xMin, and the top side */
+ /* bearing the yMax. */
+ if ( !error )
+ {
+ /* for composite glyphs, return only the left side bearing and the */
+ /* advance width */
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ {
+ glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+ glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
+ }
+ else
+ {
+ FT_BBox cbox;
+ FT_Glyph_Metrics* metrics = &glyph->root.metrics;
+
+
+ /* copy the _unscaled_ advance width */
+ metrics->horiAdvance = decoder.builder.advance.x;
+
+ /* make up vertical metrics */
+ metrics->vertBearingX = 0;
+ metrics->vertBearingY = 0;
+ metrics->vertAdvance = 0;
+
+ glyph->root.format = ft_glyph_format_outline;
+
+ glyph->root.outline.flags &= ft_outline_owner;
+ if ( size && size->root.metrics.y_ppem < 24 )
+ glyph->root.outline.flags |= ft_outline_high_precision;
+
+ glyph->root.outline.flags |= ft_outline_reverse_fill;
+
+#if 0
+ glyph->root.outline.second_pass = TRUE;
+ glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24;
+ glyph->root.outline.dropout_mode = 2;
+#endif
+
+ if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ /* scale the outline and the metrics */
+ FT_Int n;
+ FT_Outline* cur = &glyph->root.outline;
+ FT_Vector* vec = cur->points;
+ FT_Fixed x_scale = glyph->x_scale;
+ FT_Fixed y_scale = glyph->y_scale;
+
+
+ /* First of all, scale the points */
+ for ( n = cur->n_points; n > 0; n--, vec++ )
+ {
+ vec->x = FT_MulFix( vec->x, x_scale );
+ vec->y = FT_MulFix( vec->y, y_scale );
+ }
+
+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+ /* Then scale the metrics */
+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
+
+ metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+ metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+ }
+
+ /* apply the font matrix */
+ FT_Outline_Transform( &glyph->root.outline, &decoder.font_matrix );
+
+ /* compute the other metrics */
+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+ /* grid fit the bounding box if necessary */
+ if ( hinting )
+ {
+ cbox.xMin &= -64;
+ cbox.yMin &= -64;
+ cbox.xMax = ( cbox.xMax + 63 ) & -64;
+ cbox.yMax = ( cbox.yMax + 63 ) & -64;
+ }
+
+ metrics->width = cbox.xMax - cbox.xMin;
+ metrics->height = cbox.yMax - cbox.yMin;
+
+ metrics->horiBearingX = cbox.xMin;
+ metrics->horiBearingY = cbox.yMax;
+ }
+ }
+
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* cidgload.h */
+/* */
+/* OpenType Glyph Loader (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef CIDGLOAD_H
+#define CIDGLOAD_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidobjs.h"
+
+#else
+
+#include <cid/cidobjs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Structure> */
+ /* CID_Builder */
+ /* */
+ /* <Description> */
+ /* A structure used during glyph loading to store its outline. */
+ /* */
+ /* <Fields> */
+ /* memory :: The current memory object. */
+ /* */
+ /* face :: The current face object. */
+ /* */
+ /* glyph :: The current glyph slot. */
+ /* */
+ /* current :: The current glyph outline. */
+ /* */
+ /* base :: The base glyph outline. */
+ /* */
+ /* max_points :: maximum points in builder outline */
+ /* */
+ /* max_contours :: Maximal number of contours in builder outline. */
+ /* */
+ /* last :: The last point position. */
+ /* */
+ /* scale_x :: The horizontal scale (FUnits to sub-pixels). */
+ /* */
+ /* scale_y :: The vertical scale (FUnits to sub-pixels). */
+ /* */
+ /* pos_x :: The horizontal translation (if composite glyph). */
+ /* */
+ /* pos_y :: The vertical translation (if composite glyph). */
+ /* */
+ /* left_bearing :: The left side bearing point. */
+ /* */
+ /* advance :: The horizontal advance vector. */
+ /* */
+ /* bbox :: Unused. */
+ /* */
+ /* path_begun :: A flag which indicates that a new path has begun. */
+ /* */
+ /* load_points :: If this flag is not set, no points are loaded. */
+ /* */
+ /* no_recurse :: Set but not used. */
+ /* */
+ /* error :: An error code that is only used to report memory */
+ /* allocation problems. */
+ /* */
+ /* metrics_only :: A boolean indicating that we only want to compute */
+ /* the metrics of a given glyph, not load all of its */
+ /* points. */
+ /* */
+ typedef struct CID_Builder_
+ {
+ FT_Memory memory;
+ CID_Face face;
+ CID_GlyphSlot glyph;
+ FT_GlyphLoader* loader;
+ FT_Outline* base;
+ FT_Outline* current;
+
+ FT_Vector last;
+
+ FT_Fixed scale_x;
+ FT_Fixed scale_y;
+
+ FT_Pos pos_x;
+ FT_Pos pos_y;
+
+ FT_Vector left_bearing;
+ FT_Vector advance;
+
+ FT_BBox bbox; /* bounding box */
+ FT_Bool path_begun;
+ FT_Bool load_points;
+ FT_Bool no_recurse;
+
+ FT_Error error; /* only used for memory errors */
+ FT_Bool metrics_only;
+
+ } CID_Builder;
+
+
+ /* execution context charstring zone */
+
+ typedef struct CID_Decoder_Zone_
+ {
+ FT_Byte* base;
+ FT_Byte* limit;
+ FT_Byte* cursor;
+
+ } CID_Decoder_Zone;
+
+
+ typedef struct CID_Decoder_
+ {
+ CID_Builder builder;
+
+ FT_Int stack[T1_MAX_CHARSTRINGS_OPERANDS];
+ FT_Int* top;
+
+ CID_Decoder_Zone zones[T1_MAX_SUBRS_CALLS + 1];
+ CID_Decoder_Zone* zone;
+
+ FT_Matrix font_matrix;
+ CID_Subrs* subrs;
+ FT_UInt lenIV;
+
+ FT_Int flex_state;
+ FT_Int num_flex_vectors;
+ FT_Vector flex_vectors[7];
+
+ } CID_Decoder;
+
+
+ LOCAL_DEF
+ void CID_Init_Builder( CID_Builder* builder,
+ CID_Face face,
+ CID_Size size,
+ CID_GlyphSlot glyph );
+
+ LOCAL_DEF
+ void CID_Done_Builder( CID_Builder* builder );
+
+
+ LOCAL_DEF
+ void CID_Init_Decoder( CID_Decoder* decoder );
+
+
+#if 0
+
+ /* Compute the maximum advance width of a font through quick parsing */
+ LOCAL_DEF
+ FT_Error CID_Compute_Max_Advance( CID_Face face,
+ FT_Int* max_advance );
+
+#endif
+
+ /* This function is exported, because it is used by the T1Dump utility */
+ LOCAL_DEF
+ FT_Error CID_Parse_CharStrings( CID_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_Int charstring_len );
+
+ LOCAL_DEF
+ FT_Error CID_Load_Glyph( CID_GlyphSlot glyph,
+ CID_Size size,
+ FT_Int glyph_index,
+ FT_Int load_flags );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* CIDGLOAD_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* cidload.c */
+/* */
+/* CID-keyed Type1 font loader (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/config/ftconfig.h>
+#include <freetype/ftmm.h>
+
+#include <freetype/internal/t1types.h>
+#include <freetype/internal/t1errors.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidload.h"
+
+#else
+
+#include <cid/cidload.h>
+
+#endif
+
+
+#include <stdio.h>
+#include <ctype.h> /* for isspace(), isalnum() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cidload
+
+
+ /* read a single offset */
+ LOCAL_FUNC
+ FT_Long cid_get_offset( FT_Byte** start,
+ FT_Byte offsize )
+ {
+ FT_Long result;
+ FT_Byte* p = *start;
+
+
+ for ( result = 0; offsize > 0; offsize-- )
+ {
+ result <<= 8;
+ result |= *p++;
+ }
+
+ *start = p;
+ return result;
+ }
+
+
+ LOCAL_FUNC
+ void cid_decrypt( FT_Byte* buffer,
+ FT_Int length,
+ FT_UShort seed )
+ {
+ while ( length > 0 )
+ {
+ FT_Byte plain;
+
+
+ plain = ( *buffer ^ ( seed >> 8 ) );
+ seed = ( *buffer + seed ) * 52845 + 22719;
+ *buffer++ = plain;
+ length--;
+ }
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** TYPE 1 SYMBOL PARSING *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static
+ FT_Error cid_load_keyword( CID_Face face,
+ CID_Loader* loader,
+ const CID_Field_Rec* keyword )
+ {
+ FT_Error error;
+ CID_Parser* parser = &loader->parser;
+ FT_Byte* object;
+ CID_Info* cid = &face->cid;
+
+
+ /* if the keyword has a dedicated callback, call it */
+ if ( keyword->type == t1_field_callback )
+ {
+ error = keyword->reader( face, parser );
+ goto Exit;
+ }
+
+ /* we must now compute the address of our target object */
+ switch ( keyword->location )
+ {
+ case t1_field_cid_info:
+ object = (FT_Byte*)cid;
+ break;
+
+ case t1_field_font_info:
+ object = (FT_Byte*)&cid->font_info;
+ break;
+
+ default:
+ {
+ CID_FontDict* dict;
+
+
+ if ( parser->num_dict < 0 )
+ {
+ FT_ERROR(( "cid_load_keyword: invalid use of `%s'!\n",
+ keyword->ident ));
+ error = T1_Err_Syntax_Error;
+ goto Exit;
+ }
+
+ dict = cid->font_dicts + parser->num_dict;
+ switch ( keyword->location )
+ {
+ case t1_field_private:
+ object = (FT_Byte*)&dict->private_dict;
+ break;
+
+ default:
+ object = (FT_Byte*)dict;
+ }
+ }
+ }
+
+ /* now, load the keyword data in the object's field(s) */
+ if ( keyword->type == t1_field_integer_array ||
+ keyword->type == t1_field_fixed_array )
+ error = CID_Load_Field_Table( parser, keyword, object );
+ else
+ error = CID_Load_Field( parser, keyword, object );
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ FT_Error parse_font_bbox( CID_Face face,
+ CID_Parser* parser )
+ {
+ FT_Short temp[4];
+ FT_BBox* bbox = &face->cid.font_bbox;
+
+
+ (void)CID_ToCoordArray( parser, 4, temp );
+ bbox->xMin = temp[0];
+ bbox->yMin = temp[1];
+ bbox->xMax = temp[2];
+ bbox->yMax = temp[3];
+
+ return T1_Err_Ok; /* this is a callback function; */
+ /* we must return an error code */
+ }
+
+
+ static
+ FT_Error parse_font_matrix( CID_Face face,
+ CID_Parser* parser )
+ {
+ FT_Matrix* matrix;
+ CID_FontDict* dict;
+ FT_Fixed temp[4];
+
+
+ if ( parser->num_dict >= 0 )
+ {
+ dict = face->cid.font_dicts + parser->num_dict;
+ matrix = &dict->font_matrix;
+
+ (void)CID_ToFixedArray( parser, 4, temp, 3 );
+ matrix->xx = temp[0];
+ matrix->yx = temp[1];
+ matrix->xy = temp[2];
+ matrix->yy = temp[3];
+ }
+
+ return T1_Err_Ok; /* this is a callback function; */
+ /* we must return an error code */
+ }
+
+
+ static
+ FT_Error parse_fd_array( CID_Face face,
+ CID_Parser* parser )
+ {
+ CID_Info* cid = &face->cid;
+ FT_Memory memory = face->root.memory;
+ FT_Error error = T1_Err_Ok;
+ FT_Long num_dicts;
+
+
+ num_dicts = CID_ToInt( parser );
+
+ if ( !cid->font_dicts )
+ {
+ FT_Int n;
+
+
+ if ( ALLOC_ARRAY( cid->font_dicts, num_dicts, CID_FontDict ) )
+ goto Exit;
+
+ cid->num_dicts = (FT_UInt)num_dicts;
+
+ /* don't forget to set a few defaults */
+ for ( n = 0; n < cid->num_dicts; n++ )
+ {
+ CID_FontDict* dict = cid->font_dicts + n;
+
+
+ /* default value for lenIV */
+ dict->private_dict.lenIV = 4;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ const CID_Field_Rec t1_field_records[] =
+ {
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidtokens.h"
+
+#else
+
+#include <cid/cidtokens.h>
+
+#endif
+
+ { 0, t1_field_cid_info, t1_field_none, 0, 0, 0, 0, 0 }
+ };
+
+
+ static
+ int is_alpha( char c )
+ {
+ return ( isalnum( c ) ||
+ c == '.' ||
+ c == '_' );
+ }
+
+
+ static
+ void skip_whitespace( CID_Parser* parser )
+ {
+ FT_Byte* cur = parser->cursor;
+
+
+ while ( cur < parser->limit && isspace( *cur ) )
+ cur++;
+
+ parser->cursor = cur;
+ }
+
+
+ static
+ FT_Error parse_dict( CID_Face face,
+ CID_Loader* loader,
+ FT_Byte* base,
+ FT_Long size )
+ {
+ CID_Parser* parser = &loader->parser;
+
+
+ parser->cursor = base;
+ parser->limit = base + size;
+ parser->error = 0;
+
+ {
+ FT_Byte* cur = base;
+ FT_Byte* limit = cur + size;
+
+
+ for ( ;cur < limit; cur++ )
+ {
+ /* look for `%ADOBeginFontDict' */
+ if ( *cur == '%' && cur + 20 < limit &&
+ strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
+ {
+ cur += 17;
+
+ /* if /FDArray was found, then cid->num_dicts is > 0, and */
+ /* we can start increasing parser->num_dict */
+ if ( face->cid.num_dicts > 0 )
+ parser->num_dict++;
+ }
+ /* look for immediates */
+ else if ( *cur == '/' && cur + 2 < limit )
+ {
+ FT_Byte* cur2;
+ FT_Int len;
+
+
+ cur++;
+
+ cur2 = cur;
+ while ( cur2 < limit && is_alpha( *cur2 ) )
+ cur2++;
+
+ len = cur2 - cur;
+ if ( len > 0 && len < 22 )
+ {
+ /* now compare the immediate name to the keyword table */
+ const CID_Field_Rec* keyword = t1_field_records;
+
+
+ for (;;)
+ {
+ FT_Byte* name;
+
+
+ name = (FT_Byte*)keyword->ident;
+ if ( !name )
+ break;
+
+ if ( cur[0] == name[0] &&
+ len == (FT_Int)strlen( (const char*)name ) )
+ {
+ FT_Int n;
+
+
+ for ( n = 1; n < len; n++ )
+ if ( cur[n] != name[n] )
+ break;
+
+ if ( n >= len )
+ {
+ /* we found it - run the parsing callback */
+ parser->cursor = cur2;
+ skip_whitespace( parser );
+ parser->error = cid_load_keyword( face, loader, keyword );
+ if ( parser->error )
+ return parser->error;
+
+ cur = parser->cursor;
+ break;
+ }
+ }
+ keyword++;
+ }
+ }
+ }
+ }
+ }
+ return parser->error;
+ }
+
+
+ /* read the subrmap and the subrs of each font dict */
+ static
+ FT_Error cid_read_subrs( CID_Face face )
+ {
+ CID_Info* cid = &face->cid;
+ FT_Memory memory = face->root.memory;
+ FT_Stream stream = face->root.stream;
+ FT_Error error;
+ FT_Int n;
+ CID_Subrs* subr;
+ FT_UInt max_offsets = 0;
+ FT_ULong* offsets = 0;
+
+
+ if ( ALLOC_ARRAY( face->subrs, cid->num_dicts, CID_Subrs ) )
+ goto Exit;
+
+ subr = face->subrs;
+ for ( n = 0; n < cid->num_dicts; n++, subr++ )
+ {
+ CID_FontDict* dict = cid->font_dicts + n;
+ FT_UInt count, num_subrs = dict->num_subrs;
+ FT_ULong data_len;
+ FT_Byte* p;
+
+
+ /* reallocate offsets array if needed */
+ if ( num_subrs + 1 > max_offsets )
+ {
+ FT_UInt new_max = ( num_subrs + 1 + 3 ) & -4;
+
+
+ if ( REALLOC_ARRAY( offsets, max_offsets, new_max, FT_ULong ) )
+ goto Fail;
+
+ max_offsets = new_max;
+ }
+
+ /* read the subrmap's offsets */
+ if ( FILE_Seek( cid->data_offset + dict->subrmap_offset ) ||
+ ACCESS_Frame( ( num_subrs + 1 ) * dict->sd_bytes ) )
+ goto Fail;
+
+ p = (FT_Byte*)stream->cursor;
+ for ( count = 0; count <= num_subrs; count++ )
+ offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes );
+
+ FORGET_Frame();
+
+ /* now, compute the size of subrs charstrings, */
+ /* allocate, and read them */
+ data_len = offsets[num_subrs] - offsets[0];
+
+ if ( ALLOC_ARRAY( subr->code, num_subrs + 1, FT_Byte* ) ||
+ ALLOC( subr->code[0], data_len ) )
+ goto Fail;
+
+ if ( FILE_Seek( cid->data_offset + offsets[0] ) ||
+ FILE_Read( subr->code[0], data_len ) )
+ goto Exit;
+
+ /* set up pointers */
+ for ( count = 1; count <= num_subrs; count++ )
+ {
+ FT_UInt len;
+
+
+ len = offsets[count] - offsets[count - 1];
+ subr->code[count] = subr->code[count - 1] + len;
+ }
+
+ /* decrypt subroutines */
+ for ( count = 0; count < num_subrs; count++ )
+ {
+ FT_UInt len;
+
+
+ len = offsets[count + 1] - offsets[count];
+ cid_decrypt( subr->code[count], len, 4330 );
+ }
+
+ subr->num_subrs = num_subrs;
+ }
+
+ Exit:
+ FREE( offsets );
+ return error;
+
+ Fail:
+ if ( face->subrs )
+ {
+ for ( n = 0; n < cid->num_dicts; n++ )
+ {
+ if ( face->subrs[n].code )
+ FREE( face->subrs[n].code[0] );
+
+ FREE( face->subrs[n].code );
+ }
+ FREE( face->subrs );
+ }
+ goto Exit;
+ }
+
+
+ static
+ void t1_init_loader( CID_Loader* loader,
+ CID_Face face )
+ {
+ FT_UNUSED( face );
+
+ MEM_Set( loader, 0, sizeof ( *loader ) );
+ }
+
+
+ static
+ void t1_done_loader( CID_Loader* loader )
+ {
+ CID_Parser* parser = &loader->parser;
+
+
+ /* finalize parser */
+ CID_Done_Parser( parser );
+ }
+
+
+ LOCAL_FUNC
+ FT_Error CID_Open_Face( CID_Face face )
+ {
+ CID_Loader loader;
+ CID_Parser* parser;
+ FT_Error error;
+
+
+ t1_init_loader( &loader, face );
+
+ parser = &loader.parser;
+ error = CID_New_Parser( parser, face->root.stream, face->root.memory );
+ if ( error )
+ goto Exit;
+
+ error = parse_dict( face, &loader,
+ parser->postscript,
+ parser->postscript_len );
+ if ( error )
+ goto Exit;
+
+ face->cid.data_offset = loader.parser.data_offset;
+ error = cid_read_subrs( face );
+
+ Exit:
+ t1_done_loader( &loader );
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* cidload.h */
+/* */
+/* CID-keyed Type1 font loader (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef CIDLOAD_H
+#define CIDLOAD_H
+
+#include <freetype/internal/ftstream.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidparse.h"
+
+#else
+
+#include <cid/cidparse.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ typedef struct CID_Loader_
+ {
+ CID_Parser parser; /* parser used to read the stream */
+ FT_Int num_chars; /* number of characters in encoding */
+
+ } CID_Loader;
+
+
+ LOCAL_DEF
+ FT_Long cid_get_offset( FT_Byte** start,
+ FT_Byte offsize );
+
+ LOCAL_DEF
+ void cid_decrypt( FT_Byte* buffer,
+ FT_Int length,
+ FT_UShort seed );
+
+ LOCAL_DEF
+ FT_Error CID_Open_Face( CID_Face face );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* CIDLOAD_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* cidobjs.c */
+/* */
+/* CID objects manager (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidgload.h"
+#include "cidload.h"
+
+#else
+
+#include <cid/cidgload.h>
+#include <cid/cidload.h>
+
+#endif
+
+
+#include <freetype/internal/psnames.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cidobjs
+
+
+ /*************************************************************************/
+ /* */
+ /* FACE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* CID_Done_Face */
+ /* */
+ /* <Description> */
+ /* Finalizes a given face object. */
+ /* */
+ /* <Input> */
+ /* face :: A pointer to the face object to destroy. */
+ /* */
+ LOCAL_FUNC
+ void CID_Done_Face( CID_Face face )
+ {
+ FT_Memory memory;
+
+
+ if ( face )
+ {
+ CID_Info* cid = &face->cid;
+ T1_FontInfo* info = &cid->font_info;
+
+
+ memory = face->root.memory;
+
+ /* release FontInfo strings */
+ FREE( info->version );
+ FREE( info->notice );
+ FREE( info->full_name );
+ FREE( info->family_name );
+ FREE( info->weight );
+
+ /* release font dictionaries */
+ FREE( cid->font_dicts );
+ cid->num_dicts = 0;
+
+ /* release other strings */
+ FREE( cid->cid_font_name );
+ FREE( cid->registry );
+ FREE( cid->ordering );
+
+ face->root.family_name = 0;
+ face->root.style_name = 0;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* CID_Init_Face */
+ /* */
+ /* <Description> */
+ /* Initializes a given CID face object. */
+ /* */
+ /* <Input> */
+ /* stream :: The source font stream. */
+ /* */
+ /* face_index :: The index of the font face in the resource. */
+ /* */
+ /* num_params :: Number of additional generic parameters. Ignored. */
+ /* */
+ /* params :: Additional generic parameters. Ignored. */
+ /* */
+ /* <InOut> */
+ /* face :: The newly built face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error CID_Init_Face( FT_Stream stream,
+ CID_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error;
+ PSNames_Interface* psnames;
+
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+ FT_UNUSED( face_index );
+ FT_UNUSED( stream );
+
+
+ face->root.num_faces = 1;
+
+ psnames = (PSNames_Interface*)face->psnames;
+ if ( !psnames )
+ {
+ psnames = (PSNames_Interface*)FT_Get_Module_Interface(
+ FT_FACE_LIBRARY( face ), "psnames" );
+
+ face->psnames = psnames;
+ }
+
+ /* open the tokenizer; this will also check the font format */
+ if ( FILE_Seek( 0 ) )
+ goto Exit;
+
+ error = CID_Open_Face( face );
+ if ( error )
+ goto Exit;
+
+ /* if we just wanted to check the format, leave successfully now */
+ if ( face_index < 0 )
+ goto Exit;
+
+ /* check the face index */
+ if ( face_index != 0 )
+ {
+ FT_ERROR(( "CID_Init_Face: invalid face index\n" ));
+ error = T1_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* Now, load the font program into the face object */
+ {
+ /* Init the face object fields */
+ /* Now set up root face fields */
+ {
+ FT_Face root = (FT_Face)&face->root;
+
+
+ root->num_glyphs = face->cid.cid_count;
+ root->num_charmaps = 0;
+
+ root->face_index = face_index;
+ root->face_flags = FT_FACE_FLAG_SCALABLE;
+
+ root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
+
+ if ( face->cid.font_info.is_fixed_pitch )
+ root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ /* XXX: TODO: add kerning with .afm support */
+
+ /* get style name -- be careful, some broken fonts only */
+ /* have a /FontName dictionary entry! */
+ root->family_name = face->cid.font_info.family_name;
+ if ( root->family_name )
+ {
+ char* full = face->cid.font_info.full_name;
+ char* family = root->family_name;
+
+ while ( *family && *full == *family )
+ {
+ family++;
+ full++;
+ }
+
+ root->style_name = ( *full == ' ' ) ? full + 1
+ : (char *)"Regular";
+ }
+ else
+ {
+ /* do we have a `/FontName'? */
+ if ( face->cid.cid_font_name )
+ {
+ root->family_name = face->cid.cid_font_name;
+ root->style_name = "Regular";
+ }
+ }
+
+ /* no embedded bitmap support */
+ root->num_fixed_sizes = 0;
+ root->available_sizes = 0;
+
+ root->bbox = face->cid.font_bbox;
+ root->units_per_EM = 1000;
+ root->ascender = (FT_Short)face->cid.font_bbox.yMax;
+ root->descender = -(FT_Short)face->cid.font_bbox.yMin;
+ root->height = ( ( root->ascender + root->descender ) * 12 )
+ / 10;
+
+
+#if 0
+
+ /* now compute the maximum advance width */
+
+ root->max_advance_width = face->type1.private_dict.standard_width[0];
+
+ /* compute max advance width for proportional fonts */
+ if ( !face->type1.font_info.is_fixed_pitch )
+ {
+ FT_Int max_advance;
+
+
+ error = CID_Compute_Max_Advance( face, &max_advance );
+
+ /* in case of error, keep the standard width */
+ if ( !error )
+ root->max_advance_width = max_advance;
+ else
+ error = 0; /* clear error */
+ }
+
+ root->max_advance_height = root->height;
+
+#endif /* 0 */
+
+ root->underline_position = face->cid.font_info.underline_position;
+ root->underline_thickness = face->cid.font_info.underline_thickness;
+
+ root->max_points = 0;
+ root->max_contours = 0;
+ }
+ }
+
+#if 0
+
+ /* charmap support - synthetize unicode charmap when possible */
+ {
+ FT_Face root = &face->root;
+ FT_CharMap charmap = face->charmaprecs;
+
+
+ /* synthesize a Unicode charmap if there is support in the `psnames' */
+ /* module */
+ if ( face->psnames )
+ {
+ PSNames_Interface* psnames = (PSNames_Interface*)face->psnames;
+
+
+ if ( psnames->unicode_value )
+ {
+ error = psnames->build_unicodes(
+ root->memory,
+ face->type1.num_glyphs,
+ (const char**)face->type1.glyph_names,
+ &face->unicode_map );
+ if ( !error )
+ {
+ root->charmap = charmap;
+ charmap->face = (FT_Face)face;
+ charmap->encoding = ft_encoding_unicode;
+ charmap->platform_id = 3;
+ charmap->encoding_id = 1;
+ charmap++;
+ }
+
+ /* simply clear the error in case of failure (which really */
+ /* means that out of memory or no unicode glyph names) */
+ error = 0;
+ }
+ }
+
+ /* now, support either the standard, expert, or custom encodings */
+ charmap->face = (FT_Face)face;
+ charmap->platform_id = 7; /* a new platform id for Adobe fonts? */
+
+ switch ( face->type1.encoding_type )
+ {
+ case t1_encoding_standard:
+ charmap->encoding = ft_encoding_adobe_standard;
+ charmap->encoding_id = 0;
+ break;
+
+ case t1_encoding_expert:
+ charmap->encoding = ft_encoding_adobe_expert;
+ charmap->encoding_id = 1;
+ break;
+
+ default:
+ charmap->encoding = ft_encoding_adobe_custom;
+ charmap->encoding_id = 2;
+ break;
+ }
+
+ root->charmaps = face->charmaps;
+ root->num_charmaps = charmap - face->charmaprecs + 1;
+ face->charmaps[0] = &face->charmaprecs[0];
+ face->charmaps[1] = &face->charmaprecs[1];
+ }
+
+#endif /* 0 */
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* CID_Init_Driver */
+ /* */
+ /* <Description> */
+ /* Initializes a given CID driver object. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target driver object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error CID_Init_Driver( CID_Driver driver )
+ {
+ FT_UNUSED( driver );
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* CID_Done_Driver */
+ /* */
+ /* <Description> */
+ /* Finalizes a given CID driver. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target CID driver. */
+ /* */
+ LOCAL_DEF
+ void CID_Done_Driver( CID_Driver driver )
+ {
+ FT_UNUSED( driver );
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* cidobjs.h */
+/* */
+/* CID objects manager (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef CIDOBJS_H
+#define CIDOBJS_H
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/t1errors.h>
+#include <freetype/internal/t1types.h>
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /* The following structures must be defined by the hinter */
+ typedef struct CID_Size_Hints_ CID_Size_Hints;
+ typedef struct CID_Glyph_Hints_ CID_Glyph_Hints;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* CID_Driver */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 driver object. */
+ /* */
+ typedef struct CID_DriverRec_* CID_Driver;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* CID_Size */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 size object. */
+ /* */
+ typedef struct CID_SizeRec_* CID_Size;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* CID_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 glyph slot object. */
+ /* */
+ typedef struct CID_GlyphSlotRec_* CID_GlyphSlot;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* CID_CharMap */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 character mapping object. */
+ /* */
+ /* <Note> */
+ /* The Type 1 format doesn't use a charmap but an encoding table. */
+ /* The driver is responsible for making up charmap objects */
+ /* corresponding to these tables. */
+ /* */
+ typedef struct CID_CharMapRec_* CID_CharMap;
+
+
+ /*************************************************************************/
+ /* */
+ /* HERE BEGINS THE TYPE 1 SPECIFIC STUFF */
+ /* */
+ /*************************************************************************/
+
+
+ typedef struct CID_SizeRec_
+ {
+ FT_SizeRec root;
+ FT_Bool valid;
+
+ } CID_SizeRec;
+
+
+ typedef struct CID_GlyphSlotRec_
+ {
+ FT_GlyphSlotRec root;
+
+ FT_Bool hint;
+ FT_Bool scaled;
+
+ FT_Fixed x_scale;
+ FT_Fixed y_scale;
+
+ } CID_GlyphSlotRec;
+
+
+ LOCAL_DEF
+ FT_Error CID_Init_Face( FT_Stream stream,
+ CID_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+ LOCAL_DEF
+ void CID_Done_Face( CID_Face face );
+
+
+ LOCAL_DEF
+ FT_Error CID_Init_Driver( CID_Driver driver );
+
+ LOCAL_DEF
+ void CID_Done_Driver( CID_Driver driver );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* CIDOBJS_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* cidparse.c */
+/* */
+/* CID-keyed Type1 parser (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1errors.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidparse.h"
+
+#else
+
+#include <cid/cidparse.h>
+
+#endif
+
+
+#include <string.h> /* for strncmp() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cidparse
+
+
+#if 0
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** IMPLEMENTATION OF CID_TABLE OBJECT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* CID_New_Table */
+ /* */
+ /* <Description> */
+ /* Initializes a CID_Table. */
+ /* */
+ /* <InOut> */
+ /* table :: The address of the target table. */
+ /* */
+ /* <Input> */
+ /* count :: The table size, i.e., the maximal number of elements. */
+ /* */
+ /* memory :: The memory object to be used for all subsequent */
+ /* reallocations. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error CID_New_Table( CID_Table* table,
+ FT_Int count,
+ FT_Memory memory )
+ {
+ FT_Error error;
+
+
+ table->memory = memory;
+ if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) ||
+ ALLOC_ARRAY( table->lengths, count, FT_Byte* ) )
+ goto Exit;
+
+ table->max_elems = count;
+ table->init = 0xDEADBEEFL;
+ table->num_elems = 0;
+ table->block = 0;
+ table->capacity = 0;
+ table->cursor = 0;
+
+ Exit:
+ if ( error )
+ FREE( table->elements );
+
+ return error;
+ }
+
+
+ static
+ void shift_elements( CID_Table* table,
+ FT_Byte* old_base )
+ {
+ FT_Long delta = table->block - old_base;
+ FT_Byte** offset = table->elements;
+ FT_Byte** limit = offset + table->max_elems;
+
+
+ if ( delta )
+ for ( ; offset < limit; offset++ )
+ {
+ if ( offset[0] )
+ offset[0] += delta;
+ }
+ }
+
+
+ static
+ FT_Error reallocate_t1_table( CID_Table* table,
+ FT_Int new_size )
+ {
+ FT_Memory memory = table->memory;
+ FT_Byte* old_base = table->block;
+ FT_Error error;
+
+
+ /* realloc the base block */
+ if ( REALLOC( table->block, table->capacity, new_size ) )
+ return error;
+
+ table->capacity = new_size;
+
+ /* shift all offsets when needed */
+ if ( old_base )
+ shift_elements( table, old_base );
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* CID_Add_Table */
+ /* */
+ /* <Description> */
+ /* Adds an object to a CID_Table, possibly growing its memory block. */
+ /* */
+ /* <InOut> */
+ /* table :: The target table. */
+ /* */
+ /* <Input> */
+ /* index :: The index of the object in the table. */
+ /* */
+ /* object :: The address of the object to copy in the memory. */
+ /* */
+ /* length :: The length in bytes of the source object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. An error is returned if */
+ /* reallocation fails. */
+ /* */
+ LOCAL_FUNC
+ FT_Error CID_Add_Table( CID_Table* table,
+ FT_Int index,
+ void* object,
+ FT_Int length )
+ {
+ if ( index < 0 || index > table->max_elems )
+ {
+ FT_ERROR(( "CID_Add_Table: invalid index\n" ));
+ return T1_Err_Syntax_Error;
+ }
+
+ /* grow the base block if needed */
+ if ( table->cursor + length > table->capacity )
+ {
+ FT_Error error;
+ FT_Int new_size = table->capacity;
+
+
+ while ( new_size < table->cursor + length )
+ new_size += 1024;
+
+ error = reallocate_t1_table( table, new_size );
+ if ( error )
+ return error;
+ }
+
+ /* add the object to the base block and adjust offset */
+ table->elements[index] = table->block + table->cursor;
+ table->lengths [index] = length;
+
+ MEM_Copy( table->block + table->cursor, object, length );
+
+ table->cursor += length;
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* CID_Done_Table */
+ /* */
+ /* <Description> */
+ /* Finalizes a CID_Table (reallocate it to its current cursor). */
+ /* */
+ /* <InOut> */
+ /* table :: The target table. */
+ /* */
+ /* <Note> */
+ /* This function does NOT release the heap's memory block. It is up */
+ /* to the caller to clean it, or reference it in its own structures. */
+ /* */
+ LOCAL_FUNC
+ void CID_Done_Table( CID_Table* table )
+ {
+ FT_Memory memory = table->memory;
+ FT_Error error;
+ FT_Byte* old_base;
+
+
+ /* should never fail, as rec.cursor <= rec.size */
+ old_base = table->block;
+ if ( !old_base )
+ return;
+
+ (void)REALLOC( table->block, table->capacity, table->cursor );
+ table->capacity = table->cursor;
+
+ if ( old_base != table->block )
+ shift_elements( table, old_base );
+ }
+
+
+ LOCAL_FUNC
+ void CID_Release_Table( CID_Table* table )
+ {
+ FT_Memory memory = table->memory;
+
+
+ if ( table->init == 0xDEADBEEFL )
+ {
+ FREE( table->block );
+ FREE( table->elements );
+ FREE( table->lengths );
+ table->init = 0;
+ }
+ }
+
+#endif /* 0 */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** INPUT STREAM PARSER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#define IS_CID_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' )
+#define IS_CID_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' )
+
+#define IS_CID_SPACE( c ) ( IS_CID_WHITESPACE( c ) || IS_CID_LINESPACE( c ) )
+
+
+ LOCAL_FUNC
+ void CID_Skip_Spaces( CID_Parser* parser )
+ {
+ FT_Byte* cur = parser->cursor;
+ FT_Byte* limit = parser->limit;
+
+
+ while ( cur < limit )
+ {
+ FT_Byte c = *cur;
+
+
+ if ( !IS_CID_SPACE( c ) )
+ break;
+ cur++;
+ }
+
+ parser->cursor = cur;
+ }
+
+
+ LOCAL_FUNC
+ void CID_ToToken( CID_Parser* parser,
+ CID_Token_Rec* token )
+ {
+ FT_Byte* cur;
+ FT_Byte* limit;
+ FT_Byte starter, ender;
+ FT_Int embed;
+
+
+ token->type = t1_token_none;
+ token->start = 0;
+ token->limit = 0;
+
+ /* first of all, skip space */
+ CID_Skip_Spaces( parser );
+
+ cur = parser->cursor;
+ limit = parser->limit;
+
+ if ( cur < limit )
+ {
+ switch ( *cur )
+ {
+ /************* check for strings ***********************/
+ case '(':
+ token->type = t1_token_string;
+ ender = ')';
+ goto Lookup_Ender;
+
+ /************* check for programs/array ****************/
+ case '{':
+ token->type = t1_token_array;
+ ender = '}';
+ goto Lookup_Ender;
+
+ /************* check for table/array ******************/
+ case '[':
+ token->type = t1_token_array;
+ ender = ']';
+
+ Lookup_Ender:
+ embed = 1;
+ starter = *cur++;
+ token->start = cur;
+
+ while ( cur < limit )
+ {
+ if ( *cur == starter )
+ embed++;
+ else if ( *cur == ender )
+ {
+ embed--;
+ if ( embed <= 0 )
+ {
+ token->limit = cur++;
+ break;
+ }
+ }
+ cur++;
+ }
+ break;
+
+ /* **************** otherwise, it is any token **********/
+ default:
+ token->start = cur++;
+ token->type = t1_token_any;
+ while ( cur < limit && !IS_CID_SPACE( *cur ) )
+ cur++;
+
+ token->limit = cur;
+ }
+
+ if ( !token->limit )
+ {
+ token->start = 0;
+ token->type = t1_token_none;
+ }
+
+ parser->cursor = cur;
+ }
+ }
+
+
+ LOCAL_FUNC
+ void CID_ToTokenArray( CID_Parser* parser,
+ CID_Token_Rec* tokens,
+ FT_UInt max_tokens,
+ FT_Int* pnum_tokens )
+ {
+ CID_Token_Rec master;
+
+
+ *pnum_tokens = -1;
+
+ CID_ToToken( parser, &master );
+
+ if ( master.type == t1_token_array )
+ {
+ FT_Byte* old_cursor = parser->cursor;
+ FT_Byte* old_limit = parser->limit;
+ CID_Token_Rec* cur = tokens;
+ CID_Token_Rec* limit = cur + max_tokens;
+
+
+ parser->cursor = master.start;
+ parser->limit = master.limit;
+
+ while ( parser->cursor < parser->limit )
+ {
+ CID_Token_Rec token;
+
+
+ CID_ToToken( parser, &token );
+ if ( !token.type )
+ break;
+
+ if ( cur < limit )
+ *cur = token;
+
+ cur++;
+ }
+
+ *pnum_tokens = cur - tokens;
+
+ parser->cursor = old_cursor;
+ parser->limit = old_limit;
+ }
+ }
+
+
+ static
+ FT_Long t1_toint( FT_Byte** cursor,
+ FT_Byte* limit )
+ {
+ FT_Long result = 0;
+ FT_Byte* cur = *cursor;
+ FT_Byte c, d;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ c = *cur;
+ d = (FT_Byte)( c - '0' );
+ if ( d < 10 )
+ break;
+
+ if ( c == '-' )
+ {
+ cur++;
+ break;
+ }
+ }
+
+ if ( cur < limit )
+ {
+ do
+ {
+ d = (FT_Byte)( cur[0] - '0' );
+ if ( d >= 10 )
+ break;
+
+ result = result * 10 + d;
+ cur++;
+
+ } while ( cur < limit );
+
+ if ( c == '-' )
+ result = -result;
+ }
+
+ *cursor = cur;
+
+ return result;
+ }
+
+
+ static
+ FT_Long t1_tofixed( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Long power_ten )
+ {
+ FT_Byte* cur = *cursor;
+ FT_Long num, divider, result;
+ FT_Int sign = 0;
+ FT_Byte d;
+
+
+ if ( cur >= limit )
+ return 0;
+
+ /* first of all, read the integer part */
+ result = t1_toint( &cur, limit ) << 16;
+ num = 0;
+ divider = 1;
+
+ if ( result < 0 )
+ {
+ sign = 1;
+ result = -result;
+ }
+
+ if ( cur >= limit )
+ goto Exit;
+
+ /* read decimal part, if any */
+ if ( *cur == '.' && cur + 1 < limit )
+ {
+ cur++;
+
+ for (;;)
+ {
+ d = (FT_Byte)( *cur - '0' );
+ if ( d >= 10 )
+ break;
+
+ if ( divider < 10000000L )
+ {
+ num = num * 10 + d;
+ divider *= 10;
+ }
+
+ cur++;
+ if ( cur >= limit )
+ break;
+ }
+ }
+
+ /* read exponent, if any */
+ if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) )
+ {
+ cur++;
+ power_ten += t1_toint( &cur, limit );
+ }
+
+ Exit:
+ /* raise to power of ten if needed */
+ while ( power_ten > 0 )
+ {
+ result = result * 10;
+ num = num * 10;
+ power_ten--;
+ }
+
+ while ( power_ten < 0 )
+ {
+ result = result / 10;
+ divider = divider * 10;
+ power_ten++;
+ }
+
+ if ( num )
+ result += FT_DivFix( num, divider );
+
+ if ( sign )
+ result = -result;
+
+ *cursor = cur;
+
+ return result;
+ }
+
+
+ static
+ int t1_tobool( FT_Byte** cursor,
+ FT_Byte* limit )
+ {
+ FT_Byte* cur = *cursor;
+ FT_Bool result = 0;
+
+
+ /* return 1 if we find a "true", 0 otherwise */
+ if ( cur + 3 < limit &&
+ cur[0] == 't' &&
+ cur[1] == 'r' &&
+ cur[2] == 'u' &&
+ cur[3] == 'e' )
+ {
+ result = 1;
+ cur += 5;
+ }
+ else if ( cur + 4 < limit &&
+ cur[0] == 'f' &&
+ cur[1] == 'a' &&
+ cur[2] == 'l' &&
+ cur[3] == 's' &&
+ cur[4] == 'e' )
+ {
+ result = 0;
+ cur += 6;
+ }
+ *cursor = cur;
+ return result;
+ }
+
+
+ static
+ FT_Int t1_tocoordarray( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Int max_coords,
+ FT_Short* coords )
+ {
+ FT_Byte* cur = *cursor;
+ FT_Int count = 0;
+ FT_Byte c, ender;
+
+
+ if ( cur >= limit )
+ goto Exit;
+
+ /* check for the beginning of an array. */
+ /* If not, only one number will be read */
+ c = *cur;
+ ender = 0;
+
+ if ( c == '[' )
+ ender = ']';
+
+ if ( c == '{' )
+ ender = '}';
+
+ if ( ender )
+ cur++;
+
+ /* now, read the coordinates */
+ for ( ; cur < limit; )
+ {
+ /* skip whitespace in front of data */
+ for (;;)
+ {
+ c = *cur;
+ if ( c != ' ' && c != '\t' )
+ break;
+
+ cur++;
+ if ( cur >= limit )
+ goto Exit;
+ }
+
+ if ( count >= max_coords || c == ender )
+ break;
+
+ coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 );
+ count++;
+
+ if ( !ender )
+ break;
+ }
+
+ Exit:
+ *cursor = cur;
+ return count;
+ }
+
+
+ static
+ FT_Int t1_tofixedarray( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Int max_values,
+ FT_Fixed* values,
+ FT_Int power_ten )
+ {
+ FT_Byte* cur = *cursor;
+ FT_Int count = 0;
+ FT_Byte c, ender;
+
+
+ if ( cur >= limit )
+ goto Exit;
+
+ /* check for the beginning of an array. */
+ /* If not, only one number will be read */
+ c = *cur;
+ ender = 0;
+
+ if ( c == '[' )
+ ender = ']';
+
+ if ( c == '{' )
+ ender = '}';
+
+ if ( ender )
+ cur++;
+
+ /* now, read the values */
+ for ( ; cur < limit; )
+ {
+ /* skip whitespace in front of data */
+ for (;;)
+ {
+ c = *cur;
+ if ( c != ' ' && c != '\t' )
+ break;
+
+ cur++;
+ if ( cur >= limit )
+ goto Exit;
+ }
+
+ if ( count >= max_values || c == ender )
+ break;
+
+ values[count] = t1_tofixed( &cur, limit, power_ten );
+ count++;
+
+ if ( !ender )
+ break;
+ }
+
+ Exit:
+ *cursor = cur;
+
+ return count;
+ }
+
+
+ /* Loads a simple field (i.e. non-table) into the current */
+ /* list of objects */
+ LOCAL_FUNC
+ FT_Error CID_Load_Field( CID_Parser* parser,
+ const CID_Field_Rec* field,
+ void* object )
+ {
+ CID_Token_Rec token;
+ FT_Byte* cur;
+ FT_Byte* limit;
+ FT_UInt count;
+ FT_UInt index;
+ FT_Error error;
+
+
+ CID_ToToken( parser, &token );
+ if ( !token.type )
+ goto Fail;
+
+ count = 1;
+ index = 0;
+ cur = token.start;
+ limit = token.limit;
+
+ {
+ FT_Byte* q = (FT_Byte*)object + field->offset;
+ FT_Long val;
+ FT_String* string;
+
+
+ switch ( field->type )
+ {
+ case t1_field_bool:
+ val = t1_tobool( &cur, limit );
+ goto Store_Integer;
+
+ case t1_field_fixed:
+ val = t1_tofixed( &cur, limit, 0 );
+ goto Store_Integer;
+
+ case t1_field_integer:
+ val = t1_toint( &cur, limit );
+
+ Store_Integer:
+ switch ( field->size )
+ {
+ case 1:
+ *(FT_Byte*)q = (FT_Byte)val;
+ break;
+
+ case 2:
+ *(FT_UShort*)q = (FT_UShort)val;
+ break;
+
+ case 4:
+ *(FT_Int32*)q = (FT_Int)val;
+ break;
+
+ default: /* for 64-bit systems */
+ *(FT_Long*)q = val;
+ }
+ break;
+
+ case t1_field_string:
+ {
+ FT_Memory memory = parser->memory;
+ FT_UInt len = limit-cur;
+
+
+ if ( ALLOC( string, len + 1 ) )
+ goto Exit;
+
+ MEM_Copy( string, cur, len );
+ string[len] = 0;
+
+ *(FT_String**)q = string;
+ }
+ break;
+
+ default:
+ /* an error occurred */
+ goto Fail;
+ }
+ }
+
+ error = 0;
+
+ Exit:
+ return error;
+
+ Fail:
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+
+#define T1_MAX_TABLE_ELEMENTS 32
+
+
+ LOCAL_FUNC
+ FT_Error CID_Load_Field_Table( CID_Parser* parser,
+ const CID_Field_Rec* field,
+ void* object )
+ {
+ CID_Token_Rec elements[T1_MAX_TABLE_ELEMENTS];
+ CID_Token_Rec* token;
+ FT_Int num_elements;
+ FT_Error error = 0;
+ FT_Byte* old_cursor;
+ FT_Byte* old_limit;
+ CID_Field_Rec fieldrec = *(CID_Field_Rec*)field;
+
+
+ fieldrec.type = t1_field_integer;
+ if ( field->type == t1_field_fixed_array )
+ fieldrec.type = t1_field_fixed;
+
+ CID_ToTokenArray( parser, elements, 32, &num_elements );
+ if ( num_elements < 0 )
+ goto Fail;
+
+ if ( num_elements > T1_MAX_TABLE_ELEMENTS )
+ num_elements = T1_MAX_TABLE_ELEMENTS;
+
+ old_cursor = parser->cursor;
+ old_limit = parser->limit;
+
+ /* we store the elements count */
+ if ( field->count_offset )
+ *(FT_Byte*)( (FT_Byte*)object + field->count_offset ) = num_elements;
+
+ /* we now load each element, adjusting the field.offset on each one */
+ token = elements;
+ for ( ; num_elements > 0; num_elements--, token++ )
+ {
+ parser->cursor = token->start;
+ parser->limit = token->limit;
+ CID_Load_Field( parser, &fieldrec, object );
+ fieldrec.offset += fieldrec.size;
+ }
+
+ parser->cursor = old_cursor;
+ parser->limit = old_limit;
+
+ Exit:
+ return error;
+
+ Fail:
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+
+ LOCAL_FUNC
+ FT_Long CID_ToInt( CID_Parser* parser )
+ {
+ return t1_toint( &parser->cursor, parser->limit );
+ }
+
+
+ LOCAL_FUNC
+ FT_Int CID_ToCoordArray( CID_Parser* parser,
+ FT_Int max_coords,
+ FT_Short* coords )
+ {
+ return t1_tocoordarray( &parser->cursor, parser->limit,
+ max_coords, coords );
+ }
+
+
+ LOCAL_FUNC
+ FT_Int CID_ToFixedArray( CID_Parser* parser,
+ FT_Int max_values,
+ FT_Fixed* values,
+ FT_Int power_ten )
+ {
+ return t1_tofixedarray( &parser->cursor, parser->limit,
+ max_values, values, power_ten );
+ }
+
+
+#if 0
+
+ /* return the value of an hexadecimal digit */
+ static
+ int hexa_value( char c )
+ {
+ unsigned int d;
+
+
+ d = (unsigned int)( c - '0' );
+ if ( d <= 9 )
+ return (int)d;
+
+ d = (unsigned int)( c - 'a' );
+ if ( d <= 5 )
+ return (int)( d + 10 );
+
+ d = (unsigned int)( c - 'A' );
+ if ( d <= 5 )
+ return (int)( d + 10 );
+
+ return -1;
+ }
+
+#endif /* 0 */
+
+
+ LOCAL_FUNC
+ FT_Error CID_New_Parser( CID_Parser* parser,
+ FT_Stream stream,
+ FT_Memory memory )
+ {
+ FT_Error error;
+ FT_ULong base_offset, offset, ps_len;
+ FT_Byte buffer[256 + 10];
+ FT_Int buff_len;
+
+
+ MEM_Set( parser, 0, sizeof ( *parser ) );
+ parser->stream = stream;
+ parser->memory = memory;
+
+ base_offset = FILE_Pos();
+
+ /* first of all, check the font format in the header */
+ if ( ACCESS_Frame( 31 ) )
+ goto Exit;
+
+ if ( strncmp( (char *)stream->cursor,
+ "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )
+ {
+ FT_TRACE2(( "[not a valid CID-keyed font]\n" ));
+ error = FT_Err_Unknown_File_Format;
+ }
+
+ FORGET_Frame();
+ if ( error )
+ goto Exit;
+
+ /* now, read the rest of the file, until we find a `StartData' */
+ buff_len = 256;
+ for (;;)
+ {
+ FT_Byte *p, *limit = buffer + 256;
+
+ /* fill input buffer */
+ buff_len -= 256;
+ if ( buff_len > 0 )
+ MEM_Move( buffer, limit, buff_len );
+
+ if ( FILE_Read( buffer, 256 + 10 - buff_len ) )
+ goto Exit;
+
+ buff_len = 256 + 10;
+
+ /* look for `StartData' */
+ for ( p = buffer; p < limit; p++ )
+ {
+ if ( p[0] == 'S' && strncmp( (char*)p, "StartData", 9 ) == 0 )
+ {
+ /* save offset of binary data after `StartData' */
+ offset = FILE_Pos() - ( limit - p ) + 10;
+ goto Found;
+ }
+ }
+ }
+
+ Found:
+ /* we have found the start of the binary data. We will now */
+ /* rewind and extract the frame of corresponding to the Postscript */
+ /* section */
+
+ ps_len = offset - base_offset;
+ if ( FILE_Seek( base_offset ) ||
+ EXTRACT_Frame( ps_len, parser->postscript ) )
+ goto Exit;
+
+ parser->data_offset = offset;
+ parser->postscript_len = ps_len;
+ parser->cursor = parser->postscript;
+ parser->limit = parser->cursor + ps_len;
+ parser->num_dict = -1;
+
+ Exit:
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ void CID_Done_Parser( CID_Parser* parser )
+ {
+ /* always free the private dictionary */
+ if ( parser->postscript )
+ {
+ FT_Stream stream = parser->stream;
+
+
+ RELEASE_Frame( parser->postscript );
+ }
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* cidparse.h */
+/* */
+/* CID-keyed Type1 parser (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef CIDPARSE_H
+#define CIDPARSE_H
+
+#include <freetype/internal/t1types.h>
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+#if 0
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* CID_Table */
+ /* */
+ /* <Description> */
+ /* A CID_Table is a simple object used to store an array of objects */
+ /* in a single memory block. */
+ /* */
+ /* <Fields> */
+ /* block :: The address in memory of the growheap's block. This */
+ /* can change between two object adds, due to the use */
+ /* of `realloc()'. */
+ /* */
+ /* cursor :: The current top of the growheap within its block. */
+ /* */
+ /* capacity :: The current size of the heap block. Increments by */
+ /* blocks of 1 kByte. */
+ /* */
+ /* init :: A boolean. Set when the table has been initialized */
+ /* (the table user should set this field). */
+ /* */
+ /* max_elems :: The maximal number of elements in the table. */
+ /* */
+ /* num_elems :: The current number of elements (in use) in the table. */
+ /* */
+ /* elements :: A table of element addresses within the block. */
+ /* */
+ /* lengths :: A table of element sizes within the block. */
+ /* */
+ /* memory :: The memory object used for memory operations */
+ /* (allocation resp. reallocation). */
+ /* */
+ typedef struct CID_Table_
+ {
+ FT_Byte* block; /* current memory block */
+ FT_Int cursor; /* current cursor in memory block */
+ FT_Int capacity; /* current size of memory block */
+ FT_Long init;
+
+ FT_Int max_elems;
+ FT_Int num_elems;
+ FT_Byte** elements; /* addresses of table elements */
+ FT_Int* lengths; /* lengths of table elements */
+
+ FT_Memory memory;
+
+ } CID_Table;
+
+
+ LOCAL_DEF
+ FT_Error CID_New_Table( CID_Table* table,
+ FT_Int count,
+ CID_Memory memory );
+
+ LOCAL_DEF
+ FT_Error CID_Add_Table( CID_Table* table,
+ FT_Int index,
+ void* object,
+ FT_Int length );
+
+ LOCAL_DEF
+ void CID_Release_Table( CID_Table* table );
+
+#endif /* 0 */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* CID_Parser */
+ /* */
+ /* <Description> */
+ /* A CID_Parser is an object used to parse a Type 1 fonts very */
+ /* quickly. */
+ /* */
+ /* <Fields> */
+ /* stream :: The current input stream. */
+ /* */
+ /* memory :: The current memory object. */
+ /* */
+ /* postscript :: A pointer to the data to be parsed. */
+ /* */
+ /* postscript_len :: The length of the data to be parsed. */
+ /* */
+ /* data_offset :: The start position of the binary data (i.e., the */
+ /* end of the data to be parsed. */
+ /* */
+ /* cursor :: The current parser cursor. */
+ /* */
+ /* limit :: The current parser limit (i.e., the first byte */
+ /* after the current dictionary). */
+ /* */
+ /* error :: The current parsing error. */
+ /* */
+ /* cid :: A structure which holds the information about */
+ /* the current font. */
+ /* */
+ /* num_dict :: The number of font dictionaries. */
+ /* */
+ typedef struct CID_Parser_
+ {
+ FT_Stream stream;
+ FT_Memory memory;
+
+ FT_Byte* postscript;
+ FT_Int postscript_len;
+
+ FT_ULong data_offset;
+
+ FT_Byte* cursor;
+ FT_Byte* limit;
+ FT_Error error;
+
+ CID_Info* cid;
+ FT_Int num_dict;
+
+ } CID_Parser;
+
+
+ LOCAL_DEF
+ FT_Error CID_New_Parser( CID_Parser* parser,
+ FT_Stream stream,
+ FT_Memory memory );
+
+ LOCAL_DEF
+ void CID_Done_Parser( CID_Parser* parser );
+
+
+ /*************************************************************************/
+ /* */
+ /* PARSING ROUTINES */
+ /* */
+ /*************************************************************************/
+
+ LOCAL_DEF
+ FT_Long CID_ToInt( CID_Parser* parser );
+
+ LOCAL_DEF
+ FT_Int CID_ToCoordArray( CID_Parser* parser,
+ FT_Int max_coords,
+ FT_Short* coords );
+
+ LOCAL_DEF
+ FT_Int CID_ToFixedArray( CID_Parser* parser,
+ FT_Int max_values,
+ FT_Fixed* values,
+ FT_Int power_ten );
+
+ LOCAL_DEF
+ void CID_Skip_Spaces( CID_Parser* parser );
+
+
+ /* simple enumeration type used to identify token types */
+ typedef enum CID_Token_Type_
+ {
+ t1_token_none = 0,
+ t1_token_any,
+ t1_token_string,
+ t1_token_array,
+
+ /* do not remove */
+ t1_token_max
+
+ } CID_Token_Type;
+
+
+ /* a simple structure used to identify tokens */
+ typedef struct CID_Token_Rec_
+ {
+ FT_Byte* start; /* first character of token in input stream */
+ FT_Byte* limit; /* first character after the token */
+ CID_Token_Type type; /* type of token */
+
+ } CID_Token_Rec;
+
+
+ LOCAL_DEF
+ void CID_ToToken( CID_Parser* parser,
+ CID_Token_Rec* token );
+
+
+ /* enumeration type used to identify object fields */
+ typedef enum CID_Field_Type_
+ {
+ t1_field_none = 0,
+ t1_field_bool,
+ t1_field_integer,
+ t1_field_fixed,
+ t1_field_string,
+ t1_field_integer_array,
+ t1_field_fixed_array,
+ t1_field_callback,
+
+ /* do not remove */
+ t1_field_max
+
+ } CID_Field_Type;
+
+ typedef enum CID_Field_Location_
+ {
+ t1_field_cid_info,
+ t1_field_font_dict,
+ t1_field_font_info,
+ t1_field_private,
+
+ /* do not remove */
+ t1_field_location_max
+
+ } CID_Field_Location;
+
+
+ typedef FT_Error (*CID_Field_Parser)( CID_Face face,
+ CID_Parser* parser );
+
+ /* structure type used to model object fields */
+ typedef struct CID_Field_Rec_
+ {
+ const char* ident; /* field identifier */
+ CID_Field_Location location;
+ CID_Field_Type type; /* type of field */
+ CID_Field_Parser reader;
+ FT_UInt offset; /* offset of field in object */
+ FT_UInt size; /* size of field in bytes */
+ FT_UInt array_max; /* maximal number of elements for */
+ /* array */
+ FT_UInt count_offset; /* offset of element count for */
+ /* arrays */
+ } CID_Field_Rec;
+
+
+#define CID_FIELD_REF( s, f ) ( ((s*)0)->f )
+
+#define CID_NEW_SIMPLE_FIELD( _ident, _type, _fname ) \
+ { \
+ _ident, T1CODE, _type, \
+ 0, \
+ (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, _fname ), \
+ sizeof ( CID_FIELD_REF( T1TYPE, _fname ) ), \
+ 0, 0 \
+ },
+
+#define CID_NEW_CALLBACK_FIELD( _ident, _reader ) \
+ { \
+ _ident, T1CODE, t1_field_callback, \
+ _reader, \
+ 0, 0, \
+ 0, 0 \
+ },
+
+#define CID_NEW_TABLE_FIELD( _ident, _type, _fname, _max ) \
+ { \
+ _ident, T1CODE, _type, \
+ 0, \
+ (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, _fname ), \
+ sizeof ( CID_FIELD_REF( T1TYPE, _fname )[0] ), \
+ _max, \
+ (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, num_ ## _fname ) \
+ },
+
+#define CID_NEW_TABLE_FIELD2( _ident, _type, _fname, _max ) \
+ { \
+ _ident, T1CODE, _type, \
+ 0, \
+ (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, _fname ), \
+ sizeof ( CID_FIELD_REF( T1TYPE, _fname )[0] ), \
+ _max, 0 \
+ },
+
+
+#define CID_FIELD_BOOL( _ident, _fname ) \
+ CID_NEW_SIMPLE_FIELD( _ident, t1_field_bool, _fname )
+
+#define CID_FIELD_NUM( _ident, _fname ) \
+ CID_NEW_SIMPLE_FIELD( _ident, t1_field_integer, _fname )
+
+#define CID_FIELD_FIXED( _ident, _fname ) \
+ CID_NEW_SIMPLE_FIELD( _ident, t1_field_fixed, _fname )
+
+#define CID_FIELD_STRING( _ident, _fname ) \
+ CID_NEW_SIMPLE_FIELD( _ident, t1_field_string, _fname )
+
+#define CID_FIELD_NUM_TABLE( _ident, _fname, _fmax ) \
+ CID_NEW_TABLE_FIELD( _ident, t1_field_integer_array, \
+ _fname, _fmax )
+
+#define CID_FIELD_FIXED_TABLE( _ident, _fname, _fmax ) \
+ CID_NEW_TABLE_FIELD( _ident, t1_field_fixed_array, \
+ _fname, _fmax )
+
+#define CID_FIELD_NUM_TABLE2( _ident, _fname, _fmax ) \
+ CID_NEW_TABLE_FIELD2( _ident, t1_field_integer_array, \
+ _fname, _fmax )
+
+#define CID_FIELD_FIXED_TABLE2( _ident, _fname, _fmax ) \
+ CID_NEW_TABLE_FIELD2( _ident, t1_field_fixed_array, \
+ _fname, _fmax )
+
+#define CID_FIELD_CALLBACK( _ident, _name ) \
+ CID_NEW_CALLBACK_FIELD( _ident, parse_ ## _name )
+
+
+ LOCAL_DEF
+ FT_Error CID_Load_Field( CID_Parser* parser,
+ const CID_Field_Rec* field,
+ void* object );
+
+ LOCAL_DEF
+ FT_Error CID_Load_Field_Table( CID_Parser* parser,
+ const CID_Field_Rec* field,
+ void* object );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* CIDPARSE_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* cidriver.c */
+/* */
+/* CID driver interface (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidriver.h"
+#include "cidgload.h"
+
+#else
+
+#include <cid/cidriver.h>
+#include <cid/cidgload.h>
+
+#endif
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/psnames.h>
+
+#include <string.h> /* for strcmp() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ciddriver
+
+
+ static
+ FT_Module_Interface CID_Get_Interface( FT_Driver driver,
+ const FT_String* interface )
+ {
+ FT_UNUSED( driver );
+ FT_UNUSED( interface );
+
+ return 0;
+ }
+
+
+#if 0 /* unimplemented yet */
+
+ static
+ FT_Error cid_Get_Kerning( T1_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_Vector* kerning )
+ {
+ CID_AFM* afm;
+
+
+ kerning->x = 0;
+ kerning->y = 0;
+
+ afm = (CID_AFM*)face->afm_data;
+ if ( afm )
+ CID_Get_Kerning( afm, left_glyph, right_glyph, kerning );
+
+ return T1_Err_Ok;
+ }
+
+
+#endif /* 0 */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Cid_Get_Char_Index */
+ /* */
+ /* <Description> */
+ /* Uses a charmap to return a given character code's glyph index. */
+ /* */
+ /* <Input> */
+ /* charmap :: A handle to the source charmap object. */
+ /* */
+ /* charcode :: The character code. */
+ /* */
+ /* <Return> */
+ /* Glyph index. 0 means `undefined character code'. */
+ /* */
+ static
+ FT_UInt CID_Get_Char_Index( FT_CharMap charmap,
+ FT_Long charcode )
+ {
+ T1_Face face;
+ FT_UInt result = 0;
+ PSNames_Interface* psnames;
+
+
+ face = (T1_Face)charmap->face;
+ psnames = (PSNames_Interface*)face->psnames;
+ if ( psnames )
+ switch ( charmap->encoding )
+ {
+ /*******************************************************************/
+ /* */
+ /* Unicode encoding support */
+ /* */
+ case ft_encoding_unicode:
+ /* use the `PSNames' module to synthetize the Unicode charmap */
+ result = psnames->lookup_unicode( &face->unicode_map,
+ (FT_ULong)charcode );
+
+ /* the function returns 0xFFFF if the Unicode charcode has */
+ /* no corresponding glyph. */
+ if ( result == 0xFFFF )
+ result = 0;
+ goto Exit;
+
+ /*******************************************************************/
+ /* */
+ /* Custom Type 1 encoding */
+ /* */
+ case ft_encoding_adobe_custom:
+ {
+ T1_Encoding* encoding = &face->type1.encoding;
+
+
+ if ( charcode >= encoding->code_first &&
+ charcode <= encoding->code_last )
+ result = encoding->char_index[charcode];
+ goto Exit;
+ }
+
+ /*******************************************************************/
+ /* */
+ /* Adobe Standard & Expert encoding support */
+ /* */
+ default:
+ if ( charcode < 256 )
+ {
+ FT_UInt code;
+ FT_Int n;
+ const char* glyph_name;
+
+
+ code = psnames->adobe_std_encoding[charcode];
+ if ( charmap->encoding == ft_encoding_adobe_expert )
+ code = psnames->adobe_expert_encoding[charcode];
+
+ glyph_name = psnames->adobe_std_strings( code );
+ if ( !glyph_name )
+ break;
+
+ for ( n = 0; n < face->type1.num_glyphs; n++ )
+ {
+ const char* gname = face->type1.glyph_names[n];
+
+
+ if ( gname && gname[0] == glyph_name[0] &&
+ strcmp( gname, glyph_name ) == 0 )
+ {
+ result = n;
+ break;
+ }
+ }
+ }
+ }
+
+ Exit:
+ return result;
+ }
+
+
+ const FT_Driver_Class t1cid_driver_class =
+ {
+ /* first of all, the FT_Module_Class fields */
+ {
+ ft_module_font_driver | ft_module_driver_scalable,
+ sizeof( FT_DriverRec ),
+ "t1cid", /* module name */
+ 0x10000L, /* version 1.0 of driver */
+ 0x20000L, /* requires FreeType 2.0 */
+
+ 0,
+
+ (FT_Module_Constructor)CID_Init_Driver,
+ (FT_Module_Destructor) CID_Done_Driver,
+ (FT_Module_Requester) CID_Get_Interface
+ },
+
+ /* then the other font drivers fields */
+ sizeof( CID_FaceRec ),
+ sizeof( CID_SizeRec ),
+ sizeof( CID_GlyphSlotRec ),
+
+ (FTDriver_initFace) CID_Init_Face,
+ (FTDriver_doneFace) CID_Done_Face,
+
+ (FTDriver_initSize) 0,
+ (FTDriver_doneSize) 0,
+ (FTDriver_initGlyphSlot)0,
+ (FTDriver_doneGlyphSlot)0,
+
+ (FTDriver_setCharSizes) 0,
+ (FTDriver_setPixelSizes)0,
+
+ (FTDriver_loadGlyph) CID_Load_Glyph,
+ (FTDriver_getCharIndex) CID_Get_Char_Index,
+
+ (FTDriver_getKerning) 0,
+ (FTDriver_attachFile) 0,
+
+ (FTDriver_getAdvances) 0
+ };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* getDriverClass */
+ /* */
+ /* <Description> */
+ /* This function is used when compiling the TrueType driver as a */
+ /* shared library (`.DLL' or `.so'). It will be used by the */
+ /* high-level library of FreeType to retrieve the address of the */
+ /* driver's generic interface. */
+ /* */
+ /* It shouldn't be implemented in a static build, as each driver must */
+ /* have the same function as an exported entry point. */
+ /* */
+ /* <Return> */
+ /* The address of the TrueType's driver generic interface. The */
+ /* format-specific interface can then be retrieved through the method */
+ /* interface->get_format_interface. */
+ /* */
+ EXPORT_FUNC( FT_Driver_Class* ) getDriverClass( void )
+ {
+ return &t1cid_driver_class;
+ }
+
+
+#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* cidriver.h */
+/* */
+/* High-level CID driver interface (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef CIDRIVER_H
+#define CIDRIVER_H
+
+#include <freetype/internal/ftdriver.h>
+
+ FT_EXPORT_VAR( const FT_Driver_Class ) t1cid_driver_class;
+
+#endif /* CIDRIVER_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* cidtokens.h */
+/* */
+/* CID token definitions (specification only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#undef T1TYPE
+#undef T1CODE
+#define T1TYPE CID_Info
+#define T1CODE t1_field_cid_info
+
+ CID_FIELD_STRING ( "CIDFontName", cid_font_name )
+ CID_FIELD_NUM ( "CIDFontVersion", cid_version )
+ CID_FIELD_NUM ( "CIDFontType", cid_font_type )
+ CID_FIELD_STRING ( "Registry", registry )
+ CID_FIELD_STRING ( "Ordering", ordering )
+ CID_FIELD_NUM ( "Supplement", supplement )
+ CID_FIELD_CALLBACK( "FontBBox", font_bbox )
+ CID_FIELD_NUM ( "UIDBase", uid_base )
+ CID_FIELD_CALLBACK( "FDArray", fd_array )
+ CID_FIELD_NUM ( "CIDMapOffset", cidmap_offset )
+ CID_FIELD_NUM ( "FDBytes", fd_bytes )
+ CID_FIELD_NUM ( "GDBytes", gd_bytes )
+ CID_FIELD_NUM ( "CIDCount", cid_count )
+
+
+#undef T1TYPE
+#undef T1CODE
+#define T1TYPE T1_FontInfo
+#define T1CODE t1_field_font_info
+
+ CID_FIELD_STRING( "version", version )
+ CID_FIELD_STRING( "Notice", notice )
+ CID_FIELD_STRING( "FullName", full_name )
+ CID_FIELD_STRING( "FamilyName", family_name )
+ CID_FIELD_STRING( "Weight", weight )
+ CID_FIELD_FIXED ( "ItalicAngle", italic_angle )
+ CID_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch )
+ CID_FIELD_NUM ( "UnderlinePosition", underline_position )
+ CID_FIELD_NUM ( "UnderlineThickness", underline_thickness )
+
+
+#undef T1TYPE
+#undef T1CODE
+#define T1TYPE CID_FontDict
+#define T1CODE t1_field_font_dict
+
+ CID_FIELD_CALLBACK( "FontMatrix", font_matrix )
+ CID_FIELD_NUM ( "PaintType", paint_type )
+ CID_FIELD_NUM ( "FontType", font_type )
+ CID_FIELD_NUM ( "SubrMapOffset", subrmap_offset )
+ CID_FIELD_NUM ( "SDBytes", sd_bytes )
+ CID_FIELD_NUM ( "SubrCount", num_subrs )
+ CID_FIELD_NUM ( "lenBuildCharArray", len_buildchar )
+ CID_FIELD_FIXED ( "ForceBoldThreshold", forcebold_threshold )
+ CID_FIELD_FIXED ( "ExpansionFactor", expansion_factor )
+ CID_FIELD_NUM ( "StrokeWidth", stroke_width )
+
+
+#undef T1TYPE
+#undef T1CODE
+#define T1TYPE T1_Private
+#define T1CODE t1_field_private
+
+ CID_FIELD_NUM ( "UniqueID", unique_id )
+ CID_FIELD_NUM ( "lenIV", lenIV )
+ CID_FIELD_NUM ( "LanguageGroup", language_group )
+ CID_FIELD_NUM ( "password", password )
+
+ CID_FIELD_FIXED ( "BlueScale", blue_scale )
+ CID_FIELD_NUM ( "BlueShift", blue_shift )
+ CID_FIELD_NUM ( "BlueFuzz", blue_fuzz )
+
+ CID_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14 )
+ CID_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10 )
+ CID_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14 )
+ CID_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10 )
+
+ CID_FIELD_NUM_TABLE2( "StdHW", standard_width, 1 )
+ CID_FIELD_NUM_TABLE2( "StdVW", standard_height, 1 )
+ CID_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2 )
+
+ CID_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12 )
+ CID_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12 )
+
+
+/* END */
--- /dev/null
+make_module_list: add_type1cid_driver
+
+add_type1cid_driver:
+ $(OPEN_DRIVER)t1cid_driver_class$(CLOSE_DRIVER)
+ $(ECHO_DRIVER)cid $(ECHO_DRIVER_DESC)Postscript CID-keyed fonts, no known extension$(ECHO_DRIVER_DONE)
+# EOF
--- /dev/null
+#
+# FreeType 2 CID driver configuration rules
+#
+
+
+# Copyright 1996-2000 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# CID driver directory
+#
+CID_DIR := $(SRC_)cid
+CID_DIR_ := $(CID_DIR)$(SEP)
+
+
+CID_COMPILE := $(FT_COMPILE)
+
+
+# CID driver sources (i.e., C files)
+#
+CID_DRV_SRC := $(CID_DIR_)cidparse.c \
+ $(CID_DIR_)cidload.c \
+ $(CID_DIR_)cidriver.c \
+ $(CID_DIR_)cidgload.c \
+ $(CID_DIR_)cidobjs.c
+
+# CID driver headers
+#
+CID_DRV_H := $(CID_DRV_SRC:%.c=%.h) \
+ $(CID_DIR_)cidtokens.h
+
+
+# CID driver object(s)
+#
+# CID_DRV_OBJ_M is used during `multi' builds
+# CID_DRV_OBJ_S is used during `single' builds
+#
+CID_DRV_OBJ_M := $(CID_DRV_SRC:$(CID_DIR_)%.c=$(OBJ_)%.$O)
+CID_DRV_OBJ_S := $(OBJ_)type1cid.$O
+
+# CID driver source file for single build
+#
+CID_DRV_SRC_S := $(CID_DIR_)type1cid.c
+
+
+# CID driver - single object
+#
+$(CID_DRV_OBJ_S): $(CID_DRV_SRC_S) $(CID_DRV_SRC) $(FREETYPE_H) $(CID_DRV_H)
+ $(CID_COMPILE) $T$@ $(CID_DRV_SRC_S)
+
+
+# CID driver - multiple objects
+#
+$(OBJ_)%.$O: $(CID_DIR_)%.c $(FREETYPE_H) $(CID_DRV_H)
+ $(CID_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(CID_DRV_OBJ_S)
+DRV_OBJS_M += $(CID_DRV_OBJ_M)
+
+# EOF
--- /dev/null
+/***************************************************************************/
+/* */
+/* cff.c */
+/* */
+/* FreeType OpenType driver component (body only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidparse.c"
+#include "cidload.c"
+#include "cidobjs.c"
+#include "cidriver.c"
+#include "cidgload.c"
+
+#else
+
+#include <cid/cidparse.c>
+#include <cid/cidload.c>
+#include <cid/cidobjs.c>
+#include <cid/cidriver.c>
+#include <cid/cidgload.c>
+
+#endif
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftconfig.h */
+/* */
+/* ANSI-specific configuration file (specification only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This header file contains a number of macro definitions that are used */
+ /* by the rest of the engine. Most of the macros here are automatically */
+ /* determined at compile time, and you should not need to change it to */
+ /* port FreeType, except to compile the library with a non-ANSI */
+ /* compiler. */
+ /* */
+ /* Note however that if some specific modifications are needed, we */
+ /* advise you to place a modified copy in your build directory. */
+ /* */
+ /* The build directory is usually `freetype/builds/<system>', and */
+ /* contains system-specific files that are always included first when */
+ /* building the library. */
+ /* */
+ /* This ANSI version should stay in `include/freetype/config'. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef FTCONFIG_H
+#define FTCONFIG_H
+
+
+ /* Include the header file containing all developer build options */
+#include <freetype/config/ftoption.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* PLATFORM-SPECIFIC CONFIGURATION MACROS */
+ /* */
+ /* These macros can be toggled to suit a specific system. The current */
+ /* ones are defaults used to compile FreeType in an ANSI C environment */
+ /* (16bit compilers are also supported). Copy this file to your own */
+ /* `freetype/builds/<system>' directory, and edit it to port the engine. */
+ /* */
+ /*************************************************************************/
+
+
+ /* We use <limits.h> values to know the sizes of the types. */
+#include <limits.h>
+
+ /* The number of bytes in an `int' type. */
+#if UINT_MAX == 0xFFFFFFFF
+#define FT_SIZEOF_INT 4
+#elif UINT_MAX == 0xFFFF
+#define FT_SIZEOF_INT 2
+#elif UINT_MAX > 0xFFFFFFFF && UINT_MAX == 0xFFFFFFFFFFFFFFFF
+#define FT_SIZEOF_INT 8
+#else
+#error "Unsupported number of bytes in `int' type!"
+#endif
+
+ /* The number of bytes in a `long' type. */
+#if ULONG_MAX == 0xFFFFFFFF
+#define FT_SIZEOF_LONG 4
+#elif ULONG_MAX > 0xFFFFFFFF && ULONG_MAX == 0xFFFFFFFFFFFFFFFF
+#define FT_SIZEOF_LONG 8
+#else
+#error "Unsupported number of bytes in `long' type!"
+#endif
+
+
+ /* Preferred alignment of data */
+#define FT_ALIGNMENT 8
+
+
+ /* UNUSED is a macro used to indicate that a given parameter is not used */
+ /* -- this is only used to get rid of unpleasant compiler warnings */
+#ifndef FT_UNUSED
+#define FT_UNUSED( arg ) ( (arg) = (arg) )
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* AUTOMATIC CONFIGURATION MACROS */
+ /* */
+ /* These macros are computed from the ones defined above. Don't touch */
+ /* their definition, unless you know precisely what you are doing. No */
+ /* porter should need to mess with them. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* IntN types */
+ /* */
+ /* Used to guarantee the size of some specific integers. */
+ /* */
+ typedef signed short FT_Int16;
+ typedef unsigned short FT_UInt16;
+
+#if FT_SIZEOF_INT == 4
+
+ typedef signed int FT_Int32;
+ typedef unsigned int FT_UInt32;
+
+#elif FT_SIZEOF_LONG == 4
+
+ typedef signed long FT_Int32;
+ typedef unsigned long FT_UInt32;
+
+#else
+#error "no 32bit type found -- please check your configuration files"
+#endif
+
+#if FT_SIZEOF_LONG == 8
+
+ /* FT_LONG64 must be defined if a 64-bit type is available */
+#define FT_LONG64
+#define FT_INT64 long
+
+#else
+
+
+ /*************************************************************************/
+ /* */
+ /* Many compilers provide the non-ANSI `long long' 64-bit type. You can */
+ /* activate it by defining the FTCALC_USE_LONG_LONG macro in */
+ /* `ftoption.h'. */
+ /* */
+ /* Note that this will produce many -ansi warnings during library */
+ /* compilation, and that in many cases, the generated code will be */
+ /* neither smaller nor faster! */
+ /* */
+#ifdef FTCALC_USE_LONG_LONG
+
+#define FT_LONG64
+#define FT_INT64 long long
+
+#endif /* FTCALC_USE_LONG_LONG */
+#endif /* FT_SIZEOF_LONG == 8 */
+
+
+#ifdef FT_MAKE_OPTION_SINGLE_OBJECT
+#define LOCAL_DEF static
+#define LOCAL_FUNC static
+#else
+#define LOCAL_DEF extern
+#define LOCAL_FUNC /* nothing */
+#endif
+
+#ifdef FT_MAKE_OPTION_SINGLE_LIBRARY_OBJECT
+#define BASE_DEF( x ) static x
+#define BASE_FUNC( x ) static x
+#else
+#define BASE_DEF( x ) extern x
+#define BASE_FUNC( x ) extern x
+#endif
+
+#ifndef FT_EXPORT_DEF
+#define FT_EXPORT_DEF( x ) extern x
+#endif
+
+#ifndef FT_EXPORT_FUNC
+#define FT_EXPORT_FUNC( x ) extern x
+#endif
+
+#ifndef FT_EXPORT_VAR
+#define FT_EXPORT_VAR( x ) extern x
+#endif
+
+#endif /* FTCONFIG_H */
+
+
+/* END */
--- /dev/null
+FT_USE_MODULE(autohint_module_class)
+FT_USE_MODULE(cff_driver_class)
+FT_USE_MODULE(t1cid_driver_class)
+FT_USE_MODULE(psnames_module_class)
+FT_USE_MODULE(ft_raster1_renderer_class)
+FT_USE_MODULE(sfnt_module_class)
+FT_USE_MODULE(ft_smooth_renderer_class)
+FT_USE_MODULE(tt_driver_class)
+FT_USE_MODULE(t1_driver_class)
+FT_USE_MODULE(winfnt_driver_class)
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftoption.h */
+/* */
+/* User-selectable configuration macros (specification only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTOPTION_H
+#define FTOPTION_H
+
+
+ /*************************************************************************/
+ /* */
+ /* USER-SELECTABLE CONFIGURATION MACROS */
+ /* */
+ /* These macros can be toggled by developers to enable or disable */
+ /* certain aspects of FreeType. This is a default file, where all major */
+ /* options are enabled. */
+ /* */
+ /* Note that if some modifications are required for your build, we */
+ /* advise you to put a modified copy of this file in your build */
+ /* directory, rather than modifying it in-place. */
+ /* */
+ /* The build directory is normally `freetype/builds/<system>' and */
+ /* contains build or system-specific files that are included in */
+ /* priority when building the library. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** G E N E R A L F R E E T Y P E 2 C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* Convenience functions support */
+ /* */
+ /* Some functions of the FreeType 2 API are provided as a convenience */
+ /* for client applications and developers. However, they are not */
+ /* required to build and run the library itself. */
+ /* */
+ /* By defining this configuration macro, you'll disable the */
+ /* compilation of these functions at build time. This can be useful */
+ /* to reduce the library's code size when you don't need any of */
+ /* these functions. */
+ /* */
+ /* All convenience functions are declared as such in their */
+ /* documentation. */
+ /* */
+#undef FT_CONFIG_OPTION_NO_CONVENIENCE_FUNCS
+
+
+ /*************************************************************************/
+ /* */
+ /* Alternate Glyph Image Format support */
+ /* */
+ /* By default, the glyph images returned by the FreeType glyph loader */
+ /* can either be a pixmap or a vectorial outline defined through */
+ /* Bezier control points. When defining the following configuration */
+ /* macro, some font drivers will be able to register alternate */
+ /* glyph image formats. */
+ /* */
+ /* Unset this macro if you are sure that you will never use a font */
+ /* driver with an alternate glyph format; this will reduce the size of */
+ /* the base layer code. */
+ /* */
+ /* Note that a few Type 1 fonts, as well as Windows `vector' fonts */
+ /* use a vector `plotter' format that isn't supported when this */
+ /* macro is undefined. */
+ /* */
+#define FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS
+
+
+ /*************************************************************************/
+ /* */
+ /* Glyph Postscript Names handling */
+ /* */
+ /* By default, FreeType 2 is compiled with the `PSNames' module. This */
+ /* This module is in charge of converting a glyph name string into a */
+ /* Unicode value, or return a Macintosh standard glyph name for the */
+ /* use with the TrueType `post' table. */
+ /* */
+ /* Undefine this macro if you do not want `PSNames' compiled in your */
+ /* build of FreeType. This has the following effects: */
+ /* */
+ /* - The TrueType driver will provide its own set of glyph names, */
+ /* if you build it to support postscript names in the TrueType */
+ /* `post' table. */
+ /* */
+ /* - The Type 1 driver will not be able to synthetize a Unicode */
+ /* charmap out of the glyphs found in the fonts. */
+ /* */
+ /* You would normally undefine this configuration macro when building */
+ /* a version of FreeType that doesn't contain a Type 1 or CFF driver. */
+ /* */
+#define FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+ /*************************************************************************/
+ /* */
+ /* Postscript Names to Unicode Values support */
+ /* */
+ /* By default, FreeType 2 is built with the `PSNames' module compiled */
+ /* in. Among other things, the module is used to convert a glyph name */
+ /* into a Unicode value. This is especially useful in order to */
+ /* synthetize on the fly a Unicode charmap from the CFF/Type 1 driver */
+ /* through a big table named the `Adobe Glyph List' (AGL). */
+ /* */
+ /* Undefine this macro if you do not want the Adobe Glyph List */
+ /* compiled in your `PSNames' module. The Type 1 driver will not be */
+ /* able to synthetize a Unicode charmap out of the glyphs found in the */
+ /* fonts. */
+ /* */
+#define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+
+ /*************************************************************************/
+ /* */
+ /* Many compilers provide the non-ANSI `long long' 64-bit type. You can */
+ /* activate it by defining the FTCALC_USE_LONG_LONG macro. Note that */
+ /* this will produce many -ansi warnings during library compilation, and */
+ /* that in many cases the generated code will not be smaller or faster! */
+ /* */
+#undef FTCALC_USE_LONG_LONG
+
+
+ /*************************************************************************/
+ /* */
+ /* DLL export compilation */
+ /* */
+ /* When compiling FreeType as a DLL, some systems/compilers need a */
+ /* special keyword in front OR after the return type of function */
+ /* declarations. */
+ /* */
+ /* Two macros are used within the FreeType source code to define */
+ /* exported library functions: FT_EXPORT_DEF and FT_EXPORT_FUNC. */
+ /* */
+ /* FT_EXPORT_DEF( return_type ) */
+ /* */
+ /* is used in a function declaration, as in */
+ /* */
+ /* FT_EXPORT_DEF( FT_Error ) */
+ /* FT_Init_FreeType( FT_Library* alibrary ); */
+ /* */
+ /* */
+ /* FT_EXPORT_FUNC( return_type ) */
+ /* */
+ /* is used in a function definition, as in */
+ /* */
+ /* FT_EXPORT_FUNC( FT_Error ) */
+ /* FT_Init_FreeType( FT_Library* alibrary ) */
+ /* { */
+ /* ... some code ... */
+ /* return FT_Err_Ok; */
+ /* } */
+ /* */
+ /* You can provide your own implementation of FT_EXPORT_DEF and */
+ /* FT_EXPORT_FUNC here if you want. If you leave them undefined, they */
+ /* will be later automatically defined as `extern return_type' to */
+ /* allow normal compilation. */
+ /* */
+#undef FT_EXPORT_DEF
+#undef FT_EXPORT_FUNC
+
+
+ /*************************************************************************/
+ /* */
+ /* Debug level */
+ /* */
+ /* FreeType can be compiled in debug or trace mode. In debug mode, */
+ /* errors are reported through the `ftdebug' component. In trace */
+ /* mode, additional messages are sent to the standard output during */
+ /* execution. */
+ /* */
+ /* Define FT_DEBUG_LEVEL_ERROR to build the library in debug mode. */
+ /* Define FT_DEBUG_LEVEL_TRACE to build it in trace mode. */
+ /* */
+ /* Don't define any of these macros to compile in `release' mode! */
+ /* */
+#define FT_DEBUG_LEVEL_ERROR
+#define FT_DEBUG_LEVEL_TRACE
+
+
+ /*************************************************************************/
+ /* */
+ /* Computation Algorithms */
+ /* */
+ /* Used for debugging, this configuration macro should disappear */
+ /* soon. */
+ /* */
+#define FT_CONFIG_OPTION_OLD_CALCS
+
+
+ /*************************************************************************/
+ /* */
+ /* The size in bytes of the render pool used by the scan-line converter */
+ /* to do all of its work. */
+ /* */
+ /* This must be greater than 4kByte. */
+ /* */
+#define FT_RENDER_POOL_SIZE 16384
+
+
+ /*************************************************************************/
+ /* */
+ /* FT_MAX_MODULES */
+ /* */
+ /* The maximum number of modules that can be registered in a single */
+ /* FreeType library object. 16 is the default. */
+ /* */
+#define FT_MAX_MODULES 16
+
+
+ /*************************************************************************/
+ /* */
+ /* FT_MAX_EXTENSIONS */
+ /* */
+ /* The maximum number of extensions that can be registered in a single */
+ /* font driver. 8 is the default. */
+ /* */
+ /* If you don't know what this means, you certainly do not need to */
+ /* change this value. */
+ /* */
+#define FT_MAX_EXTENSIONS 8
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** S F N T D R I V E R C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* Define TT_CONFIG_OPTION_EMBEDDED_BITMAPS if you want to support */
+ /* embedded bitmaps in all formats using the SFNT module (namely */
+ /* TrueType & OpenType). */
+ /* */
+#define TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+
+ /*************************************************************************/
+ /* */
+ /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to */
+ /* load and enumerate the glyph Postscript names in a TrueType or */
+ /* OpenType file. */
+ /* */
+ /* Note that when you do not compile the `PSNames' module by undefining */
+ /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will */
+ /* contain additional code used to read the PS Names table from a font. */
+ /* */
+ /* (By default, the module uses `PSNames' to extract glyph names.) */
+ /* */
+#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+ /*************************************************************************/
+ /* */
+ /* Define TT_CONFIG_OPTION_SFNT_NAMES if your applications need to */
+ /* access the internal name table in a SFNT-based format like TrueType */
+ /* or OpenType. The name table contains various strings used to */
+ /* describe the font, like family name, copyright, version, etc. It */
+ /* does not contain any glyph name though. */
+ /* */
+ /* Accessing SFNT names is done through the functions declared in */
+ /* `freetype/ftnames.h'. */
+ /* */
+#define TT_CONFIG_OPTION_SFNT_NAMES
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** T R U E T Y P E D R I V E R C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* Define TT_CONFIG_OPTION_BYTECODE_INTERPRETER if you want to compile */
+ /* a bytecode interpreter in the TrueType driver. Note that there are */
+ /* important patent issues related to the use of the interpreter. */
+ /* */
+ /* By undefining this, you will only compile the code necessary to load */
+ /* TrueType glyphs without hinting. */
+ /* */
+#undef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+
+ /*************************************************************************/
+ /* */
+ /* Define TT_CONFIG_OPTION_INTERPRETER_SWITCH to compile the TrueType */
+ /* bytecode interpreter with a huge switch statement, rather than a call */
+ /* table. This results in smaller and faster code for a number of */
+ /* architectures. */
+ /* */
+ /* Note however that on some compiler/processor combinations, undefining */
+ /* this macro will generate faster, though larger, code. */
+ /* */
+#define TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** T Y P E 1 D R I V E R C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* T1_MAX_STACK_DEPTH is the maximal depth of the token stack used by */
+ /* the Type 1 parser (see t1load.c). A minimum of 16 is required. */
+ /* */
+#define T1_MAX_STACK_DEPTH 16
+
+
+ /*************************************************************************/
+ /* */
+ /* T1_MAX_DICT_DEPTH is the maximal depth of nest dictionaries and */
+ /* arrays in the Type 1 stream (see t1load.c). A minimum of 4 is */
+ /* required. */
+ /* */
+#define T1_MAX_DICT_DEPTH 5
+
+
+ /*************************************************************************/
+ /* */
+ /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */
+ /* calls during glyph loading. */
+ /* */
+#define T1_MAX_SUBRS_CALLS 8
+
+
+ /*************************************************************************/
+ /* */
+ /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. */
+ /* */
+#define T1_MAX_CHARSTRINGS_OPERANDS 32
+
+
+ /*************************************************************************/
+ /* */
+ /* Define T1_CONFIG_OPTION_DISABLE_HINTER if you want to generate a */
+ /* driver with no hinter. This can be useful to debug the parser. */
+ /* */
+#undef T1_CONFIG_OPTION_DISABLE_HINTER
+
+
+ /*************************************************************************/
+ /* */
+ /* Define this configuration macro if you want to prevent the */
+ /* compilation of `t1afm', which is in charge of reading Type 1 AFM */
+ /* files into an existing face. Note that if set, the T1 driver will be */
+ /* unable to produce kerning distances. */
+ /* */
+#undef T1_CONFIG_OPTION_NO_AFM
+
+
+ /*************************************************************************/
+ /* */
+ /* Define this configuration macro if you want to prevent the */
+ /* compilation of the Multiple Masters font support in the Type 1 */
+ /* driver. */
+ /* */
+#undef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+
+#endif /* FTOPTION_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* freetype.h */
+/* */
+/* FreeType high-level API and common types (specification only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FREETYPE_H
+#define FREETYPE_H
+
+
+ /*************************************************************************/
+ /* */
+ /* The `raster' component duplicates some of the declarations in */
+ /* freetype.h for stand-alone use if _FREETYPE_ isn't defined. */
+ /* */
+#define _FREETYPE_
+
+
+ /*************************************************************************/
+ /* */
+ /* The FREETYPE_MAJOR and FREETYPE_MINOR macros are used to version the */
+ /* new FreeType design, which is able to host several kinds of font */
+ /* drivers. It starts at 2.0. */
+ /* */
+#define FREETYPE_MAJOR 2
+#define FREETYPE_MINOR 0
+
+
+#include <freetype/config/ftconfig.h> /* read configuration information */
+#include <freetype/fterrors.h>
+#include <freetype/fttypes.h>
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /* */
+ /* B A S I C T Y P E S */
+ /* */
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Glyph_Metrics */
+ /* */
+ /* <Description> */
+ /* A structure used to model the metrics of a single glyph. Note */
+ /* that values are expressed in 26.6 fractional pixel format or in */
+ /* font units, depending on context. */
+ /* */
+ /* <Fields> */
+ /* width :: The glyph's width. */
+ /* */
+ /* height :: The glyph's height. */
+ /* */
+ /* horiBearingX :: Horizontal left side bearing. */
+ /* */
+ /* horiBearingY :: Horizontal top side bearing. */
+ /* */
+ /* horiAdvance :: Horizontal advance width. */
+ /* */
+ /* vertBearingX :: Vertical left side bearing. */
+ /* */
+ /* vertBearingY :: Vertical top side bearing. */
+ /* */
+ /* vertAdvance :: Vertical advance height. */
+ /* */
+ typedef struct FT_Glyph_Metrics_
+ {
+ FT_Pos width; /* glyph width */
+ FT_Pos height; /* glyph height */
+
+ FT_Pos horiBearingX; /* left side bearing in horizontal layouts */
+ FT_Pos horiBearingY; /* top side bearing in horizontal layouts */
+ FT_Pos horiAdvance; /* advance width for horizontal layout */
+
+ FT_Pos vertBearingX; /* left side bearing in vertical layouts */
+ FT_Pos vertBearingY; /* top side bearing in vertical layouts */
+ FT_Pos vertAdvance; /* advance height for vertical layout */
+
+ } FT_Glyph_Metrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Generic_Finalizer */
+ /* */
+ /* <Description> */
+ /* Describes a function used to destroy the `client' data of any */
+ /* FreeType object. See the description of the FT_Generic type for */
+ /* details of usage. */
+ /* */
+ /* <Input> */
+ /* The address of the FreeType object which is under finalization. */
+ /* Its client data is accessed through its `generic' field. */
+ /* */
+ typedef void (*FT_Generic_Finalizer)(void* object);
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Generic */
+ /* */
+ /* <Description> */
+ /* Client applications often need to associate their own data to a */
+ /* variety of FreeType core objects. For example, a text layout API */
+ /* might want to associate a glyph cache to a given size object. */
+ /* */
+ /* Most FreeType object contains a `generic' field, of type */
+ /* FT_Generic, which usage is left to client applications and font */
+ /* servers. */
+ /* */
+ /* It can be used to store a pointer to client-specific data, as well */
+ /* as the address of a `finalizer' function, which will be called by */
+ /* FreeType when the object is destroyed (for example, the previous */
+ /* client example would put the address of the glyph cache destructor */
+ /* in the `finalizer' field). */
+ /* */
+ /* <Fields> */
+ /* data :: A typeless pointer to any client-specified data. This */
+ /* field is completely ignored by the FreeType library. */
+ /* */
+ /* finalizer :: A pointer to a `generic finalizer' function, which */
+ /* will be called when the object is destroyed. If this */
+ /* field is set to NULL, no code will be called. */
+ /* */
+ typedef struct FT_Generic_
+ {
+ void* data;
+ FT_Generic_Finalizer finalizer;
+
+ } FT_Generic;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Bitmap_Size */
+ /* */
+ /* <Description> */
+ /* An extremely simple structure used to model the size of a bitmap */
+ /* strike (i.e., a bitmap instance of the font for a given */
+ /* resolution) in a fixed-size font face. This is used for the */
+ /* `available_sizes' field of the FT_Face_Properties structure. */
+ /* */
+ /* <Fields> */
+ /* height :: The character height in pixels. */
+ /* */
+ /* width :: The character width in pixels. */
+ /* */
+ typedef struct FT_Bitmap_Size_
+ {
+ FT_Short height;
+ FT_Short width;
+
+ } FT_Bitmap_Size;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /* */
+ /* O B J E C T C L A S S E S */
+ /* */
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Library */
+ /* */
+ /* <Description> */
+ /* A handle to a FreeType library instance. Each `library' is */
+ /* completely independent from the others; it is the `root' of a set */
+ /* of objects like fonts, faces, sizes, etc. */
+ /* */
+ /* It also embeds a system object (see FT_System), as well as a */
+ /* scan-line converter object (see FT_Raster). */
+ /* */
+ /* <Note> */
+ /* Library objects are created through FT_Init_FreeType(). */
+ /* */
+ typedef struct FT_LibraryRec_ *FT_Library;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Module */
+ /* */
+ /* <Description> */
+ /* A handle to a given FreeType module object. Each module can be a */
+ /* font driver, a renderer, or anything else that provides services */
+ /* to the formers. */
+ /* */
+ typedef struct FT_ModuleRec_* FT_Module;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Driver */
+ /* */
+ /* <Description> */
+ /* A handle to a given FreeType font driver object. Each font driver */
+ /* is able to create faces, sizes, glyph slots, and charmaps from the */
+ /* resources whose format it supports. */
+ /* */
+ /* A driver can support either bitmap, graymap, or scalable font */
+ /* formats. */
+ /* */
+ typedef struct FT_DriverRec_* FT_Driver;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Renderer */
+ /* */
+ /* <Description> */
+ /* A handle to a given FreeType renderer. A renderer is in charge of */
+ /* converting a glyph image to a bitmap, when necessary. Each */
+ /* supports a given glyph image format, and one or more target */
+ /* surface depths. */
+ /* */
+ typedef struct FT_RendererRec_* FT_Renderer;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Face */
+ /* */
+ /* <Description> */
+ /* A handle to a given driver face object. A face object contains */
+ /* all the instance and glyph independent data of a font file */
+ /* typeface. */
+ /* */
+ /* A face object is created from a resource object through the */
+ /* new_face() method of a given driver. */
+ /* */
+ typedef struct FT_FaceRec_* FT_Face;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Size */
+ /* */
+ /* <Description> */
+ /* A handle to a given driver size object. Such an object models the */
+ /* _resolution_ AND _size_ dependent state of a given driver face */
+ /* size. */
+ /* */
+ /* A size object is always created from a given face object. It is */
+ /* discarded automatically by its parent face. */
+ /* */
+ typedef struct FT_SizeRec_* FT_Size;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* A handle to a given `glyph slot'. A slot is a container where it */
+ /* is possible to load any of the glyphs contained within its parent */
+ /* face. */
+ /* */
+ /* A glyph slot is created from a given face object. It is discarded */
+ /* automatically by its parent face. */
+ /* */
+ typedef struct FT_GlyphSlotRec_* FT_GlyphSlot;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_CharMap */
+ /* */
+ /* <Description> */
+ /* A handle to a given character map. A charmap is used to translate */
+ /* character codes in a given encoding into glyph indexes for its */
+ /* parent's face. Some font formats may provide several charmaps per */
+ /* font. */
+ /* */
+ /* A charmap is created from a given face object. It is discarded */
+ /* automatically by its parent face. */
+ /* */
+ typedef struct FT_CharMapRec_* FT_CharMap;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Encoding */
+ /* */
+ /* <Description> */
+ /* An enumeration used to specify encodings supported by charmaps. */
+ /* Used in the FT_Select_CharMap() API function. */
+ /* */
+ /* <Note> */
+ /* Because of 32-bit charcodes defined in Unicode (i.e., surrogates), */
+ /* all character codes must be expressed as FT_Longs. */
+ /* */
+ typedef enum FT_Encoding_
+ {
+ ft_encoding_none = 0,
+ ft_encoding_symbol = FT_MAKE_TAG( 's', 'y', 'm', 'b' ),
+ ft_encoding_unicode = FT_MAKE_TAG( 'u', 'n', 'i', 'c' ),
+ ft_encoding_latin_2 = FT_MAKE_TAG( 'l', 'a', 't', '2' ),
+ ft_encoding_sjis = FT_MAKE_TAG( 's', 'j', 'i', 's' ),
+ ft_encoding_gb2312 = FT_MAKE_TAG( 'g', 'b', ' ', ' ' ),
+ ft_encoding_big5 = FT_MAKE_TAG( 'b', 'i', 'g', '5' ),
+ ft_encoding_wansung = FT_MAKE_TAG( 'w', 'a', 'n', 's' ),
+ ft_encoding_johab = FT_MAKE_TAG( 'j', 'o', 'h', 'a' ),
+
+ ft_encoding_adobe_standard = FT_MAKE_TAG( 'A', 'D', 'O', 'B' ),
+ ft_encoding_adobe_expert = FT_MAKE_TAG( 'A', 'D', 'B', 'E' ),
+ ft_encoding_adobe_custom = FT_MAKE_TAG( 'A', 'D', 'B', 'C' ),
+
+ ft_encoding_apple_roman = FT_MAKE_TAG( 'a', 'r', 'm', 'n' )
+
+ /* other encodings might be defined in the future */
+
+ } FT_Encoding;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_CharMapRec */
+ /* */
+ /* <Description> */
+ /* The base charmap class. */
+ /* */
+ /* <Fields> */
+ /* face :: A handle to the parent face object. */
+ /* */
+ /* flags :: A set of bit flags used to describe the charmap. */
+ /* Each bit indicates that a given encoding is */
+ /* supported. */
+ /* */
+ /* platform_id :: An ID number describing the platform for the */
+ /* following encoding ID. This comes directly from */
+ /* the TrueType specification and should be emulated */
+ /* for other formats. */
+ /* */
+ /* encoding_id :: A platform specific encoding number. This also */
+ /* comes from the TrueType specification and should be */
+ /* emulated similarly. */
+ /* */
+ /* <Note> */
+ /* We STRONGLY recommmend emulating a Unicode charmap for drivers */
+ /* that do not support TrueType or OpenType. */
+ /* */
+ typedef struct FT_CharMapRec_
+ {
+ FT_Face face;
+ FT_Encoding encoding;
+ FT_UShort platform_id;
+ FT_UShort encoding_id;
+
+ } FT_CharMapRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /* */
+ /* B A S E O B J E C T C L A S S E S */
+ /* */
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* FreeType base face class */
+ /* */
+ /* <Struct> */
+ /* FT_FaceRec */
+ /* */
+ /* <Description> */
+ /* FreeType root face class structure. A face object models the */
+ /* resolution and point-size independent data found in a font file. */
+ /* */
+ /* <Fields> */
+ /* num_faces :: In the case where the face is located in a */
+ /* collection (i.e., a resource which embeds */
+ /* several faces), this is the total number of */
+ /* faces found in the resource. 1 by default. */
+ /* */
+ /* face_index :: The index of the face in its resource. */
+ /* Usually, this is 0 for all normal font */
+ /* formats. It can be more in the case of */
+ /* collections (which embed several fonts in a */
+ /* single resource/file). */
+ /* */
+ /* face_flags :: A set of bit flags that give important */
+ /* information about the face; see the */
+ /* FT_FACE_FLAG_XXX macros for details. */
+ /* */
+ /* style_flags :: A set of bit flags indicating the style of */
+ /* the face (i.e., italic, bold, underline, */
+ /* etc). */
+ /* */
+ /* num_glyphs :: The total number of glyphs in the face. */
+ /* */
+ /* family_name :: The face's family name. This is an ASCII */
+ /* string, usually in English, which describes */
+ /* the typeface's family (like `Times New */
+ /* Roman', `Bodoni', `Garamond', etc). This */
+ /* is a least common denominator used to list */
+ /* fonts. Some formats (TrueType & OpenType) */
+ /* provide localized and Unicode versions of */
+ /* this string. Applications should use the */
+ /* format specific interface to access them. */
+ /* */
+ /* style_name :: The face's style name. This is an ASCII */
+ /* string, usually in English, which describes */
+ /* the typeface's style (like `Italic', */
+ /* `Bold', `Condensed', etc). Not all font */
+ /* formats provide a style name, so this field */
+ /* is optional, and can be set to NULL. As */
+ /* for `family_name', some formats provide */
+ /* localized/Unicode versions of this string. */
+ /* Applications should use the format specific */
+ /* interface to access them. */
+ /* */
+ /* num_fixed_sizes :: The number of fixed sizes available in this */
+ /* face. This should be set to 0 for scalable */
+ /* fonts, unless its resource includes a */
+ /* complete set of glyphs (called a `strike') */
+ /* for the specified size. */
+ /* */
+ /* available_sizes :: An array of sizes specifying the available */
+ /* bitmap/graymap sizes that are contained in */
+ /* in the font resource. Should be set to */
+ /* NULL if the field `num_fixed_sizes' is set */
+ /* to 0. */
+ /* */
+ /* num_charmaps :: The total number of character maps in the */
+ /* face. */
+ /* */
+ /* charmaps :: A table of pointers to the face's charmaps */
+ /* Used to scan the list of available charmaps */
+ /* this table might change after a call to */
+ /* FT_Attach_File/Stream (e.g. when it used */
+ /* to hook and additional encoding/CMap to */
+ /* the face object). */
+ /* */
+ /* generic :: A field reserved for client uses. See the */
+ /* FT_Generic type description. */
+ /* */
+ /* bbox :: The font bounding box. Coordinates are */
+ /* expressed in font units (see units_per_EM). */
+ /* The box is large enough to contain any */
+ /* glyph from the font. Thus, bbox.yMax can */
+ /* be seen as the `maximal ascender', */
+ /* bbox.yMin as the `minimal descender', and */
+ /* the maximal glyph width is given by */
+ /* `bbox.xMax-bbox.xMin' (not to be confused */
+ /* with the maximal _advance_width_). Only */
+ /* relevant for scalable formats. */
+ /* */
+ /* units_per_EM :: The number of font units per EM square for */
+ /* this face. This is typically 2048 for */
+ /* TrueType fonts, 1000 for Type1 fonts, and */
+ /* should be set to the (unrealistic) value 1 */
+ /* for fixed-sizes fonts. Only relevant for */
+ /* scalable formats. */
+ /* */
+ /* ascender :: The face's ascender is the vertical */
+ /* distance from the baseline to the topmost */
+ /* point of any glyph in the face. This */
+ /* field's value is positive, expressed in */
+ /* font units. Some font designs use a value */
+ /* different from `bbox.yMax'. Only relevant */
+ /* for scalable formats. */
+ /* */
+ /* descender :: The face's descender is the vertical */
+ /* distance from the baseline to the */
+ /* bottommost point of any glyph in the face. */
+ /* This field's value is positive, expressed */
+ /* in font units. Some font designs use a */
+ /* value different from `-bbox.yMin'. Only */
+ /* relevant for scalable formats. */
+ /* */
+ /* height :: The face's height is the vertical distance */
+ /* from one baseline to the next when writing */
+ /* several lines of text. Its value is always */
+ /* positive, expressed in font units. The */
+ /* value can be computed as */
+ /* `ascender+descender+line_gap' where the */
+ /* value of `line_gap' is also called */
+ /* `external leading'. Only relevant for */
+ /* scalable formats. */
+ /* */
+ /* max_advance_width :: The maximal advance width, in font units, */
+ /* for all glyphs in this face. This can be */
+ /* used to make word wrapping computations */
+ /* faster. Only relevant for scalable */
+ /* formats. */
+ /* */
+ /* max_advance_height :: The maximal advance height, in font units, */
+ /* for all glyphs in this face. This is only */
+ /* relevant for vertical layouts, and should */
+ /* be set to the `height' for fonts that do */
+ /* not provide vertical metrics. Only */
+ /* relevant for scalable formats. */
+ /* */
+ /* underline_position :: The position, in font units, of the */
+ /* underline line for this face. It's the */
+ /* center of the underlining stem. Only */
+ /* relevant for scalable formats. */
+ /* */
+ /* underline_thickness :: The thickness, in font units, of the */
+ /* underline for this face. Only relevant for */
+ /* scalable formats. */
+ /* */
+ /* driver :: A handle to the face's parent driver */
+ /* object. */
+ /* */
+ /* memory :: A handle to the face's parent memory */
+ /* object. Used for the allocation of */
+ /* subsequent objects. */
+ /* */
+ /* stream :: A handle to the face's stream. */
+ /* */
+ /* glyph :: The face's associated glyph slot(s). This */
+ /* object is created automatically with a new */
+ /* face object. However, certain kinds of */
+ /* applications (mainly tools like converters) */
+ /* can need more than one slot to ease their */
+ /* task. */
+ /* */
+ /* sizes_list :: The list of child sizes for this face. */
+ /* */
+ /* max_points :: The maximal number of points used to store */
+ /* the vectorial outline of any glyph in this */
+ /* face. If this value cannot be known in */
+ /* advance, or if the face isn't scalable, */
+ /* this should be set to 0. Only relevant for */
+ /* scalable formats. */
+ /* */
+ /* max_contours :: The maximal number of contours used to */
+ /* store the vectorial outline of any glyph in */
+ /* this face. If this value cannot be known */
+ /* in advance, or if the face isn't scalable, */
+ /* this should be set to 0. Only relevant for */
+ /* scalable formats. */
+ /* */
+ /* transform_matrix :: A 2x2 matrix of 16.16 coefficients used */
+ /* to transform glyph outlines after they are */
+ /* loaded from the font. Only used by the */
+ /* convenience functions. */
+ /* */
+ /* transform_delta :: A translation vector used to transform */
+ /* glyph outlines after they are loaded from */
+ /* the font. Only used by the convenience */
+ /* functions. */
+ /* */
+ /* transform_flags :: Some flags used to classify the transform. */
+ /* Only used by the convenience functions. */
+ /* */
+ typedef struct FT_FaceRec_
+ {
+ FT_Long num_faces;
+ FT_Long face_index;
+
+ FT_Long face_flags;
+ FT_Long style_flags;
+
+ FT_Long num_glyphs;
+
+ FT_String* family_name;
+ FT_String* style_name;
+
+ FT_Int num_fixed_sizes;
+ FT_Bitmap_Size* available_sizes;
+
+ /* the face's table of available charmaps */
+ FT_Int num_charmaps;
+ FT_CharMap* charmaps;
+
+ FT_Generic generic;
+
+ /* the following are only relevant for scalable outlines */
+ FT_BBox bbox;
+
+ FT_UShort units_per_EM;
+ FT_Short ascender;
+ FT_Short descender;
+ FT_Short height;
+
+ FT_Short max_advance_width;
+ FT_Short max_advance_height;
+
+ FT_Short underline_position;
+ FT_Short underline_thickness;
+
+ FT_GlyphSlot glyph;
+ FT_Size size;
+
+ /************************************************************/
+ /* The following fields should be considered private and */
+ /* rarely, if ever, used directly by client applications. */
+
+ FT_Driver driver;
+ FT_Memory memory;
+ FT_Stream stream;
+
+ FT_CharMap charmap;
+ FT_ListRec sizes_list;
+
+ FT_Generic autohint;
+ void* extensions;
+
+ FT_UShort max_points;
+ FT_Short max_contours;
+
+ FT_Matrix transform_matrix;
+ FT_Vector transform_delta;
+ FT_Int transform_flags;
+
+ } FT_FaceRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_FACE_FLAG_SCALABLE */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used to indicate that a given face provides */
+ /* vectorial outlines (i.e., TrueType or Type1). This doesn't */
+ /* prevent embedding of bitmap strikes though, i.e., a given face can */
+ /* have both this bit set, and a `num_fixed_sizes' property > 0. */
+ /* */
+#define FT_FACE_FLAG_SCALABLE 1
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_FACE_FLAG_FIXED_SIZES */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used to indicate that a given face contains */
+ /* `fixed sizes', i.e., bitmap strikes for some given pixel sizes. */
+ /* See the `num_fixed_sizes' and `available_sizes' face properties */
+ /* for more information. */
+ /* */
+#define FT_FACE_FLAG_FIXED_SIZES 2
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_FACE_FLAG_FIXED_WIDTH */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used to indicate that a given face contains */
+ /* fixed-width characters (like Courier, Lucida, MonoType, etc.). */
+ /* */
+#define FT_FACE_FLAG_FIXED_WIDTH 4
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_FACE_FLAG_SFNT */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used to indicate that a given face uses the */
+ /* `sfnt' storage fomat. For now, this means TrueType or OpenType. */
+ /* */
+#define FT_FACE_FLAG_SFNT 8
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_FACE_FLAG_HORIZONTAL */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used to indicate that a given face contains */
+ /* horizontal glyph metrics. This should be set for all common */
+ /* formats, but who knows. */
+ /* */
+#define FT_FACE_FLAG_HORIZONTAL 0x10
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_FACE_FLAG_VERTICAL */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used to indicate that a given face contains */
+ /* vertical glyph metrics. If not set, the glyph loader will */
+ /* synthetize vertical metrics itself to help display vertical text */
+ /* correctly. */
+ /* */
+#define FT_FACE_FLAG_VERTICAL 0x20
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_FACE_FLAG_KERNING */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used to indicate that a given face contains */
+ /* kerning information. When set, this information can be retrieved */
+ /* through the function FT_Get_Kerning(). Note that when unset, this */
+ /* function will always return the kerning vector (0,0). */
+ /* */
+#define FT_FACE_FLAG_KERNING 0x40
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_FACE_FLAG_FAST_GLYPHS */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used to indicate that the glyphs in a given */
+ /* font can be retrieved very quickly, and that a glyph cache is thus */
+ /* not necessary for any of its child size objects. */
+ /* */
+ /* This flag should really be set for fixed-size formats like FNT, */
+ /* where each glyph bitmap is available directly in binary form */
+ /* without any kind of compression. */
+ /* */
+#define FT_FACE_FLAG_FAST_GLYPHS 0x80
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_FACE_FLAG_MULTIPLE_MASTERS */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used to indicate that the font contains */
+ /* multiple masters and is capable of interpolating between them. */
+ /* */
+#define FT_FACE_FLAG_MULTIPLE_MASTERS 0x100
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_FACE_FLAG_GLYPH_NAMES */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used to indicate that the font contains */
+ /* glyph names that can be retrieved through FT_Get_Glyph_Name(). */
+ /* */
+#define FT_FACE_FLAG_GLYPH_NAMES 0x200
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_FACE_FLAG_EXTERNAL_STREAM */
+ /* */
+ /* <Description> */
+ /* This bit field is used internally by FreeType to indicate that */
+ /* a face's stream was provided by the client application and should */
+ /* not be destroyed by FT_Done_Face(). */
+ /* */
+#define FT_FACE_FLAG_EXTERNAL_STREAM 0x4000
+
+
+#define FT_HAS_HORIZONTAL( face ) \
+ ( face->face_flags & FT_FACE_FLAG_HORIZONTAL )
+#define FT_HAS_VERTICAL( face ) \
+ ( face->face_flags & FT_FACE_FLAG_VERTICAL )
+#define FT_HAS_KERNING( face ) \
+ ( face->face_flags & FT_FACE_FLAG_KERNING )
+#define FT_IS_SCALABLE( face ) \
+ ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+#define FT_IS_SFNT( face ) \
+ ( face->face_flags & FT_FACE_FLAG_SFNT )
+#define FT_IS_FIXED_WIDTH( face ) \
+ ( face->face_flags & FT_FACE_FLAG_FIXED_WIDTH )
+#define FT_HAS_FIXED_SIZES( face ) \
+ ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES )
+#define FT_HAS_FAST_GLYPHS( face ) \
+ ( face->face_flags & FT_FACE_FLAG_FAST_GLYPHS )
+#define FT_HAS_GLYPH_NAMES( face ) \
+ ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES )
+
+#define FT_HAS_MULTIPLE_MASTERS( face ) \
+ ( face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_STYLE_FLAG_ITALIC */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used to indicate that a given face is */
+ /* italicized. */
+ /* */
+#define FT_STYLE_FLAG_ITALIC 1
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_STYLE_FLAG_BOLD */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used to indicate that a given face is */
+ /* emboldened. */
+ /* */
+#define FT_STYLE_FLAG_BOLD 2
+
+
+ /*************************************************************************/
+ /* */
+ /* FreeType base size metrics */
+ /* */
+ /* <Struct> */
+ /* FT_Size_Metrics */
+ /* */
+ /* <Description> */
+ /* The size metrics structure returned scaled important distances for */
+ /* a given size object. */
+ /* */
+ /* <Fields> */
+ /* x_ppem :: The character width, expressed in integer pixels. */
+ /* This is the width of the EM square expressed in */
+ /* pixels, hence the term `ppem' (pixels per EM). */
+ /* */
+ /* y_ppem :: The character height, expressed in integer pixels. */
+ /* This is the height of the EM square expressed in */
+ /* pixels, hence the term `ppem' (pixels per EM). */
+ /* */
+ /* x_scale :: A simple 16.16 fixed point format coefficient used */
+ /* to scale horizontal distances expressed in font */
+ /* units to fractional (26.6) pixel coordinates. */
+ /* */
+ /* y_scale :: A simple 16.16 fixed point format coefficient used */
+ /* to scale vertical distances expressed in font */
+ /* units to fractional (26.6) pixel coordinates. */
+ /* */
+ /* x_resolution :: The horizontal device resolution for this size */
+ /* object, expressed in integer dots per inches */
+ /* (dpi). As a convention, fixed font formats set */
+ /* this value to 72. */
+ /* */
+ /* y_resolution :: The vertical device resolution for this size */
+ /* object, expressed in integer dots per inches */
+ /* (dpi). As a convention, fixed font formats set */
+ /* this value to 72. */
+ /* */
+ /* ascender :: The ascender, expressed in 26.6 fixed point */
+ /* pixels. Always positive. */
+ /* */
+ /* descender :: The descender, expressed in 26.6 fixed point */
+ /* pixels. Always positive. */
+ /* */
+ /* height :: The text height, expressed in 26.6 fixed point */
+ /* pixels. Always positive. */
+ /* */
+ /* max_advance :: Maximum horizontal advance, expressed in 26.6 */
+ /* fixed point pixels. Always positive. */
+ /* */
+ /* <Note> */
+ /* The values of `ascender', `descender', and `height' are only the */
+ /* scaled versions of `face->ascender', `face->descender', and */
+ /* `face->height'. */
+ /* */
+ /* Unfortunately, due to glyph hinting, these values might not be */
+ /* exact for certain fonts, they thus must be treated as unreliable */
+ /* with an error margin of at least one pixel! */
+ /* */
+ /* Indeed, the only way to get the exact pixel ascender and descender */
+ /* is to render _all_ glyphs. As this would be a definite */
+ /* performance hit, it is up to client applications to perform such */
+ /* computations. */
+ /* */
+ typedef struct FT_Size_Metrics_
+ {
+ FT_UShort x_ppem; /* horizontal pixels per EM */
+ FT_UShort y_ppem; /* vertical pixels per EM */
+
+ FT_Fixed x_scale; /* two scales used to convert font units */
+ FT_Fixed y_scale; /* to 26.6 frac. pixel coordinates.. */
+
+ FT_Pos ascender; /* ascender in 26.6 frac. pixels */
+ FT_Pos descender; /* descender in 26.6 frac. pixels */
+ FT_Pos height; /* text height in 26.6 frac. pixels */
+ FT_Pos max_advance; /* max horizontal advance, in 26.6 pixels */
+
+ } FT_Size_Metrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* FreeType base size class */
+ /* */
+ /* <Struct> */
+ /* FT_SizeRec */
+ /* */
+ /* <Description> */
+ /* FreeType root size class structure. A size object models the */
+ /* resolution and pointsize dependent data of a given face. */
+ /* */
+ /* <Fields> */
+ /* face :: Handle to the parent face object. */
+ /* */
+ /* generic :: A typeless pointer, which is unused by the FreeType */
+ /* library or any of its drivers. It can be used by */
+ /* client applications to link their own data to each size */
+ /* object. */
+ /* */
+ /* metrics :: Metrics for this size object. This field is read-only. */
+ /* */
+ typedef struct FT_SizeRec_
+ {
+ FT_Face face; /* parent face object */
+ FT_Generic generic; /* generic pointer for client uses */
+ FT_Size_Metrics metrics; /* size metrics */
+
+ } FT_SizeRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_SubGlyph */
+ /* */
+ /* <Description> */
+ /* The subglyph structure is an internal object used to describe */
+ /* subglyphs (for example, in the case of composites). */
+ /* */
+ /* <Note> */
+ /* The subglyph implementation is not part of the high-level API, */
+ /* hence the forward structure declaration. */
+ /* */
+ typedef struct FT_SubGlyph_ FT_SubGlyph;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_GlyphLoader */
+ /* */
+ /* <Description> */
+ /* The glyph loader is an internal object used to load several glyphs */
+ /* together (for example, in the case of composites). */
+ /* */
+ /* <Note> */
+ /* The glyph loader implementation is not part of the high-level API, */
+ /* hence the forward structure declaration. */
+ /* */
+ typedef struct FT_GlyphLoader_ FT_GlyphLoader;
+
+
+ /*************************************************************************/
+ /* */
+ /* FreeType Glyph Slot base class */
+ /* */
+ /* <Struct> */
+ /* FT_GlyphSlotRec */
+ /* */
+ /* <Description> */
+ /* FreeType root glyph slot class structure. A glyph slot is a */
+ /* container where individual glyphs can be loaded, be they */
+ /* vectorial or bitmap/graymaps. */
+ /* */
+ /* <Fields> */
+ /* library :: A handle to the FreeType library instance */
+ /* this slot belongs to. */
+ /* */
+ /* face :: A handle to the parent face object. */
+ /* */
+ /* next :: In some cases (like some font tools), several */
+ /* glyph slots per face object can be a good */
+ /* thing. As this is rare, the glyph slots are */
+ /* listed through a direct, single-linked list */
+ /* using its `next' field. */
+ /* */
+ /* generic :: A typeless pointer which is unused by the */
+ /* FreeType library or any of its drivers. It */
+ /* can be used by client applications to link */
+ /* their own data to each size object. */
+ /* */
+ /* metrics :: The metrics of the last loaded glyph in the */
+ /* slot. The returned values depend on the last */
+ /* load flags (see the FT_Load_Glyph() API */
+ /* function) and can be expressed either in 26.6 */
+ /* fractional pixels or font units. */
+ /* */
+ /* Note that even when the glyph image is */
+ /* transformed, the metrics are not. */
+ /* */
+ /* linearHoriAdvance :: For scalable formats only, this field holds */
+ /* the linearly scaled horizontal advance width */
+ /* for the glyph (i.e. the scaled and unhinted */
+ /* value of the hori advance). This can be */
+ /* important to perform correct WYSIWYG layout */
+ /* */
+ /* Note that this value is expressed by default */
+ /* in 16.16 pixels. However, when the glyph is */
+ /* loaded with the FT_LOAD_UNSCALED_LINEAR flag, */
+ /* this field contains simply the value of the */
+ /* advance in original font units. */
+ /* */
+ /* linearVertAdvance :: For scalable formats only, this field holds */
+ /* the linearly scaled vertical advance height */
+ /* for the glyph. See linearHoriAdvance for */
+ /* comments. */
+ /* */
+ /* advance :: This is the transformed advance width for the */
+ /* glyph. */
+ /* */
+ /* format :: This field indicates the format of the image */
+ /* contained in the glyph slot. Typically */
+ /* ft_glyph_format_bitmap, */
+ /* ft_glyph_format_outline, and */
+ /* ft_glyph_format_composite, but others are */
+ /* possible. */
+ /* */
+ /* bitmap :: This field is used as a bitmap descriptor */
+ /* when the slot format is */
+ /* ft_glyph_format_bitmap. Note that the */
+ /* address and content of the bitmap buffer can */
+ /* change between calls of FT_Load_Glyph() and a */
+ /* few other functions. */
+ /* */
+ /* bitmap_left :: This is the bitmap's left bearing expressed */
+ /* in integer pixels. Of course, this is only */
+ /* valid if the format is */
+ /* ft_glyph_format_bitmap. */
+ /* */
+ /* bitmap_top :: This is the bitmap's top bearing expressed in */
+ /* integer pixels. Remember that this is the */
+ /* distance from the baseline to the top-most */
+ /* glyph scanline, upwards y-coordinates being */
+ /* *positive*. */
+ /* */
+ /* outline :: The outline descriptor for the current glyph */
+ /* image if its format is */
+ /* ft_glyph_bitmap_outline. */
+ /* */
+ /* num_subglyphs :: The number of subglyphs in a composite glyph. */
+ /* This format is only valid for the composite */
+ /* glyph format, that should normally only be */
+ /* loaded with the FT_LOAD_NO_RECURSE flag. */
+ /* */
+ /* subglyphs :: An array of subglyph descriptors for */
+ /* composite glyphs. There are `num_subglyphs' */
+ /* elements in there. */
+ /* */
+ /* control_data :: Certain font drivers can also return the */
+ /* control data for a given glyph image (e.g. */
+ /* TrueType bytecode, Type 1 charstrings, etc.). */
+ /* This field is a pointer to such data. */
+ /* */
+ /* control_len :: This is the length in bytes of the control */
+ /* data. */
+ /* */
+ /* other :: Really wicked formats can use this pointer to */
+ /* present their own glyph image to client apps. */
+ /* Note that the app will need to know about the */
+ /* image format. */
+ /* */
+ /* loader :: This is a private object for the glyph slot. */
+ /* Do not touch this. */
+ /* */
+ /* <Note> */
+ /* If FT_Load_Glyph() is called with default flags (FT_LOAD_DEFAULT), */
+ /* the glyph image is loaded in the glyph slot in its native format */
+ /* (e.g. a vectorial outline for TrueType and Type 1 formats). */
+ /* */
+ /* This image can later be converted into a bitmap by calling */
+ /* FT_Render_Glyph(). This function finds the current renderer for */
+ /* the native image's format then invokes it. */
+ /* */
+ /* The renderer is in charge of transforming the native image through */
+ /* the slot's face transformation fields, then convert it into a */
+ /* bitmap that is returned in `slot->bitmap'. */
+ /* */
+ /* Note that `slot->bitmap_left' and `slot->bitmap_top' are also used */
+ /* to specify the position of the bitmap relative to the current pen */
+ /* position (e.g. coordinates [0,0] on the baseline). Of course, */
+ /* `slot->format' is also changed to `ft_glyph_format_bitmap' . */
+ /* */
+ typedef struct FT_GlyphSlotRec_
+ {
+ FT_Library library;
+ FT_Face face;
+ FT_GlyphSlot next;
+ FT_UInt flags;
+ FT_Generic generic;
+
+ FT_Glyph_Metrics metrics;
+ FT_Fixed linearHoriAdvance;
+ FT_Fixed linearVertAdvance;
+ FT_Vector advance;
+
+ FT_Glyph_Format format;
+
+ FT_Bitmap bitmap;
+ FT_Int bitmap_left;
+ FT_Int bitmap_top;
+
+ FT_Outline outline;
+
+ FT_UInt num_subglyphs;
+ FT_SubGlyph* subglyphs;
+
+ void* control_data;
+ long control_len;
+
+ void* other;
+
+ /* private fields */
+ FT_GlyphLoader* loader;
+
+ } FT_GlyphSlotRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /* */
+ /* F U N C T I O N S */
+ /* */
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Init_FreeType */
+ /* */
+ /* <Description> */
+ /* Initializes a new FreeType library object. The set of drivers */
+ /* that are registered by this function is determined at build time. */
+ /* */
+ /* <Output> */
+ /* library :: A handle to a new library object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Init_FreeType( FT_Library* library );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_FreeType */
+ /* */
+ /* <Description> */
+ /* Destroys a given FreeType library object and all of its childs, */
+ /* including resources, drivers, faces, sizes, etc. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the target library object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Done_FreeType( FT_Library library );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Open_Flags */
+ /* */
+ /* <Description> */
+ /* An enumeration used to list the bit flags used within */
+ /* FT_Open_Args(). */
+ /* */
+ /* <Fields> */
+ /* ft_open_memory :: This is a memory-based stream. */
+ /* */
+ /* ft_open_stream :: Copy the stream from the `stream' field. */
+ /* */
+ /* ft_open_pathname :: Create a new input stream from a C pathname. */
+ /* */
+ /* ft_open_driver :: Use the `driver' field. */
+ /* */
+ /* ft_open_params :: Use the `num_params' & `params' field. */
+ /* */
+ typedef enum
+ {
+ ft_open_memory = 1,
+ ft_open_stream = 2,
+ ft_open_pathname = 4,
+ ft_open_driver = 8,
+ ft_open_params = 16
+
+ } FT_Open_Flags;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Parameter */
+ /* */
+ /* <Description> */
+ /* A simple structure used to pass more or less generic parameters */
+ /* to FT_Open_Face(). */
+ /* */
+ /* <Fields> */
+ /* tag :: A 4-byte identification tag. */
+ /* */
+ /* data :: A pointer to the parameter data. */
+ /* */
+ /* <Note> */
+ /* The id and function of parameters are driver-specific. */
+ /* */
+ typedef struct FT_Parameter_
+ {
+ FT_ULong tag;
+ FT_Pointer data;
+
+ } FT_Parameter;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Open_Args */
+ /* */
+ /* <Description> */
+ /* A structure used to indicate how to open a new font file/stream. */
+ /* A pointer to such a structure can be used as a parameter for the */
+ /* functions FT_Open_Face() & FT_Attach_Stream(). */
+ /* */
+ /* <Fields> */
+ /* flags :: A set of bit flags indicating how to use the */
+ /* structure. */
+ /* */
+ /* memory_base :: The first byte of the file in memory. */
+ /* */
+ /* memory_size :: The size in bytes of the file in memory. */
+ /* */
+ /* pathname :: A pointer to an 8-bit file pathname. */
+ /* */
+ /* stream :: A handle to a source stream object. */
+ /* */
+ /* driver :: This field is exclusively used by FT_Open_Face(); */
+ /* it simply specifies the font driver to use to open */
+ /* the face. If set to 0, FreeType will try to load */
+ /* the face with each one of the drivers in its list. */
+ /* */
+ /* num_params :: The number of extra parameters. */
+ /* */
+ /* params :: Extra parameters passed to the font driver when */
+ /* opening a new face. */
+ /* */
+ /* <Note> */
+ /* `stream_type' determines which fields are used to create a new */
+ /* input stream. */
+ /* */
+ /* If it is `ft_stream_memory', a new memory-based stream will be */
+ /* created using the memory block specified by `memory_base' and */
+ /* `memory_size'. */
+ /* */
+ /* If it is `ft_stream_pathname', a new stream will be created with */
+ /* the `pathname' field, calling the system-specific FT_New_Stream() */
+ /* function. */
+ /* */
+ /* If is is `ft_stream_copy', then the content of `stream' will be */
+ /* copied to a new input stream object. The object will be closed */
+ /* and destroyed when the face is destroyed itself. Note that this */
+ /* means that you should not close the stream before the library */
+ /* does! */
+ /* */
+ typedef struct FT_Open_Args_
+ {
+ FT_Open_Flags flags;
+ FT_Byte* memory_base;
+ FT_Long memory_size;
+ FT_String* pathname;
+ FT_Stream stream;
+ FT_Module driver;
+ FT_Int num_params;
+ FT_Parameter* params;
+
+ } FT_Open_Args;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Face */
+ /* */
+ /* <Description> */
+ /* Creates a new face object from a given resource and typeface index */
+ /* using a pathname to the font file. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to the library resource. */
+ /* */
+ /* <Input> */
+ /* pathname :: A path to the font file. */
+ /* */
+ /* face_index :: The index of the face within the resource. The */
+ /* first face has index 0. */
+ /* <Output> */
+ /* aface :: A handle to a new face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Unlike FreeType 1.x, this function automatically creates a glyph */
+ /* slot for the face object which can be accessed directly through */
+ /* `face->glyph'. */
+ /* */
+ /* Note that additional slots can be added to each face with the */
+ /* FT_New_GlyphSlot() API function. Slots are linked in a single */
+ /* list through their `next' field. */
+ /* */
+ /* FT_New_Face() can be used to determine and/or check the font */
+ /* format of a given font resource. If the `face_index' field is */
+ /* negative, the function will _not_ return any face handle in */
+ /* `*face'. Its return value should be 0 if the resource is */
+ /* recognized, or non-zero if not. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_New_Face( FT_Library library,
+ const char* filepathname,
+ FT_Long face_index,
+ FT_Face* face );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Memory_Face */
+ /* */
+ /* <Description> */
+ /* Creates a new face object from a given resource and typeface index */
+ /* using a font file already loaded into memory. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to the library resource. */
+ /* */
+ /* <Input> */
+ /* file_base :: A pointer to the beginning of the font data. */
+ /* */
+ /* file_size :: The size of the memory chunk used by the font data. */
+ /* */
+ /* face_index :: The index of the face within the resource. The */
+ /* first face has index 0. */
+ /* <Output> */
+ /* face :: A handle to a new face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Unlike FreeType 1.x, this function automatically creates a glyph */
+ /* slot for the face object which can be accessed directly through */
+ /* `face->glyph'. */
+ /* */
+ /* Note that additional slots can be added to each face with the */
+ /* FT_New_GlyphSlot() API function. Slots are linked in a single */
+ /* list through their `next' field. */
+ /* */
+ /* FT_New_Memory_Face() can be used to determine and/or check the */
+ /* font format of a given font resource. If the `face_index' field */
+ /* is negative, the function will _not_ return any face handle in */
+ /* `*face'. Its return value should be 0 if the resource is */
+ /* recognized, or non-zero if not. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_New_Memory_Face( FT_Library library,
+ FT_Byte* file_base,
+ FT_Long file_size,
+ FT_Long face_index,
+ FT_Face* face );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Open_Face */
+ /* */
+ /* <Description> */
+ /* Opens a face object from a given resource and typeface index using */
+ /* an `FT_Open_Args' structure. If the face object doesn't exist, it */
+ /* will be created. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to the library resource. */
+ /* */
+ /* <Input> */
+ /* args :: A pointer to an `FT_Open_Args' structure which must */
+ /* be filled by the caller. */
+ /* */
+ /* face_index :: The index of the face within the resource. The */
+ /* first face has index 0. */
+ /* <Output> */
+ /* aface :: A handle to a new face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Unlike FreeType 1.x, this function automatically creates a glyph */
+ /* slot for the face object which can be accessed directly through */
+ /* `face->glyph'. */
+ /* */
+ /* Note that additional slots can be added to each face with the */
+ /* FT_New_GlyphSlot() API function. Slots are linked in a single */
+ /* list through their `next' field. */
+ /* */
+ /* FT_Open_Face() can be used to determine and/or check the font */
+ /* format of a given font resource. If the `face_index' field is */
+ /* negative, the function will _not_ return any face handle in */
+ /* `*face'. Its return value should be 0 if the resource is */
+ /* recognized, or non-zero if not. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Open_Face( FT_Library library,
+ FT_Open_Args* args,
+ FT_Long face_index,
+ FT_Face* face );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Attach_File */
+ /* */
+ /* <Description> */
+ /* `Attaches' a given font file to an existing face. This is usually */
+ /* to read additional information for a single face object. For */
+ /* example, it is used to read the AFM files that come with Type 1 */
+ /* fonts in order to add kerning data and other metrics. */
+ /* */
+ /* <InOut> */
+ /* face :: The target face object. */
+ /* */
+ /* <Input> */
+ /* filepathname :: An 8-bit pathname naming the `metrics' file. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* If your font file is in memory, or if you want to provide your */
+ /* own input stream object, use FT_Attach_Stream(). */
+ /* */
+ /* The meaning of the `attach' action (i.e., what really happens when */
+ /* the new file is read) is not fixed by FreeType itself. It really */
+ /* depends on the font format (and thus the font driver). */
+ /* */
+ /* Client applications are expected to know what they are doing */
+ /* when invoking this function. Most drivers simply do not implement */
+ /* file attachments. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Attach_File( FT_Face face,
+ const char* filepathname );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Attach_Stream */
+ /* */
+ /* <Description> */
+ /* This function is similar to FT_Attach_File() with the exception */
+ /* that it reads the attachment from an arbitrary stream. */
+ /* */
+ /* <Input> */
+ /* face :: The target face object. */
+ /* */
+ /* parameters :: A pointer to an FT_Open_Args structure used to */
+ /* describe the input stream to FreeType. */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The meaning of the `attach' (i.e. what really happens when the */
+ /* new file is read) is not fixed by FreeType itself. It really */
+ /* depends on the font format (and thus the font driver). */
+ /* */
+ /* Client applications are expected to know what they are doing */
+ /* when invoking this function. Most drivers simply do not implement */
+ /* file attachments. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Attach_Stream( FT_Face face,
+ FT_Open_Args* parameters );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_Face */
+ /* */
+ /* <Description> */
+ /* Discards a given face object, as well as all of its child slots */
+ /* and sizes. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a target face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Done_Face( FT_Face face );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Char_Size */
+ /* */
+ /* <Description> */
+ /* Sets the character dimensions of a given face object. The */
+ /* `char_width' and `char_height' values are used for the width and */
+ /* height, respectively, expressed in 26.6 fractional points. */
+ /* */
+ /* If the horizontal or vertical resolution values are zero, a */
+ /* default value of 72dpi is used. Similarly, if one of the */
+ /* character dimensions is zero, its value is set equal to the other. */
+ /* */
+ /* <InOut> */
+ /* size :: A handle to a target size object. */
+ /* */
+ /* <Input> */
+ /* char_width :: The character width, in 26.6 fractional points. */
+ /* */
+ /* char_height :: The character height, in 26.6 fractional */
+ /* points. */
+ /* */
+ /* horz_resolution :: The horizontal resolution. */
+ /* */
+ /* vert_resolution :: The vertical resolution. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* When dealing with fixed-size faces (i.e., non-scalable formats), */
+ /* use the function FT_Set_Pixel_Sizes(). */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Set_Char_Size( FT_Face face,
+ FT_F26Dot6 char_width,
+ FT_F26Dot6 char_height,
+ FT_UInt horz_resolution,
+ FT_UInt vert_resolution );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Pixel_Sizes */
+ /* */
+ /* <Description> */
+ /* Sets the character dimensions of a given face object. The width */
+ /* and height are expressed in integer pixels. */
+ /* */
+ /* If one of the character dimensions is zero, its value is set equal */
+ /* to the other. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* <Input> */
+ /* pixel_width :: The character width, in integer pixels. */
+ /* */
+ /* pixel_height :: The character height, in integer pixels. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Set_Pixel_Sizes( FT_Face face,
+ FT_UInt pixel_width,
+ FT_UInt pixel_height );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Load_Glyph */
+ /* */
+ /* <Description> */
+ /* A function used to load a single glyph within a given glyph slot, */
+ /* for a given size. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object where the glyph */
+ /* will be loaded. */
+ /* */
+ /* glyph_index :: The index of the glyph in the font file. */
+ /* */
+ /* load_flags :: A flag indicating what to load for this glyph. The */
+ /* FT_LOAD_XXX constants can be used to control the */
+ /* glyph loading process (e.g., whether the outline */
+ /* should be scaled, whether to load bitmaps or not, */
+ /* whether to hint the outline, etc). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* If the glyph image is not a bitmap, and if the bit flag */
+ /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */
+ /* transformed with the information passed to a previous call to */
+ /* FT_Set_Transform. */
+ /* */
+ /* Note that this also transforms the `face.glyph.advance' field, but */
+ /* *not* the values in `face.glyph.metrics'. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Load_Glyph( FT_Face face,
+ FT_UInt glyph_index,
+ FT_Int load_flags );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Load_Char */
+ /* */
+ /* <Description> */
+ /* A function used to load a single glyph within a given glyph slot, */
+ /* for a given size, according to its character code. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a target face object where the glyph */
+ /* will be loaded. */
+ /* */
+ /* char_code :: The glyph's character code, according to the */
+ /* current charmap used in the face. */
+ /* */
+ /* load_flags :: A flag indicating what to load for this glyph. The */
+ /* FT_LOAD_XXX constants can be used to control the */
+ /* glyph loading process (e.g., whether the outline */
+ /* should be scaled, whether to load bitmaps or not, */
+ /* whether to hint the outline, etc). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* If the face has no current charmap, or if the character code */
+ /* is not defined in the charmap, this function will return an */
+ /* error. */
+ /* */
+ /* If the glyph image is not a bitmap, and if the bit flag */
+ /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */
+ /* transformed with the information passed to a previous call to */
+ /* FT_Set_Transform(). */
+ /* */
+ /* Note that this also transforms the `face.glyph.advance' field, but */
+ /* *not* the values in `face.glyph.metrics'. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Load_Char( FT_Face face,
+ FT_ULong char_code,
+ FT_Int load_flags );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_NO_SCALE */
+ /* */
+ /* <Description> */
+ /* A bit field constant, used with FT_Load_Glyph() to indicate that */
+ /* the vector outline being loaded should not be scaled to 26.6 */
+ /* fractional pixels, but kept in notional units. */
+ /* */
+#define FT_LOAD_NO_SCALE 1
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_NO_HINTING */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used with FT_Load_Glyph() to indicate that */
+ /* the vector outline being loaded should not be fitted to the pixel */
+ /* grid but simply scaled to 26.6 fractional pixels. */
+ /* */
+ /* This flag is ignored if FT_LOAD_NO_SCALE is set. */
+ /* */
+#define FT_LOAD_NO_HINTING 2
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_RENDER */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used with FT_Load_Glyph() to indicate that */
+ /* the function should load the glyph and immediately convert it into */
+ /* a bitmap, if necessary, by calling FT_Render_Glyph(). */
+ /* */
+ /* Note that by default, FT_Load_Glyph() loads the glyph image in its */
+ /* native format. */
+ /* */
+#define FT_LOAD_RENDER 4
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_NO_BITMAP */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used with FT_Load_Glyph() to indicate that */
+ /* the function should not load the bitmap or pixmap of a given */
+ /* glyph. This is useful when you do not want to load the embedded */
+ /* bitmaps of scalable formats, as the native glyph image will be */
+ /* loaded, and can then be rendered through FT_Render_Glyph(). */
+ /* */
+#define FT_LOAD_NO_BITMAP 8
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_VERTICAL_LAYOUT */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used with FT_Load_Glyph() to indicate that */
+ /* the glyph image should be prepared for vertical layout. This */
+ /* basically means that `face.glyph.advance' will correspond to the */
+ /* vertical advance height (instead of the default horizontal */
+ /* advance width), and that the glyph image will translated to match */
+ /* the vertical bearings positions. */
+ /* */
+#define FT_LOAD_VERTICAL_LAYOUT 16
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_FORCE_AUTOHINT */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used with FT_Load_Glyph() to indicate that */
+ /* the function should try to auto-hint the glyphs, even if a driver */
+ /* specific hinter is available. */
+ /* */
+#define FT_LOAD_FORCE_AUTOHINT 32
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_CROP_BITMAP */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used with FT_Load_Glyph() to indicate that */
+ /* the font driver should try to crop the bitmap (i.e. remove all */
+ /* space around its black bits) when loading it. For now, this */
+ /* really only works with embedded bitmaps in TrueType fonts. */
+ /* */
+#define FT_LOAD_CROP_BITMAP 64
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_PEDANTIC */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used with FT_Load_Glyph() to indicate that */
+ /* the glyph loader should perform a pedantic bytecode */
+ /* interpretation. Many popular fonts come with broken glyph */
+ /* programs. When this flag is set, loading them will return an */
+ /* error. Otherwise, errors are ignored by the loader, sometimes */
+ /* resulting in ugly glyphs. */
+ /* */
+#define FT_LOAD_PEDANTIC 128
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used with FT_Load_Glyph() to indicate that */
+ /* the glyph loader should ignore the global advance width defined */
+ /* in the font. As far as we know, this is only used by the */
+ /* X-TrueType font server, in order to deal correctly with the */
+ /* incorrect metrics contained in DynaLab's TrueType CJK fonts. */
+ /* */
+#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH 512
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_NO_RECURSE */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used with FT_Load_Glyph() to indicate that */
+ /* the glyph loader should not load composite glyph recursively. */
+ /* Rather, when a composite glyph is encountered, it should set */
+ /* the values of `num_subglyphs' and `subglyphs', as well as set */
+ /* `face->glyph.format' to ft_glyph_format_composite. */
+ /* */
+ /* This is for use by the auto-hinter and possibly other tools. */
+ /* For nearly all applications, this flags should be left unset */
+ /* when invoking FT_Load_Glyph(). */
+ /* */
+ /* Note that the flag forces the load of unscaled glyphs. */
+ /* */
+#define FT_LOAD_NO_RECURSE 1024
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_IGNORE_TRANSFORM */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used with FT_Load_Glyph() to indicate that */
+ /* the glyph loader should not try to transform the loaded glyph */
+ /* image. */
+ /* */
+#define FT_LOAD_IGNORE_TRANSFORM 2048
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_MONOCHROME */
+ /* */
+ /* <Description> */
+ /* Only used with FT_LOAD_RENDER set, it indicates that the returned */
+ /* glyph image should be 1-bit monochrome. This really tells the */
+ /* glyph loader to use `ft_render_mode_mono' when calling */
+ /* FT_Render_Glyph(). */
+ /* */
+#define FT_LOAD_MONOCHROME 4096
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_LINEAR_DESIGN */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used with FT_Load_Glyph() to indicate that */
+ /* the function should return the linearly scaled metrics expressed */
+ /* in original font units, instead of the default 16.16 pixel values. */
+ /* */
+#define FT_LOAD_LINEAR_DESIGN 8192
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_DEFAULT */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used with FT_Load_Glyph() to indicate that */
+ /* the function should try to load the glyph normally, i.e., */
+ /* embedded bitmaps are favored over outlines, vectors are always */
+ /* scaled and grid-fitted. */
+ /* */
+#define FT_LOAD_DEFAULT 0
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Transform */
+ /* */
+ /* <Description> */
+ /* A function used to set the transformation that is applied to glyph */
+ /* images just before they are converted to bitmaps in a glyph slot */
+ /* when FT_Render_Glyph() is called. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* <Input> */
+ /* matrix :: A pointer to the transformation's 2x2 matrix. Use 0 for */
+ /* the identity matrix. */
+ /* delta :: A pointer to the translation vector. Use 0 for the null */
+ /* vector. */
+ /* */
+ /* <Note> */
+ /* The transformation is only applied to scalable image formats after */
+ /* the glyph has been loaded. It means that hinting is unaltered by */
+ /* the transformation and is performed on the character size given in */
+ /* the last call to FT_Set_Char_Sizes() or FT_Set_Pixel_Sizes(). */
+ /* */
+ FT_EXPORT_DEF( void ) FT_Set_Transform( FT_Face face,
+ FT_Matrix* matrix,
+ FT_Vector* delta );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Render_Mode */
+ /* */
+ /* <Description> */
+ /* An enumeration type that lists the render modes supported by the */
+ /* FreeType 2 renderer(s). A renderer is in charge of converting a */
+ /* glyph image into a bitmap. */
+ /* */
+ /* <Fields> */
+ /* ft_render_mode_normal :: This is the default render mode; it */
+ /* corresponds to 8-bit anti-aliased */
+ /* bitmaps, using 256 levels of gray. */
+ /* */
+ /* ft_render_mode_mono :: This render mode is used to produce 1-bit */
+ /* monochrome bitmaps. */
+ /* */
+ /* <Note> */
+ /* There is no render mode to produce 8-bit `monochrome' bitmaps -- */
+ /* you have to make the conversion yourself if you need such things */
+ /* (besides, FreeType is not a graphics library). */
+ /* */
+ /* More modes might appear later for specific display modes (e.g. TV, */
+ /* LCDs, etc.). They will be supported through the simple addition */
+ /* of a renderer module, with no changes to the rest of the engine. */
+ /* */
+ typedef enum FT_Render_Mode_
+ {
+ ft_render_mode_normal = 0,
+ ft_render_mode_mono = 1
+
+ } FT_Render_Mode;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Render_Glyph */
+ /* */
+ /* <Description> */
+ /* Converts a given glyph image to a bitmap. It does so by */
+ /* inspecting the glyph image format, find the relevant renderer, and */
+ /* invoke it. */
+ /* */
+ /* <Input> */
+ /* slot :: A handle to the glyph slot containing the image to */
+ /* convert. */
+ /* */
+ /* render_mode :: This is the render mode used to render the glyph */
+ /* image into a bitmap. See FT_Render_Mode for a list */
+ /* of possible values. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Render_Glyph( FT_GlyphSlot slot,
+ FT_UInt render_mode );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Kerning_Mode */
+ /* */
+ /* <Description> */
+ /* An enumeration used to specify which kerning values to return in */
+ /* FT_Get_Kerning(). */
+ /* */
+ /* <Fields> */
+ /* ft_kerning_default :: Return scaled and grid-fitted kerning */
+ /* distances (value is 0). */
+ /* */
+ /* ft_kerning_unfitted :: Return scaled but un-grid-fitted kerning */
+ /* distances. */
+ /* */
+ /* ft_kerning_unscaled :: Return the kerning vector in original font */
+ /* units. */
+ /* */
+ typedef enum FT_Kerning_Mode_
+ {
+ ft_kerning_default = 0,
+ ft_kerning_unfitted,
+ ft_kerning_unscaled
+
+ } FT_Kerning_Mode;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Kerning */
+ /* */
+ /* <Description> */
+ /* Returns the kerning vector between two glyphs of a same face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a source face object. */
+ /* */
+ /* left_glyph :: The index of the left glyph in the kern pair. */
+ /* */
+ /* right_glyph :: The index of the right glyph in the kern pair. */
+ /* */
+ /* kern_mode :: See FT_Kerning_Mode() for more information. */
+ /* Determines the scale/dimension of the returned */
+ /* kerning vector. */
+ /* */
+ /* <Output> */
+ /* kerning :: The kerning vector. This is in font units for */
+ /* scalable formats, and in pixels for fixed-sizes */
+ /* formats. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only horizontal layouts (left-to-right & right-to-left) are */
+ /* supported by this method. Other layouts, or more sophisticated */
+ /* kernings, are out of the scope of this API function -- they can be */
+ /* implemented through format-specific interfaces. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Get_Kerning( FT_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_UInt kern_mode,
+ FT_Vector* kerning );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Glyph_Name */
+ /* */
+ /* <Description> */
+ /* Retrieves the ASCII name of a given glyph in a face. This only */
+ /* works for those faces where FT_HAS_GLYPH_NAME(face) returns true. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a source face object. */
+ /* */
+ /* glyph_index :: The glyph index. */
+ /* */
+ /* buffer :: A pointer to a target buffer where the name will be */
+ /* copied to. */
+ /* */
+ /* buffer_max :: The maximal number of bytes available in the */
+ /* buffer. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* An error is returned if the face doesn't provide glyph names or if */
+ /* the glyph index is invalid. In all cases of failure, the first */
+ /* byte of `buffer' will be set to 0 to indicate an empty name. */
+ /* */
+ /* The glyph name is truncated to fit within the buffer if it is too */
+ /* long. The returned string is always zero-terminated. */
+ /* */
+ /* This function is not compiled within the library if the config */
+ /* macro FT_CONFIG_OPTION_NO_GLYPH_NAMES is defined in */
+ /* `include/freetype/config/ftoptions.h' */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Get_Glyph_Name( FT_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Select_Charmap */
+ /* */
+ /* <Description> */
+ /* Selects a given charmap by its encoding tag (as listed in */
+ /* `freetype.h'). */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* encoding :: A handle to the selected charmap. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function will return an error if no charmap in the face */
+ /* corresponds to the encoding queried here. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Select_Charmap( FT_Face face,
+ FT_Encoding encoding );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Charmap */
+ /* */
+ /* <Description> */
+ /* Selects a given charmap for character code to glyph index */
+ /* decoding. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* charmap :: A handle to the selected charmap. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function will return an error if the charmap is not part of */
+ /* the face (i.e., if it is not listed in the face->charmaps[] */
+ /* table). */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Set_Charmap( FT_Face face,
+ FT_CharMap charmap );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Char_Index */
+ /* */
+ /* <Description> */
+ /* Returns the glyph index of a given character code. This function */
+ /* uses a charmap object to do the translation. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* charcode :: The character code. */
+ /* */
+ /* <Return> */
+ /* The glyph index. 0 means `undefined character code'. */
+ /* */
+ FT_EXPORT_DEF( FT_UInt ) FT_Get_Char_Index( FT_Face face,
+ FT_ULong charcode );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_MulDiv */
+ /* */
+ /* <Description> */
+ /* A very simple function used to perform the computation `(a*b)/c' */
+ /* with maximal accuracy (it uses a 64-bit intermediate integer */
+ /* whenever necessary). */
+ /* */
+ /* This function isn't necessarily as fast as some processor specific */
+ /* operations, but is at least completely portable. */
+ /* */
+ /* <Input> */
+ /* a :: The first multiplier. */
+ /* b :: The second multiplier. */
+ /* c :: The divisor. */
+ /* */
+ /* <Return> */
+ /* The result of `(a*b)/c'. This function never traps when trying to */
+ /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */
+ /* on the signs of `a' and `b'. */
+ /* */
+ FT_EXPORT_DEF( FT_Long ) FT_MulDiv( FT_Long a,
+ FT_Long b,
+ FT_Long c );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_MulFix */
+ /* */
+ /* <Description> */
+ /* A very simple function used to perform the computation */
+ /* `(a*b)/0x10000' with maximal accuracy. Most of the time this is */
+ /* used to multiply a given value by a 16.16 fixed float factor. */
+ /* */
+ /* <Input> */
+ /* a :: The first multiplier. */
+ /* b :: The second multiplier. Use a 16.16 factor here whenever */
+ /* possible (see note below). */
+ /* */
+ /* <Return> */
+ /* The result of `(a*b)/0x10000'. */
+ /* */
+ /* <Note> */
+ /* This function has been optimized for the case where the absolute */
+ /* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */
+ /* As this happens mainly when scaling from notional units to */
+ /* fractional pixels in FreeType, it resulted in noticeable speed */
+ /* improvements between versions 2.x and 1.x. */
+ /* */
+ /* As a conclusion, always try to place a 16.16 factor as the */
+ /* _second_ argument of this function; this can make a great */
+ /* difference. */
+ /* */
+ FT_EXPORT_DEF( FT_Long ) FT_MulFix( FT_Long a,
+ FT_Long b );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_DivFix */
+ /* */
+ /* <Description> */
+ /* A very simple function used to perform the computation */
+ /* `(a*0x10000)/b' with maximal accuracy. Most of the time, this is */
+ /* used to divide a given value by a 16.16 fixed float factor. */
+ /* */
+ /* <Input> */
+ /* a :: The first multiplier. */
+ /* b :: The second multiplier. Use a 16.16 factor here whenever */
+ /* possible (see note below). */
+ /* */
+ /* <Return> */
+ /* The result of `(a*0x10000)/b'. */
+ /* */
+ /* <Note> */
+ /* The optimization for FT_DivFix() is simple: If (a << 16) fits in */
+ /* 32 bits, then the division is computed directly. Otherwise, we */
+ /* use a specialized version of the old FT_MulDiv64(). */
+ /* */
+ FT_EXPORT_DEF( FT_Long ) FT_DivFix( FT_Long a,
+ FT_Long b );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Vector_Transform */
+ /* */
+ /* <Description> */
+ /* Transforms a single vector through a 2x2 matrix. */
+ /* */
+ /* <InOut> */
+ /* vector :: The target vector to transform. */
+ /* */
+ /* <Input> */
+ /* matrix :: A pointer to the source 2x2 matrix. */
+ /* */
+ /* <MT-Note> */
+ /* Yes. */
+ /* */
+ /* <Note> */
+ /* The result is undefined if either `vector' or `matrix' is invalid. */
+ /* */
+ FT_EXPORT_DEF( void ) FT_Vector_Transform( FT_Vector* vec,
+ FT_Matrix* matrix );
+
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* FREETYPE_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftbbox.h */
+/* */
+/* FreeType bbox computation (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This component has a _single_ role: to compute exact outline bounding */
+ /* boxes. */
+ /* */
+ /* It is separated from the rest of the engine for various technical */
+ /* reasons. It may well be integrated in `ftoutln' later. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef FTBBOX_H
+#define FTBBOX_H
+
+#include <freetype/freetype.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Raster_GetBBox */
+ /* */
+ /* <Description> */
+ /* Computes the exact bounding box of an outline. This is slower */
+ /* than computing the control box. However, it uses an advanced */
+ /* algorithm which returns _very_ quickly when the two boxes */
+ /* coincide. Otherwise, the outline Bezier arcs are walked over to */
+ /* extract their extrema. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the source outline. */
+ /* */
+ /* <Output> */
+ /* bbox :: The outline's exact bounding box. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means success. */
+ /* */
+ FT_EXPORT_DEF(FT_Error) FT_Raster_GetBBox( FT_Outline* outline,
+ FT_BBox* abbox );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* FTBBOX_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* fterrors.h */
+/* */
+/* FreeType error codes (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the FreeType error enumeration constants */
+ /* It can also be used to create an error message table easily with */
+ /* something like: */
+ /* */
+ /* { */
+ /* #undef FTERRORS_H */
+ /* #define FT_ERRORDEF( e, v, s ) { e, s }, */
+ /* #define FT_ERROR_START_LIST { */
+ /* #define FT_ERROR_END_LIST { 0, 0 } }; */
+ /* */
+ /* const struct */
+ /* { */
+ /* int err_code; */
+ /* const char* err_msg */
+ /* } ft_errors[] = */
+ /* */
+ /* #include <freetype/fterrors.h> */
+ /* } */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef FTERRORS_H
+#define FTERRORS_H
+
+
+#ifndef FT_ERRORDEF
+
+#define FT_ERRORDEF( e, v, s ) e = v,
+#define FT_ERROR_START_LIST enum {
+#define FT_ERROR_END_LIST FT_Err_Max };
+
+#endif /* !FT_ERRORDEF */
+
+
+#ifdef FT_ERROR_START_LIST
+ FT_ERROR_START_LIST
+#endif
+
+ FT_ERRORDEF( FT_Err_Ok, 0x0000, \
+ "no error" )
+ FT_ERRORDEF( FT_Err_Cannot_Open_Resource, 0x0001, \
+ "can't open stream" )
+ FT_ERRORDEF( FT_Err_Unknown_File_Format, 0x0002, \
+ "unknown file format" )
+ FT_ERRORDEF( FT_Err_Invalid_File_Format, 0x0003, \
+ "broken file" )
+
+ FT_ERRORDEF( FT_Err_Invalid_Argument, 0x0010, \
+ "invalid argument" )
+ FT_ERRORDEF( FT_Err_Invalid_Handle, 0x0011, \
+ "invalid object handle" )
+ FT_ERRORDEF( FT_Err_Invalid_Glyph_Index, 0x0012, \
+ "invalid glyph index" )
+ FT_ERRORDEF( FT_Err_Invalid_Character_Code, 0x0013, \
+ "invalid character code" )
+
+ FT_ERRORDEF( FT_Err_Unimplemented_Feature, 0x0020, \
+ "unimplemented feature" )
+ FT_ERRORDEF( FT_Err_Invalid_Glyph_Format, 0x0021, \
+ "unsupported glyph image format" )
+ FT_ERRORDEF( FT_Err_Cannot_Render_Glyph, 0x0022, \
+ "cannot render this glyph format" )
+
+ FT_ERRORDEF( FT_Err_Invalid_Library_Handle, 0x0030, \
+ "invalid library handle" )
+ FT_ERRORDEF( FT_Err_Invalid_Driver_Handle, 0x0031, \
+ "invalid module handle" )
+ FT_ERRORDEF( FT_Err_Invalid_Face_Handle, 0x0032, \
+ "invalid face handle" )
+ FT_ERRORDEF( FT_Err_Invalid_Size_Handle, 0x0033, \
+ "invalid size handle" )
+ FT_ERRORDEF( FT_Err_Invalid_Slot_Handle, 0x0034, \
+ "invalid glyph slot handle" )
+ FT_ERRORDEF( FT_Err_Invalid_CharMap_Handle, 0x0035, \
+ "invalid charmap handle" )
+ FT_ERRORDEF( FT_Err_Invalid_Outline, 0x0036, \
+ "invalid outline" )
+ FT_ERRORDEF( FT_Err_Invalid_Version, 0x0037, \
+ "invalid FreeType version" )
+ FT_ERRORDEF( FT_Err_Lower_Module_Version, 0x0038, \
+ "module version is too low" )
+
+ FT_ERRORDEF( FT_Err_Too_Many_Drivers, 0x0040, \
+ "too many modules" )
+ FT_ERRORDEF( FT_Err_Too_Many_Extensions, 0x0041, \
+ "too many extensions" )
+
+ FT_ERRORDEF( FT_Err_Out_Of_Memory, 0x0050, \
+ "out of memory" )
+ FT_ERRORDEF( FT_Err_Unlisted_Object, 0x0051, \
+ "unlisted object" )
+
+ FT_ERRORDEF( FT_Err_Invalid_Stream_Handle, 0x0060, \
+ "invalid stream handle" )
+ FT_ERRORDEF( FT_Err_Cannot_Open_Stream, 0x0061, \
+ "cannot open stream" )
+ FT_ERRORDEF( FT_Err_Invalid_Stream_Seek, 0x0062, \
+ "invalid stream seek" )
+ FT_ERRORDEF( FT_Err_Invalid_Stream_Skip, 0x0063, \
+ "invalid stream skip" )
+ FT_ERRORDEF( FT_Err_Invalid_Stream_Read, 0x0064, \
+ "invalid stream read" )
+ FT_ERRORDEF( FT_Err_Invalid_Stream_Operation, 0x0065, \
+ "invalid stream operation" )
+ FT_ERRORDEF( FT_Err_Invalid_Frame_Operation, 0x0066, \
+ "invalid frame operation" )
+ FT_ERRORDEF( FT_Err_Nested_Frame_Access, 0x0067, \
+ "nested frame access" )
+ FT_ERRORDEF( FT_Err_Invalid_Frame_Read, 0x0068, \
+ "invalid frame read" )
+
+ FT_ERRORDEF( FT_Err_Invalid_Composite, 0x0070, \
+ "invalid composite glyph" )
+ FT_ERRORDEF( FT_Err_Too_Many_Hints, 0x0071, \
+ "too many hints" )
+
+ FT_ERRORDEF( FT_Err_Raster_Uninitialized, 0x0080, \
+ "raster uninitialized" )
+ FT_ERRORDEF( FT_Err_Raster_Corrupted, 0x0081, \
+ "raster corrupted" )
+ FT_ERRORDEF( FT_Err_Raster_Overflow, 0x0082, \
+ "raster overflow" )
+ FT_ERRORDEF( FT_Err_Raster_Negative_Height, 0x0083, \
+ "negative height while rastering" )
+
+ /* range 0x400 - 0x4FF is reserved for TrueType specific stuff */
+
+ /* range 0x500 - 0x5FF is reserved for CFF specific stuff */
+
+ /* range 0x600 - 0x6FF is reserved for Type1 specific stuff */
+
+#ifdef FT_ERROR_END_LIST
+ FT_ERROR_END_LIST
+#endif
+
+
+#undef FT_ERROR_START_LIST
+#undef FT_ERROR_END_LIST
+#undef FT_ERRORDEF
+
+
+#endif /* FTERRORS_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftglyph.h */
+/* */
+/* FreeType convenience functions to handle glyphs (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file contains the definition of several convenience functions */
+ /* that can be used by client applications to easily retrieve glyph */
+ /* bitmaps and outlines from a given face. */
+ /* */
+ /* These functions should be optional if you are writing a font server */
+ /* or text layout engine on top of FreeType. However, they are pretty */
+ /* handy for many other simple uses of the library. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef FTGLYPH_H
+#define FTGLYPH_H
+
+#include <freetype/freetype.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+ /* forward declaration to a private type */
+ typedef struct FT_Glyph_Class_ FT_Glyph_Class;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_GlyphRec */
+ /* */
+ /* <Description> */
+ /* The root glyph structure contains a given glyph image plus its */
+ /* advance width in 16.16 fixed float format. */
+ /* */
+ /* <Fields> */
+ /* library :: A handle to the FreeType library object. */
+ /* */
+ /* clazz :: A pointer to the glyph's class. Private. */
+ /* */
+ /* format :: The format of the glyph's image. */
+ /* */
+ /* advance :: A 16.16 vector that gives the glyph's advance width. */
+ /* */
+ typedef struct FT_GlyphRec_
+ {
+ FT_Library library;
+ const FT_Glyph_Class* clazz;
+ FT_Glyph_Format format;
+ FT_Vector advance;
+
+ } FT_GlyphRec, *FT_Glyph;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_BitmapGlyphRec */
+ /* */
+ /* <Description> */
+ /* A structure used for bitmap glyph images. This really is a */
+ /* `sub-class' of `FT_GlyphRec'. */
+ /* */
+ /* <Fields> */
+ /* root :: The root FT_Glyph fields. */
+ /* */
+ /* left :: The left-side bearing, i.e., the horizontal distance */
+ /* from the current pen position to the left border of the */
+ /* glyph bitmap. */
+ /* */
+ /* top :: The top-side bearing, i.e., the vertical distance from */
+ /* the current pen position to the top border of the glyph */
+ /* bitmap. This distance is positive for upwards-y! */
+ /* */
+ /* bitmap :: A descriptor for the bitmap. */
+ /* */
+ /* <Note> */
+ /* You can typecast FT_Glyph to FT_BitmapGlyph if you have */
+ /* glyph->format == ft_glyph_format_bitmap. This lets you access */
+ /* the bitmap's contents easily. */
+ /* */
+ /* The corresponding pixel buffer is always owned by the BitmapGlyph */
+ /* and is thus created and destroyed with it. */
+ /* */
+ typedef struct FT_BitmapGlyphRec_
+ {
+ FT_GlyphRec root;
+ FT_Int left;
+ FT_Int top;
+ FT_Bitmap bitmap;
+
+ } FT_BitmapGlyphRec, *FT_BitmapGlyph;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_OutlineGlyphRec */
+ /* */
+ /* <Description> */
+ /* A structure used for outline (vectorial) glyph images. This */
+ /* really is a `sub-class' of `FT_GlyphRec'. */
+ /* */
+ /* <Fields> */
+ /* root :: The root FT_Glyph fields. */
+ /* */
+ /* outline :: A descriptor for the outline. */
+ /* */
+ /* <Note> */
+ /* You can typecast FT_Glyph to FT_OutlineGlyph if you have */
+ /* glyph->format == ft_glyph_format_outline. This lets you access */
+ /* the outline's content easily. */
+ /* */
+ /* As the outline is extracted from a glyph slot, its coordinates are */
+ /* expressed normally in 26.6 pixels, unless the flag */
+ /* FT_LOAD_NO_SCALE was used in FT_Load_Glyph() or FT_Load_Char(). */
+ /* */
+ /* The outline's tables are always owned by the object and are */
+ /* destroyed with it. */
+ /* */
+ typedef struct FT_OutlineGlyphRec_
+ {
+ FT_GlyphRec root;
+ FT_Outline outline;
+
+ } FT_OutlineGlyphRec, *FT_OutlineGlyph;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Glyph */
+ /* */
+ /* <Description> */
+ /* A function used to extract a glyph image from a slot. */
+ /* */
+ /* <Input> */
+ /* slot :: A handle to the source glyph slot. */
+ /* */
+ /* <Output> */
+ /* aglyph :: A handle to the glyph object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Get_Glyph( FT_GlyphSlot slot,
+ FT_Glyph* aglyph );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Glyph_Copy */
+ /* */
+ /* <Description> */
+ /* A function used to copy a glyph image. */
+ /* */
+ /* <Input> */
+ /* source :: A handle to the source glyph object. */
+ /* */
+ /* <Output> */
+ /* target :: A handle to the target glyph object. 0 in case of */
+ /* error. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Glyph_Copy( FT_Glyph source,
+ FT_Glyph* target );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Glyph_Transform */
+ /* */
+ /* <Description> */
+ /* Transforms a glyph image if its format is scalable. */
+ /* */
+ /* <Input> */
+ /* glyph :: A handle to the target glyph object. */
+ /* */
+ /* matrix :: A pointer to a 2x2 matrix to apply. */
+ /* */
+ /* delta :: A pointer to a 2d vector to apply. Coordinates are */
+ /* expressed in 1/64th of a pixel. */
+ /* */
+ /* <Return> */
+ /* FreeType error code (the glyph format is not scalable if it is */
+ /* not zero). */
+ /* */
+ /* <Note> */
+ /* The 2x2 transformation matrix is also applied to the glyph's */
+ /* advance vector. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Glyph_Transform( FT_Glyph glyph,
+ FT_Matrix* matrix,
+ FT_Vector* delta );
+
+
+ enum
+ {
+ ft_glyph_bbox_pixels = 0,
+ ft_glyph_bbox_subpixels = 1,
+ ft_glyph_bbox_gridfit = 2
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Glyph_Get_CBox */
+ /* */
+ /* <Description> */
+ /* Returns the glyph image's bounding box. */
+ /* */
+ /* <Input> */
+ /* glyph :: A handle to the source glyph object. */
+ /* */
+ /* mode :: A set of bit flags that indicate how to interpret the */
+ /* returned bounding box values. */
+ /* */
+ /* <Output> */
+ /* box :: The glyph bounding box. Coordinates are expressed in */
+ /* 1/64th of pixels if it is grid-fitted. */
+ /* */
+ /* <Note> */
+ /* Coordinates are relative to the glyph origin, using the Y-upwards */
+ /* convention. */
+ /* */
+ /* If `ft_glyph_bbox_subpixels' is set in `mode', the bbox */
+ /* coordinates are returned in 26.6 pixels (i.e. 1/64th of pixels). */
+ /* Otherwise, coordinates are expressed in integer pixels. */
+ /* */
+ /* Note that the maximum coordinates are exclusive, which means that */
+ /* one can compute the width and height of the glyph image (be it in */
+ /* integer or 26.6 pixels) as: */
+ /* */
+ /* width = bbox.xMax - bbox.xMin; */
+ /* height = bbox.yMax - bbox.yMin; */
+ /* */
+ /* Note also that for 26.6 coordinates, if the */
+ /* `ft_glyph_bbox_gridfit' flag is set in `mode;, the coordinates */
+ /* will also be grid-fitted, which corresponds to: */
+ /* */
+ /* bbox.xMin = FLOOR(bbox.xMin); */
+ /* bbox.yMin = FLOOR(bbox.yMin); */
+ /* bbox.xMax = CEILING(bbox.xMax); */
+ /* bbox.yMax = CEILING(bbox.yMax); */
+ /* */
+ /* The default value (0) for `bbox_mode' is `ft_glyph_bbox_pixels'. */
+ /* */
+ FT_EXPORT_DEF( void ) FT_Glyph_Get_CBox( FT_Glyph glyph,
+ FT_UInt bbox_mode,
+ FT_BBox* cbox );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Glyph_To_Bitmap */
+ /* */
+ /* <Description> */
+ /* Converts a given glyph object to a bitmap glyph object. */
+ /* */
+ /* <InOut> */
+ /* glyph :: A pointer to a handle to the target glyph. */
+ /* */
+ /* <Input> */
+ /* render_mode :: A set of bit flags that describe how the data is */
+ /* */
+ /* */
+ /* origin :: A pointer to a vector used to translate the glyph */
+ /* image before rendering. Can be 0 (if no */
+ /* translation). The origin is expressed in */
+ /* 26.6 pixels. */
+ /* */
+ /* destroy :: A boolean that indicates that the original glyph */
+ /* image should be destroyed by this function. It is */
+ /* never destroyed in case of error. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The glyph image is translated with the `origin' vector before */
+ /* rendering. In case of error, it it translated back to its */
+ /* original position and the glyph is left untouched. */
+ /* */
+ /* The first parameter is a pointer to a FT_Glyph handle, that will */
+ /* be replaced by this function. Typically, you would use (omitting */
+ /* error handling): */
+ /* */
+ /* */
+ /* { */
+ /* FT_Glyph glyph; */
+ /* FT_BitmapGlyph glyph_bitmap; */
+ /* */
+ /* */
+ /* // load glyph */
+ /* error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT ); */
+ /* */
+ /* // extract glyph image */
+ /* error = FT_Get_Glyph( face->glyph, &glyph ); */
+ /* */
+ /* // convert to a bitmap (default render mode + destroy old) */
+ /* if ( glyph->format != ft_glyph_format_bitmap ) */
+ /* { */
+ /* error = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_default, */
+ /* 0, 1 ); */
+ /* if ( error ) // glyph unchanged */
+ /* ... */
+ /* } */
+ /* */
+ /* // access bitmap content by typecasting */
+ /* glyph_bitmap = (FT_BitmapGlyph)glyph; */
+ /* */
+ /* // do funny stuff with it, like blitting/drawing */
+ /* ... */
+ /* */
+ /* // discard glyph image (bitmap or not) */
+ /* FT_Done_Glyph( glyph ); */
+ /* } */
+ /* */
+ /* */
+ /* This function will always fail if the glyph's format isn't */
+ /* scalable. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Glyph_To_Bitmap( FT_Glyph* the_glyph,
+ FT_ULong render_mode,
+ FT_Vector* origin,
+ FT_Bool destroy );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_Glyph */
+ /* */
+ /* <Description> */
+ /* Destroys a given glyph. */
+ /* */
+ /* <Input> */
+ /* glyph :: A handle to the target glyph object. */
+ /* */
+ FT_EXPORT_DEF( void ) FT_Done_Glyph( FT_Glyph glyph );
+
+
+ /* other helpful functions */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Matrix_Multiply */
+ /* */
+ /* <Description> */
+ /* Performs the matrix operation `b = a*b'. */
+ /* */
+ /* <Input> */
+ /* a :: A pointer to matrix `a'. */
+ /* */
+ /* <InOut> */
+ /* b :: A pointer to matrix `b'. */
+ /* */
+ /* <MT-Note> */
+ /* Yes. */
+ /* */
+ /* <Note> */
+ /* The result is undefined if either `a' or `b' is zero. */
+ /* */
+ FT_EXPORT_DEF( void ) FT_Matrix_Multiply( FT_Matrix* a,
+ FT_Matrix* b );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Matrix_Invert */
+ /* */
+ /* <Description> */
+ /* Inverts a 2x2 matrix. Returns an error if it can't be inverted. */
+ /* */
+ /* <InOut> */
+ /* matrix :: A pointer to the target matrix. Remains untouched in */
+ /* case of error. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <MT-Note> */
+ /* Yes. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Matrix_Invert( FT_Matrix* matrix );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* FTGLYPH_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftimage.h */
+/* */
+/* FreeType glyph image formats and default raster interface */
+/* (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* Note: A `raster' is simply a scan-line converter, used to render */
+ /* FT_Outlines into FT_Bitmaps. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef FTIMAGE_H
+#define FTIMAGE_H
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Pos */
+ /* */
+ /* <Description> */
+ /* The type FT_Pos is a 32-bit integer used to store vectorial */
+ /* coordinates. Depending on the context, these can represent */
+ /* distances in integer font units, or 26.6 fixed float pixel */
+ /* coordinates. */
+ /* */
+ typedef signed long FT_Pos;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Vector */
+ /* */
+ /* <Description> */
+ /* A simple structure used to store a 2D vector; coordinates are of */
+ /* the FT_Pos type. */
+ /* */
+ /* <Fields> */
+ /* x :: The horizontal coordinate. */
+ /* y :: The vertical coordinate. */
+ /* */
+ typedef struct FT_Vector_
+ {
+ FT_Pos x;
+ FT_Pos y;
+
+ } FT_Vector;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Pixel_Mode */
+ /* */
+ /* <Description> */
+ /* An enumeration type used to describe the format of pixels in a */
+ /* given bitmap. Note that additional formats may be added in the */
+ /* future. */
+ /* */
+ /* <Fields> */
+ /* ft_pixel_mode_mono :: A monochrome bitmap (1 bit/pixel). */
+ /* */
+ /* ft_pixel_mode_grays :: An 8-bit gray-levels bitmap. Note that the */
+ /* total number of gray levels is given in the */
+ /* `num_grays' field of the FT_Bitmap */
+ /* structure. */
+ /* */
+ /* ft_pixel_mode_pal2 :: A 2-bit paletted bitmap. */
+ /* Currently unused by FreeType. */
+ /* */
+ /* ft_pixel_mode_pal4 :: A 4-bit paletted bitmap. */
+ /* Currently unused by FreeType. */
+ /* */
+ /* ft_pixel_mode_pal8 :: An 8-bit paletted bitmap. */
+ /* Currently unused by FreeType. */
+ /* */
+ /* ft_pixel_mode_rgb15 :: A 15-bit RGB bitmap. Uses 5:5:5 encoding. */
+ /* Currently unused by FreeType. */
+ /* */
+ /* ft_pixel_mode_rgb16 :: A 16-bit RGB bitmap. Uses 5:6:5 encoding. */
+ /* Currently unused by FreeType. */
+ /* */
+ /* ft_pixel_mode_rgb24 :: A 24-bit RGB bitmap. */
+ /* Currently unused by FreeType. */
+ /* */
+ /* ft_pixel_mode_rgb32 :: A 32-bit RGB bitmap. */
+ /* Currently unused by FreeType. */
+ /* */
+ /* <Note> */
+ /* Some anti-aliased bitmaps might be embedded in TrueType fonts */
+ /* using formats pal2 or pal4, though no fonts presenting those have */
+ /* been found to date. */
+ /* */
+ typedef enum FT_Pixel_Mode_
+ {
+ ft_pixel_mode_none = 0,
+ ft_pixel_mode_mono,
+ ft_pixel_mode_grays,
+ ft_pixel_mode_pal2,
+ ft_pixel_mode_pal4,
+ ft_pixel_mode_pal8,
+ ft_pixel_mode_rgb15,
+ ft_pixel_mode_rgb16,
+ ft_pixel_mode_rgb24,
+ ft_pixel_mode_rgb32,
+
+ ft_pixel_mode_max /* do not remove */
+
+ } FT_Pixel_Mode;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Palette_Mode */
+ /* */
+ /* <Description> */
+ /* An enumeration type used to describe the format of a bitmap */
+ /* palette, used with ft_pixel_mode_pal4 and ft_pixel_mode_pal8. */
+ /* */
+ /* <Fields> */
+ /* ft_palette_mode_rgb :: The palette is an array of 3-bytes RGB */
+ /* records. */
+ /* */
+ /* ft_palette_mode_rgba :: The palette is an array of 4-bytes RGBA */
+ /* records. */
+ /* */
+ /* <Note> */
+ /* As ft_pixel_mode_pal2, pal4 and pal8 are currently unused by */
+ /* FreeType, these types are not handled by the library itself. */
+ /* */
+ typedef enum FT_Palette_Mode_
+ {
+ ft_palette_mode_rgb = 0,
+ ft_palette_mode_rgba,
+
+ ft_palettte_mode_max /* do not remove */
+
+ } FT_Palette_Mode;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Bitmap */
+ /* */
+ /* <Description> */
+ /* A structure used to describe a bitmap or pixmap to the raster. */
+ /* Note that we now manage pixmaps of various depths through the */
+ /* `pixel_mode' field. */
+ /* */
+ /* <Fields> */
+ /* rows :: The number of bitmap rows. */
+ /* */
+ /* width :: The number of pixels in bitmap row. */
+ /* */
+ /* pitch :: The pitch's absolute value is the number of bytes */
+ /* taken by one bitmap row, including padding. */
+ /* However, the pitch is positive when the bitmap has */
+ /* a `down' flow, and negative when it has an `up' */
+ /* flow. In all cases, the pitch is an offset to add */
+ /* to a bitmap pointer in order to go down one row. */
+ /* */
+ /* buffer :: A typeless pointer to the bitmap buffer. This */
+ /* value should be aligned on 32-bit boundaries in */
+ /* most cases. */
+ /* */
+ /* num_grays :: This field is only used with */
+ /* `ft_pixel_mode_grays'; it gives the number of gray */
+ /* levels used in the bitmap. */
+ /* */
+ /* pixel_mode :: The pixel_mode, i.e., how pixel bits are stored. */
+ /* */
+ /* palette_mode :: This field is only used with paletted pixel modes; */
+ /* it indicates how the palette is stored. */
+ /* */
+ /* palette :: A typeless pointer to the bitmap palette; only */
+ /* used for paletted pixel modes. */
+ /* */
+ /* <Note> */
+ /* For now, the only pixel mode supported by FreeType are mono and */
+ /* grays. However, drivers might be added in the future to support */
+ /* more `colorful' options. */
+ /* */
+ /* When using pixel modes pal2, pal4 and pal8 with a void `palette' */
+ /* field, a gray pixmap with respectively 4, 16, and 256 levels of */
+ /* gray is assumed. This, in order to be compatible with some */
+ /* embedded bitmap formats defined in the TrueType specification. */
+ /* */
+ /* Note that no font was found presenting such embedded bitmaps, so */
+ /* this is currently completely unhandled by the library. */
+ /* */
+ typedef struct FT_Bitmap_
+ {
+ int rows;
+ int width;
+ int pitch;
+ unsigned char* buffer;
+ short num_grays;
+ char pixel_mode;
+ char palette_mode;
+ void* palette;
+
+ } FT_Bitmap;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Outline */
+ /* */
+ /* <Description> */
+ /* This structure is used to describe an outline to the scan-line */
+ /* converter. */
+ /* */
+ /* <Fields> */
+ /* n_contours :: The number of contours in the outline. */
+ /* */
+ /* n_points :: The number of points in the outline. */
+ /* */
+ /* points :: A pointer to an array of `n_points' FT_Vector */
+ /* elements, giving the outline's point coordinates. */
+ /* */
+ /* tags :: A pointer to an array of `n_points' chars, giving */
+ /* giving each outline point's type. If bit 0 is */
+ /* unset, the point is 'off' the curve, i.e. a Bezier */
+ /* control point, while it is `on' when unset. */
+ /* */
+ /* Bit 1 is meaningful for `off' points only. If set, */
+ /* it indicates a third-order Bezier arc control point; */
+ /* and a second-order control point if unset. */
+ /* */
+ /* contours :: An array of `n_contours' shorts, giving the end */
+ /* point of each contour within the outline. For */
+ /* example, the first contour is defined by the points */
+ /* `0' to `contours[0]', the second one is defined by */
+ /* the points `contours[0]+1' to `contours[1]', etc. */
+ /* */
+ /* flags :: A set of bit flags used to characterize the outline */
+ /* and give hints to the scan-converter and hinter on */
+ /* how to convert/grid-fit it. See FT_Outline_Flags. */
+ /* */
+ typedef struct FT_Outline_
+ {
+ short n_contours; /* number of contours in glyph */
+ short n_points; /* number of points in the glyph */
+
+ FT_Vector* points; /* the outline's points */
+ char* tags; /* the points flags */
+ short* contours; /* the contour end points */
+
+ int flags; /* outline masks */
+
+ } FT_Outline;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Outline_Flags */
+ /* */
+ /* <Description> */
+ /* A simple type used to enumerates the flags in an outline's */
+ /* `outline_flags' field. */
+ /* */
+ /* <Fields> */
+ /* ft_outline_owner :: If set, this flag indicates that the */
+ /* outline's field arrays (i.e. */
+ /* `points', `flags' & `contours') are */
+ /* `owned' by the outline object, and */
+ /* should thus be freed when it is */
+ /* destroyed. */
+ /* */
+ /* ft_outline_even_odd_fill :: By default, outlines are filled using */
+ /* the non-zero winding rule. If set to */
+ /* 1, the outline will be filled using */
+ /* the even-odd fill rule (only works */
+ /* with the smooth raster). */
+ /* */
+ /* ft_outline_reverse_fill :: By default, outside contours of an */
+ /* outline are oriented in clock-wise */
+ /* direction, as defined in the TrueType */
+ /* specification. This flag is set if */
+ /* the outline uses the opposite */
+ /* direction (typically for Type 1 */
+ /* fonts). This flag is ignored by the */
+ /* scan-converter. However, it is very */
+ /* important for the auto-hinter. */
+ /* */
+ /* ft_outline_ignore_dropouts :: By default, the scan converter will */
+ /* try to detect drop-outs in an outline */
+ /* and correct the glyph bitmap to */
+ /* ensure consistent shape continuity. */
+ /* If set, this flag hints the scan-line */
+ /* converter to ignore such cases. */
+ /* */
+ /* ft_outline_high_precision :: This flag indicates that the */
+ /* scan-line converter should try to */
+ /* convert this outline to bitmaps with */
+ /* the highest possible quality. It is */
+ /* typically set for small character */
+ /* sizes. Note that this is only a */
+ /* hint, that might be completely */
+ /* ignored by a given scan-converter. */
+ /* */
+ /* ft_outline_single_pass :: This flag is set to force a given */
+ /* scan-converter to only use a single */
+ /* pass over the outline to render a */
+ /* bitmap glyph image. Normally, it is */
+ /* set for very large character sizes. */
+ /* It is only a hint, that might be */
+ /* completely ignored by a given */
+ /* scan-converter. */
+ /* */
+ typedef enum FT_Outline_Flags_
+ {
+ ft_outline_none = 0,
+ ft_outline_owner = 1,
+ ft_outline_even_odd_fill = 2,
+ ft_outline_reverse_fill = 4,
+ ft_outline_ignore_dropouts = 8,
+ ft_outline_high_precision = 256,
+ ft_outline_single_pass = 512
+
+ } FT_Outline_Flags;
+
+
+#define FT_CURVE_TAG( flag ) ( flag & 3 )
+
+#define FT_Curve_Tag_On 1
+#define FT_Curve_Tag_Conic 0
+#define FT_Curve_Tag_Cubic 2
+
+#define FT_Curve_Tag_Touch_X 8 /* reserved for the TrueType hinter */
+#define FT_Curve_Tag_Touch_Y 16 /* reserved for the TrueType hinter */
+
+#define FT_Curve_Tag_Touch_Both ( FT_Curve_Tag_Touch_X | \
+ FT_Curve_Tag_Touch_Y )
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Outline_MoveTo_Func */
+ /* */
+ /* <Description> */
+ /* A function pointer type used to describe the signature of a `move */
+ /* to' function during outline walking/decomposition. */
+ /* */
+ /* A `move to' is emitted to start a new contour in an outline. */
+ /* */
+ /* <Input> */
+ /* to :: A pointer to the target point of the `move to'. */
+ /* */
+ /* user :: A typeless pointer which is passed from the caller of the */
+ /* decomposition function. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means success. */
+ /* */
+ typedef int (*FT_Outline_MoveTo_Func)( FT_Vector* to,
+ void* user );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Outline_LineTo_Func */
+ /* */
+ /* <Description> */
+ /* A function pointer type used to describe the signature of a `line */
+ /* to' function during outline walking/decomposition. */
+ /* */
+ /* A `line to' is emitted to indicate a segment in the outline. */
+ /* */
+ /* <Input> */
+ /* to :: A pointer to the target point of the `line to'. */
+ /* */
+ /* user :: A typeless pointer which is passed from the caller of the */
+ /* decomposition function. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means success. */
+ /* */
+ typedef int (*FT_Outline_LineTo_Func)( FT_Vector* to,
+ void* user );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Outline_ConicTo_Func */
+ /* */
+ /* <Description> */
+ /* A function pointer type use to describe the signature of a `conic */
+ /* to' function during outline walking/decomposition. */
+ /* */
+ /* A `conic to' is emitted to indicate a second-order Bezier arc in */
+ /* the outline. */
+ /* */
+ /* <Input> */
+ /* control :: An intermediate control point between the last position */
+ /* and the new target in `to'. */
+ /* */
+ /* to :: A pointer to the target end point of the conic arc. */
+ /* */
+ /* user :: A typeless pointer which is passed from the caller of */
+ /* the decomposition function. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means success. */
+ /* */
+ typedef int (*FT_Outline_ConicTo_Func)( FT_Vector* control,
+ FT_Vector* to,
+ void* user );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Outline_CubicTo_Func */
+ /* */
+ /* <Description> */
+ /* A function pointer type used to describe the signature of a `cubic */
+ /* to' function during outline walking/decomposition. */
+ /* */
+ /* A `cubic to' is emitted to indicate a third-order Bezier arc. */
+ /* */
+ /* <Input> */
+ /* control1 :: A pointer to the first Bezier control point. */
+ /* */
+ /* control2 :: A pointer to the second Bezier control point. */
+ /* */
+ /* to :: A pointer to the target end point. */
+ /* */
+ /* user :: A typeless pointer which is passed from the caller of */
+ /* the decomposition function. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means success. */
+ /* */
+ typedef int (*FT_Outline_CubicTo_Func)( FT_Vector* control1,
+ FT_Vector* control2,
+ FT_Vector* to,
+ void* user );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Outline_Funcs */
+ /* */
+ /* <Description> */
+ /* A structure to hold various function pointers used during outline */
+ /* decomposition in order to emit segments, conic, and cubic Beziers, */
+ /* as well as `move to' and `close to' operations. */
+ /* */
+ /* <Fields> */
+ /* move_to :: The `move to' emitter. */
+ /* */
+ /* line_to :: The segment emitter. */
+ /* */
+ /* conic_to :: The second-order Bezier arc emitter. */
+ /* */
+ /* cubic_to :: The third-order Bezier arc emitter. */
+ /* */
+ /* shift :: The shift that is applied to coordinates before they */
+ /* are sent to the emitter. */
+ /* */
+ /* delta :: The delta that is applied to coordinates before they */
+ /* are sent to the emitter, but after the shift. */
+ /* */
+ /* <Note> */
+ /* The point coordinates sent to the emitters are the transformed */
+ /* version of the original coordinates (this is important for high */
+ /* accuracy during scan-conversion). The transformation is simple: */
+ /* */
+ /* x' = (x << shift) - delta */
+ /* y' = (x << shift) - delta */
+ /* */
+ /* Set the value of `shift' and `delta' to 0 to get the original */
+ /* point coordinates. */
+ /* */
+ typedef struct FT_Outline_Funcs_
+ {
+ FT_Outline_MoveTo_Func move_to;
+ FT_Outline_LineTo_Func line_to;
+ FT_Outline_ConicTo_Func conic_to;
+ FT_Outline_CubicTo_Func cubic_to;
+
+ int shift;
+ FT_Pos delta;
+
+ } FT_Outline_Funcs;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Macro> */
+ /* FT_IMAGE_TAG */
+ /* */
+ /* <Description> */
+ /* This macro converts four letter tags into an unsigned long. */
+ /* */
+#define FT_IMAGE_TAG( _x1, _x2, _x3, _x4 ) \
+ ( ( (unsigned long)_x1 << 24 ) | \
+ ( (unsigned long)_x2 << 16 ) | \
+ ( (unsigned long)_x3 << 8 ) | \
+ (unsigned long)_x4 )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Glyph_Format */
+ /* */
+ /* <Description> */
+ /* An enumeration type used to describe the format of a given glyph */
+ /* image. Note that this version of FreeType only supports two image */
+ /* formats, even though future font drivers will be able to register */
+ /* their own format. */
+ /* */
+ /* <Fields> */
+ /* ft_glyph_format_composite :: The glyph image is a composite of */
+ /* several other images. This glyph */
+ /* format is _only_ used with the */
+ /* FT_LOAD_FLAG_NO_RECURSE flag (XXX: */
+ /* Which is currently unimplemented). */
+ /* */
+ /* ft_glyph_format_bitmap :: The glyph image is a bitmap, and can */
+ /* be described as a FT_Bitmap. */
+ /* */
+ /* ft_glyph_format_outline :: The glyph image is a vectorial image */
+ /* made of bezier control points, and */
+ /* can be described as a FT_Outline. */
+ /* */
+ /* ft_glyph_format_plotter :: The glyph image is a vectorial image */
+ /* made of plotter lines (some T1 fonts */
+ /* like Hershey contain glyph in this */
+ /* format). */
+ /* */
+ typedef enum FT_Glyph_Format_
+ {
+ ft_glyph_format_none = 0,
+ ft_glyph_format_composite = FT_IMAGE_TAG( 'c', 'o', 'm', 'p' ),
+ ft_glyph_format_bitmap = FT_IMAGE_TAG( 'b', 'i', 't', 's' ),
+ ft_glyph_format_outline = FT_IMAGE_TAG( 'o', 'u', 't', 'l' ),
+ ft_glyph_format_plotter = FT_IMAGE_TAG( 'p', 'l', 'o', 't' )
+
+ } FT_Glyph_Format;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** R A S T E R D E F I N I T I O N S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* A raster is a scan converter, in charge of rendering an outline into */
+ /* a a bitmap. This section contains the public API for rasters. */
+ /* */
+ /* Note that in FreeType 2, all rasters are now encapsulated within */
+ /* specific modules called `renderers'. See `freetype/ftrender.h' for */
+ /* more details on renderers. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Raster */
+ /* */
+ /* <Description> */
+ /* A handle (pointer) to a raster object. Each object can be used */
+ /* independently to convert an outline into a bitmap or pixmap. */
+ /* */
+ typedef struct FT_RasterRec_* FT_Raster;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Span */
+ /* */
+ /* <Description> */
+ /* A structure used to model a single span of gray (or black) pixels */
+ /* when rendering a monochrome or anti-aliased bitmap. */
+ /* */
+ /* <Fields> */
+ /* x :: The span's horizontal start position. */
+ /* */
+ /* len :: The span's length in pixels. */
+ /* */
+ /* coverage :: The span color/coverage, ranging from 0 (background) */
+ /* to 255 (foreground). Only used for anti-aliased */
+ /* rendering. */
+ /* */
+ /* <Note> */
+ /* This structure is used by the span drawing callback type named */
+ /* FT_Raster_Span_Func(), which takes the y-coordinate of the span as */
+ /* a parameter. */
+ /* */
+ /* The coverage value is always between 0 and 255, even if the number */
+ /* of gray levels have been set through FT_Set_Gray_Levels(). */
+ /* */
+ typedef struct FT_Span_
+ {
+ short x;
+ unsigned short len;
+ unsigned char coverage;
+
+ } FT_Span;
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Raster_Span_Func */
+ /* */
+ /* <Description> */
+ /* A function used as a call-back by the anti-aliased renderer in */
+ /* order to let client applications draw themselves the gray pixel */
+ /* spans on each scan line. */
+ /* */
+ /* <Input> */
+ /* y :: The scanline's y-coordinate. */
+ /* */
+ /* count :: The number of spans to draw on this scanline. */
+ /* */
+ /* spans :: A table of `count' spans to draw on the scanline. */
+ /* */
+ /* user :: User-supplied data that is passed to the callback. */
+ /* */
+ /* <Note> */
+ /* This callback allows client applications to directly render the */
+ /* gray spans of the anti-aliased bitmap to any kind of surfaces. */
+ /* */
+ /* This can be used to write anti-aliased outlines directly to a */
+ /* given background bitmap, and even perform translucency. */
+ /* */
+ /* Note that the `count' field cannot be greater than a fixed value */
+ /* defined by the FT_MAX_GRAY_SPANS configuration macro in */
+ /* ftoption.h. By default, this value is set to 32, which means that */
+ /* if there are more than 32 spans on a given scanline, the callback */
+ /* will be called several times with the same `y' parameter in order */
+ /* to draw all callbacks. */
+ /* */
+ /* Otherwise, the callback is only called once per scan-line, and */
+ /* only for those scanlines that do have `gray' pixels on them. */
+ /* */
+ typedef void (*FT_Raster_Span_Func)( int y,
+ int count,
+ FT_Span* spans,
+ void* user );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Raster_BitTest_Func */
+ /* */
+ /* <Description> */
+ /* A function used as a call-back by the monochrome scan-converter */
+ /* to test whether a given target pixel is already set to the drawing */
+ /* `color'. These tests are crucial to implement drop-out control */
+ /* per-se the TrueType spec. */
+ /* */
+ /* <Input> */
+ /* y :: The pixel's y-coordinate. */
+ /* */
+ /* x :: The pixel's x-coordinate. */
+ /* */
+ /* user :: User-supplied data that is passed to the callback. */
+ /* */
+ /* <Return> */
+ /* 1 if the pixel is `set', 0 otherwise. */
+ /* */
+ typedef int (*FT_Raster_BitTest_Func)( int y,
+ int x,
+ void* user );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Raster_BitSet_Func */
+ /* */
+ /* <Description> */
+ /* A function used as a call-back by the monochrome scan-converter */
+ /* to set an individual target pixel. This is crucial to implement */
+ /* drop-out control according to the TrueType specification. */
+ /* */
+ /* <Input> */
+ /* y :: The pixel's y-coordinate. */
+ /* */
+ /* x :: The pixel's x-coordinate. */
+ /* */
+ /* user :: User-supplied data that is passed to the callback. */
+ /* */
+ /* <Return> */
+ /* 1 if the pixel is `set', 0 otherwise. */
+ /* */
+ typedef void (*FT_Raster_BitSet_Func)( int y,
+ int x,
+ void* user );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Raster_Flag */
+ /* */
+ /* <Description> */
+ /* An enumeration to list the bit flags as used in the `flags' field */
+ /* of a FT_Raster_Params structure. */
+ /* */
+ /* <Fields> */
+ /* ft_raster_flag_default :: This value is 0. */
+ /* */
+ /* ft_raster_flag_aa :: Requests the rendering of an */
+ /* anti-aliased glyph bitmap. If unset, a */
+ /* monchrome bitmap will be rendered. */
+ /* */
+ /* ft_raster_flag_direct :: Requests direct rendering over the */
+ /* target bitmap. Direct rendering uses */
+ /* user-provided callbacks in order to */
+ /* perform direct drawing or composition */
+ /* over an existing bitmap. If this bit is */
+ /* unset, the content of the target bitmap */
+ /* *must be zeroed*! */
+ /* */
+ typedef enum
+ {
+ ft_raster_flag_default = 0,
+ ft_raster_flag_aa = 1,
+ ft_raster_flag_direct = 2
+
+ } FT_Raster_Flag;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Raster_Params */
+ /* */
+ /* <Description> */
+ /* A structure to hold the arguments used by a raster's render */
+ /* function. */
+ /* */
+ /* <Fields> */
+ /* target :: The target bitmap. */
+ /* */
+ /* source :: A pointer to the source glyph image (e.g. an */
+ /* FT_Outline). */
+ /* */
+ /* flags :: The rendering flags. */
+ /* */
+ /* gray_spans :: The gray span drawing callback. */
+ /* */
+ /* black_spans :: The black span drawing callback. */
+ /* */
+ /* bit_test :: The bit test callback. */
+ /* */
+ /* bit_set :: The bit set callback. */
+ /* */
+ /* user :: User-supplied data that is passed to each drawing */
+ /* callback. */
+ /* */
+ /* <Note> */
+ /* An anti-aliased glyph bitmap is drawn if the ft_raster_flag_aa bit */
+ /* flag is set in the `flags' field, otherwise a monochrome bitmap */
+ /* will be generated. */
+ /* */
+ /* If the ft_raster_flag_direct bit flag is set in `flags', the */
+ /* raster will call the `gray_spans' callback to draw gray pixel */
+ /* spans, in the case of an aa glyph bitmap, it will call */
+ /* `black_spans', and `bit_test' and `bit_set' in the case of a */
+ /* monochrome bitmap. This allows direct composition over a */
+ /* pre-existing bitmap through user-provided callbacks to perform the */
+ /* span drawing/composition. */
+ /* */
+ /* Note that the `bit_test' and `bit_set' callbacks are required when */
+ /* rendering a monochrome bitmap, as they are crucial to implement */
+ /* correct drop-out control as defined in the TrueType specification. */
+ /* */
+ typedef struct FT_Raster_Params_
+ {
+ FT_Bitmap* target;
+ void* source;
+ int flags;
+ FT_Raster_Span_Func gray_spans;
+ FT_Raster_Span_Func black_spans;
+ FT_Raster_BitTest_Func bit_test;
+ FT_Raster_BitSet_Func bit_set;
+ void* user;
+
+ } FT_Raster_Params;
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Raster_New_Func */
+ /* */
+ /* <Description> */
+ /* A function used to create a new raster object. */
+ /* */
+ /* <Input> */
+ /* memory :: A handle to the memory allocator. */
+ /* */
+ /* <Output> */
+ /* raster :: A handle to the new raster object. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The `memory' parameter is a typeless pointer in order to avoid */
+ /* un-wanted dependencies on the rest of the FreeType code. In */
+ /* practice, it is a FT_Memory, i.e., a handle to the standard */
+ /* FreeType memory allocator. However, this field can be completely */
+ /* ignored by a given raster implementation. */
+ /* */
+ typedef int (*FT_Raster_New_Func)( void* memory,
+ FT_Raster* raster );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Raster_Done_Func */
+ /* */
+ /* <Description> */
+ /* A function used to destroy a given raster object. */
+ /* */
+ /* <Input> */
+ /* raster :: A handle to the raster object. */
+ /* */
+ typedef void (*FT_Raster_Done_Func)( FT_Raster raster );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Raster_Reset_Func */
+ /* */
+ /* <Description> */
+ /* FreeType provides an area of memory called the `render pool', */
+ /* available to all registered rasters. This pool can be freely used */
+ /* during a given scan-conversion but is shared by all rasters. Its */
+ /* content is thus transient. */
+ /* */
+ /* This function is called each time the render pool changes, or just */
+ /* after a new raster object is created. */
+ /* */
+ /* <Input> */
+ /* raster :: A handle to the new raster object. */
+ /* */
+ /* pool_base :: The address in memory of the render pool. */
+ /* */
+ /* pool_size :: The size in bytes of the render pool. */
+ /* */
+ /* <Note> */
+ /* Rasters can ignore the render pool and rely on dynamic memory */
+ /* allocation if they want to (a handle to the memory allocator is */
+ /* passed to the raster constructor). However, this is not */
+ /* recommended for efficiency purposes. */
+ /* */
+ typedef void (*FT_Raster_Reset_Func)( FT_Raster raster,
+ unsigned char* pool_base,
+ unsigned long pool_size );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Raster_Set_Mode_Func */
+ /* */
+ /* <Description> */
+ /* This function is a generic facility to change modes or attributes */
+ /* in a given raster. This can be used for debugging purposes, or */
+ /* simply to allow implementation-specific `features' in a given */
+ /* raster module. */
+ /* */
+ /* <Input> */
+ /* raster :: A handle to the new raster object. */
+ /* */
+ /* mode :: A 4-byte tag used to name the mode or property. */
+ /* */
+ /* args :: A pointer to the new mode/property to use. */
+ /* */
+ typedef int (*FT_Raster_Set_Mode_Func)( FT_Raster raster,
+ unsigned long mode,
+ void* args );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Raster_Render_Func */
+ /* */
+ /* <Description> */
+ /* Invokes a given raster to scan-convert a given glyph image into a */
+ /* target bitmap. */
+ /* */
+ /* <Input> */
+ /* raster :: A handle to the raster object. */
+ /* */
+ /* params :: A pointer to a FT_Raster_Params structure used to store */
+ /* the rendering parameters. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The exact format of the source image depends on the raster's glyph */
+ /* format defined in its FT_Raster_Funcs structure. It can be an */
+ /* FT_Outline or anything else in order to support a large array of */
+ /* glyph formats. */
+ /* */
+ /* Note also that the render function can fail and return a */
+ /* FT_Err_Unimplemented_Feature error code if the raster used does */
+ /* not support direct composition. */
+ /* */
+ /* XXX: For now, the standard raster doesn't support direct */
+ /* composition but this should change for the final release (see */
+ /* the files demos/src/ftgrays.c and demos/src/ftgrays2.c for */
+ /* examples of distinct implementations which support direct */
+ /* composition). */
+ /* */
+ typedef int (*FT_Raster_Render_Func)( FT_Raster raster,
+ FT_Raster_Params* params );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Raster_Funcs */
+ /* */
+ /* <Description> */
+ /* A structure used to describe a given raster class to the library. */
+ /* */
+ /* <Fields> */
+ /* glyph_format :: The supported glyph format for this raster. */
+ /* */
+ /* raster_new :: The raster constructor. */
+ /* */
+ /* raster_reset :: Used to reset the render pool within the raster. */
+ /* */
+ /* raster_render :: A function to render a glyph into a given bitmap. */
+ /* */
+ /* raster_done :: The raster destructor. */
+ /* */
+ typedef struct FT_Raster_Funcs_
+ {
+ FT_Glyph_Format glyph_format;
+ FT_Raster_New_Func raster_new;
+ FT_Raster_Reset_Func raster_reset;
+ FT_Raster_Set_Mode_Func raster_set_mode;
+ FT_Raster_Render_Func raster_render;
+ FT_Raster_Done_Func raster_done;
+
+ } FT_Raster_Funcs;
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* FTIMAGE_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftmm.h */
+/* */
+/* FreeType Multiple Master font interface (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTMM_H
+#define FTMM_H
+
+#include <freetype/t1tables.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_MM_Axis */
+ /* */
+ /* <Description> */
+ /* A simple structure used to model a given axis in design space for */
+ /* Multiple Masters fonts. */
+ /* */
+ /* <Fields> */
+ /* name :: The axis's name. */
+ /* */
+ /* minimum :: The axis's minimum design coordinate. */
+ /* */
+ /* maximum :: The axis's maximum design coordinate. */
+ /* */
+ typedef struct FT_MM_Axis_
+ {
+ FT_String* name;
+ FT_Long minimum;
+ FT_Long maximum;
+
+ } FT_MM_Axis;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Multi_Master */
+ /* */
+ /* <Description> */
+ /* A structure used to model the axes and space of a Multiple Masters */
+ /* font. */
+ /* */
+ /* <Fields> */
+ /* num_axis :: Number of axes. Cannot exceed 4. */
+ /* */
+ /* num_designs :: Number of designs; should ne normally 2^num_axis */
+ /* even though the Type 1 specification strangely */
+ /* allows for intermediate designs to be present. This */
+ /* number cannot exceed 16. */
+ /* */
+ /* axis :: A table of axis descriptors. */
+ /* */
+ typedef struct FT_Multi_Master_
+ {
+ FT_UInt num_axis;
+ FT_UInt num_designs;
+ FT_MM_Axis axis[T1_MAX_MM_AXIS];
+
+ } FT_Multi_Master;
+
+
+ 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 );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Multi_Master */
+ /* */
+ /* <Description> */
+ /* Retrieves the Multiple Master descriptor of a given font. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face. */
+ /* */
+ /* <Output> */
+ /* master :: The Multiple Masters descriptor. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Get_Multi_Master( FT_Face face,
+ FT_Multi_Master* master );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_MM_Design_Coordinates */
+ /* */
+ /* <Description> */
+ /* For Multiple Masters fonts, choose an interpolated font design */
+ /* through design coordinates. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face. */
+ /* */
+ /* num_coords :: The number of design coordinates (must be equal to */
+ /* the number of axes in the font). */
+ /* */
+ /* coords :: The design coordinates. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Set_MM_Design_Coordinates(
+ FT_Face face,
+ FT_UInt num_coords,
+ FT_Long* coords );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_MM_Blend_Coordinates */
+ /* */
+ /* <Description> */
+ /* For Multiple Masters fonts, choose an interpolated font design */
+ /* through normalized blend coordinates. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face. */
+ /* */
+ /* num_coords :: The number of design coordinates (must be equal to */
+ /* the number of axes in the font). */
+ /* */
+ /* coords :: The design coordinates (each one must be between 0 */
+ /* and 1.0). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Set_MM_Blend_Coordinates(
+ FT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* FTMM_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftmodule.h */
+/* */
+/* FreeType modules public interface (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTMODULE_H
+#define FTMODULE_H
+
+#include <freetype/freetype.h>
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /* module bit flags */
+ typedef enum FT_Module_Flags_
+ {
+ ft_module_font_driver = 1, /* this module is a font driver */
+ ft_module_renderer = 2, /* this module is a renderer */
+ ft_module_hinter = 4, /* this module is a glyph hinter */
+ ft_module_styler = 8, /* this module is a styler */
+
+ ft_module_driver_scalable = 0x100, /* the driver supports scalable */
+ /* fonts */
+ ft_module_driver_no_outlines = 0x200, /* the driver does not support */
+ /* vector outlines */
+ ft_module_driver_has_hinter = 0x400 /* the driver provides its own */
+ /* hinter */
+
+ } FT_Module_Flags;
+
+
+ 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_Int 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. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* 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_DEF( 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_DEF( 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. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to a library object. */
+ /* */
+ /* 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_DEF( 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_DEF( FT_Error ) FT_New_Library( FT_Memory memory,
+ FT_Library* library );
+
+
+ /*************************************************************************/
+ /* */
+ /* <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_DEF( 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. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* 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_DEF( 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_DEF( void ) FT_Add_Default_Modules( FT_Library library );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* FTMODULE_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftnames.h */
+/* */
+/* Simple interface to access SFNT name tables (which are used */
+/* to hold font names, copyright info, notices, etc.). */
+/* */
+/* This is _not_ used to retrieve glyph names! */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTNAMES_H
+#define FTNAMES_H
+
+
+#include <freetype/freetype.h>
+
+
+ typedef struct FT_SfntName_
+ {
+ FT_UShort platform_id;
+ FT_UShort encoding_id;
+ FT_UShort language_id;
+ FT_UShort name_id;
+
+ FT_Byte* string;
+ FT_UInt string_len; /* in bytes */
+
+ } FT_SfntName;
+
+
+ FT_EXPORT_DEF( FT_UInt ) FT_Get_Sfnt_Name_Count( FT_Face face );
+
+ FT_EXPORT_DEF( FT_Error ) FT_Get_Sfnt_Name( FT_Face face,
+ FT_UInt index,
+ FT_SfntName* aname );
+
+
+#endif /* FTNAMES_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftoutln.h */
+/* */
+/* Support for the FT_Outline type used to store glyph shapes of */
+/* most scalable font formats (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTOUTLN_H
+#define FTOUTLN_H
+
+
+#include <freetype/freetype.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Decompose */
+ /* */
+ /* <Description> */
+ /* Walks over an outline's structure to decompose it into individual */
+ /* segments and Bezier arcs. This function is also able to emit */
+ /* `move to' and `close to' operations to indicate the start and end */
+ /* of new contours in the outline. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the source target. */
+ /* */
+ /* interface :: A table of `emitters', i.e,. function pointers called */
+ /* during decomposition to indicate path operations. */
+ /* */
+ /* user :: A typeless pointer which is passed to each emitter */
+ /* during the decomposition. It can be used to store */
+ /* the state during the decomposition. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means sucess. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Outline_Decompose(
+ FT_Outline* outline,
+ FT_Outline_Funcs* interface,
+ void* user );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_New */
+ /* */
+ /* <Description> */
+ /* Creates a new outline of a given size. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object from where the */
+ /* outline is allocated. Note however that the new */
+ /* outline will NOT necessarily be FREED, when */
+ /* destroying the library, by FT_Done_FreeType(). */
+ /* */
+ /* numPoints :: The maximal number of points within the outline. */
+ /* */
+ /* numContours :: The maximal number of contours within the outline. */
+ /* */
+ /* <Output> */
+ /* outline :: A handle to the new outline. NULL in case of */
+ /* error. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <MT-Note> */
+ /* No. */
+ /* */
+ /* <Note> */
+ /* The reason why this function takes a `library' parameter is simply */
+ /* to use the library's memory allocator. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Outline_New( FT_Library library,
+ FT_UInt numPoints,
+ FT_Int numContours,
+ FT_Outline* outline );
+
+
+ FT_EXPORT_DEF( FT_Error ) FT_Outline_New_Internal(
+ FT_Memory memory,
+ FT_UInt numPoints,
+ FT_Int numContours,
+ FT_Outline* outline );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Done */
+ /* */
+ /* <Description> */
+ /* Destroys an outline created with FT_Outline_New(). */
+ /* */
+ /* <Input> */
+ /* library :: A handle of the library object used to allocate the */
+ /* outline. */
+ /* */
+ /* outline :: A pointer to the outline object to be discarded. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <MT-Note> */
+ /* No. */
+ /* */
+ /* <Note> */
+ /* If the outline's `owner' field is not set, only the outline */
+ /* descriptor will be released. */
+ /* */
+ /* The reason why this function takes an `outline' parameter is */
+ /* simply to use FT_Free(). */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Outline_Done( FT_Library library,
+ FT_Outline* outline );
+
+
+ FT_EXPORT_DEF( FT_Error ) FT_Outline_Done_Internal( FT_Memory memory,
+ FT_Outline* outline );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Get_CBox */
+ /* */
+ /* <Description> */
+ /* Returns an outline's `control box'. The control box encloses all */
+ /* the outline's points, including Bezier control points. Though it */
+ /* coincides with the exact bounding box for most glyphs, it can be */
+ /* slightly larger in some situations (like when rotating an outline */
+ /* which contains Bezier outside arcs). */
+ /* */
+ /* Computing the control box is very fast, while getting the bounding */
+ /* box can take much more time as it needs to walk over all segments */
+ /* and arcs in the outline. To get the latter, you can use the */
+ /* `ftbbox' component which is dedicated to this single task. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the source outline descriptor. */
+ /* */
+ /* <Output> */
+ /* cbox :: The outline's control box. */
+ /* */
+ /* <MT-Note> */
+ /* Yes. */
+ /* */
+ FT_EXPORT_DEF( void ) FT_Outline_Get_CBox( FT_Outline* outline,
+ FT_BBox* cbox );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Translate */
+ /* */
+ /* <Description> */
+ /* Applies a simple translation to the points of an outline. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the target outline descriptor. */
+ /* */
+ /* xOffset :: The horizontal offset. */
+ /* */
+ /* yOffset :: The vertical offset. */
+ /* */
+ /* <MT-Note> */
+ /* Yes. */
+ /* */
+ FT_EXPORT_DEF( void ) FT_Outline_Translate( FT_Outline* outline,
+ FT_Pos xOffset,
+ FT_Pos yOffset );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Copy */
+ /* */
+ /* <Description> */
+ /* Copies an outline into another one. Both objects must have the */
+ /* same sizes (number of points & number of contours) when this */
+ /* function is called. */
+ /* */
+ /* <Input> */
+ /* source :: A handle to the source outline. */
+ /* */
+ /* <Output> */
+ /* target :: A handle to the target outline. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Outline_Copy( FT_Outline* source,
+ FT_Outline* target );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Vector_Transform */
+ /* */
+ /* <Description> */
+ /* Transforms a single vector through a 2x2 matrix. */
+ /* */
+ /* <InOut> */
+ /* vector :: The target vector to transform. */
+ /* */
+ /* <Input> */
+ /* matrix :: A pointer to the source 2x2 matrix. */
+ /* */
+ /* <MT-Note> */
+ /* Yes. */
+ /* */
+ /* <Note> */
+ /* The result is undefined if either `vector' or `matrix' is invalid. */
+ /* */
+ FT_EXPORT_DEF( void ) FT_Outline_Transform( FT_Outline* outline,
+ FT_Matrix* matrix );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Reverse */
+ /* */
+ /* <Description> */
+ /* Reverses the drawing direction of an outline. This is used to */
+ /* ensure consistent fill conventions for mirrored glyphs. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the target outline descriptor. */
+ /* */
+ /* <Note> */
+ /* This functions toggles the bit flag `ft_outline_reverse_fill' in */
+ /* the outline's `flags' field. */
+ /* */
+ /* It shouldn't be used by a normal client application, unless it */
+ /* knows what it is doing. */
+ /* */
+ FT_EXPORT_DEF( void ) FT_Outline_Reverse( FT_Outline* outline );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Get_Bitmap */
+ /* */
+ /* <Description> */
+ /* Renders an outline within a bitmap. The outline's image is simply */
+ /* OR-ed to the target bitmap. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to a FreeType library object. */
+ /* */
+ /* outline :: A pointer to the source outline descriptor. */
+ /* */
+ /* map :: A pointer to the target bitmap descriptor. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <MT-Note> */
+ /* YES. Rendering is synchronized, so that concurrent calls to the */
+ /* scan-line converter will be serialized. */
+ /* */
+ /* <Note> */
+ /* This function does NOT CREATE the bitmap, it only renders an */
+ /* outline image within the one you pass to it! */
+ /* */
+ /* It will use the raster correponding to the default glyph format. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Outline_Get_Bitmap( FT_Library library,
+ FT_Outline* outline,
+ FT_Bitmap* bitmap );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Render */
+ /* */
+ /* <Description> */
+ /* Renders an outline within a bitmap using the current scan-convert. */
+ /* This functions uses an FT_Raster_Params structure as an argument, */
+ /* allowing advanced features like direct composition, translucency, */
+ /* etc. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to a FreeType library object. */
+ /* */
+ /* outline :: A pointer to the source outline descriptor. */
+ /* */
+ /* params :: A pointer to a FT_Raster_Params structure used to */
+ /* describe the rendering operation. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <MT-Note> */
+ /* YES. Rendering is synchronized, so that concurrent calls to the */
+ /* scan-line converter will be serialized. */
+ /* */
+ /* <Note> */
+ /* You should know what you are doing and how FT_Raster_Params works */
+ /* to use this function. */
+ /* */
+ /* The field `params.source' will be set to `outline' before the scan */
+ /* converter is called, which means that the value you give to it is */
+ /* actually ignored. */
+ /* */
+ FT_EXPORT_DEF( FT_Error ) FT_Outline_Render( FT_Library library,
+ FT_Outline* outline,
+ FT_Raster_Params* params );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* FTOUTLN_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftrender.h */
+/* */
+/* FreeType renderer modules public interface (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTRENDER_H
+#define FTRENDER_H
+
+#include <freetype/ftmodule.h>
+#include <freetype/ftglyph.h>
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /* create a new glyph object */
+ typedef FT_Error (*FT_Glyph_Init_Func)( FT_Glyph glyph,
+ FT_GlyphSlot slot );
+
+ /* destroys a given glyph object */
+ typedef void (*FT_Glyph_Done_Func)( FT_Glyph glyph );
+
+ typedef void (*FT_Glyph_Transform_Func)( FT_Glyph glyph,
+ FT_Matrix* matrix,
+ FT_Vector* delta );
+
+ typedef void (*FT_Glyph_BBox_Func)( FT_Glyph glyph,
+ FT_BBox* abbox );
+
+ typedef FT_Error (*FT_Glyph_Copy_Func)( FT_Glyph source,
+ FT_Glyph target );
+
+ typedef FT_Error (*FT_Glyph_Prepare_Func)( FT_Glyph glyph,
+ FT_GlyphSlot slot );
+
+ struct FT_Glyph_Class_
+ {
+ FT_UInt glyph_size;
+ FT_Glyph_Format glyph_format;
+ FT_Glyph_Init_Func glyph_init;
+ FT_Glyph_Done_Func glyph_done;
+ FT_Glyph_Copy_Func glyph_copy;
+ FT_Glyph_Transform_Func glyph_transform;
+ FT_Glyph_BBox_Func glyph_bbox;
+ FT_Glyph_Prepare_Func glyph_prepare;
+ };
+
+
+ typedef FT_Error (*FTRenderer_render)( FT_Renderer renderer,
+ FT_GlyphSlot slot,
+ FT_UInt mode,
+ FT_Vector* origin );
+
+ typedef FT_Error (*FTRenderer_transform)( FT_Renderer renderer,
+ FT_GlyphSlot slot,
+ FT_Matrix* matrix,
+ FT_Vector* delta );
+
+ typedef void (*FTRenderer_getCBox)( FT_Renderer renderer,
+ FT_GlyphSlot slot,
+ FT_BBox* cbox );
+
+ typedef FT_Error (*FTRenderer_setMode)( FT_Renderer renderer,
+ FT_ULong mode_tag,
+ FT_Pointer mode_ptr );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Renderer_Class */
+ /* */
+ /* <Description> */
+ /* The renderer module class descriptor. */
+ /* */
+ /* <Fields> */
+ /* root :: The root FT_Module_Class fields. */
+ /* */
+ /* glyph_format :: The glyph image format this renderer handles. */
+ /* */
+ /* render_glyph :: A method used to render the image that is in a */
+ /* given glyph slot into a bitmap. */
+ /* */
+ /* set_mode :: A method used to pass additional parameters. */
+ /* */
+ /* raster_class :: For `ft_glyph_format_outline' renderers only, this */
+ /* is a pointer to its raster's class. */
+ /* */
+ /* raster :: For `ft_glyph_format_outline' renderers only. this */
+ /* is a pointer to the corresponding raster object, */
+ /* if any. */
+ /* */
+ typedef struct FT_Renderer_Class_
+ {
+ FT_Module_Class root;
+
+ FT_Glyph_Format glyph_format;
+
+ FTRenderer_render render_glyph;
+ FTRenderer_transform transform_glyph;
+ FTRenderer_getCBox get_glyph_cbox;
+ FTRenderer_setMode set_mode;
+
+ FT_Raster_Funcs* raster_class;
+
+ } FT_Renderer_Class;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Renderer */
+ /* */
+ /* <Description> */
+ /* Retrieves the current renderer for a given glyph format. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* format :: The glyph format. */
+ /* */
+ /* <Return> */
+ /* A renderer handle. 0 if none found. */
+ /* */
+ /* <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. */
+ /* */
+ /* To add a new renderer, simply use FT_Add_Module(). To retrieve a */
+ /* renderer by its name, use FT_Get_Module(). */
+ /* */
+ FT_EXPORT_DEF( FT_Renderer ) FT_Get_Renderer( FT_Library library,
+ FT_Glyph_Format format );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Renderer */
+ /* */
+ /* <Description> */
+ /* Sets the current renderer to use, and set additional mode. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* renderer :: A handle to the renderer object. */
+ /* */
+ /* num_params :: The number of additional parameters. */
+ /* */
+ /* parameters :: Additional parameters. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* In case of success, the renderer will be used to convert glyph */
+ /* images in the renderer's known format into bitmaps. */
+ /* */
+ /* This doesn't change the current renderer for other formats. */
+ /* */
+ FT_EXPORT_DEF(FT_Error) FT_Set_Renderer( FT_Library library,
+ FT_Renderer renderer,
+ FT_UInt num_params,
+ FT_Parameter* parameters );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* FTRENDER_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftsystem.h */
+/* */
+/* FreeType low-level system interface definition (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTSYSTEM_H
+#define FTSYSTEM_H
+
+
+ /*************************************************************************/
+ /* */
+ /* M E M O R Y M A N A G E M E N T */
+ /* */
+ /*************************************************************************/
+
+
+ typedef struct FT_MemoryRec_* FT_Memory;
+
+
+ typedef void* (*FT_Alloc_Func)( FT_Memory memory,
+ long size );
+
+ typedef void (*FT_Free_Func)( FT_Memory memory,
+ void* block );
+
+ typedef void* (*FT_Realloc_Func)( FT_Memory memory,
+ long cur_size,
+ long new_size,
+ void* block );
+
+
+ struct FT_MemoryRec_
+ {
+ void* user;
+ FT_Alloc_Func alloc;
+ FT_Free_Func free;
+ FT_Realloc_Func realloc;
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* I / O M A N A G E M E N T */
+ /* */
+ /*************************************************************************/
+
+
+ typedef union FT_StreamDesc_
+ {
+ long value;
+ void* pointer;
+
+ } FT_StreamDesc;
+
+
+ typedef struct FT_StreamRec_* FT_Stream;
+
+
+ typedef unsigned long (*FT_Stream_IO)( FT_Stream stream,
+ unsigned long offset,
+ unsigned char* buffer,
+ unsigned long count );
+
+ typedef void (*FT_Stream_Close)( FT_Stream stream );
+
+
+ struct FT_StreamRec_
+ {
+ unsigned char* base;
+ unsigned long size;
+ unsigned long pos;
+
+ FT_StreamDesc descriptor;
+ FT_StreamDesc pathname; /* ignored by FreeType -- */
+ /* useful for debugging */
+ FT_Stream_IO read;
+ FT_Stream_Close close;
+
+ FT_Memory memory;
+ unsigned char* cursor;
+ unsigned char* limit;
+ };
+
+
+#endif /* FTSYSTEM_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* fttypes.h */
+/* */
+/* FreeType simple types definitions (specification only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTTYPES_H
+#define FTTYPES_H
+
+
+#include <freetype/ftsystem.h>
+#include <freetype/ftimage.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Bool */
+ /* */
+ /* <Description> */
+ /* A typedef of unsigned char, used for simple booleans. */
+ /* */
+ typedef unsigned char FT_Bool;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_FWord */
+ /* */
+ /* <Description> */
+ /* A signed 16-bit integer used to store a distance in original font */
+ /* units. */
+ /* */
+ typedef signed short FT_FWord; /* distance in FUnits */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_UFWord */
+ /* */
+ /* <Description> */
+ /* An unsigned 16-bit integer used to store a distance in original */
+ /* font units. */
+ /* */
+ typedef unsigned short FT_UFWord; /* unsigned distance */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Char */
+ /* */
+ /* <Description> */
+ /* A simple typedef for the _signed_ char type. */
+ /* */
+ typedef signed char FT_Char;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Byte */
+ /* */
+ /* <Description> */
+ /* A simple typedef for the _unsigned_ char type. */
+ /* */
+ typedef unsigned char FT_Byte;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_String */
+ /* */
+ /* <Description> */
+ /* A simple typedef for the char type, usually used for strings. */
+ /* */
+ typedef char FT_String;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Short */
+ /* */
+ /* <Description> */
+ /* A typedef for signed short. */
+ /* */
+ typedef signed short FT_Short;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_UShort */
+ /* */
+ /* <Description> */
+ /* A typedef for unsigned short. */
+ /* */
+ typedef unsigned short FT_UShort;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Int */
+ /* */
+ /* <Description> */
+ /* A typedef for the int type. */
+ /* */
+ typedef int FT_Int;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_UInt */
+ /* */
+ /* <Description> */
+ /* A typedef for the unsigned int type. */
+ /* */
+ typedef unsigned int FT_UInt;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Long */
+ /* */
+ /* <Description> */
+ /* A typedef for signed long. */
+ /* */
+ typedef signed long FT_Long;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_ULong */
+ /* */
+ /* <Description> */
+ /* A typedef for unsigned long. */
+ /* */
+ typedef unsigned long FT_ULong;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_F2Dot14 */
+ /* */
+ /* <Description> */
+ /* A signed 2.14 fixed float type used for unit vectors. */
+ /* */
+ typedef signed short FT_F2Dot14;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_F26Dot6 */
+ /* */
+ /* <Description> */
+ /* A signed 26.6 fixed float type used for vectorial pixel */
+ /* coordinates. */
+ /* */
+ typedef signed long FT_F26Dot6;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Fixed */
+ /* */
+ /* <Description> */
+ /* This type is used to store 16.16 fixed float values, like scales */
+ /* or matrix coefficients. */
+ /* */
+ typedef signed long FT_Fixed;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Error */
+ /* */
+ /* <Description> */
+ /* The FreeType error code type. A value of 0 is always interpreted */
+ /* as a successful operation. */
+ /* */
+ typedef int FT_Error;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Pointer */
+ /* */
+ /* <Description> */
+ /* A simple typedef for a typeless pointer. */
+ /* */
+ typedef void* FT_Pointer;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_UnitVector */
+ /* */
+ /* <Description> */
+ /* A simple structure used to store a 2D vector unit vector. Uses */
+ /* FT_F2Dot14 types. */
+ /* */
+ /* <Fields> */
+ /* x :: Horizontal coordinate. */
+ /* */
+ /* y :: Vertical coordinate. */
+ /* */
+ typedef struct FT_UnitVector_
+ {
+ FT_F2Dot14 x;
+ FT_F2Dot14 y;
+
+ } FT_UnitVector;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Matrix */
+ /* */
+ /* <Description> */
+ /* A simple structure used to store a 2x2 matrix. Coefficients are */
+ /* in 16.16 fixed float format. The computation performed is: */
+ /* */
+ /* { */
+ /* x' = x*xx + y*xy */
+ /* y' = x*yx + y*yy */
+ /* } */
+ /* */
+ /* <Fields> */
+ /* xx :: Matrix coefficient. */
+ /* */
+ /* xy :: Matrix coefficient. */
+ /* */
+ /* yx :: Matrix coefficient. */
+ /* */
+ /* yy :: Matrix coefficient. */
+ /* */
+ typedef struct FT_Matrix_
+ {
+ FT_Fixed xx, xy;
+ FT_Fixed yx, yy;
+
+ } FT_Matrix;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_BBox */
+ /* */
+ /* <Description> */
+ /* A structure used to hold an outline's bounding box, i.e., the */
+ /* coordinates of its extrema in the horizontal and vertical */
+ /* directions. */
+ /* */
+ /* <Fields> */
+ /* xMin :: The horizontal minimum (left-most). */
+ /* */
+ /* yMin :: The vertical minimum (bottom-most). */
+ /* */
+ /* xMax :: The horizontal maximum (right-most). */
+ /* */
+ /* yMax :: The vertical maximum (top-most). */
+ /* */
+ typedef struct FT_BBox_
+ {
+ FT_Pos xMin, yMin;
+ FT_Pos xMax, yMax;
+
+ } FT_BBox;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Macro> */
+ /* FT_MAKE_TAG */
+ /* */
+ /* <Description> */
+ /* This macro converts four letter tags which are used to label */
+ /* TrueType tables into an unsigned long to be used within FreeType. */
+ /* */
+#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
+ ( ( (FT_ULong)_x1 << 24 ) | \
+ ( (FT_ULong)_x2 << 16 ) | \
+ ( (FT_ULong)_x3 << 8 ) | \
+ (FT_ULong)_x4 )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /* */
+ /* L I S T M A N A G E M E N T */
+ /* */
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_ListNode */
+ /* */
+ /* <Description> */
+ /* Many elements and objects in FreeType are listed through a */
+ /* FT_List record (see FT_ListRec). As its name suggests, a */
+ /* FT_ListNode is a handle to a single list element. */
+ /* */
+ typedef struct FT_ListNodeRec_* FT_ListNode;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_List */
+ /* */
+ /* <Description> */
+ /* A handle to a list record (see FT_ListRec). */
+ /* */
+ typedef struct FT_ListRec_* FT_List;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_ListNodeRec */
+ /* */
+ /* <Description> */
+ /* A structure used to hold a single list element. */
+ /* */
+ /* <Fields> */
+ /* prev :: The previous element in the list. NULL if first. */
+ /* */
+ /* next :: The next element in the list. NULL if last. */
+ /* */
+ /* data :: A typeless pointer to the listed object. */
+ /* */
+ typedef struct FT_ListNodeRec_
+ {
+ FT_ListNode prev;
+ FT_ListNode next;
+ void* data;
+
+ } FT_ListNodeRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_ListRec */
+ /* */
+ /* <Description> */
+ /* A structure used to hold a simple doubly-linked list. These are */
+ /* used in many parts of FreeType. */
+ /* */
+ /* <Fields> */
+ /* head :: The head (first element) of doubly-linked list. */
+ /* */
+ /* tail :: The tail (last element) of doubly-linked list. */
+ /* */
+ typedef struct FT_ListRec_
+ {
+ FT_ListNode head;
+ FT_ListNode tail;
+
+ } FT_ListRec;
+
+
+#define FT_IS_EMPTY( list ) ( (list).head == 0 )
+
+
+#endif /* FTTYPES_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* autohint.h */
+/* */
+/* High-level `autohint' module-specific interface (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* The auto-hinter is used to load and automatically hint glyphs if a */
+ /* format-specific hinter isn't available. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef AUTOHINT_H
+#define AUTOHINT_H
+
+
+ /*************************************************************************/
+ /* */
+ /* A small technical note regarding automatic hinting in order to */
+ /* clarify this module interface. */
+ /* */
+ /* An automatic hinter might compute two kinds of data for a given face: */
+ /* */
+ /* - global hints: Usually some metrics that describe global properties */
+ /* of the face. It is computed by scanning more or less */
+ /* agressively the glyphs in the face, and thus can be */
+ /* very slow to compute (even if the size of global */
+ /* hints is really small). */
+ /* */
+ /* - glyph hints: These describe some important features of the glyph */
+ /* outline, as well as how to align them. They are */
+ /* generally much faster to compute than global hints. */
+ /* */
+ /* The current FreeType auto-hinter does a pretty good job while */
+ /* performing fast computations for both global and glyph hints. */
+ /* However, we might be interested in introducing more complex and */
+ /* powerful algorithms in the future, like the one described in the John */
+ /* D. Hobby paper, which unfortunately requires a lot more horsepower. */
+ /* */
+ /* Because a sufficiently sophisticated font management system would */
+ /* typically implement an LRU cache of opened face objects to reduce */
+ /* memory usage, it is a good idea to be able to avoid recomputing */
+ /* global hints every time the same face is re-opened. */
+ /* */
+ /* We thus provide the ability to cache global hints outside of the face */
+ /* object, in order to speed up font re-opening time. Of course, this */
+ /* feature is purely optional, so most client programs won't even notice */
+ /* it. */
+ /* */
+ /* I initially thought that it would be a good idea to cache the glyph */
+ /* hints too. However, my general idea now is that if you really need */
+ /* to cache these too, you are simply in need of a new font format, */
+ /* where all this information could be stored within the font file and */
+ /* decoded on the fly. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/freetype.h>
+
+
+ typedef struct FT_AutoHinterRec_ *FT_AutoHinter;
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_AutoHinter_Get_Global_Func */
+ /* */
+ /* <Description> */
+ /* Retrieves the global hints computed for a given face object the */
+ /* resulting data is dissociated from the face and will survive a */
+ /* call to FT_Done_Face(). It must be discarded through the API */
+ /* FT_AutoHinter_Done_Global_Func(). */
+ /* */
+ /* <Input> */
+ /* hinter :: A handle to the source auto-hinter. */
+ /* */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* <Output> */
+ /* global_hints :: A typeless pointer to the global hints. */
+ /* */
+ /* global_len :: The size in bytes of the global hints. */
+ /* */
+ typedef void (*FT_AutoHinter_Get_Global_Func)(
+ FT_AutoHinter hinter,
+ FT_Face face,
+ void** global_hints,
+ long* global_len );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_AutoHinter_Done_Global_Func */
+ /* */
+ /* <Description> */
+ /* Discards the global hints retrieved through */
+ /* FT_AutoHinter_Get_Global_Func(). This is the only way these hints */
+ /* are freed from memory. */
+ /* */
+ /* <Input> */
+ /* hinter :: A handle to the auto-hinter module. */
+ /* */
+ /* global :: A pointer to retrieved global hints to discard. */
+ /* */
+ typedef void (*FT_AutoHinter_Done_Global_Func)( FT_AutoHinter hinter,
+ void* global );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_AutoHinter_Reset_Func */
+ /* */
+ /* <Description> */
+ /* This function is used to recompute the global metrics in a given */
+ /* font. This is useful when global font data changes (e.g. Multiple */
+ /* Masters fonts where blend coordinates change). */
+ /* */
+ /* <Input> */
+ /* hinter :: A handle to the source auto-hinter. */
+ /* */
+ /* face :: A handle to the face. */
+ /* */
+ typedef void (*FT_AutoHinter_Reset_Func)( FT_AutoHinter hinter,
+ FT_Face face );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_AutoHinter_Load_Func */
+ /* */
+ /* <Description> */
+ /* This function is used to load, scale, and automatically hint a */
+ /* glyph from a given face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the face. */
+ /* glyph_index :: The glyph index. */
+ /* load_flags :: The load flags. */
+ /* */
+ /* <Note> */
+ /* This function is capable of loading composite glyphs by hinting */
+ /* each sub-glyph independently (which improves quality). */
+ /* */
+ /* It will call the font driver with FT_Load_Glyph(), with */
+ /* FT_LOAD_NO_SCALE set. */
+ /* */
+ typedef FT_Error (*FT_AutoHinter_Load_Func)( FT_AutoHinter hinter,
+ FT_GlyphSlot slot,
+ FT_Size size,
+ FT_UInt glyph_index,
+ FT_ULong load_flags );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_AutoHinter_Interface */
+ /* */
+ /* <Description> */
+ /* The auto-hinter module's interface. */
+ /* */
+ typedef struct FT_AutoHinter_Interface
+ {
+ FT_AutoHinter_Reset_Func reset_face;
+ FT_AutoHinter_Load_Func load_glyph;
+
+ FT_AutoHinter_Get_Global_Func get_global_hints;
+ FT_AutoHinter_Done_Global_Func done_global_hints;
+
+ } FT_AutoHinter_Interface;
+
+
+#endif /* AUTOHINT_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftcalc.h */
+/* */
+/* Arithmetic computations (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTCALC_H
+#define FTCALC_H
+
+#include <freetype/freetype.h>
+#include <freetype/config/ftconfig.h> /* for LONG64 */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+#ifdef LONG64
+
+
+ typedef INT64 FT_Int64;
+
+#define ADD_64( x, y, z ) z = (x) + (y)
+#define MUL_64( x, y, z ) z = (FT_Int64)(x) * (y)
+
+#define DIV_64( x, y ) ( (x) / (y) )
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+#define SQRT_64( z ) FT_Sqrt64( z )
+
+ FT_EXPORT_DEF( FT_Int32 ) FT_Sqrt64( FT_Int64 l );
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+#else /* LONG64 */
+
+
+ typedef struct FT_Int64_
+ {
+ FT_UInt32 lo;
+ FT_UInt32 hi;
+
+ } FT_Int64;
+
+
+#define ADD_64( x, y, z ) FT_Add64( &x, &y, &z )
+#define MUL_64( x, y, z ) FT_MulTo64( x, y, &z )
+#define DIV_64( x, y ) FT_Div64by32( &x, y )
+
+
+ FT_EXPORT_DEF( void ) FT_Add64( FT_Int64* x,
+ FT_Int64* y,
+ FT_Int64* z );
+
+ FT_EXPORT_DEF( void ) FT_MulTo64( FT_Int32 x,
+ FT_Int32 y,
+ FT_Int64* z );
+
+ FT_EXPORT_DEF( FT_Int32 ) FT_Div64by32( FT_Int64* x,
+ FT_Int32 y );
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+#define SQRT_64( z ) FT_Sqrt64( &z )
+
+ FT_EXPORT_DEF( FT_Int32 ) FT_Sqrt64( FT_Int64* x );
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+#endif /* LONG64 */
+
+
+#ifndef FT_CONFIG_OPTION_OLD_CALCS
+
+#define SQRT_32( x ) FT_Sqrt32( x )
+
+ BASE_DEF( FT_Int32 ) FT_Sqrt32( FT_Int32 x );
+
+#endif /* !FT_CONFIG_OPTION_OLD_CALCS */
+
+
+ /*************************************************************************/
+ /* */
+ /* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */
+ /* */
+ /*************************************************************************/
+
+
+#define INT_TO_F26DOT6( x ) ( (FT_Long)(x) << 6 )
+#define INT_TO_F2DOT14( x ) ( (FT_Long)(x) << 14 )
+#define INT_TO_FIXED( x ) ( (FT_Long)(x) << 16 )
+#define F2DOT14_TO_FIXED( x ) ( (FT_Long)(x) << 2 )
+#define FLOAT_TO_FIXED( x ) ( (FT_Long)( x * 65536.0 ) )
+
+#define ROUND_F26DOT6( x ) ( x >= 0 ? ( ( (x) + 32 ) & -64 ) \
+ : ( -( ( 32 - (x) ) & -64 ) ) )
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* FTCALC_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftdebug.h */
+/* */
+/* Debugging and logging component (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTDEBUG_H
+#define FTDEBUG_H
+
+#include <freetype/config/ftconfig.h> /* for FT_DEBUG_LEVEL_TRACE, */
+ /* FT_DEBUG_LEVEL_ERROR */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /* A very stupid pre-processor trick. See K&R version 2 */
+ /* section A12.3 for details... */
+ /* */
+ /* It is also described in the section `Separate */
+ /* Expansion of Macro Arguments' in the info file */
+ /* `cpp.info', describing GNU cpp. */
+ /* */
+#define FT_CAT( x, y ) x ## y
+#define FT_XCAT( x, y ) FT_CAT( x, y )
+
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+
+ /* note that not all levels are used currently */
+
+ typedef enum FT_Trace_
+ {
+ /* the first level must always be `trace_any' */
+ trace_any = 0,
+
+ /* base components */
+ trace_aaraster, /* anti-aliasing raster (ftgrays.c) */
+ trace_calc, /* calculations (ftcalc.c) */
+ trace_extend, /* extension manager (ftextend.c) */
+ trace_glyph, /* glyph manager (ftglyph.c) */
+ trace_io, /* i/o monitoring (ftsystem.c) */
+ trace_init, /* initialization (ftinit.c) */
+ trace_list, /* list manager (ftlist.c) */
+ trace_memory, /* memory manager (ftobjs.c) */
+ trace_mm, /* MM interface (ftmm.c) */
+ trace_objs, /* base objects (ftobjs.c) */
+ trace_outline, /* outline management (ftoutln.c) */
+ trace_raster, /* rasterizer (ftraster.c) */
+ trace_stream, /* stream manager (ftstream.c) */
+
+ /* SFNT driver components */
+ trace_sfobjs, /* SFNT object handler (sfobjs.c) */
+ trace_ttcmap, /* charmap handler (ttcmap.c) */
+ trace_ttload, /* basic TrueType tables (ttload.c) */
+ trace_ttpost, /* PS table processing (ttpost.c) */
+ trace_ttsbit, /* TrueType sbit handling (ttsbit.c) */
+
+ /* TrueType driver components */
+ trace_ttdriver, /* TT font driver (ttdriver.c) */
+ trace_ttgload, /* TT glyph loader (ttgload.c) */
+ trace_ttinterp, /* bytecode interpreter (ttinterp.c) */
+ trace_ttobjs, /* TT objects manager (ttobjs.c) */
+ trace_ttpload, /* TT data/program loader (ttpload.c) */
+
+ /* Type 1 driver components */
+ trace_t1driver,
+ trace_t1gload,
+ trace_t1hint,
+ trace_t1load,
+ trace_t1objs,
+
+ /* experimental Type 1 driver components */
+ trace_z1driver,
+ trace_z1gload,
+ trace_z1hint,
+ trace_z1load,
+ trace_z1objs,
+ trace_z1parse,
+
+ /* Type 2 driver components */
+ trace_t2driver,
+ trace_t2gload,
+ trace_t2load,
+ trace_t2objs,
+ trace_t2parse,
+
+ /* CID driver components */
+ trace_cidafm,
+ trace_ciddriver,
+ trace_cidgload,
+ trace_cidload,
+ trace_cidobjs,
+ trace_cidparse,
+
+ /* Windows fonts component */
+ trace_winfnt,
+
+ /* the last level must always be `trace_max' */
+ trace_max
+
+ } FT_Trace;
+
+
+ /* declared in ftdebug.c */
+ extern char ft_trace_levels[trace_max];
+
+
+ /*************************************************************************/
+ /* */
+ /* IMPORTANT! */
+ /* */
+ /* Each component must define the macro FT_COMPONENT to a valid FT_Trace */
+ /* value before using any TRACE macro. */
+ /* */
+ /*************************************************************************/
+
+
+#define FT_TRACE( level, varformat ) \
+ do \
+ { \
+ if ( ft_trace_levels[FT_COMPONENT] >= level ) \
+ FT_XCAT( FT_Message, varformat ); \
+ } while ( 0 )
+
+
+ FT_EXPORT_DEF( void ) FT_SetTraceLevel( FT_Trace component,
+ char level );
+
+
+#elif defined( FT_DEBUG_LEVEL_ERROR )
+
+
+#define FT_TRACE( level, varformat ) do ; while ( 0 ) /* nothing */
+
+
+#else /* release mode */
+
+
+#define FT_Assert( condition ) do ; while ( 0 ) /* nothing */
+
+#define FT_TRACE( level, varformat ) do ; while ( 0 ) /* nothing */
+#define FT_ERROR( varformat ) do ; while ( 0 ) /* nothing */
+
+
+#endif /* FT_DEBUG_LEVEL_TRACE, FT_DEBUG_LEVEL_ERROR */
+
+
+ /*************************************************************************/
+ /* */
+ /* Define macros and functions that are common to the debug and trace */
+ /* modes. */
+ /* */
+ /* You need vprintf() to be able to compile ftdebug.c. */
+ /* */
+ /*************************************************************************/
+
+
+#if defined( FT_DEBUG_LEVEL_TRACE ) || defined( FT_DEBUG_LEVEL_ERROR )
+
+
+#include "stdio.h" /* for vprintf() */
+
+
+#define FT_Assert( condition ) \
+ do \
+ { \
+ if ( !( condition ) ) \
+ FT_Panic( "assertion failed on line %d of file %s\n", \
+ __LINE__, __FILE__ ); \
+ } while ( 0 )
+
+ /* print a message */
+ FT_EXPORT_DEF( void ) FT_Message( const char* fmt, ... );
+
+ /* print a message and exit */
+ FT_EXPORT_DEF( void ) FT_Panic( const char* fmt, ... );
+
+#define FT_ERROR( varformat ) FT_XCAT( FT_Message, varformat )
+
+
+#endif /* FT_DEBUG_LEVEL_TRACE || FT_DEBUG_LEVEL_ERROR */
+
+
+ /*************************************************************************/
+ /* */
+ /* You need two opening resp. closing parentheses! */
+ /* */
+ /* Example: FT_TRACE0(( "Value is %i", foo )) */
+ /* */
+ /*************************************************************************/
+
+#define FT_TRACE0( varformat ) FT_TRACE( 0, varformat )
+#define FT_TRACE1( varformat ) FT_TRACE( 1, varformat )
+#define FT_TRACE2( varformat ) FT_TRACE( 2, varformat )
+#define FT_TRACE3( varformat ) FT_TRACE( 3, varformat )
+#define FT_TRACE4( varformat ) FT_TRACE( 4, varformat )
+#define FT_TRACE5( varformat ) FT_TRACE( 5, varformat )
+#define FT_TRACE6( varformat ) FT_TRACE( 6, varformat )
+#define FT_TRACE7( varformat ) FT_TRACE( 7, varformat )
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* FTDEBUG_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftdriver.h */
+/* */
+/* FreeType font driver interface (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTDRIVER_H
+#define FTDRIVER_H
+
+
+#include <freetype/ftmodule.h>
+#include <freetype/config/ftconfig.h>
+
+
+ typedef FT_Error (*FTDriver_initFace)( FT_Stream stream,
+ FT_Face face,
+ FT_Int typeface_index,
+ FT_Int num_params,
+ FT_Parameter* parameters );
+
+ typedef void (*FTDriver_doneFace)( FT_Face face );
+
+
+ typedef FT_Error (*FTDriver_initSize)( FT_Size size );
+
+ typedef void (*FTDriver_doneSize)( FT_Size size );
+
+
+ typedef FT_Error (*FTDriver_initGlyphSlot)( FT_GlyphSlot slot );
+
+ typedef void (*FTDriver_doneGlyphSlot)( FT_GlyphSlot slot );
+
+
+ typedef FT_Error (*FTDriver_setCharSizes)( FT_Size size,
+ FT_F26Dot6 char_width,
+ FT_F26Dot6 char_height,
+ FT_UInt horz_resolution,
+ FT_UInt vert_resolution );
+
+ typedef FT_Error (*FTDriver_setPixelSizes)( FT_Size size,
+ FT_UInt pixel_width,
+ FT_UInt pixel_height );
+
+ typedef FT_Error (*FTDriver_loadGlyph)( FT_GlyphSlot slot,
+ FT_Size size,
+ FT_UInt glyph_index,
+ FT_Int load_flags );
+
+
+ typedef FT_UInt (*FTDriver_getCharIndex)( FT_CharMap charmap,
+ FT_Long charcode );
+
+ typedef FT_Error (*FTDriver_getKerning)( FT_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_Vector* kerning );
+
+
+ typedef FT_Error (*FTDriver_attachFile)( FT_Face face,
+ FT_Stream stream );
+
+
+ typedef FT_Error (*FTDriver_getAdvances)( FT_Face face,
+ FT_UInt first,
+ FT_UInt count,
+ FT_Bool vertical,
+ FT_UShort* advances );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Driver_Class */
+ /* */
+ /* <Description> */
+ /* The font driver class. This structure mostly contains pointers to */
+ /* driver methods. */
+ /* */
+ /* <Fields> */
+ /* root :: The parent module. */
+ /* */
+ /* face_object_size :: The size of a face object in bytes. */
+ /* */
+ /* size_object_size :: The size of a size object in bytes. */
+ /* */
+ /* slot_object_size :: The size of a glyph object in bytes. */
+ /* */
+ /* init_face :: The format-specific face constructor. */
+ /* */
+ /* done_face :: The format-specific face destructor. */
+ /* */
+ /* init_size :: The format-specific size constructor. */
+ /* */
+ /* done_size :: The format-specific size destructor. */
+ /* */
+ /* init_slot :: The format-specific slot constructor. */
+ /* */
+ /* done_slot :: The format-specific slot destructor. */
+ /* */
+ /* set_char_sizes :: A handle to a function used to set the new */
+ /* character size in points + resolution. Can be */
+ /* set to 0 to indicate default behaviour. */
+ /* */
+ /* set_pixel_sizes :: A handle to a function used to set the new */
+ /* character size in pixels. Can be set to 0 to */
+ /* indicate default behaviour. */
+ /* */
+ /* load_glyph :: A function handle to load a given glyph image */
+ /* in a slot. This field is mandatory! */
+ /* */
+ /* get_char_index :: A function handle to return the glyph index of */
+ /* a given character for a given charmap. This */
+ /* field is mandatory! */
+ /* */
+ /* get_kerning :: A function handle to return the unscaled */
+ /* kerning for a given pair of glyphs. Can be */
+ /* set to 0 if the format doesn't support */
+ /* kerning. */
+ /* */
+ /* attach_file :: This function handle is used to read */
+ /* additional data for a face from another */
+ /* file/stream. For example, this can be used to */
+ /* add data from AFM or PFM files on a Type 1 */
+ /* face, or a CIDMap on a CID-keyed face. */
+ /* */
+ /* get_advances :: A function handle used to return the advances */
+ /* of 'count' glyphs, starting at `index'. the */
+ /* `vertical' flags must be set when vertical */
+ /* advances are queried. The advances buffer is */
+ /* caller-allocated. */
+ /* */
+ /* <Note> */
+ /* Most function pointers, with the exception of `load_glyph' and */
+ /* `get_char_index' can be set to 0 to indicate a default behaviour. */
+ /* */
+ typedef struct FT_Driver_Class_
+ {
+ FT_Module_Class root;
+
+ FT_Int face_object_size;
+ FT_Int size_object_size;
+ FT_Int slot_object_size;
+
+ FTDriver_initFace init_face;
+ FTDriver_doneFace done_face;
+
+ FTDriver_initSize init_size;
+ FTDriver_doneSize done_size;
+
+ FTDriver_initGlyphSlot init_slot;
+ FTDriver_doneGlyphSlot done_slot;
+
+ FTDriver_setCharSizes set_char_sizes;
+ FTDriver_setPixelSizes set_pixel_sizes;
+
+ FTDriver_loadGlyph load_glyph;
+ FTDriver_getCharIndex get_char_index;
+
+ FTDriver_getKerning get_kerning;
+ FTDriver_attachFile attach_file;
+
+ FTDriver_getAdvances get_advances;
+
+ } FT_Driver_Class;
+
+
+#endif /* FTDRIVER_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftextend.h */
+/* */
+/* FreeType extensions implementation (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTEXTEND_H
+#define FTEXTEND_H
+
+
+#include <freetype/internal/ftobjs.h>
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* The extensions don't need to be integrated at compile time into the */
+ /* engine, only at link time. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Extension_Initializer */
+ /* */
+ /* <Description> */
+ /* Each new face object can have several extensions associated with */
+ /* it at creation time. This function is used to initialize given */
+ /* extension data for a given face. */
+ /* */
+ /* <InOut> */
+ /* ext :: A typeless pointer to the extension data. */
+ /* */
+ /* face :: A handle to the source face object the extension is */
+ /* associated with. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* In case of error, the initializer should not destroy the extension */
+ /* data, as the finalizer will get called later by the function's */
+ /* caller. */
+ /* */
+ typedef FT_Error (*FT_Extension_Initializer)( void* ext,
+ FT_Face face );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Extension_Finalizer */
+ /* */
+ /* <Description> */
+ /* Each new face object can have several extensions associated with */
+ /* it at creation time. This function is used to finalize given */
+ /* extension data for a given face; it occurs before the face object */
+ /* itself is finalized. */
+ /* */
+ /* <InOut> */
+ /* ext :: A typeless pointer to the extension data. */
+ /* */
+ /* face :: A handle to the source face object the extension is */
+ /* associated with. */
+ /* */
+ typedef void (*FT_Extension_Finalizer)( void* ext,
+ FT_Face face );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Extension_Class */
+ /* */
+ /* <Description> */
+ /* A simple structure used to describe a given extension to the */
+ /* FreeType base layer. An FT_Extension_Class is used as a parameter */
+ /* for FT_Register_Extension(). */
+ /* */
+ /* <Fields> */
+ /* id :: The extension's ID. This is a normal C string that */
+ /* is used to uniquely reference the extension's */
+ /* interface. */
+ /* */
+ /* size :: The size in bytes of the extension data that must be */
+ /* associated with each face object. */
+ /* */
+ /* init :: A pointer to the extension data's initializer. */
+ /* */
+ /* finalize :: A pointer to the extension data's finalizer. */
+ /* */
+ /* interface :: This pointer can be anything, but should usually */
+ /* point to a table of function pointers which implement */
+ /* the extension's interface. */
+ /* */
+ /* offset :: This field is set and used within the base layer and */
+ /* should be set to 0 when registering an extension */
+ /* through FT_Register_Extension(). It contains an */
+ /* offset within the face's extension block for the */
+ /* current extension's data. */
+ /* */
+ typedef struct FT_Extension_Class_
+ {
+ const char* id;
+ FT_ULong size;
+ FT_Extension_Initializer init;
+ FT_Extension_Finalizer finalize;
+ void* interface;
+
+ FT_ULong offset;
+
+ } FT_Extension_Class;
+
+
+ FT_EXPORT_DEF( FT_Error ) FT_Register_Extension(
+ FT_Driver driver,
+ FT_Extension_Class* clazz );
+
+
+#ifdef FT_CONFIG_OPTION_EXTEND_ENGINE
+
+
+ /* Initialize the extension component */
+ LOCAL_DEF
+ FT_Error FT_Init_Extensions( FT_Library library );
+
+ /* Finalize the extension component */
+ LOCAL_DEF
+ FT_Error FT_Done_Extensions( FT_Library library );
+
+ /* Create an extension within a face object. Called by the */
+ /* face object constructor. */
+ LOCAL_DEF
+ FT_Error FT_Create_Extensions( FT_Face face );
+
+ /* Destroy all extensions within a face object. Called by the */
+ /* face object destructor. */
+ LOCAL_DEF
+ FT_Error FT_Destroy_Extensions( FT_Face face );
+
+
+#endif
+
+
+ /* return an extension's data & interface according to its ID */
+ FT_EXPORT_DEF( void* ) FT_Get_Extension(
+ FT_Face face,
+ const char* extension_id,
+ void** extension_interface );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* FTEXTEND_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftlist.c */
+/* */
+/* Generic list support for FreeType (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file implements functions relative to list processing. Its */
+ /* data structures are defined in `freetype.h'. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef FTLIST_H
+#define FTLIST_H
+
+#include <freetype/freetype.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ FT_EXPORT_DEF( FT_ListNode ) FT_List_Find( FT_List list,
+ void* data );
+
+ FT_EXPORT_DEF( void ) FT_List_Add( FT_List list,
+ FT_ListNode node );
+
+ FT_EXPORT_DEF( void ) FT_List_Insert( FT_List list,
+ FT_ListNode node );
+
+ FT_EXPORT_DEF( void ) FT_List_Remove( FT_List list,
+ FT_ListNode node );
+
+ FT_EXPORT_DEF( void ) FT_List_Up( FT_List list,
+ FT_ListNode node );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_List_Iterator */
+ /* */
+ /* <Description> */
+ /* An FT_List iterator function which is called during a list parse */
+ /* by FT_List_Iterate(). */
+ /* */
+ /* <Input> */
+ /* node :: The current iteration list node. */
+ /* */
+ /* user :: A typeless pointer passed to FT_List_Iterate(). */
+ /* Can be used to point to the iteration's state. */
+ /* */
+ typedef FT_Error (*FT_List_Iterator)( FT_ListNode node,
+ void* user );
+
+
+ FT_EXPORT_DEF( FT_Error ) FT_List_Iterate( FT_List list,
+ FT_List_Iterator iterator,
+ void* user );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_List_Destructor */
+ /* */
+ /* <Description> */
+ /* An FT_List iterator function which is called during a list */
+ /* finalization by FT_List_Finalize() to destroy all elements in a */
+ /* given list. */
+ /* */
+ /* <Input> */
+ /* system :: The current system object. */
+ /* */
+ /* data :: The current object to destroy. */
+ /* */
+ /* user :: A typeless pointer passed to FT_List_Iterate(). It can */
+ /* be used to point to the iteration's state. */
+ /* */
+ typedef void (*FT_List_Destructor)( FT_Memory memory,
+ void* data,
+ void* user );
+
+
+ FT_EXPORT_DEF( void ) FT_List_Finalize( FT_List list,
+ FT_List_Destructor destroy,
+ FT_Memory memory,
+ void* user );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* FTLIST_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftmemory.h */
+/* */
+/* The FreeType memory management macros (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTMEMORY_H
+#define FTMEMORY_H
+
+
+#include <freetype/config/ftconfig.h>
+#include <freetype/fttypes.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* <Macro> */
+ /* FT_SET_ERROR */
+ /* */
+ /* <Description> */
+ /* This macro is used to set an implicit `error' variable to a given */
+ /* expression's value (usually a function call), and convert it to a */
+ /* boolean which is set whenever the value is != 0. */
+ /* */
+#undef FT_SET_ERROR
+#define FT_SET_ERROR( expression ) \
+ ( ( error = (expression) ) != 0 )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** M E M O R Y ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ BASE_DEF( FT_Error ) FT_Alloc( FT_Memory memory,
+ FT_Long size,
+ void** P );
+
+ BASE_DEF( FT_Error ) FT_Realloc( FT_Memory memory,
+ FT_Long current,
+ FT_Long size,
+ void** P );
+
+ BASE_DEF( void ) FT_Free( FT_Memory memory,
+ void** P );
+
+
+
+ /* This `#include' is needed by the MEM_xxx() macros; it should be */
+ /* available on all platforms we know of. */
+#include <string.h>
+
+#define MEM_Set( dest, byte, count ) memset( dest, byte, count )
+
+#define MEM_Copy( dest, source, count ) memcpy( dest, source, count )
+
+#define MEM_Move( dest, source, count ) memmove( dest, source, count )
+
+
+ /*************************************************************************/
+ /* */
+ /* We now support closures to produce completely reentrant code. This */
+ /* means the allocation functions now takes an additional argument */
+ /* (`memory'). It is a handle to a given memory object, responsible for */
+ /* all low-level operations, including memory management and */
+ /* synchronisation. */
+ /* */
+ /* In order to keep our code readable and use the same macros in the */
+ /* font drivers and the rest of the library, MEM_Alloc(), ALLOC(), and */
+ /* ALLOC_ARRAY() now use an implicit variable, `memory'. It must be */
+ /* defined at all locations where a memory operation is queried. */
+ /* */
+#define MEM_Alloc( _pointer_, _size_ ) \
+ FT_Alloc( memory, _size_, (void**)&(_pointer_) )
+
+#define MEM_Alloc_Array( _pointer_, _count_, _type_ ) \
+ FT_Alloc( memory, (_count_)*sizeof ( _type_ ), \
+ (void**)&(_pointer_) )
+
+#define MEM_Realloc( _pointer_, _current_, _size_ ) \
+ FT_Realloc( memory, _current_, _size_, (void**)&(_pointer_) )
+
+#define MEM_Realloc_Array( _pointer_, _current_, _new_, _type_ ) \
+ FT_Realloc( memory, (_current_)*sizeof ( _type_ ), \
+ (_new_)*sizeof ( _type_ ), (void**)&(_pointer_) )
+
+#define ALLOC( _pointer_, _size_ ) \
+ FT_SET_ERROR( MEM_Alloc( _pointer_, _size_ ) )
+
+#define REALLOC( _pointer_, _current_, _size_ ) \
+ FT_SET_ERROR( MEM_Realloc( _pointer_, _current_, _size_ ) )
+
+#define ALLOC_ARRAY( _pointer_, _count_, _type_ ) \
+ FT_SET_ERROR( MEM_Alloc( _pointer_, \
+ (_count_)*sizeof ( _type_ ) ) )
+
+#define REALLOC_ARRAY( _pointer_, _current_, _count_, _type_ ) \
+ FT_SET_ERROR( MEM_Realloc( _pointer_, \
+ (_current_)*sizeof ( _type_ ), \
+ (_count_)*sizeof ( _type_ ) ) )
+
+#define FREE( _pointer_ ) FT_Free( memory, (void**)&(_pointer_) )
+
+
+#endif /* FTMEMORY_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftobjs.h */
+/* */
+/* The FreeType private base classes (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file contains the definition of all internal FreeType classes. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef FTOBJS_H
+#define FTOBJS_H
+
+#include <freetype/internal/ftmemory.h>
+#include <freetype/ftrender.h>
+#include <freetype/internal/ftdriver.h>
+#include <freetype/internal/autohint.h>
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* Some generic definitions. */
+ /* */
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+#ifndef UNUSED
+#define UNUSED( arg ) ( (arg)=(arg) )
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* The min and max functions missing in C. As usual, be careful not to */
+ /* write things like MIN( a++, b++ ) to avoid side effects. */
+ /* */
+#ifndef MIN
+#define MIN( a, b ) ( (a) < (b) ? (a) : (b) )
+#endif
+
+#ifndef MAX
+#define MAX( a, b ) ( (a) > (b) ? (a) : (b) )
+#endif
+
+#ifndef ABS
+#define ABS( a ) ( (a) < 0 ? -(a) : (a) )
+#endif
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** M O D U L E S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_ModuleRec */
+ /* */
+ /* <Description> */
+ /* A module object instance. */
+ /* */
+ /* <Fields> */
+ /* clazz :: A pointer to the module's class. */
+ /* */
+ /* library :: A handle to the parent library object. */
+ /* */
+ /* memory :: A handle to the memory manager. */
+ /* */
+ /* generic :: A generic structure for user-level extensibility (?). */
+ /* */
+ typedef struct FT_ModuleRec_
+ {
+ FT_Module_Class* clazz;
+ FT_Library library;
+ FT_Memory memory;
+ FT_Generic generic;
+
+ } FT_ModuleRec;
+
+
+ /* typecast an object to a FT_Module */
+#define FT_MODULE( x ) ((FT_Module)(x))
+#define FT_MODULE_CLASS( x ) FT_MODULE(x)->clazz
+#define FT_MODULE_LIBRARY( x ) FT_MODULE(x)->library
+#define FT_MODULE_MEMORY( x ) FT_MODULE(x)->memory
+
+#define FT_MODULE_IS_DRIVER( x ) ( FT_MODULE_CLASS( x )->module_flags & \
+ ft_module_font_driver )
+
+#define FT_MODULE_IS_RENDERER( x ) ( FT_MODULE_CLASS( x )->module_flags & \
+ ft_module_renderer )
+
+#define FT_MODULE_IS_HINTER( x ) ( FT_MODULE_CLASS( x )->module_flags & \
+ ft_module_hinter )
+
+#define FT_MODULE_IS_STYLER( x ) ( FT_MODULE_CLASS( x )->module_flags & \
+ ft_module_styler )
+
+#define FT_DRIVER_IS_SCALABLE( x ) ( FT_MODULE_CLASS(x)->module_flags & \
+ ft_module_driver_scalable )
+
+#define FT_DRIVER_USES_OUTLINES( x ) !( FT_MODULE_CLASS(x)->module_flags & \
+ ft_module_driver_no_outlines )
+
+#define FT_DRIVER_HAS_HINTER( x ) ( FT_MODULE_CLASS(x)->module_flags & \
+ ft_module_driver_has_hinter )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Module_Interface */
+ /* */
+ /* <Description> */
+ /* Finds a module and returns its specific interface as a typeless */
+ /* pointer. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* module_name :: The module's name (as an ASCII string). */
+ /* */
+ /* <Return> */
+ /* A module-specific interface if available, 0 otherwise. */
+ /* */
+ /* <Note> */
+ /* You should better be familiar with FreeType internals to know */
+ /* which module to look for, and what its interface is :-) */
+ /* */
+ BASE_DEF( const void* ) FT_Get_Module_Interface( FT_Library library,
+ const char* mod_name );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* a few macros used to perform easy typecasts with minimal brain damage */
+
+#define FT_FACE( x ) ((FT_Face)(x))
+#define FT_SIZE( x ) ((FT_Size)(x))
+#define FT_SLOT( x ) ((FT_GlyphSlot)(x))
+
+#define FT_FACE_DRIVER( x ) FT_FACE( x )->driver
+#define FT_FACE_LIBRARY( x ) FT_FACE_DRIVER( x )->root.library
+#define FT_FACE_MEMORY( x ) FT_FACE( x )->memory
+
+#define FT_SIZE_FACE( x ) FT_SIZE( x )->face
+#define FT_SLOT_FACE( x ) FT_SLOT( x )->face
+
+#define FT_FACE_SLOT( x ) FT_FACE( x )->glyph
+#define FT_FACE_SIZE( x ) FT_FACE( x )->size
+
+
+ /* this must be kept exported -- tt will be used later in our own */
+ /* high-level caching font manager called SemTex (way after the */
+ /* 2.0 release though */
+ FT_EXPORT_DEF( FT_Error ) FT_New_Size( FT_Face face,
+ FT_Size* size );
+
+ FT_EXPORT_DEF( FT_Error ) FT_Done_Size( FT_Size size );
+
+
+ FT_EXPORT_DEF( FT_Error ) FT_New_GlyphSlot( FT_Face face,
+ FT_GlyphSlot* aslot );
+
+ FT_EXPORT_DEF( void ) FT_Done_GlyphSlot( FT_GlyphSlot slot );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** G L Y P H L O A D E R ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1
+#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2
+#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4
+#define FT_SUBGLYPH_FLAG_SCALE 8
+#define FT_SUBGLYPH_FLAG_XY_SCALE 0x40
+#define FT_SUBGLYPH_FLAG_2X2 0x80
+#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200
+
+
+ enum
+ {
+ ft_glyph_own_bitmap = 1
+ };
+
+
+ struct FT_SubGlyph_
+ {
+ FT_Int index;
+ FT_UShort flags;
+ FT_Int arg1;
+ FT_Int arg2;
+ FT_Matrix transform;
+ };
+
+
+ typedef struct FT_GlyphLoad_
+ {
+ FT_Outline outline; /* outline */
+ FT_UInt num_subglyphs; /* number of subglyphs */
+ FT_SubGlyph* subglyphs; /* subglyphs */
+ FT_Vector* extra_points; /* extra points table */
+
+ } FT_GlyphLoad;
+
+
+ struct FT_GlyphLoader_
+ {
+ FT_Memory memory;
+ FT_UInt max_points;
+ FT_UInt max_contours;
+ FT_UInt max_subglyphs;
+ FT_Bool use_extra;
+
+ FT_GlyphLoad base;
+ FT_GlyphLoad current;
+
+ void* other; /* for possible future extension? */
+
+ };
+
+
+ BASE_DEF( FT_Error ) FT_GlyphLoader_New( FT_Memory memory,
+ FT_GlyphLoader** aloader );
+
+ BASE_DEF( FT_Error ) FT_GlyphLoader_Create_Extra(
+ FT_GlyphLoader* loader );
+
+ BASE_DEF( void ) FT_GlyphLoader_Done( FT_GlyphLoader* loader );
+
+ BASE_DEF( void ) FT_GlyphLoader_Reset( FT_GlyphLoader* loader );
+
+ BASE_DEF( void ) FT_GlyphLoader_Rewind( FT_GlyphLoader* loader );
+
+ BASE_DEF( FT_Error ) FT_GlyphLoader_Check_Points(
+ FT_GlyphLoader* loader,
+ FT_UInt n_points,
+ FT_UInt n_contours );
+
+ BASE_DEF( FT_Error ) FT_GlyphLoader_Check_Subglyphs(
+ FT_GlyphLoader* loader,
+ FT_UInt n_subs );
+
+ BASE_DEF( void ) FT_GlyphLoader_Prepare( FT_GlyphLoader* loader );
+
+ BASE_DEF( void ) FT_GlyphLoader_Add( FT_GlyphLoader* loader );
+
+ BASE_DEF( FT_Error ) FT_GlyphLoader_Copy_Points( FT_GlyphLoader* target,
+ FT_GlyphLoader* source );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** R E N D E R E R S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#define FT_RENDERER( x ) ((FT_Renderer)( x ))
+#define FT_GLYPH( x ) ((FT_Glyph)( x ))
+#define FT_BITMAP_GLYPH( x ) ((FT_BitmapGlyph)( x ))
+#define FT_OUTLINE_GLYPH( x ) ((FT_OutlineGlyph)( x ))
+
+
+ typedef struct FT_RendererRec_
+ {
+ FT_ModuleRec root;
+ FT_Renderer_Class* clazz;
+ FT_Glyph_Format glyph_format;
+ const FT_Glyph_Class glyph_class;
+
+ FT_Raster raster;
+ FT_Raster_Render_Func raster_render;
+ FTRenderer_render render;
+
+ } FT_RendererRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** F O N T D R I V E R S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* typecast a module into a driver easily */
+#define FT_DRIVER( x ) ((FT_Driver)(x))
+
+ /* typecast a module as a driver, and get its driver class */
+#define FT_DRIVER_CLASS( x ) FT_DRIVER( x )->clazz
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_DriverRec */
+ /* */
+ /* <Description> */
+ /* The root font driver class. A font driver is responsible for */
+ /* managing and loading font files of a given format. */
+ /* */
+ /* <Fields> */
+ /* root :: Contains the fields of the root module class. */
+ /* */
+ /* clazz :: A pointer to the font driver's class. Note that */
+ /* this is NOT root.clazz. `class' wasn't used */
+ /* as it is a reserved word in C++. */
+ /* */
+ /* faces_list :: The list of faces currently opened by this */
+ /* driver. */
+ /* */
+ /* extensions :: A typeless pointer to the driver's extensions */
+ /* registry, if they are supported through the */
+ /* configuration macro FT_CONFIG_OPTION_EXTENSIONS. */
+ /* */
+ /* glyph_loader :: The glyph loader for all faces managed by this */
+ /* driver. This object isn't defined for unscalable */
+ /* formats. */
+ /* */
+ typedef struct FT_DriverRec_
+ {
+ FT_ModuleRec root;
+ FT_Driver_Class* clazz;
+
+ FT_ListRec faces_list;
+ void* extensions;
+
+ FT_GlyphLoader* glyph_loader;
+
+ } FT_DriverRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** L I B R A R I E S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#define FT_DEBUG_HOOK_TRUETYPE 0
+#define FT_DEBUG_HOOK_TYPE1 1
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_LibraryRec */
+ /* */
+ /* <Description> */
+ /* The FreeType library class. This is the root of all FreeType */
+ /* data. Use FT_New_Library() to create a library object, and */
+ /* FT_Done_Library() to discard it and all child objects. */
+ /* */
+ /* <Fields> */
+ /* memory :: The library's memory object. Manages memory */
+ /* allocation. */
+ /* */
+ /* generic :: Client data variable. Used to extend the */
+ /* Library class by higher levels and clients. */
+ /* */
+ /* num_modules :: The number of modules currently registered */
+ /* within this library. This is set to 0 for new */
+ /* libraries. New modules are added through the */
+ /* FT_Add_Module() API function. */
+ /* */
+ /* modules :: A table used to store handles to the currently */
+ /* registered modules. Note that each font driver */
+ /* contains a list of its opened faces. */
+ /* */
+ /* renderers :: The list of renderers currently registered */
+ /* within the library. */
+ /* */
+ /* cur_renderer :: The current outline renderer. This is a */
+ /* shortcut used to avoid parsing the list on */
+ /* each call to FT_Outline_Render(). It is a */
+ /* handle to the current renderer for the */
+ /* ft_glyph_format_outline format. */
+ /* */
+ /* auto_hinter :: XXX */
+ /* */
+ /* raster_pool :: The raster object's render pool. This can */
+ /* ideally be changed dynamically at run-time. */
+ /* */
+ /* raster_pool_size :: The size of the render pool in bytes. */
+ /* */
+ /* debug_hooks :: XXX */
+ /* */
+ typedef struct FT_LibraryRec_
+ {
+ FT_Memory memory; /* library's memory manager */
+
+ FT_Generic generic;
+
+ FT_UInt num_modules;
+ FT_Module modules[FT_MAX_MODULES]; /* module objects */
+
+ FT_ListRec renderers; /* list of renderers */
+ FT_Renderer cur_renderer; /* current outline renderer */
+ FT_Module auto_hinter;
+
+ FT_Byte* raster_pool; /* scan-line conversion */
+ /* render pool */
+ FT_ULong raster_pool_size; /* size of render pool in bytes */
+
+ FT_DebugHook_Func debug_hooks[4];
+
+ } FT_LibraryRec;
+
+
+ BASE_DEF( FT_Renderer ) FT_Lookup_Renderer( FT_Library library,
+ FT_Glyph_Format format,
+ FT_ListNode* node );
+
+ BASE_DEF( FT_Error ) FT_Render_Glyph_Internal( FT_Library library,
+ FT_GlyphSlot slot,
+ FT_UInt render_mode );
+
+ typedef FT_Error (*FT_Glyph_Name_Requester)( FT_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max );
+
+
+#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM
+
+
+ FT_EXPORT_DEF( FT_Error ) FT_New_Stream( const char* filepathname,
+ FT_Stream astream );
+
+ FT_EXPORT_DEF( void ) FT_Done_Stream( FT_Stream stream );
+
+ FT_EXPORT_DEF( FT_Memory ) FT_New_Memory( void );
+
+
+#endif /* !FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM */
+
+
+ /* Define default raster's interface. The default raster is located in */
+ /* `src/base/ftraster.c' */
+ /* */
+ /* Client applications can register new rasters through the */
+ /* FT_Set_Raster() API. */
+
+#ifndef FT_NO_DEFAULT_RASTER
+ FT_EXPORT_VAR( FT_Raster_Funcs ) ft_default_raster;
+#endif
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* FTOBJS_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftstream.h */
+/* */
+/* Stream handling(specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTSTREAM_H
+#define FTSTREAM_H
+
+#include <freetype/internal/ftobjs.h>
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /* format of an 8-bit frame_op value = [ xxxxx | e | s ] */
+ /* s is set to 1 if the value is signed, */
+ /* e is set to 1 if the value is little-endian */
+ /* xxxxx is a command */
+
+#define FT_FRAME_OP_SHIFT 2
+#define FT_FRAME_OP_SIGNED 1
+#define FT_FRAME_OP_LITTLE 2
+#define FT_FRAME_OP_COMMAND( x ) ( x >> FT_FRAME_OP_SHIFT )
+
+#define FT_MAKE_FRAME_OP( command, little, sign ) \
+ ( ( command << FT_FRAME_OP_SHIFT ) | ( little << 1 ) | sign )
+
+#define FT_FRAME_OP_END 0
+#define FT_FRAME_OP_START 1 /* start a new frame */
+#define FT_FRAME_OP_BYTE 2 /* read 1-byte value */
+#define FT_FRAME_OP_SHORT 3 /* read 2-byte value */
+#define FT_FRAME_OP_LONG 4 /* read 4-byte value */
+#define FT_FRAME_OP_OFF3 5 /* read 3-byte value */
+#define FT_FRAME_OP_BYTES 6 /* read a bytes sequence */
+
+
+ typedef enum FT_Frame_Op_
+ {
+ ft_frame_end = 0,
+ ft_frame_start = FT_MAKE_FRAME_OP( FT_FRAME_OP_START, 0, 0 ),
+
+ ft_frame_byte = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE, 0, 0 ),
+ ft_frame_schar = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE, 0, 1 ),
+
+ ft_frame_ushort_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 0 ),
+ ft_frame_short_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 1 ),
+ ft_frame_ushort_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 0 ),
+ ft_frame_short_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 1 ),
+
+ ft_frame_ulong_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 0 ),
+ ft_frame_ulong_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 1 ),
+ ft_frame_long_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 0 ),
+ ft_frame_long_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 1 ),
+
+ ft_frame_uoff3_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 0 ),
+ ft_frame_uoff3_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 1 ),
+ ft_frame_off3_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 0 ),
+ ft_frame_off3_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 1 ),
+
+ ft_frame_bytes = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 0 ),
+ ft_frame_skip = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 1 )
+
+ } FT_Frame_Op;
+
+
+ typedef struct FT_Frame_Field_
+ {
+ FT_Frame_Op value;
+ char size;
+ FT_UShort offset;
+
+ } FT_Frame_Field;
+
+
+ /* make-up a FT_Frame_Field out of a structure type and a field name */
+#define FT_FIELD_REF( s, f ) (((s*)0)->f)
+
+#define FT_FRAME_FIELD( frame_op, struct_type, field ) \
+ { \
+ frame_op, \
+ sizeof ( FT_FIELD_REF( struct_type,field ) ), \
+ (FT_UShort)(char*)&FT_FIELD_REF( struct_type, field ) \
+ }
+
+#define FT_MAKE_EMPTY_FIELD( frame_op ) { frame_op, 0, 0 }
+
+#define FT_FRAME_START( s ) { ft_frame_start, 0, s }
+#define FT_FRAME_END { ft_frame_end, 0, 0 }
+
+#define FT_FRAME_LONG( s, f ) FT_FRAME_FIELD( ft_frame_long_be, s, f )
+#define FT_FRAME_ULONG( s, f ) FT_FRAME_FIELD( ft_frame_ulong_be, s, f )
+#define FT_FRAME_SHORT( s, f ) FT_FRAME_FIELD( ft_frame_short_be, s, f )
+#define FT_FRAME_USHORT( s, f ) FT_FRAME_FIELD( ft_frame_ushort_be, s, f )
+#define FT_FRAME_BYTE( s, f ) FT_FRAME_FIELD( ft_frame_byte, s, f )
+#define FT_FRAME_CHAR( s, f ) FT_FRAME_FIELD( ft_frame_schar, s, f )
+
+#define FT_FRAME_LONG_LE( s, f ) FT_FRAME_FIELD( ft_frame_long_le, s, f )
+#define FT_FRAME_ULONG_LE( s, f ) FT_FRAME_FIELD( ft_frame_ulong_le, s, f )
+#define FT_FRAME_SHORT_LE( s, f ) FT_FRAME_FIELD( ft_frame_short_le, s, f )
+#define FT_FRAME_USHORT_LE( s, f ) FT_FRAME_FIELD( ft_frame_ushort_le, s, f )
+
+#define FT_FRAME_SKIP_LONG { ft_frame_long_be, 0, 0 }
+#define FT_FRAME_SKIP_SHORT { ft_frame_short_be, 0, 0 }
+#define FT_FRAME_SKIP_BYTE { ft_frame_byte, 0, 0 }
+
+#define FT_FRAME_BYTES( struct_type, field, count ) \
+ { \
+ ft_frame_bytes, \
+ count, \
+ (FT_UShort)(char*)&FT_FIELD_REF( struct_type, field ) \
+ }
+#define FT_FRAME_SKIP_BYTES( count ) { ft_frame_skip, count, 0 }
+
+
+
+ /*************************************************************************/
+ /* */
+ /* integer extraction macros -- the `buffer' parameter must ALWAYS be of */
+ /* type `char*' or equivalent (1-byte elements). */
+ /* */
+#define NEXT_Char( buffer ) \
+ ( (signed char)*buffer++ )
+#define NEXT_Byte( buffer ) \
+ ( (unsigned char)*buffer++ )
+
+#define NEXT_Short( buffer ) \
+ ( buffer += 2, \
+ ( (short)( (signed char)buffer[-2] << 8 ) | \
+ (unsigned char)buffer[-1] ) )
+
+#define NEXT_UShort( buffer ) \
+ ( (unsigned short)NEXT_Short( buffer ) )
+
+#define NEXT_Offset( buffer ) \
+ ( buffer += 3, \
+ ( ( (long)(signed char)buffer[-3] << 16 ) | \
+ ( (long)(unsigned char)buffer[-2] << 8 ) | \
+ (long)(unsigned char)buffer[-1] ) )
+
+#define NEXT_UOffset( buffer ) \
+ ( (unsigned long)NEXT_Offset( buffer ) )
+
+#define NEXT_Long( buffer ) \
+ ( buffer += 4, \
+ ( ( (long)(signed char)buffer[-4] << 24 ) | \
+ ( (long)(unsigned char)buffer[-3] << 16 ) | \
+ ( (long)(unsigned char)buffer[-2] << 8 ) | \
+ (long)(unsigned char)buffer[-1] ) )
+
+#define NEXT_ULong( buffer ) \
+ ( (unsigned long)NEXT_Long( buffer ) )
+
+
+#define NEXT_ShortLE( buffer ) \
+ ( buffer += 2, \
+ ( (short)( (signed char)buffer[-1] << 8 ) | \
+ (unsigned char)buffer[-2] ) )
+
+#define NEXT_UShortLE( buffer ) \
+ ( (unsigned short)NEXT_ShortLE( buffer ) )
+
+#define NEXT_OffsetLE( buffer ) \
+ ( buffer += 3, \
+ ( ( (long)(signed char)buffer[-1] << 16 ) | \
+ ( (long)(unsigned char)buffer[-2] << 8 ) | \
+ (long)(unsigned char)buffer[-3] ) )
+
+#define NEXT_UOffsetLE( buffer ) \
+ ( (unsigned long)NEXT_OffsetLE( buffer ) )
+
+
+#define NEXT_LongLE( buffer ) \
+ ( buffer += 4, \
+ ( ( (long)(signed char)buffer[-1] << 24 ) | \
+ ( (long)(unsigned char)buffer[-2] << 16 ) | \
+ ( (long)(unsigned char)buffer[-3] << 8 ) | \
+ (long)(unsigned char)buffer[-4] ) )
+
+#define NEXT_ULongLE( buffer ) \
+ ( (unsigned long)NEXT_LongLE( buffer ) )
+
+
+ /*************************************************************************/
+ /* */
+ /* Each GET_xxxx() macro uses an implicit `stream' variable. */
+ /* */
+#define FT_GET_MACRO( func, type ) ( (type)func( stream ) )
+
+#define GET_Char() FT_GET_MACRO( FT_Get_Char, FT_Char )
+#define GET_Byte() FT_GET_MACRO( FT_Get_Char, FT_Byte )
+#define GET_Short() FT_GET_MACRO( FT_Get_Short, FT_Short )
+#define GET_UShort() FT_GET_MACRO( FT_Get_Short, FT_UShort )
+#define GET_Offset() FT_GET_MACRO( FT_Get_Offset, FT_Long )
+#define GET_UOffset() FT_GET_MACRO( FT_Get_Offset, FT_ULong )
+#define GET_Long() FT_GET_MACRO( FT_Get_Long, FT_Long )
+#define GET_ULong() FT_GET_MACRO( FT_Get_Long, FT_ULong )
+#define GET_Tag4() FT_GET_MACRO( FT_Get_Long, FT_ULong )
+
+#define GET_ShortLE() FT_GET_MACRO( FT_Get_ShortLE, FT_Short )
+#define GET_UShortLE() FT_GET_MACRO( FT_Get_ShortLE, FT_UShort )
+#define GET_LongLE() FT_GET_MACRO( FT_Get_LongLE, FT_Short )
+#define GET_ULongLE() FT_GET_MACRO( FT_Get_LongLE, FT_Short )
+
+#define FT_READ_MACRO( func, type, var ) \
+ ( var = (type)func( stream, &error ), \
+ error != FT_Err_Ok )
+
+#define READ_Byte( var ) FT_READ_MACRO( FT_Read_Char, FT_Byte, var )
+#define READ_Char( var ) FT_READ_MACRO( FT_Read_Char, FT_Char, var )
+#define READ_Short( var ) FT_READ_MACRO( FT_Read_Short, FT_Short, var )
+#define READ_UShort( var ) FT_READ_MACRO( FT_Read_Short, FT_UShort, var )
+#define READ_Offset( var ) FT_READ_MACRO( FT_Read_Offset, FT_Long, var )
+#define READ_UOffset( var ) FT_READ_MACRO( FT_Read_Offset, FT_ULong, var )
+#define READ_Long( var ) FT_READ_MACRO( FT_Read_Long, FT_Long, var )
+#define READ_ULong( var ) FT_READ_MACRO( FT_Read_Long, FT_ULong, var )
+
+#define READ_ShortLE( var ) FT_READ_MACRO( FT_Read_ShortLE, FT_Short, var )
+#define READ_UShortLE( var ) FT_READ_MACRO( FT_Read_ShortLE, FT_UShort, var )
+#define READ_LongLE( var ) FT_READ_MACRO( FT_Read_LongLE, FT_Long, var )
+#define READ_ULongLE( var ) FT_READ_MACRO( FT_Read_LongLE, FT_ULong, var )
+
+
+ BASE_DEF( void ) FT_New_Memory_Stream( FT_Library library,
+ FT_Byte* base,
+ FT_ULong size,
+ FT_Stream stream );
+
+ BASE_DEF( FT_Error ) FT_Seek_Stream( FT_Stream stream,
+ FT_ULong pos );
+
+ BASE_DEF( FT_Error ) FT_Skip_Stream( FT_Stream stream,
+ FT_Long distance );
+
+ BASE_DEF( FT_Long ) FT_Stream_Pos( FT_Stream stream );
+
+
+ BASE_DEF( FT_Error ) FT_Read_Stream( FT_Stream stream,
+ FT_Byte* buffer,
+ FT_ULong count );
+
+ BASE_DEF( FT_Error ) FT_Read_Stream_At( FT_Stream stream,
+ FT_ULong pos,
+ FT_Byte* buffer,
+ FT_ULong count );
+
+ BASE_DEF( FT_Error ) FT_Access_Frame( FT_Stream stream,
+ FT_ULong count );
+
+ BASE_DEF( void ) FT_Forget_Frame( FT_Stream stream );
+
+ BASE_DEF( FT_Error ) FT_Extract_Frame( FT_Stream stream,
+ FT_ULong count,
+ FT_Byte** pbytes );
+
+ BASE_DEF( void ) FT_Release_Frame( FT_Stream stream,
+ FT_Byte** pbytes );
+
+ BASE_DEF( FT_Char ) FT_Get_Char( FT_Stream stream );
+
+ BASE_DEF( FT_Short ) FT_Get_Short( FT_Stream stream );
+
+ BASE_DEF( FT_Long ) FT_Get_Offset( FT_Stream stream );
+
+ BASE_DEF( FT_Long ) FT_Get_Long( FT_Stream stream );
+
+ BASE_DEF( FT_Short ) FT_Get_ShortLE( FT_Stream stream );
+
+ BASE_DEF( FT_Long ) FT_Get_LongLE( FT_Stream stream );
+
+
+ BASE_DEF( FT_Char ) FT_Read_Char( FT_Stream stream,
+ FT_Error* error );
+
+ BASE_DEF( FT_Short ) FT_Read_Short( FT_Stream stream,
+ FT_Error* error );
+
+ BASE_DEF( FT_Long ) FT_Read_Offset( FT_Stream stream,
+ FT_Error* error );
+
+ BASE_DEF( FT_Long ) FT_Read_Long( FT_Stream stream,
+ FT_Error* error );
+
+ BASE_DEF( FT_Short ) FT_Read_ShortLE( FT_Stream stream,
+ FT_Error* error );
+
+ BASE_DEF( FT_Long ) FT_Read_LongLE( FT_Stream stream,
+ FT_Error* error );
+
+ BASE_DEF( FT_Error ) FT_Read_Fields( FT_Stream stream,
+ const FT_Frame_Field* fields,
+ void* structure );
+
+
+#define USE_Stream( resource, stream ) \
+ FT_SET_ERROR( FT_Open_Stream( resource, stream ) )
+
+#define DONE_Stream( stream ) \
+ FT_Done_Stream( stream )
+
+
+#define ACCESS_Frame( size ) \
+ FT_SET_ERROR( FT_Access_Frame( stream, size ) )
+
+#define FORGET_Frame() \
+ FT_Forget_Frame( stream )
+
+#define EXTRACT_Frame( size, bytes ) \
+ FT_SET_ERROR( FT_Extract_Frame( stream, size, \
+ (FT_Byte**)&(bytes) ) )
+
+#define RELEASE_Frame( bytes ) \
+ FT_Release_Frame( stream, (FT_Byte**)&(bytes) )
+
+#define FILE_Seek( position ) \
+ FT_SET_ERROR( FT_Seek_Stream( stream, position ) )
+
+#define FILE_Skip( distance ) \
+ FT_SET_ERROR( FT_Skip_Stream( stream, distance ) )
+
+#define FILE_Pos() \
+ FT_Stream_Pos( stream )
+
+#define FILE_Read( buffer, count ) \
+ FT_SET_ERROR( FT_Read_Stream( stream, \
+ (FT_Byte*)buffer, \
+ count ) )
+
+#define FILE_Read_At( position, buffer, count ) \
+ FT_SET_ERROR( FT_Read_Stream_At( stream, \
+ position, \
+ (FT_Byte*)buffer, \
+ count ) )
+
+#define READ_Fields( fields, object ) \
+ ( ( error = FT_Read_Fields( stream, fields, object ) ) != FT_Err_Ok )
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* FTSTREAM_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* psnames.h */
+/* */
+/* High-level interface for the `PSNames' module (in charge of */
+/* various functions related to Postscript glyph names conversion). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef PSNAMES_H
+#define PSNAMES_H
+
+
+#include <freetype/freetype.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* PS_Unicode_Value_Func */
+ /* */
+ /* <Description> */
+ /* A function used to return the Unicode index corresponding to a */
+ /* given glyph name. */
+ /* */
+ /* <Input> */
+ /* glyph_name :: The glyph name. */
+ /* */
+ /* <Return> */
+ /* The Unicode character index resp. the non-Unicode value 0xFFFF if */
+ /* the glyph name has no known Unicode meaning. */
+ /* */
+ /* <Note> */
+ /* This function is able to map several different glyph names to the */
+ /* same Unicode value, according to the rules defined in the Adobe */
+ /* Glyph List table. */
+ /* */
+ /* This function will not be compiled if the configuration macro */
+ /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST is undefined. */
+ /* */
+ typedef FT_ULong (*PS_Unicode_Value_Func)( const char* glyph_name );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* PS_Unicode_Index_Func */
+ /* */
+ /* <Description> */
+ /* A function used to return the glyph index corresponding to a given */
+ /* Unicode value. */
+ /* */
+ /* <Input> */
+ /* num_glyphs :: The number of glyphs in the face. */
+ /* */
+ /* glyph_names :: An array of glyph name pointers. */
+ /* */
+ /* unicode :: The Unicode value. */
+ /* */
+ /* <Return> */
+ /* The glyph index resp. 0xFFFF if no glyph corresponds to this */
+ /* Unicode value. */
+ /* */
+ /* <Note> */
+ /* This function is able to recognize several glyph names per Unicode */
+ /* value, according to the Adobe Glyph List. */
+ /* */
+ /* This function will not be compiled if the configuration macro */
+ /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST is undefined. */
+ /* */
+ typedef FT_UInt (*PS_Unicode_Index_Func)( FT_UInt num_glyphs,
+ const char** glyph_names,
+ FT_ULong unicode );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* PS_Macintosh_Name_Func */
+ /* */
+ /* <Description> */
+ /* A function used to return the glyph name corresponding to an Apple */
+ /* glyph name index. */
+ /* */
+ /* <Input> */
+ /* name_index :: The index of the Mac name. */
+ /* */
+ /* <Return> */
+ /* The glyph name, or 0 if the index is invalid. */
+ /* */
+ /* <Note> */
+ /* This function will not be compiled if the configuration macro */
+ /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES is undefined. */
+ /* */
+ typedef const char* (*PS_Macintosh_Name_Func)( FT_UInt name_index );
+
+
+ typedef const char* (*PS_Adobe_Std_Strings_Func)( FT_UInt string_index );
+
+
+ typedef struct PS_UniMap_
+ {
+ FT_UInt unicode;
+ FT_UInt glyph_index;
+
+ } PS_UniMap;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* PS_Unicodes */
+ /* */
+ /* <Description> */
+ /* A simple table used to map Unicode values to glyph indices. It is */
+ /* built by the PS_Build_Unicodes table according to the glyphs */
+ /* present in a font file. */
+ /* */
+ /* <Fields> */
+ /* num_codes :: The number of glyphs in the font that match a given */
+ /* Unicode value. */
+ /* */
+ /* unicodes :: An array of unicode values, sorted in increasing */
+ /* order. */
+ /* */
+ /* gindex :: An array of glyph indices, corresponding to each */
+ /* Unicode value. */
+ /* */
+ /* <Note> */
+ /* Use the function PS_Lookup_Unicode() to retrieve the glyph index */
+ /* corresponding to a given Unicode character code. */
+ /* */
+ typedef struct PS_Unicodes_
+ {
+ FT_UInt num_maps;
+ PS_UniMap* maps;
+
+ } PS_Unicodes;
+
+
+ typedef FT_Error (*PS_Build_Unicodes_Func)( FT_Memory memory,
+ FT_UInt num_glyphs,
+ const char** glyph_names,
+ PS_Unicodes* unicodes );
+
+ typedef FT_UInt (*PS_Lookup_Unicode_Func)( PS_Unicodes* unicodes,
+ FT_UInt unicode );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* PSNames_Interface */
+ /* */
+ /* <Description> */
+ /* This structure defines the PSNames interface. */
+ /* */
+ /* <Fields> */
+ /* unicode_value :: A function used to convert a glyph name */
+ /* into a Unicode character code. */
+ /* */
+ /* build_unicodes :: A function which builds up the Unicode */
+ /* mapping table. */
+ /* */
+ /* lookup_unicode :: A function used to return the glyph index */
+ /* corresponding to a given Unicode */
+ /* character. */
+ /* */
+ /* macintosh_name :: A function used to return the standard */
+ /* Apple glyph Postscript name corresponding */
+ /* to a given string index (used by the */
+ /* TrueType `post' table). */
+ /* */
+ /* adobe_std_strings :: A function that returns a pointer to a */
+ /* Adobe Standard String for a given SID. */
+ /* */
+ /* adobe_std_encoding :: A table of 256 unsigned shorts that maps */
+ /* character codes in the Adobe Standard */
+ /* Encoding to SIDs. */
+ /* */
+ /* adobe_expert_encoding :: A table of 256 unsigned shorts that maps */
+ /* character codes in the Adobe Expert */
+ /* Encoding to SIDs. */
+ /* */
+ /* <Note> */
+ /* `unicode_value' and `unicode_index' will be set to 0 if the */
+ /* configuration macro FT_CONFIG_OPTION_ADOBE_GLYPH_LIST is */
+ /* undefined. */
+ /* */
+ /* `macintosh_name' will be set to 0 if the configuration macro */
+ /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES is undefined. */
+ /* */
+ typedef struct PSNames_Interface_
+ {
+ PS_Unicode_Value_Func unicode_value;
+ PS_Build_Unicodes_Func build_unicodes;
+ PS_Lookup_Unicode_Func lookup_unicode;
+ 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;
+
+ } PSNames_Interface;
+
+
+#endif /* PSNAMES_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* sfnt.h */
+/* */
+/* High-level `sfnt' driver interface (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef SFNT_H
+#define SFNT_H
+
+
+#include <freetype/freetype.h>
+#include <freetype/internal/ftdriver.h>
+#include <freetype/internal/tttypes.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Init_Face_Func */
+ /* */
+ /* <Description> */
+ /* First part of the SFNT face object initialization. This will find */
+ /* the face in a SFNT file or collection, and load its format tag in */
+ /* face->format_tag. */
+ /* */
+ /* <Input> */
+ /* stream :: The input stream. */
+ /* */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* face_index :: The index of the TrueType font, if we are opening a */
+ /* collection. */
+ /* */
+ /* num_params :: The number of additional parameters. */
+ /* */
+ /* params :: Optional additional parameters. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The stream cursor must be at the font file's origin. */
+ /* */
+ /* This function recognizes fonts embedded in a `TrueType */
+ /* collection'. */
+ /* */
+ /* Once the format tag has been validated by the font driver, it */
+ /* should then call the TT_Load_Face_Func() callback to read the rest */
+ /* of the SFNT tables in the object. */
+ /* */
+ typedef
+ FT_Error (*TT_Init_Face_Func)( FT_Stream stream,
+ TT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_Face_Func */
+ /* */
+ /* <Description> */
+ /* Second part of the SFNT face object initialization. This will */
+ /* load the common SFNT tables (head, OS/2, maxp, metrics, etc.) in */
+ /* the face object. */
+ /* */
+ /* <Input> */
+ /* stream :: The input stream. */
+ /* */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* face_index :: The index of the TrueType font, if we are opening a */
+ /* collection. */
+ /* */
+ /* num_params :: The number of additional parameters. */
+ /* */
+ /* params :: Optional additional parameters. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function must be called after TT_Init_Face_Func(). */
+ /* */
+ typedef
+ FT_Error (*TT_Load_Face_Func)( FT_Stream stream,
+ TT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Done_Face_Func */
+ /* */
+ /* <Description> */
+ /* A callback used to delete the common SFNT data from a face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* <Note> */
+ /* This function does NOT destroy the face object. */
+ /* */
+ typedef
+ void (*TT_Done_Face_Func)( TT_Face face );
+
+
+ typedef
+ FT_Module_Interface (*SFNT_Get_Interface_Func)( FT_Module module,
+ const char* interface );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_SFNT_Header_Func */
+ /* */
+ /* <Description> */
+ /* Loads the header of a SFNT font file. Supports collections. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* face_index :: The index of the TrueType font, if we are opening a */
+ /* collection. */
+ /* */
+ /* <Output> */
+ /* sfnt :: The SFNT header. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The stream cursor must be at the font file's origin. */
+ /* */
+ /* This function recognizes fonts embedded in a `TrueType */
+ /* collection'. */
+ /* */
+ /* This function checks that the header is valid by looking at the */
+ /* values of `search_range', `entry_selector', and `range_shift'. */
+ /* */
+ typedef
+ FT_Error (*TT_Load_SFNT_Header_Func)( TT_Face face,
+ FT_Stream stream,
+ FT_Long face_index,
+ SFNT_Header* sfnt );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_Directory_Func */
+ /* */
+ /* <Description> */
+ /* Loads the table directory into a face object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* sfnt :: The SFNT header. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The stream cursor must be on the first byte after the 4-byte font */
+ /* format tag. This is the case just after a call to */
+ /* TT_Load_Format_Tag(). */
+ /* */
+ typedef
+ FT_Error (*TT_Load_Directory_Func)( TT_Face face,
+ FT_Stream stream,
+ SFNT_Header* sfnt );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_Any_Func */
+ /* */
+ /* <Description> */
+ /* Loads any font table into client memory. */
+ /* */
+ /* <Input> */
+ /* face :: The face object to look for. */
+ /* */
+ /* tag :: The tag of table to load. Use the value 0 if you want */
+ /* to access the whole font file, else set this parameter */
+ /* to a valid TrueType table tag that you can forge with */
+ /* the MAKE_TT_TAG macro. */
+ /* */
+ /* offset :: The starting offset in the table (or the file if */
+ /* tag == 0). */
+ /* */
+ /* length :: The address of the decision variable: */
+ /* */
+ /* If length == NULL: */
+ /* Loads the whole table. Returns an error if */
+ /* `offset' == 0! */
+ /* */
+ /* If *length == 0: */
+ /* Exits immediately; returning the length of the given */
+ /* table or of the font file, depending on the value of */
+ /* `tag'. */
+ /* */
+ /* If *length != 0: */
+ /* Loads the next `length' bytes of table or font, */
+ /* starting at offset `offset' (in table or font too). */
+ /* */
+ /* <Output> */
+ /* buffer :: The address of target buffer. */
+ /* */
+ /* <Return> */
+ /* TrueType error code. 0 means success. */
+ /* */
+ typedef
+ FT_Error (*TT_Load_Any_Func)( TT_Face face,
+ FT_ULong tag,
+ FT_Long offset,
+ FT_Byte* buffer,
+ FT_ULong* length );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_SBit_Image_Func */
+ /* */
+ /* <Description> */
+ /* Loads a given glyph sbit image from the font resource. This also */
+ /* returns its metrics. */
+ /* */
+ /* <Input> */
+ /* face :: The target face object. */
+ /* */
+ /* x_ppem :: The horizontal resolution in points per EM. */
+ /* */
+ /* y_ppem :: The vertical resolution in points per EM. */
+ /* */
+ /* glyph_index :: The current glyph index. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Output> */
+ /* map :: The target pixmap. */
+ /* */
+ /* metrics :: A big sbit metrics structure for the glyph image. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. Returns an error if no */
+ /* glyph sbit exists for the index. */
+ /* */
+ /* <Note> */
+ /* The `map.buffer' field is always freed before the glyph is loaded. */
+ /* */
+ typedef
+ FT_Error (*TT_Load_SBit_Image_Func)( TT_Face face,
+ FT_Int x_ppem,
+ FT_Int y_ppem,
+ FT_UInt glyph_index,
+ FT_UInt load_flags,
+ FT_Stream stream,
+ FT_Bitmap* map,
+ TT_SBit_Metrics* metrics );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Get_PS_Name_Func */
+ /* */
+ /* <Description> */
+ /* Gets the PostScript glyph name of a glyph. */
+ /* */
+ /* <Input> */
+ /* index :: The glyph index. */
+ /* */
+ /* PSname :: The address of a string pointer. Will be NULL in case */
+ /* of error, otherwise it is a pointer to the glyph name. */
+ /* */
+ /* You must not modify the returned string! */
+ /* */
+ /* <Output> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ typedef
+ FT_Error (*TT_Get_PS_Name_Func)( TT_Face face,
+ FT_UInt index,
+ FT_String** PSname );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_Metrics_Func */
+ /* */
+ /* <Description> */
+ /* Loads the horizontal or vertical header in a face object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* vertical :: A boolean flag. If set, load vertical metrics. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ typedef
+ FT_Error (*TT_Load_Metrics_Func)( TT_Face face,
+ FT_Stream stream,
+ FT_Bool vertical );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_CharMap_Load_Func */
+ /* */
+ /* <Description> */
+ /* Loads a given TrueType character map into memory. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the parent face object. */
+ /* */
+ /* stream :: A handle to the current stream object. */
+ /* */
+ /* <InOut> */
+ /* cmap :: A pointer to a cmap object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The function assumes that the stream is already in use (i.e., */
+ /* opened). In case of error, all partially allocated tables are */
+ /* released. */
+ /* */
+ typedef
+ FT_Error (*TT_CharMap_Load_Func)( TT_Face face,
+ TT_CMapTable* cmap,
+ FT_Stream input );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_CharMap_Free_Func */
+ /* */
+ /* <Description> */
+ /* Destroys a character mapping table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the parent face object. */
+ /* */
+ /* cmap :: A handle to a cmap object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ typedef
+ FT_Error (*TT_CharMap_Free_Func)( TT_Face face,
+ TT_CMapTable* cmap );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_Table_Func */
+ /* */
+ /* <Description> */
+ /* Loads a given TrueType table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The function will use `face->goto_table' to seek the stream to */
+ /* the start of the table. */
+ /* */
+ typedef
+ FT_Error (*TT_Load_Table_Func)( TT_Face face,
+ FT_Stream stream );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Free_Table_Func */
+ /* */
+ /* <Description> */
+ /* Frees a given TrueType table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ typedef
+ void (*TT_Free_Table_Func)( TT_Face face );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* SFNT_Interface */
+ /* */
+ /* <Description> */
+ /* This structure holds pointers to the functions used to load and */
+ /* free the basic tables that are required in a `sfnt' font file. */
+ /* */
+ /* <Fields> */
+ /* Check the various xxx_Func() descriptions for details. */
+ /* */
+ typedef struct SFNT_Interface_
+ {
+ TT_Goto_Table_Func goto_table;
+
+ TT_Init_Face_Func init_face;
+ TT_Load_Face_Func load_face;
+ TT_Done_Face_Func done_face;
+ SFNT_Get_Interface_Func get_interface;
+
+ TT_Load_Any_Func load_any;
+ TT_Load_SFNT_Header_Func load_sfnt_header;
+ TT_Load_Directory_Func load_directory;
+
+ /* these functions are called by `load_face' but they can also */
+ /* be called from external modules, if there is a need to do so */
+ TT_Load_Table_Func load_header;
+ TT_Load_Metrics_Func load_metrics;
+ TT_Load_Table_Func load_charmaps;
+ TT_Load_Table_Func load_max_profile;
+ TT_Load_Table_Func load_os2;
+ TT_Load_Table_Func load_psnames;
+
+ TT_Load_Table_Func load_names;
+ TT_Free_Table_Func free_names;
+
+ /* optional tables */
+ TT_Load_Table_Func load_hdmx;
+ TT_Free_Table_Func free_hdmx;
+
+ TT_Load_Table_Func load_kerning;
+ TT_Load_Table_Func load_gasp;
+ TT_Load_Table_Func load_pclt;
+
+ /* see `ttsbit.h' */
+ TT_Load_Table_Func load_sbits;
+ TT_Load_SBit_Image_Func load_sbit_image;
+ TT_Free_Table_Func free_sbits;
+
+ /* see `ttpost.h' */
+ TT_Get_PS_Name_Func get_psname;
+ TT_Free_Table_Func free_psnames;
+
+ /* see `ttcmap.h' */
+ TT_CharMap_Load_Func load_charmap;
+ TT_CharMap_Free_Func free_charmap;
+
+ } SFNT_Interface;
+
+
+#endif /* SFNT_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1errors.h */
+/* */
+/* Type 1 error ID definitions (specification only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T1ERRORS_H
+#define T1ERRORS_H
+
+
+ /************************ error codes declaration **************/
+
+ /* The error codes are grouped into `classes' used to indicate the */
+ /* `level' at which the error happened. */
+ /* */
+ /* The class is given by an error code's high byte. */
+
+
+ /* ------------- Success is always 0 -------- */
+
+#define T1_Err_Ok FT_Err_Ok
+
+ /* ----------- high level API errors -------- */
+
+#define T1_Err_Invalid_File_Format FT_Err_Invalid_File_Format
+#define T1_Err_Invalid_Argument FT_Err_Invalid_Argument
+#define T1_Err_Invalid_Driver_Handle FT_Err_Invalid_Driver_Handle
+#define T1_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle
+#define T1_Err_Invalid_Size_Handle FT_Err_Invalid_Size_Handle
+#define T1_Err_Invalid_Glyph_Handle FT_Err_Invalid_Slot_Handle
+#define T1_Err_Invalid_CharMap_Handle FT_Err_Invalid_CharMap_Handle
+#define T1_Err_Invalid_Glyph_Index FT_Err_Invalid_Glyph_Index
+
+#define T1_Err_Unimplemented_Feature FT_Err_Unimplemented_Feature
+
+#define T1_Err_Invalid_Engine FT_Err_Invalid_Driver_Handle
+
+ /* ------------- internal errors ------------ */
+
+#define T1_Err_Out_Of_Memory FT_Err_Out_Of_Memory
+#define T1_Err_Unlisted_Object FT_Err_Unlisted_Object
+
+ /* ------------ general glyph outline errors ------ */
+
+#define T1_Err_Invalid_Composite FT_Err_Invalid_Composite
+
+#define T1_Err_Syntax_Error FT_Err_Invalid_File_Format
+#define T1_Err_Stack_Underflow FT_Err_Invalid_File_Format
+#define T1_Err_Stack_Overflow FT_Err_Invalid_File_Format
+
+
+#endif /* T1ERRORS_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1types.h */
+/* */
+/* Basic Type1/Type2 type definitions and interface (specification */
+/* only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T1TYPES_H
+#define T1TYPES_H
+
+
+#include <freetype/t1tables.h>
+#include <freetype/internal/psnames.h>
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** REQUIRED TYPE1/TYPE2 TABLES DEFINITIONS ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_Encoding */
+ /* */
+ /* <Description> */
+ /* A structure modeling a custom encoding */
+ /* */
+ /* <Fields> */
+ /* num_chars :: The number of character codes in the encoding. */
+ /* Usually 256. */
+ /* */
+ /* code_first :: The lowest valid character code in the encoding. */
+ /* */
+ /* code_last :: The highest valid character code in the encoding. */
+ /* */
+ /* char_index :: An array of corresponding glyph indices. */
+ /* */
+ /* char_name :: An array of corresponding glyph names. */
+ /* */
+ typedef struct T1_Encoding_
+ {
+ FT_Int num_chars;
+ FT_Int code_first;
+ FT_Int code_last;
+
+ FT_UShort* char_index;
+ FT_String** char_name;
+
+ } T1_Encoding;
+
+
+ typedef enum T1_EncodingType_
+ {
+ t1_encoding_none = 0,
+ t1_encoding_array,
+ t1_encoding_standard,
+ t1_encoding_expert
+
+ } T1_EncodingType;
+
+
+ typedef struct T1_Font_
+ {
+
+ /* font info dictionary */
+ T1_FontInfo font_info;
+
+ /* private dictionary */
+ T1_Private private_dict;
+
+ /* top-level dictionary */
+ FT_String* font_name;
+
+ T1_EncodingType encoding_type;
+ T1_Encoding encoding;
+
+ FT_Byte* subrs_block;
+ FT_Byte* charstrings_block;
+ FT_Byte* glyph_names_block;
+
+ FT_Int num_subrs;
+ FT_Byte** subrs;
+ FT_Int* subrs_len;
+
+ FT_Int num_glyphs;
+ FT_String** glyph_names; /* array of glyph names */
+ FT_Byte** charstrings; /* array of glyph charstrings */
+ FT_Int* charstrings_len;
+
+ FT_Byte paint_type;
+ FT_Byte font_type;
+ FT_Matrix font_matrix;
+ FT_BBox font_bbox;
+ FT_Long font_id;
+
+ FT_Int stroke_width;
+
+ } T1_Font;
+
+
+ typedef struct CID_Subrs_
+ {
+ FT_UInt num_subrs;
+ FT_Byte** code;
+
+ } CID_Subrs;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** ORIGINAL T1_FACE CLASS DEFINITION ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This structure/class is defined here because it is common to the */
+ /* following formats: TTF, OpenType-TT, and OpenType-CFF. */
+ /* */
+ /* Note, however, that the classes TT_Size, TT_GlyphSlot, and TT_CharMap */
+ /* are not shared between font drivers, and are thus defined normally in */
+ /* `ttobjs.h'. */
+ /* */
+ /*************************************************************************/
+
+ typedef struct T1_FaceRec_* T1_Face;
+ typedef struct CID_FaceRec_* CID_Face;
+
+
+ typedef struct T1_FaceRec_
+ {
+ FT_FaceRec root;
+ T1_Font type1;
+ void* psnames;
+ void* afm_data;
+ FT_CharMapRec charmaprecs[2];
+ FT_CharMap charmaps[2];
+ PS_Unicodes unicode_map;
+
+ /* support for Multiple Masters fonts */
+ T1_Blend* blend;
+
+ } T1_FaceRec;
+
+
+ typedef struct CID_FaceRec_
+ {
+ FT_FaceRec root;
+ void* psnames;
+ CID_Info cid;
+ void* afm_data;
+ CID_Subrs* subrs;
+
+ } CID_FaceRec;
+
+
+#endif /* T1TYPES_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t2errors.h */
+/* */
+/* OpenType error ID definitions (specification only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T2ERRORS_H
+#define T2ERRORS_H
+
+
+ /*************************************************************************/
+ /* */
+ /* Error codes declaration */
+ /* */
+ /* The error codes are grouped in `classes' used to indicate the `level' */
+ /* at which the error happened. The class is given by an error code's */
+ /* high byte. */
+ /* */
+ /*************************************************************************/
+
+
+ /* Success is always 0. */
+
+#define T2_Err_Ok FT_Err_Ok
+
+ /* High level API errors. */
+
+#define T2_Err_Invalid_File_Format FT_Err_Invalid_File_Format
+#define T2_Err_Invalid_Argument FT_Err_Invalid_Argument
+#define T2_Err_Invalid_Driver_Handle FT_Err_Invalid_Driver_Handle
+#define T2_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle
+#define T2_Err_Invalid_Instance_Handle FT_Err_Invalid_Size_Handle
+#define T2_Err_Invalid_Glyph_Handle FT_Err_Invalid_Slot_Handle
+#define T2_Err_Invalid_CharMap_Handle FT_Err_Invalid_CharMap_Handle
+#define T2_Err_Invalid_Glyph_Index FT_Err_Invalid_Glyph_Index
+
+#define T2_Err_Unimplemented_Feature FT_Err_Unimplemented_Feature
+
+#define T2_Err_Invalid_Engine FT_Err_Invalid_Driver_Handle
+
+ /* Internal errors. */
+
+#define T2_Err_Out_Of_Memory FT_Err_Out_Of_Memory
+#define T2_Err_Unlisted_Object FT_Err_Unlisted_Object
+
+ /* General glyph outline errors. */
+
+#define T2_Err_Invalid_Composite FT_Err_Invalid_Composite
+
+ /* Bytecode interpreter error codes. */
+
+ /* These error codes are produced by the TrueType */
+ /* bytecode interpreter. They usually indicate a */
+ /* broken font file, a broken glyph within a font */
+ /* file, or a bug in the interpreter! */
+
+#define T2_Err_Invalid_Opcode 0x500
+#define T2_Err_Too_Few_Arguments 0x501
+#define T2_Err_Stack_Overflow 0x502
+#define T2_Err_Code_Overflow 0x503
+#define T2_Err_Bad_Argument 0x504
+#define T2_Err_Divide_By_Zero 0x505
+#define T2_Err_Storage_Overflow 0x506
+#define T2_Err_Cvt_Overflow 0x507
+#define T2_Err_Invalid_Reference 0x508
+#define T2_Err_Invalid_Distance 0x509
+#define T2_Err_Interpolate_Twilight 0x50A
+#define T2_Err_Debug_OpCode 0x50B
+#define T2_Err_ENDF_In_Exec_Stream 0x50C
+#define T2_Err_Out_Of_CodeRanges 0x50D
+#define T2_Err_Nested_DEFS 0x50E
+#define T2_Err_Invalid_CodeRange 0x50F
+#define T2_Err_Invalid_Displacement 0x510
+#define T2_Err_Execution_Too_Long 0x511
+
+#define T2_Err_Too_Many_Instruction_Defs 0x512
+#define T2_Err_Too_Many_Function_Defs 0x513
+
+ /* Other TrueType specific error codes. */
+
+#define T2_Err_Table_Missing 0x520
+#define T2_Err_Too_Many_Extensions 0x521
+#define T2_Err_Extensions_Unsupported 0x522
+#define T2_Err_Invalid_Extension_Id 0x523
+
+#define T2_Err_No_Vertical_Data 0x524
+
+#define T2_Err_Max_Profile_Missing 0x530
+#define T2_Err_Header_Table_Missing 0x531
+#define T2_Err_Horiz_Header_Missing 0x532
+#define T2_Err_Locations_Missing 0x533
+#define T2_Err_Name_Table_Missing 0x534
+#define T2_Err_CMap_Table_Missing 0x535
+#define T2_Err_Hmtx_Table_Missing 0x536
+#define T2_Err_OS2_Table_Missing 0x537
+#define T2_Err_Post_Table_Missing 0x538
+
+#define T2_Err_Invalid_Horiz_Metrics 0x540
+#define T2_Err_Invalid_CharMap_Format 0x541
+#define T2_Err_Invalid_PPem 0x542
+#define T2_Err_Invalid_Vert_Metrics 0x543
+
+#define T2_Err_Could_Not_Find_Context 0x550
+
+
+#endif /* T2ERRORS_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t2types.h */
+/* */
+/* Basic OpenType/CFF type definitions and interface (specification */
+/* only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T2TYPES_H
+#define T2TYPES_H
+
+
+#include <freetype/freetype.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* CFF_Index */
+ /* */
+ /* <Description> */
+ /* A structure used to model a CFF Index table. */
+ /* */
+ /* <Fields> */
+ /* stream :: XXX */
+ /* */
+ /* 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 :: XXX */
+ /* */
+ /* bytes :: If the index is loaded in memory, its bytes. */
+ /* */
+ typedef struct CFF_Index_
+ {
+ FT_Stream stream;
+ FT_UInt count;
+ FT_Byte off_size;
+ FT_ULong data_offset;
+
+ FT_ULong* offsets;
+ FT_Byte* bytes;
+
+ } CFF_Index;
+
+
+ typedef struct CFF_Font_Dict_
+ {
+ 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_Pos underline_position;
+ FT_Pos underline_thickness;
+ FT_Int paint_type;
+ FT_Int charstring_type;
+ FT_Matrix font_matrix;
+ 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;
+ FT_UInt base_font_name;
+ FT_UInt 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_Long 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_Font_Dict;
+
+
+ typedef struct CFF_Private_
+ {
+ 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_Private;
+
+
+ typedef struct CFF_FD_Select_
+ {
+ 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_FD_Select;
+
+
+ /* A SubFont packs a font dict and a private dict together. They are */
+ /* needed to support CID-keyed CFF fonts. */
+ typedef struct CFF_SubFont_
+ {
+ CFF_Font_Dict font_dict;
+ CFF_Private private_dict;
+
+ CFF_Index local_subrs_index;
+ FT_UInt num_local_subrs;
+ FT_Byte** local_subrs;
+
+ } CFF_SubFont;
+
+
+ /* maximum number of sub-fonts in a CID-keyed file */
+#define CFF_MAX_CID_FONTS 16
+
+
+ typedef struct CFF_Font_
+ {
+ 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_Index name_index;
+ CFF_Index top_dict_index;
+ CFF_Index string_index;
+ CFF_Index global_subrs_index;
+
+ /* we don't load the Encoding and CharSet tables */
+
+ CFF_Index charstrings_index;
+ CFF_Index font_dict_index;
+ CFF_Index private_index;
+ CFF_Index local_subrs_index;
+
+ FT_String* font_name;
+ FT_UInt num_global_subrs;
+ FT_Byte** global_subrs;
+
+ CFF_SubFont top_font;
+ FT_UInt num_subfonts;
+ CFF_SubFont* subfonts[CFF_MAX_CID_FONTS];
+
+ CFF_FD_Select fd_select;
+
+ } CFF_Font;
+
+
+#endif /* T2TYPES_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* tterrors.h */
+/* */
+/* TrueType error ID definitions (specification only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef TTERRORS_H
+#define TTERRORS_H
+
+
+ /*************************************************************************/
+ /* */
+ /* Error codes declaration */
+ /* */
+ /* The error codes are grouped in `classes' used to indicate the `level' */
+ /* at which the error happened. The class is given by an error code's */
+ /* high byte. */
+ /* */
+ /*************************************************************************/
+
+
+ /* Success is always 0. */
+
+#define TT_Err_Ok FT_Err_Ok
+
+ /* High level API errors. */
+
+#define TT_Err_Invalid_File_Format FT_Err_Invalid_File_Format
+#define TT_Err_Invalid_Argument FT_Err_Invalid_Argument
+#define TT_Err_Invalid_Driver_Handle FT_Err_Invalid_Driver_Handle
+#define TT_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle
+#define TT_Err_Invalid_Instance_Handle FT_Err_Invalid_Size_Handle
+#define TT_Err_Invalid_Glyph_Handle FT_Err_Invalid_Slot_Handle
+#define TT_Err_Invalid_CharMap_Handle FT_Err_Invalid_CharMap_Handle
+#define TT_Err_Invalid_Glyph_Index FT_Err_Invalid_Glyph_Index
+
+#define TT_Err_Unimplemented_Feature FT_Err_Unimplemented_Feature
+
+#define TT_Err_Invalid_Engine FT_Err_Invalid_Driver_Handle
+
+ /* Internal errors. */
+
+#define TT_Err_Out_Of_Memory FT_Err_Out_Of_Memory
+#define TT_Err_Unlisted_Object FT_Err_Unlisted_Object
+
+ /* General glyph outline errors. */
+
+#define TT_Err_Too_Many_Ins FT_Err_Too_Many_Hints
+#define TT_Err_Invalid_Composite FT_Err_Invalid_Composite
+
+ /* Bytecode interpreter error codes. */
+
+ /* These error codes are produced by the TrueType */
+ /* bytecode interpreter. They usually indicate a */
+ /* broken font file, a broken glyph within a font */
+ /* file, or a bug in the interpreter! */
+
+#define TT_Err_Invalid_Opcode 0x400
+#define TT_Err_Too_Few_Arguments 0x401
+#define TT_Err_Stack_Overflow 0x402
+#define TT_Err_Code_Overflow 0x403
+#define TT_Err_Bad_Argument 0x404
+#define TT_Err_Divide_By_Zero 0x405
+#define TT_Err_Storage_Overflow 0x406
+#define TT_Err_Cvt_Overflow 0x407
+#define TT_Err_Invalid_Reference 0x408
+#define TT_Err_Invalid_Distance 0x409
+#define TT_Err_Interpolate_Twilight 0x40A
+#define TT_Err_Debug_OpCode 0x40B
+#define TT_Err_ENDF_In_Exec_Stream 0x40C
+#define TT_Err_Out_Of_CodeRanges 0x40D
+#define TT_Err_Nested_DEFS 0x40E
+#define TT_Err_Invalid_CodeRange 0x40F
+#define TT_Err_Invalid_Displacement 0x410
+#define TT_Err_Execution_Too_Long 0x411
+#define TT_Err_Too_Many_Function_Defs 0x412
+#define TT_Err_Too_Many_Instruction_Defs 0x413
+
+ /* Other TrueType specific error codes. */
+
+#define TT_Err_Table_Missing 0x420
+#define TT_Err_Too_Many_Extensions 0x421
+#define TT_Err_Extensions_Unsupported 0x422
+#define TT_Err_Invalid_Extension_Id 0x423
+
+#define TT_Err_No_Vertical_Data 0x424
+
+#define TT_Err_Max_Profile_Missing 0x430
+#define TT_Err_Header_Table_Missing 0x431
+#define TT_Err_Horiz_Header_Missing 0x432
+#define TT_Err_Locations_Missing 0x433
+#define TT_Err_Name_Table_Missing 0x434
+#define TT_Err_CMap_Table_Missing 0x435
+#define TT_Err_Hmtx_Table_Missing 0x436
+#define TT_Err_OS2_Table_Missing 0x437
+#define TT_Err_Post_Table_Missing 0x438
+
+#define TT_Err_Invalid_Horiz_Metrics 0x440
+#define TT_Err_Invalid_CharMap_Format 0x441
+#define TT_Err_Invalid_PPem 0x442
+#define TT_Err_Invalid_Vert_Metrics 0x443
+
+#define TT_Err_Could_Not_Find_Context 0x450
+
+
+#endif /* TTERRORS_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* tttypes.h */
+/* */
+/* Basic SFNT/TrueType type definitions and interface (specification */
+/* only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef TTTYPES_H
+#define TTTYPES_H
+
+
+#include <freetype/tttables.h>
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** REQUIRED TRUETYPE/OPENTYPE TABLES DEFINITIONS ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TTC_Header */
+ /* */
+ /* <Description> */
+ /* TrueType collection header. This table contains the offsets of */
+ /* the font headers of each distinct TrueType face in the file. */
+ /* */
+ /* <Fields> */
+ /* tag :: Must be `ttc ' to indicate a TrueType collection. */
+ /* */
+ /* version :: The version number. */
+ /* */
+ /* count :: The number of faces in the collection. The */
+ /* specification says this should be an unsigned long, but */
+ /* we use a signed long since we need the value -1 for */
+ /* specific purposes. */
+ /* */
+ /* offsets :: The offsets of the font headers, one per face. */
+ /* */
+ typedef struct TTC_Header_
+ {
+ FT_ULong tag;
+ FT_Fixed version;
+ FT_Long count;
+ FT_ULong* offsets;
+
+ } TTC_Header;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* SFNT_Header */
+ /* */
+ /* <Description> */
+ /* SFNT file format header. */
+ /* */
+ /* <Fields> */
+ /* format_tag :: The font format tag. */
+ /* */
+ /* num_tables :: The number of tables in file. */
+ /* */
+ /* search_range :: Must be 16*(max power of 2 <= num_tables). */
+ /* */
+ /* entry_selector :: Must be log2 of search_range/16. */
+ /* */
+ /* range_shift :: Must be num_tables*16 - search_range. */
+ /* */
+ typedef struct SFNT_Header_
+ {
+ FT_ULong format_tag;
+ FT_UShort num_tables;
+ FT_UShort search_range;
+ FT_UShort entry_selector;
+ FT_UShort range_shift;
+
+ } SFNT_Header;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_TableDir */
+ /* */
+ /* <Description> */
+ /* This structure models a TrueType table directory. It is used to */
+ /* access the various tables of the font face. */
+ /* */
+ /* <Fields> */
+ /* version :: The version number; starts with 0x00010000. */
+ /* */
+ /* numTables :: The number of tables. */
+ /* */
+ /* searchRange :: Unused. */
+ /* */
+ /* entrySelector :: Unused. */
+ /* */
+ /* rangeShift :: Unused. */
+ /* */
+ /* <Note> */
+ /* This structure is only used during font opening. */
+ /* */
+ typedef struct TT_TableDir_
+ {
+ FT_Fixed version; /* should be 0x10000 */
+ FT_UShort numTables; /* number of tables */
+
+ FT_UShort searchRange; /* These parameters are only used */
+ FT_UShort entrySelector; /* for a dichotomy search in the */
+ FT_UShort rangeShift; /* directory. We ignore them. */
+
+ } TT_TableDir;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_Table */
+ /* */
+ /* <Description> */
+ /* This structure describes a given table of a TrueType font. */
+ /* */
+ /* <Fields> */
+ /* Tag :: A four-bytes tag describing the table. */
+ /* */
+ /* CheckSum :: The table checksum. This value can be ignored. */
+ /* */
+ /* Offset :: The offset of the table from the start of the TrueType */
+ /* font in its resource. */
+ /* */
+ /* Length :: The table length (in bytes). */
+ /* */
+ typedef struct TT_Table_
+ {
+ FT_ULong Tag; /* table type */
+ FT_ULong CheckSum; /* table checksum */
+ FT_ULong Offset; /* table file offset */
+ FT_ULong Length; /* table length */
+
+ } TT_Table;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_CMapDir */
+ /* */
+ /* <Description> */
+ /* This structure describes the directory of the `cmap' table, */
+ /* containing the font's character mappings table. */
+ /* */
+ /* <Fields> */
+ /* tableVersionNumber :: The version number. */
+ /* */
+ /* numCMaps :: The number of charmaps in the font. */
+ /* */
+ /* <Note> */
+ /* This structure is only used during font loading. */
+ /* */
+ typedef struct TT_CMapDir_
+ {
+ FT_UShort tableVersionNumber;
+ FT_UShort numCMaps;
+
+ } TT_CMapDir;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_CMapDirEntry */
+ /* */
+ /* <Description> */
+ /* This structure describes a charmap in a TrueType font. */
+ /* */
+ /* <Fields> */
+ /* platformID :: An ID used to specify for which platform this */
+ /* charmap is defined (FreeType manages all platforms). */
+ /* */
+ /* encodingID :: A platform-specific ID used to indicate which source */
+ /* encoding is used in this charmap. */
+ /* */
+ /* offset :: The offset of the charmap relative to the start of */
+ /* the `cmap' table. */
+ /* */
+ /* <Note> */
+ /* This structure is only used during font loading. */
+ /* */
+ typedef struct TT_CMapDirEntry_
+ {
+ FT_UShort platformID;
+ FT_UShort platformEncodingID;
+ FT_Long offset;
+
+ } TT_CMapDirEntry;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_LongMetrics */
+ /* */
+ /* <Description> */
+ /* A structure modeling the long metrics of the `hmtx' and `vmtx' */
+ /* TrueType tables. The values are expressed in font units. */
+ /* */
+ /* <Fields> */
+ /* advance :: The advance width or height for the glyph. */
+ /* */
+ /* bearing :: The left-side or top-side bearing for the glyph. */
+ /* */
+ typedef struct TT_LongMetrics_
+ {
+ FT_UShort advance;
+ FT_Short bearing;
+
+ } TT_LongMetrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> TT_ShortMetrics */
+ /* */
+ /* <Description> */
+ /* A simple type to model the short metrics of the `hmtx' and `vmtx' */
+ /* tables. */
+ /* */
+ typedef FT_Short TT_ShortMetrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_NameRec */
+ /* */
+ /* <Description> */
+ /* A structure modeling TrueType name records. Name records are used */
+ /* to store important strings like family name, style name, */
+ /* copyright, etc. in _localized_ versions (i.e., language, encoding, */
+ /* etc). */
+ /* */
+ /* <Fields> */
+ /* platformID :: The ID of the name's encoding platform. */
+ /* */
+ /* encodingID :: The platform-specific ID for the name's encoding. */
+ /* */
+ /* languageID :: The platform-specific ID for the name's language. */
+ /* */
+ /* nameID :: The ID specifying what kind of name this is. */
+ /* */
+ /* stringLength :: The length of the string in bytes. */
+ /* */
+ /* stringOffset :: The offset to the string in the `name' table. */
+ /* */
+ /* string :: A pointer to the string's bytes. Note that these */
+ /* are usually UTF-16 encoded characters. */
+ /* */
+ typedef struct TT_NameRec_
+ {
+ FT_UShort platformID;
+ FT_UShort encodingID;
+ FT_UShort languageID;
+ FT_UShort nameID;
+ FT_UShort stringLength;
+ FT_UShort stringOffset;
+
+ /* this last field is not defined in the spec */
+ /* but used by the FreeType engine */
+
+ FT_Byte* string;
+
+ } TT_NameRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_NameTable */
+ /* */
+ /* <Description> */
+ /* A structure modeling the TrueType name table. */
+ /* */
+ /* <Fields> */
+ /* format :: The format of the name table. */
+ /* */
+ /* numNameRecords :: The number of names in table. */
+ /* */
+ /* storageOffset :: The offset of the name table in the `name' */
+ /* TrueType table. */
+ /* */
+ /* names :: An array of name records. */
+ /* */
+ /* storage :: The names storage area. */
+ /* */
+ typedef struct TT_NameTable_
+ {
+ FT_UShort format;
+ FT_UShort numNameRecords;
+ FT_UShort storageOffset;
+ TT_NameRec* names;
+ FT_Byte* storage;
+
+ } TT_NameTable;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** OPTIONAL TRUETYPE/OPENTYPE TABLES DEFINITIONS ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_GaspRange */
+ /* */
+ /* <Description> */
+ /* A tiny structure used to model a gasp range according to the */
+ /* TrueType specification. */
+ /* */
+ /* <Fields> */
+ /* maxPPEM :: The maximum ppem value to which `gaspFlag' applies. */
+ /* */
+ /* gaspFlag :: A flag describing the grid-fitting and anti-aliasing */
+ /* modes to be used. */
+ /* */
+ typedef struct TT_GaspRange_
+ {
+ FT_UShort maxPPEM;
+ FT_UShort gaspFlag;
+
+ } TT_GaspRange;
+
+
+#define TT_GASP_GRIDFIT 0x01
+#define TT_GASP_DOGRAY 0x02
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_Gasp */
+ /* */
+ /* <Description> */
+ /* A structure modeling the TrueType `gasp' table used to specify */
+ /* grid-fitting and anti-aliasing behaviour. */
+ /* */
+ /* <Fields> */
+ /* version :: The version number. */
+ /* */
+ /* numRanges :: The number of gasp ranges in table. */
+ /* */
+ /* gaspRanges :: An array of gasp ranges. */
+ /* */
+ typedef struct TT_Gasp_
+ {
+ FT_UShort version;
+ FT_UShort numRanges;
+ TT_GaspRange* gaspRanges;
+
+ } TT_Gasp;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_HdmxRec */
+ /* */
+ /* <Description> */
+ /* A small structure used to model the pre-computed widths of a given */
+ /* size. They are found in the `hdmx' table. */
+ /* */
+ /* <Fields> */
+ /* ppem :: The pixels per EM value at which these metrics apply. */
+ /* */
+ /* max_width :: The maximum advance width for this metric. */
+ /* */
+ /* widths :: An array of widths. Note: These are 8-bit bytes. */
+ /* */
+ typedef struct TT_HdmxRec_
+ {
+ FT_Byte ppem;
+ FT_Byte max_width;
+ FT_Byte* widths;
+
+ } TT_HdmxRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_Hdmx */
+ /* */
+ /* <Description> */
+ /* A structure used to model the `hdmx' table, which contains */
+ /* pre-computed widths for a set of given sizes/dimensions. */
+ /* */
+ /* <Fields> */
+ /* version :: The version number. */
+ /* */
+ /* num_records :: The number of hdmx records. */
+ /* */
+ /* records :: An array of hdmx records. */
+ /* */
+ typedef struct TT_Hdmx_
+ {
+ FT_UShort version;
+ FT_Short num_records;
+ TT_HdmxRec* records;
+
+ } TT_Hdmx;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_Kern_0_Pair */
+ /* */
+ /* <Description> */
+ /* A structure used to model a kerning pair for the kerning table */
+ /* format 0. The engine now loads this table if it finds one in the */
+ /* font file. */
+ /* */
+ /* <Fields> */
+ /* left :: The index of the left glyph in pair. */
+ /* */
+ /* right :: The index of the right glyph in pair. */
+ /* */
+ /* value :: The kerning distance. A positive value spaces the */
+ /* glyphs, a negative one makes them closer. */
+ /* */
+ typedef struct TT_Kern_0_Pair_
+ {
+ FT_UShort left; /* index of left glyph in pair */
+ FT_UShort right; /* index of right glyph in pair */
+ FT_FWord value; /* kerning value */
+
+ } TT_Kern_0_Pair;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** EMBEDDED BITMAPS SUPPORT ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_SBit_Metrics */
+ /* */
+ /* <Description> */
+ /* A structure used to hold the big metrics of a given glyph bitmap */
+ /* in a TrueType or OpenType font. These are usually found in the */
+ /* `EBDT' (Microsoft) or `bdat' (Apple) table. */
+ /* */
+ /* <Fields> */
+ /* height :: The glyph height in pixels. */
+ /* */
+ /* width :: The glyph width in pixels. */
+ /* */
+ /* horiBearingX :: The horizontal left bearing. */
+ /* */
+ /* horiBearingY :: The horizontal top bearing. */
+ /* */
+ /* horiAdvance :: The horizontal advance. */
+ /* */
+ /* vertBearingX :: The vertical left bearing. */
+ /* */
+ /* vertBearingY :: The vertical top bearing. */
+ /* */
+ /* vertAdvance :: The vertical advance. */
+ /* */
+ typedef struct TT_SBit_Metrics_
+ {
+ FT_Byte height;
+ FT_Byte width;
+
+ FT_Char horiBearingX;
+ FT_Char horiBearingY;
+ FT_Byte horiAdvance;
+
+ FT_Char vertBearingX;
+ FT_Char vertBearingY;
+ FT_Byte vertAdvance;
+
+ } TT_SBit_Metrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_SBit_Small_Metrics */
+ /* */
+ /* <Description> */
+ /* A structure used to hold the small metrics of a given glyph bitmap */
+ /* in a TrueType or OpenType font. These are usually found in the */
+ /* `EBDT' (Microsoft) or the `bdat' (Apple) table. */
+ /* */
+ /* <Fields> */
+ /* height :: The glyph height in pixels. */
+ /* */
+ /* width :: The glyph width in pixels. */
+ /* */
+ /* bearingX :: The left-side bearing. */
+ /* */
+ /* bearingY :: The top-side bearing. */
+ /* */
+ /* advance :: The advance width or height. */
+ /* */
+ typedef struct TT_SBit_Small_Metrics_
+ {
+ FT_Byte height;
+ FT_Byte width;
+
+ FT_Char bearingX;
+ FT_Char bearingY;
+ FT_Byte advance;
+
+ } TT_SBit_Small_Metrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_SBit_Line_Metrics */
+ /* */
+ /* <Description> */
+ /* A structure used to describe the text line metrics of a given */
+ /* bitmap strike, for either a horizontal or vertical layout. */
+ /* */
+ /* <Fields> */
+ /* ascender :: The ascender in pixels. */
+ /* */
+ /* descender :: The descender in pixels. */
+ /* */
+ /* max_width :: The maximum glyph width in pixels. */
+ /* */
+ /* caret_slope_enumerator :: Rise of the caret slope, typically set */
+ /* to 1 for non-italic fonts. */
+ /* */
+ /* caret_slope_denominator :: Rise of the caret slope, typically set */
+ /* to 0 for non-italic fonts. */
+ /* */
+ /* caret_offset :: Offset in pixels to move the caret for */
+ /* proper positioning. */
+ /* */
+ /* min_origin_SB :: Minimum of horiBearingX (resp. */
+ /* vertBearingY). */
+ /* min_advance_SB :: Minimum of */
+ /* */
+ /* horizontal advance - */
+ /* ( horiBearingX + width ) */
+ /* */
+ /* resp. */
+ /* */
+ /* vertical advance - */
+ /* ( vertBearingY + height ) */
+ /* */
+ /* max_before_BL :: Maximum of horiBearingY (resp. */
+ /* vertBearingY). */
+ /* */
+ /* min_after_BL :: Minimum of */
+ /* */
+ /* horiBearingY - height */
+ /* */
+ /* resp. */
+ /* */
+ /* vertBearingX - width */
+ /* */
+ /* pads :: Unused (to make the size of the record */
+ /* a multiple of 32 bits. */
+ /* */
+ typedef struct TT_SBit_Line_Metrics_
+ {
+ FT_Char ascender;
+ FT_Char descender;
+ FT_Byte max_width;
+ FT_Char caret_slope_numerator;
+ FT_Char caret_slope_denominator;
+ FT_Char caret_offset;
+ FT_Char min_origin_SB;
+ FT_Char min_advance_SB;
+ FT_Char max_before_BL;
+ FT_Char min_after_BL;
+ FT_Char pads[2];
+
+ } TT_SBit_Line_Metrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_SBit_Range */
+ /* */
+ /* <Description> */
+ /* A TrueType/OpenType subIndexTable as defined in the `EBLC' */
+ /* (Microsoft) or `bloc' (Apple) tables. */
+ /* */
+ /* <Fields> */
+ /* first_glyph :: The first glyph index in the range. */
+ /* */
+ /* last_glyph :: The last glyph index in the range. */
+ /* */
+ /* index_format :: The format of index table. Valid values are 1 */
+ /* to 5. */
+ /* */
+ /* image_format :: The format of `EBDT' image data. */
+ /* */
+ /* image_offset :: The offset to image data in `EBDT'. */
+ /* */
+ /* image_size :: For index formats 2 and 5. This is the size in */
+ /* bytes of each glyph bitmap. */
+ /* */
+ /* big_metrics :: For index formats 2 and 5. This is the big */
+ /* metrics for each glyph bitmap. */
+ /* */
+ /* num_glyphs :: For index formats 4 and 5. This is the number of */
+ /* glyphs in the code array. */
+ /* */
+ /* glyph_offsets :: For index formats 1 and 3. */
+ /* */
+ /* glyph_codes :: For index formats 4 and 5. */
+ /* */
+ /* table_offset :: The offset of the index table in the `EBLC' */
+ /* table. Only used during strike loading. */
+ /* */
+ typedef struct TT_SBit_Range
+ {
+ FT_UShort first_glyph;
+ FT_UShort last_glyph;
+
+ FT_UShort index_format;
+ FT_UShort image_format;
+ FT_ULong image_offset;
+
+ FT_ULong image_size;
+ TT_SBit_Metrics metrics;
+ FT_ULong num_glyphs;
+
+ FT_ULong* glyph_offsets;
+ FT_UShort* glyph_codes;
+
+ FT_ULong table_offset;
+
+ } TT_SBit_Range;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_SBit_Strike */
+ /* */
+ /* <Description> */
+ /* A structure used describe a given bitmap strike in the `EBLC' */
+ /* (Microsoft) or `bloc' (Apple) tables. */
+ /* */
+ /* <Fields> */
+ /* num_index_ranges :: The number of index ranges. */
+ /* */
+ /* index_ranges :: An array of glyph index ranges. */
+ /* */
+ /* color_ref :: Unused. A color reference? */
+ /* */
+ /* hori :: The line metrics for horizontal layouts. */
+ /* */
+ /* vert :: The line metrics for vertical layouts. */
+ /* */
+ /* start_glyph :: The lowest glyph index for this strike. */
+ /* */
+ /* end_glyph :: The highest glyph index for this strike. */
+ /* */
+ /* x_ppem :: The number of horizontal pixels per EM. */
+ /* */
+ /* y_ppem :: The number of vertical pixels per EM. */
+ /* */
+ /* bit_depth :: The bit depth. Valid values are 1, 2, 4, */
+ /* and 8. */
+ /* */
+ /* flags :: Is this a vertical or horizontal strike? */
+ /* */
+ typedef struct TT_SBit_Strike_
+ {
+ FT_Int num_ranges;
+ TT_SBit_Range* sbit_ranges;
+ FT_ULong ranges_offset;
+
+ FT_ULong color_ref;
+
+ TT_SBit_Line_Metrics hori;
+ TT_SBit_Line_Metrics vert;
+
+ FT_UShort start_glyph;
+ FT_UShort end_glyph;
+
+ FT_Byte x_ppem;
+ FT_Byte y_ppem;
+
+ FT_Byte bit_depth;
+ FT_Char flags;
+
+ } TT_SBit_Strike;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_SBit_Component */
+ /* */
+ /* <Description> */
+ /* A simple structure to describe a compound sbit element. */
+ /* */
+ /* <Fields> */
+ /* glyph_code :: The element's glyph index. */
+ /* */
+ /* x_offset :: The element's left bearing. */
+ /* */
+ /* y_offset :: The element's top bearing. */
+ /* */
+ typedef struct TT_SBit_Component_
+ {
+ FT_UShort glyph_code;
+
+ FT_Char x_offset;
+ FT_Char y_offset;
+
+ } TT_SBit_Component;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_SBit_Scale */
+ /* */
+ /* <Description> */
+ /* A structure used describe a given bitmap scaling table, as defined */
+ /* in the `EBSC' table. */
+ /* */
+ /* <Fields> */
+ /* hori :: The horizontal line metrics. */
+ /* */
+ /* vert :: The vertical line metrics. */
+ /* */
+ /* x_ppem :: The number of horizontal pixels per EM. */
+ /* */
+ /* y_ppem :: The number of vertical pixels per EM. */
+ /* */
+ /* x_ppem_substitute :: Substitution x_ppem value. */
+ /* */
+ /* y_ppem_substitute :: Substitution y_ppem value. */
+ /* */
+ typedef struct TT_SBit_Scale_
+ {
+ TT_SBit_Line_Metrics hori;
+ TT_SBit_Line_Metrics vert;
+
+ FT_Byte x_ppem;
+ FT_Byte y_ppem;
+
+ FT_Byte x_ppem_substitute;
+ FT_Byte y_ppem_substitute;
+
+ } TT_SBit_Scale;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** POSTSCRIPT GLYPH NAMES SUPPORT ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_Post_20 */
+ /* */
+ /* <Description> */
+ /* Postscript names sub-table, format 2.0. Stores the PS name of */
+ /* each glyph in the font face. */
+ /* */
+ /* <Fields> */
+ /* num_glyphs :: The number of named glyphs in the table. */
+ /* */
+ /* num_names :: The number of PS names stored in the table. */
+ /* */
+ /* glyph_indices :: The indices of the glyphs in the names arrays. */
+ /* */
+ /* glyph_names :: The PS names not in Mac Encoding. */
+ /* */
+ typedef struct TT_Post_20_
+ {
+ FT_UShort num_glyphs;
+ FT_UShort num_names;
+ FT_UShort* glyph_indices;
+ FT_Char** glyph_names;
+
+ } TT_Post_20;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_Post_25 */
+ /* */
+ /* <Description> */
+ /* Postscript names sub-table, format 2.5. Stores the PS name of */
+ /* each glyph in the font face. */
+ /* */
+ /* <Fields> */
+ /* num_glyphs :: The number of glyphs in the table. */
+ /* */
+ /* offsets :: An array of signed offsets in a normal Mac */
+ /* Postscript name encoding. */
+ /* */
+ typedef struct TT_Post_25_
+ {
+ FT_UShort num_glyphs;
+ FT_Char* offsets;
+
+ } TT_Post_25;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_Post_Names */
+ /* */
+ /* <Description> */
+ /* Postscript names table, either format 2.0 or 2.5. */
+ /* */
+ /* <Fields> */
+ /* loaded :: A flag to indicate whether the PS names are loaded. */
+ /* */
+ /* format_20 :: The sub-table used for format 2.0. */
+ /* */
+ /* format_25 :: The sub-table used for format 2.5. */
+ /* */
+ typedef struct TT_Post_Names_
+ {
+ FT_Bool loaded;
+
+ union
+ {
+ TT_Post_20 format_20;
+ TT_Post_25 format_25;
+
+ } names;
+
+ } TT_Post_Names;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** TRUETYPE CHARMAPS SUPPORT ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* format 0 */
+
+ typedef struct TT_CMap0_
+ {
+ FT_Byte* glyphIdArray;
+
+ } TT_CMap0;
+
+
+ /* format 2 */
+
+ typedef struct TT_CMap2SubHeader_
+ {
+ FT_UShort firstCode; /* first valid low byte */
+ FT_UShort entryCount; /* number of valid low bytes */
+ FT_Short idDelta; /* delta value to glyphIndex */
+ FT_UShort idRangeOffset; /* offset from here to 1st code */
+
+ } TT_CMap2SubHeader;
+
+
+ typedef struct TT_CMap2_
+ {
+ FT_UShort* subHeaderKeys;
+ /* high byte mapping table */
+ /* value = subHeader index * 8 */
+
+ TT_CMap2SubHeader* subHeaders;
+ FT_UShort* glyphIdArray;
+ FT_UShort numGlyphId; /* control value */
+
+ } TT_CMap2;
+
+
+ /* format 4 */
+
+ typedef struct TT_CMap4Segment_
+ {
+ FT_UShort endCount;
+ FT_UShort startCount;
+ FT_Short idDelta;
+ FT_UShort idRangeOffset;
+
+ } TT_CMap4Segment;
+
+
+ typedef struct TT_CMap4_
+ {
+ FT_UShort segCountX2; /* number of segments * 2 */
+ FT_UShort searchRange; /* these parameters can be used */
+ FT_UShort entrySelector; /* for a binary search */
+ FT_UShort rangeShift;
+
+ TT_CMap4Segment* segments;
+ FT_UShort* glyphIdArray;
+ FT_UShort numGlyphId; /* control value */
+
+ TT_CMap4Segment* last_segment; /* last used segment; this is a small */
+ /* cache to potentially increase speed */
+ } TT_CMap4;
+
+
+ /* format 6 */
+
+ typedef struct TT_CMap6_
+ {
+ FT_UShort firstCode; /* first character code of subrange */
+ FT_UShort entryCount; /* number of character codes in subrange */
+
+ FT_UShort* glyphIdArray;
+
+ } TT_CMap6;
+
+
+ typedef struct TT_CMapTable_ TT_CMapTable;
+
+
+ typedef
+ FT_UInt (*TT_CharMap_Func)( TT_CMapTable* charmap,
+ FT_ULong char_code );
+
+
+ /* charmap table */
+ struct TT_CMapTable_
+ {
+ FT_UShort platformID;
+ FT_UShort platformEncodingID;
+ FT_UShort format;
+ FT_UShort length;
+ FT_UShort version;
+
+ FT_Bool loaded;
+ FT_ULong offset;
+
+ union
+ {
+ TT_CMap0 cmap0;
+ TT_CMap2 cmap2;
+ TT_CMap4 cmap4;
+ TT_CMap6 cmap6;
+ } c;
+
+ TT_CharMap_Func get_index;
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_CharMapRec */
+ /* */
+ /* <Description> */
+ /* The TrueType character map object type. */
+ /* */
+ /* <Fields> */
+ /* root :: The parent character map structure. */
+ /* */
+ /* cmap :: The used character map. */
+ /* */
+ typedef struct TT_CharMapRec_
+ {
+ FT_CharMapRec root;
+ TT_CMapTable cmap;
+
+ } TT_CharMapRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** ORIGINAL TT_FACE CLASS DEFINITION ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This structure/class is defined here because it is common to the */
+ /* following formats: TTF, OpenType-TT, and OpenType-CFF. */
+ /* */
+ /* Note, however, that the classes TT_Size, TT_GlyphSlot, and TT_CharMap */
+ /* are not shared between font drivers, and are thus defined normally in */
+ /* `ttobjs.h'. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* TT_Face */
+ /* */
+ /* <Description> */
+ /* A handle to a TrueType face/font object. A TT_Face encapsulates */
+ /* the resolution and scaling independent parts of a TrueType font */
+ /* resource. */
+ /* */
+ /* <Note> */
+ /* The TT_Face structure is also used as a `parent class' for the */
+ /* OpenType-CFF class (T2_Face). */
+ /* */
+ typedef struct TT_FaceRec_* TT_Face;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* TT_CharMap */
+ /* */
+ /* <Description> */
+ /* A handle to a TrueType character mapping object. */
+ /* */
+ typedef struct TT_CharMapRec_* TT_CharMap;
+
+
+ /* a function type used for the truetype bytecode interpreter hooks */
+ typedef FT_Error (*TT_Interpreter)( void* exec_context );
+
+ /* forward declaration */
+ typedef struct TT_Loader_ TT_Loader;
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Goto_Table_Func */
+ /* */
+ /* <Description> */
+ /* Seeks a stream to the start of a given TrueType table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* tag :: A 4-byte tag used to name the table. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Output> */
+ /* length :: The length of the table in bytes. Set to 0 if not */
+ /* needed. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The stream cursor must be at the font file's origin. */
+ /* */
+ typedef
+ FT_Error (*TT_Goto_Table_Func)( TT_Face face,
+ FT_ULong tag,
+ FT_Stream stream,
+ FT_ULong* length );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Access_Glyph_Frame_Func */
+ /* */
+ /* <Description> */
+ /* Seeks a stream to the start of a given glyph element, and opens a */
+ /* frame for it. */
+ /* */
+ /* <Input> */
+ /* loader :: The current TrueType glyph loader object. */
+ /* */
+ /* glyph index :: The index of the glyph to access. */
+ /* */
+ /* offset :: The offset of the glyph according to the */
+ /* `locations' table. */
+ /* */
+ /* byte_count :: The size of the frame in bytes. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function is normally equivalent to FILE_Seek(offset) */
+ /* followed by ACCESS_Frame(byte_count) with the loader's stream, but */
+ /* alternative formats (e.g. compressed ones) might use something */
+ /* different. */
+ /* */
+ typedef
+ FT_Error (*TT_Access_Glyph_Frame_Func)( TT_Loader* loader,
+ FT_UInt glyph_index,
+ FT_ULong offset,
+ FT_UInt byte_count );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_Glyph_Element_Func */
+ /* */
+ /* <Description> */
+ /* Reads one glyph element (its header, a simple glyph, or a */
+ /* composite) from the loader's current stream frame. */
+ /* */
+ /* <Input> */
+ /* loader :: The current TrueType glyph loader object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ typedef
+ FT_Error (*TT_Load_Glyph_Element_Func)( TT_Loader* loader );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Forget_Glyph_Frame_Func */
+ /* */
+ /* <Description> */
+ /* Closes the current loader stream frame for the glyph. */
+ /* */
+ /* <Input> */
+ /* loader :: The current TrueType glyph loader object. */
+ /* */
+ typedef
+ void (*TT_Forget_Glyph_Frame_Func)( TT_Loader* loader );
+
+
+
+ /*************************************************************************/
+ /* */
+ /* TrueType Face Type */
+ /* */
+ /* <Struct> */
+ /* TT_Face */
+ /* */
+ /* <Description> */
+ /* The TrueType face class. These objects model the resolution and */
+ /* point-size independent data found in a TrueType font file. */
+ /* */
+ /* <Fields> */
+ /* root :: The base FT_Face structure, managed by the */
+ /* base layer. */
+ /* */
+ /* ttc_header :: The TrueType collection header, used when */
+ /* the file is a `ttc' rather than a `ttf'. */
+ /* For ordinary font files, the field */
+ /* `ttc_header.count' is set to 0. */
+ /* */
+ /* format_tag :: The font format tag. */
+ /* */
+ /* num_tables :: The number of TrueType tables in this font */
+ /* file. */
+ /* */
+ /* dir_tables :: The directory of TrueType tables for this */
+ /* font file. */
+ /* */
+ /* header :: The font's font header (`head' table). */
+ /* Read on font opening. */
+ /* */
+ /* horizontal :: The font's horizontal header (`hhea' */
+ /* table). This field also contains the */
+ /* associated horizontal metrics table */
+ /* (`hmtx'). */
+ /* */
+ /* max_profile :: The font's maximum profile table. Read on */
+ /* font opening. Note that some maximum */
+ /* values cannot be taken directly from this */
+ /* table. We thus define additional fields */
+ /* below to hold the computed maxima. */
+ /* */
+ /* max_components :: The maximum number of glyph components */
+ /* required to load any composite glyph from */
+ /* this font. Used to size the load stack. */
+ /* */
+ /* vertical_info :: A boolean which is set when the font file */
+ /* contains vertical metrics. If not, the */
+ /* value of the `vertical' field is */
+ /* undefined. */
+ /* */
+ /* vertical :: The font's vertical header (`vhea' table). */
+ /* This field also contains the associated */
+ /* vertical metrics table (`vmtx'), if found. */
+ /* IMPORTANT: The contents of this field is */
+ /* undefined if the `verticalInfo' field is */
+ /* unset. */
+ /* */
+ /* num_names :: The number of name records within this */
+ /* TrueType font. */
+ /* */
+ /* name_table :: The table of name records (`name'). */
+ /* */
+ /* os2 :: The font's OS/2 table (`OS/2'). */
+ /* */
+ /* postscript :: The font's PostScript table (`post' */
+ /* table). The PostScript glyph names are */
+ /* not loaded by the driver on face opening. */
+ /* See the `ttpost' module for more details. */
+ /* */
+ /* num_charmaps :: The number of character mappings in the */
+ /* font. */
+ /* */
+ /* charmaps :: The array of charmap objects for this font */
+ /* file. Note that this field is a typeless */
+ /* pointer. The Reason is that the format of */
+ /* charmaps varies with the underlying font */
+ /* format and cannot be determined here. */
+ /* */
+ /* goto_table :: A function called by each TrueType table */
+ /* loader to position a stream's cursor to */
+ /* the start of a given table according to */
+ /* its tag. It defaults to TT_Goto_Face but */
+ /* can be different for strange formats (e.g. */
+ /* Type 42). */
+ /* */
+ /* access_glyph_frame :: XXX */
+ /* */
+ /* read_glyph_header :: XXX */
+ /* */
+ /* read_simple_glyph :: XXX */
+ /* */
+ /* read_composite_glyph :: XXX */
+ /* */
+ /* forget_glyph_frame :: XXX */
+ /* */
+ /* sfnt :: A pointer to the SFNT `driver' interface. */
+ /* */
+ /* psnames :: A pointer to the `PSNames' module */
+ /* interface. */
+ /* */
+ /* hdmx :: The face's horizontal device metrics */
+ /* (`hdmx' table). This table is optional in */
+ /* TrueType/OpenType fonts. */
+ /* */
+ /* gasp :: The grid-fitting and scaling properties */
+ /* table (`gasp'). This table is optional in */
+ /* TrueType/OpenType fonts. */
+ /* */
+ /* pclt :: XXX */
+ /* */
+ /* num_sbit_strikes :: The number of sbit strikes, i.e., bitmap */
+ /* sizes, embedded in this font. */
+ /* */
+ /* sbit_strikes :: An array of sbit strikes embedded in this */
+ /* font. This table is optional in a */
+ /* TrueType/OpenType font. */
+ /* */
+ /* num_sbit_scales :: The number of sbit scales for this font. */
+ /* */
+ /* sbit_scales :: Array of sbit scales embedded in this */
+ /* font. This table is optional in a */
+ /* TrueType/OpenType font. */
+ /* */
+ /* postscript_names :: A table used to store the Postscript names */
+ /* of the glyphs for this font. See the */
+ /* file `ttconfig.h' for comments on the */
+ /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES option. */
+ /* */
+ /* num_locations :: The number of glyph locations in this */
+ /* TrueType file. This should be */
+ /* identical to the number of glyphs. */
+ /* Ignored for Type 2 fonts. */
+ /* */
+ /* glyph_locations :: An array of longs. These are offsets to */
+ /* glyph data within the `glyf' table. */
+ /* Ignored for Type 2 font faces. */
+ /* */
+ /* font_program_size :: Size in bytecodes of the face's font */
+ /* program. 0 if none defined. Ignored for */
+ /* Type 2 fonts. */
+ /* */
+ /* font_program :: The face's font program (bytecode stream) */
+ /* executed at load time, also used during */
+ /* glyph rendering. Comes from the `fpgm' */
+ /* table. Ignored for Type 2 font fonts. */
+ /* */
+ /* cvt_program_size :: The size in bytecodes of the face's cvt */
+ /* program. Ignored for Type 2 fonts. */
+ /* */
+ /* cvt_program :: The face's cvt program (bytecode stream) */
+ /* executed each time an instance/size is */
+ /* changed/reset. Comes from the `prep' */
+ /* table. Ignored for Type 2 fonts. */
+ /* */
+ /* cvt_size :: Size of the control value table (in */
+ /* entries). Ignored for Type 2 fonts. */
+ /* */
+ /* cvt :: The face's original control value table. */
+ /* Coordinates are expressed in unscaled font */
+ /* units. Comes from the `cvt ' table. */
+ /* Ignored for Type 2 fonts. */
+ /* */
+ /* num_kern_pairs :: The number of kerning pairs present in the */
+ /* font file. The engine only loads the */
+ /* first horizontal format 0 kern table it */
+ /* finds in the font file. You should use */
+ /* the `ttxkern' structures if you want to */
+ /* access other kerning tables. Ignored */
+ /* for Type 2 fonts. */
+ /* */
+ /* kern_table_index :: The index of the kerning table in the font */
+ /* kerning directory. Only used by the */
+ /* ttxkern extension to avoid data */
+ /* duplication. Ignored for Type 2 fonts. */
+ /* */
+ /* interpreter :: A pointer to the TrueType bytecode */
+ /* interpreters field is also used to hook */
+ /* the debugger in `ttdebug'. */
+ /* */
+ /* extra :: XXX */
+ /* */
+ typedef struct TT_FaceRec_
+ {
+ FT_FaceRec root;
+
+ TTC_Header ttc_header;
+
+ FT_ULong format_tag;
+ FT_UShort num_tables;
+ TT_Table* dir_tables;
+
+ TT_Header header; /* TrueType header table */
+ TT_HoriHeader horizontal; /* TrueType horizontal header */
+
+ TT_MaxProfile max_profile;
+ FT_ULong max_components;
+
+ FT_Bool vertical_info;
+ TT_VertHeader vertical; /* TT Vertical header, if present */
+
+ FT_Int num_names; /* number of name records */
+ TT_NameTable name_table; /* name table */
+
+ TT_OS2 os2; /* TrueType OS/2 table */
+ TT_Postscript postscript; /* TrueType Postscript table */
+
+ FT_Int num_charmaps;
+ TT_CharMap charmaps; /* array of TT_CharMapRec */
+
+ TT_Goto_Table_Func goto_table;
+
+ TT_Access_Glyph_Frame_Func access_glyph_frame;
+ TT_Load_Glyph_Element_Func read_glyph_header;
+ TT_Load_Glyph_Element_Func read_simple_glyph;
+ TT_Load_Glyph_Element_Func read_composite_glyph;
+ TT_Forget_Glyph_Frame_Func forget_glyph_frame;
+
+ /* a typeless pointer to the SFNT_Interface table used to load */
+ /* the basic TrueType tables in the face object */
+ void* sfnt;
+
+ /* a typeless pointer to the PSNames_Interface table used to */
+ /* handle glyph names <-> unicode & Mac values */
+ void* psnames;
+
+ /***********************************************************************/
+ /* */
+ /* Optional TrueType/OpenType tables */
+ /* */
+ /***********************************************************************/
+
+ /* horizontal device metrics */
+ TT_Hdmx hdmx;
+
+ /* grid-fitting and scaling table */
+ TT_Gasp gasp; /* the `gasp' table */
+
+ /* PCL 5 table */
+ TT_PCLT pclt;
+
+ /* embedded bitmaps support */
+ FT_Int num_sbit_strikes;
+ TT_SBit_Strike* sbit_strikes;
+
+ FT_Int num_sbit_scales;
+ TT_SBit_Scale* sbit_scales;
+
+ /* postscript names table */
+ TT_Post_Names postscript_names;
+
+
+ /***********************************************************************/
+ /* */
+ /* TrueType-specific fields (ignored by the OTF-Type2 driver) */
+ /* */
+ /***********************************************************************/
+
+ /* the glyph locations */
+ FT_UShort num_locations;
+ FT_Long* glyph_locations;
+
+ /* the font program, if any */
+ FT_ULong font_program_size;
+ FT_Byte* font_program;
+
+ /* the cvt program, if any */
+ FT_ULong cvt_program_size;
+ FT_Byte* cvt_program;
+
+ /* the original, unscaled, control value table */
+ FT_ULong cvt_size;
+ FT_Short* cvt;
+
+ /* the format 0 kerning table, if any */
+ FT_Int num_kern_pairs;
+ FT_Int kern_table_index;
+ TT_Kern_0_Pair* kern_pairs;
+
+ /* A pointer to the bytecode interpreter to use. This is also */
+ /* used to hook the debugger for the `ttdebug' utility. */
+ TT_Interpreter interpreter;
+
+
+ /***********************************************************************/
+ /* */
+ /* Other tables or fields. This is used by derivative formats like */
+ /* OpenType. */
+ /* */
+ /***********************************************************************/
+
+ FT_Generic extra;
+
+ } TT_FaceRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_GlyphZone */
+ /* */
+ /* <Description> */
+ /* A glyph zone is used to load, scale and hint glyph outline */
+ /* coordinates. */
+ /* */
+ /* <Fields> */
+ /* memory :: A handle to the memory manager. */
+ /* */
+ /* max_points :: The maximal size in points of the zone. */
+ /* */
+ /* max_contours :: Max size in links contours of thez one. */
+ /* */
+ /* n_points :: The current number of points in the zone. */
+ /* */
+ /* n_contours :: The current number of contours in the zone. */
+ /* */
+ /* org :: The original glyph coordinates (font */
+ /* units/scaled). */
+ /* */
+ /* cur :: The current glyph coordinates (scaled/hinted). */
+ /* */
+ /* tags :: The point control tags. */
+ /* */
+ /* contours :: The contours end points. */
+ /* */
+ typedef struct TT_GlyphZone_
+ {
+ FT_Memory memory;
+ FT_UShort max_points;
+ FT_UShort max_contours;
+ FT_UShort n_points; /* number of points in zone */
+ FT_Short n_contours; /* number of contours */
+
+ FT_Vector* org; /* original point coordinates */
+ FT_Vector* cur; /* current point coordinates */
+
+ FT_Byte* tags; /* current touch flags */
+ FT_UShort* contours; /* contour end points */
+
+ } TT_GlyphZone;
+
+
+ /* handle to execution context */
+ typedef struct TT_ExecContextRec_* TT_ExecContext;
+
+ /* glyph loader structure */
+ struct TT_Loader_
+ {
+ FT_Face face;
+ FT_Size size;
+ FT_GlyphSlot glyph;
+ FT_GlyphLoader* gloader;
+
+ FT_ULong load_flags;
+ FT_UInt glyph_index;
+
+ FT_Stream stream;
+ FT_Int byte_len;
+
+ FT_Short n_contours;
+ FT_BBox bbox;
+ FT_Int left_bearing;
+ FT_Int advance;
+ FT_Bool preserve_pps;
+ FT_Vector pp1;
+ FT_Vector pp2;
+
+ FT_ULong glyf_offset;
+
+ /* the zone where we load our glyphs */
+ TT_GlyphZone base;
+ TT_GlyphZone zone;
+
+ TT_ExecContext exec;
+ FT_Byte* instructions;
+ FT_ULong ins_pos;
+
+ /* for possible extensibility in other formats */
+ void* other;
+
+ };
+
+
+#endif /* TTTYPES_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1tables.h */
+/* */
+/* Basic Type 1/Type 2 tables definitions and interface (specification */
+/* only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T1TABLES_H
+#define T1TABLES_H
+
+
+#include <freetype/freetype.h>
+
+
+ /* Note that we separate font data in T1_FontInfo and T1_Private */
+ /* structures in order to support Multiple Master fonts. */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_FontInfo */
+ /* */
+ /* <Description> */
+ /* A structure used to model a Type1/Type2 FontInfo dictionary. Note */
+ /* that for Multiple Master fonts, each instance has its own */
+ /* FontInfo. */
+ /* */
+ typedef struct T1_FontInfo
+ {
+ FT_String* version;
+ FT_String* notice;
+ FT_String* full_name;
+ FT_String* family_name;
+ FT_String* weight;
+ FT_Long italic_angle;
+ FT_Bool is_fixed_pitch;
+ FT_Short underline_position;
+ FT_UShort underline_thickness;
+
+ } T1_FontInfo;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_Private */
+ /* */
+ /* <Description> */
+ /* A structure used to model a Type1/Type2 FontInfo dictionary. Note */
+ /* that for Multiple Master fonts, each instance has its own Private */
+ /* dict. */
+ /* */
+ typedef struct T1_Private
+ {
+ FT_Int unique_id;
+ FT_Int lenIV;
+
+ FT_Byte num_blue_values;
+ FT_Byte num_other_blues;
+ FT_Byte num_family_blues;
+ FT_Byte num_family_other_blues;
+
+ FT_Short blue_values[14];
+ FT_Short other_blues[10];
+
+ FT_Short family_blues [14];
+ FT_Short family_other_blues[10];
+
+ FT_Fixed blue_scale;
+ FT_Int blue_shift;
+ FT_Int blue_fuzz;
+
+ FT_UShort standard_width[1];
+ FT_UShort standard_height[1];
+
+ FT_Byte num_snap_widths;
+ FT_Byte num_snap_heights;
+ FT_Bool force_bold;
+ FT_Bool round_stem_up;
+
+ 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;
+
+ FT_Short min_feature[2];
+
+ } T1_Private;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* T1_Blend_Flags */
+ /* */
+ /* <Description> */
+ /* A set of flags used to indicate which fields are present in a */
+ /* given blen dictionary (font info or private). Used to support */
+ /* Multiple Masters fonts. */
+ /* */
+ typedef enum
+ {
+ /* required fields in a FontInfo blend dictionary */
+ t1_blend_underline_position = 0,
+ t1_blend_underline_thickness,
+ t1_blend_italic_angle,
+
+ /* required fields in a Private blend dictionary */
+ t1_blend_blue_values,
+ t1_blend_other_blues,
+ t1_blend_standard_width,
+ t1_blend_standard_height,
+ t1_blend_stem_snap_widths,
+ t1_blend_stem_snap_heights,
+ t1_blend_blue_scale,
+ t1_blend_blue_shift,
+ t1_blend_family_blues,
+ t1_blend_family_other_blues,
+ t1_blend_force_bold,
+
+ /* never remove */
+ t1_blend_max
+
+ } T1_Blend_Flags;
+
+
+ /* maximum number of Multiple Masters designs, as defined in the spec */
+#define T1_MAX_MM_DESIGNS 16
+
+ /* maximum number of Multiple Masters axes, as defined in the spec */
+#define T1_MAX_MM_AXIS 4
+
+ /* maximum number of elements in a design map */
+#define T1_MAX_MM_MAP_POINTS 20
+
+
+ /* this structure is used to store the BlendDesignMap entry for an axis */
+ typedef struct T1_DesignMap_
+ {
+ FT_Byte num_points;
+ FT_Fixed* design_points;
+ FT_Fixed* blend_points;
+
+ } T1_DesignMap;
+
+
+ typedef struct T1_Blend_
+ {
+ FT_UInt num_designs;
+ FT_UInt num_axis;
+
+ FT_String* axis_names[T1_MAX_MM_AXIS];
+ FT_Fixed* design_pos[T1_MAX_MM_DESIGNS];
+ T1_DesignMap design_map[T1_MAX_MM_AXIS];
+
+ FT_Fixed* weight_vector;
+ FT_Fixed* default_weight_vector;
+
+ T1_FontInfo* font_infos[T1_MAX_MM_DESIGNS + 1];
+ T1_Private* privates [T1_MAX_MM_DESIGNS + 1];
+
+ FT_ULong blend_bitflags;
+
+ } T1_Blend;
+
+
+ typedef struct CID_FontDict_
+ {
+ 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;
+
+ } CID_FontDict;
+
+
+ typedef struct CID_Info_
+ {
+ FT_String* cid_font_name;
+ FT_Fixed cid_version;
+ FT_Int cid_font_type;
+
+ FT_String* registry;
+ FT_String* ordering;
+ FT_Int supplement;
+
+ T1_FontInfo font_info;
+ FT_BBox font_bbox;
+ FT_ULong uid_base;
+
+ FT_Int num_xuid;
+ FT_ULong xuid[16];
+
+
+ FT_ULong cidmap_offset;
+ FT_Int fd_bytes;
+ FT_Int gd_bytes;
+ FT_ULong cid_count;
+
+ FT_Int num_dicts;
+ CID_FontDict* font_dicts;
+
+ FT_ULong data_offset;
+
+ } CID_Info;
+
+
+#endif /* T1TABLES_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttmakeid.h */
+/* */
+/* TrueType name ID definitions (specification only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef TTNAMEID_H
+#define TTNAMEID_H
+
+
+ /*************************************************************************/
+ /* */
+ /* Possible values for the `platform' identifier code in the name */
+ /* records of the TTF `name' table. */
+ /* */
+#define TT_PLATFORM_APPLE_UNICODE 0
+#define TT_PLATFORM_MACINTOSH 1
+#define TT_PLATFORM_ISO 2 /* deprecated */
+#define TT_PLATFORM_MICROSOFT 3
+
+
+ /*************************************************************************/
+ /* */
+ /* Possible values of the platform specific encoding identifier field in */
+ /* the name records of the TTF `name' table if the `platform' identifier */
+ /* code is TT_PLATFORM_APPLE_UNICODE. */
+ /* */
+#define TT_APPLE_ID_DEFAULT 0
+#define TT_APPLE_ID_UNICODE_1_1 1 /* specify Hangul at U+34xx */
+#define TT_APPLE_ID_ISO_10646 2 /* deprecated */
+#define TT_APPLE_ID_UNICODE_2_0 3 /* or later */
+
+
+ /*************************************************************************/
+ /* */
+ /* Possible values of the platform specific encoding identifier field in */
+ /* the name records of the TTF `name' table if the `platform' identifier */
+ /* code is TT_PLATFORM_MACINTOSH. */
+ /* */
+#define TT_MAC_ID_ROMAN 0
+#define TT_MAC_ID_JAPANESE 1
+#define TT_MAC_ID_TRADITIONAL_CHINESE 2
+#define TT_MAC_ID_KOREAN 3
+#define TT_MAC_ID_ARABIC 4
+#define TT_MAC_ID_HEBREW 5
+#define TT_MAC_ID_GREEK 6
+#define TT_MAC_ID_RUSSIAN 7
+#define TT_MAC_ID_RSYMBOL 8
+#define TT_MAC_ID_DEVANAGARI 9
+#define TT_MAC_ID_GURMUKHI 10
+#define TT_MAC_ID_GUJARATI 11
+#define TT_MAC_ID_ORIYA 12
+#define TT_MAC_ID_BENGALI 13
+#define TT_MAC_ID_TAMIL 14
+#define TT_MAC_ID_TELUGU 15
+#define TT_MAC_ID_KANNADA 16
+#define TT_MAC_ID_MALAYALAM 17
+#define TT_MAC_ID_SINHALESE 18
+#define TT_MAC_ID_BURMESE 19
+#define TT_MAC_ID_KHMER 20
+#define TT_MAC_ID_THAI 21
+#define TT_MAC_ID_LAOTIAN 22
+#define TT_MAC_ID_GEORGIAN 23
+#define TT_MAC_ID_ARMENIAN 24
+#define TT_MAC_ID_MALDIVIAN 25
+#define TT_MAC_ID_SIMPLIFIED_CHINESE 25
+#define TT_MAC_ID_TIBETAN 26
+#define TT_MAC_ID_MONGOLIAN 27
+#define TT_MAC_ID_GEEZ 28
+#define TT_MAC_ID_SLAVIC 29
+#define TT_MAC_ID_VIETNAMESE 30
+#define TT_MAC_ID_SINDHI 31
+#define TT_MAC_ID_UNINTERP 32
+
+
+ /*************************************************************************/
+ /* */
+ /* Possible values of the platform specific encoding identifier field in */
+ /* the name records of the TTF `name' table if the `platform' identifier */
+ /* code is TT_PLATFORM_ISO. */
+ /* */
+ /* This use is now deprecated. */
+ /* */
+#define TT_ISO_ID_7BIT_ASCII 0
+#define TT_ISO_ID_10646 1
+#define TT_ISO_ID_8859_1 2
+
+
+ /*************************************************************************/
+ /* */
+ /* possible values of the platform specific encoding identifier field in */
+ /* the name records of the TTF `name' table if the `platform' identifier */
+ /* code is TT_PLATFORM_MICROSOFT. */
+ /* */
+#define TT_MS_ID_SYMBOL_CS 0
+#define TT_MS_ID_UNICODE_CS 1
+#define TT_MS_ID_SJIS 2
+#define TT_MS_ID_GB2312 3
+#define TT_MS_ID_BIG_5 4
+#define TT_MS_ID_WANSUNG 5
+#define TT_MS_ID_JOHAB 6
+
+
+ /*************************************************************************/
+ /* */
+ /* Possible values of the language identifier field in the name records */
+ /* of the TTF `name' table if the `platform' identifier code is */
+ /* TT_PLATFORM_MACINTOSH. */
+ /* */
+ /* The canonical source for the Apple assigned Language ID's is at */
+ /* */
+ /* http://fonts.apple.com/TTRefMan/RM06/Chap6name.html */
+ /* */
+#define TT_MAC_LANGID_ENGLISH 0
+#define TT_MAC_LANGID_FRENCH 1
+#define TT_MAC_LANGID_GERMAN 2
+#define TT_MAC_LANGID_ITALIAN 3
+#define TT_MAC_LANGID_DUTCH 4
+#define TT_MAC_LANGID_SWEDISH 5
+#define TT_MAC_LANGID_SPANISH 6
+#define TT_MAC_LANGID_DANISH 7
+#define TT_MAC_LANGID_PORTUGUESE 8
+#define TT_MAC_LANGID_NORWEGIAN 9
+#define TT_MAC_LANGID_HEBREW 10
+#define TT_MAC_LANGID_JAPANESE 11
+#define TT_MAC_LANGID_ARABIC 12
+#define TT_MAC_LANGID_FINNISH 13
+#define TT_MAC_LANGID_GREEK 14
+#define TT_MAC_LANGID_ICELANDIC 15
+#define TT_MAC_LANGID_MALTESE 16
+#define TT_MAC_LANGID_TURKISH 17
+#define TT_MAC_LANGID_CROATIAN 18
+#define TT_MAC_LANGID_CHINESE_TRADITIONAL 19
+#define TT_MAC_LANGID_URDU 20
+#define TT_MAC_LANGID_HINDI 21
+#define TT_MAC_LANGID_THAI 22
+#define TT_MAC_LANGID_KOREAN 23
+#define TT_MAC_LANGID_LITHUANIAN 24
+#define TT_MAC_LANGID_POLISH 25
+#define TT_MAC_LANGID_HUNGARIAN 26
+#define TT_MAC_LANGID_ESTONIAN 27
+#define TT_MAC_LANGID_LETTISH 28
+#define TT_MAC_LANGID_SAAMISK 29
+#define TT_MAC_LANGID_FAEROESE 30
+#define TT_MAC_LANGID_FARSI 31
+#define TT_MAC_LANGID_RUSSIAN 32
+#define TT_MAC_LANGID_CHINESE_SIMPLIFIED 33
+#define TT_MAC_LANGID_FLEMISH 34
+#define TT_MAC_LANGID_IRISH 35
+#define TT_MAC_LANGID_ALBANIAN 36
+#define TT_MAC_LANGID_ROMANIAN 37
+#define TT_MAC_LANGID_CZECH 38
+#define TT_MAC_LANGID_SLOVAK 39
+#define TT_MAC_LANGID_SLOVENIAN 40
+#define TT_MAC_LANGID_YIDDISH 41
+#define TT_MAC_LANGID_SERBIAN 42
+#define TT_MAC_LANGID_MACEDONIAN 43
+#define TT_MAC_LANGID_BULGARIAN 44
+#define TT_MAC_LANGID_UKRAINIAN 45
+#define TT_MAC_LANGID_BYELORUSSIAN 46
+#define TT_MAC_LANGID_UZBEK 47
+#define TT_MAC_LANGID_KAZAKH 48
+#define TT_MAC_LANGID_AZERBAIJANI 49
+#define TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT 49
+#define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT 50
+#define TT_MAC_LANGID_ARMENIAN 51
+#define TT_MAC_LANGID_GEORGIAN 52
+#define TT_MAC_LANGID_MOLDAVIAN 53
+#define TT_MAC_LANGID_KIRGHIZ 54
+#define TT_MAC_LANGID_TAJIKI 55
+#define TT_MAC_LANGID_TURKMEN 56
+#define TT_MAC_LANGID_MONGOLIAN 57
+#define TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT 57
+#define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT 58
+#define TT_MAC_LANGID_PASHTO 59
+#define TT_MAC_LANGID_KURDISH 60
+#define TT_MAC_LANGID_KASHMIRI 61
+#define TT_MAC_LANGID_SINDHI 62
+#define TT_MAC_LANGID_TIBETAN 63
+#define TT_MAC_LANGID_NEPALI 64
+#define TT_MAC_LANGID_SANSKRIT 65
+#define TT_MAC_LANGID_MARATHI 66
+#define TT_MAC_LANGID_BENGALI 67
+#define TT_MAC_LANGID_ASSAMESE 68
+#define TT_MAC_LANGID_GUJARATI 69
+#define TT_MAC_LANGID_PUNJABI 70
+#define TT_MAC_LANGID_ORIYA 71
+#define TT_MAC_LANGID_MALAYALAM 72
+#define TT_MAC_LANGID_KANNADA 73
+#define TT_MAC_LANGID_TAMIL 74
+#define TT_MAC_LANGID_TELUGU 75
+#define TT_MAC_LANGID_SINHALESE 76
+#define TT_MAC_LANGID_BURMESE 77
+#define TT_MAC_LANGID_KHMER 78
+#define TT_MAC_LANGID_LAO 79
+#define TT_MAC_LANGID_VIETNAMESE 80
+#define TT_MAC_LANGID_INDONESIAN 81
+#define TT_MAC_LANGID_TAGALOG 82
+#define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT 83
+#define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT 84
+#define TT_MAC_LANGID_AMHARIC 85
+#define TT_MAC_LANGID_TIGRINYA 86
+#define TT_MAC_LANGID_GALLA 87
+#define TT_MAC_LANGID_SOMALI 88
+#define TT_MAC_LANGID_SWAHILI 89
+#define TT_MAC_LANGID_RUANDA 90
+#define TT_MAC_LANGID_RUNDI 91
+#define TT_MAC_LANGID_CHEWA 92
+#define TT_MAC_LANGID_MALAGASY 93
+#define TT_MAC_LANGID_ESPERANTO 94
+#define TT_MAC_LANGID_WELSH 128
+#define TT_MAC_LANGID_BASQUE 129
+#define TT_MAC_LANGID_CATALAN 130
+#define TT_MAC_LANGID_LATIN 131
+#define TT_MAC_LANGID_QUECHUA 132
+#define TT_MAC_LANGID_GUARANI 133
+#define TT_MAC_LANGID_AYMARA 134
+#define TT_MAC_LANGID_TATAR 135
+#define TT_MAC_LANGID_UIGHUR 136
+#define TT_MAC_LANGID_DZONGKHA 137
+#define TT_MAC_LANGID_JAVANESE 138
+#define TT_MAC_LANGID_SUNDANESE 139
+
+
+#if 0 /* these seem to be errors that have been dropped */
+
+#define TT_MAC_LANGID_SCOTTISH_GAELIC 140
+#define TT_MAC_LANGID_IRISH_GAELIC 141
+
+#endif
+
+
+ /* The following codes are new as of 2000-03-10 */
+#define TT_MAC_LANGID_GALICIAN 140
+#define TT_MAC_LANGID_AFRIKAANS 141
+#define TT_MAC_LANGID_BRETON 142
+#define TT_MAC_LANGID_INUKTITUT 143
+#define TT_MAC_LANGID_SCOTTISH_GAELIC 144
+#define TT_MAC_LANGID_MANX_GAELIC 145
+#define TT_MAC_LANGID_IRISH_GAELIC 146
+#define TT_MAC_LANGID_TONGAN 147
+#define TT_MAC_LANGID_GREEK_POLYTONIC 148
+#define TT_MAC_LANGID_GREELANDIC 149
+#define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT 150
+
+
+ /*************************************************************************/
+ /* */
+ /* Possible values of the language identifier field in the name records */
+ /* of the TTF `name' table if the `platform' identifier code is */
+ /* TT_PLATFORM_MICROSOFT. */
+ /* */
+ /* The canonical source for the MS assigned LCID's is at */
+ /* */
+ /* http://www.microsoft.com/typography/OTSPEC/lcid-cp.txt */
+ /* */
+#define TT_MS_LANGID_ARABIC_SAUDI_ARABIA 0x0401
+#define TT_MS_LANGID_ARABIC_IRAQ 0x0801
+#define TT_MS_LANGID_ARABIC_EGYPT 0x0c01
+#define TT_MS_LANGID_ARABIC_LIBYA 0x1001
+#define TT_MS_LANGID_ARABIC_ALGERIA 0x1401
+#define TT_MS_LANGID_ARABIC_MOROCCO 0x1801
+#define TT_MS_LANGID_ARABIC_TUNISIA 0x1c01
+#define TT_MS_LANGID_ARABIC_OMAN 0x2001
+#define TT_MS_LANGID_ARABIC_YEMEN 0x2401
+#define TT_MS_LANGID_ARABIC_SYRIA 0x2801
+#define TT_MS_LANGID_ARABIC_JORDAN 0x2c01
+#define TT_MS_LANGID_ARABIC_LEBANON 0x3001
+#define TT_MS_LANGID_ARABIC_KUWAIT 0x3401
+#define TT_MS_LANGID_ARABIC_UAE 0x3801
+#define TT_MS_LANGID_ARABIC_BAHRAIN 0x3c01
+#define TT_MS_LANGID_ARABIC_QATAR 0x4001
+#define TT_MS_LANGID_BULGARIAN_BULGARIA 0x0402
+#define TT_MS_LANGID_CATALAN_SPAIN 0x0403
+#define TT_MS_LANGID_CHINESE_TAIWAN 0x0404
+#define TT_MS_LANGID_CHINESE_PRC 0x0804
+#define TT_MS_LANGID_CHINESE_HONG_KONG 0x0c04
+#define TT_MS_LANGID_CHINESE_SINGAPORE 0x1004
+#define TT_MS_LANGID_CHINESE_MACAU 0x1404
+#define TT_MS_LANGID_CZECH_CZECH_REPUBLIC 0x0405
+#define TT_MS_LANGID_DANISH_DENMARK 0x0406
+#define TT_MS_LANGID_GERMAN_GERMANY 0x0407
+#define TT_MS_LANGID_GERMAN_SWITZERLAND 0x0807
+#define TT_MS_LANGID_GERMAN_AUSTRIA 0x0c07
+#define TT_MS_LANGID_GERMAN_LUXEMBOURG 0x1007
+#define TT_MS_LANGID_GERMAN_LIECHTENSTEI 0x1407
+#define TT_MS_LANGID_GREEK_GREECE 0x0408
+#define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409
+#define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM 0x0809
+#define TT_MS_LANGID_ENGLISH_AUSTRALIA 0x0c09
+#define TT_MS_LANGID_ENGLISH_CANADA 0x1009
+#define TT_MS_LANGID_ENGLISH_NEW_ZEALAND 0x1409
+#define TT_MS_LANGID_ENGLISH_IRELAND 0x1809
+#define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA 0x1c09
+#define TT_MS_LANGID_ENGLISH_JAMAICA 0x2009
+#define TT_MS_LANGID_ENGLISH_CARIBBEAN 0x2409
+#define TT_MS_LANGID_ENGLISH_BELIZE 0x2809
+#define TT_MS_LANGID_ENGLISH_TRINIDAD 0x2c09
+#define TT_MS_LANGID_ENGLISH_ZIMBABWE 0x3009
+#define TT_MS_LANGID_ENGLISH_PHILIPPINES 0x3409
+#define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT 0x040a
+#define TT_MS_LANGID_SPANISH_MEXICO 0x080a
+#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT 0x0c0a
+#define TT_MS_LANGID_SPANISH_GUATEMALA 0x100a
+#define TT_MS_LANGID_SPANISH_COSTA_RICA 0x140a
+#define TT_MS_LANGID_SPANISH_PANAMA 0x180a
+#define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC 0x1c0a
+#define TT_MS_LANGID_SPANISH_VENEZUELA 0x200a
+#define TT_MS_LANGID_SPANISH_COLOMBIA 0x240a
+#define TT_MS_LANGID_SPANISH_PERU 0x280a
+#define TT_MS_LANGID_SPANISH_ARGENTINA 0x2c0a
+#define TT_MS_LANGID_SPANISH_ECUADOR 0x300a
+#define TT_MS_LANGID_SPANISH_CHILE 0x340a
+#define TT_MS_LANGID_SPANISH_URUGUAY 0x380a
+#define TT_MS_LANGID_SPANISH_PARAGUAY 0x3c0a
+#define TT_MS_LANGID_SPANISH_BOLIVIA 0x400a
+#define TT_MS_LANGID_SPANISH_EL_SALVADOR 0x440a
+#define TT_MS_LANGID_SPANISH_HONDURAS 0x480a
+#define TT_MS_LANGID_SPANISH_NICARAGUA 0x4c0a
+#define TT_MS_LANGID_SPANISH_PUERTO_RICO 0x500a
+#define TT_MS_LANGID_FINNISH_FINLAND 0x040b
+#define TT_MS_LANGID_FRENCH_FRANCE 0x040c
+#define TT_MS_LANGID_FRENCH_BELGIUM 0x080c
+#define TT_MS_LANGID_FRENCH_CANADA 0x0c0c
+#define TT_MS_LANGID_FRENCH_SWITZERLAND 0x100c
+#define TT_MS_LANGID_FRENCH_LUXEMBOURG 0x140c
+#define TT_MS_LANGID_FRENCH_MONACO 0x180c
+#define TT_MS_LANGID_HEBREW_ISRAEL 0x040d
+#define TT_MS_LANGID_HUNGARIAN_HUNGARY 0x040e
+#define TT_MS_LANGID_ICELANDIC_ICELAND 0x040f
+#define TT_MS_LANGID_ITALIAN_ITALY 0x0410
+#define TT_MS_LANGID_ITALIAN_SWITZERLAND 0x0810
+#define TT_MS_LANGID_JAPANESE_JAPAN 0x0411
+#define TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA 0x0412
+#define TT_MS_LANGID_KOREAN_JOHAB_KOREA 0x0812
+#define TT_MS_LANGID_DUTCH_NETHERLANDS 0x0413
+#define TT_MS_LANGID_DUTCH_BELGIUM 0x0813
+#define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL 0x0414
+#define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK 0x0814
+#define TT_MS_LANGID_POLISH_POLAND 0x0415
+#define TT_MS_LANGID_PORTUGUESE_BRAZIL 0x0416
+#define TT_MS_LANGID_PORTUGUESE_PORTUGAL 0x0816
+#define TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND 0x0417
+#define TT_MS_LANGID_ROMANIAN_ROMANIA 0x0418
+#define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA 0x0818
+#define TT_MS_LANGID_RUSSIAN_RUSSIA 0x0419
+#define TT_MS_LANGID_RUSSIAN_MOLDAVIA 0x0819
+#define TT_MS_LANGID_CROATIAN_CROATIA 0x041a
+#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN 0x081a
+#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 0x0c1a
+#define TT_MS_LANGID_SLOVAK_SLOVAKIA 0x041b
+#define TT_MS_LANGID_ALBANIAN_ALBANIA 0x041c
+#define TT_MS_LANGID_SWEDISH_SWEDEN 0x041d
+#define TT_MS_LANGID_SWEDISH_FINLAND 0x081d
+#define TT_MS_LANGID_THAI_THAILAND 0x041e
+#define TT_MS_LANGID_TURKISH_TURKEY 0x041f
+#define TT_MS_LANGID_URDU_PAKISTAN 0x0420
+#define TT_MS_LANGID_INDONESIAN_INDONESIA 0x0421
+#define TT_MS_LANGID_UKRAINIAN_UKRAINE 0x0422
+#define TT_MS_LANGID_BELARUSIAN_BELARUS 0x0423
+#define TT_MS_LANGID_SLOVENE_SLOVENIA 0x0424
+#define TT_MS_LANGID_ESTONIAN_ESTONIA 0x0425
+#define TT_MS_LANGID_LATVIAN_LATVIA 0x0426
+#define TT_MS_LANGID_LITHUANIAN_LITHUANIA 0x0427
+#define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA 0x0827
+#define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0428
+#define TT_MS_LANGID_FARSI_IRAN 0x0429
+#define TT_MS_LANGID_VIETNAMESE_VIET_NAM 0x042a
+#define TT_MS_LANGID_ARMENIAN_ARMENIA 0x042b
+#define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN 0x042c
+#define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC 0x082c
+#define TT_MS_LANGID_BASQUE_SPAIN 0x042d
+#define TT_MS_LANGID_SORBIAN_GERMANY 0x042e
+#define TT_MS_LANGID_MACEDONIAN_MACEDONIA 0x042f
+#define TT_MS_LANGID_SUTU_SOUTH_AFRICA 0x0430
+#define TT_MS_LANGID_TSONGA_SOUTH_AFRICA 0x0431
+#define TT_MS_LANGID_TSWANA_SOUTH_AFRICA 0x0432
+#define TT_MS_LANGID_VENDA_SOUTH_AFRICA 0x0433
+#define TT_MS_LANGID_XHOSA_SOUTH_AFRICA 0x0434
+#define TT_MS_LANGID_ZULU_SOUTH_AFRICA 0x0435
+#define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA 0x0436
+#define TT_MS_LANGID_GEORGIAN_GEORGIA 0x0437
+#define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 0x0438
+#define TT_MS_LANGID_HINDI_INDIA 0x0439
+#define TT_MS_LANGID_MALTESE_MALTA 0x043a
+#define TT_MS_LANGID_SAAMI_LAPONIA 0x043b
+#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c
+#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c
+#define TT_MS_LANGID_MALAY_MALAYSIA 0x043e
+#define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 0x083e
+#define TT_MS_LANGID_KAZAK_KAZAKSTAN 0x043f
+#define TT_MS_LANGID_SWAHILI_KENYA 0x0441
+#define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 0x0443
+#define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC 0x0843
+#define TT_MS_LANGID_TATAR_TATARSTAN 0x0444
+#define TT_MS_LANGID_BENGALI_INDIA 0x0445
+#define TT_MS_LANGID_PUNJABI_INDIA 0x0446
+#define TT_MS_LANGID_GUJARATI_INDIA 0x0447
+#define TT_MS_LANGID_ORIYA_INDIA 0x0448
+#define TT_MS_LANGID_TAMIL_INDIA 0x0449
+#define TT_MS_LANGID_TELUGU_INDIA 0x044a
+#define TT_MS_LANGID_KANNADA_INDIA 0x044b
+#define TT_MS_LANGID_MALAYALAM_INDIA 0x044c
+#define TT_MS_LANGID_ASSAMESE_INDIA 0x044d
+#define TT_MS_LANGID_MARATHI_INDIA 0x044e
+#define TT_MS_LANGID_SANSKRIT_INDIA 0x044f
+#define TT_MS_LANGID_KONKANI_INDIA 0x0457
+
+
+ /*************************************************************************/
+ /* */
+ /* Possible values of the `name' identifier field in the name records of */
+ /* the TTF `name' table. These values are platform independent. */
+ /* */
+#define TT_NAME_ID_COPYRIGHT 0
+#define TT_NAME_ID_FONT_FAMILY 1
+#define TT_NAME_ID_FONT_SUBFAMILY 2
+#define TT_NAME_ID_UNIQUE_ID 3
+#define TT_NAME_ID_FULL_NAME 4
+#define TT_NAME_ID_VERSION_STRING 5
+#define TT_NAME_ID_PS_NAME 6
+#define TT_NAME_ID_TRADEMARK 7
+
+/* the following values are from the OpenType spec */
+#define TT_NAME_ID_MANUFACTURER 8
+#define TT_NAME_ID_DESIGNER 9
+#define TT_NAME_ID_DESCRIPTION 10
+#define TT_NAME_ID_VENDOR_URL 11
+#define TT_NAME_ID_DESIGNER_URL 12
+#define TT_NAME_ID_LICENSE 13
+#define TT_NAME_ID_LICENSE_URL 14
+/* number 15 is reserved */
+#define TT_NAME_ID_PREFERRED_FAMILY 16
+#define TT_NAME_ID_PREFERRED_SUBFAMILY 17
+#define TT_NAME_ID_MAC_FULL_NAME 18
+
+/* The following code is new as of 2000-01-21 */
+#define TT_NAME_ID_SAMPLE_TEXT 19
+
+
+ /*************************************************************************/
+ /* */
+ /* Bit mask values for the Unicode Ranges from the TTF `OS2 ' table. */
+ /* */
+ /* Updated 02-Jul-2000. */
+ /* */
+
+ /* General Scripts Area */
+
+ /* Bit 0 C0 Controls and Basic Latin */
+#define TT_UCR_BASIC_LATIN (1L << 0) /* U+0020-U+007E */
+ /* Bit 1 C1 Controls and Latin-1 Supplement */
+#define TT_UCR_LATIN1_SUPPLEMENT (1L << 1) /* U+00A0-U+00FF */
+ /* Bit 2 Latin Extended-A */
+#define TT_UCR_LATIN_EXTENDED_A (1L << 2) /* U+0100-U+017F */
+ /* Bit 3 Latin Extended-B */
+#define TT_UCR_LATIN_EXTENDED_B (1L << 3) /* U+0180-U+024F */
+ /* Bit 4 IPA Extensions */
+#define TT_UCR_IPA_EXTENSIONS (1L << 4) /* U+0250-U+02AF */
+ /* Bit 5 Spacing Modifier Letters */
+#define TT_UCR_SPACING_MODIFIER (1L << 5) /* U+02B0-U+02FF */
+ /* Bit 6 Combining Diacritical Marks */
+#define TT_UCR_COMBINING_DIACRITICS (1L << 6) /* U+0300-U+036F */
+ /* Bit 7 Greek */
+#define TT_UCR_GREEK (1L << 7) /* U+0370-U+03FF */
+ /* Bit 8 is reserved (was: Greek Symbols and Coptic) */
+ /* Bit 9 Cyrillic */
+#define TT_UCR_CYRILLIC (1L << 9) /* U+0400-U+04FF */
+ /* Bit 10 Armenian */
+#define TT_UCR_ARMENIAN (1L << 10) /* U+0530-U+058F */
+ /* Bit 11 Hebrew */
+#define TT_UCR_HEBREW (1L << 11) /* U+0590-U+05FF */
+ /* Bit 12 is reserved (was: Hebrew Extended) */
+ /* Bit 13 Arabic */
+#define TT_UCR_ARABIC (1L << 13) /* U+0600-U+06FF */
+ /* Bit 14 is reserved (was: Arabic Extended) */
+ /* Bit 15 Devanagari */
+#define TT_UCR_DEVANAGARI (1L << 15) /* U+0900-U+097F */
+ /* Bit 16 Bengali */
+#define TT_UCR_BENGALI (1L << 16) /* U+0980-U+09FF */
+ /* Bit 17 Gurmukhi */
+#define TT_UCR_GURMUKHI (1L << 17) /* U+0A00-U+0A7F */
+ /* Bit 18 Gujarati */
+#define TT_UCR_GUJARATI (1L << 18) /* U+0A80-U+0AFF */
+ /* Bit 19 Oriya */
+#define TT_UCR_ORIYA (1L << 19) /* U+0B00-U+0B7F */
+ /* Bit 20 Tamil */
+#define TT_UCR_TAMIL (1L << 20) /* U+0B80-U+0BFF */
+ /* Bit 21 Telugu */
+#define TT_UCR_TELUGU (1L << 21) /* U+0C00-U+0C7F */
+ /* Bit 22 Kannada */
+#define TT_UCR_KANNADA (1L << 22) /* U+0C80-U+0CFF */
+ /* Bit 23 Malayalam */
+#define TT_UCR_MALAYALAM (1L << 23) /* U+0D00-U+0D7F */
+ /* Bit 24 Thai */
+#define TT_UCR_THAI (1L << 24) /* U+0E00-U+0E7F */
+ /* Bit 25 Lao */
+#define TT_UCR_LAO (1L << 25) /* U+0E80-U+0EFF */
+ /* Bit 26 Georgian */
+#define TT_UCR_GEORGIAN (1L << 26) /* U+10A0-U+10FF */
+ /* Bit 27 is reserved (was Georgian Extended) */
+ /* Bit 28 Hangul Jamo */
+#define TT_UCR_HANGUL_JAMO (1L << 28) /* U+1100-U+11FF */
+ /* Bit 29 Latin Extended Additional */
+#define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1L << 29) /* U+1E00-U+1EFF */
+ /* Bit 30 Greek Extended */
+#define TT_UCR_GREEK_EXTENDED (1L << 30) /* U+1F00-U+1FFF */
+
+ /* Symbols Area */
+
+ /* Bit 31 General Punctuation */
+#define TT_UCR_GENERAL_PUNCTUATION (1L << 31) /* U+2000-U+206F */
+ /* Bit 32 Superscripts And Subscripts */
+#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1L << 0) /* U+2070-U+209F */
+ /* Bit 33 Currency Symbols */
+#define TT_UCR_CURRENCY_SYMBOLS (1L << 1) /* U+20A0-U+20CF */
+ /* Bit 34 Combining Diacritical Marks For Symbols */
+#define TT_UCR_COMBINING_DIACRITICS_SYMB (1L << 2) /* U+20D0-U+20FF */
+ /* Bit 35 Letterlike Symbols */
+#define TT_UCR_LETTERLIKE_SYMBOLS (1L << 3) /* U+2100-U+214F */
+ /* Bit 36 Number Forms */
+#define TT_UCR_NUMBER_FORMS (1L << 4) /* U+2150-U+218F */
+ /* Bit 37 Arrows */
+#define TT_UCR_ARROWS (1L << 5) /* U+2190-U+21FF */
+ /* Bit 38 Mathematical Operators */
+#define TT_UCR_MATHEMATICAL_OPERATORS (1L << 6) /* U+2200-U+22FF */
+ /* Bit 39 Miscellaneous Technical */
+#define TT_UCR_MISCELLANEOUS_TECHNICAL (1L << 7) /* U+2300-U+23FF */
+ /* Bit 40 Control Pictures */
+#define TT_UCR_CONTROL_PICTURES (1L << 8) /* U+2400-U+243F */
+ /* Bit 41 Optical Character Recognition */
+#define TT_UCR_OCR (1L << 9) /* U+2440-U+245F */
+ /* Bit 42 Enclosed Alphanumerics */
+#define TT_UCR_ENCLOSED_ALPHANUMERICS (1L << 10) /* U+2460-U+24FF */
+ /* Bit 43 Box Drawing */
+#define TT_UCR_BOX_DRAWING (1L << 11) /* U+2500-U+257F */
+ /* Bit 44 Block Elements */
+#define TT_UCR_BLOCK_ELEMENTS (1L << 12) /* U+2580-U+259F */
+ /* Bit 45 Geometric Shapes */
+#define TT_UCR_GEOMETRIC_SHAPES (1L << 13) /* U+25A0-U+25FF */
+ /* Bit 46 Miscellaneous Symbols */
+#define TT_UCR_MISCELLANEOUS_SYMBOLS (1L << 14) /* U+2600-U+26FF */
+ /* Bit 47 Dingbats */
+#define TT_UCR_DINGBATS (1L << 15) /* U+2700-U+27BF */
+
+ /* CJK Phonetics and Symbols Area */
+
+ /* Bit 48 CJK Symbols And Punctuation */
+#define TT_UCR_CJK_SYMBOLS (1L << 16) /* U+3000-U+303F */
+ /* Bit 49 Hiragana */
+#define TT_UCR_HIRAGANA (1L << 17) /* U+3040-U+309F */
+ /* Bit 50 Katakana */
+#define TT_UCR_KATAKANA (1L << 18) /* U+30A0-U+30FF */
+ /* Bit 51 Bopomofo + Extended Bopomofo */
+#define TT_UCR_BOPOMOFO (1L << 19) /* U+3100-U+312F */
+ /* U+31A0-U+31BF */
+ /* Bit 52 Hangul Compatibility Jamo */
+#define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1L << 20) /* U+3130-U+318F */
+ /* Bit 53 CJK Miscellaneous */
+#define TT_UCR_CJK_MISC (1L << 21) /* U+3190-U+319F */
+ /* Bit 54 Enclosed CJK Letters And Months */
+#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1L << 22) /* U+3200-U+32FF */
+ /* Bit 55 CJK Compatibility */
+#define TT_UCR_CJK_COMPATIBILITY (1L << 23) /* U+3300-U+33FF */
+
+ /* Hangul Syllables Area */
+
+ /* Bit 56 Hangul */
+#define TT_UCR_HANGUL (1L << 24) /* U+AC00-U+D7A3 */
+
+ /* Surrogates Area */
+
+ /* Bit 57 Surrogates */
+#define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DFFF */
+ /* Bit 58 is reserved for Unicode SubRanges */
+
+ /* CJK Ideographs Area */
+
+ /* Bit 59 CJK Unified Ideographs + */
+ /* CJK Radical Supplement + */
+ /* Kangxi Radicals + */
+ /* Ideographic Description + */
+ /* CJK Unified Ideographs Extension A */
+#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1L << 27) /* U+4E00-U+9FFF */
+ /* U+2E80-U+2EFF */
+ /* U+2F00-U+2FDF */
+ /* U+2FF0-U+2FFF */
+ /* U+34E0-U+4DB5 */
+
+ /* Private Use Area */
+
+ /* Bit 60 Private Use */
+#define TT_UCR_PRIVATE_USE (1L << 28) /* U+E000-U+F8FF */
+
+ /* Compatibility Area and Specials */
+
+ /* Bit 61 CJK Compatibility Ideographs */
+#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1L << 29) /* U+F900-U+FAFF */
+ /* Bit 62 Alphabetic Presentation Forms */
+#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1L << 30) /* U+FB00-U+FB4F */
+ /* Bit 63 Arabic Presentation Forms-A */
+#define TT_UCR_ARABIC_PRESENTATIONS_A (1L << 31) /* U+FB50-U+FDFF */
+ /* Bit 64 Combining Half Marks */
+#define TT_UCR_COMBINING_HALF_MARKS (1L << 0) /* U+FE20-U+FE2F */
+ /* Bit 65 CJK Compatibility Forms */
+#define TT_UCR_CJK_COMPATIBILITY_FORMS (1L << 1) /* U+FE30-U+FE4F */
+ /* Bit 66 Small Form Variants */
+#define TT_UCR_SMALL_FORM_VARIANTS (1L << 2) /* U+FE50-U+FE6F */
+ /* Bit 67 Arabic Presentation Forms-B */
+#define TT_UCR_ARABIC_PRESENTATIONS_B (1L << 3) /* U+FE70-U+FEFE */
+ /* Bit 68 Halfwidth And Fullwidth Forms */
+#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1L << 4) /* U+FF00-U+FFEF */
+ /* Bit 69 Specials */
+#define TT_UCR_SPECIALS (1L << 5) /* U+FFF0-U+FFFD */
+ /* Bit 70 Tibetan */
+#define TT_UCR_TIBETAN (1L << 6) /* U+0F00-U+0FCF */
+ /* Bit 71 Syriac */
+#define TT_UCR_SYRIAC (1L << 7) /* U+0700-U+074F */
+ /* Bit 72 Thaana */
+#define TT_UCR_THAANA (1L << 8) /* U+0780-U+07BF */
+ /* Bit 73 Sinhala */
+#define TT_UCR_SINHALA (1L << 9) /* U+0D80-U+0DFF */
+ /* Bit 74 Myanmar */
+#define TT_UCR_MYANMAR (1L << 10) /* U+1000-U+109F */
+ /* Bit 75 Ethiopic */
+#define TT_UCR_ETHIOPIC (1L << 11) /* U+1200-U+12BF */
+ /* Bit 76 Cherokee */
+#define TT_UCR_CHEROKEE (1L << 12) /* U+13A0-U+13FF */
+ /* Bit 77 Canadian Aboriginal Syllabics */
+#define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS (1L << 13) /* U+1400-U+14DF */
+ /* Bit 78 Ogham */
+#define TT_UCR_OGHAM (1L << 14) /* U+1680-U+169F */
+ /* Bit 79 Runic */
+#define TT_UCR_RUNIC (1L << 15) /* U+16A0-U+16FF */
+ /* Bit 80 Khmer */
+#define TT_UCR_KHMER (1L << 16) /* U+1780-U+17FF */
+ /* Bit 81 Mongolian */
+#define TT_UCR_MONGOLIAN (1L << 17) /* U+1800-U+18AF */
+ /* Bit 82 Braille */
+#define TT_UCR_BRAILLE (1L << 18) /* U+2800-U+28FF */
+ /* Bit 83 Yi + Yi Radicals */
+#define TT_UCR_YI (1L << 19) /* U+A000-U+A48C */
+ /* U+A490-U+A4CF */
+
+
+ /*************************************************************************/
+ /* */
+ /* Some compilers have a very limited length of identifiers. */
+ /* */
+#if defined( __TURBOC__ ) && __TURBOC__ < 0x0410 || defined( __PACIFIC__ )
+#define HAVE_LIMIT_ON_IDENTS
+#endif
+
+
+#ifndef HAVE_LIMIT_ON_IDENTS
+
+
+ /*************************************************************************/
+ /* */
+ /* Here some alias #defines in order to be clearer. */
+ /* */
+ /* These are not always #defined to stay within the 31 character limit */
+ /* which some compilers have. */
+ /* */
+ /* Credits go to Dave Hoo <dhoo@flash.net> for pointing out that modern */
+ /* Borland compilers (read: from BC++ 3.1 on) can increase this limit. */
+ /* If you get a warning with such a compiler, use the -i40 switch. */
+ /* */
+#define TT_UCR_ARABIC_PRESENTATION_FORMS_A \
+ TT_UCR_ARABIC_PRESENTATIONS_A
+#define TT_UCR_ARABIC_PRESENTATION_FORMS_B \
+ TT_UCR_ARABIC_PRESENTATIONS_B
+
+#define TT_UCR_COMBINING_DIACRITICAL_MARKS \
+ TT_UCR_COMBINING_DIACRITICS
+#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \
+ TT_UCR_COMBINING_DIACRITICS_SYMB
+
+
+#endif /* !HAVE_LIMIT_ON_IDENTS */
+
+
+#endif /* TTNAMEID_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* tttables.h */
+/* */
+/* Basic SFNT/TrueType tables definitions and interface */
+/* (specification only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef TTTABLES_H
+#define TTTABLES_H
+
+
+#include <freetype/freetype.h>
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_Header */
+ /* */
+ /* <Description> */
+ /* A structure used to model a TrueType font header table. All */
+ /* fields follow the TrueType specification. */
+ /* */
+ typedef struct TT_Header_
+ {
+ FT_Fixed Table_Version;
+ FT_Fixed Font_Revision;
+
+ FT_Long CheckSum_Adjust;
+ FT_Long Magic_Number;
+
+ FT_UShort Flags;
+ FT_UShort Units_Per_EM;
+
+ FT_Long Created [2];
+ FT_Long Modified[2];
+
+ FT_Short xMin;
+ FT_Short yMin;
+ FT_Short xMax;
+ FT_Short yMax;
+
+ FT_UShort Mac_Style;
+ FT_UShort Lowest_Rec_PPEM;
+
+ FT_Short Font_Direction;
+ FT_Short Index_To_Loc_Format;
+ FT_Short Glyph_Data_Format;
+
+ } TT_Header;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_HoriHeader */
+ /* */
+ /* <Description> */
+ /* A structure used to model a TrueType horizontal header, the `hhea' */
+ /* table, as well as the corresponding horizontal metrics table, */
+ /* i.e., the `hmtx' table. */
+ /* */
+ /* <Fields> */
+ /* Version :: The table version. */
+ /* */
+ /* Ascender :: The font's ascender, i.e., the distance */
+ /* from the baseline to the top-most of all */
+ /* glyph points found in the font. */
+ /* */
+ /* This value is invalid in many fonts, as */
+ /* it is usually set by the font designer, */
+ /* and often reflects only a portion of the */
+ /* glyphs found in the font (maybe ASCII). */
+ /* */
+ /* You should use the `sTypoAscender' field */
+ /* of the OS/2 table instead if you want */
+ /* the correct one. */
+ /* */
+ /* Descender :: The font's descender, i.e., the distance */
+ /* from the baseline to the bottom-most of */
+ /* all glyph points found in the font. It */
+ /* is negative. */
+ /* */
+ /* This value is invalid in many fonts, as */
+ /* it is usually set by the font designer, */
+ /* and often reflects only a portion of the */
+ /* glyphs found in the font (maybe ASCII). */
+ /* */
+ /* You should use the `sTypoDescender' */
+ /* field of the OS/2 table instead if you */
+ /* want the correct one. */
+ /* */
+ /* Line_Gap :: The font's line gap, i.e., the distance */
+ /* to add to the ascender and descender to */
+ /* get the BTB, i.e., the */
+ /* baseline-to-baseline distance for the */
+ /* font. */
+ /* */
+ /* advance_Width_Max :: This field is the maximum of all advance */
+ /* widths found in the font. It can be */
+ /* used to compute the maximum width of an */
+ /* arbitrary string of text. */
+ /* */
+ /* min_Left_Side_Bearing :: The minimum left side bearing of all */
+ /* glyphs within the font. */
+ /* */
+ /* min_Right_Side_Bearing :: The minimum right side bearing of all */
+ /* glyphs within the font. */
+ /* */
+ /* xMax_Extent :: The maximum horizontal extent (i.e., the */
+ /* `width' of a glyph's bounding box) for */
+ /* all glyphs in the font. */
+ /* */
+ /* caret_Slope_Rise :: The rise coefficient of the cursor's */
+ /* slope of the cursor (slope=rise/run). */
+ /* */
+ /* caret_Slope_Run :: The run coefficient of the cursor's */
+ /* slope. */
+ /* */
+ /* Reserved :: 10 reserved bytes. */
+ /* */
+ /* metric_Data_Format :: Always 0. */
+ /* */
+ /* number_Of_HMetrics :: Number of HMetrics entries in the `hmtx' */
+ /* table -- this value can be smaller than */
+ /* the total number of glyphs in the font. */
+ /* */
+ /* long_metrics :: A pointer into the `hmtx' table. */
+ /* */
+ /* short_metrics :: A pointer into the `hmtx' table. */
+ /* */
+ /* <Note> */
+ /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */
+ /* be identical except for the names of their fields which */
+ /* are different. */
+ /* */
+ /* This ensures that a single function in the `ttload' */
+ /* module is able to read both the horizontal and vertical */
+ /* headers. */
+ /* */
+ typedef struct TT_HoriHeader_
+ {
+ FT_Fixed Version;
+ FT_Short Ascender;
+ FT_Short Descender;
+ FT_Short Line_Gap;
+
+ FT_UShort advance_Width_Max; /* advance width maximum */
+
+ FT_Short min_Left_Side_Bearing; /* minimum left-sb */
+ FT_Short min_Right_Side_Bearing; /* minimum right-sb */
+ FT_Short xMax_Extent; /* xmax extents */
+ FT_Short caret_Slope_Rise;
+ FT_Short caret_Slope_Run;
+ FT_Short caret_Offset;
+
+ FT_Short Reserved[4];
+
+ FT_Short metric_Data_Format;
+ FT_UShort number_Of_HMetrics;
+
+ /* The following fields are not defined by the TrueType specification */
+ /* but they're used to connect the metrics header to the relevant */
+ /* `HMTX' table. */
+
+ void* long_metrics;
+ void* short_metrics;
+
+ } TT_HoriHeader;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_VertHeader */
+ /* */
+ /* <Description> */
+ /* A structure used to model a TrueType vertical header, the `vhea' */
+ /* table, as well as the corresponding vertical metrics table, i.e., */
+ /* the `vmtx' table. */
+ /* */
+ /* <Fields> */
+ /* Version :: The table version. */
+ /* */
+ /* Ascender :: The font's ascender, i.e., the distance */
+ /* from the baseline to the top-most of */
+ /* all glyph points found in the font. */
+ /* */
+ /* This value is invalid in many fonts, as */
+ /* it is usually set by the font designer, */
+ /* and often reflects only a portion of */
+ /* the glyphs found in the font (maybe */
+ /* ASCII). */
+ /* */
+ /* You should use the `sTypoAscender' */
+ /* field of the OS/2 table instead if you */
+ /* want the correct one. */
+ /* */
+ /* Descender :: The font's descender, i.e., the */
+ /* distance from the baseline to the */
+ /* bottom-most of all glyph points found */
+ /* in the font. It is negative. */
+ /* */
+ /* This value is invalid in many fonts, as */
+ /* it is usually set by the font designer, */
+ /* and often reflects only a portion of */
+ /* the glyphs found in the font (maybe */
+ /* ASCII). */
+ /* */
+ /* You should use the `sTypoDescender' */
+ /* field of the OS/2 table instead if you */
+ /* want the correct one. */
+ /* */
+ /* Line_Gap :: The font's line gap, i.e., the distance */
+ /* to add to the ascender and descender to */
+ /* get the BTB, i.e., the */
+ /* baseline-to-baseline distance for the */
+ /* font. */
+ /* */
+ /* advance_Height_Max :: This field is the maximum of all */
+ /* advance heights found in the font. It */
+ /* can be used to compute the maximum */
+ /* height of an arbitrary string of text. */
+ /* */
+ /* min_Top_Side_Bearing :: The minimum top side bearing of all */
+ /* glyphs within the font. */
+ /* */
+ /* min_Bottom_Side_Bearing :: The minimum bottom side bearing of all */
+ /* glyphs within the font. */
+ /* */
+ /* yMax_Extent :: The maximum vertical extent (i.e., the */
+ /* `height' of a glyph's bounding box) for */
+ /* all glyphs in the font. */
+ /* */
+ /* caret_Slope_Rise :: The rise coefficient of the cursor's */
+ /* slope of the cursor (slope=rise/run). */
+ /* */
+ /* caret_Slope_Run :: The run coefficient of the cursor's */
+ /* slope. */
+ /* */
+ /* Reserved :: 10 reserved bytes. */
+ /* */
+ /* metric_Data_Format :: Always 0. */
+ /* */
+ /* number_Of_HMetrics :: Number of VMetrics entries in the */
+ /* `vmtx' table -- this value can be */
+ /* smaller than the total number of glyphs */
+ /* in the font. */
+ /* */
+ /* long_metrics :: A pointer into the `vmtx' table. */
+ /* */
+ /* short_metrics :: A pointer into the `vmtx' table. */
+ /* */
+ /* <Note> */
+ /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */
+ /* be identical except for the names of their fields which */
+ /* are different. */
+ /* */
+ /* This ensures that a single function in the `ttload' */
+ /* module is able to read both the horizontal and vertical */
+ /* headers. */
+ /* */
+ typedef struct TT_VertHeader_
+ {
+ FT_Fixed Version;
+ FT_Short Ascender;
+ FT_Short Descender;
+ FT_Short Line_Gap;
+
+ FT_UShort advance_Height_Max; /* advance height maximum */
+
+ FT_Short min_Top_Side_Bearing; /* minimum left-sb or top-sb */
+ FT_Short min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb */
+ FT_Short yMax_Extent; /* xmax or ymax extents */
+ FT_Short caret_Slope_Rise;
+ FT_Short caret_Slope_Run;
+ FT_Short caret_Offset;
+
+ FT_Short Reserved[4];
+
+ FT_Short metric_Data_Format;
+ FT_UShort number_Of_VMetrics;
+
+ /* The following fields are not defined by the TrueType specification */
+ /* but they're used to connect the metrics header to the relevant */
+ /* `HMTX' or `VMTX' table. */
+
+ void* long_metrics;
+ void* short_metrics;
+
+ } TT_VertHeader;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_OS2 */
+ /* */
+ /* <Description> */
+ /* A structure used to model a TrueType OS/2 table. This is the long */
+ /* table version. All fields comply to the TrueType specification. */
+ /* */
+ /* Note that we now support old Mac fonts which do not include an */
+ /* OS/2 table. In this case, the `version' field is always set to */
+ /* 0xFFFF. */
+ /* */
+ typedef struct TT_OS2_
+ {
+ FT_UShort version; /* 0x0001 - more or 0xFFFF */
+ FT_Short xAvgCharWidth;
+ FT_UShort usWeightClass;
+ FT_UShort usWidthClass;
+ FT_Short fsType;
+ FT_Short ySubscriptXSize;
+ FT_Short ySubscriptYSize;
+ FT_Short ySubscriptXOffset;
+ FT_Short ySubscriptYOffset;
+ FT_Short ySuperscriptXSize;
+ FT_Short ySuperscriptYSize;
+ FT_Short ySuperscriptXOffset;
+ FT_Short ySuperscriptYOffset;
+ FT_Short yStrikeoutSize;
+ FT_Short yStrikeoutPosition;
+ FT_Short sFamilyClass;
+
+ FT_Byte panose[10];
+
+ FT_ULong ulUnicodeRange1; /* Bits 0-31 */
+ FT_ULong ulUnicodeRange2; /* Bits 32-63 */
+ FT_ULong ulUnicodeRange3; /* Bits 64-95 */
+ FT_ULong ulUnicodeRange4; /* Bits 96-127 */
+
+ FT_Char achVendID[4];
+
+ FT_UShort fsSelection;
+ FT_UShort usFirstCharIndex;
+ FT_UShort usLastCharIndex;
+ FT_Short sTypoAscender;
+ FT_Short sTypoDescender;
+ FT_Short sTypoLineGap;
+ FT_UShort usWinAscent;
+ FT_UShort usWinDescent;
+
+ /* only version 1 tables: */
+
+ FT_ULong ulCodePageRange1; /* Bits 0-31 */
+ FT_ULong ulCodePageRange2; /* Bits 32-63 */
+
+ /* only version 2 tables: */
+
+ FT_Short sxHeight;
+ FT_Short sCapHeight;
+ FT_UShort usDefaultChar;
+ FT_UShort usBreakChar;
+ FT_UShort usMaxContext;
+
+ } TT_OS2;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_Postscript */
+ /* */
+ /* <Description> */
+ /* A structure used to model a TrueType Postscript table. All fields */
+ /* comply to the TrueType table. This structure does not reference */
+ /* the Postscript glyph names, which can be nevertheless accessed */
+ /* with the `ttpost' module. */
+ /* */
+ typedef struct TT_Postscript_
+ {
+ FT_Fixed FormatType;
+ FT_Fixed italicAngle;
+ FT_Short underlinePosition;
+ FT_Short underlineThickness;
+ FT_ULong isFixedPitch;
+ FT_ULong minMemType42;
+ FT_ULong maxMemType42;
+ FT_ULong minMemType1;
+ FT_ULong maxMemType1;
+
+ /* Glyph names follow in the file, but we don't */
+ /* load them by default. See the ttpost.c file. */
+
+ } TT_Postscript;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_PCLT */
+ /* */
+ /* <Description> */
+ /* A structure used to model a TrueType PCLT table. All fields */
+ /* comply to the TrueType table. */
+ /* */
+ typedef struct TT_PCLT_
+ {
+ FT_Fixed Version;
+ FT_ULong FontNumber;
+ FT_UShort Pitch;
+ FT_UShort xHeight;
+ FT_UShort Style;
+ FT_UShort TypeFamily;
+ FT_UShort CapHeight;
+ FT_UShort SymbolSet;
+ FT_Char TypeFace[16];
+ FT_Char CharacterComplement[8];
+ FT_Char FileName[6];
+ FT_Char StrokeWeight;
+ FT_Char WidthType;
+ FT_Byte SerifStyle;
+ FT_Byte Reserved;
+
+ } TT_PCLT;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_MaxProfile */
+ /* */
+ /* <Description> */
+ /* The maximum profile is a table containing many max values which */
+ /* can be used to pre-allocate arrays. This ensures that no memory */
+ /* allocation occurs during a glyph load. */
+ /* */
+ /* <Fields> */
+ /* version :: The version number. */
+ /* */
+ /* numGlyphs :: The number of glyphs in this TrueType */
+ /* font. */
+ /* */
+ /* maxPoints :: The maximum number of points in a */
+ /* non-composite TrueType glyph. See also */
+ /* the structure element */
+ /* `maxCompositePoints'. */
+ /* */
+ /* maxContours :: The maximum number of contours in a */
+ /* non-composite TrueType glyph. See also */
+ /* the structure element */
+ /* `maxCompositeContours'. */
+ /* */
+ /* maxCompositePoints :: The maximum number of points in a */
+ /* composite TrueType glyph. See also the */
+ /* structure element `maxPoints'. */
+ /* */
+ /* maxCompositeContours :: The maximum number of contours in a */
+ /* composite TrueType glyph. See also the */
+ /* structure element `maxContours'. */
+ /* */
+ /* maxZones :: The maximum number of zones used for */
+ /* glyph hinting. */
+ /* */
+ /* maxTwilightPoints :: The maximum number of points in the */
+ /* twilight zone used for glyph hinting. */
+ /* */
+ /* maxStorage :: The maximum number of elements in the */
+ /* storage area used for glyph hinting. */
+ /* */
+ /* maxFunctionDefs :: The maximum number of function */
+ /* definitions in the TrueType bytecode for */
+ /* this font. */
+ /* */
+ /* maxInstructionDefs :: The maximum number of instruction */
+ /* definitions in the TrueType bytecode for */
+ /* this font. */
+ /* */
+ /* maxStackElements :: The maximum number of stack elements used */
+ /* during bytecode interpretation. */
+ /* */
+ /* maxSizeOfInstructions :: The maximum number of TrueType opcodes */
+ /* used for glyph hinting. */
+ /* */
+ /* maxComponentElements :: An obscure value related to composite */
+ /* glyphs definitions. */
+ /* */
+ /* maxComponentDepth :: An obscure value related to composite */
+ /* glyphs definitions. Probably the maximum */
+ /* number of simple glyphs in a composite. */
+ /* */
+ /* <Note> */
+ /* This structure is only used during font loading. */
+ /* */
+ typedef struct TT_MaxProfile_
+ {
+ FT_Fixed version;
+ FT_UShort numGlyphs;
+ FT_UShort maxPoints;
+ FT_UShort maxContours;
+ FT_UShort maxCompositePoints;
+ FT_UShort maxCompositeContours;
+ FT_UShort maxZones;
+ FT_UShort maxTwilightPoints;
+ FT_UShort maxStorage;
+ FT_UShort maxFunctionDefs;
+ FT_UShort maxInstructionDefs;
+ FT_UShort maxStackElements;
+ FT_UShort maxSizeOfInstructions;
+ FT_UShort maxComponentElements;
+ FT_UShort maxComponentDepth;
+
+ } TT_MaxProfile;
+
+
+ typedef enum
+ {
+ ft_sfnt_head = 0,
+ ft_sfnt_maxp = 1,
+ ft_sfnt_os2 = 2,
+ ft_sfnt_hhea = 3,
+ ft_sfnt_vhea = 4,
+ ft_sfnt_post = 5,
+ ft_sfnt_pclt = 6,
+
+ sfnt_max /* don't remove */
+
+ } FT_Sfnt_Tag;
+
+
+ /* internal use only */
+ typedef void* (*FT_Get_Sfnt_Table_Func)( FT_Face face,
+ FT_Sfnt_Tag tag );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Sfnt_Table */
+ /* */
+ /* <Description> */
+ /* Returns a pointer to a given SFNT table within a face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source. */
+ /* */
+ /* tag :: The index of the SFNT table. */
+ /* */
+ /* <Return> */
+ /* A type-less pointer to the table. This will be 0 in case of */
+ /* error, or if the corresponding table was not found *OR* loaded */
+ /* from the file. */
+ /* */
+ /* <Note> */
+ /* The table is owned by the face object and disappears with it. */
+ /* */
+ /* This function is only useful to access SFNT tables that are loaded */
+ /* by the sfnt/truetype/opentype drivers. See FT_Sfnt_tag for a */
+ /* list. */
+ /* */
+ /* You can load any table using the (internal) SFNT_Interface */
+ /* structure -- this is available via FT_Get_Module_Interface(). */
+ /* */
+ FT_EXPORT_DEF( void* ) FT_Get_Sfnt_Table( FT_Face face,
+ FT_Sfnt_Tag tag );
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* TTTABLES_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* tttags.h */
+/* */
+/* Tags for TrueType tables (specification only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef TTAGS_H
+#define TTAGS_H
+
+
+#include <freetype/freetype.h> /* for MAKE_TT_TAG() */
+
+
+#define TTAG_cmap FT_MAKE_TAG( 'c', 'm', 'a', 'p' )
+#define TTAG_cvt FT_MAKE_TAG( 'c', 'v', 't', ' ' )
+#define TTAG_CFF FT_MAKE_TAG( 'C', 'F', 'F', ' ' )
+#define TTAG_DSIG FT_MAKE_TAG( 'D', 'S', 'I', 'G' )
+#define TTAG_bdat FT_MAKE_TAG( 'b', 'd', 'a', 't' )
+#define TTAG_bloc FT_MAKE_TAG( 'b', 'l', 'o', 'c' )
+#define TTAG_EBDT FT_MAKE_TAG( 'E', 'B', 'D', 'T' )
+#define TTAG_EBLC FT_MAKE_TAG( 'E', 'B', 'L', 'C' )
+#define TTAG_EBSC FT_MAKE_TAG( 'E', 'B', 'S', 'C' )
+#define TTAG_fpgm FT_MAKE_TAG( 'f', 'p', 'g', 'm' )
+#define TTAG_fvar FT_MAKE_TAG( 'f', 'v', 'a', 'r' )
+#define TTAG_gasp FT_MAKE_TAG( 'g', 'a', 's', 'p' )
+#define TTAG_glyf FT_MAKE_TAG( 'g', 'l', 'y', 'f' )
+#define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' )
+#define TTAG_hdmx FT_MAKE_TAG( 'h', 'd', 'm', 'x' )
+#define TTAG_head FT_MAKE_TAG( 'h', 'e', 'a', 'd' )
+#define TTAG_hhea FT_MAKE_TAG( 'h', 'h', 'e', 'a' )
+#define TTAG_hmtx FT_MAKE_TAG( 'h', 'm', 't', 'x' )
+#define TTAG_kern FT_MAKE_TAG( 'k', 'e', 'r', 'n' )
+#define TTAG_loca FT_MAKE_TAG( 'l', 'o', 'c', 'a' )
+#define TTAG_LTSH FT_MAKE_TAG( 'L', 'T', 'S', 'H' )
+#define TTAG_maxp FT_MAKE_TAG( 'm', 'a', 'x', 'p' )
+#define TTAG_MMSD FT_MAKE_TAG( 'M', 'M', 'S', 'D' )
+#define TTAG_MMFX FT_MAKE_TAG( 'M', 'M', 'F', 'X' )
+#define TTAG_name FT_MAKE_TAG( 'n', 'a', 'm', 'e' )
+#define TTAG_OS2 FT_MAKE_TAG( 'O', 'S', '/', '2' )
+#define TTAG_OTTO FT_MAKE_TAG( 'O', 'T', 'T', 'O' )
+#define TTAG_PCLT FT_MAKE_TAG( 'P', 'C', 'L', 'T' )
+#define TTAG_post FT_MAKE_TAG( 'p', 'o', 's', 't' )
+#define TTAG_prep FT_MAKE_TAG( 'p', 'r', 'e', 'p' )
+#define TTAG_true FT_MAKE_TAG( 't', 'r', 'u', 'e' )
+#define TTAG_ttc FT_MAKE_TAG( 't', 't', 'c', ' ' )
+#define TTAG_ttcf FT_MAKE_TAG( 't', 't', 'c', 'f' )
+#define TTAG_VDMX FT_MAKE_TAG( 'V', 'D', 'M', 'X' )
+#define TTAG_vhea FT_MAKE_TAG( 'v', 'h', 'e', 'a' )
+#define TTAG_vmtx FT_MAKE_TAG( 'v', 'm', 't', 'x' )
+
+#endif /* TTAGS_H */
+
+
+/* END */
--- /dev/null
+/* ftconfig.h. Generated automatically by configure. */
+/***************************************************************************/
+/* */
+/* ftconfig.in */
+/* */
+/* UNIX-specific configuration file (specification only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This header file contains a number of macro definitions that are used */
+ /* by the rest of the engine. Most of the macros here are automatically */
+ /* determined at compile time, and you should not need to change it to */
+ /* port FreeType, except to compile the library with a non-ANSI */
+ /* compiler. */
+ /* */
+ /* Note however that if some specific modifications are needed, we */
+ /* advise you to place a modified copy in your build directory. */
+ /* */
+ /* The build directory is usually `freetype/builds/<system>', and */
+ /* contains system-specific files that are always included first when */
+ /* building the library. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef FTCONFIG_H
+#define FTCONFIG_H
+
+
+ /* Include the header file containing all developer build options */
+#include <freetype/config/ftoption.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* PLATFORM-SPECIFIC CONFIGURATION MACROS */
+ /* */
+ /* These macros can be toggled to suit a specific system. The current */
+ /* ones are defaults used to compile FreeType in an ANSI C environment */
+ /* (16bit compilers are also supported). Copy this file to your own */
+ /* `freetype/builds/<system>' directory, and edit it to port the engine. */
+ /* */
+ /*************************************************************************/
+
+
+#include "wx/setup.h"
+
+#define FT_SIZEOF_INT SIZEOF_INT
+#define FT_SIZEOF_LONG SIZEOF_LONG
+
+
+ /* Preferred alignment of data */
+#define FT_ALIGNMENT 8
+
+
+ /* UNUSED is a macro used to indicate that a given parameter is not used */
+ /* -- this is only used to get rid of unpleasant compiler warnings */
+#ifndef FT_UNUSED
+#define FT_UNUSED( arg ) ( (arg) = (arg) )
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* AUTOMATIC CONFIGURATION MACROS */
+ /* */
+ /* These macros are computed from the ones defined above. Don't touch */
+ /* their definition, unless you know precisely what you are doing. No */
+ /* porter should need to mess with them. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* IntN types */
+ /* */
+ /* Used to guarantee the size of some specific integers. */
+ /* */
+ typedef signed short FT_Int16;
+ typedef unsigned short FT_UInt16;
+
+#if FT_SIZEOF_INT == 4
+
+ typedef signed int FT_Int32;
+ typedef unsigned int FT_UInt32;
+
+#elif FT_SIZEOF_LONG == 4
+
+ typedef signed long FT_Int32;
+ typedef unsigned long FT_UInt32;
+
+#else
+#error "no 32bit type found -- please check your configuration files"
+#endif
+
+#if FT_SIZEOF_LONG == 8
+
+ /* FT_LONG64 must be defined if a 64-bit type is available */
+#define FT_LONG64
+#define FT_INT64 long
+
+#else
+
+
+ /*************************************************************************/
+ /* */
+ /* Many compilers provide the non-ANSI `long long' 64-bit type. You can */
+ /* activate it by defining the FTCALC_USE_LONG_LONG macro in */
+ /* `ftoption.h'. */
+ /* */
+ /* Note that this will produce many -ansi warnings during library */
+ /* compilation, and that in many cases, the generated code will be */
+ /* neither smaller nor faster! */
+ /* */
+#ifdef FTCALC_USE_LONG_LONG
+
+#define FT_LONG64
+#define FT_INT64 long long
+
+#endif /* FTCALC_USE_LONG_LONG */
+#endif /* FT_SIZEOF_LONG == 8 */
+
+
+#ifdef FT_MAKE_OPTION_SINGLE_OBJECT
+#define LOCAL_DEF static
+#define LOCAL_FUNC static
+#else
+#define LOCAL_DEF extern
+#define LOCAL_FUNC /* nothing */
+#endif
+
+#ifdef FT_MAKE_OPTION_SINGLE_LIBRARY_OBJECT
+#define BASE_DEF( x ) static x
+#define BASE_FUNC( x ) static x
+#else
+#define BASE_DEF( x ) extern x
+#define BASE_FUNC( x ) extern x
+#endif
+
+#ifndef FT_EXPORT_DEF
+#define FT_EXPORT_DEF( x ) extern x
+#endif
+
+#ifndef FT_EXPORT_FUNC
+#define FT_EXPORT_FUNC( x ) extern x
+#endif
+
+#ifndef FT_EXPORT_VAR
+#define FT_EXPORT_VAR( x ) extern x
+#endif
+
+#endif /* FTCONFIG_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* fonddrvr.c */
+/* */
+/* Mac FOND font driver. Written by just@letterror.com. */
+/* */
+/* Copyright 1996-2000 by */
+/* Just van Rossum, 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. */
+/* */
+/***************************************************************************/
+
+
+/*
+ Notes
+
+ Mac suitcase files can (and often do!) contain multiple fonts. To
+ support this I use the face_index argument of FT_(Open|New)_Face()
+ functions, and pretend the suitcase file is a collection.
+ Warning: although the FOND driver sets face->num_faces field to the
+ number of available fonts, but the Type 1 driver sets it to 1 anyway.
+ So this field is currently not reliable, and I don't see a clean way
+ to resolve that. The face_index argument translates to
+ Get1IndResource( 'FOND', face_index + 1 );
+ so clients should figure out the resource index of the FOND.
+ (I'll try to provide some example code for this at some point.)
+
+ The Mac FOND driver works roughly like this:
+
+ - Check whether the offered stream points to a Mac suitcase file.
+ This is done by checking the file type: it has to be 'FFIL' or 'tfil'.
+ The stream that gets passed to our init_face() routine is a stdio
+ stream, which isn't usable for us, since the FOND resources live
+ in the resource fork. So we just grab the stream->pathname field.
+
+ - Read the FOND resource into memory, then check whether there is
+ a TrueType font and/or (!) a Type 1 font available.
+
+ - If there is a Type 1 font available (as a separate 'LWFN' file),
+ read its data into memory, massage it slightly so it becomes
+ PFB data, wrap it into a memory stream, load the Type 1 driver
+ and delegate the rest of the work to it, by calling the init_face()
+ method of the Type 1 driver.
+ (XXX TODO: after this has been done, the kerning data from the FOND
+ resource should be appended to the face: on the Mac there are usually
+ no AFM files available. However, this is tricky since we need to map
+ Mac char codes to ps glyph names to glyph ID's...)
+
+ - If there is a TrueType font (an 'sfnt' resource), read it into
+ memory, wrap it into a memory stream, load the TrueType driver
+ and delegate the rest of the work to it, by calling the init_face()
+ method if the TrueType driver.
+
+ - In both cases, the original stream gets closed and *reinitialized*
+ to become a memory stream. Additionally, the face->driver field --
+ which is set to the FOND driver upon entering our init_face() --
+ gets *reset* to either the TT or the T1 driver. I had to make a minor
+ change to ftobjs.c to make this work.
+
+ - We might consider creating an FT_New_Face_Mac() API call, as this
+ would avoid some of the mess described above.
+*/
+
+#include <truetype/ttobjs.h>
+#include <type1z/z1objs.h>
+
+#include <Resources.h>
+#include <Fonts.h>
+#include <Errors.h>
+
+#include <ctype.h> /* for isupper() and isalnum() */
+#include <stdlib.h> /* for malloc() and free() */
+
+
+/* set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
+ TrueType in case *both* are available */
+#ifndef PREFER_LWFN
+#define PREFER_LWFN 1
+#endif
+
+
+ static
+ FT_Error init_driver( FT_Driver driver )
+ {
+ /* we don't keep no stinkin' state ;-) */
+ return FT_Err_Ok;
+ }
+
+ static
+ FT_Error done_driver( FT_Driver driver )
+ {
+ return FT_Err_Ok;
+ }
+
+
+ /* MacRoman glyph names, needed for FOND kerning support. */
+ /* XXX which is not implemented yet! */
+ static const char* mac_roman_glyph_names[256] = {
+ ".null",
+ };
+
+
+ /* The FOND face object is just a union of TT and T1: both is possible,
+ and we don't need anything else. We still need to be able to hold
+ either, as the face object is not allocated by us. Again, creating
+ an FT_New_Face_Mac() would avoid this kludge. */
+ typedef union FOND_FaceRec_
+ {
+ TT_FaceRec tt;
+ T1_FaceRec t1;
+ } FOND_FaceRec, *FOND_Face;
+
+
+ /* given a pathname, fill in a File Spec */
+ static
+ int make_file_spec( char* pathname, FSSpec *spec )
+ {
+ Str255 p_path;
+ int path_len;
+
+ /* convert path to a pascal string */
+ path_len = strlen( pathname );
+ if ( path_len > 255 )
+ return -1;
+ p_path[0] = path_len;
+ strncpy( (char*)p_path+1, pathname, path_len );
+
+ if ( FSMakeFSSpec( 0, 0, p_path, spec ) != noErr )
+ return -1;
+ else
+ return 0;
+ }
+
+
+ /* is_suitcase() returns true if the file specified by 'pathname'
+ is a Mac suitcase file, and false if it ain't. */
+ static
+ int is_suitcase( FSSpec *spec )
+ {
+ FInfo finfo;
+
+ if ( FSpGetFInfo( spec, &finfo ) != noErr )
+ return 0;
+ if ( finfo.fdType == 'FFIL' || finfo.fdType == 'tfil' )
+ return 1;
+ else
+ return 0;
+ }
+
+
+ /* Quick 'n' Dirty Pascal string to C string converter.
+ Warning: this call is not thread safe! Use with caution. */
+ static
+ char * p2c_str( unsigned char *pstr )
+ {
+ static char cstr[256];
+
+ strncpy( cstr, (char*)pstr+1, pstr[0] );
+ cstr[pstr[0]] = '\0';
+ return cstr;
+ }
+
+
+ /* Given a PostScript font name, create the Macintosh LWFN file name */
+ static
+ void create_lwfn_name( char* ps_name, Str255 lwfn_file_name )
+ {
+ int max = 5, count = 0;
+ unsigned char* p = lwfn_file_name;
+ char* q = ps_name;
+
+ lwfn_file_name[0] = 0;
+
+ while ( *q )
+ {
+ if ( isupper(*q) )
+ {
+ if ( count )
+ max = 3;
+ count = 0;
+ }
+ if ( count < max && (isalnum(*q) || *q == '_' ) )
+ {
+ *++p = *q;
+ lwfn_file_name[0]++;
+ count++;
+ }
+ q++;
+ }
+ }
+
+
+ /* Suck the relevant info out of the FOND data */
+ static
+ FT_Error parse_fond( char* fond_data,
+ short *have_sfnt,
+ short *sfnt_id,
+ Str255 lwfn_file_name )
+ {
+ AsscEntry* assoc;
+ FamRec* fond;
+
+ *sfnt_id = *have_sfnt = 0;
+ lwfn_file_name[0] = 0;
+
+ fond = (FamRec*)fond_data;
+ assoc = (AsscEntry*)(fond_data + sizeof(FamRec) + 2);
+
+ if ( assoc->fontSize == 0 )
+ {
+ *have_sfnt = 1;
+ *sfnt_id = assoc->fontID;
+ }
+
+ if ( fond->ffStylOff )
+ {
+ unsigned char* p = (unsigned char*)fond_data;
+ StyleTable* style;
+ unsigned short string_count;
+ unsigned char* name_table = 0;
+ char ps_name[256];
+ unsigned char* names[64];
+ int i;
+
+ p += fond->ffStylOff;
+ style = (StyleTable*)p;
+ p += sizeof(StyleTable);
+ string_count = *(unsigned short*)(p);
+ p += sizeof(short);
+
+ for ( i=0 ; i<string_count && i<64; i++ )
+ {
+ names[i] = p;
+ p += names[i][0];
+ p++;
+ }
+ strcpy(ps_name, p2c_str(names[0])); /* Family name */
+
+ if ( style->indexes[0] > 1 )
+ {
+ unsigned char* suffixes = names[style->indexes[0]-1];
+ for ( i=1; i<=suffixes[0]; i++ )
+ strcat( ps_name, p2c_str(names[suffixes[i]-1]) );
+ }
+ create_lwfn_name( ps_name, lwfn_file_name );
+ }
+ return FT_Err_Ok;
+ }
+
+
+ /* Read Type 1 data from the POST resources inside the LWFN file, return a
+ PFB buffer -- apparently FT doesn't like a pure binary T1 stream. */
+ static
+ unsigned char* read_type1_data( FT_Memory memory, FSSpec* lwfn_spec, unsigned long *size )
+ {
+ short res_ref, res_id;
+ unsigned char *buffer, *p, *size_p;
+ unsigned long total_size = 0;
+ unsigned long post_size, pfb_chunk_size;
+ Handle post_data;
+ char code, last_code;
+
+ res_ref = FSpOpenResFile( lwfn_spec, fsRdPerm );
+ if ( ResError() )
+ return NULL;
+ UseResFile( res_ref );
+
+ /* first pass: load all POST resources, and determine the size of
+ the output buffer */
+ res_id = 501;
+ last_code = -1;
+ for (;;)
+ {
+ post_data = Get1Resource( 'POST', res_id++ );
+ if ( post_data == NULL )
+ break;
+ code = (*post_data)[0];
+ if ( code != last_code )
+ {
+ if ( code == 5 )
+ total_size += 2; /* just the end code */
+ else
+ total_size += 6; /* code + 4 bytes chunk length */
+ }
+ total_size += GetHandleSize( post_data ) - 2;
+ last_code = code;
+ }
+
+ buffer = memory->alloc( memory, total_size );
+ if ( !buffer )
+ goto error;
+
+ /* second pass: append all POST data to the buffer, add PFB fields */
+ p = buffer;
+ res_id = 501;
+ last_code = -1;
+ pfb_chunk_size = 0;
+ for (;;)
+ {
+ post_data = Get1Resource( 'POST', res_id++ );
+ if ( post_data == NULL )
+ break;
+ post_size = GetHandleSize( post_data ) - 2;
+ code = (*post_data)[0];
+ if ( code != last_code )
+ {
+ if ( last_code != -1 )
+ {
+ /* we're done adding a chunk, fill in the size field */
+ *size_p++ = pfb_chunk_size & 0xFF;
+ *size_p++ = (pfb_chunk_size >> 8) & 0xFF;
+ *size_p++ = (pfb_chunk_size >> 16) & 0xFF;
+ *size_p++ = (pfb_chunk_size >> 24) & 0xFF;
+ pfb_chunk_size = 0;
+ }
+ *p++ = 0x80;
+ if ( code == 5 )
+ *p++ = 0x03; /* the end */
+ else if ( code == 2 )
+ *p++ = 0x02; /* binary segment */
+ else
+ *p++ = 0x01; /* ASCII segment */
+ if ( code != 5 )
+ {
+ size_p = p; /* save for later */
+ p += 4; /* make space for size field */
+ }
+ }
+ memcpy( p, *post_data + 2, post_size );
+ pfb_chunk_size += post_size;
+ p += post_size;
+ last_code = code;
+ }
+
+ CloseResFile( res_ref );
+
+ *size = total_size;
+/* printf( "XXX %d %d\n", p - buffer, total_size ); */
+ return buffer;
+
+error:
+ CloseResFile( res_ref );
+ return NULL;
+ }
+
+
+ /* Finalizer for the sfnt stream */
+ static
+ void sfnt_stream_close( FT_Stream stream )
+ {
+ Handle sfnt_data = stream->descriptor.pointer;
+ HUnlock( sfnt_data );
+ DisposeHandle( sfnt_data );
+
+ stream->descriptor.pointer = NULL;
+ stream->size = 0;
+ stream->base = 0;
+ stream->close = 0;
+ }
+
+
+ /* Finalizer for the LWFN stream */
+ static
+ void lwfn_stream_close( FT_Stream stream )
+ {
+ stream->memory->free( stream->memory, stream->base );
+ stream->descriptor.pointer = NULL;
+ stream->size = 0;
+ stream->base = 0;
+ stream->close = 0;
+ }
+
+
+ /* Main entry point. Determine whether we're dealing with a Mac
+ suitcase or not; then determine if we're dealing with Type 1
+ or TrueType; delegate the work to the proper driver. */
+ static
+ FT_Error init_face( FT_Stream stream,
+ FT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* parameters )
+ {
+ FT_Error err;
+ FSSpec suit_spec, lwfn_spec;
+ short res_ref;
+ Handle fond_data, sfnt_data;
+ short res_index, sfnt_id, have_sfnt;
+ Str255 lwfn_file_name;
+
+ if ( !stream->pathname.pointer )
+ return FT_Err_Unknown_File_Format;
+
+ if ( make_file_spec( stream->pathname.pointer, &suit_spec ) )
+ return FT_Err_Invalid_Argument;
+
+ if ( !is_suitcase( &suit_spec ) )
+ return FT_Err_Unknown_File_Format;
+
+ res_ref = FSpOpenResFile( &suit_spec, fsRdPerm );
+ if ( ResError() )
+ return FT_Err_Invalid_File_Format;
+ UseResFile( res_ref );
+
+ /* face_index may be -1, in which case we
+ just need to do a sanity check */
+ if ( face_index < 0)
+ res_index = 1;
+ else
+ {
+ res_index = face_index + 1;
+ face_index = 0;
+ }
+ fond_data = Get1IndResource( 'FOND', res_index );
+ if ( ResError() )
+ {
+ CloseResFile( res_ref );
+ return FT_Err_Invalid_File_Format;
+ }
+ /* Set the number of faces. Not that it helps much: the t1 driver
+ just sets it to 1 anyway :-( */
+ face->num_faces = Count1Resources('FOND');
+
+ HLock( fond_data );
+ err = parse_fond( *fond_data, &have_sfnt, &sfnt_id, lwfn_file_name );
+ HUnlock( fond_data );
+ if ( err )
+ {
+ CloseResFile( res_ref );
+ return FT_Err_Invalid_Handle;
+ }
+
+ if ( lwfn_file_name[0] )
+ {
+ /* We look for the LWFN file in the same directory as the suitcase
+ file. ATM would look in other places, too, but this is the usual
+ situation. */
+ err = FSMakeFSSpec( suit_spec.vRefNum, suit_spec.parID, lwfn_file_name, &lwfn_spec );
+ if ( err != noErr )
+ lwfn_file_name[0] = 0; /* no LWFN file found */
+ }
+
+ if ( lwfn_file_name[0] && ( !have_sfnt || PREFER_LWFN ) )
+ {
+ FT_Driver t1_driver;
+ unsigned char* type1_data;
+ unsigned long size;
+
+ CloseResFile( res_ref ); /* XXX still need to read kerning! */
+
+ type1_data = read_type1_data( stream->memory, &lwfn_spec, &size );
+ if ( !type1_data )
+ {
+ return FT_Err_Out_Of_Memory;
+ }
+
+#if 0
+ {
+ FILE* f;
+ char * path;
+
+ path = p2c_str( lwfn_file_name );
+ strcat( path, ".PFB" );
+ f = fopen(path, "wb");
+ if ( f )
+ {
+ fwrite( type1_data, 1, size, f );
+ fclose( f );
+ }
+ }
+#endif
+
+ /* reinitialize the stream */
+ if ( stream->close )
+ stream->close( stream );
+ stream->close = lwfn_stream_close;
+ stream->read = 0; /* it's now memory based */
+ stream->base = type1_data;
+ stream->size = size;
+ stream->pos = 0; /* just in case */
+
+ /* delegate the work to the Type 1 module */
+ t1_driver = (FT_Driver)FT_Get_Module( face->driver->root.library, "type1z" );
+ if ( t1_driver )
+ {
+ face->driver = t1_driver;
+ return t1_driver->clazz->init_face( stream, face, face_index, 0, NULL );
+ }
+ else
+ return FT_Err_Invalid_Driver_Handle;
+ }
+ else if ( have_sfnt )
+ {
+ FT_Driver tt_driver;
+
+ sfnt_data = Get1Resource( 'sfnt', sfnt_id );
+ if ( ResError() )
+ {
+ CloseResFile( res_ref );
+ return FT_Err_Invalid_Handle;
+ }
+ DetachResource( sfnt_data );
+ CloseResFile( res_ref );
+ HLockHi( sfnt_data );
+
+ /* reinitialize the stream */
+ if ( stream->close )
+ stream->close( stream );
+ stream->close = sfnt_stream_close;
+ stream->descriptor.pointer = sfnt_data;
+ stream->read = 0; /* it's now memory based */
+ stream->base = (unsigned char *)*sfnt_data;
+ stream->size = GetHandleSize( sfnt_data );
+ stream->pos = 0; /* just in case */
+
+ /* delegate the work to the TrueType driver */
+ tt_driver = (FT_Driver)FT_Get_Module( face->driver->root.library, "truetype" );
+ if ( tt_driver )
+ {
+ face->driver = tt_driver;
+ return tt_driver->clazz->init_face( stream, face, face_index, 0, NULL );
+ }
+ else
+ return FT_Err_Invalid_Driver_Handle;
+ }
+ else
+ {
+ CloseResFile( res_ref );
+ }
+ return FT_Err_Invalid_File_Format;
+ }
+
+
+ static
+ void done_face( FT_Face face )
+ {
+ /* nothing to do */
+ }
+
+ /* The FT_DriverInterface structure is defined in ftdriver.h. */
+
+ const FT_Driver_Class fond_driver_class =
+ {
+ {
+ ft_module_font_driver | ft_module_driver_scalable,
+ sizeof ( FT_DriverRec ),
+
+ "fond", /* driver name */
+ 0x10000L, /* driver version == 1.0 */
+ 0x20000L, /* driver requires FreeType 2.0 or above */
+
+ (void*)0,
+
+ (FT_Module_Constructor) init_driver,
+ (FT_Module_Destructor) done_driver,
+ (FT_Module_Requester) 0
+ },
+
+ sizeof ( FOND_FaceRec ),
+ 0,
+ 0,
+
+ (FTDriver_initFace) init_face,
+ (FTDriver_doneFace) done_face,
+ (FTDriver_initSize) 0,
+ (FTDriver_doneSize) 0,
+ (FTDriver_initGlyphSlot) 0,
+ (FTDriver_doneGlyphSlot) 0,
+
+ (FTDriver_setCharSizes) 0,
+ (FTDriver_setPixelSizes) 0,
+ (FTDriver_loadGlyph) 0,
+ (FTDriver_getCharIndex) 0,
+
+ (FTDriver_getKerning) 0,
+ (FTDriver_attachFile) 0,
+ (FTDriver_getAdvances) 0
+ };
+
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* getDriverInterface */
+ /* */
+ /* <Description> */
+ /* This function is used when compiling the FOND driver as a */
+ /* shared library (`.DLL' or `.so'). It will be used by the */
+ /* high-level library of FreeType to retrieve the address of the */
+ /* driver's generic interface. */
+ /* */
+ /* It shouldn't be implemented in a static build, as each driver must */
+ /* have the same function as an exported entry point. */
+ /* */
+ /* <Return> */
+ /* The address of the TrueType's driver generic interface. The */
+ /* format-specific interface can then be retrieved through the method */
+ /* interface->get_format_interface. */
+ /* */
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+ FT_EXPORT_FUNC(const FT_Driver_Class*) getDriverClass( void )
+ {
+ return &fond_driver_class;
+ }
+
+#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
--- /dev/null
+#include <oltypes.h>
+
+ LOCAL_FUNC
+ TT_Error OTL_Table_Init( OTL_Table* table,
+ FT_Memory memory )
+ {
+ MEM_Set( table, 0, sizeof(*table) );
+ table->memory = memory;
+ }
+
+ /* read a script list table */
+ /* use with any table */
+ LOCAL_FUNC
+ TT_Error OTL_Table_Set_Scripts( OTL_Table* table,
+ TT_Byte* bytes,
+ TT_Long len,
+ OTL_Type otl_type )
+ {
+ TT_Byte* p;
+ TT_Byte* start = bytes;
+ TT_UInt count, max_langs;
+ TT_Error error;
+
+ /* skip version of the JSTF table */
+ if (otl_type == otl_jstf)
+ start += 4;
+
+ p = start;
+
+ /* we must allocate the script_tags and language_tags arrays */
+ /* this requires that we compute the maximum number of languages */
+ /* per script.. */
+
+ count = table->num_scripts = OTL_UShort(p);
+ max_langs = 0;
+ for ( ; count > 0; count++ )
+ {
+ TT_Byte* script;
+ TT_UInt num_langs;
+
+ p += 4; /* skip tag */
+ script = bytes + OTL_UShort(p);
+
+ /* skip the baseValues or extenders field of the BASE and JSTF table */
+ if (otl_type == otl_type_base || otl_type == otl_type_jstf)
+ script += 2;
+
+ /* test if there is a default language system */
+ if ( OTL_UShort(script) )
+ num_langs++;
+
+ /* test other language systems */
+ num_langs += OTL_UShort(script); /* add other lang sys */
+
+ if (num_langs > max_langs)
+ max_langs = num_langs;
+ }
+
+ /* good, now allocate the tag arrays */
+ if ( !ALLOC_ARRAY( table->script_tags,
+ table->num_scripts + max_langs,
+ TT_ULong ) )
+ {
+ table->language_tags = table->script_tags + table->num_scripts;
+ table->max_languages = max_langs;
+ table->num_languages = 0;
+ table->otl_type = otl_type;
+
+ table->scripts_table = bytes;
+ table->scripts_len = len;
+
+ /* fill the script_tags array */
+ {
+ TT_UInt n;
+ TT_Byte* p = start + 2; /* skip count */
+
+ for ( n = 0; n < table->num_scripts; n++ )
+ {
+ table->script_tags[n] = OTL_ULong(p);
+ p += 2; /* skip offset */
+ }
+ }
+ }
+ return error;
+ }
+
+
+
+ /* add a features list to the table */
+ /* use only with a GSUB or GPOS table */
+ LOCAL_FUNC
+ TT_Error OTL_Table_Set_Features( OTL_Table* table,
+ TT_Byte* bytes,
+ TT_Long len )
+ {
+ TT_Error error;
+ TT_Byte* p = bytes;
+ TT_UInt count;
+
+ table->max_features = count = OTL_UShort(p);
+ if ( !ALLOC_ARRAY( table->feature_tags, count, TT_ULong ) &&
+ !ALLOC_ARRAY( table->features, count, TT_Bool ) )
+ {
+ table->features_table = bytes;
+ table->features_len = len;
+ }
+ return error;
+ }
+
+
+ /* add a lookup list to the table */
+ /* use only with a GSUB or GPOS table */
+ LOCAL_FUNC
+ TT_Error OTL_Table_Set_Lookups( OTL_Table* table,
+ TT_Byte* bytes,
+ TT_Long len )
+ {
+ TT_Error error;
+ TT_Byte* p = bytes;
+ TT_UInt count;
+
+ table->max_lookups = count = OTL_UShort(p);
+ if ( !ALLOC_ARRAY( table->lookups, count, TT_Bool ) )
+ {
+ table->lookups_table = bytes;
+ table->lookups_len = len;
+ }
+ return error;
+ }
+
+ /* discard table arrays */
+ LOCAL_FUNC
+ void OTL_Table_Done( OTL_Table* table )
+ {
+ FREE( table->scrip_tags );
+ FREE( table->language_tags );
+ FREE( table->feature_tags );
+ FREE( table->lookups );
+ }
+
+
+ /* return the list of available languages for a given script */
+ /* use with any table.. */
+ LOCAL_FUNC
+ void OTL_Get_Languages_List( OTL_Table* table,
+ TT_ULong script_tag )
+ {
+ TT_UInt n;
+ TT_Byte* p;
+ TT_Byte* script = 0;
+ TT_Byte* start = table->scripts_table;
+
+ if ( table->otl_type == otl_type_jstf ) /* skip version for JSTF */
+ start += 4;
+
+ p = start + 6; /* skip count+first tag */
+
+ for ( n = 0; n < table->num_scripts; n++, p += 6 )
+ {
+ if ( table->script_tags[n] == script_tag )
+ {
+ script = table->scripts_table + OTL_UShort(p);
+ break;
+ }
+ }
+
+ table->cur_script = script;
+ if (!script)
+ table->num_languages = 0;
+ else
+ {
+ /* now fill the language_tags array with the appropriate values */
+ /* not that we put a '0' tag in front of the list to indicate that */
+ /* there is a default language for this script.. */
+ TT_ULong* tags = table->language_tags;
+
+ switch (table->otl_type)
+ {
+ case otl_type_base:
+ case otl_type_jstf:
+ script += 2; /* skip basevalue or extenders */
+ /* fall-through */
+
+ default:
+ if ( OTL_UShort(script) )
+ *tags++ = 0;
+ }
+
+ count = OTL_UShort(script);
+ for ( ; count > 0; count-- )
+ {
+ *tags++ = OTL_ULong(script);
+ script += 2; /* skip offset */
+ }
+
+ table->num_langs = tags - table->language_tags;
+ }
+ }
+
+
+ /* return the list of available features for the current script/language */
+ /* use with a GPOS or GSUB script table */
+ LOCAL_FUNC
+ void OTL_Get_Features_List( OTL_Table* table,
+ TT_ULong language_tag )
+ {
+ TT_UInt n;
+ TT_Byte* script = table->cur_script;
+ TT_Byte* language = 0;
+ TT_UShort offset;
+
+ /* clear feature selection table */
+ for ( n = 0; n < table->max_features; n++ )
+ table->features[n] = 0;
+
+ /* now, look for the current language */
+ if ( language_tag == 0 )
+ {
+ offset = OTL_UShort(script);
+ if (!offset) return; /* if there is no default language, exit */
+
+ language = script - 2 + offset;
+ }
+ else
+ {
+ TT_Byte* p = script + 8; /* skip default+count+1st tag */
+ TT_UShort index;
+
+ for ( n = 0; n < table->num_languages; n++, p+=6 )
+ {
+ if ( table->language_tags[n] == language_tag )
+ {
+ language = script + OTL_UShort(p);
+ break;
+ }
+ }
+
+ table->cur_language = language;
+ if (!language) return;
+
+ p = language + 2; /* skip lookup order */
+ index = OTL_UShort(p); /* required feature index */
+ if (index != 0xFFFF)
+ {
+ if (index < table->max_features)
+ table->features[index] = 1;
+ }
+
+ count = OTL_UShort(p);
+ for ( ; count > 0; count-- )
+ {
+ index = OTL_UShort(p);
+ if (index < table->max_features)
+ table->features[index] = 1;
+ }
+ }
+ }
+
+
+ /* return the list of lookups for the current features list */
+ /* use only with a GSUB or GPOS table */
+ LOCAL_FUNC
+ void OTL_Get_Lookups_List( OTL_Table* table )
+ {
+ TT_UInt n;
+ TT_Byte* features = table->features_table;
+ TT_Byte* p = features + 6; /* skip count+1st tag */
+
+ /* clear lookup list */
+ for ( n = 0; n < table->max_lookups; n++ )
+ table->lookups[n] = 0;
+
+ /* now, parse the features list */
+ for ( n = 0; n < table->features; n++ )
+ {
+ if (table->features[n])
+ {
+ TT_UInt count;
+ TT_UShort index;
+ TT_Byte* feature;
+
+ feature = features + OTL_UShort(p);
+ p += 4; /* skip tag */
+
+ /* now, select all lookups from this feature */
+ count = OTL_UShort(feature);
+ for ( ; count > 0; count-- )
+ {
+ index = OTL_UShort(feature);
+ if (index < table->max_lookups)
+ table->lookups[index] = 1;
+ }
+ }
+ }
+ }
+
+
+ /* find the basevalues and minmax for the current script/language */
+ /* only use it with a BASE table.. */
+ LOCAL_FUNC
+ void OTL_Get_Baseline_Values( OTL_Table* table,
+ TT_ULong language_tag )
+ {
+ TT_Byte* script = table->cur_script;
+ TT_Byte* p = script;
+ TT_UShort offset, count;
+
+ table->cur_basevalues = 0;
+ table->cur_minmax = 0;
+
+ /* read basevalues */
+ offset = OTL_UShort(p);
+ if (offset)
+ table->cur_basevalues = script + offset;
+
+ offset = OTL_UShort(p);
+ if (offset)
+ table->cur_minmax = script + offset;
+
+ count = OTL_UShort(p);
+ for ( ; count > 0; count-- )
+ {
+ TT_ULong tag;
+
+ tag = OTL_ULong(p);
+ if ( language_tag == tag )
+ {
+ table->cur_minmax = script + OTL_UShort(p);
+ break;
+ }
+ p += 2; /* skip offset */
+ }
+ }
+
+
+ /* compute the coverage value of a given glyph id */
+ LOCAL_FUNC
+ TT_Long OTL_Get_Coverage_Index( TT_Byte* coverage,
+ TT_UInt glyph_id )
+ {
+ TT_Long result = -1;
+ TT_UInt count, index, start, end;
+ TT_Byte* p = coverage;
+
+ switch ( OTL_UShort(p) )
+ {
+ case 1: /* coverage format 1 - array of glyph indices */
+ {
+ count = OTL_UShort(p);
+ for ( index = 0; index < count; index++ )
+ {
+ if ( OTL_UShort(p) == glyph_id )
+ {
+ result = index;
+ break;
+ }
+ }
+ }
+ break;
+
+ case 2:
+ {
+ count = OTL_UShort(p);
+ for ( ; count > 0; count-- )
+ {
+ start = OTL_UShort(p);
+ end = OTL_UShort(p);
+ index = OTL_UShort(p);
+ if (start <= glyph_id && glyph_id <= end)
+ {
+ result = glyph_id - start + index;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ return result;
+ }
+
+
+ /* compute the class value of a given glyph_id */
+ LOCAL_FUNC
+ TT_UInt OTL_Get_Glyph_Class( TT_Byte* class_def,
+ TT_UInt glyph_id )
+ {
+ TT_Byte* p = class_def;
+ TT_UInt result = 0;
+ TT_UInt start, end, count, index;
+
+ switch ( OTL_UShort(p) )
+ {
+ case 1:
+ {
+ start = OTL_UShort(p);
+ count = OTL_UShort(p);
+
+ glyph_id -= start;
+ if (glyph_id < count)
+ {
+ p += 2*glyph_id;
+ result = OTL_UShort(p);
+ }
+ }
+ break;
+
+ case 2:
+ {
+ count = OTL_UShort(p);
+ for ( ; count > 0; count-- )
+ {
+ start = OTL_UShort(p);
+ end = OTL_UShort(p);
+ index = OTL_UShort(p);
+ if ( start <= glyph_id && glyph_id <= end )
+ {
+ result = index;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ return result;
+ }
+
+
+ /* compute the adjustement necessary for a given device size */
+ LOCAL_FUNC
+ TT_Int OTL_Get_Device_Adjustment( TT_Byte* device,
+ TT_UInt size )
+ {
+ TT_Byte* p = device;
+ TT_Int result = 0;
+ TT_UInt start, end;
+ TT_Short value;
+
+ start = OTL_UShort(p);
+ end = OTL_UShort(p);
+ if (size >= start && size <= end)
+ {
+ /* I know we could do all of this without a switch, with */
+ /* clever shifts and everything, but it makes the code */
+ /* really difficult to understand.. */
+
+ size -= start;
+ switch ( OTL_UShort(p) )
+ {
+ case 1: /* 2-bits per value */
+ {
+ p += 2*(size >> 3);
+ size = (size & 7) << 1;
+ value = (TT_Short)((TT_Short)OTL_UShort(p) << size);
+ result = value >> 14;
+ }
+ break;
+
+ case 2: /* 4-bits per value */
+ {
+ p += 2*(size >> 2);
+ size = (size & 3) << 2;
+ value = (TT_Short)((TT_Short)OTL_UShort(p) << size);
+ result = value >> 12;
+ }
+ break;
+
+ case 3: /* 8-bits per value */
+ {
+ p += 2*(size >> 1);
+ size = (size & 1) << 3;
+ value = (TT_Short)((TT_Short)OTL_UShort(p) << size);
+ result = value >> 8;
+ }
+ break;
+ }
+ }
+ return result;
+ }
+
+ /* extract a BaseCoord value */
+ LOCAL_FUNC
+ void OTL_Get_Base_Coordinate( TT_Byte* base_coord,
+ OTL_ValueRecord* coord )
+ {
+ TT_Byte* p = base_coord;
+ TT_Int result = 0;
+
+ coord->format = OTL_UShort(p);
+ coord->coordinate = OTL_Short(p);
+ coord->device = 0;
+
+ switch (coord->format)
+ {
+ case 2: /* format 2 */
+ coord->ref_glyph = OTL_UShort(p);
+ coord->ref_point = OTL_UShort(p);
+ break;
+
+ case 3: /* format 3 */
+ coord->device = p - 4 + OTL_UShort(p);
+ break;
+
+ default:
+ ;
+ }
+ }
+
+
+ /* compute size of ValueRecord */
+ LOCAL_FUNC
+ TT_Int OTL_ValueRecord_Size( TT_UShort format )
+ {
+ TT_Int count;
+
+ /* each bit in the value format corresponds to a single ushort */
+ /* we thus count the bits, and multiply the result by 2 */
+
+ count = (TT_Int)(format & 0xFF);
+ count = ((count & 0xAA) >> 1) + (count & 0x55);
+ count = ((count & 0xCC) >> 2) + (count & 0x33);
+ count = ((count & 0xF0) >> 4) + (count & 0x0F);
+
+ return count*2;
+ }
+
+
+
+ /* extract ValueRecord */
+ LOCAL_FUNC
+ void OTL_Get_ValueRecord( TT_Byte* value_record,
+ TT_UShort value_format,
+ TT_Byte* pos_table,
+ OTL_ValueRecord* record )
+ {
+ TT_Byte* p = value_record;
+
+ /* clear vectors */
+ record->placement.x = 0;
+ record->placement.y = 0;
+ record->advance.x = 0;
+ record->advance.y = 0;
+
+ record->device_pla_x = 0;
+ record->device_pla_y = 0;
+ record->device_adv_x = 0;
+ record->device_adv_y = 0;
+
+ if (value_format & 1) record->placement.x = NEXT_Short(p);
+ if (value_format & 2) record->placement.y = NEXT_Short(p);
+ if (value_format & 4) record->advance.x = NEXT_Short(p);
+ if (value_format & 8) record->advance.y = NEXT_Short(p);
+
+ if (value_format & 16) record->device_pla_x = pos_table + NEXT_UShort(p);
+ if (value_format & 32) record->device_pla_y = pos_table + NEXT_UShort(p);
+ if (value_format & 64) record->device_adv_x = pos_table + NEXT_UShort(p);
+ if (value_format & 128) record->device_adv_y = pos_table + NEXT_UShort(p);
+ }
+
+
+
+ /* extract Anchor */
+ LOCAL_FUNC
+ void OTL_Get_Anchor( TT_Byte* anchor_table,
+ OTL_Anchor* anchor )
+ {
+ TT_Byte* p = anchor_table;
+
+ anchor->format = NEXT_UShort(p);
+ anchor->coord.x = NEXT_Short(p);
+ anchor->coord.y = NEXT_Short(p);
+ anchor->point = 0;
+ anchor->device_x = 0;
+ anchor->device_y = 0;
+
+ switch (anchor->format)
+ {
+ case 2:
+ anchor->point = NEXT_UShort(p);
+ break;
+
+ case 3:
+ anchor->device_x = anchor_table + NEXT_UShort(p);
+ anchor->device_y = anchor_table + NEXT_UShort(p);
+ break;
+
+ default:
+ ;
+ }
+ }
+
+
+
+ /* extract Mark from MarkArray */
+ LOCAL_FUNC
+ void OTL_Get_Mark( TT_Byte* mark_array,
+ TT_UInt index,
+ TT_UShort* clazz,
+ OTL_Anchor* anchor )
+ {
+ TT_Byte* p = mark_array;
+ TT_UInt count;
+
+ *clazz = 0;
+ MEM_Set( anchor, 0, sizeof(*anchor) );
+
+ count = NEXT_UShort(p);
+ if (index < count)
+ {
+ p += 4*index;
+ *clazz = NEXT_UShort(p);
+ OTL_Get_Anchor( mark_array + NEXT_UShort(p), anchor );
+ }
+ }
+
--- /dev/null
+#ifndef OLTYPES_H
+#define OLTYPES_H
+
+#include <ftobjs.h>
+#include <tttypes.h>
+
+ /*************************************************************
+ *
+ * <Struct> OTL_Table
+ *
+ * <Description>
+ * The base table of most OpenType Layout sub-tables.
+ * Provides a simple way to scan a table for script,
+ * languages, features and lookups..
+ *
+ * <Fields>
+ * num_scripts :: number of scripts in table's script list
+ * script_tags :: array of tags for each table script
+ *
+ * max_languages :: max number of languages for any script in
+ * the table.
+ * num_languages :: number of languages available for current script
+ * language_tags :: tags of all languages available for current script.
+ *
+ * max_features :: total number of features in table
+ * feature_tags :: tags of all features for current script/language
+ * features :: selection flags for all features in current script/lang
+ *
+ * max_lookups :: total number of lookups in table
+ * lookups :: selection flags for all lookups for current
+ * feature list.
+ *
+ ****************************************************************/
+
+ typedef enum OTL_Type_
+ {
+ otl_type_none = 0,
+ otl_type_base,
+ otl_type_gdef,
+ otl_type_gpos,
+ otl_type_gsub,
+ otl_type_jstf
+
+ } OTL_Type;
+
+
+ typedef struct OTL_Table_
+ {
+ FT_Memory memory;
+
+ TT_Int num_scripts;
+ TT_Tag* script_tags;
+
+ TT_Int max_languages;
+ TT_Int num_languages;
+ TT_Tag* language_tags;
+
+ TT_Int max_features;
+ TT_Tag* feature_tags;
+ TT_Bool* features;
+
+ TT_Int max_lookups;
+ TT_Bool* lookups;
+
+ TT_Byte* scripts_table;
+ TT_Long scripts_len;
+
+ TT_Byte* features_table;
+ TT_Long* features_len;
+
+ TT_Byte* lookups_table;
+ TT_Byte* lookups_len;
+
+ TT_Byte* cur_script; /* current script */
+ TT_Byte* cur_language; /* current language */
+
+ TT_Byte* cur_base_values;
+ TT_Byte* cur_min_max;
+
+ OTL_Type otl_type;
+
+ } OTL_Table;
+
+
+ typedef struct OTL_BaseCoord_
+ {
+ TT_UShort format;
+ TT_Short coordinate;
+ TT_UShort ref_glyph;
+ TT_UShort ref_point;
+ TT_Byte* device;
+
+ } OTL_BaseCoord;
+
+
+ typedef struct OTL_ValueRecord_
+ {
+ TT_Vector placement;
+ TT_Vector advance;
+
+ TT_Byte* device_pla_x;
+ TT_Byte* device_pla_y;
+ TT_Byte* device_adv_x;
+ TT_Byte* device_adv_y;
+
+ } OTL_ValueRecord;
+
+
+ typedef struct OTL_Anchor_
+ {
+ TT_UInt format;
+ TT_Vector coord;
+ TT_UInt anchor_point;
+ TT_Byte* device_x;
+ TT_Byte* device_y;
+
+ } OTL_Anchor;
+
+ LOCAL_DEF
+ TT_Error OTL_Table_Init( OTL_Table* table,
+ FT_Memory memory );
+
+ LOCAL_DEF
+ TT_Error OTL_Table_Set_Scripts( OTL_Table* table,
+ TT_Byte* bytes,
+ TT_Long len,
+ OTL_Type otl_type );
+
+ LOCAL_DEF
+ TT_Error OTL_Table_Set_Features( OTL_Table* table,
+ TT_Byte* bytes,
+ TT_Long len );
+
+ LOCAL_DEF
+ TT_Error OTL_Table_Set_Lookups( OTL_Table* table,
+ TT_Byte* bytes,
+ TT_Long len );
+
+ LOCAL_DEF
+ void OTL_Table_Done( OTL_Table* table );
+
+
+
+/*****************************************************
+ *
+ * Typical uses:
+ *
+ * - after OTL_Table_Set_Scripts have been called :
+ *
+ * table->script_tags contains the list of tags of all
+ * scripts defined for this table.
+ *
+ * table->num_scripts is the number of scripts
+ *
+ */
+
+/********************************************************
+ *
+ * - after calling OTL_Table_Set_Features:
+ *
+ * table->max_features is the number of all features
+ * in the table
+ *
+ * table->feature_tags is the list of tags of all
+ * features in the table
+ *
+ * table->features[] is an array of boolean used to
+ * indicate which feature is active for a given script/language
+ * it is empty (zero-filled) by default.
+ *
+ */
+
+/*******************************************************************
+ *
+ * - after calling OTL_Get_Languages_List(script_tag):
+ *
+ * table->num_languages is the number of language systems
+ * available for the script, including the default
+ * langsys if there is one
+ *
+ * table->language_tags contains the list of tags of all
+ * languages for the script. Note that the default langsys
+ * has tag "0" and is always placed first in "language_tags".
+ *
+ *
+ *
+ */
+ LOCAL_DEF
+ void OTL_Get_Languages_List( OTL_Table* table,
+ TT_ULong script_tag );
+
+
+/*******************************************************************
+ *
+ * - after calling OTL_Get_Features_List(language_tag):
+ *
+ * table->features[] is an array of booleans used to indicate
+ * which features are active for the current script/language
+ *
+ * note that this function must be called after OTL_Get_Languages
+ * which remembers the last "script_tag" used..
+ *
+ * A client application can change the table->features[] array
+ * to add or remove features from the list.
+ *
+ *
+ *
+ */
+ LOCAL_DEF
+ void OTL_Get_Features_List( OTL_Table* table,
+ TT_ULong language_tag );
+
+ LOCAL_DEF
+ void OTL_Get_Baseline_Values( OTL_Table* table,
+ TT_ULong language_tag );
+
+ LOCAL_DEF
+ void OTL_Get_Justification( OTL_Table* table,
+ TT_ULong language_tag );
+
+/*******************************************************************
+ *
+ * - after calling OTL_Get_Lookups_List():
+ *
+ * The function uses the table->features[] array of boolean
+ * to determine which lookups must be processed.
+ *
+ * It fills the table->lookups[] array accordingly. It is also
+ * an array of booleans (one for each lookup).
+ *
+ *
+ */
+
+ LOCAL_DEF
+ void OTL_Get_Lookups_List( OTL_Table* table );
+
+
+/***************************************************************
+ *
+ * So the whole thing looks like:
+ *
+ *
+ * 1. A client specifies a given script and requests available
+ * language through OTL_Get_Languages_List()
+ *
+ * 2. It selects the language tag it needs, then calls
+ * OTL_Get_Features_List()
+ *
+ * 3. It updates the list of active features if it needs to
+ *
+ * 4. It calls OTL_Get_Lookups_List()
+ * It now has a list of active lookups in "table->lookups[]"
+ *
+ * 5. The lookups are processed according to the table's type..
+ *
+ */
+
+
+
+
+ LOCAL_DEF
+ TT_Long OTL_Get_Coverage_Index( TT_Byte* coverage,
+ TT_UInt glyph_id );
+
+ LOCAL_DEF
+ TT_UInt OTL_Get_Glyph_Class( TT_Byte* class_def,
+ TT_UInt glyph_id );
+
+ LOCAL_DEF
+ TT_Int OTL_Get_Device_Adjustment( TT_Byte* device,
+ TT_UInt size );
+
+ LOCAL_DEF
+ void OTL_Get_Base_Coordinate( TT_Byte* base_coord,
+ OTL_BaseCoord* coord );
+
+
+ LOCAL_DEF
+ TT_Int OTL_ValueRecord_Size( TT_UShort value_format );
+
+
+ LOCAL_DEF
+ void OTL_Get_ValueRecord( TT_Byte* value_record,
+ TT_UShort value_format,
+ TT_Byte* pos_table,
+ OTL_ValueRecord* record );
+
+
+ LOCAL_DEF
+ void OTL_Get_Anchor( TT_Byte* anchor_table,
+ OTL_Anchor* anchor );
+
+
+ LOCAL_DEF
+ void OTL_Get_Mark( TT_Byte* mark_array,
+ TT_UInt index,
+ TT_UShort* clazz,
+ OTL_Anchor* anchor );
+
+
+
+#define OTL_Byte(p) (p++, p[-1])
+
+#define OTL_UShort(p) (p+=2, ((TT_UShort)p[-2] << 8) | p[-1])
+
+#define OTL_ULong(p) (p+=4, ((TT_ULong)p[-4] << 24) | \
+ ((TT_ULong)p[-3] << 16) | \
+ ((TT_ULong)p[-2] << 8 ) | p[-1] )
+
+#endif /* OLTYPES_H */
--- /dev/null
+make_module_list: add_psnames_module
+
+add_psnames_module:
+ $(OPEN_DRIVER)psnames_module_class$(CLOSE_DRIVER)
+ $(ECHO_DRIVER)psnames $(ECHO_DRIVER_DESC)Postscript & Unicode Glyph name handling$(ECHO_DRIVER_DONE)
+
+# EOF
--- /dev/null
+/***************************************************************************/
+/* */
+/* psmodule.c */
+/* */
+/* PSNames module implementation (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/psnames.h>
+#include <freetype/internal/ftobjs.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "psmodule.h"
+#include "pstables.h"
+
+#else
+
+#include <psnames/psmodule.h>
+#include <psnames/pstables.h>
+
+#endif
+
+
+#include <stdlib.h> /* for qsort() */
+#include <string.h> /* for strcmp(), strncpy() */
+
+
+#ifndef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
+
+
+
+
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+
+ /* return the Unicode value corresponding to a given glyph. Note that */
+ /* we do deal with glyph variants by detecting a non-initial dot in */
+ /* the name, as in `A.swash' or `e.final', etc. */
+ /* */
+ static
+ FT_ULong PS_Unicode_Value( const char* glyph_name )
+ {
+ FT_Int n;
+ char first = glyph_name[0];
+ char temp[64];
+
+
+ /* if the name begins with `uni', then the glyph name may be a */
+ /* hard-coded unicode character code. */
+ if ( glyph_name[0] == 'u' &&
+ glyph_name[1] == 'n' &&
+ glyph_name[2] == 'i' )
+ {
+ /* determine whether the next four characters following are */
+ /* hexadecimal. */
+
+ /* XXX: Add code to deal with ligatures, i.e. glyph names like */
+ /* `uniXXXXYYYYZZZZ'... */
+
+ FT_Int count;
+ FT_ULong value = 0;
+ const char* p = glyph_name + 4;
+
+
+ for ( count = 4; count > 0; count--, p++ )
+ {
+ char c = *p;
+ unsigned char d;
+
+
+ d = (unsigned char)c - '0';
+ if ( d >= 10 )
+ {
+ d = (unsigned char)c - 'A';
+ if ( d >= 6 )
+ d = 16;
+ else
+ d += 10;
+ }
+
+ /* exit if a non-uppercase hexadecimal character was found */
+ if ( d >= 16 )
+ break;
+
+ value = ( value << 4 ) + d;
+
+ if ( count == 0 )
+ return value;
+ }
+ }
+
+ /* look for a non-initial dot in the glyph name in order to */
+ /* sort-out variants like `A.swash', `e.final', etc. */
+ {
+ const char* p;
+ int len;
+
+
+ p = glyph_name;
+
+ while ( *p && *p != '.' )
+ p++;
+
+ len = p - glyph_name;
+
+ if ( *p && len < 64 )
+ {
+ strncpy( temp, glyph_name, len );
+ temp[len] = 0;
+ glyph_name = temp;
+ }
+ }
+
+ /* now, look up the glyph in the Adobe Glyph List */
+ for ( n = 0; n < NUM_ADOBE_GLYPHS; n++ )
+ {
+ const char* name = t1_standard_glyphs[n];
+
+
+ if ( first == name[0] && strcmp( glyph_name, name ) == 0 )
+ return names_to_unicode[n];
+ }
+
+ /* not found, there is probably no Unicode value for this glyph name */
+ return 0;
+ }
+
+
+ /* qsort callback to sort the unicode map */
+ static
+ int compare_uni_maps( const void* a,
+ const void* b )
+ {
+ PS_UniMap* map1 = (PS_UniMap*)a;
+ PS_UniMap* map2 = (PS_UniMap*)b;
+
+
+ return ( map1->unicode - map2->unicode );
+ }
+
+
+ /* Builds a table that maps Unicode values to glyph indices */
+ static
+ FT_Error PS_Build_Unicode_Table( FT_Memory memory,
+ FT_UInt num_glyphs,
+ const char** glyph_names,
+ PS_Unicodes* table )
+ {
+ FT_Error error;
+
+
+ /* we first allocate the table */
+ table->num_maps = 0;
+ table->maps = 0;
+
+ if ( !ALLOC_ARRAY( table->maps, num_glyphs, PS_UniMap ) )
+ {
+ FT_UInt n;
+ FT_UInt count;
+ PS_UniMap* map;
+ FT_ULong uni_char;
+
+
+ map = table->maps;
+
+ for ( n = 0; n < num_glyphs; n++ )
+ {
+ const char* gname = glyph_names[n];
+
+
+ if ( gname )
+ {
+ uni_char = PS_Unicode_Value( gname );
+
+ if ( uni_char && uni_char != 0xFFFF )
+ {
+ map->unicode = uni_char;
+ map->glyph_index = n;
+ map++;
+ }
+ }
+ }
+
+ /* now, compress the table a bit */
+ count = map - table->maps;
+
+ if ( count > 0 && REALLOC( table->maps,
+ num_glyphs * sizeof ( PS_UniMap ),
+ count * sizeof ( PS_UniMap ) ) )
+ count = 0;
+
+ if ( count == 0 )
+ {
+ FREE( table->maps );
+ if ( !error )
+ error = FT_Err_Invalid_Argument; /* no unicode chars here! */
+ }
+ else
+ /* sort the table in increasing order of unicode values */
+ qsort( table->maps, count, sizeof ( PS_UniMap ), compare_uni_maps );
+
+ table->num_maps = count;
+ }
+
+ return error;
+ }
+
+
+ static
+ FT_UInt PS_Lookup_Unicode( PS_Unicodes* table,
+ FT_ULong unicode )
+ {
+ PS_UniMap *min, *max, *mid;
+
+
+ /* perform a binary search on the table */
+
+ min = table->maps;
+ max = min + table->num_maps - 1;
+
+ while ( min <= max )
+ {
+ mid = min + ( max - min ) / 2;
+ if ( mid->unicode == unicode )
+ return mid->glyph_index;
+
+ if ( min == max )
+ break;
+
+ if ( mid->unicode < unicode )
+ min = mid + 1;
+ else
+ max = mid - 1;
+ }
+
+ return 0xFFFF;
+ }
+
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+
+
+ static
+ const char* PS_Macintosh_Name( FT_UInt name_index )
+ {
+ if ( name_index >= 258 )
+ name_index = 0;
+
+ return standard_glyph_names[mac_standard_names[name_index]];
+ }
+
+
+ static
+ const char* PS_Standard_Strings( FT_UInt sid )
+ {
+ return ( sid < NUM_STD_GLYPHS ? t1_standard_glyphs[sid] : 0 );
+ }
+
+
+ static const PSNames_Interface psnames_interface =
+ {
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+ (PS_Unicode_Value_Func) PS_Unicode_Value,
+ (PS_Build_Unicodes_Func) PS_Build_Unicode_Table,
+ (PS_Lookup_Unicode_Func) PS_Lookup_Unicode,
+
+#else
+
+ 0,
+ 0,
+ 0,
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+
+ (PS_Macintosh_Name_Func) PS_Macintosh_Name,
+ (PS_Adobe_Std_Strings_Func)PS_Standard_Strings,
+
+ t1_standard_encoding,
+ t1_expert_encoding
+ };
+
+
+#endif /* !FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES */
+
+
+ const FT_Module_Class psnames_module_class =
+ {
+ 0, /* this is not a font driver, nor a renderer */
+ sizeof( FT_ModuleRec ),
+
+ "psnames", /* driver name */
+ 0x10000L, /* driver version */
+ 0x20000L, /* driver requires FreeType 2 or above */
+
+#ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
+ 0,
+#else
+ (void*)&psnames_interface, /* module specific interface */
+#endif
+
+ (FT_Module_Constructor)0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+ };
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* psmodule.h */
+/* */
+/* High-level PSNames module interface (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef PSDRIVER_H
+#define PSDRIVER_H
+
+#include <freetype/ftmodule.h>
+
+ FT_EXPORT_VAR( const FT_Module_Class ) psnames_module_class;
+
+#endif /* PSDRIVER_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* psnames.c */
+/* */
+/* FreeType PSNames module component (body only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <psmodule.c>
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* pstables.h */
+/* */
+/* PostScript glyph names (specification only). */
+/* */
+/* Copyright 2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /* this file has been generated automatically -- do not edit! */
+
+
+ static const char* standard_glyph_names[] =
+ {
+ ".null",
+ "CR",
+ "notequal",
+ "infinity",
+ "lessequal",
+ "greaterequal",
+ "partialdiff",
+ "summation",
+ "product",
+ "pi",
+ "integral",
+ "Omega",
+ "radical",
+ "approxequal",
+ "Delta",
+ "nbspace",
+ "lozenge",
+ "periodcentered",
+ "apple",
+ "lslash",
+ "franc",
+ "Gbreve",
+ "gbreve",
+ "Idot",
+ "Scedilla",
+ "scedilla",
+ "Cacute",
+ "cacute",
+ "Ccaron",
+ "ccaron",
+ "dmacron",
+ ".notdef",
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quoteright",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "quoteleft",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+ "braceright",
+ "asciitilde",
+ "exclamdown",
+ "cent",
+ "sterling",
+ "fraction",
+ "yen",
+ "florin",
+ "section",
+ "currency",
+ "quotesingle",
+ "quotedblleft",
+ "guillemotleft",
+ "guilsinglleft",
+ "guilsinglright",
+ "fi",
+ "fl",
+ "endash",
+ "dagger",
+ "daggerdbl",
+ "periodcenter",
+ "paragraph",
+ "bullet",
+ "quotesinglbase",
+ "quotedblbase",
+ "quotedblright",
+ "guillemotright",
+ "ellipsis",
+ "perthousand",
+ "questiondown",
+ "grave",
+ "acute",
+ "circumflex",
+ "tilde",
+ "macron",
+ "breve",
+ "dotaccent",
+ "dieresis",
+ "ring",
+ "cedilla",
+ "hungarumlaut",
+ "ogonek",
+ "caron",
+ "emdash",
+ "AE",
+ "ordfeminine",
+ "Lslash",
+ "Oslash",
+ "OE",
+ "ordmasculine",
+ "ae",
+ "dotlessi",
+ "Islash",
+ "oslash",
+ "oe",
+ "germandbls",
+ "onesuperior",
+ "logicalnot",
+ "mu",
+ "trademark",
+ "Eth",
+ "onehalf",
+ "plusminus",
+ "Thorn",
+ "onequarter",
+ "divide",
+ "brokenbar",
+ "degree",
+ "thorn",
+ "threequarters",
+ "twosuperior",
+ "registered",
+ "minus",
+ "eth",
+ "multiply",
+ "threesuperior",
+ "copyright",
+ "Aacute",
+ "Acircumflex",
+ "Adieresis",
+ "Agrave",
+ "Aring",
+ "Atilde",
+ "Ccedilla",
+ "Eacute",
+ "Ecircumflex",
+ "Edieresis",
+ "Egrave",
+ "Iacute",
+ "Icircumflex",
+ "Idieresis",
+ "Igrave",
+ "Ntilde",
+ "Oacute",
+ "Ocircumflex",
+ "Odieresis",
+ "Ograve",
+ "Otilde",
+ "Scaron",
+ "Uacute",
+ "Ucircumflex",
+ "Udieresis",
+ "Ugrave",
+ "Yacute",
+ "Ydieresis",
+ "Zcaron",
+ "aacute",
+ "acircumflex",
+ "adieresis",
+ "agrave",
+ "aring",
+ "atilde",
+ "ccedilla",
+ "eacute",
+ "ecircumflex",
+ "edieresis",
+ "egrave",
+ "iacute",
+ "icircumflex",
+ "idieresis",
+ "igrave",
+ "ntilde",
+ "oacute",
+ "ocircumflex",
+ "odieresis",
+ "ograve",
+ "otilde",
+ "scaron",
+ "uacute",
+ "ucircumflex",
+ "udieresis",
+ "ugrave",
+ "yacute",
+ "ydieresis",
+ "zcaron",
+ "exclamsmall",
+ "Hungarumlautsmall",
+ "dollaroldstyle",
+ "dollarsuperior",
+ "ampersandsmall",
+ "Acutesmall",
+ "parenleftsuperior",
+ "parenrightsuperior",
+ "twodotenleader",
+ "onedotenleader",
+ "zerooldstyle",
+ "oneoldstyle",
+ "twooldstyle",
+ "threeoldstyle",
+ "fouroldstyle",
+ "fiveoldstyle",
+ "sixoldstyle",
+ "sevenoldstyle",
+ "eightoldstyle",
+ "nineoldstyle",
+ "commasuperior",
+ "threequartersemdash",
+ "periodsuperior",
+ "questionsmall",
+ "asuperior",
+ "bsuperior",
+ "centsuperior",
+ "dsuperior",
+ "esuperior",
+ "isuperior",
+ "lsuperior",
+ "msuperior",
+ "nsuperior",
+ "osuperior",
+ "rsuperior",
+ "ssuperior",
+ "tsuperior",
+ "ff",
+ "ffi",
+ "ffl",
+ "parenleftinferior",
+ "parenrightinferior",
+ "Circumflexsmall",
+ "hyphensuperior",
+ "Gravesmall",
+ "Asmall",
+ "Bsmall",
+ "Csmall",
+ "Dsmall",
+ "Esmall",
+ "Fsmall",
+ "Gsmall",
+ "Hsmall",
+ "Ismall",
+ "Jsmall",
+ "Ksmall",
+ "Lsmall",
+ "Msmall",
+ "Nsmall",
+ "Osmall",
+ "Psmall",
+ "Qsmall",
+ "Rsmall",
+ "Ssmall",
+ "Tsmall",
+ "Usmall",
+ "Vsmall",
+ "Wsmall",
+ "Xsmall",
+ "Ysmall",
+ "Zsmall",
+ "colonmonetary",
+ "onefitted",
+ "rupiah",
+ "Tildesmall",
+ "exclamdownsmall",
+ "centoldstyle",
+ "Lslashsmall",
+ "Scaronsmall",
+ "Zcaronsmall",
+ "Dieresissmall",
+ "Brevesmall",
+ "Caronsmall",
+ "Dotaccentsmall",
+ "Macronsmall",
+ "figuredash",
+ "hypheninferior",
+ "Ogoneksmall",
+ "Ringsmall",
+ "Cedillasmall",
+ "questiondownsmall",
+ "oneeighth",
+ "threeeighths",
+ "fiveeighths",
+ "seveneighths",
+ "onethird",
+ "twothirds",
+ "zerosuperior",
+ "foursuperior",
+ "fivesuperior",
+ "sixsuperior",
+ "sevensuperior",
+ "eightsuperior",
+ "ninesuperior",
+ "zeroinferior",
+ "oneinferior",
+ "twoinferior",
+ "threeinferior",
+ "fourinferior",
+ "fiveinferior",
+ "sixinferior",
+ "seveninferior",
+ "eightinferior",
+ "nineinferior",
+ "centinferior",
+ "dollarinferior",
+ "periodinferior",
+ "commainferior",
+ "Agravesmall",
+ "Aacutesmall",
+ "Acircumflexsmall",
+ "Atildesmall",
+ "Adieresissmall",
+ "Aringsmall",
+ "AEsmall",
+ "Ccedillasmall",
+ "Egravesmall",
+ "Eacutesmall",
+ "Ecircumflexsmall",
+ "Edieresissmall",
+ "Igravesmall",
+ "Iacutesmall",
+ "Icircumflexsmall",
+ "Idieresissmall",
+ "Ethsmall",
+ "Ntildesmall",
+ "Ogravesmall",
+ "Oacutesmall",
+ "Ocircumflexsmall",
+ "Otildesmall",
+ "Odieresissmall",
+ "OEsmall",
+ "Oslashsmall",
+ "Ugravesmall",
+ "Uacautesmall",
+ "Ucircumflexsmall",
+ "Udieresissmall",
+ "Yacutesmall",
+ "Thornsmall",
+ "Ydieresissmall",
+ "001.000",
+ "001.001",
+ "001.002",
+ "001.003",
+ "Black",
+ "Bold",
+ "Book",
+ "Light",
+ "Medium",
+ "Regular",
+ "Roman",
+ "Semibold",
+
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+ "AEacute",
+ "Abreve",
+ "Acute",
+ "Alpha",
+ "Alphatonos",
+ "Amacron",
+ "Aogonek",
+ "Aringacute",
+ "Beta",
+ "Caron",
+ "Ccircumflex",
+ "Cdotaccent",
+ "Chi",
+ "Dcaron",
+ "Dcroat",
+ "Dieresis",
+ "DieresisAcute",
+ "DieresisGrave",
+ "Ebreve",
+ "Ecaron",
+ "Edotaccent",
+ "Emacron",
+ "Eng",
+ "Eogonek",
+ "Epsilon",
+ "Epsilontonos",
+ "Eta",
+ "Etatonos",
+ "Euro",
+ "Gamma",
+ "Gcaron",
+ "Gcircumflex",
+ "Gcommaaccent",
+ "Gdotaccent",
+ "Grave",
+ "H18533",
+ "H18543",
+ "H18551",
+ "H22073",
+ "Hbar",
+ "Hcircumflex",
+ "Hungarumlaut",
+ "IJ",
+ "Ibreve",
+ "Idotaccent",
+ "Ifraktur",
+ "Imacron",
+ "Iogonek",
+ "Iota",
+ "Iotadieresis",
+ "Iotatonos",
+ "Itilde",
+ "Jcircumflex",
+ "Kappa",
+ "Kcommaaccent",
+ "LL",
+ "Lacute",
+ "Lambda",
+ "Lcaron",
+ "Lcommaaccent",
+ "Ldot",
+ "Macron",
+ "Mu",
+ "Nacute",
+ "Ncaron",
+ "Ncommaaccent",
+ "Nu",
+ "Obreve",
+ "Ohorn",
+ "Ohungarumlaut",
+ "Omacron",
+ "Omegatonos",
+ "Omicron",
+ "Omicrontonos",
+ "Oslashacute",
+ "Phi",
+ "Pi",
+ "Psi",
+ "Racute",
+ "Rcaron",
+ "Rcommaaccent",
+ "Rfraktur",
+ "Rho",
+ "SF010000",
+ "SF020000",
+ "SF030000",
+ "SF040000",
+ "SF050000",
+ "SF060000",
+ "SF070000",
+ "SF080000",
+ "SF090000",
+ "SF100000",
+ "SF110000",
+ "SF190000",
+ "SF200000",
+ "SF210000",
+ "SF220000",
+ "SF230000",
+ "SF240000",
+ "SF250000",
+ "SF260000",
+ "SF270000",
+ "SF280000",
+ "SF360000",
+ "SF370000",
+ "SF380000",
+ "SF390000",
+ "SF400000",
+ "SF410000",
+ "SF420000",
+ "SF430000",
+ "SF440000",
+ "SF450000",
+ "SF460000",
+ "SF470000",
+ "SF480000",
+ "SF490000",
+ "SF500000",
+ "SF510000",
+ "SF520000",
+ "SF530000",
+ "SF540000",
+ "Sacute",
+ "Scircumflex",
+ "Scommaaccent",
+ "Sigma",
+ "Tau",
+ "Tbar",
+ "Tcaron",
+ "Tcommaaccent",
+ "Tcommaaccent",
+ "Theta",
+ "Uacutesmall",
+ "Ubreve",
+ "Uhorn",
+ "Uhungarumlaut",
+ "Umacron",
+ "Uogonek",
+ "Upsilon",
+ "Upsilon1",
+ "Upsilondieresis",
+ "Upsilontonos",
+ "Uring",
+ "Utilde",
+ "Wacute",
+ "Wcircumflex",
+ "Wdieresis",
+ "Wgrave",
+ "Xi",
+ "Ycircumflex",
+ "Ygrave",
+ "Zacute",
+ "Zdotaccent",
+ "Zeta",
+ "abreve",
+ "acutecomb",
+ "aeacute",
+ "afii00208",
+ "afii10017",
+ "afii10018",
+ "afii10019",
+ "afii10020",
+ "afii10021",
+ "afii10022",
+ "afii10023",
+ "afii10024",
+ "afii10025",
+ "afii10026",
+ "afii10027",
+ "afii10028",
+ "afii10029",
+ "afii10030",
+ "afii10031",
+ "afii10032",
+ "afii10033",
+ "afii10034",
+ "afii10035",
+ "afii10036",
+ "afii10037",
+ "afii10038",
+ "afii10039",
+ "afii10040",
+ "afii10041",
+ "afii10042",
+ "afii10043",
+ "afii10044",
+ "afii10045",
+ "afii10046",
+ "afii10047",
+ "afii10048",
+ "afii10049",
+ "afii10050",
+ "afii10051",
+ "afii10052",
+ "afii10053",
+ "afii10054",
+ "afii10055",
+ "afii10056",
+ "afii10057",
+ "afii10058",
+ "afii10059",
+ "afii10060",
+ "afii10061",
+ "afii10062",
+ "afii10063",
+ "afii10064",
+ "afii10065",
+ "afii10066",
+ "afii10067",
+ "afii10068",
+ "afii10069",
+ "afii10070",
+ "afii10071",
+ "afii10072",
+ "afii10073",
+ "afii10074",
+ "afii10075",
+ "afii10076",
+ "afii10077",
+ "afii10078",
+ "afii10079",
+ "afii10080",
+ "afii10081",
+ "afii10082",
+ "afii10083",
+ "afii10084",
+ "afii10085",
+ "afii10086",
+ "afii10087",
+ "afii10088",
+ "afii10089",
+ "afii10090",
+ "afii10091",
+ "afii10092",
+ "afii10093",
+ "afii10094",
+ "afii10095",
+ "afii10096",
+ "afii10097",
+ "afii10098",
+ "afii10099",
+ "afii10100",
+ "afii10101",
+ "afii10102",
+ "afii10103",
+ "afii10104",
+ "afii10105",
+ "afii10106",
+ "afii10107",
+ "afii10108",
+ "afii10109",
+ "afii10110",
+ "afii10145",
+ "afii10146",
+ "afii10147",
+ "afii10148",
+ "afii10192",
+ "afii10193",
+ "afii10194",
+ "afii10195",
+ "afii10196",
+ "afii10831",
+ "afii10832",
+ "afii10846",
+ "afii299",
+ "afii300",
+ "afii301",
+ "afii57381",
+ "afii57388",
+ "afii57392",
+ "afii57393",
+ "afii57394",
+ "afii57395",
+ "afii57396",
+ "afii57397",
+ "afii57398",
+ "afii57399",
+ "afii57400",
+ "afii57401",
+ "afii57403",
+ "afii57407",
+ "afii57409",
+ "afii57410",
+ "afii57411",
+ "afii57412",
+ "afii57413",
+ "afii57414",
+ "afii57415",
+ "afii57416",
+ "afii57417",
+ "afii57418",
+ "afii57419",
+ "afii57420",
+ "afii57421",
+ "afii57422",
+ "afii57423",
+ "afii57424",
+ "afii57425",
+ "afii57426",
+ "afii57427",
+ "afii57428",
+ "afii57429",
+ "afii57430",
+ "afii57431",
+ "afii57432",
+ "afii57433",
+ "afii57434",
+ "afii57440",
+ "afii57441",
+ "afii57442",
+ "afii57443",
+ "afii57444",
+ "afii57445",
+ "afii57446",
+ "afii57448",
+ "afii57449",
+ "afii57450",
+ "afii57451",
+ "afii57452",
+ "afii57453",
+ "afii57454",
+ "afii57455",
+ "afii57456",
+ "afii57457",
+ "afii57458",
+ "afii57470",
+ "afii57505",
+ "afii57506",
+ "afii57507",
+ "afii57508",
+ "afii57509",
+ "afii57511",
+ "afii57512",
+ "afii57513",
+ "afii57514",
+ "afii57519",
+ "afii57534",
+ "afii57636",
+ "afii57645",
+ "afii57658",
+ "afii57664",
+ "afii57665",
+ "afii57666",
+ "afii57667",
+ "afii57668",
+ "afii57669",
+ "afii57670",
+ "afii57671",
+ "afii57672",
+ "afii57673",
+ "afii57674",
+ "afii57675",
+ "afii57676",
+ "afii57677",
+ "afii57678",
+ "afii57679",
+ "afii57680",
+ "afii57681",
+ "afii57682",
+ "afii57683",
+ "afii57684",
+ "afii57685",
+ "afii57686",
+ "afii57687",
+ "afii57688",
+ "afii57689",
+ "afii57690",
+ "afii57694",
+ "afii57695",
+ "afii57700",
+ "afii57705",
+ "afii57716",
+ "afii57717",
+ "afii57718",
+ "afii57723",
+ "afii57793",
+ "afii57794",
+ "afii57795",
+ "afii57796",
+ "afii57797",
+ "afii57798",
+ "afii57799",
+ "afii57800",
+ "afii57801",
+ "afii57802",
+ "afii57803",
+ "afii57804",
+ "afii57806",
+ "afii57807",
+ "afii57839",
+ "afii57841",
+ "afii57842",
+ "afii57929",
+ "afii61248",
+ "afii61289",
+ "afii61352",
+ "afii61573",
+ "afii61574",
+ "afii61575",
+ "afii61664",
+ "afii63167",
+ "afii64937",
+ "aleph",
+ "alpha",
+ "alphatonos",
+ "amacron",
+ "angle",
+ "angleleft",
+ "angleright",
+ "anoteleia",
+ "aogonek",
+ "aringacute",
+ "arrowboth",
+ "arrowdblboth",
+ "arrowdbldown",
+ "arrowdblleft",
+ "arrowdblright",
+ "arrowdblup",
+ "arrowdown",
+ "arrowhorizex",
+ "arrowleft",
+ "arrowright",
+ "arrowup",
+ "arrowupdn",
+ "arrowupdnbse",
+ "arrowvertex",
+ "asteriskmath",
+ "beta",
+ "block",
+ "braceex",
+ "braceleftbt",
+ "braceleftmid",
+ "bracelefttp",
+ "bracerightbt",
+ "bracerightmid",
+ "bracerighttp",
+ "bracketleftbt",
+ "bracketleftex",
+ "bracketlefttp",
+ "bracketrightbt",
+ "bracketrightex",
+ "bracketrighttp",
+ "carriagereturn",
+ "ccircumflex",
+ "cdotaccent",
+ "chi",
+ "circle",
+ "circlemultiply",
+ "circleplus",
+ "club",
+ "commaaccent",
+ "congruent",
+ "copyrightsans",
+ "copyrightserif",
+ "cyrBreve",
+ "cyrFlex",
+ "cyrbreve",
+ "cyrflex",
+ "dblGrave",
+ "dblgrave",
+ "dcaron",
+ "dcroat",
+ "delta",
+ "diamond",
+ "dieresisacute",
+ "dieresisgrave",
+ "dieresistonos",
+ "dkshade",
+ "dnblock",
+ "dong",
+ "dotbelowcomb",
+ "dotlessj",
+ "dotmath",
+ "ebreve",
+ "ecaron",
+ "edotaccent",
+ "element",
+ "emacron",
+ "emptyset",
+ "eng",
+ "eogonek",
+ "epsilon",
+ "epsilontonos",
+ "equivalence",
+ "estimated",
+ "eta",
+ "etatonos",
+ "exclamdbl",
+ "existential",
+ "female",
+ "filledbox",
+ "filledrect",
+ "gamma",
+ "gcaron",
+ "gcircumflex",
+ "gcommaaccent",
+ "gdotaccent",
+ "gradient",
+ "gravecomb",
+ "hbar",
+ "hcircumflex",
+ "heart",
+ "hookabovecomb",
+ "house",
+ "ibreve",
+ "ij",
+ "imacron",
+ "integralbt",
+ "integralex",
+ "integraltp",
+ "intersection",
+ "invbullet",
+ "invcircle",
+ "invsmileface",
+ "iogonek",
+ "iota",
+ "iotadieresis",
+ "iotadieresistonos",
+ "iotatonos",
+ "itilde",
+ "jcircumflex",
+ "kappa",
+ "kcommaaccent",
+ "kgreenlandic",
+ "lacute",
+ "lambda",
+ "lcaron",
+ "lcommaaccent",
+ "ldot",
+ "lfblock",
+ "lira",
+ "ll",
+ "logicaland",
+ "logicalor",
+ "longs",
+ "ltshade",
+ "male",
+ "minute",
+ "musicalnote",
+ "musicalnotedbl",
+ "nacute",
+ "napostrophe",
+ "ncaron",
+ "ncommaaccent",
+ "notelement",
+ "notsubset",
+ "nu",
+ "obreve",
+ "ohorn",
+ "ohungarumlaut",
+ "omacron",
+ "omega",
+ "omega1",
+ "omegatonos",
+ "omicron",
+ "omicrontonos",
+ "openbullet",
+ "orthogonal",
+ "oslashacute",
+ "parenleftbt",
+ "parenleftex",
+ "parenlefttp",
+ "parenrightbt",
+ "parenrightex",
+ "parenrighttp",
+ "perpendicular",
+ "peseta",
+ "phi",
+ "phi1",
+ "prescription",
+ "propersubset",
+ "propersuperset",
+ "proportional",
+ "psi",
+ "quotereversed",
+ "racute",
+ "radicalex",
+ "rcaron",
+ "rcommaaccent",
+ "reflexsubset",
+ "reflexsuperset",
+ "registersans",
+ "registerserif",
+ "revlogicalnot",
+ "rho",
+ "rtblock",
+ "sacute",
+ "scircumflex",
+ "scommaaccent",
+ "second",
+ "shade",
+ "sigma",
+ "sigma1",
+ "similar",
+ "smileface",
+ "spade",
+ "suchthat",
+ "sun",
+ "tau",
+ "tbar",
+ "tcaron",
+ "tcommaaccent",
+ "tcommaaccent",
+ "therefore",
+ "theta",
+ "theta1",
+ "tildecomb",
+ "tonos",
+ "trademarksans",
+ "trademarkserif",
+ "triagdn",
+ "triaglf",
+ "triagrt",
+ "triagup",
+ "ubreve",
+ "uhorn",
+ "uhungarumlaut",
+ "umacron",
+ "underscoredbl",
+ "union",
+ "universal",
+ "uogonek",
+ "upblock",
+ "upsilon",
+ "upsilondieresis",
+ "upsilondieresistonos",
+ "upsilontonos",
+ "uring",
+ "utilde",
+ "wacute",
+ "wcircumflex",
+ "wdieresis",
+ "weierstrass",
+ "wgrave",
+ "xi",
+ "ycircumflex",
+ "ygrave",
+ "zacute",
+ "zdotaccent",
+ "zeta",
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+
+ 0
+ };
+
+
+ static const char** t1_standard_glyphs = standard_glyph_names + 31;
+
+
+#define NUM_STD_GLYPHS 391
+
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+#define NUM_ADOBE_GLYPHS 1032
+#else
+#define NUM_ADOBE_GLYPHS 391
+#endif
+
+
+ static const unsigned short mac_standard_names[259] =
+ {
+ 0,
+ 0,
+ 1,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 104,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 60,
+ 61,
+ 62,
+ 63,
+ 64,
+ 124,
+ 66,
+ 67,
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 74,
+ 75,
+ 76,
+ 77,
+ 78,
+ 79,
+ 80,
+ 81,
+ 82,
+ 83,
+ 84,
+ 85,
+ 86,
+ 87,
+ 88,
+ 89,
+ 90,
+ 91,
+ 92,
+ 93,
+ 94,
+ 95,
+ 173,
+ 175,
+ 177,
+ 178,
+ 186,
+ 189,
+ 195,
+ 200,
+ 203,
+ 201,
+ 202,
+ 205,
+ 204,
+ 206,
+ 207,
+ 210,
+ 208,
+ 209,
+ 211,
+ 214,
+ 212,
+ 213,
+ 215,
+ 216,
+ 219,
+ 217,
+ 218,
+ 220,
+ 222,
+ 225,
+ 223,
+ 224,
+ 112,
+ 161,
+ 97,
+ 98,
+ 102,
+ 116,
+ 115,
+ 149,
+ 165,
+ 170,
+ 153,
+ 125,
+ 131,
+ 2,
+ 138,
+ 141,
+ 3,
+ 156,
+ 4,
+ 5,
+ 100,
+ 152,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 139,
+ 143,
+ 11,
+ 144,
+ 147,
+ 123,
+ 96,
+ 151,
+ 12,
+ 101,
+ 13,
+ 14,
+ 106,
+ 120,
+ 121,
+ 15,
+ 174,
+ 176,
+ 191,
+ 142,
+ 148,
+ 111,
+ 137,
+ 105,
+ 119,
+ 65,
+ 8,
+ 159,
+ 16,
+ 227,
+ 198,
+ 99,
+ 103,
+ 107,
+ 108,
+ 109,
+ 110,
+ 113,
+ 17,
+ 117,
+ 118,
+ 122,
+ 172,
+ 179,
+ 171,
+ 180,
+ 181,
+ 182,
+ 183,
+ 184,
+ 185,
+ 187,
+ 188,
+ 18,
+ 190,
+ 193,
+ 194,
+ 196,
+ 145,
+ 126,
+ 127,
+ 128,
+ 129,
+ 130,
+ 132,
+ 133,
+ 134,
+ 135,
+ 136,
+ 140,
+ 19,
+ 192,
+ 221,
+ 199,
+ 228,
+ 160,
+ 154,
+ 167,
+ 197,
+ 226,
+ 157,
+ 162,
+ 166,
+ 168,
+ 150,
+ 164,
+ 169,
+ 155,
+ 158,
+ 163,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 0
+ };
+
+
+
+ static const unsigned short names_to_unicode[1033] =
+ {
+ 0,
+ 0x0020,
+ 0x0021,
+ 0x0022,
+ 0x0023,
+ 0x0024,
+ 0x0025,
+ 0x0026,
+ 0x2019,
+ 0x0028,
+ 0x0029,
+ 0x002A,
+ 0x002B,
+ 0x002C,
+ 0x002D,
+ 0x002E,
+ 0x002F,
+ 0x0030,
+ 0x0031,
+ 0x0032,
+ 0x0033,
+ 0x0034,
+ 0x0035,
+ 0x0036,
+ 0x0037,
+ 0x0038,
+ 0x0039,
+ 0x003A,
+ 0x003B,
+ 0x003C,
+ 0x003D,
+ 0x003E,
+ 0x003F,
+ 0x0040,
+ 0x0041,
+ 0x0042,
+ 0x0043,
+ 0x0044,
+ 0x0045,
+ 0x0046,
+ 0x0047,
+ 0x0048,
+ 0x0049,
+ 0x004A,
+ 0x004B,
+ 0x004C,
+ 0x004D,
+ 0x004E,
+ 0x004F,
+ 0x0050,
+ 0x0051,
+ 0x0052,
+ 0x0053,
+ 0x0054,
+ 0x0055,
+ 0x0056,
+ 0x0057,
+ 0x0058,
+ 0x0059,
+ 0x005A,
+ 0x005B,
+ 0x005C,
+ 0x005D,
+ 0x005E,
+ 0x005F,
+ 0x2018,
+ 0x0061,
+ 0x0062,
+ 0x0063,
+ 0x0064,
+ 0x0065,
+ 0x0066,
+ 0x0067,
+ 0x0068,
+ 0x0069,
+ 0x006A,
+ 0x006B,
+ 0x006C,
+ 0x006D,
+ 0x006E,
+ 0x006F,
+ 0x0070,
+ 0x0071,
+ 0x0072,
+ 0x0073,
+ 0x0074,
+ 0x0075,
+ 0x0076,
+ 0x0077,
+ 0x0078,
+ 0x0079,
+ 0x007A,
+ 0x007B,
+ 0x007C,
+ 0x007D,
+ 0x007E,
+ 0x00A1,
+ 0x00A2,
+ 0x00A3,
+ 0x2044,
+ 0x00A5,
+ 0x0192,
+ 0x00A7,
+ 0x00A4,
+ 0x0027,
+ 0x201C,
+ 0x00AB,
+ 0x2039,
+ 0x203A,
+ 0xFB01,
+ 0xFB02,
+ 0x2013,
+ 0x2020,
+ 0x2021,
+ 0,
+ 0x00B6,
+ 0x2022,
+ 0x201A,
+ 0x201E,
+ 0x201D,
+ 0x00BB,
+ 0x2026,
+ 0x2030,
+ 0x00BF,
+ 0x0060,
+ 0x00B4,
+ 0x02C6,
+ 0x02DC,
+ 0x00AF,
+ 0x02D8,
+ 0x02D9,
+ 0x00A8,
+ 0x02DA,
+ 0x00B8,
+ 0x02DD,
+ 0x02DB,
+ 0x02C7,
+ 0x2014,
+ 0x00C6,
+ 0x00AA,
+ 0x0141,
+ 0x00D8,
+ 0x0152,
+ 0x00BA,
+ 0x00E6,
+ 0x0131,
+ 0,
+ 0x00F8,
+ 0x0153,
+ 0x00DF,
+ 0x00B9,
+ 0x00AC,
+ 0x00B5,
+ 0x2122,
+ 0x00D0,
+ 0x00BD,
+ 0x00B1,
+ 0x00DE,
+ 0x00BC,
+ 0x00F7,
+ 0x00A6,
+ 0x00B0,
+ 0x00FE,
+ 0x00BE,
+ 0x00B2,
+ 0x00AE,
+ 0x2212,
+ 0x00F0,
+ 0x00D7,
+ 0x00B3,
+ 0x00A9,
+ 0x00C1,
+ 0x00C2,
+ 0x00C4,
+ 0x00C0,
+ 0x00C5,
+ 0x00C3,
+ 0x00C7,
+ 0x00C9,
+ 0x00CA,
+ 0x00CB,
+ 0x00C8,
+ 0x00CD,
+ 0x00CE,
+ 0x00CF,
+ 0x00CC,
+ 0x00D1,
+ 0x00D3,
+ 0x00D4,
+ 0x00D6,
+ 0x00D2,
+ 0x00D5,
+ 0x0160,
+ 0x00DA,
+ 0x00DB,
+ 0x00DC,
+ 0x00D9,
+ 0x00DD,
+ 0x0178,
+ 0x017D,
+ 0x00E1,
+ 0x00E2,
+ 0x00E4,
+ 0x00E0,
+ 0x00E5,
+ 0x00E3,
+ 0x00E7,
+ 0x00E9,
+ 0x00EA,
+ 0x00EB,
+ 0x00E8,
+ 0x00ED,
+ 0x00EE,
+ 0x00EF,
+ 0x00EC,
+ 0x00F1,
+ 0x00F3,
+ 0x00F4,
+ 0x00F6,
+ 0x00F2,
+ 0x00F5,
+ 0x0161,
+ 0x00FA,
+ 0x00FB,
+ 0x00FC,
+ 0x00F9,
+ 0x00FD,
+ 0x00FF,
+ 0x017E,
+ 0xF721,
+ 0xF6F8,
+ 0xF724,
+ 0xF6E4,
+ 0xF726,
+ 0xF7B4,
+ 0x207D,
+ 0x207E,
+ 0x2025,
+ 0x2024,
+ 0xF730,
+ 0xF731,
+ 0xF732,
+ 0xF733,
+ 0xF734,
+ 0xF735,
+ 0xF736,
+ 0xF737,
+ 0xF738,
+ 0xF739,
+ 0xF6E2,
+ 0xF6DE,
+ 0xF6E8,
+ 0xF73F,
+ 0xF6E9,
+ 0xF6EA,
+ 0xF6E0,
+ 0xF6EB,
+ 0xF6EC,
+ 0xF6ED,
+ 0xF6EE,
+ 0xF6EF,
+ 0x207F,
+ 0xF6F0,
+ 0xF6F1,
+ 0xF6F2,
+ 0xF6F3,
+ 0xFB00,
+ 0xFB03,
+ 0xFB04,
+ 0x208D,
+ 0x208E,
+ 0xF6F6,
+ 0xF6E6,
+ 0xF760,
+ 0xF761,
+ 0xF762,
+ 0xF763,
+ 0xF764,
+ 0xF765,
+ 0xF766,
+ 0xF767,
+ 0xF768,
+ 0xF769,
+ 0xF76A,
+ 0xF76B,
+ 0xF76C,
+ 0xF76D,
+ 0xF76E,
+ 0xF76F,
+ 0xF770,
+ 0xF771,
+ 0xF772,
+ 0xF773,
+ 0xF774,
+ 0xF775,
+ 0xF776,
+ 0xF777,
+ 0xF778,
+ 0xF779,
+ 0xF77A,
+ 0x20A1,
+ 0xF6DC,
+ 0xF6DD,
+ 0xF6FE,
+ 0xF7A1,
+ 0xF7A2,
+ 0xF6F9,
+ 0xF6FD,
+ 0xF6FF,
+ 0xF7A8,
+ 0xF6F4,
+ 0xF6F5,
+ 0xF6F7,
+ 0xF7AF,
+ 0x2012,
+ 0xF6E5,
+ 0xF6FB,
+ 0xF6FC,
+ 0xF7B8,
+ 0xF7BF,
+ 0x215B,
+ 0x215C,
+ 0x215D,
+ 0x215E,
+ 0x2153,
+ 0x2154,
+ 0x2070,
+ 0x2074,
+ 0x2075,
+ 0x2076,
+ 0x2077,
+ 0x2078,
+ 0x2079,
+ 0x2080,
+ 0x2081,
+ 0x2082,
+ 0x2083,
+ 0x2084,
+ 0x2085,
+ 0x2086,
+ 0x2087,
+ 0x2088,
+ 0x2089,
+ 0xF6DF,
+ 0xF6E3,
+ 0xF6E7,
+ 0xF6E1,
+ 0xF7E0,
+ 0xF7E1,
+ 0xF7E2,
+ 0xF7E3,
+ 0xF7E4,
+ 0xF7E5,
+ 0xF7E6,
+ 0xF7E7,
+ 0xF7E8,
+ 0xF7E9,
+ 0xF7EA,
+ 0xF7EB,
+ 0xF7EC,
+ 0xF7ED,
+ 0xF7EE,
+ 0xF7EF,
+ 0xF7F0,
+ 0xF7F1,
+ 0xF7F2,
+ 0xF7F3,
+ 0xF7F4,
+ 0xF7F5,
+ 0xF7F6,
+ 0xF6FA,
+ 0xF7F8,
+ 0xF7F9,
+ 0,
+ 0xF7FB,
+ 0xF7FC,
+ 0xF7FD,
+ 0xF7FE,
+ 0xF7FF,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+ 0x01FC,
+ 0x0102,
+ 0xF6C9,
+ 0x0391,
+ 0x0386,
+ 0x0100,
+ 0x0104,
+ 0x01FA,
+ 0x0392,
+ 0xF6CA,
+ 0x0108,
+ 0x010A,
+ 0x03A7,
+ 0x010E,
+ 0x0110,
+ 0xF6CB,
+ 0xF6CC,
+ 0xF6CD,
+ 0x0114,
+ 0x011A,
+ 0x0116,
+ 0x0112,
+ 0x014A,
+ 0x0118,
+ 0x0395,
+ 0x0388,
+ 0x0397,
+ 0x0389,
+ 0x20AC,
+ 0x0393,
+ 0x01E6,
+ 0x011C,
+ 0x0122,
+ 0x0120,
+ 0xF6CE,
+ 0x25CF,
+ 0x25AA,
+ 0x25AB,
+ 0x25A1,
+ 0x0126,
+ 0x0124,
+ 0xF6CF,
+ 0x0132,
+ 0x012C,
+ 0x0130,
+ 0x2111,
+ 0x012A,
+ 0x012E,
+ 0x0399,
+ 0x03AA,
+ 0x038A,
+ 0x0128,
+ 0x0134,
+ 0x039A,
+ 0x0136,
+ 0xF6BF,
+ 0x0139,
+ 0x039B,
+ 0x013D,
+ 0x013B,
+ 0x013F,
+ 0xF6D0,
+ 0x039C,
+ 0x0143,
+ 0x0147,
+ 0x0145,
+ 0x039D,
+ 0x014E,
+ 0x01A0,
+ 0x0150,
+ 0x014C,
+ 0x038F,
+ 0x039F,
+ 0x038C,
+ 0x01FE,
+ 0x03A6,
+ 0x03A0,
+ 0x03A8,
+ 0x0154,
+ 0x0158,
+ 0x0156,
+ 0x211C,
+ 0x03A1,
+ 0x250C,
+ 0x2514,
+ 0x2510,
+ 0x2518,
+ 0x253C,
+ 0x252C,
+ 0x2534,
+ 0x251C,
+ 0x2524,
+ 0x2500,
+ 0x2502,
+ 0x2561,
+ 0x2562,
+ 0x2556,
+ 0x2555,
+ 0x2563,
+ 0x2551,
+ 0x2557,
+ 0x255D,
+ 0x255C,
+ 0x255B,
+ 0x255E,
+ 0x255F,
+ 0x255A,
+ 0x2554,
+ 0x2569,
+ 0x2566,
+ 0x2560,
+ 0x2550,
+ 0x256C,
+ 0x2567,
+ 0x2568,
+ 0x2564,
+ 0x2565,
+ 0x2559,
+ 0x2558,
+ 0x2552,
+ 0x2553,
+ 0x256B,
+ 0x256A,
+ 0x015A,
+ 0x015C,
+ 0x0218,
+ 0x03A3,
+ 0x03A4,
+ 0x0166,
+ 0x0164,
+ 0x0162,
+ 0x0162,
+ 0x0398,
+ 0xF7FA,
+ 0x016C,
+ 0x01AF,
+ 0x0170,
+ 0x016A,
+ 0x0172,
+ 0x03A5,
+ 0x03D2,
+ 0x03AB,
+ 0x038E,
+ 0x016E,
+ 0x0168,
+ 0x1E82,
+ 0x0174,
+ 0x1E84,
+ 0x1E80,
+ 0x039E,
+ 0x0176,
+ 0x1EF2,
+ 0x0179,
+ 0x017B,
+ 0x0396,
+ 0x0103,
+ 0x0301,
+ 0x01FD,
+ 0x2015,
+ 0x0410,
+ 0x0411,
+ 0x0412,
+ 0x0413,
+ 0x0414,
+ 0x0415,
+ 0x0401,
+ 0x0416,
+ 0x0417,
+ 0x0418,
+ 0x0419,
+ 0x041A,
+ 0x041B,
+ 0x041C,
+ 0x041D,
+ 0x041E,
+ 0x041F,
+ 0x0420,
+ 0x0421,
+ 0x0422,
+ 0x0423,
+ 0x0424,
+ 0x0425,
+ 0x0426,
+ 0x0427,
+ 0x0428,
+ 0x0429,
+ 0x042A,
+ 0x042B,
+ 0x042C,
+ 0x042D,
+ 0x042E,
+ 0x042F,
+ 0x0490,
+ 0x0402,
+ 0x0403,
+ 0x0404,
+ 0x0405,
+ 0x0406,
+ 0x0407,
+ 0x0408,
+ 0x0409,
+ 0x040A,
+ 0x040B,
+ 0x040C,
+ 0x040E,
+ 0xF6C4,
+ 0xF6C5,
+ 0x0430,
+ 0x0431,
+ 0x0432,
+ 0x0433,
+ 0x0434,
+ 0x0435,
+ 0x0451,
+ 0x0436,
+ 0x0437,
+ 0x0438,
+ 0x0439,
+ 0x043A,
+ 0x043B,
+ 0x043C,
+ 0x043D,
+ 0x043E,
+ 0x043F,
+ 0x0440,
+ 0x0441,
+ 0x0442,
+ 0x0443,
+ 0x0444,
+ 0x0445,
+ 0x0446,
+ 0x0447,
+ 0x0448,
+ 0x0449,
+ 0x044A,
+ 0x044B,
+ 0x044C,
+ 0x044D,
+ 0x044E,
+ 0x044F,
+ 0x0491,
+ 0x0452,
+ 0x0453,
+ 0x0454,
+ 0x0455,
+ 0x0456,
+ 0x0457,
+ 0x0458,
+ 0x0459,
+ 0x045A,
+ 0x045B,
+ 0x045C,
+ 0x045E,
+ 0x040F,
+ 0x0462,
+ 0x0472,
+ 0x0474,
+ 0xF6C6,
+ 0x045F,
+ 0x0463,
+ 0x0473,
+ 0x0475,
+ 0xF6C7,
+ 0xF6C8,
+ 0x04D9,
+ 0x200E,
+ 0x200F,
+ 0x200D,
+ 0x066A,
+ 0x060C,
+ 0x0660,
+ 0x0661,
+ 0x0662,
+ 0x0663,
+ 0x0664,
+ 0x0665,
+ 0x0666,
+ 0x0667,
+ 0x0668,
+ 0x0669,
+ 0x061B,
+ 0x061F,
+ 0x0621,
+ 0x0622,
+ 0x0623,
+ 0x0624,
+ 0x0625,
+ 0x0626,
+ 0x0627,
+ 0x0628,
+ 0x0629,
+ 0x062A,
+ 0x062B,
+ 0x062C,
+ 0x062D,
+ 0x062E,
+ 0x062F,
+ 0x0630,
+ 0x0631,
+ 0x0632,
+ 0x0633,
+ 0x0634,
+ 0x0635,
+ 0x0636,
+ 0x0637,
+ 0x0638,
+ 0x0639,
+ 0x063A,
+ 0x0640,
+ 0x0641,
+ 0x0642,
+ 0x0643,
+ 0x0644,
+ 0x0645,
+ 0x0646,
+ 0x0648,
+ 0x0649,
+ 0x064A,
+ 0x064B,
+ 0x064C,
+ 0x064D,
+ 0x064E,
+ 0x064F,
+ 0x0650,
+ 0x0651,
+ 0x0652,
+ 0x0647,
+ 0x06A4,
+ 0x067E,
+ 0x0686,
+ 0x0698,
+ 0x06AF,
+ 0x0679,
+ 0x0688,
+ 0x0691,
+ 0x06BA,
+ 0x06D2,
+ 0x06D5,
+ 0x20AA,
+ 0x05BE,
+ 0x05C3,
+ 0x05D0,
+ 0x05D1,
+ 0x05D2,
+ 0x05D3,
+ 0x05D4,
+ 0x05D5,
+ 0x05D6,
+ 0x05D7,
+ 0x05D8,
+ 0x05D9,
+ 0x05DA,
+ 0x05DB,
+ 0x05DC,
+ 0x05DD,
+ 0x05DE,
+ 0x05DF,
+ 0x05E0,
+ 0x05E1,
+ 0x05E2,
+ 0x05E3,
+ 0x05E4,
+ 0x05E5,
+ 0x05E6,
+ 0x05E7,
+ 0x05E8,
+ 0x05E9,
+ 0x05EA,
+ 0xFB2A,
+ 0xFB2B,
+ 0xFB4B,
+ 0xFB1F,
+ 0x05F0,
+ 0x05F1,
+ 0x05F2,
+ 0xFB35,
+ 0x05B4,
+ 0x05B5,
+ 0x05B6,
+ 0x05BB,
+ 0x05B8,
+ 0x05B7,
+ 0x05B0,
+ 0x05B2,
+ 0x05B1,
+ 0x05B3,
+ 0x05C2,
+ 0x05C1,
+ 0x05B9,
+ 0x05BC,
+ 0x05BD,
+ 0x05BF,
+ 0x05C0,
+ 0x02BC,
+ 0x2105,
+ 0x2113,
+ 0x2116,
+ 0x202C,
+ 0x202D,
+ 0x202E,
+ 0x200C,
+ 0x066D,
+ 0x02BD,
+ 0x2135,
+ 0x03B1,
+ 0x03AC,
+ 0x0101,
+ 0x2220,
+ 0x2329,
+ 0x232A,
+ 0x0387,
+ 0x0105,
+ 0x01FB,
+ 0x2194,
+ 0x21D4,
+ 0x21D3,
+ 0x21D0,
+ 0x21D2,
+ 0x21D1,
+ 0x2193,
+ 0xF8E7,
+ 0x2190,
+ 0x2192,
+ 0x2191,
+ 0x2195,
+ 0x21A8,
+ 0xF8E6,
+ 0x2217,
+ 0x03B2,
+ 0x2588,
+ 0xF8F4,
+ 0xF8F3,
+ 0xF8F2,
+ 0xF8F1,
+ 0xF8FE,
+ 0xF8FD,
+ 0xF8FC,
+ 0xF8F0,
+ 0xF8EF,
+ 0xF8EE,
+ 0xF8FB,
+ 0xF8FA,
+ 0xF8F9,
+ 0x21B5,
+ 0x0109,
+ 0x010B,
+ 0x03C7,
+ 0x25CB,
+ 0x2297,
+ 0x2295,
+ 0x2663,
+ 0xF6C3,
+ 0x2245,
+ 0xF8E9,
+ 0xF6D9,
+ 0xF6D1,
+ 0xF6D2,
+ 0xF6D4,
+ 0xF6D5,
+ 0xF6D3,
+ 0xF6D6,
+ 0x010F,
+ 0x0111,
+ 0x03B4,
+ 0x2666,
+ 0xF6D7,
+ 0xF6D8,
+ 0x0385,
+ 0x2593,
+ 0x2584,
+ 0x20AB,
+ 0x0323,
+ 0xF6BE,
+ 0x22C5,
+ 0x0115,
+ 0x011B,
+ 0x0117,
+ 0x2208,
+ 0x0113,
+ 0x2205,
+ 0x014B,
+ 0x0119,
+ 0x03B5,
+ 0x03AD,
+ 0x2261,
+ 0x212E,
+ 0x03B7,
+ 0x03AE,
+ 0x203C,
+ 0x2203,
+ 0x2640,
+ 0x25A0,
+ 0x25AC,
+ 0x03B3,
+ 0x01E7,
+ 0x011D,
+ 0x0123,
+ 0x0121,
+ 0x2207,
+ 0x0300,
+ 0x0127,
+ 0x0125,
+ 0x2665,
+ 0x0309,
+ 0x2302,
+ 0x012D,
+ 0x0133,
+ 0x012B,
+ 0x2321,
+ 0xF8F5,
+ 0x2320,
+ 0x2229,
+ 0x25D8,
+ 0x25D9,
+ 0x263B,
+ 0x012F,
+ 0x03B9,
+ 0x03CA,
+ 0x0390,
+ 0x03AF,
+ 0x0129,
+ 0x0135,
+ 0x03BA,
+ 0x0137,
+ 0x0138,
+ 0x013A,
+ 0x03BB,
+ 0x013E,
+ 0x013C,
+ 0x0140,
+ 0x258C,
+ 0x20A4,
+ 0xF6C0,
+ 0x2227,
+ 0x2228,
+ 0x017F,
+ 0x2591,
+ 0x2642,
+ 0x2032,
+ 0x266A,
+ 0x266B,
+ 0x0144,
+ 0x0149,
+ 0x0148,
+ 0x0146,
+ 0x2209,
+ 0x2284,
+ 0x03BD,
+ 0x014F,
+ 0x01A1,
+ 0x0151,
+ 0x014D,
+ 0x03C9,
+ 0x03D6,
+ 0x03CE,
+ 0x03BF,
+ 0x03CC,
+ 0x25E6,
+ 0x221F,
+ 0x01FF,
+ 0xF8ED,
+ 0xF8EC,
+ 0xF8EB,
+ 0xF8F8,
+ 0xF8F7,
+ 0xF8F6,
+ 0x22A5,
+ 0x20A7,
+ 0x03C6,
+ 0x03D5,
+ 0x211E,
+ 0x2282,
+ 0x2283,
+ 0x221D,
+ 0x03C8,
+ 0x201B,
+ 0x0155,
+ 0xF8E5,
+ 0x0159,
+ 0x0157,
+ 0x2286,
+ 0x2287,
+ 0xF8E8,
+ 0xF6DA,
+ 0x2310,
+ 0x03C1,
+ 0x2590,
+ 0x015B,
+ 0x015D,
+ 0x0219,
+ 0x2033,
+ 0x2592,
+ 0x03C3,
+ 0x03C2,
+ 0x223C,
+ 0x263A,
+ 0x2660,
+ 0x220B,
+ 0x263C,
+ 0x03C4,
+ 0x0167,
+ 0x0165,
+ 0x0163,
+ 0x0163,
+ 0x2234,
+ 0x03B8,
+ 0x03D1,
+ 0x0303,
+ 0x0384,
+ 0xF8EA,
+ 0xF6DB,
+ 0x25BC,
+ 0x25C4,
+ 0x25BA,
+ 0x25B2,
+ 0x016D,
+ 0x01B0,
+ 0x0171,
+ 0x016B,
+ 0x2017,
+ 0x222A,
+ 0x2200,
+ 0x0173,
+ 0x2580,
+ 0x03C5,
+ 0x03CB,
+ 0x03B0,
+ 0x03CD,
+ 0x016F,
+ 0x0169,
+ 0x1E83,
+ 0x0175,
+ 0x1E85,
+ 0x2118,
+ 0x1E81,
+ 0x03BE,
+ 0x0177,
+ 0x1EF3,
+ 0x017A,
+ 0x017C,
+ 0x03B6,
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+ 0
+ };
+
+
+
+ static const unsigned short t1_standard_encoding[257] =
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 60,
+ 61,
+ 62,
+ 63,
+ 64,
+ 65,
+ 66,
+ 67,
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 74,
+ 75,
+ 76,
+ 77,
+ 78,
+ 79,
+ 80,
+ 81,
+ 82,
+ 83,
+ 84,
+ 85,
+ 86,
+ 87,
+ 88,
+ 89,
+ 90,
+ 91,
+ 92,
+ 93,
+ 94,
+ 95,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 96,
+ 97,
+ 98,
+ 99,
+ 100,
+ 101,
+ 102,
+ 103,
+ 104,
+ 105,
+ 106,
+ 107,
+ 108,
+ 109,
+ 110,
+ 0,
+ 111,
+ 112,
+ 113,
+ 114,
+ 0,
+ 115,
+ 116,
+ 117,
+ 118,
+ 119,
+ 120,
+ 121,
+ 122,
+ 0,
+ 123,
+ 0,
+ 124,
+ 125,
+ 126,
+ 127,
+ 128,
+ 129,
+ 130,
+ 131,
+ 0,
+ 132,
+ 133,
+ 0,
+ 134,
+ 135,
+ 136,
+ 137,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 138,
+ 0,
+ 139,
+ 0,
+ 0,
+ 0,
+ 0,
+ 140,
+ 141,
+ 142,
+ 143,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 144,
+ 0,
+ 0,
+ 0,
+ 145,
+ 0,
+ 0,
+ 146,
+ 147,
+ 148,
+ 149,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ };
+
+
+ static const unsigned short t1_expert_encoding[257] =
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1,
+ 229,
+ 230,
+ 0,
+ 231,
+ 232,
+ 233,
+ 234,
+ 235,
+ 236,
+ 237,
+ 238,
+ 13,
+ 14,
+ 15,
+ 99,
+ 239,
+ 240,
+ 241,
+ 242,
+ 243,
+ 244,
+ 245,
+ 246,
+ 247,
+ 248,
+ 27,
+ 28,
+ 249,
+ 250,
+ 251,
+ 252,
+ 0,
+ 253,
+ 254,
+ 255,
+ 256,
+ 257,
+ 0,
+ 0,
+ 0,
+ 258,
+ 0,
+ 0,
+ 259,
+ 260,
+ 261,
+ 262,
+ 0,
+ 0,
+ 263,
+ 264,
+ 265,
+ 0,
+ 266,
+ 109,
+ 110,
+ 267,
+ 268,
+ 269,
+ 0,
+ 270,
+ 271,
+ 272,
+ 273,
+ 274,
+ 275,
+ 276,
+ 277,
+ 278,
+ 279,
+ 280,
+ 281,
+ 282,
+ 283,
+ 284,
+ 285,
+ 286,
+ 287,
+ 288,
+ 289,
+ 290,
+ 291,
+ 292,
+ 293,
+ 294,
+ 295,
+ 296,
+ 297,
+ 298,
+ 299,
+ 300,
+ 301,
+ 302,
+ 303,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 304,
+ 305,
+ 306,
+ 0,
+ 0,
+ 307,
+ 308,
+ 309,
+ 310,
+ 311,
+ 0,
+ 312,
+ 0,
+ 0,
+ 312,
+ 0,
+ 0,
+ 314,
+ 315,
+ 0,
+ 0,
+ 316,
+ 317,
+ 318,
+ 0,
+ 0,
+ 0,
+ 158,
+ 155,
+ 163,
+ 319,
+ 320,
+ 321,
+ 322,
+ 323,
+ 324,
+ 325,
+ 0,
+ 0,
+ 326,
+ 150,
+ 164,
+ 169,
+ 327,
+ 328,
+ 329,
+ 330,
+ 331,
+ 332,
+ 333,
+ 334,
+ 335,
+ 336,
+ 337,
+ 338,
+ 339,
+ 340,
+ 341,
+ 342,
+ 343,
+ 344,
+ 345,
+ 346,
+ 347,
+ 348,
+ 349,
+ 350,
+ 351,
+ 352,
+ 353,
+ 354,
+ 355,
+ 356,
+ 357,
+ 358,
+ 359,
+ 360,
+ 361,
+ 362,
+ 363,
+ 364,
+ 365,
+ 366,
+ 367,
+ 368,
+ 369,
+ 370,
+ 371,
+ 372,
+ 373,
+ 374,
+ 375,
+ 376,
+ 377,
+ 378,
+ 0
+ };
+
+
+/* END */
--- /dev/null
+#
+# FreeType 2 PSNames driver configuration rules
+#
+
+
+# Copyright 1996-2000 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# PSNames driver directory
+#
+PSNAMES_DIR := $(SRC_)psnames
+PSNAMES_DIR_ := $(PSNAMES_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+PSNAMES_COMPILE := $(FT_COMPILE)
+
+
+# PSNames driver sources (i.e., C files)
+#
+PSNAMES_DRV_SRC := $(PSNAMES_DIR_)psmodule.c
+
+
+# PSNames driver headers
+#
+PSNAMES_DRV_H := $(PSNAMES_DRV_SRC:%.c=%.h) \
+ $(PSNAMES_DIR_)pstables.h
+
+
+# PSNames driver object(s)
+#
+# PSNAMES_DRV_OBJ_M is used during `multi' builds
+# PSNAMES_DRV_OBJ_S is used during `single' builds
+#
+PSNAMES_DRV_OBJ_M := $(PSNAMES_DRV_SRC:$(PSNAMES_DIR_)%.c=$(OBJ_)%.$O)
+PSNAMES_DRV_OBJ_S := $(OBJ_)psnames.$O
+
+# PSNames driver source file for single build
+#
+PSNAMES_DRV_SRC_S := $(PSNAMES_DIR_)psmodule.c
+
+
+# PSNames driver - single object
+#
+$(PSNAMES_DRV_OBJ_S): $(PSNAMES_DRV_SRC_S) $(PSNAMES_DRV_SRC) \
+ $(FREETYPE_H) $(PSNAMES_DRV_H)
+ $(PSNAMES_COMPILE) $T$@ $(PSNAMES_DRV_SRC_S)
+
+
+# PSNames driver - multiple objects
+#
+$(OBJ_)%.$O: $(PSNAMES_DIR_)%.c $(FREETYPE_H) $(PSNAMES_DRV_H)
+ $(PSNAMES_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(PSNAMES_DRV_OBJ_S)
+DRV_OBJS_M += $(PSNAMES_DRV_OBJ_M)
+
+
+# EOF
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftraster.c */
+/* */
+/* The FreeType glyph rasterizer (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* This is a rewrite of the FreeType 1.x scan-line converter */
+ /* */
+ /*************************************************************************/
+
+
+#include "ftraster.h"
+#include <freetype/internal/ftcalc.h> /* for FT_MulDiv() only */
+
+
+ /*************************************************************************/
+ /* */
+ /* A simple technical note on how the raster works */
+ /* ----------------------------------------------- */
+ /* */
+ /* Converting an outline into a bitmap is achieved in several steps: */
+ /* */
+ /* 1 - Decomposing the outline into successive `profiles'. Each */
+ /* profile is simply an array of scanline intersections on a given */
+ /* dimension. A profile's main attributes are */
+ /* */
+ /* o its scanline position boundaries, i.e. `Ymin' and `Ymax'. */
+ /* */
+ /* o an array of intersection coordinates for each scanline */
+ /* between `Ymin' and `Ymax'. */
+ /* */
+ /* o a direction, indicating whether it was built going `up' or */
+ /* `down', as this is very important for filling rules. */
+ /* */
+ /* 2 - Sweeping the target map's scanlines in order to compute segment */
+ /* `spans' which are then filled. Additionally, this pass */
+ /* performs drop-out control. */
+ /* */
+ /* The outline data is parsed during step 1 only. The profiles are */
+ /* built from the bottom of the render pool, used as a stack. The */
+ /* following graphics shows the profile list under construction: */
+ /* */
+ /* ____________________________________________________________ _ _ */
+ /* | | | | | */
+ /* | profile | coordinates for | profile | coordinates for |--> */
+ /* | 1 | profile 1 | 2 | profile 2 |--> */
+ /* |_________|___________________|_________|_________________|__ _ _ */
+ /* */
+ /* ^ ^ */
+ /* | | */
+ /* start of render pool top */
+ /* */
+ /* The top of the profile stack is kept in the `top' variable. */
+ /* */
+ /* As you can see, a profile record is pushed on top of the render */
+ /* pool, which is then followed by its coordinates/intersections. If */
+ /* a change of direction is detected in the outline, a new profile is */
+ /* generated until the end of the outline. */
+ /* */
+ /* Note that when all profiles have been generated, the function */
+ /* Finalize_Profile_Table() is used to record, for each profile, its */
+ /* bottom-most scanline as well as the scanline above its upmost */
+ /* boundary. These positions are called `y-turns' because they (sort */
+ /* of) correspond to local extrema. They are stored in a sorted list */
+ /* built from the top of the render pool as a downwards stack: */
+ /* */
+ /* _ _ _______________________________________ */
+ /* | | */
+ /* <--| sorted list of | */
+ /* <--| extrema scanlines | */
+ /* _ _ __________________|____________________| */
+ /* */
+ /* ^ ^ */
+ /* | | */
+ /* maxBuff sizeBuff = end of pool */
+ /* */
+ /* This list is later used during the sweep phase in order to */
+ /* optimize performance (see technical note on the sweep below). */
+ /* */
+ /* Of course, the raster detects whether the two stacks collide and */
+ /* handles the situation propertly. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /** **/
+ /** CONFIGURATION MACROS **/
+ /** **/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* define DEBUG_RASTER if you want to compile a debugging version */
+#define xxxDEBUG_RASTER
+
+ /* The default render pool size in bytes */
+#define RASTER_RENDER_POOL 8192
+
+ /* undefine FT_RASTER_OPTION_ANTI_ALIASING if you do not want to support */
+ /* 5-levels anti-aliasing */
+#ifdef FT_CONFIG_OPTION_5_GRAY_LEVELS
+#define FT_RASTER_OPTION_ANTI_ALIASING
+#endif
+
+ /* The size of the two-lines intermediate bitmap used */
+ /* for anti-aliasing, in bytes. */
+#define RASTER_GRAY_LINES 2048
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /** **/
+ /** OTHER MACROS (do not change) **/
+ /** **/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_raster
+
+
+#ifdef _STANDALONE_
+
+
+ /* This macro is used to indicate that a function parameter is unused. */
+ /* Its purpose is simply to reduce compiler warnings. Note also that */
+ /* simply defining it as `(void)x' doesn't avoid warnings with certain */
+ /* ANSI compilers (e.g. LCC). */
+#define FT_UNUSED( x ) (x) = (x)
+
+ /* Disable the tracing mechanism for simplicity -- developers can */
+ /* activate it easily by redefining these two macros. */
+#ifndef FT_ERROR
+#define FT_ERROR( x ) do ; while ( 0 ) /* nothing */
+#endif
+
+#ifndef FT_TRACE
+#define FT_TRACE( x ) do ; while ( 0 ) /* nothing */
+#endif
+
+#define Raster_Err_None 0
+#define Raster_Err_Not_Ini -1
+#define Raster_Err_Overflow -2
+#define Raster_Err_Neg_Height -3
+#define Raster_Err_Invalid -4
+#define Raster_Err_Unsupported -5
+
+
+#else /* _STANDALONE_ */
+
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftdebug.h> /* for FT_TRACE() and FT_ERROR() */
+
+#define Raster_Err_None FT_Err_Ok
+#define Raster_Err_Not_Ini FT_Err_Raster_Uninitialized
+#define Raster_Err_Overflow FT_Err_Raster_Overflow
+#define Raster_Err_Neg_Height FT_Err_Raster_Negative_Height
+#define Raster_Err_Invalid FT_Err_Invalid_Outline
+#define Raster_Err_Unsupported FT_Err_Unimplemented_Feature
+
+
+#endif /* _STANDALONE_ */
+
+
+ /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is */
+ /* typically a small value and the result of a*b is known to fit into */
+ /* 32 bits. */
+#define FMulDiv( a, b, c ) ( (a) * (b) / (c) )
+
+ /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
+ /* for clipping computations. It simply uses the FT_MulDiv() function */
+ /* defined in `ftcalc.h'. */
+#define SMulDiv FT_MulDiv
+
+ /* The rasterizer is a very general purpose component; please leave */
+ /* the following redefinitions there (you never know your target */
+ /* environment). */
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+#ifndef SUCCESS
+#define SUCCESS 0
+#endif
+
+#ifndef FAILURE
+#define FAILURE 1
+#endif
+
+
+#define MaxBezier 32 /* The maximum number of stacked Bezier curves. */
+ /* Setting this constant to more than 32 is a */
+ /* pure waste of space. */
+
+#define Pixel_Bits 6 /* fractional bits of *input* coordinates */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /** **/
+ /** SIMPLE TYPE DECLARATIONS **/
+ /** **/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef int Int;
+ typedef unsigned int UInt;
+ typedef short Short;
+ typedef unsigned short UShort, *PUShort;
+ typedef long Long, *PLong;
+ typedef unsigned long ULong;
+
+ typedef unsigned char Byte, *PByte;
+ typedef char Bool;
+
+ typedef struct TPoint_
+ {
+ Long x;
+ Long y;
+
+ } TPoint;
+
+
+ typedef enum TFlow_
+ {
+ Flow_None = 0,
+ Flow_Up = 1,
+ Flow_Down = -1
+
+ } TFlow;
+
+
+ /* States of each line, arc, and profile */
+ typedef enum TStates_
+ {
+ Unknown,
+ Ascending,
+ Descending,
+ Flat
+
+ } TStates;
+
+
+ typedef struct TProfile_ TProfile;
+ typedef TProfile* PProfile;
+
+ struct TProfile_
+ {
+ FT_F26Dot6 X; /* current coordinate during sweep */
+ PProfile link; /* link to next profile - various purpose */
+ PLong offset; /* start of profile's data in render pool */
+ Int flow; /* Profile orientation: Asc/Descending */
+ Long height; /* profile's height in scanlines */
+ Long start; /* profile's starting scanline */
+
+ UShort countL; /* number of lines to step before this */
+ /* profile becomes drawable */
+
+ PProfile next; /* next profile in same contour, used */
+ /* during drop-out control */
+ };
+
+ typedef PProfile TProfileList;
+ typedef PProfile* PProfileList;
+
+
+ /* Simple record used to implement a stack of bands, required */
+ /* by the sub-banding mechanism */
+ typedef struct TBand_
+ {
+ Short y_min; /* band's minimum */
+ Short y_max; /* band's maximum */
+
+ } TBand;
+
+
+#define AlignProfileSize \
+ ( ( sizeof ( TProfile ) + sizeof ( long ) - 1 ) / sizeof ( long ) )
+
+
+#ifdef TT_STATIC_RASTER
+
+
+#define RAS_ARGS /* void */
+#define RAS_ARG /* void */
+
+#define RAS_VARS /* void */
+#define RAS_VAR /* void */
+
+#define FT_UNUSED_RASTER do ; while ( 0 )
+
+
+#else /* TT_STATIC_RASTER */
+
+
+#define RAS_ARGS TRaster_Instance* raster,
+#define RAS_ARG TRaster_Instance* raster
+
+#define RAS_VARS raster,
+#define RAS_VAR raster
+
+#define FT_UNUSED_RASTER FT_UNUSED( raster )
+
+
+#endif /* TT_STATIC_RASTER */
+
+
+ typedef struct TRaster_Instance_ TRaster_Instance;
+
+
+ /* prototypes used for sweep function dispatch */
+ typedef void Function_Sweep_Init( RAS_ARGS Short* min,
+ Short* max );
+
+ typedef void Function_Sweep_Span( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right );
+
+ typedef void Function_Sweep_Step( RAS_ARG );
+
+
+ /* NOTE: These operations are only valid on 2's complement processors */
+
+#define FLOOR( x ) ( (x) & -ras.precision )
+#define CEILING( x ) ( ( (x) + ras.precision - 1 ) & -ras.precision )
+#define TRUNC( x ) ( (signed long)(x) >> ras.precision_bits )
+#define FRAC( x ) ( (x) & ( ras.precision - 1 ) )
+#define SCALED( x ) ( ( (x) << ras.scale_shift ) - ras.precision_half )
+
+ /* Note that I have moved the location of some fields in the */
+ /* structure to ensure that the most used variables are used */
+ /* at the top. Thus, their offset can be coded with less */
+ /* opcodes, and it results in a smaller executable. */
+
+ struct TRaster_Instance_
+ {
+ Int precision_bits; /* precision related variables */
+ Int precision;
+ Int precision_half;
+ Long precision_mask;
+ Int precision_shift;
+ Int precision_step;
+ Int precision_jitter;
+
+ Int scale_shift; /* == precision_shift for bitmaps */
+ /* == precision_shift+1 for pixmaps */
+
+ PLong buff; /* The profiles buffer */
+ PLong sizeBuff; /* Render pool size */
+ PLong maxBuff; /* Profiles buffer size */
+ PLong top; /* Current cursor in buffer */
+
+ FT_Error error;
+
+ Int numTurns; /* number of Y-turns in outline */
+
+ TPoint* arc; /* current Bezier arc pointer */
+
+ UShort bWidth; /* target bitmap width */
+ PByte bTarget; /* target bitmap buffer */
+ PByte gTarget; /* target pixmap buffer */
+
+ Long lastX, lastY, minY, maxY;
+
+ UShort num_Profs; /* current number of profiles */
+
+ Bool fresh; /* signals a fresh new profile which */
+ /* 'start' field must be completed */
+ Bool joint; /* signals that the last arc ended */
+ /* exactly on a scanline. Allows */
+ /* removal of doublets */
+ PProfile cProfile; /* current profile */
+ PProfile fProfile; /* head of linked list of profiles */
+ PProfile gProfile; /* contour's first profile in case */
+ /* of impact */
+
+ TStates state; /* rendering state */
+
+ FT_Bitmap target; /* description of target bit/pixmap */
+ FT_Outline outline;
+
+ Long traceOfs; /* current offset in target bitmap */
+ Long traceG; /* current offset in target pixmap */
+
+ Short traceIncr; /* sweep's increment in target bitmap */
+
+ Short gray_min_x; /* current min x during gray rendering */
+ Short gray_max_x; /* current max x during gray rendering */
+
+ /* dispatch variables */
+
+ Function_Sweep_Init* Proc_Sweep_Init;
+ Function_Sweep_Span* Proc_Sweep_Span;
+ Function_Sweep_Span* Proc_Sweep_Drop;
+ Function_Sweep_Step* Proc_Sweep_Step;
+
+ Byte dropOutControl; /* current drop_out control method */
+
+ Bool second_pass; /* indicates wether a horizontal pass */
+ /* should be performed to control */
+ /* drop-out accurately when calling */
+ /* Render_Glyph. Note that there is */
+ /* no horizontal pass during gray */
+ /* rendering. */
+
+ TPoint arcs[2 * MaxBezier + 1]; /* The Bezier stack */
+
+ TBand band_stack[16]; /* band stack used for sub-banding */
+ Int band_top; /* band stack top */
+
+ Int count_table[256]; /* Look-up table used to quickly count */
+ /* set bits in a gray 2x2 cell */
+
+ void* memory;
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+ Byte grays[5]; /* Palette of gray levels used for */
+ /* render. */
+
+ Byte gray_lines[RASTER_GRAY_LINES];
+ /* Intermediate table used to render the */
+ /* graylevels pixmaps. */
+ /* gray_lines is a buffer holding two */
+ /* monochrome scanlines */
+
+ Short gray_width; /* width in bytes of one monochrome */
+ /* intermediate scanline of gray_lines. */
+ /* Each gray pixel takes 2 bits long there */
+
+ /* The gray_lines must hold 2 lines, thus with size */
+ /* in bytes of at least `gray_width*2'. */
+
+#endif /* FT_RASTER_ANTI_ALIASING */
+
+#if 0
+ PByte flags; /* current flags table */
+ PUShort outs; /* current outlines table */
+ FT_Vector* coords;
+
+ UShort nPoints; /* number of points in current glyph */
+ Short nContours; /* number of contours in current glyph */
+#endif
+
+ };
+
+
+#ifdef FT_CONFIG_OPTION_STATIC_RASTER
+
+ static TRaster_Instance cur_ras;
+#define ras cur_ras
+
+#else
+
+#define ras (*raster)
+
+#endif /* FT_CONFIG_OPTION_STATIC_RASTER */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /** **/
+ /** PROFILES COMPUTATION **/
+ /** **/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Set_High_Precision */
+ /* */
+ /* <Description> */
+ /* Sets precision variables according to param flag. */
+ /* */
+ /* <Input> */
+ /* High :: Set to True for high precision (typically for ppem < 18), */
+ /* false otherwise. */
+ /* */
+ static
+ void Set_High_Precision( RAS_ARGS Int High )
+ {
+ if ( High )
+ {
+ ras.precision_bits = 10;
+ ras.precision_step = 128;
+ ras.precision_jitter = 24;
+ }
+ else
+ {
+ ras.precision_bits = 6;
+ ras.precision_step = 32;
+ ras.precision_jitter = 2;
+ }
+
+ FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
+
+ ras.precision = 1L << ras.precision_bits;
+ ras.precision_half = ras.precision / 2;
+ ras.precision_shift = ras.precision_bits - Pixel_Bits;
+ ras.precision_mask = -ras.precision;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* New_Profile */
+ /* */
+ /* <Description> */
+ /* Creates a new profile in the render pool. */
+ /* */
+ /* <Input> */
+ /* aState :: The state/orientation of the new profile. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success. FAILURE in case of overflow or of incoherent */
+ /* profile. */
+ /* */
+ static
+ Bool New_Profile( RAS_ARGS TStates aState )
+ {
+ if ( !ras.fProfile )
+ {
+ ras.cProfile = (PProfile)ras.top;
+ ras.fProfile = ras.cProfile;
+ ras.top += AlignProfileSize;
+ }
+
+ if ( ras.top >= ras.maxBuff )
+ {
+ ras.error = Raster_Err_Overflow;
+ return FAILURE;
+ }
+
+ switch ( aState )
+ {
+ case Ascending:
+ ras.cProfile->flow = Flow_Up;
+ FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile ));
+ break;
+
+ case Descending:
+ ras.cProfile->flow = Flow_Down;
+ FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile ));
+ break;
+
+ default:
+ FT_ERROR(( "New_Profile: invalid profile direction!\n" ));
+ ras.error = Raster_Err_Invalid;
+ return FAILURE;
+ }
+
+ ras.cProfile->start = 0;
+ ras.cProfile->height = 0;
+ ras.cProfile->offset = ras.top;
+ ras.cProfile->link = (PProfile)0;
+ ras.cProfile->next = (PProfile)0;
+
+ if ( !ras.gProfile )
+ ras.gProfile = ras.cProfile;
+
+ ras.state = aState;
+ ras.fresh = TRUE;
+ ras.joint = FALSE;
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* End_Profile */
+ /* */
+ /* <Description> */
+ /* Finalizes the current profile. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success. FAILURE in case of overflow or incoherency. */
+ /* */
+ static
+ Bool End_Profile( RAS_ARG )
+ {
+ Long h;
+ PProfile oldProfile;
+
+
+ h = ras.top - ras.cProfile->offset;
+
+ if ( h < 0 )
+ {
+ FT_ERROR(( "End_Profile: negative height encountered!\n" ));
+ ras.error = Raster_Err_Neg_Height;
+ return FAILURE;
+ }
+
+ if ( h > 0 )
+ {
+ FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n",
+ (long)ras.cProfile, ras.cProfile->start, h ));
+
+ oldProfile = ras.cProfile;
+ ras.cProfile->height = h;
+ ras.cProfile = (PProfile)ras.top;
+
+ ras.top += AlignProfileSize;
+
+ ras.cProfile->height = 0;
+ ras.cProfile->offset = ras.top;
+ oldProfile->next = ras.cProfile;
+ ras.num_Profs++;
+ }
+
+ if ( ras.top >= ras.maxBuff )
+ {
+ FT_TRACE1(( "overflow in End_Profile\n" ));
+ ras.error = Raster_Err_Overflow;
+ return FAILURE;
+ }
+
+ ras.joint = FALSE;
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Insert_Y_Turn */
+ /* */
+ /* <Description> */
+ /* Inserts a salient into the sorted list placed on top of the render */
+ /* pool. */
+ /* */
+ /* <Input> */
+ /* New y scanline position. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success. FAILURE in case of overflow. */
+ /* */
+ static
+ Bool Insert_Y_Turn( RAS_ARGS Int y )
+ {
+ PLong y_turns;
+ Int y2, n;
+
+
+ n = ras.numTurns - 1;
+ y_turns = ras.sizeBuff - ras.numTurns;
+
+ /* look for first y value that is <= */
+ while ( n >= 0 && y < y_turns[n] )
+ n--;
+
+ /* if it is <, simply insert it, ignore if == */
+ if ( n >= 0 && y > y_turns[n] )
+ while ( n >= 0 )
+ {
+ y2 = y_turns[n];
+ y_turns[n] = y;
+ y = y2;
+ n--;
+ }
+
+ if ( n < 0 )
+ {
+ if ( ras.maxBuff <= ras.top )
+ {
+ ras.error = Raster_Err_Overflow;
+ return FAILURE;
+ }
+ ras.maxBuff--;
+ ras.numTurns++;
+ ras.sizeBuff[-ras.numTurns] = y;
+ }
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Finalize_Profile_Table */
+ /* */
+ /* <Description> */
+ /* Adjusts all links in the profiles list. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success. FAILURE in case of overflow. */
+ /* */
+ static
+ Bool Finalize_Profile_Table( RAS_ARG )
+ {
+ Int bottom, top;
+ UShort n;
+ PProfile p;
+
+
+ n = ras.num_Profs;
+
+ if ( n > 1 )
+ {
+ p = ras.fProfile;
+ while ( n > 0 )
+ {
+ if ( n > 1 )
+ p->link = (PProfile)( p->offset + p->height );
+ else
+ p->link = NULL;
+
+ switch ( p->flow )
+ {
+ case Flow_Down:
+ bottom = p->start - p->height+1;
+ top = p->start;
+ p->start = bottom;
+ p->offset += p->height - 1;
+ break;
+
+ case Flow_Up:
+ default:
+ bottom = p->start;
+ top = p->start + p->height - 1;
+ }
+
+ if ( Insert_Y_Turn( RAS_VARS bottom ) ||
+ Insert_Y_Turn( RAS_VARS top + 1 ) )
+ return FAILURE;
+
+ p = p->link;
+ n--;
+ }
+ }
+ else
+ ras.fProfile = NULL;
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Split_Conic */
+ /* */
+ /* <Description> */
+ /* Subdivides one conic Bezier into two joint sub-arcs in the Bezier */
+ /* stack. */
+ /* */
+ /* <Input> */
+ /* None (subdivided Bezier is taken from the top of the stack). */
+ /* */
+ /* <Note> */
+ /* This routine is the `beef' of this component. It is _the_ inner */
+ /* loop that should be optimized to hell to get the best performance. */
+ /* */
+ static
+ void Split_Conic( TPoint* base )
+ {
+ Long a, b;
+
+
+ base[4].x = base[2].x;
+ b = base[1].x;
+ a = base[3].x = ( base[2].x + b ) / 2;
+ b = base[1].x = ( base[0].x + b ) / 2;
+ base[2].x = ( a + b ) / 2;
+
+ base[4].y = base[2].y;
+ b = base[1].y;
+ a = base[3].y = ( base[2].y + b ) / 2;
+ b = base[1].y = ( base[0].y + b ) / 2;
+ base[2].y = ( a + b ) / 2;
+
+ /* hand optimized. gcc doesn't seem to be too good at common */
+ /* expression substitution and instruction scheduling ;-) */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Split_Cubic */
+ /* */
+ /* <Description> */
+ /* Subdivides a third-order Bezier arc into two joint sub-arcs in the */
+ /* Bezier stack. */
+ /* */
+ /* <Note> */
+ /* This routine is the `beef' of the component. It is one of _the_ */
+ /* inner loops that should be optimized like hell to get the best */
+ /* performance. */
+ /* */
+ static
+ void Split_Cubic( TPoint* base )
+ {
+ Long a, b, c, d;
+
+
+ base[6].x = base[3].x;
+ c = base[1].x;
+ d = base[2].x;
+ base[1].x = a = ( base[0].x + c + 1 ) >> 1;
+ base[5].x = b = ( base[3].x + d + 1 ) >> 1;
+ c = ( c + d + 1 ) >> 1;
+ base[2].x = a = ( a + c + 1 ) >> 1;
+ base[4].x = b = ( b + c + 1 ) >> 1;
+ base[3].x = ( a + b + 1 ) >> 1;
+
+ base[6].y = base[3].y;
+ c = base[1].y;
+ d = base[2].y;
+ base[1].y = a = ( base[0].y + c + 1 ) >> 1;
+ base[5].y = b = ( base[3].y + d + 1 ) >> 1;
+ c = ( c + d + 1 ) >> 1;
+ base[2].y = a = ( a + c + 1 ) >> 1;
+ base[4].y = b = ( b + c + 1 ) >> 1;
+ base[3].y = ( a + b + 1 ) >> 1;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Line_Up */
+ /* */
+ /* <Description> */
+ /* Computes the x-coordinates of an ascending line segment and stores */
+ /* them in the render pool. */
+ /* */
+ /* <Input> */
+ /* x1 :: The x-coordinate of the segment's start point. */
+ /* */
+ /* y1 :: The y-coordinate of the segment's start point. */
+ /* */
+ /* x2 :: The x-coordinate of the segment's end point. */
+ /* */
+ /* y2 :: The y-coordinate of the segment's end point. */
+ /* */
+ /* miny :: A lower vertical clipping bound value. */
+ /* */
+ /* maxy :: An upper vertical clipping bound value. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow. */
+ /* */
+ static
+ Bool Line_Up( RAS_ARGS Long x1,
+ Long y1,
+ Long x2,
+ Long y2,
+ Long miny,
+ Long maxy )
+ {
+ Long Dx, Dy;
+ Int e1, e2, f1, f2, size; /* XXX: is `Short' sufficient? */
+ Long Ix, Rx, Ax;
+
+ PLong top;
+
+
+ Dx = x2 - x1;
+ Dy = y2 - y1;
+
+ if ( Dy <= 0 || y2 < miny || y1 > maxy )
+ return SUCCESS;
+
+ if ( y1 < miny )
+ {
+ /* Take care: miny-y1 can be a very large value; we use */
+ /* a slow MulDiv function to avoid clipping bugs */
+ x1 += SMulDiv( Dx, miny - y1, Dy );
+ e1 = TRUNC( miny );
+ f1 = 0;
+ }
+ else
+ {
+ e1 = TRUNC( y1 );
+ f1 = FRAC( y1 );
+ }
+
+ if ( y2 > maxy )
+ {
+ /* x2 += FMulDiv( Dx, maxy - y2, Dy ); UNNECESSARY */
+ e2 = TRUNC( maxy );
+ f2 = 0;
+ }
+ else
+ {
+ e2 = TRUNC( y2 );
+ f2 = FRAC( y2 );
+ }
+
+ if ( f1 > 0 )
+ {
+ if ( e1 == e2 )
+ return SUCCESS;
+ else
+ {
+ x1 += FMulDiv( Dx, ras.precision - f1, Dy );
+ e1 += 1;
+ }
+ }
+ else
+ if ( ras.joint )
+ {
+ ras.top--;
+ ras.joint = FALSE;
+ }
+
+ ras.joint = ( f2 == 0 );
+
+ if ( ras.fresh )
+ {
+ ras.cProfile->start = e1;
+ ras.fresh = FALSE;
+ }
+
+ size = e2 - e1 + 1;
+ if ( ras.top + size >= ras.maxBuff )
+ {
+ ras.error = Raster_Err_Overflow;
+ return FAILURE;
+ }
+
+ if ( Dx > 0 )
+ {
+ Ix = ( ras.precision * Dx ) / Dy;
+ Rx = ( ras.precision * Dx ) % Dy;
+ Dx = 1;
+ }
+ else
+ {
+ Ix = -( ( ras.precision * -Dx ) / Dy );
+ Rx = ( ras.precision * -Dx ) % Dy;
+ Dx = -1;
+ }
+
+ Ax = -Dy;
+ top = ras.top;
+
+ while ( size > 0 )
+ {
+ *top++ = x1;
+
+ x1 += Ix;
+ Ax += Rx;
+ if ( Ax >= 0 )
+ {
+ Ax -= Dy;
+ x1 += Dx;
+ }
+ size--;
+ }
+
+ ras.top = top;
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Line_Down */
+ /* */
+ /* <Description> */
+ /* Computes the x-coordinates of an descending line segment and */
+ /* stores them in the render pool. */
+ /* */
+ /* <Input> */
+ /* x1 :: The x-coordinate of the segment's start point. */
+ /* */
+ /* y1 :: The y-coordinate of the segment's start point. */
+ /* */
+ /* x2 :: The x-coordinate of the segment's end point. */
+ /* */
+ /* y2 :: The y-coordinate of the segment's end point. */
+ /* */
+ /* miny :: A lower vertical clipping bound value. */
+ /* */
+ /* maxy :: An upper vertical clipping bound value. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow. */
+ /* */
+ static
+ Bool Line_Down( RAS_ARGS Long x1,
+ Long y1,
+ Long x2,
+ Long y2,
+ Long miny,
+ Long maxy )
+ {
+ Bool result, fresh;
+
+
+ fresh = ras.fresh;
+
+ result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
+
+ if ( fresh && !ras.fresh )
+ ras.cProfile->start = -ras.cProfile->start;
+
+ return result;
+ }
+
+
+ /* A function type describing the functions used to split Bezier arcs */
+ typedef void (*TSplitter)( TPoint* base );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Bezier_Up */
+ /* */
+ /* <Description> */
+ /* Computes the x-coordinates of an ascending Bezier arc and stores */
+ /* them in the render pool. */
+ /* */
+ /* <Input> */
+ /* degree :: The degree of the Bezier arc (either 2 or 3). */
+ /* */
+ /* splitter :: The function to split Bezier arcs. */
+ /* */
+ /* miny :: A lower vertical clipping bound value. */
+ /* */
+ /* maxy :: An upper vertical clipping bound value. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow. */
+ /* */
+ static
+ Bool Bezier_Up( RAS_ARGS Int degree,
+ TSplitter splitter,
+ Long miny,
+ Long maxy )
+ {
+ Long y1, y2, e, e2, e0;
+ Short f1;
+
+ TPoint* arc;
+ TPoint* start_arc;
+
+ PLong top;
+
+
+ arc = ras.arc;
+ y1 = arc[degree].y;
+ y2 = arc[0].y;
+ top = ras.top;
+
+ if ( y2 < miny || y1 > maxy )
+ goto Fin;
+
+ e2 = FLOOR( y2 );
+
+ if ( e2 > maxy )
+ e2 = maxy;
+
+ e0 = miny;
+
+ if ( y1 < miny )
+ e = miny;
+ else
+ {
+ e = CEILING( y1 );
+ f1 = FRAC( y1 );
+ e0 = e;
+
+ if ( f1 == 0 )
+ {
+ if ( ras.joint )
+ {
+ top--;
+ ras.joint = FALSE;
+ }
+
+ *top++ = arc[degree].x;
+
+ e += ras.precision;
+ }
+ }
+
+ if ( ras.fresh )
+ {
+ ras.cProfile->start = TRUNC( e0 );
+ ras.fresh = FALSE;
+ }
+
+ if ( e2 < e )
+ goto Fin;
+
+ if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
+ {
+ ras.top = top;
+ ras.error = Raster_Err_Overflow;
+ return FAILURE;
+ }
+
+ start_arc = arc;
+
+ while ( arc >= start_arc && e <= e2 )
+ {
+ ras.joint = FALSE;
+
+ y2 = arc[0].y;
+
+ if ( y2 > e )
+ {
+ y1 = arc[degree].y;
+ if ( y2 - y1 >= ras.precision_step )
+ {
+ splitter( arc );
+ arc += degree;
+ }
+ else
+ {
+ *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x,
+ e - y1, y2 - y1 );
+ arc -= degree;
+ e += ras.precision;
+ }
+ }
+ else
+ {
+ if ( y2 == e )
+ {
+ ras.joint = TRUE;
+ *top++ = arc[0].x;
+
+ e += ras.precision;
+ }
+ arc -= degree;
+ }
+ }
+
+ Fin:
+ ras.top = top;
+ ras.arc -= degree;
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Bezier_Down */
+ /* */
+ /* <Description> */
+ /* Computes the x-coordinates of an descending Bezier arc and stores */
+ /* them in the render pool. */
+ /* */
+ /* <Input> */
+ /* degree :: The degree of the Bezier arc (either 2 or 3). */
+ /* */
+ /* splitter :: The function to split Bezier arcs. */
+ /* */
+ /* miny :: A lower vertical clipping bound value. */
+ /* */
+ /* maxy :: An upper vertical clipping bound value. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow. */
+ /* */
+ static
+ Bool Bezier_Down( RAS_ARGS Int degree,
+ TSplitter splitter,
+ Long miny,
+ Long maxy )
+ {
+ TPoint* arc = ras.arc;
+ Bool result, fresh;
+
+
+ arc[0].y = -arc[0].y;
+ arc[1].y = -arc[1].y;
+ arc[2].y = -arc[2].y;
+ if ( degree > 2 )
+ arc[3].y = -arc[3].y;
+
+ fresh = ras.fresh;
+
+ result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
+
+ if ( fresh && !ras.fresh )
+ ras.cProfile->start = -ras.cProfile->start;
+
+ arc[0].y = -arc[0].y;
+ return result;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Line_To */
+ /* */
+ /* <Description> */
+ /* Injects a new line segment and adjusts Profiles list. */
+ /* */
+ /* <Input> */
+ /* x :: The x-coordinate of the segment's end point (its start point */
+ /* is stored in `LastX'). */
+ /* */
+ /* y :: The y-coordinate of the segment's end point (its start point */
+ /* is stored in `LastY'). */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
+ /* profile. */
+ /* */
+ static
+ Bool Line_To( RAS_ARGS Long x,
+ Long y )
+ {
+ /* First, detect a change of direction */
+
+ switch ( ras.state )
+ {
+ case Unknown:
+ if ( y > ras.lastY )
+ {
+ if ( New_Profile( RAS_VARS Ascending ) )
+ return FAILURE;
+ }
+ else
+ {
+ if ( y < ras.lastY )
+ if ( New_Profile( RAS_VARS Descending ) )
+ return FAILURE;
+ }
+ break;
+
+ case Ascending:
+ if ( y < ras.lastY )
+ {
+ if ( End_Profile( RAS_VAR ) ||
+ New_Profile( RAS_VARS Descending ) )
+ return FAILURE;
+ }
+ break;
+
+ case Descending:
+ if ( y > ras.lastY )
+ {
+ if ( End_Profile( RAS_VAR ) ||
+ New_Profile( RAS_VARS Ascending ) )
+ return FAILURE;
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ /* Then compute the lines */
+
+ switch ( ras.state )
+ {
+ case Ascending:
+ if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
+ x, y, ras.minY, ras.maxY ) )
+ return FAILURE;
+ break;
+
+ case Descending:
+ if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
+ x, y, ras.minY, ras.maxY ) )
+ return FAILURE;
+ break;
+
+ default:
+ ;
+ }
+
+ ras.lastX = x;
+ ras.lastY = y;
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Conic_To */
+ /* */
+ /* <Description> */
+ /* Injects a new conic arc and adjusts the profile list. */
+ /* */
+ /* <Input> */
+ /* cx :: The x-coordinate of the arc's new control point. */
+ /* */
+ /* cy :: The y-coordinate of the arc's new control point. */
+ /* */
+ /* x :: The x-coordinate of the arc's end point (its start point is */
+ /* stored in `LastX'). */
+ /* */
+ /* y :: The y-coordinate of the arc's end point (its start point is */
+ /* stored in `LastY'). */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
+ /* profile. */
+ /* */
+ static
+ Bool Conic_To( RAS_ARGS Long cx,
+ Long cy,
+ Long x,
+ Long y )
+ {
+ Long y1, y2, y3, x3, ymin, ymax;
+ TStates state_bez;
+
+
+ ras.arc = ras.arcs;
+ ras.arc[2].x = ras.lastX;
+ ras.arc[2].y = ras.lastY;
+ ras.arc[1].x = cx; ras.arc[1].y = cy;
+ ras.arc[0].x = x; ras.arc[0].y = y;
+
+ do
+ {
+ y1 = ras.arc[2].y;
+ y2 = ras.arc[1].y;
+ y3 = ras.arc[0].y;
+ x3 = ras.arc[0].x;
+
+ /* first, categorize the Bezier arc */
+
+ if ( y1 <= y3 )
+ {
+ ymin = y1;
+ ymax = y3;
+ }
+ else
+ {
+ ymin = y3;
+ ymax = y1;
+ }
+
+ if ( y2 < ymin || y2 > ymax )
+ {
+ /* this arc has no given direction, split it! */
+ Split_Conic( ras.arc );
+ ras.arc += 2;
+ }
+ else if ( y1 == y3 )
+ {
+ /* this arc is flat, ignore it and pop it from the Bezier stack */
+ ras.arc -= 2;
+ }
+ else
+ {
+ /* the arc is y-monotonous, either ascending or descending */
+ /* detect a change of direction */
+ state_bez = y1 < y3 ? Ascending : Descending;
+ if ( ras.state != state_bez )
+ {
+ /* finalize current profile if any */
+ if ( ras.state != Unknown &&
+ End_Profile( RAS_VAR ) )
+ goto Fail;
+
+ /* create a new profile */
+ if ( New_Profile( RAS_VARS state_bez ) )
+ goto Fail;
+ }
+
+ /* now call the appropriate routine */
+ if ( state_bez == Ascending )
+ {
+ if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+ goto Fail;
+ }
+ else
+ if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+ goto Fail;
+ }
+
+ } while ( ras.arc >= ras.arcs );
+
+ ras.lastX = x3;
+ ras.lastY = y3;
+
+ return SUCCESS;
+
+ Fail:
+ return FAILURE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Cubic_To */
+ /* */
+ /* <Description> */
+ /* Injects a new cubic arc and adjusts the profile list. */
+ /* */
+ /* <Input> */
+ /* cx1 :: The x-coordinate of the arc's first new control point. */
+ /* */
+ /* cy1 :: The y-coordinate of the arc's first new control point. */
+ /* */
+ /* cx2 :: The x-coordinate of the arc's second new control point. */
+ /* */
+ /* cy2 :: The y-coordinate of the arc's second new control point. */
+ /* */
+ /* x :: The x-coordinate of the arc's end point (its start point is */
+ /* stored in `LastX'). */
+ /* */
+ /* y :: The y-coordinate of the arc's end point (its start point is */
+ /* stored in `LastY'). */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
+ /* profile. */
+ /* */
+ static
+ Bool Cubic_To( RAS_ARGS Long cx1,
+ Long cy1,
+ Long cx2,
+ Long cy2,
+ Long x,
+ Long y )
+ {
+ Long y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
+ TStates state_bez;
+
+
+ ras.arc = ras.arcs;
+ ras.arc[3].x = ras.lastX;
+ ras.arc[3].y = ras.lastY;
+ ras.arc[2].x = cx1; ras.arc[2].y = cy1;
+ ras.arc[1].x = cx2; ras.arc[1].y = cy2;
+ ras.arc[0].x = x; ras.arc[0].y = y;
+
+ do
+ {
+ y1 = ras.arc[3].y;
+ y2 = ras.arc[2].y;
+ y3 = ras.arc[1].y;
+ y4 = ras.arc[0].y;
+ x4 = ras.arc[0].x;
+
+ /* first, categorize the Bezier arc */
+
+ if ( y1 <= y4 )
+ {
+ ymin1 = y1;
+ ymax1 = y4;
+ }
+ else
+ {
+ ymin1 = y4;
+ ymax1 = y1;
+ }
+
+ if ( y2 <= y3 )
+ {
+ ymin2 = y2;
+ ymax2 = y3;
+ }
+ else
+ {
+ ymin2 = y3;
+ ymax2 = y2;
+ }
+
+ if ( ymin2 < ymin1 || ymax2 > ymax1 )
+ {
+ /* this arc has no given direction, split it! */
+ Split_Cubic( ras.arc );
+ ras.arc += 3;
+ }
+ else if ( y1 == y4 )
+ {
+ /* this arc is flat, ignore it and pop it from the Bezier stack */
+ ras.arc -= 3;
+ }
+ else
+ {
+ state_bez = ( y1 <= y4 ) ? Ascending : Descending;
+
+ /* detect a change of direction */
+ if ( ras.state != state_bez )
+ {
+ if ( ras.state != Unknown &&
+ End_Profile( RAS_VAR ) )
+ goto Fail;
+
+ if ( New_Profile( RAS_VARS state_bez ) )
+ goto Fail;
+ }
+
+ /* compute intersections */
+ if ( state_bez == Ascending )
+ {
+ if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+ goto Fail;
+ }
+ else
+ if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+ goto Fail;
+ }
+
+ } while ( ras.arc >= ras.arcs );
+
+ ras.lastX = x4;
+ ras.lastY = y4;
+
+ return SUCCESS;
+
+ Fail:
+ return FAILURE;
+ }
+
+
+#undef SWAP_
+#define SWAP_( x, y ) do \
+ { \
+ Long swap = x; \
+ \
+ \
+ x = y; \
+ y = swap; \
+ } while ( 0 )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Decompose_Curve */
+ /* */
+ /* <Description> */
+ /* Scans the outline arays in order to emit individual segments and */
+ /* Beziers by calling Line_To() and Bezier_To(). It handles all */
+ /* weird cases, like when the first point is off the curve, or when */
+ /* there are simply no `on' points in the contour! */
+ /* */
+ /* <Input> */
+ /* first :: The index of the first point in the contour. */
+ /* */
+ /* last :: The index of the last point in the contour. */
+ /* */
+ /* flipped :: If set, flip the direction of the curve. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on error. */
+ /* */
+ static
+ Bool Decompose_Curve( RAS_ARGS UShort first,
+ UShort last,
+ int flipped )
+ {
+ FT_Vector v_last;
+ FT_Vector v_control;
+ FT_Vector v_start;
+
+ FT_Vector* points;
+ FT_Vector* point;
+ FT_Vector* limit;
+ char* tags;
+
+ char tag; /* current point's state */
+
+
+ points = ras.outline.points;
+ limit = points + last;
+
+ v_start.x = SCALED( points[first].x );
+ v_start.y = SCALED( points[first].y );
+ v_last.x = SCALED( points[last].x );
+ v_last.y = SCALED( points[last].y );
+
+ if ( flipped )
+ {
+ SWAP_( v_start.x, v_start.y );
+ SWAP_( v_last.x, v_last.y );
+ }
+
+ v_control = v_start;
+
+ point = points + first;
+ tags = ras.outline.tags + first;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ /* A contour cannot start with a cubic control point! */
+ if ( tag == FT_Curve_Tag_Cubic )
+ goto Invalid_Outline;
+
+ /* check first point to determine origin */
+ if ( tag == FT_Curve_Tag_Conic )
+ {
+ /* first point is conic control. Yes, this happens. */
+ if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_Curve_Tag_On )
+ {
+ /* start at last point if it is on the curve */
+ v_start = v_last;
+ limit--;
+ }
+ else
+ {
+ /* if both first and last points are conic, */
+ /* start at their middle and record its position */
+ /* for closure */
+ v_start.x = ( v_start.x + v_last.x ) / 2;
+ v_start.y = ( v_start.y + v_last.y ) / 2;
+
+ v_last = v_start;
+ }
+ point--;
+ tags--;
+ }
+
+ ras.lastX = v_start.x;
+ ras.lastY = v_start.y;
+
+ while ( point < limit )
+ {
+ point++;
+ tags++;
+
+ tag = FT_CURVE_TAG( tags[0] );
+
+ switch ( tag )
+ {
+ case FT_Curve_Tag_On: /* emit a single line_to */
+ {
+ Long x, y;
+
+
+ x = SCALED( point->x );
+ y = SCALED( point->y );
+ if ( flipped )
+ SWAP_( x, y );
+
+ if ( Line_To( RAS_VARS x, y ) )
+ goto Fail;
+ continue;
+ }
+
+ case FT_Curve_Tag_Conic: /* consume conic arcs */
+ v_control.x = SCALED( point[0].x );
+ v_control.y = SCALED( point[0].y );
+
+ if ( flipped )
+ SWAP_( v_control.x, v_control.y );
+
+ Do_Conic:
+ if ( point < limit )
+ {
+ FT_Vector v_middle;
+ Long x, y;
+
+
+ point++;
+ tags++;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ x = SCALED( point[0].x );
+ y = SCALED( point[0].y );
+
+ if ( flipped )
+ SWAP_( x, y );
+
+ if ( tag == FT_Curve_Tag_On )
+ {
+ if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )
+ goto Fail;
+ continue;
+ }
+
+ if ( tag != FT_Curve_Tag_Conic )
+ goto Invalid_Outline;
+
+ v_middle.x = ( v_control.x + x ) / 2;
+ v_middle.y = ( v_control.y + y ) / 2;
+
+ if ( Conic_To( RAS_VARS v_control.x, v_control.y,
+ v_middle.x, v_middle.y ) )
+ goto Fail;
+
+ v_control.x = x;
+ v_control.y = y;
+
+ goto Do_Conic;
+ }
+
+ if ( Conic_To( RAS_VARS v_control.x, v_control.y,
+ v_start.x, v_start.y ) )
+ goto Fail;
+
+ goto Close;
+
+ default: /* FT_Curve_Tag_Cubic */
+ {
+ Long x1, y1, x2, y2, x3, y3;
+
+
+ if ( point + 1 > limit ||
+ FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
+ goto Invalid_Outline;
+
+ point += 2;
+ tags += 2;
+
+ x1 = SCALED( point[-2].x );
+ y1 = SCALED( point[-2].y );
+ x2 = SCALED( point[-1].x );
+ y2 = SCALED( point[-1].y );
+ x3 = SCALED( point[ 0].x );
+ y3 = SCALED( point[ 0].y );
+
+ if ( flipped )
+ {
+ SWAP_( x1, y1 );
+ SWAP_( x2, y2 );
+ SWAP_( x3, y3 );
+ }
+
+ if ( point <= limit )
+ {
+ if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )
+ goto Fail;
+ continue;
+ }
+
+ if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )
+ goto Fail;
+ goto Close;
+ }
+ }
+ }
+
+ /* close the contour with a line segment */
+ if ( Line_To( RAS_VARS v_start.x, v_start.y ) )
+ goto Fail;
+
+ Close:
+ return SUCCESS;
+
+ Invalid_Outline:
+ ras.error = Raster_Err_Invalid;
+
+ Fail:
+ return FAILURE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Convert_Glyph */
+ /* */
+ /* <Description> */
+ /* Converts a glyph into a series of segments and arcs and makes a */
+ /* profiles list with them. */
+ /* */
+ /* <Input> */
+ /* flipped :: If set, flip the direction of curve. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE if any error was encountered during */
+ /* rendering. */
+ /* */
+ static
+ Bool Convert_Glyph( RAS_ARGS int flipped )
+ {
+ Short i;
+ UShort start;
+
+ PProfile lastProfile;
+
+
+ ras.fProfile = NULL;
+ ras.joint = FALSE;
+ ras.fresh = FALSE;
+
+ ras.maxBuff = ras.sizeBuff - AlignProfileSize;
+
+ ras.numTurns = 0;
+
+ ras.cProfile = (PProfile)ras.top;
+ ras.cProfile->offset = ras.top;
+ ras.num_Profs = 0;
+
+ start = 0;
+
+ for ( i = 0; i < ras.outline.n_contours; i++ )
+ {
+ ras.state = Unknown;
+ ras.gProfile = NULL;
+
+ if ( Decompose_Curve( RAS_VARS start, ras.outline.contours[i], flipped ) )
+ return FAILURE;
+
+ start = ras.outline.contours[i] + 1;
+
+ /* We must now see whether the extreme arcs join or not */
+ if ( FRAC( ras.lastY ) == 0 &&
+ ras.lastY >= ras.minY &&
+ ras.lastY <= ras.maxY )
+ if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow )
+ ras.top--;
+ /* Note that ras.gProfile can be nil if the contour was too small */
+ /* to be drawn. */
+
+ lastProfile = ras.cProfile;
+ if ( End_Profile( RAS_VAR ) )
+ return FAILURE;
+
+ /* close the `next profile in contour' linked list */
+ if ( ras.gProfile )
+ lastProfile->next = ras.gProfile;
+ }
+
+ if ( Finalize_Profile_Table( RAS_VAR ) )
+ return FAILURE;
+
+ return ( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /** **/
+ /** SCAN-LINE SWEEPS AND DRAWING **/
+ /** **/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* Init_Linked */
+ /* */
+ /* Initializes an empty linked list. */
+ /* */
+ static
+ void Init_Linked( TProfileList* l )
+ {
+ *l = NULL;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* InsNew */
+ /* */
+ /* Inserts a new profile in a linked list. */
+ /* */
+ static
+ void InsNew( PProfileList list,
+ PProfile profile )
+ {
+ PProfile *old, current;
+ Long x;
+
+
+ old = list;
+ current = *old;
+ x = profile->X;
+
+ while ( current )
+ {
+ if ( x < current->X )
+ break;
+ old = ¤t->link;
+ current = *old;
+ }
+
+ profile->link = current;
+ *old = profile;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DelOld */
+ /* */
+ /* Removes an old profile from a linked list. */
+ /* */
+ static
+ void DelOld( PProfileList list,
+ PProfile profile )
+ {
+ PProfile *old, current;
+
+
+ old = list;
+ current = *old;
+
+ while ( current )
+ {
+ if ( current == profile )
+ {
+ *old = current->link;
+ return;
+ }
+
+ old = ¤t->link;
+ current = *old;
+ }
+
+ /* we should never get there, unless the profile was not part of */
+ /* the list. */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Update */
+ /* */
+ /* Update all X offsets of a drawing list. */
+ /* */
+ static
+ void Update( PProfile first )
+ {
+ PProfile current = first;
+
+
+ while ( current )
+ {
+ current->X = *current->offset;
+ current->offset += current->flow;
+ current->height--;
+ current = current->link;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Sort */
+ /* */
+ /* Sorts a trace list. In 95%, the list is already sorted. We need */
+ /* an algorithm which is fast in this case. Bubble sort is enough */
+ /* and simple. */
+ /* */
+ static
+ void Sort( PProfileList list )
+ {
+ PProfile *old, current, next;
+
+
+ /* First, set the new X coordinate of each profile */
+ Update( *list );
+
+ /* Then sort them */
+ old = list;
+ current = *old;
+
+ if ( !current )
+ return;
+
+ next = current->link;
+
+ while ( next )
+ {
+ if ( current->X <= next->X )
+ {
+ old = ¤t->link;
+ current = *old;
+
+ if ( !current )
+ return;
+ }
+ else
+ {
+ *old = next;
+ current->link = next->link;
+ next->link = current;
+
+ old = list;
+ current = *old;
+ }
+
+ next = current->link;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Vertical Sweep Procedure Set */
+ /* */
+ /* These four routines are used during the vertical black/white sweep */
+ /* phase by the generic Draw_Sweep() function. */
+ /* */
+ /*************************************************************************/
+
+ static
+ void Vertical_Sweep_Init( RAS_ARGS Short* min,
+ Short* max )
+ {
+ Long pitch = ras.target.pitch;
+
+ FT_UNUSED( max );
+
+
+ ras.traceIncr = (Short)-pitch;
+ ras.traceOfs = -*min * pitch;
+ if ( pitch > 0 )
+ ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
+
+ ras.gray_min_x = 0;
+ ras.gray_max_x = 0;
+ }
+
+
+ static
+ void Vertical_Sweep_Span( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ Long e1, e2;
+ Short c1, c2;
+ Byte f1, f2;
+ Byte* target;
+
+ FT_UNUSED( y );
+ FT_UNUSED( left );
+ FT_UNUSED( right );
+
+
+ /* Drop-out control */
+
+ e1 = TRUNC( CEILING( x1 ) );
+
+ if ( x2 - x1 - ras.precision <= ras.precision_jitter )
+ e2 = e1;
+ else
+ e2 = TRUNC( FLOOR( x2 ) );
+
+ if ( e2 >= 0 && e1 < ras.bWidth )
+ {
+ if ( e1 < 0 )
+ e1 = 0;
+ if ( e2 >= ras.bWidth )
+ e2 = ras.bWidth - 1;
+
+ c1 = (Short)( e1 >> 3 );
+ c2 = (Short)( e2 >> 3 );
+
+ f1 = (unsigned char)0xFF >> ( e1 & 7 );
+ f2 = ~( (unsigned char)0x7F >> ( e2 & 7 ) );
+
+ if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
+ if ( ras.gray_max_x < c2 ) ras.gray_max_x = c2;
+
+ target = ras.bTarget + ras.traceOfs + c1;
+ c2 -= c1;
+
+ if ( c2 > 0 )
+ {
+ target[0] |= f1;
+
+ /* memset() is slower than the following code on many platforms. */
+ /* This is due to the fact that, in the vast majority of cases, */
+ /* the span length in bytes is relatively small. */
+ c2--;
+ while ( c2 > 0 )
+ {
+ *(++target) = 0xFF;
+ c2--;
+ }
+ target[1] |= f2;
+ }
+ else
+ *target |= ( f1 & f2 );
+ }
+ }
+
+
+ static
+ void Vertical_Sweep_Drop( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ Long e1, e2;
+ Short c1, f1;
+
+
+ /* Drop-out control */
+
+ e1 = CEILING( x1 );
+ e2 = FLOOR ( x2 );
+
+ if ( e1 > e2 )
+ {
+ if ( e1 == e2 + ras.precision )
+ {
+ switch ( ras.dropOutControl )
+ {
+ case 1:
+ e1 = e2;
+ break;
+
+ case 4:
+ e1 = CEILING( (x1 + x2 + 1) / 2 );
+ break;
+
+ case 2:
+ case 5:
+ /* Drop-out Control Rule #4 */
+
+ /* The spec is not very clear regarding rule #4. It */
+ /* presents a method that is way too costly to implement */
+ /* while the general idea seems to get rid of `stubs'. */
+ /* */
+ /* Here, we only get rid of stubs recognized if: */
+ /* */
+ /* upper stub: */
+ /* */
+ /* - P_Left and P_Right are in the same contour */
+ /* - P_Right is the successor of P_Left in that contour */
+ /* - y is the top of P_Left and P_Right */
+ /* */
+ /* lower stub: */
+ /* */
+ /* - P_Left and P_Right are in the same contour */
+ /* - P_Left is the successor of P_Right in that contour */
+ /* - y is the bottom of P_Left */
+ /* */
+
+ /* FIXXXME: uncommenting this line solves the disappearing */
+ /* bit problem in the `7' of verdana 10pts, but */
+ /* makes a new one in the `C' of arial 14pts */
+
+#if 0
+ if ( x2 - x1 < ras.precision_half )
+#endif
+ {
+ /* upper stub test */
+ if ( left->next == right && left->height <= 0 )
+ return;
+
+ /* lower stub test */
+ if ( right->next == left && left->start == y )
+ return;
+ }
+
+ /* check that the rightmost pixel isn't set */
+
+ e1 = TRUNC( e1 );
+
+ c1 = (Short)( e1 >> 3 );
+ f1 = e1 & 7;
+
+ if ( e1 >= 0 && e1 < ras.bWidth &&
+ ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
+ return;
+
+ if ( ras.dropOutControl == 2 )
+ e1 = e2;
+ else
+ e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+ break;
+
+ default:
+ return; /* unsupported mode */
+ }
+ }
+ else
+ return;
+ }
+
+ e1 = TRUNC( e1 );
+
+ if ( e1 >= 0 && e1 < ras.bWidth )
+ {
+ c1 = (Short)( e1 >> 3 );
+ f1 = e1 & 7;
+
+ if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
+ if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1;
+
+ ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
+ }
+ }
+
+
+ static
+ void Vertical_Sweep_Step( RAS_ARG )
+ {
+ ras.traceOfs += ras.traceIncr;
+ }
+
+
+ /***********************************************************************/
+ /* */
+ /* Horizontal Sweep Procedure Set */
+ /* */
+ /* These four routines are used during the horizontal black/white */
+ /* sweep phase by the generic Draw_Sweep() function. */
+ /* */
+ /***********************************************************************/
+
+ static
+ void Horizontal_Sweep_Init( RAS_ARGS Short* min,
+ Short* max )
+ {
+ /* nothing, really */
+ FT_UNUSED( raster );
+ FT_UNUSED( min );
+ FT_UNUSED( max );
+ }
+
+
+ static
+ void Horizontal_Sweep_Span( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ Long e1, e2;
+ PByte bits;
+ Byte f1;
+
+ FT_UNUSED( left );
+ FT_UNUSED( right );
+
+
+ if ( x2 - x1 < ras.precision )
+ {
+ e1 = CEILING( x1 );
+ e2 = FLOOR ( x2 );
+
+ if ( e1 == e2 )
+ {
+ bits = ras.bTarget + ( y >> 3 );
+ f1 = (Byte)( 0x80 >> ( y & 7 ) );
+
+ e1 = TRUNC( e1 );
+
+ if ( e1 >= 0 && e1 < ras.target.rows )
+ {
+ PByte p;
+
+
+ p = bits - e1*ras.target.pitch;
+ if ( ras.target.pitch > 0 )
+ p += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+ p[0] |= f1;
+ }
+ }
+ }
+ }
+
+
+ static
+ void Horizontal_Sweep_Drop( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ Long e1, e2;
+ PByte bits;
+ Byte f1;
+
+
+ /* During the horizontal sweep, we only take care of drop-outs */
+
+ e1 = CEILING( x1 );
+ e2 = FLOOR ( x2 );
+
+ if ( e1 > e2 )
+ {
+ if ( e1 == e2 + ras.precision )
+ {
+ switch ( ras.dropOutControl )
+ {
+ case 1:
+ e1 = e2;
+ break;
+
+ case 4:
+ e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+ break;
+
+ case 2:
+ case 5:
+
+ /* Drop-out Control Rule #4 */
+
+ /* The spec is not very clear regarding rule #4. It */
+ /* presents a method that is way too costly to implement */
+ /* while the general idea seems to get rid of `stubs'. */
+ /* */
+
+ /* rightmost stub test */
+ if ( left->next == right && left->height <= 0 )
+ return;
+
+ /* leftmost stub test */
+ if ( right->next == left && left->start == y )
+ return;
+
+ /* check that the rightmost pixel isn't set */
+
+ e1 = TRUNC( e1 );
+
+ bits = ras.bTarget + ( y >> 3 );
+ f1 = (Byte)( 0x80 >> ( y & 7 ) );
+
+ bits -= e1 * ras.target.pitch;
+ if ( ras.target.pitch > 0 )
+ bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+ if ( e1 >= 0 &&
+ e1 < ras.target.rows &&
+ *bits & f1 )
+ return;
+
+ if ( ras.dropOutControl == 2 )
+ e1 = e2;
+ else
+ e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+ break;
+
+ default:
+ return; /* unsupported mode */
+ }
+ }
+ else
+ return;
+ }
+
+ bits = ras.bTarget + ( y >> 3 );
+ f1 = (Byte)( 0x80 >> ( y & 7 ) );
+
+ e1 = TRUNC( e1 );
+
+ if ( e1 >= 0 && e1 < ras.target.rows )
+ {
+ bits -= e1 * ras.target.pitch;
+ if ( ras.target.pitch > 0 )
+ bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+ bits[0] |= f1;
+ }
+ }
+
+
+ static
+ void Horizontal_Sweep_Step( RAS_ARG )
+ {
+ /* Nothing, really */
+ FT_UNUSED( raster );
+ }
+
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+
+ /*************************************************************************/
+ /* */
+ /* Vertical Gray Sweep Procedure Set */
+ /* */
+ /* These two routines are used during the vertical gray-levels sweep */
+ /* phase by the generic Draw_Sweep() function. */
+ /* */
+ /* NOTES */
+ /* */
+ /* - The target pixmap's width *must* be a multiple of 4. */
+ /* */
+ /* - You have to use the function Vertical_Sweep_Span() for the gray */
+ /* span call. */
+ /* */
+ /*************************************************************************/
+
+ static
+ void Vertical_Gray_Sweep_Init( RAS_ARGS Short* min,
+ Short* max )
+ {
+ Long pitch, byte_len;
+
+
+ *min = *min & -2;
+ *max = ( *max + 3 ) & -2;
+
+ ras.traceOfs = 0;
+ pitch = ras.target.pitch;
+ byte_len = -pitch;
+ ras.traceIncr = (Short)byte_len;
+ ras.traceG = ( *min / 2 ) * byte_len;
+
+ if ( pitch > 0 )
+ {
+ ras.traceG += ( ras.target.rows - 1 ) * pitch;
+ byte_len = -byte_len;
+ }
+
+ ras.gray_min_x = (Short)byte_len;
+ ras.gray_max_x = -(Short)byte_len;
+ }
+
+
+ static
+ void Vertical_Gray_Sweep_Step( RAS_ARG )
+ {
+ Int c1, c2;
+ PByte pix, bit, bit2;
+ Int* count = ras.count_table;
+ Byte* grays;
+
+
+ ras.traceOfs += ras.gray_width;
+
+ if ( ras.traceOfs > ras.gray_width )
+ {
+ pix = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
+ grays = ras.grays;
+
+ if ( ras.gray_max_x >= 0 )
+ {
+ Long last_pixel = ras.target.width - 1;
+ Int last_cell = last_pixel >> 2;
+ Int last_bit = last_pixel & 3;
+ Bool over = 0;
+
+
+ if ( ras.gray_max_x >= last_cell && last_bit != 3 )
+ {
+ ras.gray_max_x = last_cell - 1;
+ over = 1;
+ }
+
+ if ( ras.gray_min_x < 0 )
+ ras.gray_min_x = 0;
+
+ bit = ras.bTarget + ras.gray_min_x;
+ bit2 = bit + ras.gray_width;
+
+ c1 = ras.gray_max_x - ras.gray_min_x;
+
+ while ( c1 >= 0 )
+ {
+ c2 = count[*bit] + count[*bit2];
+
+ if ( c2 )
+ {
+ pix[0] = grays[(c2 >> 12) & 0x000F];
+ pix[1] = grays[(c2 >> 8 ) & 0x000F];
+ pix[2] = grays[(c2 >> 4 ) & 0x000F];
+ pix[3] = grays[ c2 & 0x000F];
+
+ *bit = 0;
+ *bit2 = 0;
+ }
+
+ bit++;
+ bit2++;
+ pix += 4;
+ c1--;
+ }
+
+ if ( over )
+ {
+ c2 = count[*bit] + count[*bit2];
+ if ( c2 )
+ {
+ switch ( last_bit )
+ {
+ case 2:
+ pix[2] = grays[(c2 >> 4 ) & 0x000F];
+ case 1:
+ pix[1] = grays[(c2 >> 8 ) & 0x000F];
+ default:
+ pix[0] = grays[(c2 >> 12) & 0x000F];
+ }
+
+ *bit = 0;
+ *bit2 = 0;
+ }
+ }
+ }
+
+ ras.traceOfs = 0;
+ ras.traceG += ras.traceIncr;
+
+ ras.gray_min_x = 32000;
+ ras.gray_max_x = -32000;
+ }
+ }
+
+
+ static
+ void Horizontal_Gray_Sweep_Span( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ /* nothing, really */
+ FT_UNUSED( raster );
+ FT_UNUSED( y );
+ FT_UNUSED( x1 );
+ FT_UNUSED( x2 );
+ FT_UNUSED( left );
+ FT_UNUSED( right );
+ }
+
+
+ static
+ void Horizontal_Gray_Sweep_Drop( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ Long e1, e2;
+ PByte pixel;
+ Byte color;
+
+
+ /* During the horizontal sweep, we only take care of drop-outs */
+ e1 = CEILING( x1 );
+ e2 = FLOOR ( x2 );
+
+ if ( e1 > e2 )
+ {
+ if ( e1 == e2 + ras.precision )
+ {
+ switch ( ras.dropOutControl )
+ {
+ case 1:
+ e1 = e2;
+ break;
+
+ case 4:
+ e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+ break;
+
+ case 2:
+ case 5:
+
+ /* Drop-out Control Rule #4 */
+
+ /* The spec is not very clear regarding rule #4. It */
+ /* presents a method that is way too costly to implement */
+ /* while the general idea seems to get rid of `stubs'. */
+ /* */
+
+ /* rightmost stub test */
+ if ( left->next == right && left->height <= 0 )
+ return;
+
+ /* leftmost stub test */
+ if ( right->next == left && left->start == y )
+ return;
+
+ if ( ras.dropOutControl == 2 )
+ e1 = e2;
+ else
+ e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+ break;
+
+ default:
+ return; /* unsupported mode */
+ }
+ }
+ else
+ return;
+ }
+
+ if ( e1 >= 0 )
+ {
+ if ( x2 - x1 >= ras.precision_half )
+ color = ras.grays[2];
+ else
+ color = ras.grays[1];
+
+ e1 = TRUNC( e1 ) / 2;
+ if ( e1 < ras.target.rows )
+ {
+ pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
+ if ( ras.target.pitch > 0 )
+ pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+ if ( pixel[0] == ras.grays[0] )
+ pixel[0] = color;
+ }
+ }
+ }
+
+
+#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+
+ /*************************************************************************/
+ /* */
+ /* Generic Sweep Drawing routine */
+ /* */
+ /*************************************************************************/
+
+ static
+ Bool Draw_Sweep( RAS_ARG )
+ {
+ Short y, y_change, y_height;
+
+ PProfile P, Q, P_Left, P_Right;
+
+ Short min_Y, max_Y, top, bottom, dropouts;
+
+ Long x1, x2, xs, e1, e2;
+
+ TProfileList wait;
+ TProfileList draw_left, draw_right;
+
+
+ /* Init empty linked lists */
+
+ Init_Linked( &wait );
+
+ Init_Linked( &draw_left );
+ Init_Linked( &draw_right );
+
+ /* first, compute min and max Y */
+
+ P = ras.fProfile;
+ max_Y = (Short)TRUNC( ras.minY );
+ min_Y = (Short)TRUNC( ras.maxY );
+
+ while ( P )
+ {
+ Q = P->link;
+
+ bottom = (Short)P->start;
+ top = (Short)P->start + P->height - 1;
+
+ if ( min_Y > bottom ) min_Y = bottom;
+ if ( max_Y < top ) max_Y = top;
+
+ P->X = 0;
+ InsNew( &wait, P );
+
+ P = Q;
+ }
+
+ /* Check the Y-turns */
+ if ( ras.numTurns == 0 )
+ {
+ ras.error = Raster_Err_Invalid;
+ return FAILURE;
+ }
+
+ /* Now inits the sweep */
+
+ ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
+
+ /* Then compute the distance of each profile from min_Y */
+
+ P = wait;
+
+ while ( P )
+ {
+ P->countL = P->start - min_Y;
+ P = P->link;
+ }
+
+ /* Let's go */
+
+ y = min_Y;
+ y_height = 0;
+
+ if ( ras.numTurns > 0 &&
+ ras.sizeBuff[-ras.numTurns] == min_Y )
+ ras.numTurns--;
+
+ while ( ras.numTurns > 0 )
+ {
+ /* look in the wait list for new activations */
+
+ P = wait;
+
+ while ( P )
+ {
+ Q = P->link;
+ P->countL -= y_height;
+ if ( P->countL == 0 )
+ {
+ DelOld( &wait, P );
+
+ switch ( P->flow )
+ {
+ case Flow_Up:
+ InsNew( &draw_left, P );
+ break;
+
+ case Flow_Down:
+ InsNew( &draw_right, P );
+ break;
+ }
+ }
+
+ P = Q;
+ }
+
+ /* Sort the drawing lists */
+
+ Sort( &draw_left );
+ Sort( &draw_right );
+
+ y_change = (Short)ras.sizeBuff[-ras.numTurns--];
+ y_height = y_change - y;
+
+ while ( y < y_change )
+ {
+ /* Let's trace */
+
+ dropouts = 0;
+
+ P_Left = draw_left;
+ P_Right = draw_right;
+
+ while ( P_Left )
+ {
+ x1 = P_Left ->X;
+ x2 = P_Right->X;
+
+ if ( x1 > x2 )
+ {
+ xs = x1;
+ x1 = x2;
+ x2 = xs;
+ }
+
+ if ( x2 - x1 <= ras.precision )
+ {
+ e1 = FLOOR( x1 );
+ e2 = CEILING( x2 );
+
+ if ( ras.dropOutControl != 0 &&
+ ( e1 > e2 || e2 == e1 + ras.precision ) )
+ {
+ /* a drop out was detected */
+
+ P_Left ->X = x1;
+ P_Right->X = x2;
+
+ /* mark profile for drop-out processing */
+ P_Left->countL = 1;
+ dropouts++;
+
+ goto Skip_To_Next;
+ }
+ }
+
+ ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
+
+ Skip_To_Next:
+
+ P_Left = P_Left->link;
+ P_Right = P_Right->link;
+ }
+
+ /* now perform the dropouts _after_ the span drawing -- */
+ /* drop-outs processing has been moved out of the loop */
+ /* for performance tuning */
+ if ( dropouts > 0 )
+ goto Scan_DropOuts;
+
+ Next_Line:
+
+ ras.Proc_Sweep_Step( RAS_VAR );
+
+ y++;
+
+ if ( y < y_change )
+ {
+ Sort( &draw_left );
+ Sort( &draw_right );
+ }
+ }
+
+ /* Now finalize the profiles that needs it */
+
+ {
+ PProfile Q, P;
+
+
+ P = draw_left;
+ while ( P )
+ {
+ Q = P->link;
+ if ( P->height == 0 )
+ DelOld( &draw_left, P );
+ P = Q;
+ }
+ }
+
+ {
+ PProfile Q, P = draw_right;
+
+
+ while ( P )
+ {
+ Q = P->link;
+ if ( P->height == 0 )
+ DelOld( &draw_right, P );
+ P = Q;
+ }
+ }
+ }
+
+ /* for gray-scaling, flushes the bitmap scanline cache */
+ while ( y <= max_Y )
+ {
+ ras.Proc_Sweep_Step( RAS_VAR );
+ y++;
+ }
+
+ return SUCCESS;
+
+ Scan_DropOuts:
+
+ P_Left = draw_left;
+ P_Right = draw_right;
+
+ while ( P_Left )
+ {
+ if ( P_Left->countL )
+ {
+ P_Left->countL = 0;
+#if 0
+ dropouts--; /* -- this is useful when debugging only */
+#endif
+ ras.Proc_Sweep_Drop( RAS_VARS y,
+ P_Left->X,
+ P_Right->X,
+ P_Left,
+ P_Right );
+ }
+
+ P_Left = P_Left->link;
+ P_Right = P_Right->link;
+ }
+
+ goto Next_Line;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Render_Single_Pass */
+ /* */
+ /* <Description> */
+ /* Performs one sweep with sub-banding. */
+ /* */
+ /* <Input> */
+ /* flipped :: If set, flip the direction of the outline. */
+ /* */
+ /* <Return> */
+ /* Renderer error code. */
+ /* */
+ static
+ int Render_Single_Pass( RAS_ARGS Bool flipped )
+ {
+ Short i, j, k;
+
+
+ while ( ras.band_top >= 0 )
+ {
+ ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
+ ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
+
+ ras.top = ras.buff;
+
+ ras.error = Raster_Err_None;
+
+ if ( Convert_Glyph( RAS_VARS flipped ) )
+ {
+ if ( ras.error != Raster_Err_Overflow )
+ return FAILURE;
+
+ ras.error = Raster_Err_None;
+
+ /* sub-banding */
+
+#ifdef DEBUG_RASTER
+ ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
+#endif
+
+ i = ras.band_stack[ras.band_top].y_min;
+ j = ras.band_stack[ras.band_top].y_max;
+
+ k = ( i + j ) / 2;
+
+ if ( ras.band_top >= 7 || k < i )
+ {
+ ras.band_top = 0;
+ ras.error = Raster_Err_Invalid;
+
+ return ras.error;
+ }
+
+ ras.band_stack[ras.band_top + 1].y_min = k;
+ ras.band_stack[ras.band_top + 1].y_max = j;
+
+ ras.band_stack[ras.band_top].y_max = k - 1;
+
+ ras.band_top++;
+ }
+ else
+ {
+ if ( ras.fProfile )
+ if ( Draw_Sweep( RAS_VAR ) )
+ return ras.error;
+ ras.band_top--;
+ }
+ }
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Render_Glyph */
+ /* */
+ /* <Description> */
+ /* Renders a glyph in a bitmap. Sub-banding if needed. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* XXX Fixme: ftraster's error codes don't harmonize with FT2's ones! */
+ /* */
+ LOCAL_FUNC
+ FT_Error Render_Glyph( RAS_ARG )
+ {
+ FT_Error error;
+
+
+ Set_High_Precision( RAS_VARS ras.outline.flags &
+ ft_outline_high_precision );
+ ras.scale_shift = ras.precision_shift;
+ ras.dropOutControl = 2;
+ ras.second_pass = !( ras.outline.flags & ft_outline_single_pass );
+
+ /* Vertical Sweep */
+ ras.Proc_Sweep_Init = Vertical_Sweep_Init;
+ ras.Proc_Sweep_Span = Vertical_Sweep_Span;
+ ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
+ ras.Proc_Sweep_Step = Vertical_Sweep_Step;
+
+ ras.band_top = 0;
+ ras.band_stack[0].y_min = 0;
+ ras.band_stack[0].y_max = ras.target.rows - 1;
+
+ ras.bWidth = ras.target.width;
+ ras.bTarget = (Byte*)ras.target.buffer;
+
+ if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
+ return error;
+
+ /* Horizontal Sweep */
+ if ( ras.second_pass && ras.dropOutControl != 0 )
+ {
+ ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
+ ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
+ ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
+ ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
+
+ ras.band_top = 0;
+ ras.band_stack[0].y_min = 0;
+ ras.band_stack[0].y_max = ras.target.width - 1;
+
+ if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
+ return error;
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Render_Gray_Glyph */
+ /* */
+ /* <Description> */
+ /* Renders a glyph with grayscaling. Sub-banding if needed. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error Render_Gray_Glyph( RAS_ARG )
+ {
+ Long pixel_width;
+ FT_Error error;
+
+
+ Set_High_Precision( RAS_VARS ras.outline.flags &
+ ft_outline_high_precision );
+ ras.scale_shift = ras.precision_shift + 1;
+ ras.dropOutControl = 2;
+ ras.second_pass = !( ras.outline.flags & ft_outline_single_pass );
+
+ /* Vertical Sweep */
+
+ ras.band_top = 0;
+ ras.band_stack[0].y_min = 0;
+ ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
+
+ ras.bWidth = ras.gray_width;
+ pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
+
+ if ( ras.bWidth > pixel_width )
+ ras.bWidth = pixel_width;
+
+ ras.bWidth = ras.bWidth * 8;
+ ras.bTarget = (Byte*)ras.gray_lines;
+ ras.gTarget = (Byte*)ras.target.buffer;
+
+ ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
+ ras.Proc_Sweep_Span = Vertical_Sweep_Span;
+ ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
+ ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
+
+ error = Render_Single_Pass( RAS_VARS 0 );
+ if ( error )
+ return error;
+
+ /* Horizontal Sweep */
+ if ( ras.second_pass && ras.dropOutControl != 0 )
+ {
+ ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
+ ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
+ ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
+ ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
+
+ ras.band_top = 0;
+ ras.band_stack[0].y_min = 0;
+ ras.band_stack[0].y_max = ras.target.width * 2 - 1;
+
+ error = Render_Single_Pass( RAS_VARS 1 );
+ if ( error )
+ return error;
+ }
+
+ return FT_Err_Ok;
+ }
+
+#else /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+ LOCAL_FUNC
+ FT_Error Render_Gray_Glyph( RAS_ARG )
+ {
+ FT_UNUSED_RASTER;
+
+ return FT_Err_Cannot_Render_Glyph;
+ }
+
+#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+
+ static
+ void ft_black_init( TRaster_Instance* raster )
+ {
+ FT_UInt n;
+ FT_ULong c;
+
+
+ /* setup count table */
+ for ( n = 0; n < 256; n++ )
+ {
+ c = ( n & 0x55 ) + ( ( n & 0xAA ) >> 1 );
+
+ c = ( ( c << 6 ) & 0x3000 ) |
+ ( ( c << 4 ) & 0x0300 ) |
+ ( ( c << 2 ) & 0x0030 ) |
+ (c & 0x0003 );
+
+ raster->count_table[n] = c;
+ }
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+ /* set default 5-levels gray palette */
+ for ( n = 0; n < 5; n++ )
+ raster->grays[n] = n * 255 / 4;
+
+ raster->gray_width = RASTER_GRAY_LINES / 2;
+
+#endif
+ }
+
+
+ /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
+ /**** a static object. *****/
+
+
+#ifdef _STANDALONE_
+
+
+ static
+ int ft_black_new( void* memory,
+ FT_Raster *araster )
+ {
+ static FT_RasterRec_ the_raster;
+
+
+ *araster = &the_raster;
+ memset( &the_raster, sizeof ( the_raster ), 0 );
+ ft_black_init( &the_raster );
+
+ return 0;
+ }
+
+
+ static
+ void ft_black_done( FT_Raster raster )
+ {
+ /* nothing */
+ raster->init = 0;
+ }
+
+
+#else /* _STANDALONE_ */
+
+
+ static
+ int ft_black_new( FT_Memory memory,
+ TRaster_Instance** araster )
+ {
+ FT_Error error;
+ TRaster_Instance* raster;
+
+
+ *araster = 0;
+ if ( !ALLOC( raster, sizeof ( *raster ) ) )
+ {
+ raster->memory = memory;
+ ft_black_init( raster );
+
+ *araster = raster;
+ }
+
+ return error;
+ }
+
+
+ static
+ void ft_black_done( TRaster_Instance* raster )
+ {
+ FT_Memory memory = (FT_Memory)raster->memory;
+ FREE( raster );
+ }
+
+
+#endif /* _STANDALONE_ */
+
+
+ static
+ void ft_black_reset( TRaster_Instance* raster,
+ const char* pool_base,
+ long pool_size )
+ {
+ if ( raster && pool_base && pool_size >= 4096 )
+ {
+ /* save the pool */
+ raster->buff = (PLong)pool_base;
+ raster->sizeBuff = raster->buff + pool_size / sizeof ( Long );
+ }
+ }
+
+
+ static
+ void ft_black_set_mode( TRaster_Instance* raster,
+ unsigned long mode,
+ const char* palette )
+ {
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+ if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
+ {
+ /* set 5-levels gray palette */
+ raster->grays[0] = palette[0];
+ raster->grays[1] = palette[1];
+ raster->grays[2] = palette[2];
+ raster->grays[3] = palette[3];
+ raster->grays[4] = palette[4];
+ }
+
+#else
+
+ FT_UNUSED( raster );
+ FT_UNUSED( mode );
+ FT_UNUSED( palette );
+
+#endif
+ }
+
+
+ static
+ int ft_black_render( TRaster_Instance* raster,
+ FT_Raster_Params* params )
+ {
+ FT_Outline* outline = (FT_Outline*)params->source;
+ FT_Bitmap* target_map = params->target;
+
+
+ if ( !raster || !raster->buff || !raster->sizeBuff )
+ return Raster_Err_Not_Ini;
+
+ if ( !outline || !outline->contours || !outline->points )
+ return Raster_Err_Invalid;
+
+ /* return immediately if the outline is empty */
+ if ( outline->n_points == 0 || outline->n_contours <= 0 )
+ return Raster_Err_None;
+
+ if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 )
+ return Raster_Err_Invalid;
+
+ if ( !target_map || !target_map->buffer )
+ return Raster_Err_Invalid;
+
+ /* this version of the raster does not support direct rendering, sorry */
+ if ( params->flags & ft_raster_flag_direct )
+ return Raster_Err_Unsupported;
+
+ ras.outline = *outline;
+ ras.target = *target_map;
+
+ return ( ( params->flags & ft_raster_flag_aa )
+ ? Render_Gray_Glyph( raster )
+ : Render_Glyph( raster ) );
+ }
+
+
+ FT_Raster_Funcs ft_standard_raster =
+ {
+ ft_glyph_format_outline,
+ (FT_Raster_New_Func) ft_black_new,
+ (FT_Raster_Reset_Func) ft_black_reset,
+ (FT_Raster_Set_Mode_Func)ft_black_set_mode,
+ (FT_Raster_Render_Func) ft_black_render,
+ (FT_Raster_Done_Func) ft_black_done
+ };
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftraster.h */
+/* */
+/* The FreeType glyph rasterizer (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used */
+/* modified and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTRASTER_H
+#define FTRASTER_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include <freetype/ftimage.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* Uncomment the following line if you are using ftraster.c as a */
+ /* standalone module, fully independent of FreeType. */
+ /* */
+/* #define _STANDALONE_ */
+
+#ifndef FT_EXPORT_VAR
+#define FT_EXPORT_VAR( x ) extern x
+#endif
+
+ FT_EXPORT_VAR( FT_Raster_Funcs ) ft_standard_raster;
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* FTRASTER_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftrend1.c */
+/* */
+/* The FreeType glyph rasterizer interface (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/ftoutln.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ftrend1.h"
+#include "ftraster.h"
+
+#else
+
+#include <raster1/ftrend1.h>
+#include <raster1/ftraster.h>
+
+#endif
+
+
+ /* initialize renderer -- init its raster */
+ static
+ FT_Error ft_raster1_init( FT_Renderer render )
+ {
+ FT_Library library = FT_MODULE_LIBRARY( render );
+
+
+ render->clazz->raster_class->raster_reset( render->raster,
+ library->raster_pool,
+ library->raster_pool_size );
+
+ return FT_Err_Ok;
+ }
+
+
+ /* set render-specific mode */
+ static
+ FT_Error ft_raster1_set_mode( FT_Renderer render,
+ FT_ULong mode_tag,
+ FT_Pointer data )
+ {
+ /* we simply pass it to the raster */
+ return render->clazz->raster_class->raster_set_mode( render->raster,
+ mode_tag,
+ data );
+ }
+
+
+ /* transform a given glyph image */
+ static
+ FT_Error ft_raster1_transform( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_Matrix* matrix,
+ FT_Vector* delta )
+ {
+ FT_Error error = FT_Err_Ok;
+
+
+ if ( slot->format != render->glyph_format )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ if ( matrix )
+ FT_Outline_Transform( &slot->outline, matrix );
+
+ if ( delta )
+ FT_Outline_Translate( &slot->outline, delta->x, delta->y );
+
+ Exit:
+ return error;
+ }
+
+
+ /* return the glyph's control box */
+ static
+ void ft_raster1_get_cbox( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_BBox* cbox )
+ {
+ MEM_Set( cbox, 0, sizeof ( *cbox ) );
+
+ if ( slot->format == render->glyph_format )
+ FT_Outline_Get_CBox( &slot->outline, cbox );
+ }
+
+
+ /* convert a slot's glyph image into a bitmap */
+ static
+ FT_Error ft_raster1_render( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_UInt mode,
+ FT_Vector* origin )
+ {
+ FT_Error error;
+ FT_Outline* outline;
+ FT_BBox cbox;
+ FT_UInt width, height, pitch;
+ FT_Bitmap* bitmap;
+ FT_Memory memory;
+
+ FT_Raster_Params params;
+
+
+ /* check glyph image format */
+ if ( slot->format != render->glyph_format )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* check rendering mode */
+ if ( mode != ft_render_mode_mono )
+ {
+ /* raster1 is only capable of producing monochrome bitmaps */
+ if ( render->clazz == &ft_raster1_renderer_class )
+ return FT_Err_Cannot_Render_Glyph;
+ }
+ else
+ {
+ /* raster5 is only capable of producing 5-gray-levels bitmaps */
+ if ( render->clazz == &ft_raster5_renderer_class )
+ return FT_Err_Cannot_Render_Glyph;
+ }
+
+ outline = &slot->outline;
+
+ /* translate the outline to the new origin if needed */
+ if ( origin )
+ FT_Outline_Translate( outline, origin->x, origin->y );
+
+ /* compute the control box, and grid fit it */
+ FT_Outline_Get_CBox( outline, &cbox );
+
+ cbox.xMin &= -64;
+ cbox.yMin &= -64;
+ cbox.xMax = ( cbox.xMax + 63 ) & -64;
+ cbox.yMax = ( cbox.yMax + 63 ) & -64;
+
+ width = ( cbox.xMax - cbox.xMin ) >> 6;
+ height = ( cbox.yMax - cbox.yMin ) >> 6;
+ bitmap = &slot->bitmap;
+ memory = render->root.memory;
+
+ /* release old bitmap buffer */
+ if ( slot->flags & ft_glyph_own_bitmap )
+ {
+ FREE( bitmap->buffer );
+ slot->flags &= ~ft_glyph_own_bitmap;
+ }
+
+ /* allocate new one, depends on pixel format */
+ if ( !( mode & ft_render_mode_mono ) )
+ {
+ /* we pad to 32 bits, only for backwards compatibility with FT 1.x */
+ pitch = ( width + 3 ) & -4;
+ bitmap->pixel_mode = ft_pixel_mode_grays;
+ bitmap->num_grays = 256;
+ }
+ else
+ {
+ pitch = ( width + 7 ) >> 3;
+ bitmap->pixel_mode = ft_pixel_mode_mono;
+ }
+
+ bitmap->width = width;
+ bitmap->rows = height;
+ bitmap->pitch = pitch;
+
+ if ( ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
+ goto Exit;
+
+ slot->flags |= ft_glyph_own_bitmap;
+
+ /* translate outline to render it into the bitmap */
+ FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin );
+
+ /* set up parameters */
+ params.target = bitmap;
+ params.source = outline;
+ params.flags = 0;
+
+ if ( bitmap->pixel_mode == ft_pixel_mode_grays )
+ params.flags |= ft_raster_flag_aa;
+
+ /* render outline into the bitmap */
+ error = render->raster_render( render->raster, ¶ms );
+ if ( error )
+ goto Exit;
+
+ slot->format = ft_glyph_format_bitmap;
+ slot->bitmap_left = cbox.xMin >> 6;
+ slot->bitmap_top = cbox.yMax >> 6;
+
+ Exit:
+ return error;
+ }
+
+
+ const FT_Renderer_Class ft_raster1_renderer_class =
+ {
+ {
+ ft_module_renderer,
+ sizeof( FT_RendererRec ),
+
+ "raster1",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* module specific interface */
+
+ (FT_Module_Constructor)ft_raster1_init,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+ },
+
+ ft_glyph_format_outline,
+
+ (FTRenderer_render) ft_raster1_render,
+ (FTRenderer_transform)ft_raster1_transform,
+ (FTRenderer_getCBox) ft_raster1_get_cbox,
+ (FTRenderer_setMode) ft_raster1_set_mode,
+
+ (FT_Raster_Funcs*) &ft_standard_raster
+ };
+
+
+ /* this renderer is _NOT_ part of the default modules, you'll need */
+ /* to register it by hand in your application. It should only be */
+ /* used for backwards-compatibility with FT 1.x anyway. */
+ const FT_Renderer_Class ft_raster5_renderer_class =
+ {
+ {
+ ft_module_renderer,
+ sizeof( FT_RendererRec ),
+
+ "raster5",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* module specific interface */
+
+ (FT_Module_Constructor)ft_raster1_init,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+ },
+
+ ft_glyph_format_outline,
+
+ (FTRenderer_render) ft_raster1_render,
+ (FTRenderer_transform)ft_raster1_transform,
+ (FTRenderer_getCBox) ft_raster1_get_cbox,
+ (FTRenderer_setMode) ft_raster1_set_mode,
+
+ (FT_Raster_Funcs*) &ft_standard_raster
+ };
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftrend1.h */
+/* */
+/* The FreeType glyph rasterizer interface (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTREND1_H
+#define FTREND1_H
+
+#include <freetype/ftrender.h>
+
+
+ FT_EXPORT_VAR( const FT_Renderer_Class ) ft_raster1_renderer_class;
+
+ /* this renderer is _NOT_ part of the default modules, you'll need */
+ /* to register it by hand in your application. It should only be */
+ /* used for backwards-compatibility with FT 1.x anyway. */
+ /* */
+ FT_EXPORT_VAR( const FT_Renderer_Class ) ft_raster5_renderer_class;
+
+
+#endif /* FTREND1_H */
+
+
+/* END */
--- /dev/null
+make_module_list: add_raster1_module
+
+add_raster1_module:
+ $(OPEN_DRIVER)ft_raster1_renderer_class$(CLOSE_DRIVER)
+ $(ECHO_DRIVER)raster1 $(ECHO_DRIVER_DESC)monochrome bitmap renderer$(ECHO_DRIVER_DONE)
+
+# EOF
--- /dev/null
+/***************************************************************************/
+/* */
+/* raster1.c */
+/* */
+/* FreeType monochrome rasterer module component (body only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ftraster.c"
+#include "ftrend1.c"
+
+#else
+
+#include <raster1/ftraster.c>
+#include <raster1/ftrend1.c>
+
+#endif
+
+
+/* END */
--- /dev/null
+#
+# FreeType 2 renderer module build rules
+#
+
+
+# Copyright 1996-2000 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# raster1 driver directory
+#
+RAS1_DIR := $(SRC_)raster1
+RAS1_DIR_ := $(RAS1_DIR)$(SEP)
+
+# compilation flags for the driver
+#
+RAS1_COMPILE := $(FT_COMPILE)
+
+
+# raster1 driver sources (i.e., C files)
+#
+RAS1_DRV_SRC := $(RAS1_DIR_)ftraster.c \
+ $(RAS1_DIR_)ftrend1.c
+
+
+# raster1 driver headers
+#
+RAS1_DRV_H := $(RAS1_DRV_SRC:%.c=%.h)
+
+
+# raster1 driver object(s)
+#
+# RAS1_DRV_OBJ_M is used during `multi' builds.
+# RAS1_DRV_OBJ_S is used during `single' builds.
+#
+RAS1_DRV_OBJ_M := $(RAS1_DRV_SRC:$(RAS1_DIR_)%.c=$(OBJ_)%.$O)
+RAS1_DRV_OBJ_S := $(OBJ_)raster1.$O
+
+# raster1 driver source file for single build
+#
+RAS1_DRV_SRC_S := $(RAS1_DIR_)raster1.c
+
+
+# raster1 driver - single object
+#
+$(RAS1_DRV_OBJ_S): $(RAS1_DRV_SRC_S) $(RAS1_DRV_SRC) \
+ $(FREETYPE_H) $(RAS1_DRV_H)
+ $(RAS1_COMPILE) $T$@ $(RAS1_DRV_SRC_S)
+
+
+# raster1 driver - multiple objects
+#
+$(OBJ_)%.$O: $(RAS1_DIR_)%.c $(FREETYPE_H) $(RAS1_DRV_H)
+ $(RAS1_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(RAS1_DRV_OBJ_S)
+DRV_OBJS_M += $(RAS1_DRV_OBJ_M)
+
+
+# EOF
--- /dev/null
+make_module_list: add_sfnt_module
+
+add_sfnt_module:
+ $(OPEN_DRIVER)sfnt_module_class$(CLOSE_DRIVER)
+ $(ECHO_DRIVER)sfnt $(ECHO_DRIVER_DESC)helper module for TrueType & OpenType formats$(ECHO_DRIVER_DONE)
+
+# EOF
--- /dev/null
+#
+# FreeType 2 SFNT driver configuration rules
+#
+
+
+# Copyright 1996-2000 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# SFNT driver directory
+#
+SFNT_DIR := $(SRC_)sfnt
+SFNT_DIR_ := $(SFNT_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+SFNT_COMPILE := $(FT_COMPILE)
+
+
+# SFNT driver sources (i.e., C files)
+#
+SFNT_DRV_SRC := $(SFNT_DIR_)ttload.c \
+ $(SFNT_DIR_)ttcmap.c \
+ $(SFNT_DIR_)ttsbit.c \
+ $(SFNT_DIR_)ttpost.c \
+ $(SFNT_DIR_)sfobjs.c \
+ $(SFNT_DIR_)sfdriver.c
+
+# SFNT driver headers
+#
+SFNT_DRV_H := $(SFNT_DRV_SRC:%c=%h)
+
+
+# SFNT driver object(s)
+#
+# SFNT_DRV_OBJ_M is used during `multi' builds.
+# SFNT_DRV_OBJ_S is used during `single' builds.
+#
+SFNT_DRV_OBJ_M := $(SFNT_DRV_SRC:$(SFNT_DIR_)%.c=$(OBJ_)%.$O)
+SFNT_DRV_OBJ_S := $(OBJ_)sfnt.$O
+
+# SFNT driver source file for single build
+#
+SFNT_DRV_SRC_S := $(SFNT_DIR_)sfnt.c
+
+
+# SFNT driver - single object
+#
+$(SFNT_DRV_OBJ_S): $(SFNT_DRV_SRC_S) $(SFNT_DRV_SRC) \
+ $(FREETYPE_H) $(SFNT_DRV_H)
+ $(SFNT_COMPILE) $T$@ $(SFNT_DRV_SRC_S)
+
+
+# SFNT driver - multiple objects
+#
+$(OBJ_)%.$O: $(SFNT_DIR_)%.c $(FREETYPE_H) $(SFNT_DRV_H)
+ $(SFNT_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(SFNT_DRV_OBJ_S)
+DRV_OBJS_M += $(SFNT_DRV_OBJ_M)
+
+
+# EOF
--- /dev/null
+/***************************************************************************/
+/* */
+/* sfdriver.c */
+/* */
+/* High-level SFNT driver interface (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/sfnt.h>
+#include <freetype/internal/ftobjs.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "sfdriver.h"
+#include "ttload.h"
+#include "ttsbit.h"
+#include "ttpost.h"
+#include "ttcmap.h"
+#include "sfobjs.h"
+
+#else
+
+#include <sfnt/sfdriver.h>
+#include <sfnt/ttload.h>
+#include <sfnt/ttsbit.h>
+#include <sfnt/ttpost.h>
+#include <sfnt/ttcmap.h>
+#include <sfnt/sfobjs.h>
+
+#endif
+
+
+#include <string.h> /* for strcmp() */
+
+
+ static
+ void* get_sfnt_table( TT_Face face,
+ FT_Sfnt_Tag tag )
+ {
+ void* table;
+
+
+ switch ( tag )
+ {
+ case ft_sfnt_head:
+ table = &face->header;
+ break;
+
+ case ft_sfnt_hhea:
+ table = &face->horizontal;
+ break;
+
+ case ft_sfnt_vhea:
+ table = face->vertical_info ? &face->vertical : 0;
+ break;
+
+ case ft_sfnt_os2:
+ table = face->os2.version == 0xFFFF ? 0 : &face->os2;
+ break;
+
+ case ft_sfnt_post:
+ table = &face->postscript;
+ break;
+
+ case ft_sfnt_maxp:
+ table = &face->max_profile;
+ break;
+
+ case ft_sfnt_pclt:
+ table = face->pclt.Version ? &face->pclt : 0;
+ break;
+
+ default:
+ table = 0;
+ }
+
+ return table;
+ }
+
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+ static
+ FT_Error get_sfnt_glyph_name( TT_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max )
+ {
+ FT_String* gname;
+ FT_Error error;
+
+
+ error = TT_Get_PS_Name( face, glyph_index, &gname );
+ if ( !error && buffer_max > 0 )
+ {
+ FT_UInt len = strlen( gname );
+
+
+ if ( len >= buffer_max )
+ len = buffer_max - 1;
+
+ MEM_Copy( buffer, gname, len );
+ ((FT_Byte*)buffer)[len] = 0;
+ }
+
+ return error;
+ }
+
+
+#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+
+ static
+ FT_Module_Interface SFNT_Get_Interface( FT_Module module,
+ const char* interface )
+ {
+ FT_UNUSED( module );
+
+ if ( strcmp( interface, "get_sfnt" ) == 0 )
+ return (FT_Module_Interface)get_sfnt_table;
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+ if ( strcmp( interface, "glyph_name" ) == 0 )
+ return (FT_Module_Interface)get_sfnt_glyph_name;
+#endif
+ return 0;
+ }
+
+
+ static
+ const SFNT_Interface sfnt_interface =
+ {
+ TT_Goto_Table,
+
+ SFNT_Init_Face,
+ SFNT_Load_Face,
+ SFNT_Done_Face,
+ SFNT_Get_Interface,
+
+ TT_Load_Any,
+ TT_Load_SFNT_Header,
+ TT_Load_Directory,
+
+ TT_Load_Header,
+ TT_Load_Metrics_Header,
+ TT_Load_CMap,
+ TT_Load_MaxProfile,
+ TT_Load_OS2,
+ TT_Load_PostScript,
+
+ TT_Load_Names,
+ TT_Free_Names,
+
+ TT_Load_Hdmx,
+ TT_Free_Hdmx,
+
+ TT_Load_Kern,
+ TT_Load_Gasp,
+ TT_Load_PCLT,
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+ /* see `ttsbit.h' */
+ TT_Load_SBit_Strikes,
+ TT_Load_SBit_Image,
+ TT_Free_SBit_Strikes,
+
+#else /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+ 0,
+ 0,
+ 0,
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+ /* see `ttpost.h' */
+ TT_Get_PS_Name,
+ TT_Free_Post_Names,
+
+#else /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+ 0,
+ 0,
+
+#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+ /* see `ttcmap.h' */
+ TT_CharMap_Load,
+ TT_CharMap_Free,
+ };
+
+
+ const
+ FT_Module_Class sfnt_module_class =
+ {
+ 0, /* not a font driver or renderer */
+ sizeof( FT_ModuleRec ),
+
+ "sfnt", /* driver name */
+ 0x10000L, /* driver version 1.0 */
+ 0x20000L, /* driver requires FreeType 2.0 or higher */
+
+ (const void*)&sfnt_interface, /* module specific interface */
+
+ (FT_Module_Constructor)0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) SFNT_Get_Interface
+ };
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* sfdriver.h */
+/* */
+/* High-level SFNT driver interface (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef SFDRIVER_H
+#define SFDRIVER_H
+
+#include <freetype/ftmodule.h>
+
+ FT_EXPORT_VAR( const FT_Module_Class ) sfnt_module_class;
+
+#endif /* SFDRIVER_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* sfnt.c */
+/* */
+/* Single object library component. */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttload.c"
+#include "ttcmap.c"
+#include "sfobjs.c"
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+#include "ttsbit.c"
+#endif
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+#include "ttpost.c"
+#endif
+
+#include "sfdriver.c"
+
+#else /* FT_FLAT_COMPILE */
+
+#include <sfnt/ttload.c>
+#include <sfnt/ttcmap.c>
+#include <sfnt/sfobjs.c>
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+#include <sfnt/ttsbit.c>
+#endif
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+#include <sfnt/ttpost.c>
+#endif
+
+#include <sfnt/sfdriver.c>
+
+#endif /* FT_FLAT_COMPILE */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* sfobjs.c */
+/* */
+/* SFNT object management (base). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "sfobjs.h"
+
+#else
+
+#include <sfnt/sfobjs.h>
+
+#endif
+
+
+#include <freetype/internal/sfnt.h>
+#include <freetype/internal/psnames.h>
+#include <freetype/ttnameid.h>
+#include <freetype/internal/tterrors.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_sfobjs
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Name */
+ /* */
+ /* <Description> */
+ /* Returns a given ENGLISH name record in ASCII. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* nameid :: The name id of the name record to return. */
+ /* */
+ /* <Return> */
+ /* Character string. NULL if no name is present. */
+ /* */
+ static
+ FT_String* Get_Name( TT_Face face,
+ FT_UShort nameid )
+ {
+ FT_Memory memory = face->root.memory;
+ FT_UShort n;
+ TT_NameRec* rec;
+ FT_Bool wide_chars = 1;
+
+
+ rec = face->name_table.names;
+ for ( n = 0; n < face->name_table.numNameRecords; n++, rec++ )
+ {
+ if ( rec->nameID == nameid )
+ {
+ /* found the name -- now create an ASCII string from it */
+ FT_Bool found = 0;
+
+
+ /* test for Microsoft English language */
+ if ( rec->platformID == TT_PLATFORM_MICROSOFT &&
+ rec->encodingID <= TT_MS_ID_UNICODE_CS &&
+ ( rec->languageID & 0x3FF ) == 0x009 )
+ found = 1;
+
+ /* test for Apple Unicode encoding */
+ else if ( rec->platformID == TT_PLATFORM_APPLE_UNICODE )
+ found = 1;
+
+ /* test for Apple Roman */
+ else if ( rec->platformID == TT_PLATFORM_MACINTOSH &&
+ rec->languageID == TT_MAC_ID_ROMAN )
+ {
+ found = 1;
+ wide_chars = 0;
+ }
+
+ /* found a Unicode name */
+ if ( found )
+ {
+ FT_String* string;
+ FT_UInt len;
+
+
+ if ( wide_chars )
+ {
+ FT_UInt m;
+
+
+ len = (FT_UInt)rec->stringLength / 2;
+ if ( MEM_Alloc( string, len + 1 ) )
+ return NULL;
+
+ for ( m = 0; m < len; m ++ )
+ string[m] = rec->string[2 * m + 1];
+ }
+ else
+ {
+ len = rec->stringLength;
+ if ( MEM_Alloc( string, len + 1 ) )
+ return NULL;
+
+ MEM_Copy( string, rec->string, len );
+ }
+
+ string[len] = '\0';
+ return string;
+ }
+ }
+ }
+
+ return NULL;
+ }
+
+
+ static
+ FT_Encoding find_encoding( int platform_id,
+ int encoding_id )
+ {
+ typedef struct TEncoding
+ {
+ int platform_id;
+ int encoding_id;
+ FT_Encoding encoding;
+
+ } TEncoding;
+
+ static
+ const TEncoding tt_encodings[] =
+ {
+ { TT_PLATFORM_ISO, -1, ft_encoding_unicode },
+
+ { TT_PLATFORM_APPLE_UNICODE, -1, ft_encoding_unicode },
+
+ { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, ft_encoding_apple_roman },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, ft_encoding_unicode },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, ft_encoding_sjis },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, ft_encoding_gb2312 },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, ft_encoding_big5 },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, ft_encoding_wansung },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, ft_encoding_johab }
+ };
+
+ const TEncoding *cur, *limit;
+
+
+ cur = tt_encodings;
+ limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
+
+ for ( ; cur < limit; cur++ )
+ {
+ if ( cur->platform_id == platform_id )
+ {
+ if ( cur->encoding_id == encoding_id ||
+ cur->encoding_id == -1 )
+ return cur->encoding;
+ }
+ }
+
+ return ft_encoding_none;
+ }
+
+
+ LOCAL_FUNC
+ FT_Error SFNT_Init_Face( FT_Stream stream,
+ TT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error;
+ FT_Library library = face->root.driver->root.library;
+ SFNT_Interface* sfnt;
+ SFNT_Header sfnt_header;
+
+ /* for now, parameters are unused */
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+
+ sfnt = (SFNT_Interface*)face->sfnt;
+ if ( !sfnt )
+ {
+ sfnt = (SFNT_Interface*)FT_Get_Module_Interface( library, "sfnt" );
+ if ( !sfnt )
+ {
+ error = FT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ face->sfnt = sfnt;
+ face->goto_table = sfnt->goto_table;
+ }
+
+ if ( !face->psnames )
+ {
+ face->psnames = (PSNames_Interface*)
+ FT_Get_Module_Interface( library, "psnames" );
+ }
+
+ /* check that we have a valid TrueType file */
+ error = sfnt->load_sfnt_header( face, stream, face_index, &sfnt_header );
+ if ( error )
+ goto Exit;
+
+ face->format_tag = sfnt_header.format_tag;
+ face->num_tables = sfnt_header.num_tables;
+
+ /* Load font directory */
+ error = sfnt->load_directory( face, stream, &sfnt_header );
+ if ( error )
+ goto Exit;
+
+ face->root.num_faces = face->ttc_header.count;
+ if ( face->root.num_faces < 1 )
+ face->root.num_faces = 1;
+
+ Exit:
+ return error;
+ }
+
+
+#undef LOAD_
+#define LOAD_( x ) ( ( error = sfnt->load_##x( face, stream ) ) \
+ != TT_Err_Ok )
+
+
+ LOCAL_FUNC
+ FT_Error SFNT_Load_Face( FT_Stream stream,
+ TT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error;
+ SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt;
+
+ FT_UNUSED( face_index );
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+
+
+ /* Load tables */
+ if ( LOAD_( header ) ||
+ LOAD_( max_profile ) ||
+
+ /* load the `hhea' & `hmtx' tables at once */
+ ( error = sfnt->load_metrics( face, stream, 0 ) ) != TT_Err_Ok ||
+
+ /* try to load the `vhea' & `vmtx' at once if present */
+ ( error = sfnt->load_metrics( face, stream, 1 ) ) != TT_Err_Ok ||
+
+ LOAD_( charmaps ) ||
+ LOAD_( names ) ||
+ LOAD_( os2 ) ||
+ LOAD_( psnames ) )
+ goto Exit;
+
+ /* the optional tables */
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+ /* embedded bitmap support. */
+ if ( sfnt->load_sbits && LOAD_( sbits ) )
+ goto Exit;
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+ if ( LOAD_( hdmx ) ||
+ LOAD_( gasp ) ||
+ LOAD_( kerning ) ||
+ LOAD_( pclt ) )
+ goto Exit;
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+ if ( ( error = TT_Extension_Create( face ) ) != TT_Err_Ok )
+ goto Exit;
+#endif
+
+ face->root.family_name = Get_Name( face, TT_NAME_ID_FONT_FAMILY );
+ face->root.style_name = Get_Name( face, TT_NAME_ID_FONT_SUBFAMILY );
+
+ /* now set up root fields */
+ {
+ FT_Face root = &face->root;
+ FT_Int flags;
+ TT_CharMap charmap;
+ FT_Int n;
+ FT_Memory memory;
+
+
+ memory = root->memory;
+
+ /*********************************************************************/
+ /* */
+ /* Compute face flags. */
+ /* */
+ flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */
+ FT_FACE_FLAG_SFNT | /* SFNT file format */
+ FT_FACE_FLAG_HORIZONTAL; /* horizontal data */
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+ /* might need more polish to detect the presence of a Postscript */
+ /* name table in the font */
+ flags |= FT_FACE_FLAG_GLYPH_NAMES;
+#endif
+
+ /* fixed width font? */
+ if ( face->postscript.isFixedPitch )
+ flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ /* vertical information? */
+ if ( face->vertical_info )
+ flags |= FT_FACE_FLAG_VERTICAL;
+
+ /* kerning available ? */
+ if ( face->kern_pairs )
+ flags |= FT_FACE_FLAG_KERNING;
+
+ root->face_flags = flags;
+
+ /*********************************************************************/
+ /* */
+ /* Compute style flags. */
+ /* */
+ flags = 0;
+
+ if ( face->os2.version != 0xFFFF )
+ {
+ /* we have an OS/2 table; use the `fsSelection' field */
+ if ( face->os2.fsSelection & 1 )
+ flags |= FT_STYLE_FLAG_ITALIC;
+
+ if ( face->os2.fsSelection & 32 )
+ flags |= FT_STYLE_FLAG_BOLD;
+ }
+ else
+ {
+ /* this is an old Mac font, use the header field */
+ if ( face->header.Mac_Style & 1 )
+ flags |= FT_STYLE_FLAG_BOLD;
+
+ if ( face->header.Mac_Style & 2 )
+ flags |= FT_STYLE_FLAG_ITALIC;
+ }
+
+ root->style_flags = flags;
+
+ /*********************************************************************/
+ /* */
+ /* Polish the charmaps. */
+ /* */
+ /* Try to set the charmap encoding according to the platform & */
+ /* encoding ID of each charmap. */
+ /* */
+ charmap = face->charmaps;
+ root->num_charmaps = face->num_charmaps;
+
+ /* allocate table of pointers */
+ if ( ALLOC_ARRAY( root->charmaps, root->num_charmaps, FT_CharMap ) )
+ goto Exit;
+
+ for ( n = 0; n < root->num_charmaps; n++, charmap++ )
+ {
+ FT_Int platform = charmap->cmap.platformID;
+ FT_Int encoding = charmap->cmap.platformEncodingID;
+
+
+ charmap->root.face = (FT_Face)face;
+ charmap->root.platform_id = platform;
+ charmap->root.encoding_id = encoding;
+ charmap->root.encoding = find_encoding( platform, encoding );
+
+ /* now, set root->charmap with a unicode charmap */
+ /* wherever available */
+ if ( !root->charmap &&
+ charmap->root.encoding == ft_encoding_unicode )
+ root->charmap = (FT_CharMap)charmap;
+
+ root->charmaps[n] = (FT_CharMap)charmap;
+ }
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+ if ( face->num_sbit_strikes )
+ {
+ root->num_fixed_sizes = face->num_sbit_strikes;
+ if ( ALLOC_ARRAY( root->available_sizes,
+ face->num_sbit_strikes,
+ FT_Bitmap_Size ) )
+ return error;
+
+ for ( n = 0 ; n < face->num_sbit_strikes ; n++ )
+ {
+ root->available_sizes[n].width =
+ face->sbit_strikes[n].x_ppem;
+ root->available_sizes[n].height =
+ face->sbit_strikes[n].y_ppem;
+ }
+ }
+ else
+
+#else /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+ {
+ root->num_fixed_sizes = 0;
+ root->available_sizes = 0;
+ }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+ /*********************************************************************/
+ /* */
+ /* Set up metrics. */
+ /* */
+ root->bbox.xMin = face->header.xMin;
+ root->bbox.yMin = face->header.yMin;
+ root->bbox.xMax = face->header.xMax;
+ root->bbox.yMax = face->header.yMax;
+ root->units_per_EM = face->header.Units_Per_EM;
+
+ /* The ascender/descender/height are computed from the OS/2 table */
+ /* when found. Otherwise, they're taken from the horizontal header. */
+ if ( face->os2.version != 0xFFFF )
+ {
+ root->ascender = face->os2.sTypoAscender;
+ root->descender = -face->os2.sTypoDescender;
+ root->height = root->ascender + root->descender +
+ face->os2.sTypoLineGap;
+ }
+ else
+ {
+ root->ascender = face->horizontal.Ascender;
+ root->descender = face->horizontal.Descender;
+ root->height = root->ascender + root->descender +
+ face->horizontal.Line_Gap;
+ }
+
+ root->max_advance_width = face->horizontal.advance_Width_Max;
+
+ root->max_advance_height = face->vertical_info
+ ? face->vertical.advance_Height_Max
+ : root->height;
+
+ root->underline_position = face->postscript.underlinePosition;
+ root->underline_thickness = face->postscript.underlineThickness;
+
+ /* root->max_points -- already set up */
+ /* root->max_contours -- already set up */
+ }
+
+ Exit:
+ return error;
+ }
+
+
+#undef LOAD_
+
+
+ LOCAL_FUNC
+ void SFNT_Done_Face( TT_Face face )
+ {
+ FT_Memory memory = face->root.memory;
+ SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt;
+
+
+ if ( sfnt )
+ {
+ /* destroy the postscript names table if it is loaded */
+ if ( sfnt->free_psnames )
+ sfnt->free_psnames( face );
+
+ /* destroy the embedded bitmaps table if it is loaded */
+ if ( sfnt->free_sbits )
+ sfnt->free_sbits( face );
+ }
+
+ /* freeing the kerning table */
+ FREE( face->kern_pairs );
+ face->num_kern_pairs = 0;
+
+ /* freeing the collection table */
+ FREE( face->ttc_header.offsets );
+ face->ttc_header.count = 0;
+
+ /* freeing table directory */
+ FREE( face->dir_tables );
+ face->num_tables = 0;
+
+ /* freeing the character mapping tables */
+ if ( sfnt && sfnt->load_charmaps )
+ {
+ FT_UShort n;
+
+
+ for ( n = 0; n < face->num_charmaps; n++ )
+ sfnt->free_charmap( face, &face->charmaps[n].cmap );
+ }
+
+ FREE( face->charmaps );
+ face->num_charmaps = 0;
+
+ FREE( face->root.charmaps );
+ face->root.num_charmaps = 0;
+ face->root.charmap = 0;
+
+ /* freeing the horizontal metrics */
+ FREE( face->horizontal.long_metrics );
+ FREE( face->horizontal.short_metrics );
+
+ /* freeing the vertical ones, if any */
+ if ( face->vertical_info )
+ {
+ FREE( face->vertical.long_metrics );
+ FREE( face->vertical.short_metrics );
+ face->vertical_info = 0;
+ }
+
+ /* freeing the gasp table */
+ FREE( face->gasp.gaspRanges );
+ face->gasp.numRanges = 0;
+
+ /* freeing the name table */
+ sfnt->free_names( face );
+
+ /* freeing the hdmx table */
+ sfnt->free_hdmx( face );
+
+ /* freeing family and style name */
+ FREE( face->root.family_name );
+ FREE( face->root.style_name );
+
+ /* freeing sbit size table */
+ face->root.num_fixed_sizes = 0;
+ if ( face->root.available_sizes )
+ FREE( face->root.available_sizes );
+
+ face->sfnt = 0;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* sfobjs.h */
+/* */
+/* SFNT object management (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef SFOBJS_H
+#define SFOBJS_H
+
+#include <freetype/internal/sfnt.h>
+#include <freetype/internal/ftobjs.h>
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ LOCAL_DEF
+ FT_Error SFNT_Init_Face( FT_Stream stream,
+ TT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+ LOCAL_DEF
+ FT_Error SFNT_Load_Face( FT_Stream stream,
+ TT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+ LOCAL_DEF
+ void SFNT_Done_Face( TT_Face face );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* SFDRIVER_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttcmap.c */
+/* */
+/* TrueType character mapping table (cmap) support (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/tterrors.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttload.h"
+#include "ttcmap.h"
+
+#else
+
+#include <sfnt/ttload.h>
+#include <sfnt/ttcmap.h>
+
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttcmap
+
+
+ static FT_UInt code_to_index0( TT_CMapTable* charmap,
+ FT_ULong char_code );
+ static FT_UInt code_to_index2( TT_CMapTable* charmap,
+ FT_ULong char_code );
+ static FT_UInt code_to_index4( TT_CMapTable* charmap,
+ FT_ULong char_code );
+ static FT_UInt code_to_index6( TT_CMapTable* charmap,
+ FT_ULong char_code );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_CharMap_Load */
+ /* */
+ /* <Description> */
+ /* Loads a given TrueType character map into memory. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the parent face object. */
+ /* stream :: A handle to the current stream object. */
+ /* */
+ /* <InOut> */
+ /* table :: A pointer to a cmap object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The function assumes that the stream is already in use (i.e., */
+ /* opened). In case of error, all partially allocated tables are */
+ /* released. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_CharMap_Load( TT_Face face,
+ TT_CMapTable* cmap,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FT_UShort num_SH, num_Seg, i;
+
+ FT_UShort u, l;
+
+ TT_CMap0* cmap0;
+ TT_CMap2* cmap2;
+ TT_CMap4* cmap4;
+ TT_CMap6* cmap6;
+
+ TT_CMap2SubHeader* cmap2sub;
+ TT_CMap4Segment* segments;
+
+
+ if ( cmap->loaded )
+ return TT_Err_Ok;
+
+ memory = stream->memory;
+
+ if ( FILE_Seek( cmap->offset ) )
+ return error;
+
+ switch ( cmap->format )
+ {
+ case 0:
+ cmap0 = &cmap->c.cmap0;
+
+ if ( ALLOC( cmap0->glyphIdArray, 256L ) ||
+ FILE_Read( cmap0->glyphIdArray, 256L ) )
+ goto Fail;
+
+ cmap->get_index = code_to_index0;
+ break;
+
+ case 2:
+ num_SH = 0;
+ cmap2 = &cmap->c.cmap2;
+
+ /* allocate subheader keys */
+
+ if ( ALLOC_ARRAY( cmap2->subHeaderKeys, 256, FT_UShort ) ||
+ ACCESS_Frame( 512L ) )
+ goto Fail;
+
+ for ( i = 0; i < 256; i++ )
+ {
+ u = GET_UShort() / 8;
+ cmap2->subHeaderKeys[i] = u;
+
+ if ( num_SH < u )
+ num_SH = u;
+ }
+
+ FORGET_Frame();
+
+ /* load subheaders */
+
+ cmap2->numGlyphId = l =
+ ( ( cmap->length - 2L * ( 256 + 3 ) - num_SH * 8L ) & 0xFFFF ) / 2;
+
+ if ( ALLOC_ARRAY( cmap2->subHeaders,
+ num_SH + 1,
+ TT_CMap2SubHeader ) ||
+ ACCESS_Frame( ( num_SH + 1 ) * 8L ) )
+ goto Fail;
+
+ cmap2sub = cmap2->subHeaders;
+
+ for ( i = 0; i <= num_SH; i++ )
+ {
+ cmap2sub->firstCode = GET_UShort();
+ cmap2sub->entryCount = GET_UShort();
+ cmap2sub->idDelta = GET_Short();
+ /* we apply the location offset immediately */
+ cmap2sub->idRangeOffset = GET_UShort() - ( num_SH - i ) * 8 - 2;
+
+ cmap2sub++;
+ }
+
+ FORGET_Frame();
+
+ /* load glyph IDs */
+
+ if ( ALLOC_ARRAY( cmap2->glyphIdArray, l, FT_UShort ) ||
+ ACCESS_Frame( l * 2L ) )
+ goto Fail;
+
+ for ( i = 0; i < l; i++ )
+ cmap2->glyphIdArray[i] = GET_UShort();
+
+ FORGET_Frame();
+
+ cmap->get_index = code_to_index2;
+ break;
+
+ case 4:
+ cmap4 = &cmap->c.cmap4;
+
+ /* load header */
+
+ if ( ACCESS_Frame( 8L ) )
+ goto Fail;
+
+ cmap4->segCountX2 = GET_UShort();
+ cmap4->searchRange = GET_UShort();
+ cmap4->entrySelector = GET_UShort();
+ cmap4->rangeShift = GET_UShort();
+
+ num_Seg = cmap4->segCountX2 / 2;
+
+ FORGET_Frame();
+
+ /* load segments */
+
+ if ( ALLOC_ARRAY( cmap4->segments,
+ num_Seg,
+ TT_CMap4Segment ) ||
+ ACCESS_Frame( ( num_Seg * 4 + 1 ) * 2L ) )
+ goto Fail;
+
+ segments = cmap4->segments;
+
+ for ( i = 0; i < num_Seg; i++ )
+ segments[i].endCount = GET_UShort();
+
+ (void)GET_UShort();
+
+ for ( i = 0; i < num_Seg; i++ )
+ segments[i].startCount = GET_UShort();
+
+ for ( i = 0; i < num_Seg; i++ )
+ segments[i].idDelta = GET_Short();
+
+ for ( i = 0; i < num_Seg; i++ )
+ segments[i].idRangeOffset = GET_UShort();
+
+ FORGET_Frame();
+
+ cmap4->numGlyphId = l =
+ ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xFFFF ) / 2;
+
+ /* load IDs */
+
+ if ( ALLOC_ARRAY( cmap4->glyphIdArray, l, FT_UShort ) ||
+ ACCESS_Frame( l * 2L ) )
+ goto Fail;
+
+ for ( i = 0; i < l; i++ )
+ cmap4->glyphIdArray[i] = GET_UShort();
+
+ FORGET_Frame();
+
+ cmap->get_index = code_to_index4;
+
+ cmap4->last_segment = cmap4->segments;
+ break;
+
+ case 6:
+ cmap6 = &cmap->c.cmap6;
+
+ if ( ACCESS_Frame( 4L ) )
+ goto Fail;
+
+ cmap6->firstCode = GET_UShort();
+ cmap6->entryCount = GET_UShort();
+
+ FORGET_Frame();
+
+ l = cmap6->entryCount;
+
+ if ( ALLOC_ARRAY( cmap6->glyphIdArray,
+ cmap6->entryCount,
+ FT_Short ) ||
+ ACCESS_Frame( l * 2L ) )
+ goto Fail;
+
+ for ( i = 0; i < l; i++ )
+ cmap6->glyphIdArray[i] = GET_UShort();
+
+ FORGET_Frame();
+ cmap->get_index = code_to_index6;
+ break;
+
+ default: /* corrupt character mapping table */
+ return TT_Err_Invalid_CharMap_Format;
+
+ }
+
+ return TT_Err_Ok;
+
+ Fail:
+ TT_CharMap_Free( face, cmap );
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_CharMap_Free */
+ /* */
+ /* <Description> */
+ /* Destroys a character mapping table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the parent face object. */
+ /* cmap :: A handle to a cmap object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_CharMap_Free( TT_Face face,
+ TT_CMapTable* cmap )
+ {
+ FT_Memory memory;
+
+
+ if ( !cmap )
+ return TT_Err_Ok;
+
+ memory = face->root.driver->root.memory;
+
+ switch ( cmap->format )
+ {
+ case 0:
+ FREE( cmap->c.cmap0.glyphIdArray );
+ break;
+
+ case 2:
+ FREE( cmap->c.cmap2.subHeaderKeys );
+ FREE( cmap->c.cmap2.subHeaders );
+ FREE( cmap->c.cmap2.glyphIdArray );
+ break;
+
+ case 4:
+ FREE( cmap->c.cmap4.segments );
+ FREE( cmap->c.cmap4.glyphIdArray );
+ cmap->c.cmap4.segCountX2 = 0;
+ break;
+
+ case 6:
+ FREE( cmap->c.cmap6.glyphIdArray );
+ cmap->c.cmap6.entryCount = 0;
+ break;
+
+ default:
+ /* invalid table format, do nothing */
+ ;
+ }
+
+ cmap->loaded = FALSE;
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* code_to_index0 */
+ /* */
+ /* <Description> */
+ /* Converts the character code into a glyph index. Uses format 0. */
+ /* `charCode' must be in the range 0x00-0xFF (otherwise 0 is */
+ /* returned). */
+ /* */
+ /* <Input> */
+ /* charCode :: The wanted character code. */
+ /* cmap0 :: A pointer to a cmap table in format 0. */
+ /* */
+ /* <Return> */
+ /* Glyph index into the glyphs array. 0 if the glyph does not exist. */
+ /* */
+ static
+ FT_UInt code_to_index0( TT_CMapTable* cmap,
+ FT_ULong charCode )
+ {
+ TT_CMap0* cmap0 = &cmap->c.cmap0;
+
+
+ return ( charCode <= 0xFF ? cmap0->glyphIdArray[charCode] : 0 );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* code_to_index2 */
+ /* */
+ /* <Description> */
+ /* Converts the character code into a glyph index. Uses format 2. */
+ /* */
+ /* <Input> */
+ /* charCode :: The wanted character code. */
+ /* cmap2 :: A pointer to a cmap table in format 2. */
+ /* */
+ /* <Return> */
+ /* Glyph index into the glyphs array. 0 if the glyph does not exist. */
+ /* */
+ static
+ FT_UInt code_to_index2( TT_CMapTable* cmap,
+ FT_ULong charCode )
+ {
+ FT_UInt result, index1, offset;
+ FT_UInt char_lo;
+ FT_ULong char_hi;
+ TT_CMap2SubHeader* sh2;
+ TT_CMap2* cmap2;
+
+
+ cmap2 = &cmap->c.cmap2;
+ result = 0;
+ char_lo = (FT_UInt)( charCode & 0xFF );
+ char_hi = charCode >> 8;
+
+ if ( char_hi == 0 )
+ {
+ /* an 8-bit character code -- we use the subHeader 0 in this case */
+ /* to test whether the character code is in the charmap */
+ if ( cmap2->subHeaderKeys[char_lo] == 0 )
+ result = cmap2->glyphIdArray[char_lo];
+ }
+ else
+ {
+ /* a 16-bit character code */
+ index1 = cmap2->subHeaderKeys[char_hi & 0xFF];
+ if ( index1 )
+ {
+ sh2 = cmap2->subHeaders + index1;
+ char_lo -= sh2->firstCode;
+
+ if ( char_lo < sh2->entryCount )
+ {
+ offset = sh2->idRangeOffset / 2 + char_lo;
+ if ( offset < cmap2->numGlyphId )
+ {
+ result = cmap2->glyphIdArray[offset];
+ if ( result )
+ result = ( result + sh2->idDelta ) & 0xFFFF;
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* code_to_index4 */
+ /* */
+ /* <Description> */
+ /* Converts the character code into a glyph index. Uses format 4. */
+ /* */
+ /* <Input> */
+ /* charCode :: The wanted character code. */
+ /* cmap4 :: A pointer to a cmap table in format 4. */
+ /* */
+ /* <Return> */
+ /* Glyph index into the glyphs array. 0 if the glyph does not exist. */
+ /* */
+ static
+ FT_UInt code_to_index4( TT_CMapTable* cmap,
+ FT_ULong charCode )
+ {
+ FT_UInt result, index1, segCount;
+ TT_CMap4* cmap4;
+ TT_CMap4Segment *seg4, *limit;
+
+
+ cmap4 = &cmap->c.cmap4;
+ result = 0;
+ segCount = cmap4->segCountX2 / 2;
+ seg4 = cmap4->segments;
+ limit = seg4 + segCount;
+
+ /* check against the last segment */
+ seg4 = cmap4->last_segment;
+
+ /* the following is equivalent to performing two tests, as in */
+ /* */
+ /* if ( charCode >= seg4->startCount && charCode <= seg4->endCount ) */
+ /* */
+ /* Yes, that's a bit strange, but it's faster, and the idea behind */
+ /* the cache is to significantly speed up charcode to glyph index */
+ /* conversion. */
+
+ if ( (FT_ULong)(charCode - seg4->startCount) <
+ (FT_ULong)(seg4->endCount - seg4->startCount) )
+ goto Found;
+
+ for ( seg4 = cmap4->segments; seg4 < limit; seg4++ )
+ {
+ /* the ranges are sorted in increasing order. If we are out of */
+ /* the range here, the char code isn't in the charmap, so exit. */
+
+ if ( charCode > seg4->endCount )
+ continue;
+
+ if ( charCode >= seg4->startCount )
+ goto Found;
+ }
+ return 0;
+
+ Found:
+ cmap4->last_segment = seg4;
+
+ /* if the idRangeOffset is 0, we can compute the glyph index */
+ /* directly */
+
+ if ( seg4->idRangeOffset == 0 )
+ result = ( charCode + seg4->idDelta ) & 0xFFFF;
+ else
+ {
+ /* otherwise, we must use the glyphIdArray to do it */
+ index1 = seg4->idRangeOffset / 2
+ + ( charCode - seg4->startCount )
+ + ( seg4 - cmap4->segments )
+ - segCount;
+
+ if ( index1 < cmap4->numGlyphId &&
+ cmap4->glyphIdArray[index1] != 0 )
+ result = ( cmap4->glyphIdArray[index1] + seg4->idDelta ) & 0xFFFF;
+ }
+
+ return result;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* code_to_index6 */
+ /* */
+ /* <Description> */
+ /* Converts the character code into a glyph index. Uses format 6. */
+ /* */
+ /* <Input> */
+ /* charCode :: The wanted character code. */
+ /* cmap6 :: A pointer to a cmap table in format 6. */
+ /* */
+ /* <Return> */
+ /* Glyph index into the glyphs array. 0 if the glyph does not exist. */
+ /* */
+ static
+ FT_UInt code_to_index6( TT_CMapTable* cmap,
+ FT_ULong charCode )
+ {
+ TT_CMap6* cmap6;
+ FT_UInt result = 0;
+
+
+ cmap6 = &cmap->c.cmap6;
+ result = 0;
+ charCode -= cmap6->firstCode;
+
+ if ( charCode < cmap6->entryCount )
+ result = cmap6->glyphIdArray[charCode];
+
+ return result;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttcmap.h */
+/* */
+/* TrueType character mapping table (cmap) support (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef TTCMAP_H
+#define TTCMAP_H
+
+#include <freetype/internal/tttypes.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ LOCAL_DEF
+ FT_Error TT_CharMap_Load( TT_Face face,
+ TT_CMapTable* cmap,
+ FT_Stream input );
+
+ LOCAL_DEF
+ FT_Error TT_CharMap_Free( TT_Face face,
+ TT_CMapTable* cmap );
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* TTCMAP_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttload.c */
+/* */
+/* Load the basic TrueType tables, i.e., tables that can be either in */
+/* TTF or OTF fonts (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/tterrors.h>
+#include <freetype/tttags.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttload.h"
+#include "ttcmap.h"
+
+#else
+
+#include <sfnt/ttload.h>
+#include <sfnt/ttcmap.h>
+
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttload
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_LookUp_Table */
+ /* */
+ /* <Description> */
+ /* Looks for a TrueType table by name. */
+ /* */
+ /* <Input> */
+ /* face :: A face object handle. */
+ /* tag :: The searched tag. */
+ /* */
+ /* <Return> */
+ /* A pointer to the table directory entry. 0 if not found. */
+ /* */
+ LOCAL_FUNC
+ TT_Table* TT_LookUp_Table( TT_Face face,
+ FT_ULong tag )
+ {
+ TT_Table* entry;
+ TT_Table* limit;
+
+
+ FT_TRACE3(( "TT_LookUp_Table: %08p, `%c%c%c%c'\n",
+ face,
+ (FT_Char)( tag >> 24 ),
+ (FT_Char)( tag >> 16 ),
+ (FT_Char)( tag >> 8 ),
+ (FT_Char)( tag ) ));
+
+ entry = face->dir_tables;
+ limit = entry + face->num_tables;
+
+ for ( ; entry < limit; entry++ )
+ {
+ if ( entry->Tag == tag )
+ return entry;
+ }
+
+ FT_TRACE3(( " Could not find table!\n" ));
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Goto_Table */
+ /* */
+ /* <Description> */
+ /* Looks for a TrueType table by name, then seek a stream to it. */
+ /* */
+ /* <Input> */
+ /* face :: A face object handle. */
+ /* tag :: The searched tag. */
+ /* stream :: The stream to seek when the table is found. */
+ /* */
+ /* <Output> */
+ /* length :: The length of the table if found, undefined otherwise. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Goto_Table( TT_Face face,
+ FT_ULong tag,
+ FT_Stream stream,
+ FT_ULong* length )
+ {
+ TT_Table* table;
+ FT_Error error;
+
+
+ table = TT_LookUp_Table( face, tag );
+ if ( table )
+ {
+ if ( length )
+ *length = table->Length;
+
+ (void)FILE_Seek( table->Offset );
+ }
+ else
+ error = TT_Err_Table_Missing;
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_SFNT_Header */
+ /* */
+ /* <Description> */
+ /* Loads the header of a SFNT font file. Supports collections. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* stream :: The input stream. */
+ /* face_index :: If the font is a collection, the number of the font */
+ /* in the collection, ignored otherwise. */
+ /* */
+ /* <Output> */
+ /* sfnt :: The SFNT header. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The stream cursor must be at the font file's origin. */
+ /* */
+ /* This function recognizes fonts embedded in a `TrueType collection' */
+ /* */
+ /* The header will be checked whether it is valid by looking at the */
+ /* values of `search_range', `entry_selector', and `range_shift'. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_SFNT_Header( TT_Face face,
+ FT_Stream stream,
+ FT_Long face_index,
+ SFNT_Header* sfnt )
+ {
+ FT_Error error;
+ FT_ULong format_tag;
+ FT_Memory memory = stream->memory;
+
+ const FT_Frame_Field sfnt_header_fields[] =
+ {
+ FT_FRAME_START( 8 ),
+ FT_FRAME_USHORT( SFNT_Header, num_tables ),
+ FT_FRAME_USHORT( SFNT_Header, search_range ),
+ FT_FRAME_USHORT( SFNT_Header, entry_selector ),
+ FT_FRAME_USHORT( SFNT_Header, range_shift ),
+ FT_FRAME_END
+ };
+
+ const FT_Frame_Field ttc_header_fields[] =
+ {
+ FT_FRAME_START( 8 ),
+ FT_FRAME_LONG( TTC_Header, version ),
+ FT_FRAME_LONG( TTC_Header, count ),
+ FT_FRAME_END };
+
+
+ FT_TRACE2(( "TT_Load_SFNT_Header: %08p, %ld\n",
+ face, face_index ));
+
+ face->ttc_header.tag = 0;
+ face->ttc_header.version = 0;
+ face->ttc_header.count = 0;
+
+ face->num_tables = 0;
+
+ /* first of all, read the first 4 bytes. If it is `ttcf', then the */
+ /* file is a TrueType collection, otherwise it can be any other */
+ /* kind of font. */
+ if ( READ_ULong( format_tag ) )
+ goto Exit;
+
+ if ( format_tag == TTAG_ttcf )
+ {
+ FT_Int n;
+
+
+ FT_TRACE3(( "TT_Load_SFNT_Header: file is a collection\n" ));
+
+ /* it's a TrueType collection, i.e. a file containing several */
+ /* font files. Read the font directory now */
+ if ( READ_Fields( ttc_header_fields, &face->ttc_header ) )
+ goto Exit;
+
+ /* now read the offsets of each font in the file */
+ if ( ALLOC_ARRAY( face->ttc_header.offsets,
+ face->ttc_header.count,
+ FT_ULong ) ||
+ ACCESS_Frame( face->ttc_header.count * 4L ) )
+ goto Exit;
+
+ for ( n = 0; n < face->ttc_header.count; n++ )
+ face->ttc_header.offsets[n] = GET_ULong();
+
+ FORGET_Frame();
+
+ /* check face index */
+ if ( face_index >= face->ttc_header.count )
+ {
+ error = TT_Err_Bad_Argument;
+ goto Exit;
+ }
+
+ /* seek to the appropriate TrueType file, then read tag */
+ if ( FILE_Seek( face->ttc_header.offsets[face_index] ) ||
+ READ_Long( format_tag ) )
+ goto Exit;
+ }
+
+ /* the format tag was read, now check the rest of the header */
+ sfnt->format_tag = format_tag;
+ if ( READ_Fields( sfnt_header_fields, sfnt ) )
+ goto Exit;
+
+ /* now, check the values of `num_tables', `seach_range', etc. */
+ {
+ FT_UInt num_tables = sfnt->num_tables;
+ FT_ULong entry_selector = 1L << sfnt->entry_selector;
+
+
+ /* IMPORTANT: Many fonts have an incorrect `search_range' value, so */
+ /* we only check the `entry_selector' correctness here. */
+ /* */
+ if ( num_tables == 0 ||
+ entry_selector > num_tables ||
+ entry_selector * 2 <= num_tables )
+ {
+ FT_TRACE2(( "TT_Load_SFNT_Header: file is not SFNT!\n" ));
+ error = FT_Err_Unknown_File_Format;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Directory */
+ /* */
+ /* <Description> */
+ /* Loads the table directory into a face object. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* <Input> */
+ /* stream :: The input stream. */
+ /* sfnt :: The SFNT directory header. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The stream cursor must be at the font file's origin. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_Directory( TT_Face face,
+ FT_Stream stream,
+ SFNT_Header* sfnt )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ TT_Table *entry, *limit;
+
+
+ FT_TRACE2(( "TT_Load_Directory: %08p\n", face ));
+
+ FT_TRACE2(( "-- Tables count: %12u\n", sfnt->num_tables ));
+ FT_TRACE2(( "-- Format version: %08lx\n", sfnt->format_tag ));
+
+ face->num_tables = sfnt->num_tables;
+
+ if ( ALLOC_ARRAY( face->dir_tables,
+ face->num_tables,
+ TT_Table ) )
+ goto Exit;
+
+ if ( ACCESS_Frame( face->num_tables * 16L ) )
+ goto Exit;
+
+ entry = face->dir_tables;
+ limit = entry + face->num_tables;
+
+ for ( ; entry < limit; entry++ )
+ { /* loop through the tables and get all entries */
+ entry->Tag = GET_Tag4();
+ entry->CheckSum = GET_ULong();
+ entry->Offset = GET_Long();
+ entry->Length = GET_Long();
+
+ FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n",
+ (FT_Char)( entry->Tag >> 24 ),
+ (FT_Char)( entry->Tag >> 16 ),
+ (FT_Char)( entry->Tag >> 8 ),
+ (FT_Char)( entry->Tag ),
+ entry->Offset,
+ entry->Length ));
+ }
+
+ FORGET_Frame();
+
+ FT_TRACE2(( "Directory loaded\n\n" ));
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Any */
+ /* */
+ /* <Description> */
+ /* Loads any font table into client memory. */
+ /* */
+ /* <Input> */
+ /* face :: The face object to look for. */
+ /* */
+ /* tag :: The tag of table to load. Use the value 0 if you want */
+ /* to access the whole font file, else set this parameter */
+ /* to a valid TrueType table tag that you can forge with */
+ /* the MAKE_TT_TAG macro. */
+ /* */
+ /* offset :: The starting offset in the table (or the file if */
+ /* tag == 0). */
+ /* */
+ /* length :: The address of the decision variable: */
+ /* */
+ /* If length == NULL: */
+ /* Loads the whole table. Returns an error if */
+ /* `offset' == 0! */
+ /* */
+ /* If *length == 0: */
+ /* Exits immediately; returning the length of the given */
+ /* table or of the font file, depending on the value of */
+ /* `tag'. */
+ /* */
+ /* If *length != 0: */
+ /* Loads the next `length' bytes of table or font, */
+ /* starting at offset `offset' (in table or font too). */
+ /* */
+ /* <Output> */
+ /* buffer :: The address of target buffer. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_Any( TT_Face face,
+ FT_ULong tag,
+ FT_Long offset,
+ FT_Byte* buffer,
+ FT_ULong* length )
+ {
+ FT_Error error;
+ FT_Stream stream;
+ TT_Table* table;
+ FT_ULong size;
+
+
+ if ( tag != 0 )
+ {
+ /* look for tag in font directory */
+ table = TT_LookUp_Table( face, tag );
+ if ( !table )
+ {
+ error = TT_Err_Table_Missing;
+ goto Exit;
+ }
+
+ offset += table->Offset;
+ size = table->Length;
+ }
+ else
+ /* tag == 0 -- the user wants to access the font file directly */
+ size = face->root.stream->size;
+
+ if ( length && *length == 0 )
+ {
+ *length = size;
+
+ return TT_Err_Ok;
+ }
+
+ if ( length )
+ size = *length;
+
+ stream = face->root.stream;
+ (void)FILE_Read_At( offset, buffer, size );
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Header */
+ /* */
+ /* <Description> */
+ /* Loads the TrueType font header. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_Header( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ TT_Header* header;
+
+ static const FT_Frame_Field header_fields[] =
+ {
+ FT_FRAME_START( 54 ),
+ FT_FRAME_ULONG( TT_Header, Table_Version ),
+ FT_FRAME_ULONG( TT_Header, Font_Revision ),
+ FT_FRAME_LONG( TT_Header, CheckSum_Adjust ),
+ FT_FRAME_LONG( TT_Header, Magic_Number ),
+ FT_FRAME_USHORT( TT_Header, Flags ),
+ FT_FRAME_USHORT( TT_Header, Units_Per_EM ),
+ FT_FRAME_LONG( TT_Header, Created[0] ),
+ FT_FRAME_LONG( TT_Header, Created[1] ),
+ FT_FRAME_LONG( TT_Header, Modified[0] ),
+ FT_FRAME_LONG( TT_Header, Modified[1] ),
+ FT_FRAME_SHORT( TT_Header, xMin ),
+ FT_FRAME_SHORT( TT_Header, yMin ),
+ FT_FRAME_SHORT( TT_Header, xMax ),
+ FT_FRAME_SHORT( TT_Header, yMax ),
+ FT_FRAME_USHORT( TT_Header, Mac_Style ),
+ FT_FRAME_USHORT( TT_Header, Lowest_Rec_PPEM ),
+ FT_FRAME_SHORT( TT_Header, Font_Direction ),
+ FT_FRAME_SHORT( TT_Header, Index_To_Loc_Format ),
+ FT_FRAME_SHORT( TT_Header, Glyph_Data_Format ),
+ FT_FRAME_END
+ };
+
+
+ FT_TRACE2(( "Load_TT_Header: %08p\n", face ));
+
+ error = face->goto_table( face, TTAG_head, stream, 0 );
+ if ( error )
+ {
+ FT_TRACE0(( "Font Header is missing!\n" ));
+ goto Exit;
+ }
+
+ header = &face->header;
+
+ if ( READ_Fields( header_fields, header ) )
+ goto Exit;
+
+ FT_TRACE2(( " Units per EM: %8u\n", header->Units_Per_EM ));
+ FT_TRACE2(( " IndexToLoc: %8d\n", header->Index_To_Loc_Format ));
+ FT_TRACE2(( "Font Header Loaded.\n" ));
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_MaxProfile */
+ /* */
+ /* <Description> */
+ /* Loads the maximum profile into a face object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_MaxProfile( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ TT_MaxProfile* maxProfile = &face->max_profile;
+
+ const FT_Frame_Field maxp_fields[] =
+ {
+ FT_FRAME_START( 32 ),
+ FT_FRAME_ULONG( TT_MaxProfile, version ),
+ FT_FRAME_USHORT( TT_MaxProfile, numGlyphs ),
+ FT_FRAME_USHORT( TT_MaxProfile, maxPoints ),
+ FT_FRAME_USHORT( TT_MaxProfile, maxContours ),
+ FT_FRAME_USHORT( TT_MaxProfile, maxCompositePoints ),
+ FT_FRAME_USHORT( TT_MaxProfile, maxCompositeContours ),
+ FT_FRAME_USHORT( TT_MaxProfile, maxZones ),
+ FT_FRAME_USHORT( TT_MaxProfile, maxTwilightPoints ),
+ FT_FRAME_USHORT( TT_MaxProfile, maxStorage ),
+ FT_FRAME_USHORT( TT_MaxProfile, maxFunctionDefs ),
+ FT_FRAME_USHORT( TT_MaxProfile, maxInstructionDefs ),
+ FT_FRAME_USHORT( TT_MaxProfile, maxStackElements ),
+ FT_FRAME_USHORT( TT_MaxProfile, maxSizeOfInstructions ),
+ FT_FRAME_USHORT( TT_MaxProfile, maxComponentElements ),
+ FT_FRAME_USHORT( TT_MaxProfile, maxComponentDepth ),
+ FT_FRAME_END };
+
+
+ FT_TRACE2(( "Load_TT_MaxProfile: %08p\n", face ));
+
+ error = face->goto_table( face, TTAG_maxp, stream, 0 );
+ if ( error )
+ goto Exit;
+
+ if ( READ_Fields( maxp_fields, maxProfile ) )
+ goto Exit;
+
+ /* XXX: an adjustment that is necessary to load certain */
+ /* broken fonts like `Keystrokes MT' :-( */
+ /* */
+ /* We allocate 64 function entries by default when */
+ /* the maxFunctionDefs field is null. */
+
+ if ( maxProfile->maxFunctionDefs == 0 )
+ maxProfile->maxFunctionDefs = 64;
+
+ face->root.num_glyphs = maxProfile->numGlyphs;
+
+ face->root.max_points = MAX( maxProfile->maxCompositePoints,
+ maxProfile->maxPoints );
+
+ face->root.max_contours = MAX( maxProfile->maxCompositeContours,
+ maxProfile->maxContours );
+
+ face->max_components = (FT_ULong)maxProfile->maxComponentElements +
+ maxProfile->maxComponentDepth;
+
+ /* XXX: some fonts have maxComponents set to 0; we will */
+ /* then use 16 of them by default. */
+ if ( face->max_components == 0 )
+ face->max_components = 16;
+
+ /* We also increase maxPoints and maxContours in order to support */
+ /* some broken fonts. */
+ face->root.max_points += 8;
+ face->root.max_contours += 4;
+
+ FT_TRACE2(( "MAXP loaded.\n" ));
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Metrics */
+ /* */
+ /* <Description> */
+ /* Loads the horizontal or vertical metrics table into a face object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* stream :: The input stream. */
+ /* vertical :: A boolean flag. If set, load vertical metrics. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error TT_Load_Metrics( TT_Face face,
+ FT_Stream stream,
+ FT_Bool vertical )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_ULong table_len;
+ FT_Long num_shorts, num_longs, num_shorts_checked;
+
+ TT_LongMetrics** longs;
+ TT_ShortMetrics** shorts;
+
+
+ FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical"
+ : "Horizontal",
+ face ));
+
+ if ( vertical )
+ {
+ /* The table is optional, quit silently if it wasn't found */
+ /* XXX: Some fonts have a valid vertical header with a non-null */
+ /* `number_of_VMetrics' fields, but no corresponding `vmtx' */
+ /* table to get the metrics from (e.g. mingliu). */
+ /* */
+ /* For safety, we set the field to 0! */
+ /* */
+ error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
+ if ( error )
+ {
+ /* Set number_Of_VMetrics to 0! */
+ FT_TRACE2(( " no vertical header in file.\n" ));
+ face->vertical.number_Of_VMetrics = 0;
+ error = TT_Err_Ok;
+ goto Exit;
+ }
+
+ num_longs = face->vertical.number_Of_VMetrics;
+ longs = (TT_LongMetrics**)&face->vertical.long_metrics;
+ shorts = (TT_ShortMetrics**)&face->vertical.short_metrics;
+ }
+ else
+ {
+ error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
+ if ( error )
+ {
+ FT_ERROR(( " no horizontal metrics in file!\n" ));
+ error = TT_Err_Hmtx_Table_Missing;
+ goto Exit;
+ }
+
+ num_longs = face->horizontal.number_Of_HMetrics;
+ longs = (TT_LongMetrics**)&face->horizontal.long_metrics;
+ shorts = (TT_ShortMetrics**)&face->horizontal.short_metrics;
+ }
+
+ /* never trust derived values */
+
+ num_shorts = face->max_profile.numGlyphs - num_longs;
+ num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
+
+ if ( num_shorts < 0 )
+ {
+ FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n",
+ vertical ? "Vertical"
+ : "Horizontal" ));
+
+ error = vertical ? TT_Err_Invalid_Vert_Metrics
+ : TT_Err_Invalid_Horiz_Metrics;
+ goto Exit;
+ }
+
+ if ( ALLOC_ARRAY( *longs, num_longs, TT_LongMetrics ) ||
+ ALLOC_ARRAY( *shorts, num_shorts, TT_ShortMetrics ) )
+ goto Exit;
+
+ if ( ACCESS_Frame( table_len ) )
+ goto Exit;
+
+ {
+ TT_LongMetrics* cur = *longs;
+ TT_LongMetrics* limit = cur + num_longs;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ cur->advance = GET_UShort();
+ cur->bearing = GET_Short();
+ }
+ }
+
+ /* do we have an inconsistent number of metric values? */
+ {
+ TT_ShortMetrics* cur = *shorts;
+ TT_ShortMetrics* limit = cur + MIN( num_shorts, num_shorts_checked );
+
+
+ for ( ; cur < limit; cur++ )
+ *cur = GET_Short();
+
+ /* we fill up the missing left side bearings with the */
+ /* last valid value. Since this will occur for buggy CJK */
+ /* fonts usually only, nothing serious will happen */
+ if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
+ {
+ FT_Short val = *(shorts)[num_shorts_checked - 1];
+
+
+ limit = *shorts + num_shorts;
+ for ( ; cur < limit; cur++ )
+ *cur = val;
+ }
+ }
+
+ FORGET_Frame();
+
+ FT_TRACE2(( "loaded\n" ));
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Metrics_Header */
+ /* */
+ /* <Description> */
+ /* Loads the horizontal or vertical header in a face object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* stream :: The input stream. */
+ /* vertical :: A boolean flag. If set, load vertical metrics. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_Metrics_Header( TT_Face face,
+ FT_Stream stream,
+ FT_Bool vertical )
+ {
+ FT_Error error;
+ TT_HoriHeader* header;
+
+ const FT_Frame_Field metrics_header_fields[] =
+ {
+ FT_FRAME_START( 36 ),
+ FT_FRAME_ULONG( TT_HoriHeader, Version ),
+ FT_FRAME_SHORT( TT_HoriHeader, Ascender ),
+ FT_FRAME_SHORT( TT_HoriHeader, Descender ),
+ FT_FRAME_SHORT( TT_HoriHeader, Line_Gap ),
+ FT_FRAME_USHORT( TT_HoriHeader, advance_Width_Max ),
+ FT_FRAME_SHORT( TT_HoriHeader, min_Left_Side_Bearing ),
+ FT_FRAME_SHORT( TT_HoriHeader, min_Right_Side_Bearing ),
+ FT_FRAME_SHORT( TT_HoriHeader, xMax_Extent ),
+ FT_FRAME_SHORT( TT_HoriHeader, caret_Slope_Rise ),
+ FT_FRAME_SHORT( TT_HoriHeader, caret_Slope_Run ),
+ FT_FRAME_SHORT( TT_HoriHeader, Reserved[0] ),
+ FT_FRAME_SHORT( TT_HoriHeader, Reserved[1] ),
+ FT_FRAME_SHORT( TT_HoriHeader, Reserved[2] ),
+ FT_FRAME_SHORT( TT_HoriHeader, Reserved[3] ),
+ FT_FRAME_SHORT( TT_HoriHeader, Reserved[4] ),
+ FT_FRAME_SHORT( TT_HoriHeader, metric_Data_Format ),
+ FT_FRAME_USHORT( TT_HoriHeader, number_Of_HMetrics ),
+ FT_FRAME_END
+ };
+
+
+ FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " ));
+
+ if ( vertical )
+ {
+ face->vertical_info = 0;
+
+ /* The vertical header table is optional, so return quietly if */
+ /* we don't find it. */
+ error = face->goto_table( face, TTAG_vhea, stream, 0 );
+ if ( error )
+ {
+ error = TT_Err_Ok;
+ goto Exit;
+ }
+
+ face->vertical_info = 1;
+ header = (TT_HoriHeader*)&face->vertical;
+ }
+ else
+ {
+ /* The horizontal header is mandatory; return an error if we */
+ /* don't find it. */
+ error = face->goto_table( face, TTAG_hhea, stream, 0 );
+ if ( error )
+ {
+ error = TT_Err_Horiz_Header_Missing;
+ goto Exit;
+ }
+
+ header = &face->horizontal;
+ }
+
+ if ( READ_Fields( metrics_header_fields, header ) )
+ goto Exit;
+
+ header->long_metrics = NULL;
+ header->short_metrics = NULL;
+
+ FT_TRACE2(( "loaded\n" ));
+
+ /* Now try to load the corresponding metrics */
+
+ error = TT_Load_Metrics( face, stream, vertical );
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Names */
+ /* */
+ /* <Description> */
+ /* Loads the name records. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_Names( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_ULong table_pos, table_len;
+ FT_ULong storageSize;
+
+ TT_NameTable* names;
+
+ const FT_Frame_Field name_table_fields[] =
+ {
+ FT_FRAME_START( 6 ),
+ FT_FRAME_USHORT( TT_NameTable, format ),
+ FT_FRAME_USHORT( TT_NameTable, numNameRecords ),
+ FT_FRAME_USHORT( TT_NameTable, storageOffset ),
+ FT_FRAME_END
+ };
+
+ const FT_Frame_Field name_record_fields[] =
+ {
+ /* no FT_FRAME_START */
+ FT_FRAME_USHORT( TT_NameRec, platformID ),
+ FT_FRAME_USHORT( TT_NameRec, encodingID ),
+ FT_FRAME_USHORT( TT_NameRec, languageID ),
+ FT_FRAME_USHORT( TT_NameRec, nameID ),
+ FT_FRAME_USHORT( TT_NameRec, stringLength ),
+ FT_FRAME_USHORT( TT_NameRec, stringOffset ),
+ FT_FRAME_END
+ };
+
+
+ FT_TRACE2(( "Names " ));
+
+ error = face->goto_table( face, TTAG_name, stream, &table_len );
+ if ( error )
+ {
+ /* The name table is required so indicate failure. */
+ FT_TRACE2(( "is missing!\n" ));
+ error = TT_Err_Name_Table_Missing;
+ goto Exit;
+ }
+
+ table_pos = FILE_Pos();
+
+ names = &face->name_table;
+
+ if ( READ_Fields( name_table_fields, names ) )
+ goto Exit;
+
+ /* Allocate the array of name records. */
+ if ( ALLOC_ARRAY( names->names,
+ names->numNameRecords,
+ TT_NameRec ) ||
+ ACCESS_Frame( names->numNameRecords * 12L ) )
+ goto Exit;
+
+ /* Load the name records and determine how much storage is needed */
+ /* to hold the strings themselves. */
+ {
+ TT_NameRec* cur = names->names;
+ TT_NameRec* limit = cur + names->numNameRecords;
+
+
+ storageSize = 0;
+
+ for ( ; cur < limit; cur ++ )
+ {
+ FT_ULong upper;
+
+
+ (void)READ_Fields( name_record_fields, cur );
+
+ upper = (FT_ULong)( cur->stringOffset + cur->stringLength );
+ if ( upper > storageSize )
+ storageSize = upper;
+ }
+ }
+
+ FORGET_Frame();
+
+ if ( storageSize > 0 )
+ {
+ /* allocate the name storage area in memory, then read it */
+ if ( ALLOC( names->storage, storageSize ) ||
+ FILE_Read_At( table_pos + names->storageOffset,
+ names->storage, storageSize ) )
+ goto Exit;
+
+ /* Go through and assign the string pointers to the name records. */
+ {
+ TT_NameRec* cur = names->names;
+ TT_NameRec* limit = cur + names->numNameRecords;
+
+
+ for ( ; cur < limit; cur++ )
+ cur->string = names->storage + cur->stringOffset;
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+ /* Print Name Record Table in case of debugging */
+ {
+ TT_NameRec* cur = names->names;
+ TT_NameRec* limit = cur + names->numNameRecords;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ FT_UInt j;
+
+
+ FT_TRACE3(( "%d %d %x %d\n ",
+ cur->platformID,
+ cur->encodingID,
+ cur->languageID,
+ cur->nameID ));
+
+ /* I know that M$ encoded strings are Unicode, */
+ /* but this works reasonable well for debugging purposes. */
+ if ( cur->string )
+ for ( j = 0; j < cur->stringLength; j++ )
+ {
+ FT_Char c = *( cur->string + j );
+
+
+ if ( (FT_Byte)c < 128 )
+ FT_TRACE3(( "%c", c ));
+ }
+ }
+ }
+ FT_TRACE3(( "\n" ));
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+ }
+ FT_TRACE2(( "loaded\n" ));
+
+ /* everything went well, update face->num_names */
+ face->num_names = names->numNameRecords;
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Free_Names */
+ /* */
+ /* <Description> */
+ /* Frees the name records. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ LOCAL_FUNC
+ void TT_Free_Names( TT_Face face )
+ {
+ FT_Memory memory = face->root.driver->root.memory;
+ TT_NameTable* names = &face->name_table;
+
+
+ /* free strings table */
+ FREE( names->names );
+
+ /* free strings storage */
+ FREE( names->storage );
+
+ names->numNameRecords = 0;
+ names->format = 0;
+ names->storageOffset = 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_CMap */
+ /* */
+ /* <Description> */
+ /* Loads the cmap directory in a face object. The cmaps itselves are */
+ /* loaded on demand in the `ttcmap.c' module. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_CMap( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_Long table_start;
+ TT_CMapDir cmap_dir;
+
+ const FT_Frame_Field cmap_fields[] =
+ {
+ FT_FRAME_START( 4 ),
+ FT_FRAME_USHORT( TT_CMapDir, tableVersionNumber ),
+ FT_FRAME_USHORT( TT_CMapDir, numCMaps ),
+ FT_FRAME_END
+ };
+
+ const FT_Frame_Field cmap_rec_fields[] =
+ {
+ FT_FRAME_START( 6 ),
+ FT_FRAME_USHORT( TT_CMapTable, format ),
+ FT_FRAME_USHORT( TT_CMapTable, length ),
+ FT_FRAME_USHORT( TT_CMapTable, version ),
+ FT_FRAME_END
+ };
+
+
+ FT_TRACE2(( "CMaps " ));
+
+ error = face->goto_table( face, TTAG_cmap, stream, 0 );
+ if ( error )
+ {
+ error = TT_Err_CMap_Table_Missing;
+ goto Exit;
+ }
+
+ table_start = FILE_Pos();
+
+ if ( READ_Fields( cmap_fields, &cmap_dir ) )
+ goto Exit;
+
+ /* reserve space in face table for cmap tables */
+ if ( ALLOC_ARRAY( face->charmaps,
+ cmap_dir.numCMaps,
+ TT_CharMapRec ) )
+ goto Exit;
+
+ face->num_charmaps = cmap_dir.numCMaps;
+ {
+ TT_CharMap charmap = face->charmaps;
+ TT_CharMap limit = charmap + face->num_charmaps;
+
+
+ /* read the header of each charmap first */
+ if ( ACCESS_Frame( face->num_charmaps * 8L ) )
+ goto Exit;
+
+ for ( ; charmap < limit; charmap++ )
+ {
+ TT_CMapTable* cmap;
+
+
+ charmap->root.face = (FT_Face)face;
+ cmap = &charmap->cmap;
+
+ cmap->loaded = FALSE;
+ cmap->platformID = GET_UShort();
+ cmap->platformEncodingID = GET_UShort();
+ cmap->offset = (FT_ULong)GET_Long();
+ }
+
+ FORGET_Frame();
+
+ /* now read the rest of each table */
+ for ( charmap = face->charmaps; charmap < limit; charmap++ )
+ {
+ TT_CMapTable* cmap = &charmap->cmap;
+
+
+ if ( FILE_Seek( table_start + (FT_Long)cmap->offset ) ||
+ READ_Fields( cmap_rec_fields, cmap ) )
+ goto Exit;
+
+ cmap->offset = FILE_Pos();
+ }
+ }
+
+ FT_TRACE2(( "loaded\n" ));
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_OS2 */
+ /* */
+ /* <Description> */
+ /* Loads the OS2 table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_OS2( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ TT_OS2* os2;
+
+ const FT_Frame_Field os2_fields[] =
+ {
+ FT_FRAME_START( 78 ),
+ FT_FRAME_USHORT( TT_OS2, version ),
+ FT_FRAME_SHORT( TT_OS2, xAvgCharWidth ),
+ FT_FRAME_USHORT( TT_OS2, usWeightClass ),
+ FT_FRAME_USHORT( TT_OS2, usWidthClass ),
+ FT_FRAME_SHORT( TT_OS2, fsType ),
+ FT_FRAME_SHORT( TT_OS2, ySubscriptXSize ),
+ FT_FRAME_SHORT( TT_OS2, ySubscriptYSize ),
+ FT_FRAME_SHORT( TT_OS2, ySubscriptXOffset ),
+ FT_FRAME_SHORT( TT_OS2, ySubscriptYOffset ),
+ FT_FRAME_SHORT( TT_OS2, ySuperscriptXSize ),
+ FT_FRAME_SHORT( TT_OS2, ySuperscriptYSize ),
+ FT_FRAME_SHORT( TT_OS2, ySuperscriptXOffset ),
+ FT_FRAME_SHORT( TT_OS2, ySuperscriptYOffset ),
+ FT_FRAME_SHORT( TT_OS2, yStrikeoutSize ),
+ FT_FRAME_SHORT( TT_OS2, yStrikeoutPosition ),
+ FT_FRAME_SHORT( TT_OS2, sFamilyClass ),
+ FT_FRAME_BYTE( TT_OS2, panose[0] ),
+ FT_FRAME_BYTE( TT_OS2, panose[1] ),
+ FT_FRAME_BYTE( TT_OS2, panose[2] ),
+ FT_FRAME_BYTE( TT_OS2, panose[3] ),
+ FT_FRAME_BYTE( TT_OS2, panose[4] ),
+ FT_FRAME_BYTE( TT_OS2, panose[5] ),
+ FT_FRAME_BYTE( TT_OS2, panose[6] ),
+ FT_FRAME_BYTE( TT_OS2, panose[7] ),
+ FT_FRAME_BYTE( TT_OS2, panose[8] ),
+ FT_FRAME_BYTE( TT_OS2, panose[9] ),
+ FT_FRAME_ULONG( TT_OS2, ulUnicodeRange1 ),
+ FT_FRAME_ULONG( TT_OS2, ulUnicodeRange2 ),
+ FT_FRAME_ULONG( TT_OS2, ulUnicodeRange3 ),
+ FT_FRAME_ULONG( TT_OS2, ulUnicodeRange4 ),
+ FT_FRAME_BYTE( TT_OS2, achVendID[0] ),
+ FT_FRAME_BYTE( TT_OS2, achVendID[1] ),
+ FT_FRAME_BYTE( TT_OS2, achVendID[2] ),
+ FT_FRAME_BYTE( TT_OS2, achVendID[3] ),
+
+ FT_FRAME_USHORT( TT_OS2, fsSelection ),
+ FT_FRAME_USHORT( TT_OS2, usFirstCharIndex ),
+ FT_FRAME_USHORT( TT_OS2, usLastCharIndex ),
+ FT_FRAME_SHORT( TT_OS2, sTypoAscender ),
+ FT_FRAME_SHORT( TT_OS2, sTypoDescender ),
+ FT_FRAME_SHORT( TT_OS2, sTypoLineGap ),
+ FT_FRAME_USHORT( TT_OS2, usWinAscent ),
+ FT_FRAME_USHORT( TT_OS2, usWinDescent ),
+ FT_FRAME_END
+ };
+
+ const FT_Frame_Field os2_fields_extra[] =
+ {
+ FT_FRAME_START( 8 ),
+ FT_FRAME_ULONG( TT_OS2, ulCodePageRange1 ),
+ FT_FRAME_ULONG( TT_OS2, ulCodePageRange2 ),
+ FT_FRAME_END
+ };
+
+ const FT_Frame_Field os2_fields_extra2[] =
+ {
+ FT_FRAME_START( 10 ),
+ FT_FRAME_SHORT( TT_OS2, sxHeight ),
+ FT_FRAME_SHORT( TT_OS2, sCapHeight ),
+ FT_FRAME_USHORT( TT_OS2, usDefaultChar ),
+ FT_FRAME_USHORT( TT_OS2, usBreakChar ),
+ FT_FRAME_USHORT( TT_OS2, usMaxContext ),
+ FT_FRAME_END
+ };
+
+
+ FT_TRACE2(( "OS/2 Table " ));
+
+ /* We now support old Mac fonts where the OS/2 table doesn't */
+ /* exist. Simply put, we set the `version' field to 0xFFFF */
+ /* and test this value each time we need to access the table. */
+ error = face->goto_table( face, TTAG_OS2, stream, 0 );
+ if ( error )
+ {
+ FT_TRACE2(( "is missing!\n" ));
+ face->os2.version = 0xFFFF;
+ error = TT_Err_Ok;
+ goto Exit;
+ }
+
+ os2 = &face->os2;
+
+ if ( READ_Fields( os2_fields, os2 ) )
+ goto Exit;
+
+ os2->ulCodePageRange1 = 0;
+ os2->ulCodePageRange2 = 0;
+
+ if ( os2->version >= 0x0001 )
+ {
+ /* only version 1 tables */
+ if ( READ_Fields( os2_fields_extra, os2 ) )
+ goto Exit;
+
+ if ( os2->version >= 0x0002 )
+ {
+ /* only version 2 tables */
+ if ( READ_Fields( os2_fields_extra2, os2 ) )
+ goto Exit;
+ }
+ }
+
+ FT_TRACE2(( "loaded\n" ));
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Postscript */
+ /* */
+ /* <Description> */
+ /* Loads the Postscript table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_PostScript( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ TT_Postscript* post = &face->postscript;
+
+ static const FT_Frame_Field post_fields[] =
+ {
+ FT_FRAME_START( 32 ),
+ FT_FRAME_ULONG( TT_Postscript, FormatType ),
+ FT_FRAME_ULONG( TT_Postscript, italicAngle ),
+ FT_FRAME_SHORT( TT_Postscript, underlinePosition ),
+ FT_FRAME_SHORT( TT_Postscript, underlineThickness ),
+ FT_FRAME_ULONG( TT_Postscript, isFixedPitch ),
+ FT_FRAME_ULONG( TT_Postscript, minMemType42 ),
+ FT_FRAME_ULONG( TT_Postscript, maxMemType42 ),
+ FT_FRAME_ULONG( TT_Postscript, minMemType1 ),
+ FT_FRAME_ULONG( TT_Postscript, maxMemType1 ),
+ FT_FRAME_END
+ };
+
+
+ FT_TRACE2(( "PostScript " ));
+
+ error = face->goto_table( face, TTAG_post, stream, 0 );
+ if ( error )
+ return TT_Err_Post_Table_Missing;
+
+ if ( READ_Fields( post_fields, post ) )
+ return error;
+
+ /* we don't load the glyph names, we do that in another */
+ /* module (ttpost). */
+ FT_TRACE2(( "loaded\n" ));
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_PCLT */
+ /* */
+ /* <Description> */
+ /* Loads the PCL 5 Table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_PCLT( TT_Face face,
+ FT_Stream stream )
+ {
+ static const FT_Frame_Field pclt_fields[] =
+ {
+ FT_FRAME_START( 54 ),
+ FT_FRAME_ULONG ( TT_PCLT, Version ),
+ FT_FRAME_ULONG ( TT_PCLT, FontNumber ),
+ FT_FRAME_USHORT( TT_PCLT, Pitch ),
+ FT_FRAME_USHORT( TT_PCLT, xHeight ),
+ FT_FRAME_USHORT( TT_PCLT, Style ),
+ FT_FRAME_USHORT( TT_PCLT, TypeFamily ),
+ FT_FRAME_USHORT( TT_PCLT, CapHeight ),
+ FT_FRAME_BYTES ( TT_PCLT, TypeFace, 16 ),
+ FT_FRAME_BYTES ( TT_PCLT, CharacterComplement, 8 ),
+ FT_FRAME_BYTES ( TT_PCLT, FileName, 6 ),
+ FT_FRAME_CHAR ( TT_PCLT, StrokeWeight ),
+ FT_FRAME_CHAR ( TT_PCLT, WidthType ),
+ FT_FRAME_BYTE ( TT_PCLT, SerifStyle ),
+ FT_FRAME_BYTE ( TT_PCLT, Reserved ),
+ FT_FRAME_END
+ };
+
+ FT_Error error;
+ TT_PCLT* pclt = &face->pclt;
+
+
+ FT_TRACE2(( "PCLT " ));
+
+ /* optional table */
+ error = face->goto_table( face, TTAG_PCLT, stream, 0 );
+ if ( error )
+ {
+ FT_TRACE2(( "missing (optional)\n" ));
+ pclt->Version = 0;
+ return TT_Err_Ok;
+ }
+
+ if ( READ_Fields( pclt_fields, pclt ) )
+ goto Exit;
+
+ FT_TRACE2(( "loaded\n" ));
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Gasp */
+ /* */
+ /* <Description> */
+ /* Loads the `gasp' table into a face object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_Gasp( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UInt j,num_ranges;
+ TT_GaspRange* gaspranges;
+
+
+ FT_TRACE2(( "TT_Load_Gasp: %08p\n", face ));
+
+ /* the gasp table is optional */
+ error = face->goto_table( face, TTAG_gasp, stream, 0 );
+ if ( error )
+ return TT_Err_Ok;
+
+ if ( ACCESS_Frame( 4L ) )
+ goto Exit;
+
+ face->gasp.version = GET_UShort();
+ face->gasp.numRanges = GET_UShort();
+
+ FORGET_Frame();
+
+ num_ranges = face->gasp.numRanges;
+ FT_TRACE3(( "number of ranges = %d\n", num_ranges ));
+
+ if ( ALLOC_ARRAY( gaspranges, num_ranges, TT_GaspRange ) ||
+ ACCESS_Frame( num_ranges * 4L ) )
+ goto Exit;
+
+ face->gasp.gaspRanges = gaspranges;
+
+ for ( j = 0; j < num_ranges; j++ )
+ {
+ gaspranges[j].maxPPEM = GET_UShort();
+ gaspranges[j].gaspFlag = GET_UShort();
+
+ FT_TRACE3(( " [max:%d flag:%d]",
+ gaspranges[j].maxPPEM,
+ gaspranges[j].gaspFlag ));
+ }
+ FT_TRACE3(( "\n" ));
+
+ FORGET_Frame();
+ FT_TRACE2(( "GASP loaded\n" ));
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Kern */
+ /* */
+ /* <Description> */
+ /* Loads the first kerning table with format 0 in the font. Only */
+ /* accepts the first horizontal kerning table. Developers should use */
+ /* the `ftxkern' extension to access other kerning tables in the font */
+ /* file, if they really want to. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_Kern( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UInt n, num_tables, version;
+
+
+ /* the kern table is optional; exit silently if it is missing */
+ error = face->goto_table( face, TTAG_kern, stream, 0 );
+ if ( error )
+ return TT_Err_Ok;
+
+ if ( ACCESS_Frame( 4L ) )
+ goto Exit;
+
+ version = GET_UShort();
+ num_tables = GET_UShort();
+
+ FORGET_Frame();
+
+ for ( n = 0; n < num_tables; n++ )
+ {
+ FT_UInt coverage;
+ FT_UInt length;
+
+
+ if ( ACCESS_Frame( 6L ) )
+ goto Exit;
+
+ version = GET_UShort(); /* version */
+ length = GET_UShort() - 6; /* substract header length */
+ coverage = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( coverage == 0x0001 )
+ {
+ FT_UInt num_pairs;
+ TT_Kern_0_Pair* pair;
+ TT_Kern_0_Pair* limit;
+
+
+ /* found a horizontal format 0 kerning table! */
+ if ( ACCESS_Frame( 8L ) )
+ goto Exit;
+
+ num_pairs = GET_UShort();
+
+ /* skip the rest */
+
+ FORGET_Frame();
+
+ /* allocate array of kerning pairs */
+ if ( ALLOC_ARRAY( face->kern_pairs, num_pairs, TT_Kern_0_Pair ) ||
+ ACCESS_Frame( 6L * num_pairs ) )
+ goto Exit;
+
+ pair = face->kern_pairs;
+ limit = pair + num_pairs;
+ for ( ; pair < limit; pair++ )
+ {
+ pair->left = GET_UShort();
+ pair->right = GET_UShort();
+ pair->value = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ face->num_kern_pairs = num_pairs;
+ face->kern_table_index = n;
+ goto Exit;
+ }
+
+ if ( FILE_Skip( length ) )
+ goto Exit;
+ }
+
+ /* no kern table found -- doesn't matter */
+ face->kern_table_index = -1;
+ face->num_kern_pairs = 0;
+ face->kern_pairs = NULL;
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Hdmx */
+ /* */
+ /* <Description> */
+ /* Loads the horizontal device metrics table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_Hdmx( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ TT_Hdmx* hdmx = &face->hdmx;
+ FT_Long num_glyphs;
+ FT_Long record_size;
+
+
+ hdmx->version = 0;
+ hdmx->num_records = 0;
+ hdmx->records = 0;
+
+ /* this table is optional */
+ error = face->goto_table( face, TTAG_hdmx, stream, 0 );
+ if ( error )
+ return TT_Err_Ok;
+
+ if ( ACCESS_Frame( 8L ) )
+ goto Exit;
+
+ hdmx->version = GET_UShort();
+ hdmx->num_records = GET_Short();
+ record_size = GET_Long();
+
+ FORGET_Frame();
+
+ /* Only recognize format 0 */
+ if ( hdmx->version != 0 )
+ goto Exit;
+
+ if ( ALLOC_ARRAY( hdmx->records, hdmx->num_records, TT_HdmxRec ) )
+ goto Exit;
+
+ num_glyphs = face->root.num_glyphs;
+ record_size -= num_glyphs + 2;
+
+ {
+ TT_HdmxRec* cur = hdmx->records;
+ TT_HdmxRec* limit = cur + hdmx->num_records;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ /* read record */
+ if ( READ_Byte( cur->ppem ) ||
+ READ_Byte( cur->max_width ) )
+ goto Exit;
+
+ if ( ALLOC( cur->widths, num_glyphs ) ||
+ FILE_Read( cur->widths, num_glyphs ) )
+ goto Exit;
+
+ /* skip padding bytes */
+ if ( record_size > 0 && FILE_Skip( record_size ) )
+ goto Exit;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Free_Hdmx */
+ /* */
+ /* <Description> */
+ /* Frees the horizontal device metrics table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ LOCAL_FUNC
+ void TT_Free_Hdmx( TT_Face face )
+ {
+ if ( face )
+ {
+ FT_Int n;
+ FT_Memory memory = face->root.driver->root.memory;
+
+
+ for ( n = 0; n < face->hdmx.num_records; n++ )
+ FREE( face->hdmx.records[n].widths );
+
+ FREE( face->hdmx.records );
+ face->hdmx.num_records = 0;
+ }
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttload.h */
+/* */
+/* Load the basic TrueType tables, i.e., tables that can be either in */
+/* TTF or OTF fonts (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef TTLOAD_H
+#define TTLOAD_H
+
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/tttypes.h>
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ LOCAL_DEF
+ TT_Table* TT_LookUp_Table( TT_Face face,
+ FT_ULong tag );
+
+ LOCAL_DEF
+ FT_Error TT_Goto_Table( TT_Face face,
+ FT_ULong tag,
+ FT_Stream stream,
+ FT_ULong* length );
+
+
+ LOCAL_DEF
+ FT_Error TT_Load_SFNT_Header( TT_Face face,
+ FT_Stream stream,
+ FT_Long face_index,
+ SFNT_Header* sfnt );
+ LOCAL_DEF
+ FT_Error TT_Load_Directory( TT_Face face,
+ FT_Stream stream,
+ SFNT_Header* sfnt );
+
+ LOCAL_DEF
+ FT_Error TT_Load_Any( TT_Face face,
+ FT_ULong tag,
+ FT_Long offset,
+ FT_Byte* buffer,
+ FT_ULong* length );
+
+
+ LOCAL_DEF
+ FT_Error TT_Load_Header( TT_Face face,
+ FT_Stream stream );
+
+
+ LOCAL_DEF
+ FT_Error TT_Load_Metrics_Header( TT_Face face,
+ FT_Stream stream,
+ FT_Bool vertical );
+
+
+ LOCAL_DEF
+ FT_Error TT_Load_CMap( TT_Face face,
+ FT_Stream stream );
+
+
+ LOCAL_DEF
+ FT_Error TT_Load_MaxProfile( TT_Face face,
+ FT_Stream stream );
+
+
+ LOCAL_DEF
+ FT_Error TT_Load_Names( TT_Face face,
+ FT_Stream stream );
+
+
+ LOCAL_DEF
+ FT_Error TT_Load_OS2( TT_Face face,
+ FT_Stream stream );
+
+
+ LOCAL_DEF
+ FT_Error TT_Load_PostScript( TT_Face face,
+ FT_Stream stream );
+
+
+ LOCAL_DEF
+ FT_Error TT_Load_Hdmx( TT_Face face,
+ FT_Stream stream );
+
+ LOCAL_DEF
+ FT_Error TT_Load_PCLT( TT_Face face,
+ FT_Stream stream );
+
+ LOCAL_DEF
+ void TT_Free_Names( TT_Face face );
+
+
+ LOCAL_DEF
+ void TT_Free_Hdmx ( TT_Face face );
+
+
+ LOCAL_DEF
+ FT_Error TT_Load_Kern( TT_Face face,
+ FT_Stream stream );
+
+
+ LOCAL_DEF
+ FT_Error TT_Load_Gasp( TT_Face face,
+ FT_Stream stream );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* TTLOAD_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttpost.c */
+/* */
+/* Postcript name table processing for TrueType and OpenType fonts */
+/* (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* The post table is not completely loaded by the core engine. This */
+ /* file loads the missing PS glyph names and implements an API to access */
+ /* them. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/tterrors.h>
+#include <freetype/tttags.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttpost.h"
+#include "ttload.h"
+
+#else
+
+#include <sfnt/ttpost.h>
+#include <sfnt/ttload.h>
+
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttpost
+
+
+ /* If this configuration macro is defined, we rely on the `PSNames' */
+ /* module to grab the glyph names. */
+
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+#include <freetype/internal/psnames.h>
+
+#define MAC_NAME( x ) ( (FT_String*)psnames->macintosh_name( x ) )
+
+
+#else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+
+ /* Otherwise, we ignore the `PSNames' module, and provide our own */
+ /* table of Mac names. Thus, it is possible to build a version of */
+ /* FreeType without the Type 1 driver & PSNames module. */
+
+#define MAC_NAME( x ) TT_Post_Default_Names[x]
+
+ /* the 258 default Mac PS glyph names */
+
+ FT_String* TT_Post_Default_Names[258] =
+ {
+ /* 0 */
+ ".notdef", ".null", "CR", "space", "exclam",
+ "quotedbl", "numbersign", "dollar", "percent", "ampersand",
+ /* 10 */
+ "quotesingle", "parenleft", "parenright", "asterisk", "plus",
+ "comma", "hyphen", "period", "slash", "zero",
+ /* 20 */
+ "one", "two", "three", "four", "five",
+ "six", "seven", "eight", "nine", "colon",
+ /* 30 */
+ "semicolon", "less", "equal", "greater", "question",
+ "at", "A", "B", "C", "D",
+ /* 40 */
+ "E", "F", "G", "H", "I",
+ "J", "K", "L", "M", "N",
+ /* 50 */
+ "O", "P", "Q", "R", "S",
+ "T", "U", "V", "W", "X",
+ /* 60 */
+ "Y", "Z", "bracketleft", "backslash", "bracketright",
+ "asciicircum", "underscore", "grave", "a", "b",
+ /* 70 */
+ "c", "d", "e", "f", "g",
+ "h", "i", "j", "k", "l",
+ /* 80 */
+ "m", "n", "o", "p", "q",
+ "r", "s", "t", "u", "v",
+ /* 90 */
+ "w", "x", "y", "z", "braceleft",
+ "bar", "braceright", "asciitilde", "Adieresis", "Aring",
+ /* 100 */
+ "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
+ "aacute", "agrave", "acircumflex", "adieresis", "atilde",
+ /* 110 */
+ "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
+ "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
+ /* 120 */
+ "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
+ "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
+ /* 130 */
+ "dagger", "degree", "cent", "sterling", "section",
+ "bullet", "paragraph", "germandbls", "registered", "copyright",
+ /* 140 */
+ "trademark", "acute", "dieresis", "notequal", "AE",
+ "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
+ /* 150 */
+ "yen", "mu", "partialdiff", "summation", "product",
+ "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
+ /* 160 */
+ "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
+ "radical", "florin", "approxequal", "Delta", "guillemotleft",
+ /* 170 */
+ "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde",
+ "Otilde", "OE", "oe", "endash", "emdash",
+ /* 180 */
+ "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
+ "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
+ /* 190 */
+ "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
+ "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
+ /* 200 */
+ "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
+ "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
+ /* 210 */
+ "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
+ "dotlessi", "circumflex", "tilde", "macron", "breve",
+ /* 220 */
+ "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
+ "caron", "Lslash", "lslash", "Scaron", "scaron",
+ /* 230 */
+ "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
+ "Yacute", "yacute", "Thorn", "thorn", "minus",
+ /* 240 */
+ "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
+ "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
+ /* 250 */
+ "Idot", "Scedilla", "scedilla", "Cacute", "cacute",
+ "Ccaron", "ccaron", "dmacron",
+ };
+
+
+#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+
+ static
+ FT_Error Load_Format_20( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Memory memory = stream->memory;
+ FT_Error error;
+
+ FT_Int num_glyphs;
+ FT_Int num_names;
+
+ FT_UShort* glyph_indices = 0;
+ FT_Char** name_strings = 0;
+
+
+ if ( READ_UShort( num_glyphs ) )
+ goto Exit;
+
+ /* UNDOCUMENTED! The number of glyphs in this table can be smaller */
+ /* than the value in the maxp table (cf. cyberbit.ttf). */
+
+ /* There already exist fonts which have more than 32768 glyph names */
+ /* in this table, so the test for this threshold has been dropped. */
+
+ if ( num_glyphs > face->root.num_glyphs )
+ {
+ error = TT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* load the indices */
+ {
+ FT_Int n;
+
+
+ if ( ALLOC_ARRAY ( glyph_indices, num_glyphs, FT_UShort ) ||
+ ACCESS_Frame( num_glyphs * 2L ) )
+ goto Fail;
+
+ for ( n = 0; n < num_glyphs; n++ )
+ glyph_indices[n] = GET_UShort();
+
+ FORGET_Frame();
+ }
+
+ /* compute number of names stored in table */
+ {
+ FT_Int n;
+
+
+ num_names = 0;
+
+ for ( n = 0; n < num_glyphs; n++ )
+ {
+ FT_Int index;
+
+
+ index = glyph_indices[n];
+ if ( index >= 258 )
+ {
+ index -= 257;
+ if ( index > num_names )
+ num_names = index;
+ }
+ }
+ }
+
+ /* now load the name strings */
+ {
+ FT_Int n;
+
+
+ if ( ALLOC_ARRAY( name_strings, num_names, FT_Char* ) )
+ goto Fail;
+
+ for ( n = 0; n < num_names; n++ )
+ {
+ FT_UInt len;
+
+
+ if ( READ_Byte ( len ) ||
+ ALLOC_ARRAY( name_strings[n], len + 1, FT_Char ) ||
+ FILE_Read ( name_strings[n], len ) )
+ goto Fail1;
+
+ name_strings[n][len] = '\0';
+ }
+ }
+
+ /* all right, set table fields and exit successfuly */
+ {
+ TT_Post_20* table = &face->postscript_names.names.format_20;
+
+
+ table->num_glyphs = num_glyphs;
+ table->num_names = num_names;
+ table->glyph_indices = glyph_indices;
+ table->glyph_names = name_strings;
+ }
+ return TT_Err_Ok;
+
+
+ Fail1:
+ {
+ FT_Int n;
+
+
+ for ( n = 0; n < num_names; n++ )
+ FREE( name_strings[n] );
+ }
+
+ Fail:
+ FREE( name_strings );
+ FREE( glyph_indices );
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ FT_Error Load_Format_25( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Memory memory = stream->memory;
+ FT_Error error;
+
+ FT_Int num_glyphs;
+ FT_Char* offset_table = 0;
+
+
+ /* UNDOCUMENTED! This value appears only in the Apple TT specs. */
+ if ( READ_UShort( num_glyphs ) )
+ goto Exit;
+
+ /* check the number of glyphs */
+ if ( num_glyphs > face->root.num_glyphs || num_glyphs > 258 )
+ {
+ error = TT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ if ( ALLOC ( offset_table, num_glyphs ) ||
+ FILE_Read( offset_table, num_glyphs ) )
+ goto Fail;
+
+ /* now check the offset table */
+ {
+ FT_Int n;
+
+
+ for ( n = 0; n < num_glyphs; n++ )
+ {
+ FT_Long index = (FT_Long)n + offset_table[n];
+
+
+ if ( index < 0 || index > num_glyphs )
+ {
+ error = TT_Err_Invalid_File_Format;
+ goto Fail;
+ }
+ }
+ }
+
+ /* OK, set table fields and exit successfuly */
+ {
+ TT_Post_25* table = &face->postscript_names.names.format_25;
+
+
+ table->num_glyphs = num_glyphs;
+ table->offsets = offset_table;
+ }
+
+ return TT_Err_Ok;
+
+ Fail:
+ FREE( offset_table );
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ FT_Error Load_Post_Names( TT_Face face )
+ {
+ FT_Stream stream;
+ FT_Error error;
+
+ /* get a stream for the face's resource */
+ stream = face->root.stream;
+
+ /* seek to the beginning of the PS names table */
+ error = face->goto_table( face, TTAG_post, stream, 0 );
+ if ( error )
+ goto Exit;
+
+ /* now read postscript table */
+ switch ( face->postscript.FormatType )
+ {
+ case 0x00020000L:
+ error = Load_Format_20( face, stream );
+ break;
+
+ case 0x00028000L:
+ error = Load_Format_25( face, stream );
+ break;
+
+ default:
+ error = TT_Err_Invalid_File_Format;
+ }
+
+ face->postscript_names.loaded = 1;
+
+ Exit:
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ void TT_Free_Post_Names( TT_Face face )
+ {
+ FT_Memory memory = face->root.memory;
+ TT_Post_Names* names = &face->postscript_names;
+
+
+ if ( names->loaded )
+ {
+ switch ( face->postscript.FormatType )
+ {
+ case 0x00020000L:
+ {
+ TT_Post_20* table = &names->names.format_20;
+ FT_UInt n;
+
+
+ FREE( table->glyph_indices );
+ table->num_glyphs = 0;
+
+ for ( n = 0; n < table->num_names; n++ )
+ FREE( table->glyph_names[n] );
+
+ FREE( table->glyph_names );
+ table->num_names = 0;
+ }
+ break;
+
+ case 0x00028000L:
+ {
+ TT_Post_25* table = &names->names.format_25;
+
+
+ FREE( table->offsets );
+ table->num_glyphs = 0;
+ }
+ break;
+ }
+ }
+ names->loaded = 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Get_PS_Name */
+ /* */
+ /* <Description> */
+ /* Gets the PostScript glyph name of a glyph. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the parent face. */
+ /* */
+ /* index :: The glyph index. */
+ /* */
+ /* PSname :: The address of a string pointer. Will be NULL in case */
+ /* of error, otherwise it is a pointer to the glyph name. */
+ /* */
+ /* You must not modify the returned string! */
+ /* */
+ /* <Output> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Get_PS_Name( TT_Face face,
+ FT_UInt index,
+ FT_String** PSname )
+ {
+ FT_Error error;
+ TT_Post_Names* names;
+
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+ PSNames_Interface* psnames;
+#endif
+
+
+ if ( !face )
+ return TT_Err_Invalid_Face_Handle;
+
+ if ( index >= (FT_UInt)face->root.num_glyphs )
+ return TT_Err_Invalid_Glyph_Index;
+
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+ psnames = (PSNames_Interface*)face->psnames;
+ if ( !psnames )
+ return TT_Err_Unimplemented_Feature;
+#endif
+
+ names = &face->postscript_names;
+
+ /* `.notdef' by default */
+ *PSname = MAC_NAME( 0 );
+
+ switch ( face->postscript.FormatType )
+ {
+ case 0x00010000L:
+ if ( index < 258 ) /* paranoid checking */
+ *PSname = MAC_NAME( index );
+ break;
+
+ case 0x00020000L:
+ {
+ TT_Post_20* table = &names->names.format_20;
+
+
+ if ( !names->loaded )
+ {
+ error = Load_Post_Names( face );
+ if ( error )
+ break;
+ }
+
+ if ( index < table->num_glyphs )
+ {
+ FT_UShort name_index = table->glyph_indices[index];
+
+
+ if ( name_index < 258 )
+ *PSname = MAC_NAME( name_index );
+ else
+ *PSname = (FT_String*)table->glyph_names[name_index - 258];
+ }
+ }
+ break;
+
+ case 0x00028000L:
+ {
+ TT_Post_25* table = &names->names.format_25;
+
+
+ if ( !names->loaded )
+ {
+ error = Load_Post_Names( face );
+ if ( error )
+ break;
+ }
+
+ if ( index < table->num_glyphs ) /* paranoid checking */
+ {
+ index += table->offsets[index];
+ *PSname = MAC_NAME( index );
+ }
+ }
+ break;
+
+ case 0x00030000L:
+ break; /* nothing to do */
+ }
+
+ return TT_Err_Ok;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttpost.h */
+/* */
+/* Postcript name table processing for TrueType and OpenType fonts */
+/* (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef TTPOST_H
+#define TTPOST_H
+
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/tttypes.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+#define TT_Err_Invalid_Post_Table_Format 0x0B00
+#define TT_Err_Invalid_Post_Table 0x0B01
+
+
+ LOCAL_DEF
+ FT_Error TT_Get_PS_Name( TT_Face face,
+ FT_UInt index,
+ FT_String** PSname );
+
+ LOCAL_DEF
+ void TT_Free_Post_Names( TT_Face face );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* TTPOST_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttsbit.c */
+/* */
+/* TrueType and OpenType embedded bitmap support (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/tterrors.h>
+#include <freetype/tttags.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttsbit.h"
+
+#else
+
+#include <sfnt/ttsbit.h>
+
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttsbit
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* blit_sbit */
+ /* */
+ /* <Description> */
+ /* Blits a bitmap from an input stream into a given target. Supports */
+ /* x and y offsets as well as byte padded lines. */
+ /* */
+ /* <Input> */
+ /* target :: The target bitmap/pixmap. */
+ /* */
+ /* source :: The input packed bitmap data. */
+ /* */
+ /* line_bits :: The number of bits per line. */
+ /* */
+ /* byte_padded :: A flag which is true if lines are byte-padded. */
+ /* */
+ /* x_offset :: The horizontal offset. */
+ /* */
+ /* y_offset :: The vertical offset. */
+ /* */
+ /* <Note> */
+ /* IMPORTANT: The x and y offsets are relative to the top corner of */
+ /* the target bitmap (unlike the normal TrueType */
+ /* convention). A positive y offset indicates a downwards */
+ /* direction! */
+ /* */
+ static
+ void blit_sbit( FT_Bitmap* target,
+ FT_Byte* source,
+ FT_Int line_bits,
+ FT_Bool byte_padded,
+ FT_Int x_offset,
+ FT_Int y_offset )
+ {
+ FT_Byte* line_buff;
+ FT_Int line_incr;
+ FT_Int height;
+
+ FT_UShort acc;
+ FT_Byte loaded;
+
+
+ /* first of all, compute starting write position */
+ line_incr = target->pitch;
+ line_buff = target->buffer;
+
+ if ( line_incr < 0 )
+ line_buff -= line_incr * ( target->rows - 1 );
+
+ line_buff += ( x_offset >> 3 ) + y_offset * line_incr;
+
+ /***********************************************************************/
+ /* */
+ /* We use the extra-classic `accumulator' trick to extract the bits */
+ /* from the source byte stream. */
+ /* */
+ /* Namely, the variable `acc' is a 16-bit accumulator containing the */
+ /* last `loaded' bits from the input stream. The bits are shifted to */
+ /* the upmost position in `acc'. */
+ /* */
+ /***********************************************************************/
+
+ acc = 0; /* clear accumulator */
+ loaded = 0; /* no bits were loaded */
+
+ for ( height = target->rows; height > 0; height-- )
+ {
+ FT_Byte* cur = line_buff; /* current write cursor */
+ FT_Int count = line_bits; /* # of bits to extract per line */
+ FT_Byte shift = x_offset & 7; /* current write shift */
+ FT_Byte space = 8 - shift;
+
+
+ /* first of all, read individual source bytes */
+ if ( count >= 8 )
+ {
+ count -= 8;
+ {
+ do
+ {
+ FT_Byte val;
+
+
+ /* ensure that there are at least 8 bits in the accumulator */
+ if ( loaded < 8 )
+ {
+ acc |= (FT_UShort)*source++ << ( 8 - loaded );
+ loaded += 8;
+ }
+
+ /* now write one byte */
+ val = (FT_Byte)( acc >> 8 );
+ if ( shift )
+ {
+ cur[0] |= val >> shift;
+ cur[1] |= val << space;
+ }
+ else
+ cur[0] |= val;
+
+ cur++;
+ acc <<= 8; /* remove bits from accumulator */
+ loaded -= 8;
+ count -= 8;
+
+ } while ( count >= 0 );
+ }
+
+ /* restore `count' to correct value */
+ count += 8;
+ }
+
+ /* now write remaining bits (count < 8) */
+ if ( count > 0 )
+ {
+ FT_Byte val;
+
+
+ /* ensure that there are at least `count' bits in the accumulator */
+ if ( loaded < count )
+ {
+ acc |= (FT_UShort)*source++ << ( 8 - loaded );
+ loaded += 8;
+ }
+
+ /* now write remaining bits */
+ val = ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count );
+ cur[0] |= val >> shift;
+
+ if ( count > space )
+ cur[1] |= val << space;
+
+ acc <<= count;
+ loaded -= count;
+ }
+
+ /* now, skip to next line */
+ if ( byte_padded )
+ acc = loaded = 0; /* clear accumulator on byte-padded lines */
+
+ line_buff += line_incr;
+ }
+ }
+
+
+ const FT_Frame_Field sbit_metrics_fields[] =
+ {
+ FT_FRAME_START( 8 ),
+ FT_FRAME_BYTE( TT_SBit_Metrics, height ),
+ FT_FRAME_BYTE( TT_SBit_Metrics, width ),
+
+ FT_FRAME_CHAR( TT_SBit_Metrics, horiBearingX ),
+ FT_FRAME_CHAR( TT_SBit_Metrics, horiBearingY ),
+ FT_FRAME_BYTE( TT_SBit_Metrics, horiAdvance ),
+
+ FT_FRAME_CHAR( TT_SBit_Metrics, vertBearingX ),
+ FT_FRAME_CHAR( TT_SBit_Metrics, vertBearingY ),
+ FT_FRAME_BYTE( TT_SBit_Metrics, vertAdvance ),
+ FT_FRAME_END
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_SBit_Const_Metrics */
+ /* */
+ /* <Description> */
+ /* Loads the metrics for `EBLC' index tables format 2 and 5. */
+ /* */
+ /* <Input> */
+ /* range :: The target range. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Load_SBit_Const_Metrics( TT_SBit_Range* range,
+ FT_Stream stream )
+ {
+ FT_Error error;
+
+
+ if ( READ_ULong( range->image_size ) )
+ return error;
+
+ return READ_Fields( sbit_metrics_fields, &range->metrics );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_SBit_Range_Codes */
+ /* */
+ /* <Description> */
+ /* Loads the range codes for `EBLC' index tables format 4 and 5. */
+ /* */
+ /* <Input> */
+ /* range :: The target range. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* load_offsets :: A flag whether to load the glyph offset table. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Load_SBit_Range_Codes( TT_SBit_Range* range,
+ FT_Stream stream,
+ FT_Bool load_offsets )
+ {
+ FT_Error error;
+ FT_ULong count, n, size;
+ FT_Memory memory = stream->memory;
+
+
+ if ( READ_ULong( count ) )
+ goto Exit;
+
+ range->num_glyphs = count;
+
+ /* Allocate glyph offsets table if needed */
+ if ( load_offsets )
+ {
+ if ( ALLOC_ARRAY( range->glyph_offsets, count, FT_ULong ) )
+ goto Exit;
+
+ size = count * 4L;
+ }
+ else
+ size = count * 2L;
+
+ /* Allocate glyph codes table and access frame */
+ if ( ALLOC_ARRAY ( range->glyph_codes, count, FT_UShort ) ||
+ ACCESS_Frame( size ) )
+ goto Exit;
+
+ for ( n = 0; n < count; n++ )
+ {
+ range->glyph_codes[n] = GET_UShort();
+
+ if ( load_offsets )
+ range->glyph_offsets[n] = (FT_ULong)range->image_offset +
+ GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_SBit_Range */
+ /* */
+ /* <Description> */
+ /* Loads a given `EBLC' index/range table. */
+ /* */
+ /* <Input> */
+ /* range :: The target range. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Load_SBit_Range( TT_SBit_Range* range,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+
+ switch( range->index_format )
+ {
+ case 1: /* variable metrics with 4-byte offsets */
+ case 3: /* variable metrics with 2-byte offsets */
+ {
+ FT_ULong num_glyphs, n;
+ FT_Int size_elem;
+ FT_Bool large = ( range->index_format == 1 );
+
+
+ num_glyphs = range->last_glyph - range->first_glyph + 1L;
+ range->num_glyphs = num_glyphs;
+ num_glyphs++; /* XXX: BEWARE - see spec */
+
+ size_elem = large ? 4 : 2;
+
+ if ( ALLOC_ARRAY( range->glyph_offsets,
+ num_glyphs, FT_ULong ) ||
+ ACCESS_Frame( num_glyphs * size_elem ) )
+ goto Exit;
+
+ for ( n = 0; n < num_glyphs; n++ )
+ range->glyph_offsets[n] = (FT_ULong)( range->image_offset +
+ ( large ? GET_ULong()
+ : GET_UShort() ) );
+ FORGET_Frame();
+ }
+ break;
+
+ case 2: /* all glyphs have identical metrics */
+ error = Load_SBit_Const_Metrics( range, stream );
+ break;
+
+ case 4:
+ error = Load_SBit_Range_Codes( range, stream, 1 );
+ break;
+
+ case 5:
+ error = Load_SBit_Const_Metrics( range, stream ) ||
+ Load_SBit_Range_Codes( range, stream, 0 );
+ break;
+
+ default:
+ error = TT_Err_Invalid_File_Format;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_SBit_Strikes */
+ /* */
+ /* <Description> */
+ /* Loads the table of embedded bitmap sizes for this face. */
+ /* */
+ /* <Input> */
+ /* face :: The target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_SBit_Strikes( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error = 0;
+ FT_Memory memory = stream->memory;
+ FT_Fixed version;
+ FT_ULong num_strikes;
+ FT_ULong table_base;
+
+ const FT_Frame_Field sbit_line_metrics_fields[] =
+ {
+ /* no FT_FRAME_START */
+ FT_FRAME_CHAR( TT_SBit_Line_Metrics, ascender ),
+ FT_FRAME_CHAR( TT_SBit_Line_Metrics, descender ),
+ FT_FRAME_BYTE( TT_SBit_Line_Metrics, max_width ),
+
+ FT_FRAME_CHAR( TT_SBit_Line_Metrics, caret_slope_numerator ),
+ FT_FRAME_CHAR( TT_SBit_Line_Metrics, caret_slope_denominator ),
+ FT_FRAME_CHAR( TT_SBit_Line_Metrics, caret_offset ),
+
+ FT_FRAME_CHAR( TT_SBit_Line_Metrics, min_origin_SB ),
+ FT_FRAME_CHAR( TT_SBit_Line_Metrics, min_advance_SB ),
+ FT_FRAME_CHAR( TT_SBit_Line_Metrics, max_before_BL ),
+ FT_FRAME_CHAR( TT_SBit_Line_Metrics, min_after_BL ),
+ FT_FRAME_CHAR( TT_SBit_Line_Metrics, pads[0] ),
+ FT_FRAME_CHAR( TT_SBit_Line_Metrics, pads[1] ),
+ FT_FRAME_END
+ };
+
+ const FT_Frame_Field strike_start_fields[] =
+ {
+ /* no FT_FRAME_START */
+ FT_FRAME_ULONG( TT_SBit_Strike, ranges_offset ),
+ FT_FRAME_SKIP_LONG,
+ FT_FRAME_ULONG( TT_SBit_Strike, num_ranges ),
+ FT_FRAME_ULONG( TT_SBit_Strike, color_ref ),
+ FT_FRAME_END
+ };
+
+ const FT_Frame_Field strike_end_fields[] =
+ {
+ /* no FT_FRAME_START */
+ FT_FRAME_USHORT( TT_SBit_Strike, start_glyph ),
+ FT_FRAME_USHORT( TT_SBit_Strike, end_glyph ),
+ FT_FRAME_BYTE ( TT_SBit_Strike, x_ppem ),
+ FT_FRAME_BYTE ( TT_SBit_Strike, y_ppem ),
+ FT_FRAME_BYTE ( TT_SBit_Strike, bit_depth ),
+ FT_FRAME_CHAR ( TT_SBit_Strike, flags ),
+ FT_FRAME_END
+ };
+
+
+ face->num_sbit_strikes = 0;
+
+ /* this table is optional */
+ error = face->goto_table( face, TTAG_EBLC, stream, 0 );
+ if (error)
+ error = face->goto_table( face, TTAG_bloc, stream, 0 );
+ if ( error )
+ {
+ error = 0;
+ goto Exit;
+ }
+
+ table_base = FILE_Pos();
+ if ( ACCESS_Frame( 8L ) )
+ goto Exit;
+
+ version = GET_Long();
+ num_strikes = GET_ULong();
+
+ FORGET_Frame();
+
+ /* check version number and strike count */
+ if ( version != 0x00020000L ||
+ num_strikes >= 0x10000L )
+ {
+ FT_ERROR(( "TT_Load_SBit_Strikes: invalid table version!\n" ));
+ error = TT_Err_Invalid_File_Format;
+
+ goto Exit;
+ }
+
+ /* allocate the strikes table */
+ if ( ALLOC_ARRAY( face->sbit_strikes, num_strikes, TT_SBit_Strike ) )
+ goto Exit;
+
+ face->num_sbit_strikes = num_strikes;
+
+ /* now read each strike table separately */
+ {
+ TT_SBit_Strike* strike = face->sbit_strikes;
+ FT_ULong count = num_strikes;
+
+
+ if ( ACCESS_Frame( 48L * num_strikes ) )
+ goto Exit;
+
+ while ( count > 0 )
+ {
+ (void)READ_Fields( strike_start_fields, strike );
+
+ (void)READ_Fields( sbit_line_metrics_fields, &strike->hori );
+ (void)READ_Fields( sbit_line_metrics_fields, &strike->vert );
+
+ (void)READ_Fields( strike_end_fields, strike );
+
+ count--;
+ strike++;
+ }
+
+ FORGET_Frame();
+ }
+
+ /* allocate the index ranges for each strike table */
+ {
+ TT_SBit_Strike* strike = face->sbit_strikes;
+ FT_ULong count = num_strikes;
+
+
+ while ( count > 0 )
+ {
+ TT_SBit_Range* range;
+ FT_ULong count2 = strike->num_ranges;
+
+
+ if ( ALLOC_ARRAY( strike->sbit_ranges,
+ strike->num_ranges,
+ TT_SBit_Range ) )
+ goto Exit;
+
+ /* read each range */
+ if ( FILE_Seek( table_base + strike->ranges_offset ) ||
+ ACCESS_Frame( strike->num_ranges * 8L ) )
+ goto Exit;
+
+ range = strike->sbit_ranges;
+ while ( count2 > 0 )
+ {
+ range->first_glyph = GET_UShort();
+ range->last_glyph = GET_UShort();
+ range->table_offset = table_base + strike->ranges_offset
+ + GET_ULong();
+ count2--;
+ range++;
+ }
+
+ FORGET_Frame();
+
+ /* Now, read each index table */
+ count2 = strike->num_ranges;
+ range = strike->sbit_ranges;
+ while ( count2 > 0 )
+ {
+ /* Read the header */
+ if ( FILE_Seek( range->table_offset ) ||
+ ACCESS_Frame( 8L ) )
+ goto Exit;
+
+ range->index_format = GET_UShort();
+ range->image_format = GET_UShort();
+ range->image_offset = GET_ULong();
+
+ FORGET_Frame();
+
+ error = Load_SBit_Range( range, stream );
+ if ( error )
+ goto Exit;
+
+ count2--;
+ range++;
+ }
+
+ count--;
+ strike++;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Free_SBit_Strikes */
+ /* */
+ /* <Description> */
+ /* Releases the embedded bitmap tables. */
+ /* */
+ /* <Input> */
+ /* face :: The target face object. */
+ /* */
+ LOCAL_FUNC
+ void TT_Free_SBit_Strikes( TT_Face face )
+ {
+ FT_Memory memory = face->root.memory;
+ TT_SBit_Strike* strike = face->sbit_strikes;
+ TT_SBit_Strike* strike_limit = strike + face->num_sbit_strikes;
+
+
+ if ( strike )
+ {
+ for ( ; strike < strike_limit; strike++ )
+ {
+ TT_SBit_Range* range = strike->sbit_ranges;
+ TT_SBit_Range* range_limit = range + strike->num_ranges;
+
+
+ if ( range )
+ {
+ for ( ; range < range_limit; range++ )
+ {
+ /* release the glyph offsets and codes tables */
+ /* where appropriate */
+ FREE( range->glyph_offsets );
+ FREE( range->glyph_codes );
+ }
+ }
+ FREE( strike->sbit_ranges );
+ strike->num_ranges = 0;
+ }
+ FREE( face->sbit_strikes );
+ }
+ face->num_sbit_strikes = 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Find_SBit_Range */
+ /* */
+ /* <Description> */
+ /* Scans a given strike's ranges and return, for a given glyph */
+ /* index, the corresponding sbit range, and `EBDT' offset. */
+ /* */
+ /* <Input> */
+ /* glyph_index :: The glyph index. */
+ /* strike :: The source/current sbit strike. */
+ /* */
+ /* <Output> */
+ /* arange :: The sbit range containing the glyph index. */
+ /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means the glyph index was found. */
+ /* */
+ static
+ FT_Error Find_SBit_Range( FT_UInt glyph_index,
+ TT_SBit_Strike* strike,
+ TT_SBit_Range** arange,
+ FT_ULong* aglyph_offset )
+ {
+ TT_SBit_Range *range, *range_limit;
+
+
+ /* check whether the glyph index is within this strike's */
+ /* glyph range */
+ if ( glyph_index < strike->start_glyph ||
+ glyph_index > strike->end_glyph )
+ goto Fail;
+
+ /* scan all ranges in strike */
+ range = strike->sbit_ranges;
+ range_limit = range + strike->num_ranges;
+ if ( !range )
+ goto Fail;
+
+ for ( ; range < range_limit; range++ )
+ {
+ if ( glyph_index >= range->first_glyph &&
+ glyph_index <= range->last_glyph )
+ {
+ FT_UShort delta = glyph_index - range->first_glyph;
+
+
+ switch ( range->index_format )
+ {
+ case 1:
+ case 3:
+ *aglyph_offset = range->glyph_offsets[delta];
+ break;
+
+ case 2:
+ *aglyph_offset = range->image_offset +
+ range->image_size * delta;
+ break;
+
+ case 4:
+ case 5:
+ {
+ FT_ULong n;
+
+
+ for ( n = 0; n < range->num_glyphs; n++ )
+ {
+ if ( range->glyph_codes[n] == glyph_index )
+ {
+ if ( range->index_format == 4 )
+ *aglyph_offset = range->glyph_offsets[n];
+ else
+ *aglyph_offset = range->image_offset +
+ n * range->image_size;
+ goto Found;
+ }
+ }
+ }
+
+ /* fall-through */
+ default:
+ goto Fail;
+ }
+
+ Found:
+ /* return successfully! */
+ *arange = range;
+ return 0;
+ }
+ }
+
+ Fail:
+ *arange = 0;
+ *aglyph_offset = 0;
+
+ return TT_Err_Invalid_Argument;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Find_SBit_Image */
+ /* */
+ /* <Description> */
+ /* Checks whether an embedded bitmap (an `sbit') exists for a given */
+ /* glyph, at given x and y ppems. */
+ /* */
+ /* <Input> */
+ /* face :: The target face object. */
+ /* glyph_index :: The glyph index. */
+ /* x_ppem :: The horizontal resolution in points per EM. */
+ /* y_ppem :: The vertical resolution in points per EM. */
+ /* */
+ /* <Output> */
+ /* arange :: The SBit range containing the glyph index. */
+ /* astrike :: The SBit strike containing the glyph index. */
+ /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. Returns */
+ /* TT_Err_Invalid_Argument if no sbit exists for the requested glyph. */
+ /* */
+ static
+ FT_Error Find_SBit_Image( TT_Face face,
+ FT_UInt glyph_index,
+ FT_Int x_ppem,
+ FT_Int y_ppem,
+
+ TT_SBit_Range** arange,
+ TT_SBit_Strike** astrike,
+ FT_ULong* aglyph_offset )
+ {
+ TT_SBit_Strike* strike = face->sbit_strikes;
+ TT_SBit_Strike* strike_limit = strike + face->num_sbit_strikes;
+
+
+ if ( !strike )
+ goto Fail;
+
+ for ( ; strike < strike_limit; strike++ )
+ {
+ if ( strike->x_ppem == x_ppem && strike->y_ppem == y_ppem )
+ {
+ FT_Error error;
+
+
+ error = Find_SBit_Range( glyph_index, strike,
+ arange, aglyph_offset );
+ if ( error )
+ goto Fail;
+
+ *astrike = strike;
+
+ return TT_Err_Ok;
+ }
+ }
+
+ Fail:
+ /* no embedded bitmap for this glyph in face */
+ *arange = 0;
+ *astrike = 0;
+ *aglyph_offset = 0;
+
+ return TT_Err_Invalid_Argument;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Load_SBit_Metrics */
+ /* */
+ /* <Description> */
+ /* Gets the big metrics for a given SBit. */
+ /* */
+ /* <Input> */
+ /* stream :: The input stream. */
+ /* */
+ /* range :: The SBit range containing the glyph. */
+ /* */
+ /* <Output> */
+ /* big_metrics :: A big SBit metrics structure for the glyph. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The stream cursor must be positioned at the glyph's offset within */
+ /* the `EBDT' table before the call. */
+ /* */
+ /* If the image format uses variable metrics, the stream cursor is */
+ /* positioned just after the metrics header in the `EBDT' table on */
+ /* function exit. */
+ /* */
+ static
+ FT_Error Load_SBit_Metrics( FT_Stream stream,
+ TT_SBit_Range* range,
+ TT_SBit_Metrics* metrics )
+ {
+ FT_Error error = TT_Err_Ok;
+
+
+ switch ( range->image_format )
+ {
+ case 1:
+ case 2:
+ case 8:
+ /* variable small metrics */
+ {
+ TT_SBit_Small_Metrics smetrics;
+
+ const FT_Frame_Field sbit_small_metrics_fields[] =
+ {
+ FT_FRAME_START( 5 ),
+ FT_FRAME_BYTE( TT_SBit_Small_Metrics, height ),
+ FT_FRAME_BYTE( TT_SBit_Small_Metrics, width ),
+ FT_FRAME_CHAR( TT_SBit_Small_Metrics, bearingX ),
+ FT_FRAME_CHAR( TT_SBit_Small_Metrics, bearingY ),
+ FT_FRAME_BYTE( TT_SBit_Small_Metrics, advance ),
+ FT_FRAME_END
+ };
+
+
+ /* read small metrics */
+ if ( READ_Fields( sbit_small_metrics_fields, &smetrics ) )
+ goto Exit;
+
+ /* convert it to a big metrics */
+ metrics->height = smetrics.height;
+ metrics->width = smetrics.width;
+ metrics->horiBearingX = smetrics.bearingX;
+ metrics->horiBearingY = smetrics.bearingY;
+ metrics->horiAdvance = smetrics.advance;
+
+ /* these metrics are made up at a higher level when */
+ /* needed. */
+ metrics->vertBearingX = 0;
+ metrics->vertBearingY = 0;
+ metrics->vertAdvance = 0;
+ }
+ break;
+
+ case 6:
+ case 7:
+ case 9:
+ /* variable big metrics */
+ (void)READ_Fields( sbit_metrics_fields, metrics );
+ break;
+
+ case 5:
+ default: /* constant metrics */
+ if ( range->index_format == 2 || range->index_format == 5 )
+ *metrics = range->metrics;
+ else
+ return TT_Err_Invalid_File_Format;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Crop_Bitmap */
+ /* */
+ /* <Description> */
+ /* Crops a bitmap to its tightest bounding box, and adjusts its */
+ /* metrics. */
+ /* */
+ /* <Input> */
+ /* image :: The input glyph slot. */
+ /* */
+ /* metrics :: The corresponding metrics structure. */
+ /* */
+ static
+ void Crop_Bitmap( FT_Bitmap* map,
+ TT_SBit_Metrics* metrics )
+ {
+ /***********************************************************************/
+ /* */
+ /* In this situation, some bounding boxes of embedded bitmaps are too */
+ /* large. We need to crop it to a reasonable size. */
+ /* */
+ /* --------- */
+ /* | | ----- */
+ /* | *** | |***| */
+ /* | * | | * | */
+ /* | * | ------> | * | */
+ /* | * | | * | */
+ /* | * | | * | */
+ /* | *** | |***| */
+ /* --------- ----- */
+ /* */
+ /***********************************************************************/
+
+ FT_Int rows, count;
+ FT_Long line_len;
+ FT_Byte* line;
+
+
+ /***********************************************************************/
+ /* */
+ /* first of all, check the top-most lines of the bitmap, and remove */
+ /* them if they're empty. */
+ /* */
+ {
+ line = (FT_Byte*)map->buffer;
+ rows = map->rows;
+ line_len = map->pitch;
+
+
+ for ( count = 0; count < rows; count++ )
+ {
+ FT_Byte* cur = line;
+ FT_Byte* limit = line + line_len;
+
+
+ for ( ; cur < limit; cur++ )
+ if ( cur[0] )
+ goto Found_Top;
+
+ /* the current line was empty - skip to next one */
+ line = limit;
+ }
+
+ Found_Top:
+ /* check that we have at least one filled line */
+ if ( count >= rows )
+ goto Empty_Bitmap;
+
+ /* now, crop the empty upper lines */
+ if ( count > 0 )
+ {
+ line = (FT_Byte*)map->buffer;
+
+ MEM_Move( line, line + count * line_len,
+ ( rows - count ) * line_len );
+
+ metrics->height -= count;
+ metrics->horiBearingY -= count;
+ metrics->vertBearingY -= count;
+
+ map->rows -= count;
+ rows -= count;
+ }
+ }
+
+ /***********************************************************************/
+ /* */
+ /* second, crop the lower lines */
+ /* */
+ {
+ line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len;
+
+ for ( count = 0; count < rows; count++ )
+ {
+ FT_Byte* cur = line;
+ FT_Byte* limit = line + line_len;
+
+
+ for ( ; cur < limit; cur++ )
+ if ( cur[0] )
+ goto Found_Bottom;
+
+ /* the current line was empty - skip to previous one */
+ line -= line_len;
+ }
+
+ Found_Bottom:
+ if ( count > 0 )
+ {
+ metrics->height -= count;
+ rows -= count;
+ map->rows -= count;
+ }
+ }
+
+ /***********************************************************************/
+ /* */
+ /* third, get rid of the space on the left side of the glyph */
+ /* */
+ do
+ {
+ FT_Byte* limit;
+
+
+ line = (FT_Byte*)map->buffer;
+ limit = line + rows * line_len;
+
+ for ( ; line < limit; line += line_len )
+ if ( line[0] & 0x80 )
+ goto Found_Left;
+
+ /* shift the whole glyph one pixel to the left */
+ line = (FT_Byte*)map->buffer;
+ limit = line + rows * line_len;
+
+ for ( ; line < limit; line += line_len )
+ {
+ FT_Int n, width = map->width;
+ FT_Byte old;
+ FT_Byte* cur = line;
+
+
+ old = cur[0] << 1;
+ for ( n = 8; n < width; n += 8 )
+ {
+ FT_Byte val;
+
+
+ val = cur[1];
+ cur[0] = old | ( val >> 7 );
+ old = val << 1;
+ cur++;
+ }
+ cur[0] = old;
+ }
+
+ map->width--;
+ metrics->horiBearingX++;
+ metrics->vertBearingX++;
+ metrics->width--;
+
+ } while ( map->width > 0 );
+
+ Found_Left:
+
+ /***********************************************************************/
+ /* */
+ /* finally, crop the bitmap width to get rid of the space on the right */
+ /* side of the glyph. */
+ /* */
+ do
+ {
+ FT_Int right = map->width - 1;
+ FT_Byte* limit;
+ FT_Byte mask;
+
+
+ line = (FT_Byte*)map->buffer + ( right >> 3 );
+ limit = line + rows * line_len;
+ mask = 0x80 >> ( right & 7 );
+
+ for ( ; line < limit; line += line_len )
+ if ( line[0] & mask )
+ goto Found_Right;
+
+ /* crop the whole glyph to the right */
+ map->width--;
+ metrics->width--;
+
+ } while ( map->width > 0 );
+
+ Found_Right:
+ /* all right, the bitmap was cropped */
+ return;
+
+ Empty_Bitmap:
+ map->width = 0;
+ map->rows = 0;
+ map->pitch = 0;
+ map->pixel_mode = ft_pixel_mode_mono;
+ }
+
+
+ static
+ FT_Error Load_SBit_Single( FT_Bitmap* map,
+ FT_Int x_offset,
+ FT_Int y_offset,
+ FT_Int pix_bits,
+ FT_UShort image_format,
+ TT_SBit_Metrics* metrics,
+ FT_Stream stream )
+ {
+ FT_Error error;
+
+
+ /* check that the source bitmap fits into the target pixmap */
+ if ( x_offset < 0 || x_offset + metrics->width > map->width ||
+ y_offset < 0 || y_offset + metrics->height > map->rows )
+ {
+ error = TT_Err_Invalid_Argument;
+
+ goto Exit;
+ }
+
+ {
+ FT_Int glyph_width = metrics->width;
+ FT_Int glyph_height = metrics->height;
+ FT_Int glyph_size;
+ FT_Int line_bits = pix_bits * glyph_width;
+ FT_Bool pad_bytes = 0;
+
+
+ /* compute size of glyph image */
+ switch ( image_format )
+ {
+ case 1: /* byte-padded formats */
+ case 6:
+ {
+ FT_Int line_length;
+
+
+ switch ( pix_bits )
+ {
+ case 1: line_length = ( glyph_width + 7 ) >> 3; break;
+ case 2: line_length = ( glyph_width + 3 ) >> 2; break;
+ case 4: line_length = ( glyph_width + 1 ) >> 1; break;
+ default: line_length = glyph_width;
+ }
+
+ glyph_size = glyph_height * line_length;
+ pad_bytes = 1;
+ }
+ break;
+
+ case 2:
+ case 5:
+ case 7:
+ line_bits = glyph_width * pix_bits;
+ glyph_size = ( glyph_height * line_bits + 7 ) >> 3;
+ break;
+
+ default: /* invalid format */
+ return TT_Err_Invalid_File_Format;
+ }
+
+ /* Now read data and draw glyph into target pixmap */
+ if ( ACCESS_Frame( glyph_size ) )
+ goto Exit;
+
+ /* don't forget to multiply `x_offset' by `map->pix_bits' as */
+ /* the sbit blitter doesn't make a difference between pixmap */
+ /* depths. */
+ blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes,
+ x_offset * pix_bits, y_offset );
+
+ FORGET_Frame();
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ FT_Error Load_SBit_Image( TT_SBit_Strike* strike,
+ TT_SBit_Range* range,
+ FT_ULong ebdt_pos,
+ FT_ULong glyph_offset,
+ FT_Bitmap* map,
+ FT_Int x_offset,
+ FT_Int y_offset,
+ FT_Stream stream,
+ TT_SBit_Metrics* metrics )
+ {
+ FT_Memory memory = stream->memory;
+ FT_Error error;
+
+
+ /* place stream at beginning of glyph data and read metrics */
+ if ( FILE_Seek( ebdt_pos + glyph_offset ) )
+ goto Exit;
+
+ error = Load_SBit_Metrics( stream, range, metrics );
+ if ( error )
+ goto Exit;
+
+ /* this function is recursive. At the top-level call, the */
+ /* field map.buffer is NULL. We thus begin by finding the */
+ /* dimensions of the higher-level glyph to allocate the */
+ /* final pixmap buffer */
+ if ( map->buffer == 0 )
+ {
+ FT_Long size;
+
+
+ map->width = metrics->width;
+ map->rows = metrics->height;
+
+ switch ( strike->bit_depth )
+ {
+ case 1:
+ map->pixel_mode = ft_pixel_mode_mono;
+ map->pitch = ( map->width + 7 ) >> 3;
+ break;
+
+ case 2:
+ map->pixel_mode = ft_pixel_mode_pal2;
+ map->pitch = ( map->width + 3 ) >> 2;
+ break;
+
+ case 4:
+ map->pixel_mode = ft_pixel_mode_pal4;
+ map->pitch = ( map->width + 1 ) >> 1;
+ break;
+
+ case 8:
+ map->pixel_mode = ft_pixel_mode_grays;
+ map->pitch = map->width;
+ break;
+
+ default:
+ return TT_Err_Invalid_File_Format;
+ }
+
+ size = map->rows * map->pitch;
+
+ /* check that there is no empty image */
+ if ( size == 0 )
+ goto Exit; /* exit successfully! */
+
+ if ( ALLOC( map->buffer, size ) )
+ goto Exit;
+ }
+
+ switch ( range->image_format )
+ {
+ case 1: /* single sbit image - load it */
+ case 2:
+ case 5:
+ case 6:
+ case 7:
+ return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth,
+ range->image_format, metrics, stream );
+
+ case 8: /* compound format */
+ FT_Skip_Stream( stream, 1L );
+ /* fallthrough */
+
+ case 9:
+ break;
+
+ default: /* invalid image format */
+ return TT_Err_Invalid_File_Format;
+ }
+
+ /* All right, we have a compound format. First of all, read */
+ /* the array of elements. */
+ {
+ TT_SBit_Component* components;
+ TT_SBit_Component* comp;
+ FT_UShort num_components, count;
+
+
+ if ( READ_UShort( num_components ) ||
+ ALLOC_ARRAY( components, num_components, TT_SBit_Component ) )
+ goto Exit;
+
+ count = num_components;
+
+ if ( ACCESS_Frame( 4L * num_components ) )
+ goto Fail_Memory;
+
+ for ( comp = components; count > 0; count--, comp++ )
+ {
+ comp->glyph_code = GET_UShort();
+ comp->x_offset = GET_Char();
+ comp->y_offset = GET_Char();
+ }
+
+ FORGET_Frame();
+
+ /* Now recursively load each element glyph */
+ count = num_components;
+ comp = components;
+ for ( ; count > 0; count--, comp++ )
+ {
+ TT_SBit_Range* elem_range;
+ TT_SBit_Metrics elem_metrics;
+ FT_ULong elem_offset;
+
+
+ /* find the range for this element */
+ error = Find_SBit_Range( comp->glyph_code,
+ strike,
+ &elem_range,
+ &elem_offset );
+ if ( error )
+ goto Fail_Memory;
+
+ /* now load the element, recursively */
+ error = Load_SBit_Image( strike,
+ elem_range,
+ ebdt_pos,
+ elem_offset,
+ map,
+ x_offset + comp->x_offset,
+ y_offset + comp->y_offset,
+ stream,
+ &elem_metrics );
+ if ( error )
+ goto Fail_Memory;
+ }
+
+ Fail_Memory:
+ FREE( components );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_SBit_Image */
+ /* */
+ /* <Description> */
+ /* Loads a given glyph sbit image from the font resource. This also */
+ /* returns its metrics. */
+ /* */
+ /* <Input> */
+ /* face :: The target face object. */
+ /* */
+ /* x_ppem :: The horizontal resolution in points per EM. */
+ /* */
+ /* y_ppem :: The vertical resolution in points per EM. */
+ /* */
+ /* glyph_index :: The current glyph index. */
+ /* */
+ /* load_flags :: The glyph load flags (the code checks for the flag */
+ /* FT_LOAD_CROP_BITMAP */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Output> */
+ /* map :: The target pixmap. */
+ /* */
+ /* metrics :: A big sbit metrics structure for the glyph image. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. Returns an error if no */
+ /* glyph sbit exists for the index. */
+ /* */
+ /* <Note> */
+ /* The `map.buffer' field is always freed before the glyph is loaded. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_SBit_Image( TT_Face face,
+ FT_Int x_ppem,
+ FT_Int y_ppem,
+ FT_UInt glyph_index,
+ FT_UInt load_flags,
+ FT_Stream stream,
+ FT_Bitmap* map,
+ TT_SBit_Metrics* metrics )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_ULong ebdt_pos, glyph_offset;
+
+ TT_SBit_Strike* strike;
+ TT_SBit_Range* range;
+
+
+ /* Check whether there is a glyph sbit for the current index */
+ error = Find_SBit_Image( face, glyph_index, x_ppem, y_ppem,
+ &range, &strike, &glyph_offset );
+ if ( error )
+ goto Exit;
+
+ /* now, find the location of the `EBDT' table in */
+ /* the font file */
+ error = face->goto_table( face, TTAG_EBDT, stream, 0 );
+ if ( error )
+ error = face->goto_table( face, TTAG_bdat, stream, 0 );
+ if (error)
+ goto Exit;
+
+ ebdt_pos = FILE_Pos();
+
+ /* clear the bitmap & load the bitmap */
+ if ( face->root.glyph->flags & ft_glyph_own_bitmap )
+ FREE( map->buffer );
+
+ map->rows = map->pitch = map->width = 0;
+
+ error = Load_SBit_Image( strike, range, ebdt_pos, glyph_offset,
+ map, 0, 0, stream, metrics );
+ if ( error )
+ goto Exit;
+
+ /* the glyph slot owns this bitmap buffer */
+ face->root.glyph->flags |= ft_glyph_own_bitmap;
+
+ /* setup vertical metrics if needed */
+ if ( strike->flags & 1 )
+ {
+ /* in case of a horizontal strike only */
+ FT_Int advance;
+ FT_Int top;
+
+
+ advance = strike->hori.ascender - strike->hori.descender;
+ top = advance / 10;
+
+ /* some heuristic values */
+
+ metrics->vertBearingX = -metrics->width / 2;
+ metrics->vertBearingY = advance / 10;
+ metrics->vertAdvance = advance * 12 / 10;
+ }
+
+ /* Crop the bitmap now, unless specified otherwise */
+ if ( load_flags & FT_LOAD_CROP_BITMAP )
+ Crop_Bitmap( map, metrics );
+
+ Exit:
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttsbit.h */
+/* */
+/* TrueType and OpenType embedded bitmap support (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef TTSBIT_H
+#define TTSBIT_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttload.h"
+
+#else
+
+#include <sfnt/ttload.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ LOCAL_DEF
+ FT_Error TT_Load_SBit_Strikes( TT_Face face,
+ FT_Stream stream );
+
+ LOCAL_DEF
+ void TT_Free_SBit_Strikes( TT_Face face );
+
+ LOCAL_DEF
+ FT_Error TT_Load_SBit_Image( TT_Face face,
+ FT_Int x_ppem,
+ FT_Int y_ppem,
+ FT_UInt glyph_index,
+ FT_UInt load_flags,
+ FT_Stream stream,
+ FT_Bitmap* map,
+ TT_SBit_Metrics* metrics );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* TTSBIT_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftgrays.c */
+/* */
+/* A new `perfect' anti-aliasing renderer (body). */
+/* */
+/* Copyright 2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* This file can be compiled without the rest of the FreeType engine, */
+ /* by defining the _STANDALONE_ macro when compiling it. You also need */
+ /* to put the files `ftgrays.h' and `ftimage.h' into the current */
+ /* compilation directory. Typically, you could do something like */
+ /* */
+ /* - copy `src/base/ftgrays.c' to your current directory */
+ /* */
+ /* - copy `include/freetype/ftimage.h' and */
+ /* `include/freetype/ftgrays.h' to the same directory */
+ /* */
+ /* - compile `ftgrays' with the _STANDALONE_ macro defined, as in */
+ /* */
+ /* cc -c -D_STANDALONE_ ftgrays.c */
+ /* */
+ /* The renderer can be initialized with a call to */
+ /* `ft_grays_raster.grays_raster_new'; an anti-aliased bitmap can be */
+ /* generated with a call to `ft_grays_raster.grays_raster_render'. */
+ /* */
+ /* See the comments and documentation in the file `ftimage.h' for */
+ /* more details on how the raster works. */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* This is a new anti-aliasing scan-converter for FreeType 2. The */
+ /* algorithm used here is _very_ different from the one in the standard */
+ /* `ftraster' module. Actually, `ftgrays' computes the _exact_ */
+ /* coverage of the outline on each pixel cell. */
+ /* */
+ /* It is based on ideas that I initially found in Raph Levien's */
+ /* excellent LibArt graphics library (see http://www.levien.com/libart */
+ /* for more information, though the web pages do not tell anything */
+ /* about the renderer; you'll have to dive into the source code to */
+ /* understand how it works). */
+ /* */
+ /* Note, however, that this is a _very_ different implementation */
+ /* compared to Raph's. Coverage information is stored in a very */
+ /* different way, and I don't use sorted vector paths. Also, it */
+ /* doesn't use floating point values. */
+ /* */
+ /* This renderer has the following advantages: */
+ /* */
+ /* - It doesn't need an intermediate bitmap. Instead, one can supply */
+ /* a callback function that will be called by the renderer to draw */
+ /* gray spans on any target surface. You can thus do direct */
+ /* composition on any kind of bitmap, provided that you give the */
+ /* renderer the right callback. */
+ /* */
+ /* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on */
+ /* each pixel cell */
+ /* */
+ /* - It performs a single pass on the outline (the `standard' FT2 */
+ /* renderer makes two passes). */
+ /* */
+ /* - It can easily be modified to render to _any_ number of gray levels */
+ /* cheaply. */
+ /* */
+ /* - For small (< 20) pixel sizes, it is faster than the standard */
+ /* renderer. */
+ /* */
+ /*************************************************************************/
+
+
+#include <string.h> /* for memcpy() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_aaraster
+
+
+#ifdef _STANDALONE_
+
+
+#define ErrRaster_Invalid_Mode -2
+#define ErrRaster_Invalid_Outline -1
+
+#include "ftimage.h"
+#include "ftgrays.h"
+
+ /* This macro is used to indicate that a function parameter is unused. */
+ /* Its purpose is simply to reduce compiler warnings. Note also that */
+ /* simply defining it as `(void)x' doesn't avoid warnings with certain */
+ /* ANSI compilers (e.g. LCC). */
+#define FT_UNUSED( x ) (x) = (x)
+
+ /* Disable the tracing mechanism for simplicity -- developers can */
+ /* activate it easily by redefining these two macros. */
+#ifndef FT_ERROR
+#define FT_ERROR( x ) do ; while ( 0 ) /* nothing */
+#endif
+
+#ifndef FT_TRACE
+#define FT_TRACE( x ) do ; while ( 0 ) /* nothing */
+#endif
+
+
+#else /* _STANDALONE_ */
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ftgrays.h"
+
+#else
+
+#include <smooth/ftgrays.h>
+
+#endif
+
+
+#include <freetype/internal/ftobjs.h> /* for FT_UNUSED() */
+#include <freetype/internal/ftdebug.h> /* for FT_TRACE() and FT_ERROR() */
+#include <freetype/ftoutln.h> /* for FT_Outline_Decompose() */
+
+#define ErrRaster_Invalid_Mode FT_Err_Cannot_Render_Glyph
+#define ErrRaster_Invalid_Outline FT_Err_Invalid_Outline
+
+
+#endif /* _STANDALONE_ */
+
+
+ /* define this to dump debugging information */
+#define xxxDEBUG_GRAYS
+
+ /* as usual, for the speed hungry :-) */
+
+#ifndef FT_STATIC_RASTER
+
+
+#define RAS_ARG PRaster raster
+#define RAS_ARG_ PRaster raster,
+
+#define RAS_VAR raster
+#define RAS_VAR_ raster,
+
+#define ras (*raster)
+
+
+#else /* FT_STATIC_RASTER */
+
+
+#define RAS_ARG /* empty */
+#define RAS_ARG_ /* empty */
+#define RAS_VAR /* empty */
+#define RAS_VAR_ /* empty */
+
+ static TRaster ras;
+
+
+#endif /* FT_STATIC_RASTER */
+
+
+ /* must be at least 6 bits! */
+#define PIXEL_BITS 8
+
+#define ONE_PIXEL ( 1L << PIXEL_BITS )
+#define PIXEL_MASK ( -1L << PIXEL_BITS )
+#define TRUNC( x ) ( (x) >> PIXEL_BITS )
+#define SUBPIXELS( x ) ( (x) << PIXEL_BITS )
+#define FLOOR( x ) ( (x) & -ONE_PIXEL )
+#define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
+#define ROUND( x ) ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
+
+#if PIXEL_BITS >= 6
+#define UPSCALE( x ) ( (x) << ( PIXEL_BITS - 6 ) )
+#define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) )
+#else
+#define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) )
+#define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) )
+#endif
+
+ /* Define this if you want to use a more compact storage scheme. This */
+ /* increases the number of cells available in the render pool but slows */
+ /* down the rendering a bit. It is useful if you have a really tiny */
+ /* render pool. */
+#define xxxGRAYS_COMPACT
+
+
+ /*************************************************************************/
+ /* */
+ /* TYPE DEFINITIONS */
+ /* */
+ typedef int TScan; /* integer scanline/pixel coordinate */
+ typedef long TPos; /* sub-pixel coordinate */
+
+ /* maximal number of gray spans in a call to the span callback */
+#define FT_MAX_GRAY_SPANS 32
+
+
+#ifdef GRAYS_COMPACT
+
+ typedef struct TCell_
+ {
+ short x : 14;
+ short y : 14;
+ int cover : PIXEL_BITS + 2;
+ int area : PIXEL_BITS * 2 + 2;
+
+ } TCell, *PCell;
+
+#else /* GRAYS_COMPACT */
+
+ typedef struct TCell_
+ {
+ TScan x;
+ TScan y;
+ int cover;
+ int area;
+
+ } TCell, *PCell;
+
+#endif /* GRAYS_COMPACT */
+
+
+ typedef struct TRaster_
+ {
+ PCell cells;
+ int max_cells;
+ int num_cells;
+
+ TScan min_ex, max_ex;
+ TScan min_ey, max_ey;
+
+ int area;
+ int cover;
+ int invalid;
+
+ TScan ex, ey;
+ TScan cx, cy;
+ TPos x, y;
+
+ TScan last_ey;
+
+ FT_Vector bez_stack[32 * 3];
+ int lev_stack[32];
+
+ FT_Outline outline;
+ FT_Bitmap target;
+
+ FT_Span gray_spans[FT_MAX_GRAY_SPANS];
+ int num_gray_spans;
+
+ FT_Raster_Span_Func render_span;
+ void* render_span_data;
+ int span_y;
+
+ int band_size;
+ int band_shoot;
+ int conic_level;
+ int cubic_level;
+
+ void* memory;
+
+ } TRaster, *PRaster;
+
+
+ /*************************************************************************/
+ /* */
+ /* Initialize the cells table. */
+ /* */
+ static
+ void init_cells( RAS_ARG_ void* buffer,
+ long byte_size )
+ {
+ ras.cells = (PCell)buffer;
+ ras.max_cells = byte_size / sizeof ( TCell );
+ ras.num_cells = 0;
+ ras.area = 0;
+ ras.cover = 0;
+ ras.invalid = 1;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Compute the outline bounding box. */
+ /* */
+ static
+ void compute_cbox( RAS_ARG_ FT_Outline* outline )
+ {
+ FT_Vector* vec = outline->points;
+ FT_Vector* limit = vec + outline->n_points;
+
+
+ if ( outline->n_points <= 0 )
+ {
+ ras.min_ex = ras.max_ex = 0;
+ ras.min_ey = ras.max_ey = 0;
+ return;
+ }
+
+ ras.min_ex = ras.max_ex = vec->x;
+ ras.min_ey = ras.max_ey = vec->y;
+
+ vec++;
+
+ for ( ; vec < limit; vec++ )
+ {
+ TPos x = vec->x;
+ TPos y = vec->y;
+
+
+ if ( x < ras.min_ex ) ras.min_ex = x;
+ if ( x > ras.max_ex ) ras.max_ex = x;
+ if ( y < ras.min_ey ) ras.min_ey = y;
+ if ( y > ras.max_ey ) ras.max_ey = y;
+ }
+
+ /* truncate the bounding box to integer pixels */
+ ras.min_ex = ras.min_ex >> 6;
+ ras.min_ey = ras.min_ey >> 6;
+ ras.max_ex = ( ras.max_ex + 63 ) >> 6;
+ ras.max_ey = ( ras.max_ey + 63 ) >> 6;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Record the current cell in the table. */
+ /* */
+ static
+ int record_cell( RAS_ARG )
+ {
+ PCell cell;
+
+
+ if ( !ras.invalid && ( ras.area | ras.cover ) )
+ {
+ if ( ras.num_cells >= ras.max_cells )
+ return 1;
+
+ cell = ras.cells + ras.num_cells++;
+ cell->x = ras.ex - ras.min_ex;
+ cell->y = ras.ey - ras.min_ey;
+ cell->area = ras.area;
+ cell->cover = ras.cover;
+ }
+
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Set the current cell to a new position. */
+ /* */
+ static
+ int set_cell( RAS_ARG_ TScan ex,
+ TScan ey )
+ {
+ int invalid, record, clean;
+
+
+ /* Move the cell pointer to a new position. We set the `invalid' */
+ /* flag to indicate that the cell isn't part of those we're interested */
+ /* 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_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. */
+
+ record = 0;
+ clean = 1;
+
+ invalid = ( ey < ras.min_ey || ey >= ras.max_ey || ex >= ras.max_ex );
+ if ( !invalid )
+ {
+ /* All cells that are on the left of the clipping region go to the */
+ /* min_ex - 1 horizontal position. */
+ if ( ex < ras.min_ex )
+ ex = ras.min_ex - 1;
+
+ /* if our position is new, then record the previous cell */
+ if ( ex != ras.ex || ey != ras.ey )
+ record = 1;
+ else
+ clean = ras.invalid; /* do not clean if we didn't move from */
+ /* a valid cell */
+ }
+
+ /* record the previous cell if needed (i.e., if we changed the cell */
+ /* position, of changed the `invalid' flag) */
+ if ( ( ras.invalid != invalid || record ) && record_cell( RAS_VAR ) )
+ return 1;
+
+ if ( clean )
+ {
+ ras.area = 0;
+ ras.cover = 0;
+ }
+
+ ras.invalid = invalid;
+ ras.ex = ex;
+ ras.ey = ey;
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Start a new contour at a given cell. */
+ /* */
+ static
+ void start_cell( RAS_ARG_ TScan ex,
+ TScan ey )
+ {
+ if ( ex < ras.min_ex )
+ ex = ras.min_ex - 1;
+
+ ras.area = 0;
+ ras.cover = 0;
+ ras.ex = ex;
+ ras.ey = ey;
+ ras.last_ey = SUBPIXELS( ey );
+ ras.invalid = 0;
+
+ (void)set_cell( RAS_VAR_ ex, ey );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Render a scanline as one or more cells. */
+ /* */
+ static
+ int render_scanline( RAS_ARG_ TScan ey,
+ TPos x1,
+ TScan y1,
+ TPos x2,
+ TScan y2 )
+ {
+ TScan ex1, ex2, fx1, fx2, delta;
+ long p, first, dx;
+ int incr, lift, mod, rem;
+
+
+ dx = x2 - x1;
+
+ ex1 = TRUNC( x1 ); /* if (ex1 >= ras.max_ex) ex1 = ras.max_ex-1; */
+ ex2 = TRUNC( x2 ); /* if (ex2 >= ras.max_ex) ex2 = ras.max_ex-1; */
+ fx1 = x1 - SUBPIXELS( ex1 );
+ fx2 = x2 - SUBPIXELS( ex2 );
+
+ /* trivial case. Happens often */
+ if ( y1 == y2 )
+ return set_cell( RAS_VAR_ ex2, ey );
+
+ /* everything is located in a single cell. That is easy! */
+ /* */
+ if ( ex1 == ex2 )
+ {
+ delta = y2 - y1;
+ ras.area += ( fx1 + fx2 ) * delta;
+ ras.cover += delta;
+ return 0;
+ }
+
+ /* ok, we'll have to render a run of adjacent cells on the same */
+ /* scanline... */
+ /* */
+ p = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );
+ first = ONE_PIXEL;
+ incr = 1;
+
+ if ( dx < 0 )
+ {
+ p = fx1 * ( y2 - y1 );
+ first = 0;
+ incr = -1;
+ dx = -dx;
+ }
+
+ delta = p / dx;
+ mod = p % dx;
+ if ( mod < 0 )
+ {
+ delta--;
+ mod += dx;
+ }
+
+ ras.area += ( fx1 + first ) * delta;
+ ras.cover += delta;
+
+ ex1 += incr;
+ if ( set_cell( RAS_VAR_ ex1, ey ) )
+ goto Error;
+ y1 += delta;
+
+ if ( ex1 != ex2 )
+ {
+ p = ONE_PIXEL * ( y2 - y1 );
+ lift = p / dx;
+ rem = p % dx;
+ if ( rem < 0 )
+ {
+ lift--;
+ rem += dx;
+ }
+
+ mod -= dx;
+
+ while ( ex1 != ex2 )
+ {
+ delta = lift;
+ mod += rem;
+ if ( mod >= 0 )
+ {
+ mod -= dx;
+ delta++;
+ }
+
+ ras.area += ONE_PIXEL * delta;
+ ras.cover += delta;
+ y1 += delta;
+ ex1 += incr;
+ if ( set_cell( RAS_VAR_ ex1, ey ) )
+ goto Error;
+ }
+ }
+
+ delta = y2 - y1;
+ ras.area += ( fx2 + ONE_PIXEL - first ) * delta;
+ ras.cover += delta;
+
+ return 0;
+
+ Error:
+ return 1;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Render a given line as a series of scanlines. */
+ /* */
+ static
+ int render_line( RAS_ARG_ TPos to_x,
+ TPos to_y )
+ {
+ TScan ey1, ey2, fy1, fy2;
+ TPos dx, dy, x, x2;
+ int p, rem, mod, lift, delta, first, incr;
+
+
+ ey1 = TRUNC( ras.last_ey );
+ ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
+ fy1 = ras.y - ras.last_ey;
+ fy2 = to_y - SUBPIXELS( ey2 );
+
+ dx = to_x - ras.x;
+ dy = to_y - ras.y;
+
+ /* XXX: we should do something about the trivial case where dx == 0, */
+ /* as it happens very often! */
+
+ /* perform vertical clipping */
+ {
+ TScan min, max;
+
+
+ min = ey1;
+ max = ey2;
+ if ( ey1 > ey2 )
+ {
+ min = ey2;
+ max = ey1;
+ }
+ if ( min >= ras.max_ey || max < ras.min_ey )
+ goto End;
+ }
+
+ /* everything is on a single scanline */
+ if ( ey1 == ey2 )
+ {
+ if ( render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 ) )
+ goto Error;
+ goto End;
+ }
+
+ /* ok, we have to render several scanlines */
+ p = ( ONE_PIXEL - fy1 ) * dx;
+ first = ONE_PIXEL;
+ incr = 1;
+
+ if ( dy < 0 )
+ {
+ p = fy1 * dx;
+ first = 0;
+ incr = -1;
+ dy = -dy;
+ }
+
+ delta = p / dy;
+ mod = p % dy;
+ if ( mod < 0 )
+ {
+ delta--;
+ mod += dy;
+ }
+
+ x = ras.x + delta;
+ if ( render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, first ) )
+ goto Error;
+
+ ey1 += incr;
+ if ( set_cell( RAS_VAR_ TRUNC( x ), ey1 ) )
+ goto Error;
+
+ if ( ey1 != ey2 )
+ {
+ p = ONE_PIXEL * dx;
+ lift = p / dy;
+ rem = p % dy;
+ if ( rem < 0 )
+ {
+ lift--;
+ rem += dy;
+ }
+ mod -= dy;
+
+ while ( ey1 != ey2 )
+ {
+ delta = lift;
+ mod += rem;
+ if ( mod >= 0 )
+ {
+ mod -= dy;
+ delta++;
+ }
+
+ x2 = x + delta;
+ if ( render_scanline( RAS_VAR_ ey1,
+ x, ONE_PIXEL - first, x2, first ) )
+ goto Error;
+ x = x2;
+ ey1 += incr;
+ if ( set_cell( RAS_VAR_ TRUNC( x ), ey1 ) )
+ goto Error;
+ }
+ }
+
+ if ( render_scanline( RAS_VAR_ ey1,
+ x, ONE_PIXEL - first, to_x, fy2 ) )
+ goto Error;
+
+ End:
+ ras.x = to_x;
+ ras.y = to_y;
+ ras.last_ey = SUBPIXELS( ey2 );
+
+ return 0;
+
+ Error:
+ return 1;
+ }
+
+
+ static
+ void split_conic( FT_Vector* base )
+ {
+ TPos a, b;
+
+
+ base[4].x = base[2].x;
+ b = base[1].x;
+ a = base[3].x = ( base[2].x + b ) / 2;
+ b = base[1].x = ( base[0].x + b ) / 2;
+ base[2].x = ( a + b ) / 2;
+
+ base[4].y = base[2].y;
+ b = base[1].y;
+ a = base[3].y = ( base[2].y + b ) / 2;
+ b = base[1].y = ( base[0].y + b ) / 2;
+ base[2].y = ( a + b ) / 2;
+ }
+
+
+ static
+ int render_conic( RAS_ARG_ FT_Vector* control,
+ FT_Vector* to )
+ {
+ TPos dx, dy;
+ int top, level;
+ int* levels;
+ FT_Vector* arc;
+
+
+ dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 );
+ if ( dx < 0 )
+ dx = -dx;
+ dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 );
+ if ( dy < 0 )
+ dy = -dy;
+ if ( dx < dy )
+ dx = dy;
+
+ level = 1;
+ dx = dx / ras.conic_level;
+ while ( dx > 0 )
+ {
+ dx >>= 1;
+ level++;
+ }
+
+ /* a shortcut to speed things up */
+ if ( level <= 1 )
+ {
+ /* we compute the mid-point directly in order to avoid */
+ /* calling split_conic() */
+ TPos to_x, to_y, mid_x, mid_y;
+
+
+ to_x = UPSCALE( to->x );
+ to_y = UPSCALE( to->y );
+ mid_x = ( ras.x + to_x + 2 * UPSCALE( control->x ) ) / 4;
+ mid_y = ( ras.y + to_y + 2 * UPSCALE( control->y ) ) / 4;
+
+ return render_line( RAS_VAR_ mid_x, mid_y ) ||
+ render_line( RAS_VAR_ to_x, to_y );
+ }
+
+ arc = ras.bez_stack;
+ levels = ras.lev_stack;
+ top = 0;
+ levels[0] = level;
+
+ arc[0].x = UPSCALE( to->x );
+ arc[0].y = UPSCALE( to->y );
+ arc[1].x = UPSCALE( control->x );
+ arc[1].y = UPSCALE( control->y );
+ arc[2].x = ras.x;
+ arc[2].y = ras.y;
+
+ while ( top >= 0 )
+ {
+ level = levels[top];
+ if ( level > 1 )
+ {
+ /* check that the arc crosses the current band */
+ TPos min, max, y;
+
+
+ min = max = arc[0].y;
+
+ y = arc[1].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
+
+ y = arc[2].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
+
+ if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
+ goto Draw;
+
+ split_conic( arc );
+ arc += 2;
+ top++;
+ levels[top] = levels[top - 1] = level - 1;
+ continue;
+ }
+
+ Draw:
+ {
+ TPos to_x, to_y, mid_x, mid_y;
+
+
+ to_x = arc[0].x;
+ to_y = arc[0].y;
+ mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4;
+ mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4;
+
+ if ( render_line( RAS_VAR_ mid_x, mid_y ) ||
+ render_line( RAS_VAR_ to_x, to_y ) )
+ return 1;
+
+ top--;
+ arc -= 2;
+ }
+ }
+ return 0;
+ }
+
+
+ static
+ void split_cubic( FT_Vector* base )
+ {
+ TPos a, b, c, d;
+
+
+ base[6].x = base[3].x;
+ c = base[1].x;
+ d = base[2].x;
+ base[1].x = a = ( base[0].x + c ) / 2;
+ base[5].x = b = ( base[3].x + d ) / 2;
+ c = ( c + d ) / 2;
+ base[2].x = a = ( a + c ) / 2;
+ base[4].x = b = ( b + c ) / 2;
+ base[3].x = ( a + b ) / 2;
+
+ base[6].y = base[3].y;
+ c = base[1].y;
+ d = base[2].y;
+ base[1].y = a = ( base[0].y + c ) / 2;
+ base[5].y = b = ( base[3].y + d ) / 2;
+ c = ( c + d ) / 2;
+ base[2].y = a = ( a + c ) / 2;
+ base[4].y = b = ( b + c ) / 2;
+ base[3].y = ( a + b ) / 2;
+ }
+
+
+ static
+ int render_cubic( RAS_ARG_ FT_Vector* control1,
+ FT_Vector* control2,
+ FT_Vector* to )
+ {
+ TPos dx, dy, da, db;
+ int top, level;
+ int* levels;
+ FT_Vector* arc;
+
+
+ dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 );
+ if ( dx < 0 )
+ dx = -dx;
+ dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 );
+ if ( dy < 0 )
+ dy = -dy;
+ if ( dx < dy )
+ dx = dy;
+ da = dx;
+
+ dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x );
+ if ( dx < 0 )
+ dx = -dx;
+ dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->x + control2->y );
+ if ( dy < 0 )
+ dy = -dy;
+ if ( dx < dy )
+ dx = dy;
+ db = dx;
+
+ level = 1;
+ da = da / ras.cubic_level;
+ db = db / ras.conic_level;
+ while ( da > 0 || db > 0 )
+ {
+ da >>= 1;
+ db >>= 2;
+ level++;
+ }
+
+ if ( level <= 1 )
+ {
+ TPos to_x, to_y, mid_x, mid_y;
+
+
+ to_x = UPSCALE( to->x );
+ to_y = UPSCALE( to->y );
+ mid_x = ( ras.x + to_x +
+ 3 * UPSCALE( control1->x + control2->x ) ) / 8;
+ mid_y = ( ras.y + to_y +
+ 3 * UPSCALE( control1->y + control2->y ) ) / 8;
+
+ return render_line( RAS_VAR_ mid_x, mid_y ) ||
+ render_line( RAS_VAR_ to_x, to_y );
+ }
+
+ arc = ras.bez_stack;
+ arc[0].x = UPSCALE( to->x );
+ arc[0].y = UPSCALE( to->y );
+ arc[1].x = UPSCALE( control2->x );
+ arc[1].y = UPSCALE( control2->y );
+ arc[2].x = UPSCALE( control1->x );
+ arc[2].y = UPSCALE( control1->y );
+ arc[3].x = ras.x;
+ arc[3].y = ras.y;
+
+ levels = ras.lev_stack;
+ top = 0;
+ levels[0] = level;
+
+ while ( top >= 0 )
+ {
+ level = levels[top];
+ if ( level > 1 )
+ {
+ /* check that the arc crosses the current band */
+ TPos min, max, y;
+
+
+ min = max = arc[0].y;
+ y = arc[1].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
+ y = arc[2].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
+ y = arc[3].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
+ if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
+ goto Draw;
+ split_cubic( arc );
+ arc += 3;
+ top ++;
+ levels[top] = levels[top - 1] = level - 1;
+ continue;
+ }
+
+ Draw:
+ {
+ TPos to_x, to_y, mid_x, mid_y;
+
+
+ to_x = arc[0].x;
+ to_y = arc[0].y;
+ mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8;
+ mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8;
+
+ if ( render_line( RAS_VAR_ mid_x, mid_y ) ||
+ render_line( RAS_VAR_ to_x, to_y ) )
+ return 1;
+ top --;
+ arc -= 3;
+ }
+ }
+ return 0;
+ }
+
+
+ /* a macro comparing two cell pointers. Returns true if a <= b. */
+#if 1
+
+#define PACK( a ) ( ( (long)(a)->y << 16 ) + (a)->x )
+#define LESS_THAN( a, b ) ( PACK( a ) < PACK( b ) )
+
+#else /* 1 */
+
+#define LESS_THAN( a, b ) ( (a)->y < (b)->y || \
+ ( (a)->y == (b)->y && (a)->x < (b)->x ) )
+
+#endif /* 1 */
+
+#define SWAP_CELLS( a, b, temp ) do \
+ { \
+ temp = *(a); \
+ *(a) = *(b); \
+ *(b) = temp; \
+ } while ( 0 )
+#define DEBUG_SORT
+#define QUICK_SORT
+
+#ifdef SHELL_SORT
+
+ /* a simple shell sort algorithm that works directly on our */
+ /* cells table */
+ static
+ void shell_sort ( PCell cells,
+ int count )
+ {
+ PCell i, j, limit = cells + count;
+ TCell temp;
+ int gap;
+
+
+ /* compute initial gap */
+ for ( gap = 0; ++gap < count; gap *= 3 )
+ ;
+
+ while ( gap /= 3 )
+ {
+ for ( i = cells + gap; i < limit; i++ )
+ {
+ for ( j = i - gap; ; j -= gap )
+ {
+ PCell k = j + gap;
+
+
+ if ( LESS_THAN( j, k ) )
+ break;
+
+ SWAP_CELLS( j, k, temp );
+
+ if ( j < cells + gap )
+ break;
+ }
+ }
+ }
+ }
+
+#endif /* SHELL_SORT */
+
+
+#ifdef QUICK_SORT
+
+ /* This is a non-recursive quicksort that directly process our cells */
+ /* array. It should be faster than calling the stdlib qsort(), and we */
+ /* can even tailor our insertion threshold... */
+
+#define QSORT_THRESHOLD 9 /* below this size, a sub-array will be sorted */
+ /* through a normal insertion sort */
+
+ static
+ void quick_sort( PCell cells,
+ int count )
+ {
+ PCell stack[40]; /* should be enough ;-) */
+ PCell* top; /* top of stack */
+ PCell base, limit;
+ TCell temp;
+
+
+ limit = cells + count;
+ base = cells;
+ top = stack;
+
+ for (;;)
+ {
+ int len = limit - base;
+ PCell i, j, pivot;
+
+
+ if ( len > QSORT_THRESHOLD )
+ {
+ /* we use base + len/2 as the pivot */
+ pivot = base + len / 2;
+ SWAP_CELLS( base, pivot, temp );
+
+ i = base + 1;
+ j = limit - 1;
+
+ /* now ensure that *i <= *base <= *j */
+ if ( LESS_THAN( j, i ) )
+ SWAP_CELLS( i, j, temp );
+
+ if ( LESS_THAN( base, i ) )
+ SWAP_CELLS( base, i, temp );
+
+ if ( LESS_THAN( j, base ) )
+ SWAP_CELLS( base, j, temp );
+
+ for (;;)
+ {
+ do i++; while ( LESS_THAN( i, base ) );
+ do j--; while ( LESS_THAN( base, j ) );
+
+ if ( i > j )
+ break;
+
+ SWAP_CELLS( i, j, temp );
+ }
+
+ SWAP_CELLS( base, j, temp );
+
+ /* now, push the largest sub-array */
+ if ( j - base > limit - i )
+ {
+ top[0] = base;
+ top[1] = j;
+ base = i;
+ }
+ else
+ {
+ top[0] = i;
+ top[1] = limit;
+ limit = j;
+ }
+ top += 2;
+ }
+ else
+ {
+ /* the sub-array is small, perform insertion sort */
+ j = base;
+ i = j + 1;
+
+ for ( ; i < limit; j = i, i++ )
+ {
+ for ( ; LESS_THAN( j + 1, j ); j-- )
+ {
+ SWAP_CELLS( j + 1, j, temp );
+ if ( j == base )
+ break;
+ }
+ }
+ if ( top > stack )
+ {
+ top -= 2;
+ base = top[0];
+ limit = top[1];
+ }
+ else
+ break;
+ }
+ }
+ }
+
+#endif /* QUICK_SORT */
+
+
+#ifdef DEBUG_GRAYS
+#ifdef DEBUG_SORT
+
+ static
+ int check_sort( PCell cells,
+ int count )
+ {
+ PCell p, q;
+
+
+ for ( p = cells + count - 2; p >= cells; p-- )
+ {
+ q = p + 1;
+ if ( !LESS_THAN( p, q ) )
+ return 0;
+ }
+ return 1;
+ }
+
+#endif /* DEBUG_SORT */
+#endif /* DEBUG_GRAYS */
+
+
+ static
+ int Move_To( FT_Vector* to,
+ FT_Raster raster )
+ {
+ TPos x, y;
+
+
+ /* record current cell, if any */
+ record_cell( (PRaster)raster );
+
+ /* start to a new position */
+ x = UPSCALE( to->x );
+ y = UPSCALE( to->y );
+ start_cell( (PRaster)raster, TRUNC( x ), TRUNC( y ) );
+ ((PRaster)raster)->x = x;
+ ((PRaster)raster)->y = y;
+ return 0;
+ }
+
+
+ static
+ int Line_To( FT_Vector* to,
+ FT_Raster raster )
+ {
+ return render_line( (PRaster)raster,
+ UPSCALE( to->x ), UPSCALE( to->y ) );
+ }
+
+
+ static
+ int Conic_To( FT_Vector* control,
+ FT_Vector* to,
+ FT_Raster raster )
+ {
+ return render_conic( (PRaster)raster, control, to );
+ }
+
+
+ static
+ int Cubic_To( FT_Vector* control1,
+ FT_Vector* control2,
+ FT_Vector* to,
+ FT_Raster raster )
+ {
+ return render_cubic( (PRaster)raster, control1, control2, to );
+ }
+
+
+ static
+ void grays_render_span( int y,
+ int count,
+ FT_Span* spans,
+ PRaster raster )
+ {
+ unsigned char* p;
+ FT_Bitmap* map = &raster->target;
+
+
+ /* first of all, compute the scanline offset */
+ p = (unsigned char*)map->buffer - y * map->pitch;
+ if ( map->pitch >= 0 )
+ p += ( map->rows - 1 ) * map->pitch;
+
+ for ( ; count > 0; count--, spans++ )
+ {
+ if ( spans->coverage )
+#if 1
+ memset( p + spans->x, (unsigned char)spans->coverage, spans->len );
+#else /* 1 */
+ {
+ q = p + spans->x;
+ limit = q + spans->len;
+ for ( ; q < limit; q++ )
+ q[0] = (unsigned char)spans->coverage;
+ }
+#endif /* 1 */
+ }
+ }
+
+
+#ifdef DEBUG_GRAYS
+
+#include <stdio.h>
+
+ static
+ void dump_cells( RAS_ARG )
+ {
+ PCell cell, limit;
+ int y = -1;
+
+
+ cell = ras.cells;
+ limit = cell + ras.num_cells;
+
+ for ( ; cell < limit; cell++ )
+ {
+ if ( cell->y != y )
+ {
+ fprintf( stderr, "\n%2d: ", cell->y );
+ y = cell->y;
+ }
+ fprintf( stderr, "[%d %d %d]",
+ cell->x, cell->area, cell->cover );
+ }
+ fprintf(stderr, "\n" );
+ }
+
+#endif /* DEBUG_GRAYS */
+
+
+ static
+ void grays_hline( RAS_ARG_ TScan x,
+ TScan y,
+ TPos area,
+ int acount )
+ {
+ FT_Span* span;
+ int count;
+ int coverage;
+
+
+ /* compute the coverage line's coverage, depending on the */
+ /* outline fill rule */
+ /* */
+ /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */
+ /* */
+ coverage = area >> ( PIXEL_BITS * 2 + 1 - 8); /* use range 0..256 */
+
+ if ( ras.outline.flags & ft_outline_even_odd_fill )
+ {
+ if ( coverage < 0 )
+ coverage = -coverage;
+
+ while ( coverage >= 512 )
+ coverage -= 512;
+
+ if ( coverage > 256 )
+ coverage = 512 - coverage;
+ else if ( coverage == 256 )
+ coverage = 255;
+ }
+ else
+ {
+ /* normal non-zero winding rule */
+ if ( coverage < 0 )
+ coverage = -coverage;
+
+ if ( coverage >= 256 )
+ coverage = 255;
+ }
+
+ y += ras.min_ey;
+ x += ras.min_ex;
+
+ if ( coverage )
+ {
+ /* see if we can add this span to the current list */
+ count = ras.num_gray_spans;
+ span = ras.gray_spans + count - 1;
+ if ( count > 0 &&
+ ras.span_y == y &&
+ (int)span->x + span->len == (int)x &&
+ span->coverage == coverage )
+ {
+ span->len += acount;
+ return;
+ }
+
+ if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS )
+ {
+ if ( ras.render_span )
+ ras.render_span( ras.span_y, count, ras.gray_spans,
+ ras.render_span_data );
+ /* ras.render_span( span->y, ras.gray_spans, count ); */
+
+#ifdef DEBUG_GRAYS
+
+ if ( ras.span_y >= 0 )
+ {
+ int n;
+
+
+ fprintf( stderr, "y=%3d ", ras.span_y );
+ span = ras.gray_spans;
+ for ( n = 0; n < count; n++, span++ )
+ fprintf( stderr, "[%d..%d]:%02x ",
+ span->x, span->x + span->len - 1, span->coverage );
+ fprintf( stderr, "\n" );
+ }
+
+#endif /* DEBUG_GRAYS */
+
+ ras.num_gray_spans = 0;
+ ras.span_y = y;
+
+ count = 0;
+ span = ras.gray_spans;
+ }
+ else
+ span++;
+
+ /* add a gray span to the current list */
+ span->x = (short)x;
+ span->len = (unsigned short)acount;
+ span->coverage = (unsigned char)coverage;
+ ras.num_gray_spans++;
+ }
+ }
+
+
+ static
+ void grays_sweep( RAS_ARG_ FT_Bitmap* target )
+ {
+ TScan x, y, cover, area;
+ PCell start, cur, limit;
+
+ FT_UNUSED( target );
+
+
+ cur = ras.cells;
+ limit = cur + ras.num_cells;
+
+ cover = 0;
+ ras.span_y = -1;
+ ras.num_gray_spans = 0;
+
+ for (;;)
+ {
+ start = cur;
+ y = start->y;
+ x = start->x;
+
+ area = start->area;
+ cover += start->cover;
+
+ /* accumulate all start cells */
+ for (;;)
+ {
+ ++cur;
+ if ( cur >= limit || cur->y != start->y || cur->x != start->x )
+ break;
+
+ area += cur->area;
+ cover += cur->cover;
+ }
+
+ /* if the start cell has a non-null area, we must draw an */
+ /* individual gray pixel there */
+ if ( area && x >= 0 )
+ {
+ grays_hline( RAS_VAR_ x, y, cover * ( ONE_PIXEL * 2 ) - area, 1 );
+ x++;
+ }
+
+ if ( x < 0 )
+ x = 0;
+
+ if ( cur < limit && start->y == cur->y )
+ {
+ /* draw a gray span between the start cell and the current one */
+ if ( cur->x > x )
+ grays_hline( RAS_VAR_ x, y,
+ cover * ( ONE_PIXEL * 2 ), cur->x - x );
+ }
+ else
+ {
+ /* draw a gray span until the end of the clipping region */
+ if ( cover && x < ras.max_ex - ras.min_ex )
+ grays_hline( RAS_VAR_ x, y,
+ cover * ( ONE_PIXEL * 2 ),
+ ras.max_ex - x - ras.min_ex );
+ cover = 0;
+ }
+
+ if ( cur >= limit )
+ break;
+ }
+
+ if ( ras.render_span && ras.num_gray_spans > 0 )
+ ras.render_span( ras.span_y, ras.num_gray_spans,
+ ras.gray_spans, ras.render_span_data );
+
+#ifdef DEBUG_GRAYS
+
+ {
+ int n;
+ FT_Span* span;
+
+
+ fprintf( stderr, "y=%3d ", ras.span_y );
+ span = ras.gray_spans;
+ for ( n = 0; n < ras.num_gray_spans; n++, span++ )
+ fprintf( stderr, "[%d..%d]:%02x ",
+ span->x, span->x + span->len - 1, span->coverage );
+ fprintf( stderr, "\n" );
+ }
+
+#endif /* DEBUG_GRAYS */
+
+ }
+
+
+#ifdef _STANDALONE_
+
+ /*************************************************************************/
+ /* */
+ /* The following function should only compile in stand_alone mode, */
+ /* i.e., when building this component without the rest of FreeType. */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Decompose */
+ /* */
+ /* <Description> */
+ /* Walks over an outline's structure to decompose it into individual */
+ /* segments and Bezier arcs. This function is also able to emit */
+ /* `move to' and `close to' operations to indicate the start and end */
+ /* of new contours in the outline. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the source target. */
+ /* */
+ /* interface :: A table of `emitters', i.e,. function pointers called */
+ /* during decomposition to indicate path operations. */
+ /* */
+ /* user :: A typeless pointer which is passed to each emitter */
+ /* during the decomposition. It can be used to store */
+ /* the state during the decomposition. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means sucess. */
+ /* */
+ static
+ int FT_Outline_Decompose( FT_Outline* outline,
+ FT_Outline_Funcs* interface,
+ void* user )
+ {
+#undef SCALED
+#define SCALED( x ) ( ( (x) << shift ) - delta )
+
+ FT_Vector v_last;
+ FT_Vector v_control;
+ FT_Vector v_start;
+
+ FT_Vector* point;
+ FT_Vector* limit;
+ char* tags;
+
+ int n; /* index of contour in outline */
+ int first; /* index of first point in contour */
+ int error;
+ char tag; /* current point's state */
+
+ int shift = interface->shift;
+ FT_Pos delta = interface->delta;
+
+
+ first = 0;
+
+ for ( n = 0; n < outline->n_contours; n++ )
+ {
+ int last; /* index of last point in contour */
+
+
+ last = outline->contours[n];
+ limit = outline->points + last;
+
+ v_start = outline->points[first];
+ v_last = outline->points[last];
+
+ v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
+ v_last.x = SCALED( v_last.x ); v_last.y = SCALED( v_last.y );
+
+ v_control = v_start;
+
+ point = outline->points + first;
+ tags = outline->tags + first;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ /* A contour cannot start with a cubic control point! */
+ if ( tag == FT_Curve_Tag_Cubic )
+ goto Invalid_Outline;
+
+ /* check first point to determine origin */
+ if ( tag == FT_Curve_Tag_Conic )
+ {
+ /* first point is conic control. Yes, this happens. */
+ if ( FT_CURVE_TAG( outline->tags[last] ) == FT_Curve_Tag_On )
+ {
+ /* start at last point if it is on the curve */
+ v_start = v_last;
+ limit--;
+ }
+ else
+ {
+ /* if both first and last points are conic, */
+ /* start at their middle and record its position */
+ /* for closure */
+ v_start.x = ( v_start.x + v_last.x ) / 2;
+ v_start.y = ( v_start.y + v_last.y ) / 2;
+
+ v_last = v_start;
+ }
+ point--;
+ tags--;
+ }
+
+ error = interface->move_to( &v_start, user );
+ if ( error )
+ goto Exit;
+
+ while ( point < limit )
+ {
+ point++;
+ tags++;
+
+ tag = FT_CURVE_TAG( tags[0] );
+ switch ( tag )
+ {
+ case FT_Curve_Tag_On: /* emit a single line_to */
+ {
+ FT_Vector vec;
+
+
+ vec.x = SCALED( point->x );
+ vec.y = SCALED( point->y );
+
+ error = interface->line_to( &vec, user );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ case FT_Curve_Tag_Conic: /* consume conic arcs */
+ {
+ v_control.x = SCALED( point->x );
+ v_control.y = SCALED( point->y );
+
+ Do_Conic:
+ if ( point < limit )
+ {
+ FT_Vector vec;
+ FT_Vector v_middle;
+
+
+ point++;
+ tags++;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ vec.x = SCALED( point->x );
+ vec.y = SCALED( point->y );
+
+ if ( tag == FT_Curve_Tag_On )
+ {
+ error = interface->conic_to( &v_control, &vec, user );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ if ( tag != FT_Curve_Tag_Conic )
+ goto Invalid_Outline;
+
+ v_middle.x = ( v_control.x + vec.x ) / 2;
+ v_middle.y = ( v_control.y + vec.y ) / 2;
+
+ error = interface->conic_to( &v_control, &v_middle, user );
+ if ( error )
+ goto Exit;
+
+ v_control = vec;
+ goto Do_Conic;
+ }
+
+ error = interface->conic_to( &v_control, &v_start, user );
+ goto Close;
+ }
+
+ default: /* FT_Curve_Tag_Cubic */
+ {
+ FT_Vector vec1, vec2;
+
+
+ if ( point + 1 > limit ||
+ FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
+ goto Invalid_Outline;
+
+ point += 2;
+ tags += 2;
+
+ vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
+ vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
+
+ if ( point <= limit )
+ {
+ FT_Vector vec;
+
+
+ vec.x = SCALED( point->x );
+ vec.y = SCALED( point->y );
+
+ error = interface->cubic_to( &vec1, &vec2, &vec, user );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ error = interface->cubic_to( &vec1, &vec2, &v_start, user );
+ goto Close;
+ }
+ }
+ }
+
+ /* close the contour with a line segment */
+ error = interface->line_to( &v_start, user );
+
+ Close:
+ if ( error )
+ goto Exit;
+
+ first = last + 1;
+ }
+
+ return 0;
+
+ Exit:
+ return error;
+
+ Invalid_Outline:
+ return ErrRaster_Invalid_Outline;
+ }
+
+#endif /* _STANDALONE_ */
+
+
+ typedef struct TBand_
+ {
+ FT_Pos min, max;
+
+ } TBand;
+
+
+ static
+ int grays_convert_glyph( RAS_ARG_ FT_Outline* outline )
+ {
+ static
+ FT_Outline_Funcs interface =
+ {
+ (FT_Outline_MoveTo_Func) Move_To,
+ (FT_Outline_LineTo_Func) Line_To,
+ (FT_Outline_ConicTo_Func)Conic_To,
+ (FT_Outline_CubicTo_Func)Cubic_To,
+ 0,
+ 0
+ };
+
+ TBand bands[40], *band;
+ int n, num_bands;
+ TPos min, max, max_y;
+
+
+ /* Set up state in the raster object */
+ compute_cbox( RAS_VAR_ outline );
+
+ /* clip to target bitmap, exit if nothing to do */
+ if ( ras.max_ex <= 0 || ras.min_ex >= ras.target.width ||
+ ras.max_ey <= 0 || ras.min_ey >= ras.target.rows )
+ return 0;
+
+ if ( ras.min_ex < 0 ) ras.min_ex = 0;
+ if ( ras.min_ey < 0 ) ras.min_ey = 0;
+
+ if ( ras.max_ex > ras.target.width ) ras.max_ex = ras.target.width;
+ if ( ras.max_ey > ras.target.rows ) ras.max_ey = ras.target.rows;
+
+ /* simple heuristic used to speed-up the bezier decomposition -- see */
+ /* the code in render_conic() and render_cubic() for more details */
+ ras.conic_level = 32;
+ ras.cubic_level = 16;
+
+ {
+ int level = 0;
+
+
+ if ( ras.max_ex > 24 || ras.max_ey > 24 )
+ level++;
+ if ( ras.max_ex > 120 || ras.max_ey > 120 )
+ level += 2;
+
+ ras.conic_level <<= level;
+ ras.cubic_level <<= level;
+ }
+
+ /* setup vertical bands */
+ num_bands = ( ras.max_ey - ras.min_ey ) / ras.band_size;
+ if ( num_bands == 0 ) num_bands = 1;
+ if ( num_bands >= 39 ) num_bands = 39;
+
+ ras.band_shoot = 0;
+
+ min = ras.min_ey;
+ max_y = ras.max_ey;
+
+ for ( n = 0; n < num_bands; n++, min = max )
+ {
+ max = min + ras.band_size;
+ if ( n == num_bands - 1 || max > max_y )
+ max = max_y;
+
+ bands[0].min = min;
+ bands[0].max = max;
+ band = bands;
+
+ while ( band >= bands )
+ {
+ FT_Pos bottom, top, middle;
+ int error;
+
+
+ ras.num_cells = 0;
+ ras.invalid = 1;
+ ras.min_ey = band->min;
+ ras.max_ey = band->max;
+
+ error = FT_Outline_Decompose( outline, &interface, &ras ) ||
+ record_cell( RAS_VAR );
+
+ if ( !error )
+ {
+#ifdef SHELL_SORT
+ shell_sort( ras.cells, ras.num_cells );
+#else
+ quick_sort( ras.cells, ras.num_cells );
+#endif
+
+#ifdef DEBUG_GRAYS
+ check_sort( ras.cells, ras.num_cells );
+ dump_cells( RAS_VAR );
+#endif
+
+ grays_sweep( RAS_VAR_ &ras.target );
+ band--;
+ continue;
+ }
+
+ /* render pool overflow, we will reduce the render band by half */
+ bottom = band->min;
+ top = band->max;
+ middle = bottom + ( ( top - bottom ) >> 1 );
+
+ /* waoow! This is too complex for a single scanline, something */
+ /* must be really rotten here! */
+ if ( middle == bottom )
+ {
+#ifdef DEBUG_GRAYS
+ fprintf( stderr, "Rotten glyph!\n" );
+#endif
+ return 1;
+ }
+
+ if ( bottom-top >= ras.band_size )
+ ras.band_shoot++;
+
+ band[1].min = bottom;
+ band[1].max = middle;
+ band[0].min = middle;
+ band[0].max = top;
+ band++;
+ }
+ }
+
+ if ( ras.band_shoot > 8 && ras.band_size > 16 )
+ ras.band_size = ras.band_size / 2;
+
+ return 0;
+ }
+
+
+ extern
+ int grays_raster_render( PRaster raster,
+ FT_Raster_Params* params )
+ {
+ FT_Outline* outline = (FT_Outline*)params->source;
+ FT_Bitmap* target_map = params->target;
+
+
+ if ( !raster || !raster->cells || !raster->max_cells )
+ return -1;
+
+ /* return immediately if the outline is empty */
+ if ( outline->n_points == 0 || outline->n_contours <= 0 )
+ return 0;
+
+ if ( !outline || !outline->contours || !outline->points )
+ return ErrRaster_Invalid_Outline;
+
+ if ( outline->n_points !=
+ outline->contours[outline->n_contours - 1] + 1 )
+ return ErrRaster_Invalid_Outline;
+
+ if ( !target_map || !target_map->buffer )
+ return -1;
+
+ /* XXX: this version does not support monochrome rendering yet! */
+ if ( !(params->flags & ft_raster_flag_aa) )
+ return ErrRaster_Invalid_Mode;
+
+ ras.outline = *outline;
+ ras.target = *target_map;
+ ras.num_cells = 0;
+ ras.invalid = 1;
+
+ ras.render_span = (FT_Raster_Span_Func)grays_render_span;
+ ras.render_span_data = &ras;
+
+ if ( params->flags & ft_raster_flag_direct )
+ {
+ ras.render_span = (FT_Raster_Span_Func)params->gray_spans;
+ ras.render_span_data = params->user;
+ }
+
+ return grays_convert_glyph( (PRaster)raster, outline );
+ }
+
+
+ /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
+ /**** a static object. *****/
+
+#ifdef _STANDALONE_
+
+ static
+ int grays_raster_new( void* memory,
+ FT_Raster* araster )
+ {
+ static TRaster the_raster;
+
+ FT_UNUSED( memory );
+
+
+ *araster = (FT_Raster)&the_raster;
+ memset( &the_raster, 0, sizeof ( the_raster ) );
+
+ return 0;
+ }
+
+
+ static
+ void grays_raster_done( FT_Raster raster )
+ {
+ /* nothing */
+ FT_UNUSED( raster );
+ }
+
+#else /* _STANDALONE_ */
+
+ static
+ int grays_raster_new( FT_Memory memory,
+ FT_Raster* araster )
+ {
+ FT_Error error;
+ PRaster raster;
+
+
+ *araster = 0;
+ if ( !ALLOC( raster, sizeof ( TRaster ) ) )
+ {
+ raster->memory = memory;
+ *araster = (FT_Raster)raster;
+ }
+
+ return error;
+ }
+
+
+ static
+ void grays_raster_done( FT_Raster raster )
+ {
+ FT_Memory memory = (FT_Memory)((PRaster)raster)->memory;
+
+
+ FREE( raster );
+ }
+
+#endif /* _STANDALONE_ */
+
+
+ static
+ void grays_raster_reset( FT_Raster raster,
+ const char* pool_base,
+ long pool_size )
+ {
+ PRaster rast = (PRaster)raster;
+
+
+ if ( raster && pool_base && pool_size >= 4096 )
+ init_cells( rast, (char*)pool_base, pool_size );
+
+ rast->band_size = ( pool_size / sizeof ( TCell ) ) / 8;
+ }
+
+
+ FT_Raster_Funcs ft_grays_raster =
+ {
+ ft_glyph_format_outline,
+
+ (FT_Raster_New_Func) grays_raster_new,
+ (FT_Raster_Reset_Func) grays_raster_reset,
+ (FT_Raster_Set_Mode_Func)0,
+ (FT_Raster_Render_Func) grays_raster_render,
+ (FT_Raster_Done_Func) grays_raster_done
+ };
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftgrays.h */
+/* */
+/* FreeType smooth renderer declaration */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#ifndef FTGRAYS_H
+#define FTGRAYS_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#ifdef _STANDALONE_
+#include "ftimage.h"
+#else
+#include <freetype/ftimage.h>
+#endif
+
+ /*************************************************************************/
+ /* */
+ /* To make ftgrays.h independent from configuration files we check */
+ /* whether FT_EXPORT_DEF has been defined already. */
+ /* */
+ /* On some systems and compilers (Win32 mostly), an extra keyword is */
+ /* necessary to compile the library as a DLL. */
+ /* */
+#ifndef FT_EXPORT_VAR
+#define FT_EXPORT_VAR( x ) extern x
+#endif
+
+ FT_EXPORT_VAR( FT_Raster_Funcs ) ft_grays_raster;
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* FTGRAYS_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftsmooth.c */
+/* */
+/* Anti-aliasing renderer interface (body). */
+/* */
+/* Copyright 2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/ftoutln.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ftsmooth.h"
+#include "ftgrays.h"
+
+#else
+
+#include <smooth/ftsmooth.h>
+#include <smooth/ftgrays.h>
+
+#endif
+
+
+ /* initialize renderer -- init its raster */
+ static
+ FT_Error ft_smooth_init( FT_Renderer render )
+ {
+ FT_Library library = FT_MODULE_LIBRARY( render );
+
+
+ render->clazz->raster_class->raster_reset( render->raster,
+ library->raster_pool,
+ library->raster_pool_size );
+
+ return 0;
+ }
+
+
+ /* sets render-specific mode */
+ static
+ FT_Error ft_smooth_set_mode( FT_Renderer render,
+ FT_ULong mode_tag,
+ FT_Pointer data )
+ {
+ /* we simply pass it to the raster */
+ return render->clazz->raster_class->raster_set_mode( render->raster,
+ mode_tag,
+ data );
+ }
+
+ /* transform a given glyph image */
+ static
+ FT_Error ft_smooth_transform( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_Matrix* matrix,
+ FT_Vector* delta )
+ {
+ FT_Error error = FT_Err_Ok;
+
+
+ if ( slot->format != render->glyph_format )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ if ( matrix )
+ FT_Outline_Transform( &slot->outline, matrix );
+
+ if ( delta )
+ FT_Outline_Translate( &slot->outline, delta->x, delta->y );
+
+ Exit:
+ return error;
+ }
+
+
+ /* return the glyph's control box */
+ static
+ void ft_smooth_get_cbox( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_BBox* cbox )
+ {
+ MEM_Set( cbox, 0, sizeof ( *cbox ) );
+
+ if ( slot->format == render->glyph_format )
+ FT_Outline_Get_CBox( &slot->outline, cbox );
+ }
+
+
+ /* convert a slot's glyph image into a bitmap */
+ static
+ FT_Error ft_smooth_render( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_UInt mode,
+ FT_Vector* origin )
+ {
+ FT_Error error;
+ FT_Outline* outline;
+ FT_BBox cbox;
+ FT_UInt width, height, pitch;
+ FT_Bitmap* bitmap;
+ FT_Memory memory;
+
+ FT_Raster_Params params;
+
+
+ /* check glyph image format */
+ if ( slot->format != render->glyph_format )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* check mode */
+ if ( mode != ft_render_mode_normal )
+ return FT_Err_Cannot_Render_Glyph;
+
+ outline = &slot->outline;
+
+ /* translate the outline to the new origin if needed */
+ if ( origin )
+ FT_Outline_Translate( outline, origin->x, origin->y );
+
+ /* compute the control box, and grid fit it */
+ FT_Outline_Get_CBox( outline, &cbox );
+
+ cbox.xMin &= -64;
+ cbox.yMin &= -64;
+ cbox.xMax = ( cbox.xMax + 63 ) & -64;
+ cbox.yMax = ( cbox.yMax + 63 ) & -64;
+
+ width = ( cbox.xMax - cbox.xMin ) >> 6;
+ height = ( cbox.yMax - cbox.yMin ) >> 6;
+ bitmap = &slot->bitmap;
+ memory = render->root.memory;
+
+ /* release old bitmap buffer */
+ if ( slot->flags & ft_glyph_own_bitmap )
+ {
+ FREE( bitmap->buffer );
+ slot->flags &= ~ft_glyph_own_bitmap;
+ }
+
+ /* allocate new one, depends on pixel format */
+ pitch = width;
+ bitmap->pixel_mode = ft_pixel_mode_grays;
+ bitmap->num_grays = 256;
+ bitmap->width = width;
+ bitmap->rows = height;
+ bitmap->pitch = pitch;
+
+ if ( ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
+ goto Exit;
+
+ slot->flags |= ft_glyph_own_bitmap;
+
+ /* translate outline to render it into the bitmap */
+ FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin );
+
+ /* set up parameters */
+ params.target = bitmap;
+ params.source = outline;
+ params.flags = ft_raster_flag_aa;
+
+ /* render outline into the bitmap */
+ error = render->raster_render( render->raster, ¶ms );
+ if ( error )
+ goto Exit;
+
+ slot->format = ft_glyph_format_bitmap;
+ slot->bitmap_left = cbox.xMin >> 6;
+ slot->bitmap_top = cbox.yMax >> 6;
+
+ Exit:
+ return error;
+ }
+
+
+ const FT_Renderer_Class ft_smooth_renderer_class =
+ {
+ {
+ ft_module_renderer,
+ sizeof( FT_RendererRec ),
+
+ "smooth",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* module specific interface */
+
+ (FT_Module_Constructor)ft_smooth_init,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+ },
+
+ ft_glyph_format_outline,
+
+ (FTRenderer_render) ft_smooth_render,
+ (FTRenderer_transform)ft_smooth_transform,
+ (FTRenderer_getCBox) ft_smooth_get_cbox,
+ (FTRenderer_setMode) ft_smooth_set_mode,
+
+ (FT_Raster_Funcs*) &ft_grays_raster
+ };
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftsmooth.h */
+/* */
+/* Anti-aliasing renderer interface (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTSMOOTH_H
+#define FTSMOOTH_H
+
+#include <freetype/ftrender.h>
+
+#ifndef FT_CONFIG_OPTION_NO_STD_RASTER
+ FT_EXPORT_VAR( const FT_Renderer_Class ) ft_std_renderer_class;
+#endif
+
+#ifndef FT_CONFIG_OPTION_NO_SMOOTH_RASTER
+ FT_EXPORT_VAR( const FT_Renderer_Class ) ft_smooth_renderer_class;
+#endif
+
+#endif /* FTSMOOTH_H */
+
+
+/* END */
--- /dev/null
+make_module_list: add_smooth_renderer
+
+add_smooth_renderer:
+ $(OPEN_DRIVER)ft_smooth_renderer_class$(CLOSE_DRIVER)
+ $(ECHO_DRIVER)smooth $(ECHO_DRIVER_DESC)anti-aliased bitmap renderer$(ECHO_DRIVER_DONE)
+
+# EOF
--- /dev/null
+#
+# FreeType 2 renderer module build rules
+#
+
+
+# Copyright 1996-2000 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# smooth driver directory
+#
+SMOOTH_DIR := $(SRC_)smooth
+SMOOTH_DIR_ := $(SMOOTH_DIR)$(SEP)
+
+# compilation flags for the driver
+#
+SMOOTH_COMPILE := $(FT_COMPILE)
+
+
+# smooth driver sources (i.e., C files)
+#
+SMOOTH_DRV_SRC := $(SMOOTH_DIR_)ftgrays.c \
+ $(SMOOTH_DIR_)ftsmooth.c
+
+
+# smooth driver headers
+#
+SMOOTH_DRV_H := $(SMOOTH_DRV_SRC:%c=%h)
+
+
+# smooth driver object(s)
+#
+# SMOOTH_DRV_OBJ_M is used during `multi' builds.
+# SMOOTH_DRV_OBJ_S is used during `single' builds.
+#
+SMOOTH_DRV_OBJ_M := $(SMOOTH_DRV_SRC:$(SMOOTH_DIR_)%.c=$(OBJ_)%.$O)
+SMOOTH_DRV_OBJ_S := $(OBJ_)smooth.$O
+
+# smooth driver source file for single build
+#
+SMOOTH_DRV_SRC_S := $(SMOOTH_DIR_)smooth.c
+
+
+# smooth driver - single object
+#
+$(SMOOTH_DRV_OBJ_S): $(SMOOTH_DRV_SRC_S) $(SMOOTH_DRV_SRC) \
+ $(FREETYPE_H) $(SMOOTH_DRV_H)
+ $(SMOOTH_COMPILE) $T$@ $(SMOOTH_DRV_SRC_S)
+
+
+# smooth driver - multiple objects
+#
+$(OBJ_)%.$O: $(SMOOTH_DIR_)%.c $(FREETYPE_H) $(SMOOTH_DRV_H)
+ $(SMOOTH_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(SMOOTH_DRV_OBJ_S)
+DRV_OBJS_M += $(SMOOTH_DRV_OBJ_M)
+
+
+# EOF
--- /dev/null
+/***************************************************************************/
+/* */
+/* smooth.c */
+/* */
+/* FreeType anti-aliasing rasterer module component (body only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ftgrays.c"
+#include "ftsmooth.c"
+
+#else
+
+#include <smooth/ftgrays.c>
+#include <smooth/ftsmooth.c>
+
+#endif
+
+
+/* END */
--- /dev/null
+make_module_list: add_truetype_driver
+
+add_truetype_driver:
+ $(OPEN_DRIVER)tt_driver_class$(CLOSE_DRIVER)
+ $(ECHO_DRIVER)truetype $(ECHO_DRIVER_DESC)Windows/Mac font files with extension *.ttf or *.ttc$(ECHO_DRIVER_DONE)
+
+# EOF
--- /dev/null
+#
+# FreeType 2 TrueType driver configuration rules
+#
+
+
+# Copyright 1996-2000 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# TrueType driver directory
+#
+TT_DIR := $(SRC_)truetype
+TT_DIR_ := $(TT_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+TT_COMPILE := $(FT_COMPILE)
+
+
+# TrueType driver sources (i.e., C files)
+#
+TT_DRV_SRC := $(TT_DIR_)ttobjs.c \
+ $(TT_DIR_)ttpload.c \
+ $(TT_DIR_)ttgload.c \
+ $(TT_DIR_)ttinterp.c \
+ $(TT_DIR_)ttdriver.c
+
+# TrueType driver headers
+#
+TT_DRV_H := $(TT_DRV_SRC:%.c=%.h)
+
+
+# TrueType driver object(s)
+#
+# TT_DRV_OBJ_M is used during `multi' builds
+# TT_DRV_OBJ_S is used during `single' builds
+#
+TT_DRV_OBJ_M := $(TT_DRV_SRC:$(TT_DIR_)%.c=$(OBJ_)%.$O)
+TT_DRV_OBJ_S := $(OBJ_)truetype.$O
+
+# TrueType driver source file for single build
+#
+TT_DRV_SRC_S := $(TT_DIR_)truetype.c
+
+
+# TrueType driver - single object
+#
+$(TT_DRV_OBJ_S): $(TT_DRV_SRC_S) $(TT_DRV_SRC) $(FREETYPE_H) $(TT_DRV_H)
+ $(TT_COMPILE) $T$@ $(TT_DRV_SRC_S)
+
+
+# driver - multiple objects
+#
+$(OBJ_)%.$O: $(TT_DIR_)%.c $(FREETYPE_H) $(TT_DRV_H)
+ $(TT_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(TT_DRV_OBJ_S)
+DRV_OBJS_M += $(TT_DRV_OBJ_M)
+
+# EOF
--- /dev/null
+/***************************************************************************/
+/* */
+/* truetype.c */
+/* */
+/* FreeType TrueType driver component (body only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttdriver.c" /* driver interface */
+#include "ttpload.c" /* tables loader */
+#include "ttgload.c" /* glyph loader */
+#include "ttobjs.c" /* object manager */
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#include "ttinterp.c" /* bytecode interpreter */
+#endif
+
+#else /* FT_FLAT_COMPILE */
+
+#include <truetype/ttdriver.c> /* driver interface */
+#include <truetype/ttpload.c> /* tables loader */
+#include <truetype/ttgload.c> /* glyph loader */
+#include <truetype/ttobjs.c> /* object manager */
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#include <truetype/ttinterp.c> /* bytecode interpreter */
+#endif
+
+#endif /* FT_FLAT_COMPILE */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttdriver.c */
+/* */
+/* TrueType font driver implementation (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/sfnt.h>
+#include <freetype/ttnameid.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttdriver.h"
+#include "ttgload.h"
+
+#else
+
+#include <truetype/ttdriver.h>
+#include <truetype/ttgload.h>
+
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttdriver
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** F A C E S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#undef PAIR_TAG
+#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \
+ (FT_ULong)right )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Kerning */
+ /* */
+ /* <Description> */
+ /* A driver method used to return the kerning vector between two */
+ /* glyphs of the same face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* left_glyph :: The index of the left glyph in the kern pair. */
+ /* */
+ /* right_glyph :: The index of the right glyph in the kern pair. */
+ /* */
+ /* <Output> */
+ /* kerning :: The kerning vector. This is in font units for */
+ /* scalable formats, and in pixels for fixed-sizes */
+ /* formats. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only horizontal layouts (left-to-right & right-to-left) are */
+ /* supported by this function. Other layouts, or more sophisticated */
+ /* kernings, are out of scope of this method (the basic driver */
+ /* interface is meant to be simple). */
+ /* */
+ /* They can be implemented by format-specific interfaces. */
+ /* */
+ static
+ FT_Error Get_Kerning( TT_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_Vector* kerning )
+ {
+ TT_Kern_0_Pair* pair;
+
+
+ if ( !face )
+ return TT_Err_Invalid_Face_Handle;
+
+ kerning->x = 0;
+ kerning->y = 0;
+
+ if ( face->kern_pairs )
+ {
+ /* there are some kerning pairs in this font file! */
+ FT_ULong search_tag = PAIR_TAG( left_glyph, right_glyph );
+ FT_Long left, right;
+
+
+ left = 0;
+ right = face->num_kern_pairs - 1;
+
+ while ( left <= right )
+ {
+ FT_Int middle = left + ( ( right - left ) >> 1 );
+ FT_ULong cur_pair;
+
+
+ pair = face->kern_pairs + middle;
+ cur_pair = PAIR_TAG( pair->left, pair->right );
+
+ if ( cur_pair == search_tag )
+ goto Found;
+
+ if ( cur_pair < search_tag )
+ left = middle + 1;
+ else
+ right = middle - 1;
+ }
+ }
+
+ Exit:
+ return TT_Err_Ok;
+
+ Found:
+ kerning->x = pair->value;
+ goto Exit;
+ }
+
+
+#undef PAIR_TAG
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** S I Z E S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Set_Char_Sizes */
+ /* */
+ /* <Description> */
+ /* A driver method used to reset a size's character sizes (horizontal */
+ /* and vertical) expressed in fractional points. */
+ /* */
+ /* <Input> */
+ /* char_width :: The character width expressed in 26.6 */
+ /* fractional points. */
+ /* */
+ /* char_height :: The character height expressed in 26.6 */
+ /* fractional points. */
+ /* */
+ /* horz_resolution :: The horizontal resolution of the output device. */
+ /* */
+ /* vert_resolution :: The vertical resolution of the output device. */
+ /* */
+ /* <InOut> */
+ /* size :: A handle to the target size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Set_Char_Sizes( TT_Size size,
+ FT_F26Dot6 char_width,
+ FT_F26Dot6 char_height,
+ FT_UInt horz_resolution,
+ FT_UInt vert_resolution )
+ {
+ FT_Size_Metrics* metrics = &size->root.metrics;
+ TT_Face face = (TT_Face)size->root.face;
+ FT_Long dim_x, dim_y;
+
+
+ /* This bit flag, when set, indicates that the pixel size must be */
+ /* truncated to an integer. Nearly all TrueType fonts have this */
+ /* bit set, as hinting won't work really well otherwise. */
+ /* */
+ /* However, for those rare fonts who do not set it, we override */
+ /* the default computations performed by the base layer. I */
+ /* really don't know whether this is useful, but hey, that's the */
+ /* spec :-) */
+ /* */
+ if ( ( face->header.Flags & 8 ) == 0 )
+ {
+ /* Compute pixel sizes in 26.6 units */
+ dim_x = ( char_width * horz_resolution ) / 72;
+ dim_y = ( char_height * vert_resolution ) / 72;
+
+ metrics->x_scale = FT_DivFix( dim_x, face->root.units_per_EM );
+ metrics->y_scale = FT_DivFix( dim_y, face->root.units_per_EM );
+
+ metrics->x_ppem = (FT_UShort)( dim_x >> 6 );
+ metrics->y_ppem = (FT_UShort)( dim_y >> 6 );
+ }
+
+ size->ttmetrics.valid = FALSE;
+
+ return TT_Reset_Size( size );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Set_Pixel_Sizes */
+ /* */
+ /* <Description> */
+ /* A driver method used to reset a size's character sizes (horizontal */
+ /* and vertical) expressed in integer pixels. */
+ /* */
+ /* <Input> */
+ /* pixel_width :: The character width expressed in integer pixels. */
+ /* */
+ /* pixel_height :: The character height expressed in integer pixels. */
+ /* */
+ /* <InOut> */
+ /* size :: A handle to the target size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Set_Pixel_Sizes( TT_Size size,
+ FT_UInt pixel_width,
+ FT_UInt pixel_height )
+ {
+ FT_UNUSED( pixel_width );
+ FT_UNUSED( pixel_height );
+
+ /* many things have been pre-computed by the base layer */
+
+ size->ttmetrics.valid = FALSE;
+
+ return TT_Reset_Size( size );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Load_Glyph */
+ /* */
+ /* <Description> */
+ /* A driver method used to load a glyph within a given glyph slot. */
+ /* */
+ /* <Input> */
+ /* slot :: A handle to the target slot object where the glyph */
+ /* will be loaded. */
+ /* */
+ /* size :: A handle to the source face size at which the glyph */
+ /* must be scaled, loaded, etc. */
+ /* */
+ /* glyph_index :: The index of the glyph in the font file. */
+ /* */
+ /* load_flags :: A flag indicating what to load for this glyph. The */
+ /* FTLOAD_??? constants can be used to control the */
+ /* glyph loading process (e.g., whether the outline */
+ /* should be scaled, whether to load bitmaps or not, */
+ /* whether to hint the outline, etc). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Load_Glyph( TT_GlyphSlot slot,
+ TT_Size size,
+ FT_UShort glyph_index,
+ FT_UInt load_flags )
+ {
+ FT_Error error;
+
+
+ if ( !slot )
+ return TT_Err_Invalid_Glyph_Handle;
+
+ /* check whether we want a scaled outline or bitmap */
+ if ( !size )
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+ if ( load_flags & FT_LOAD_NO_SCALE )
+ size = NULL;
+
+ /* reset the size object if necessary */
+ if ( size )
+ {
+ /* these two object must have the same parent */
+ if ( size->root.face != slot->face )
+ return TT_Err_Invalid_Face_Handle;
+
+ if ( !size->ttmetrics.valid )
+ {
+ if ( FT_SET_ERROR( TT_Reset_Size( size ) ) )
+ return error;
+ }
+ }
+
+ /* now load the glyph outline if necessary */
+ error = TT_Load_Glyph( size, slot, glyph_index, load_flags );
+
+ /* force drop-out mode to 2 - irrelevant now */
+ /* slot->outline.dropout_mode = 2; */
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** C H A R A C T E R M A P P I N G S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Char_Index */
+ /* */
+ /* <Description> */
+ /* Uses a charmap to return a given character code's glyph index. */
+ /* */
+ /* <Input> */
+ /* charmap :: A handle to the source charmap object. */
+ /* charcode :: The character code. */
+ /* */
+ /* <Return> */
+ /* Glyph index. 0 means `undefined character code'. */
+ /* */
+ static
+ FT_UInt Get_Char_Index( TT_CharMap charmap,
+ FT_Long charcode )
+ {
+ FT_Error error;
+ TT_Face face;
+ TT_CMapTable* cmap;
+
+
+ cmap = &charmap->cmap;
+ face = (TT_Face)charmap->root.face;
+
+ /* Load table if needed */
+ if ( !cmap->loaded )
+ {
+ SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt;
+
+
+ error = sfnt->load_charmap( face, cmap, face->root.stream );
+ if ( error )
+ return 0;
+
+ cmap->loaded = TRUE;
+ }
+
+ if ( cmap->get_index )
+ return cmap->get_index( cmap, charcode );
+ else
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** D R I V E R I N T E R F A C E ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static
+ FT_Module_Interface tt_get_interface( TT_Driver driver,
+ const char* interface )
+ {
+ FT_Module sfntd = FT_Get_Module( driver->root.root.library,
+ "sfnt" );
+ SFNT_Interface* sfnt;
+
+
+ /* only return the default interface from the SFNT module */
+ if ( sfntd )
+ {
+ sfnt = (SFNT_Interface*)( sfntd->clazz->module_interface );
+ if ( sfnt )
+ return sfnt->get_interface( FT_MODULE( driver ), interface );
+ }
+
+ return 0;
+ }
+
+
+ /* The FT_DriverInterface structure is defined in ftdriver.h. */
+
+ const FT_Driver_Class tt_driver_class =
+ {
+ {
+ ft_module_font_driver |
+ ft_module_driver_scalable |
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+ ft_module_driver_has_hinter,
+#else
+ 0,
+#endif
+
+ sizeof ( TT_DriverRec ),
+
+ "truetype", /* driver name */
+ 0x10000L, /* driver version == 1.0 */
+ 0x20000L, /* driver requires FreeType 2.0 or above */
+
+ (void*)0, /* driver specific interface */
+
+ (FT_Module_Constructor)TT_Init_Driver,
+ (FT_Module_Destructor) TT_Done_Driver,
+ (FT_Module_Requester) tt_get_interface,
+ },
+
+ sizeof ( TT_FaceRec ),
+ sizeof ( TT_SizeRec ),
+ sizeof ( FT_GlyphSlotRec ),
+
+
+ (FTDriver_initFace) TT_Init_Face,
+ (FTDriver_doneFace) TT_Done_Face,
+ (FTDriver_initSize) TT_Init_Size,
+ (FTDriver_doneSize) TT_Done_Size,
+ (FTDriver_initGlyphSlot)0,
+ (FTDriver_doneGlyphSlot)0,
+
+ (FTDriver_setCharSizes) Set_Char_Sizes,
+ (FTDriver_setPixelSizes)Set_Pixel_Sizes,
+ (FTDriver_loadGlyph) Load_Glyph,
+ (FTDriver_getCharIndex) Get_Char_Index,
+
+ (FTDriver_getKerning) Get_Kerning,
+ (FTDriver_attachFile) 0,
+ (FTDriver_getAdvances) 0
+ };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* getDriverInterface */
+ /* */
+ /* <Description> */
+ /* This function is used when compiling the TrueType driver as a */
+ /* shared library (`.DLL' or `.so'). It will be used by the */
+ /* high-level library of FreeType to retrieve the address of the */
+ /* driver's generic interface. */
+ /* */
+ /* It shouldn't be implemented in a static build, as each driver must */
+ /* have the same function as an exported entry point. */
+ /* */
+ /* <Return> */
+ /* The address of the TrueType's driver generic interface. The */
+ /* format-specific interface can then be retrieved through the method */
+ /* interface->get_format_interface. */
+ /* */
+ EXPORT_FUNC( const FT_Driver_Class* ) getDriverClass( void )
+ {
+ return &tt_driver_class;
+ }
+
+
+#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttdriver.h */
+/* */
+/* High-level TrueType driver interface (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef TTDRIVER_H
+#define TTDRIVER_H
+
+#include <freetype/internal/ftdriver.h>
+
+
+ FT_EXPORT_VAR( const FT_Driver_Class ) tt_driver_class;
+
+
+#endif /* TTDRIVER_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttgload.c */
+/* */
+/* TrueType Glyph Loader (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/sfnt.h>
+#include <freetype/tttags.h>
+#include <freetype/ftoutln.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttgload.h"
+
+#else
+
+#include <truetype/ttgload.h>
+
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttgload
+
+
+ /*************************************************************************/
+ /* */
+ /* Composite font flags. */
+ /* */
+#define ARGS_ARE_WORDS 0x001
+#define ARGS_ARE_XY_VALUES 0x002
+#define ROUND_XY_TO_GRID 0x004
+#define WE_HAVE_A_SCALE 0x008
+/* reserved 0x010 */
+#define MORE_COMPONENTS 0x020
+#define WE_HAVE_AN_XY_SCALE 0x040
+#define WE_HAVE_A_2X2 0x080
+#define WE_HAVE_INSTR 0x100
+#define USE_MY_METRICS 0x200
+
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Get_Metrics */
+ /* */
+ /* <Description> */
+ /* Returns the horizontal or vertical metrics in font units for a */
+ /* given glyph. The metrics are the left side bearing (resp. top */
+ /* side bearing) and advance width (resp. advance height). */
+ /* */
+ /* <Input> */
+ /* header :: A pointer to either the horizontal or vertical metrics */
+ /* structure. */
+ /* */
+ /* index :: The glyph index. */
+ /* */
+ /* <Output> */
+ /* bearing :: The bearing, either left side or top side. */
+ /* */
+ /* advance :: The advance width resp. advance height. */
+ /* */
+ /* <Note> */
+ /* This function will much probably move to another component in the */
+ /* near future, but I haven't decided which yet. */
+ /* */
+ LOCAL_FUNC
+ void TT_Get_Metrics( TT_HoriHeader* header,
+ FT_UInt index,
+ FT_Short* bearing,
+ FT_UShort* advance )
+ {
+ TT_LongMetrics* longs_m;
+ FT_UShort k = header->number_Of_HMetrics;
+
+
+ if ( index < k )
+ {
+ longs_m = (TT_LongMetrics*)header->long_metrics + index;
+ *bearing = longs_m->bearing;
+ *advance = longs_m->advance;
+ }
+ else
+ {
+ *bearing = ((TT_ShortMetrics*)header->short_metrics)[index - k];
+ *advance = ((TT_LongMetrics*)header->long_metrics)[k - 1].advance;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Returns the horizontal metrics in font units for a given glyph. If */
+ /* `check' is true, take care of monospaced fonts by returning the */
+ /* advance width maximum. */
+ /* */
+ static
+ void Get_HMetrics( TT_Face face,
+ FT_UInt index,
+ FT_Bool check,
+ FT_Short* lsb,
+ FT_UShort* aw )
+ {
+ TT_Get_Metrics( &face->horizontal, index, lsb, aw );
+
+ if ( check && face->postscript.isFixedPitch )
+ *aw = face->horizontal.advance_Width_Max;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Returns the advance width table for a given pixel size if it is */
+ /* found in the font's `hdmx' table (if any). */
+ /* */
+ static
+ FT_Byte* Get_Advance_Widths( TT_Face face,
+ FT_UShort ppem )
+ {
+ FT_UShort n;
+
+ for ( n = 0; n < face->hdmx.num_records; n++ )
+ if ( face->hdmx.records[n].ppem == ppem )
+ return face->hdmx.records[n].widths;
+
+ return NULL;
+ }
+
+
+#define cur_to_org( n, zone ) \
+ MEM_Copy( (zone)->org, (zone)->cur, n * sizeof ( FT_Vector ) )
+
+#define org_to_cur( n, zone ) \
+ MEM_Copy( (zone)->cur, (zone)->org, n * sizeof ( FT_Vector ) )
+
+
+ /*************************************************************************/
+ /* */
+ /* Translates an array of coordinates. */
+ /* */
+ static
+ void translate_array( FT_UInt n,
+ FT_Vector* coords,
+ FT_Pos delta_x,
+ FT_Pos delta_y )
+ {
+ FT_UInt k;
+
+
+ if ( delta_x )
+ for ( k = 0; k < n; k++ )
+ coords[k].x += delta_x;
+
+ if ( delta_y )
+ for ( k = 0; k < n; k++ )
+ coords[k].y += delta_y;
+ }
+
+
+ static
+ void tt_prepare_zone( TT_GlyphZone* zone,
+ FT_GlyphLoad* load,
+ FT_UInt start_point,
+ FT_UInt start_contour )
+ {
+ zone->n_points = load->outline.n_points - start_point;
+ zone->n_contours = load->outline.n_contours - start_contour;
+ zone->org = load->extra_points + start_point;
+ zone->cur = load->outline.points + start_point;
+ zone->tags = (FT_Byte*)load->outline.tags + start_point;
+ zone->contours = (FT_UShort*)load->outline.contours + start_contour;
+ }
+
+
+#undef IS_HINTED
+#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
+
+
+ /*************************************************************************/
+ /* */
+ /* The following functions are used by default with TrueType fonts. */
+ /* However, they can be replaced by alternatives if we need to support */
+ /* TrueType-compressed formats (like MicroType) in the future. */
+ /* */
+ /*************************************************************************/
+
+ static
+ FT_Error TT_Access_Glyph_Frame( TT_Loader* loader,
+ FT_UInt glyph_index,
+ FT_ULong offset,
+ FT_UInt byte_count )
+ {
+ FT_Error error;
+ FT_Stream stream = loader->stream;
+
+
+ /* the following line sets the `error' variable through macros! */
+ (void)( FILE_Seek( offset ) || ACCESS_Frame( byte_count ) );
+
+ FT_TRACE5(( "Glyph %ld\n", glyph_index ));
+ return error;
+ }
+
+
+ static
+ void TT_Forget_Glyph_Frame( TT_Loader* loader )
+ {
+ FT_Stream stream = loader->stream;
+
+
+ FORGET_Frame();
+ }
+
+
+ static
+ FT_Error TT_Load_Glyph_Header( TT_Loader* loader )
+ {
+ FT_Stream stream = loader->stream;
+
+
+ loader->n_contours = GET_Short();
+
+ loader->bbox.xMin = GET_Short();
+ loader->bbox.yMin = GET_Short();
+ loader->bbox.xMax = GET_Short();
+ loader->bbox.yMax = GET_Short();
+
+ FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
+ FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
+ loader->bbox.xMax ));
+ FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
+ loader->bbox.yMax ));
+
+ return FT_Err_Ok;
+ }
+
+
+ static
+ FT_Error TT_Load_Simple_Glyph( TT_Loader* load )
+ {
+ FT_Error error;
+ FT_Stream stream = load->stream;
+ FT_GlyphLoader* gloader = load->gloader;
+ FT_Int n_contours = load->n_contours;
+ FT_Outline* outline;
+ TT_Face face = (TT_Face)load->face;
+ TT_GlyphSlot slot = (TT_GlyphSlot)load->glyph;
+ FT_UShort n_ins;
+ FT_Int n, n_points;
+
+
+ /* reading the contours endpoints & number of points */
+ {
+ short* cur = gloader->current.outline.contours;
+ short* limit = cur + n_contours;
+
+
+ for ( ; cur < limit; cur++ )
+ cur[0] = GET_UShort();
+
+ n_points = 0;
+ if ( n_contours > 0 )
+ n_points = cur[-1] + 1;
+
+ error = FT_GlyphLoader_Check_Points( gloader, n_points + 2, 0 );
+ if ( error )
+ goto Fail;
+
+ outline = &gloader->current.outline;
+ }
+
+ /* reading the bytecode instructions */
+ slot->control_len = 0;
+ slot->control_data = 0;
+
+ n_ins = GET_UShort();
+
+ FT_TRACE5(( " Instructions size: %d\n", n_ins ));
+
+ if ( n_ins > face->max_profile.maxSizeOfInstructions )
+ {
+ FT_TRACE0(( "ERROR: Too many instructions!\n" ));
+ error = TT_Err_Too_Many_Ins;
+ goto Fail;
+ }
+
+ if ( stream->cursor + n_ins > stream->limit )
+ {
+ FT_TRACE0(( "ERROR: Instruction count mismatch!\n" ));
+ error = TT_Err_Too_Many_Ins;
+ goto Fail;
+ }
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+ if ( ( load->load_flags &
+ ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 &&
+ load->instructions )
+ {
+ slot->control_len = n_ins;
+ slot->control_data = load->instructions;
+
+ MEM_Copy( load->instructions, stream->cursor, n_ins );
+ }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+ stream->cursor += n_ins;
+
+ /* reading the point tags */
+
+ {
+ FT_Byte* flag = (FT_Byte*)outline->tags;
+ FT_Byte* limit = flag + n_points;
+ FT_Byte c, count;
+
+
+ for ( ; flag < limit; flag++ )
+ {
+ *flag = c = GET_Byte();
+ if ( c & 8 )
+ {
+ for ( count = GET_Byte(); count > 0; count-- )
+ *++flag = c;
+ }
+ }
+ }
+
+ /* reading the X coordinates */
+
+ {
+ FT_Vector* vec = outline->points;
+ FT_Vector* limit = vec + n_points;
+ FT_Byte* flag = (FT_Byte*)outline->tags;
+ FT_Pos x = 0;
+
+
+ for ( ; vec < limit; vec++, flag++ )
+ {
+ FT_Pos y = 0;
+
+
+ if ( *flag & 2 )
+ {
+ y = GET_Byte();
+ if ( ( *flag & 16 ) == 0 )
+ y = -y;
+ }
+ else if ( ( *flag & 16 ) == 0 )
+ y = GET_Short();
+
+ x += y;
+ vec->x = x;
+ }
+ }
+
+ /* reading the Y coordinates */
+
+ {
+ FT_Vector* vec = gloader->current.outline.points;
+ FT_Vector* limit = vec + n_points;
+ FT_Byte* flag = (FT_Byte*)outline->tags;
+ FT_Pos x = 0;
+
+
+ for ( ; vec < limit; vec++, flag++ )
+ {
+ FT_Pos y = 0;
+
+
+ if ( *flag & 4 )
+ {
+ y = GET_Byte();
+ if ( ( *flag & 32 ) == 0 )
+ y = -y;
+ }
+ else if ( ( *flag & 32 ) == 0 )
+ y = GET_Short();
+
+ x += y;
+ vec->y = x;
+ }
+ }
+
+ /* clear the touch tags */
+ for ( n = 0; n < n_points; n++ )
+ outline->tags[n] &= FT_Curve_Tag_On;
+
+ outline->n_points = n_points;
+ outline->n_contours = n_contours;
+
+ Fail:
+ return error;
+ }
+
+
+ static
+ FT_Error TT_Load_Composite_Glyph( TT_Loader* loader )
+ {
+ FT_Error error;
+ FT_Stream stream = loader->stream;
+ FT_GlyphLoader* gloader = loader->gloader;
+ FT_SubGlyph* subglyph;
+ FT_UInt num_subglyphs;
+
+
+ num_subglyphs = 0;
+
+ do
+ {
+ FT_Fixed xx, xy, yy, yx;
+
+
+ /* check that we can load a new subglyph */
+ error = FT_GlyphLoader_Check_Subglyphs( gloader, num_subglyphs + 1 );
+ if ( error )
+ goto Fail;
+
+ subglyph = gloader->current.subglyphs + num_subglyphs;
+
+ subglyph->arg1 = subglyph->arg2 = 0;
+
+ subglyph->flags = GET_UShort();
+ subglyph->index = GET_UShort();
+
+ /* read arguments */
+ if ( subglyph->flags & ARGS_ARE_WORDS )
+ {
+ subglyph->arg1 = GET_Short();
+ subglyph->arg2 = GET_Short();
+ }
+ else
+ {
+ subglyph->arg1 = GET_Char();
+ subglyph->arg2 = GET_Char();
+ }
+
+ /* read transform */
+ xx = yy = 0x10000L;
+ xy = yx = 0;
+
+ if ( subglyph->flags & WE_HAVE_A_SCALE )
+ {
+ xx = (FT_Fixed)GET_Short() << 2;
+ yy = xx;
+ }
+ else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
+ {
+ xx = (FT_Fixed)GET_Short() << 2;
+ yy = (FT_Fixed)GET_Short() << 2;
+ }
+ else if ( subglyph->flags & WE_HAVE_A_2X2 )
+ {
+ xx = (FT_Fixed)GET_Short() << 2;
+ xy = (FT_Fixed)GET_Short() << 2;
+ yx = (FT_Fixed)GET_Short() << 2;
+ yy = (FT_Fixed)GET_Short() << 2;
+ }
+
+ subglyph->transform.xx = xx;
+ subglyph->transform.xy = xy;
+ subglyph->transform.yx = yx;
+ subglyph->transform.yy = yy;
+
+ num_subglyphs++;
+
+ } while ( subglyph->flags & MORE_COMPONENTS );
+
+ gloader->current.num_subglyphs = num_subglyphs;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+ {
+ /* we must undo the ACCESS_Frame in order to point to the */
+ /* composite instructions, if we find some. */
+ /* we will process them later... */
+ /* */
+ loader->ins_pos = FILE_Pos() + stream->cursor - stream->limit;
+ }
+#endif
+
+ Fail:
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ void TT_Init_Glyph_Loading( TT_Face face )
+ {
+ face->access_glyph_frame = TT_Access_Glyph_Frame;
+ face->read_glyph_header = TT_Load_Glyph_Header;
+ face->read_simple_glyph = TT_Load_Simple_Glyph;
+ face->read_composite_glyph = TT_Load_Composite_Glyph;
+ face->forget_glyph_frame = TT_Forget_Glyph_Frame;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Process_Simple_Glyph */
+ /* */
+ /* <Description> */
+ /* Once a simple glyph has been loaded, it needs to be processed. */
+ /* Usually, this means scaling and hinting through bytecode */
+ /* interpretation. */
+ /* */
+ static
+ FT_Error TT_Process_Simple_Glyph( TT_Loader* load,
+ FT_Bool debug )
+ {
+ FT_GlyphLoader* gloader = load->gloader;
+ FT_Outline* outline = &gloader->current.outline;
+ FT_UInt n_points = outline->n_points;
+ FT_UInt n_ins;
+ TT_GlyphZone* zone = &load->zone;
+ FT_Error error = FT_Err_Ok;
+
+
+ n_ins = load->glyph->control_len;
+
+ /* add shadow points */
+
+ /* Now add the two shadow points at n and n + 1. */
+ /* We need the left side bearing and advance width. */
+
+ {
+ FT_Vector* pp1;
+ FT_Vector* pp2;
+
+
+ /* pp1 = xMin - lsb */
+ pp1 = outline->points + n_points;
+ pp1->x = load->bbox.xMin - load->left_bearing;
+ pp1->y = 0;
+
+ /* pp2 = pp1 + aw */
+ pp2 = pp1 + 1;
+ pp2->x = pp1->x + load->advance;
+ pp2->y = 0;
+
+ outline->tags[n_points ] = 0;
+ outline->tags[n_points + 1] = 0;
+ }
+
+ /* Note that we return two more points that are not */
+ /* part of the glyph outline. */
+
+ n_points += 2;
+
+ /* set up zone for hinting */
+ tt_prepare_zone( zone, &gloader->current, 0, 0 );
+
+ /* eventually scale the glyph */
+ if ( !( load->load_flags & FT_LOAD_NO_SCALE ) )
+ {
+ FT_Vector* vec = zone->cur;
+ FT_Vector* limit = vec + n_points;
+ FT_Fixed x_scale = load->size->metrics.x_scale;
+ FT_Fixed y_scale = load->size->metrics.y_scale;
+
+
+ /* first scale the glyph points */
+ for ( ; vec < limit; vec++ )
+ {
+ vec->x = FT_MulFix( vec->x, x_scale );
+ vec->y = FT_MulFix( vec->y, y_scale );
+ }
+ }
+
+ cur_to_org( n_points, zone );
+
+ /* eventually hint the glyph */
+ if ( IS_HINTED( load->load_flags ) )
+ {
+ FT_Pos x = zone->org[n_points-2].x;
+
+
+ x = ( ( x + 32 ) & -64 ) - x;
+ translate_array( n_points, zone->org, x, 0 );
+
+ org_to_cur( n_points, zone );
+
+ zone->cur[n_points - 1].x = ( zone->cur[n_points - 1].x + 32 ) & -64;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+ /* now consider hinting */
+ if ( n_ins > 0 )
+ {
+ error = TT_Set_CodeRange( load->exec, tt_coderange_glyph,
+ load->exec->glyphIns, n_ins );
+ if ( error )
+ goto Exit;
+
+ load->exec->is_composite = FALSE;
+ load->exec->pedantic_hinting = (FT_Bool)( load->load_flags &
+ FT_LOAD_PEDANTIC );
+ load->exec->pts = *zone;
+ load->exec->pts.n_points += 2;
+
+ error = TT_Run_Context( load->exec, debug );
+ if ( error && load->exec->pedantic_hinting )
+ goto Exit;
+
+ error = FT_Err_Ok; /* ignore bytecode errors in non-pedantic mode */
+ }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+ }
+
+ /* save glyph phantom points */
+ if ( !load->preserve_pps )
+ {
+ load->pp1 = zone->cur[n_points - 2];
+ load->pp2 = zone->cur[n_points - 1];
+ }
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+ Exit:
+#endif
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* load_truetype_glyph */
+ /* */
+ /* <Description> */
+ /* Loads a given truetype glyph. Handles composites and uses a */
+ /* TT_Loader object. */
+ /* */
+ static
+ FT_Error load_truetype_glyph( TT_Loader* loader,
+ FT_UInt glyph_index )
+ {
+ FT_Stream stream = loader->stream;
+ FT_Error error;
+ TT_Face face = (TT_Face)loader->face;
+ FT_ULong offset;
+ FT_Int contours_count;
+ FT_UInt index, num_points, num_contours, count;
+ FT_Fixed x_scale, y_scale;
+ FT_ULong ins_offset;
+ FT_GlyphLoader* gloader = loader->gloader;
+ FT_Bool opened_frame = 0;
+
+
+ /* check glyph index */
+ index = glyph_index;
+ if ( index >= (FT_UInt)face->root.num_glyphs )
+ {
+ error = TT_Err_Invalid_Glyph_Index;
+ goto Exit;
+ }
+
+ loader->glyph_index = glyph_index;
+ num_contours = 0;
+ num_points = 0;
+ ins_offset = 0;
+
+ x_scale = 0x10000L;
+ y_scale = 0x10000L;
+ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ x_scale = loader->size->metrics.x_scale;
+ y_scale = loader->size->metrics.y_scale;
+ }
+
+ /* get horizontal metrics */
+ {
+ FT_Short left_bearing;
+ FT_UShort advance_width;
+
+
+ Get_HMetrics( face, index,
+ (FT_Bool)!(loader->load_flags &
+ FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH),
+ &left_bearing,
+ &advance_width );
+
+ loader->left_bearing = left_bearing;
+ loader->advance = advance_width;
+ }
+
+ offset = face->glyph_locations[index];
+ count = 0;
+
+ if ( index < (FT_UInt)face->num_locations - 1 )
+ count = face->glyph_locations[index + 1] - offset;
+
+ if ( count == 0 )
+ {
+ /* as described by Frederic Loyer, these are spaces, and */
+ /* not the unknown glyph. */
+ loader->bbox.xMin = 0;
+ loader->bbox.xMax = 0;
+ loader->bbox.yMin = 0;
+ loader->bbox.yMax = 0;
+
+ loader->pp1.x = 0;
+ loader->pp2.x = loader->advance;
+
+ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+ if ( loader->exec )
+ loader->exec->glyphSize = 0;
+
+#endif
+
+ error = FT_Err_Ok;
+ goto Exit;
+ }
+
+ offset = loader->glyf_offset + offset;
+
+ /* access glyph frame */
+ error = face->access_glyph_frame( loader, glyph_index, offset, count );
+ if ( error )
+ goto Exit;
+
+ opened_frame = 1;
+
+ /* read first glyph header */
+ error = face->read_glyph_header( loader );
+ if ( error )
+ goto Fail;
+
+ contours_count = loader->n_contours;
+
+ count -= 10;
+
+ loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
+ loader->pp1.y = 0;
+ loader->pp2.x = loader->pp1.x + loader->advance;
+ loader->pp2.y = 0;
+
+ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
+ loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+ }
+
+ /***********************************************************************/
+ /***********************************************************************/
+ /***********************************************************************/
+
+ /* if it is a simple glyph, load it */
+
+ if ( contours_count >= 0 )
+ {
+ /* check that we can add the contours to the glyph */
+ error = FT_GlyphLoader_Check_Points( gloader, 0, contours_count );
+ if ( error )
+ goto Fail;
+
+ error = face->read_simple_glyph( loader );
+ if ( error )
+ goto Fail;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+ {
+ TT_Size size = (TT_Size)loader->size;
+
+
+ error = TT_Process_Simple_Glyph( loader,
+ (FT_Bool)( size && size->debug ) );
+ }
+
+#else
+
+ error = TT_Process_Simple_Glyph( loader, 0 );
+
+#endif
+
+ if ( error )
+ goto Fail;
+
+ FT_GlyphLoader_Add( gloader );
+
+ /* Note: We could have put the simple loader source there */
+ /* but the code is fat enough already :-) */
+ }
+
+ /***********************************************************************/
+ /***********************************************************************/
+ /***********************************************************************/
+
+ /* otherwise, load a composite! */
+ else
+ {
+ TT_GlyphSlot glyph = (TT_GlyphSlot)loader->glyph;
+ FT_UInt start_point, start_contour;
+ FT_ULong ins_pos; /* position of composite instructions, if any */
+
+
+ /* for each subglyph, read composite header */
+ start_point = gloader->base.outline.n_points;
+ start_contour = gloader->base.outline.n_contours;
+
+ error = face->read_composite_glyph( loader );
+ if ( error )
+ goto Fail;
+
+ ins_pos = loader->ins_pos;
+ face->forget_glyph_frame( loader );
+ opened_frame = 0;
+
+ /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
+ /* `as is' in the glyph slot (the client application will be */
+ /* responsible for interpreting this data)... */
+ /* */
+ if ( loader->load_flags & FT_LOAD_NO_RECURSE )
+ {
+ /* set up remaining glyph fields */
+ FT_GlyphLoader_Add( gloader );
+
+ glyph->num_subglyphs = gloader->base.num_subglyphs;
+ glyph->format = ft_glyph_format_composite;
+ glyph->subglyphs = gloader->base.subglyphs;
+
+ goto Exit;
+ }
+
+ /*********************************************************************/
+ /*********************************************************************/
+ /*********************************************************************/
+
+ /* Now, read each subglyph independently. */
+ {
+ FT_Int n, num_base_points, num_new_points;
+ FT_SubGlyph* subglyph = 0;
+
+ FT_UInt num_subglyphs = gloader->current.num_subglyphs;
+ FT_UInt num_base_subgs = gloader->base.num_subglyphs;
+
+
+ FT_GlyphLoader_Add( gloader );
+
+ for ( n = 0; n < (FT_Int)num_subglyphs; n++ )
+ {
+ FT_Vector pp1, pp2;
+ FT_Pos x, y;
+
+
+ /* Each time we call load_truetype_glyph in this loop, the */
+ /* value of `gloader.base.subglyphs' can change due to table */
+ /* reallocations. We thus need to recompute the subglyph */
+ /* pointer on each iteration. */
+ subglyph = gloader->base.subglyphs + num_base_subgs + n;
+
+ pp1 = loader->pp1;
+ pp2 = loader->pp2;
+
+ num_base_points = gloader->base.outline.n_points;
+
+ error = load_truetype_glyph( loader, subglyph->index );
+ if ( error )
+ goto Fail;
+
+ subglyph = gloader->base.subglyphs + num_base_subgs + n;
+
+ if ( subglyph->flags & 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 & ( WE_HAVE_A_SCALE |
+ WE_HAVE_AN_XY_SCALE |
+ WE_HAVE_A_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 & ARGS_ARE_XY_VALUES ) )
+ {
+ FT_UInt k = subglyph->arg1;
+ FT_UInt l = subglyph->arg2;
+ FT_Vector* p1;
+ FT_Vector* p2;
+
+
+ if ( start_point + k >= (FT_UInt)num_base_points ||
+ l >= (FT_UInt)num_new_points )
+ {
+ error = TT_Err_Invalid_Composite;
+ goto Fail;
+ }
+
+ l += num_base_points;
+
+ 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 = subglyph->arg1;
+ y = subglyph->arg2;
+
+ if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
+ {
+ x = FT_MulFix( x, x_scale );
+ y = FT_MulFix( y, y_scale );
+
+ if ( subglyph->flags & ROUND_XY_TO_GRID )
+ {
+ x = ( x + 32 ) & -64;
+ y = ( y + 32 ) & -64;
+ }
+ }
+ }
+
+ translate_array( num_new_points, loader->zone.cur, x, y );
+ cur_to_org( num_new_points, &loader->zone );
+ }
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /*******************************************************************/
+
+ /* we have finished loading all sub-glyphs; now, look for */
+ /* instructions for this composite! */
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+ if ( num_subglyphs > 0 &&
+ loader->exec &&
+ ins_pos > 0 &&
+ subglyph->flags & WE_HAVE_INSTR )
+ {
+ FT_UShort n_ins;
+ TT_ExecContext exec = loader->exec;
+ TT_GlyphZone* pts;
+ FT_Vector* pp1;
+
+
+ /* read size of instructions */
+ if ( FILE_Seek( ins_pos ) ||
+ READ_UShort( n_ins ) )
+ goto Fail;
+ FT_TRACE5(( " Instructions size = %d\n", n_ins ));
+
+ /* in some fonts? */
+ if ( n_ins == 0xFFFF )
+ n_ins = 0;
+
+ /* check it */
+ if ( n_ins > face->max_profile.maxSizeOfInstructions )
+ {
+ FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n",
+ n_ins, subglyph->index ));
+ return TT_Err_Too_Many_Ins;
+ }
+
+ /* read the instructions */
+ if ( FILE_Read( exec->glyphIns, n_ins ) )
+ goto Fail;
+
+ glyph->control_data = exec->glyphIns;
+ glyph->control_len = n_ins;
+
+ error = TT_Set_CodeRange( exec,
+ tt_coderange_glyph,
+ exec->glyphIns,
+ n_ins );
+ if ( error )
+ goto Fail;
+
+ /* prepare the execution context */
+ tt_prepare_zone( &exec->pts, &gloader->base,
+ start_point, start_contour );
+ pts = &exec->pts;
+
+ pts->n_points = num_points + 2;
+ pts->n_contours = gloader->base.outline.n_contours;
+
+ /* add phantom points */
+ pp1 = pts->cur + num_points;
+ pp1[0] = loader->pp1;
+ pp1[1] = loader->pp2;
+
+ pts->tags[num_points ] = 0;
+ pts->tags[num_points + 1] = 0;
+
+ /* if hinting, round the phantom points */
+ if ( IS_HINTED( loader->load_flags ) )
+ {
+ pp1[0].x = ( ( loader->pp1.x + 32 ) & -64 );
+ pp1[1].x = ( ( loader->pp2.x + 32 ) & -64 );
+ }
+
+ {
+ FT_UInt k;
+
+
+ for ( k = 0; k < num_points; k++ )
+ pts->tags[k] &= FT_Curve_Tag_On;
+ }
+
+ cur_to_org( num_points + 2, pts );
+
+ /* now consider hinting */
+ if ( IS_HINTED( loader->load_flags ) && n_ins > 0 )
+ {
+ exec->is_composite = TRUE;
+ exec->pedantic_hinting =
+ (FT_Bool)( loader->load_flags & FT_LOAD_PEDANTIC );
+
+ error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug );
+ if ( error && exec->pedantic_hinting )
+ goto Fail;
+ }
+
+ /* save glyph origin and advance points */
+ loader->pp1 = pp1[0];
+ loader->pp2 = pp1[1];
+ }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+ }
+ /* end of composite loading */
+ }
+
+ /***********************************************************************/
+ /***********************************************************************/
+ /***********************************************************************/
+
+ Fail:
+ if ( opened_frame )
+ face->forget_glyph_frame( loader );
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ void compute_glyph_metrics( TT_Loader* loader,
+ FT_UInt glyph_index )
+ {
+ FT_BBox bbox;
+ TT_Face face = (TT_Face)loader->face;
+ FT_Fixed x_scale, y_scale;
+ TT_GlyphSlot glyph = loader->glyph;
+ TT_Size size = (TT_Size)loader->size;
+
+
+ x_scale = 0x10000L;
+ y_scale = 0x10000L;
+ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ x_scale = size->root.metrics.x_scale;
+ y_scale = size->root.metrics.y_scale;
+ }
+
+ if ( glyph->format != ft_glyph_format_composite )
+ {
+ glyph->outline.flags &= ~ft_outline_single_pass;
+
+ /* copy outline to our glyph slot */
+ FT_GlyphLoader_Copy_Points( glyph->loader, loader->gloader );
+ glyph->outline = glyph->loader->base.outline;
+
+ /* translate array so that (0,0) is the glyph's origin */
+ FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 );
+
+ FT_Outline_Get_CBox( &glyph->outline, &bbox );
+
+ if ( IS_HINTED( loader->load_flags ) )
+ {
+ /* grid-fit the bounding box */
+ bbox.xMin &= -64;
+ bbox.yMin &= -64;
+ bbox.xMax = ( bbox.xMax + 63 ) & -64;
+ bbox.yMax = ( bbox.yMax + 63 ) & -64;
+ }
+ }
+ else
+ bbox = loader->bbox;
+
+ /* get the device-independent horizontal advance. It is scaled later */
+ /* by the base layer. */
+ {
+ FT_Pos advance = loader->advance;
+
+
+ /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
+ /* correctly support DynaLab fonts, which have an incorrect */
+ /* `advance_Width_Max' field! It is used, to my knowledge, */
+ /* exclusively in the X-TrueType font server. */
+ /* */
+ if ( face->postscript.isFixedPitch &&
+ ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
+ advance = face->horizontal.advance_Width_Max;
+
+ /* we need to return the advance in font units in linearHoriAdvance, */
+ /* it will be scaled later by the base layer. */
+ glyph->linearHoriAdvance = advance;
+ }
+
+ glyph->metrics.horiBearingX = bbox.xMin;
+ glyph->metrics.horiBearingY = bbox.yMax;
+ glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
+
+ /* Now take care of vertical metrics. In the case where there is */
+ /* no vertical information within the font (relatively common), make */
+ /* up some metrics by `hand'... */
+
+ {
+ FT_Short top_bearing; /* vertical top side bearing (EM units) */
+ FT_UShort advance_height; /* vertical advance height (EM units) */
+
+ FT_Pos left; /* scaled vertical left side bearing */
+ FT_Pos Top; /* scaled original vertical top side bearing */
+ FT_Pos top; /* scaled vertical top side bearing */
+ FT_Pos advance; /* scaled vertical advance height */
+
+
+ /* Get the unscaled `tsb' and `ah' */
+ if ( face->vertical_info &&
+ face->vertical.number_Of_VMetrics > 0 )
+ {
+ /* Don't assume that both the vertical header and vertical */
+ /* metrics are present in the same font :-) */
+
+ TT_Get_Metrics( (TT_HoriHeader*)&face->vertical,
+ glyph_index,
+ &top_bearing,
+ &advance_height );
+ }
+ else
+ {
+ /* Make up the distances from the horizontal header. */
+
+ /* NOTE: The OS/2 values are the only `portable' ones, */
+ /* which is why we use them, if there is an OS/2 */
+ /* table in the font. Otherwise, we use the */
+ /* values defined in the horizontal header. */
+ /* */
+ /* NOTE2: The sTypoDescender is negative, which is why */
+ /* we compute the baseline-to-baseline distance */
+ /* here with: */
+ /* ascender - descender + linegap */
+ /* */
+ if ( face->os2.version != 0xFFFF )
+ {
+ top_bearing = face->os2.sTypoLineGap / 2;
+ advance_height = (FT_UShort)( face->os2.sTypoAscender -
+ face->os2.sTypoDescender +
+ face->os2.sTypoLineGap );
+ }
+ else
+ {
+ top_bearing = face->horizontal.Line_Gap / 2;
+ advance_height = (FT_UShort)( face->horizontal.Ascender +
+ face->horizontal.Descender +
+ face->horizontal.Line_Gap );
+ }
+ }
+
+ /* We must adjust the top_bearing value from the bounding box given */
+ /* in the glyph header to te bounding box calculated with */
+ /* FT_Get_Outline_CBox(). */
+
+ /* scale the metrics */
+ if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
+ {
+ Top = FT_MulFix( top_bearing, y_scale );
+ top = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale )
+ - bbox.yMax;
+ advance = FT_MulFix( advance_height, y_scale );
+ }
+ else
+ {
+ Top = top_bearing;
+ top = top_bearing + loader->bbox.yMax - bbox.yMax;
+ advance = advance_height;
+ }
+
+ /* set the advance height in design units. It is scaled later by */
+ /* the base layer. */
+ glyph->linearVertAdvance = advance_height;
+
+ /* XXX: for now, we have no better algorithm for the lsb, but it */
+ /* should work fine. */
+ /* */
+ left = ( bbox.xMin - bbox.xMax ) / 2;
+
+ /* grid-fit them if necessary */
+ if ( IS_HINTED( loader->load_flags ) )
+ {
+ left &= -64;
+ top = ( top + 63 ) & -64;
+ advance = ( advance + 32 ) & -64;
+ }
+
+ glyph->metrics.vertBearingX = left;
+ glyph->metrics.vertBearingY = top;
+ glyph->metrics.vertAdvance = advance;
+ }
+
+ /* adjust advance width to the value contained in the hdmx table */
+ if ( !face->postscript.isFixedPitch && size &&
+ IS_HINTED( loader->load_flags ) )
+ {
+ FT_Byte* widths = Get_Advance_Widths( face,
+ size->root.metrics.x_ppem );
+
+
+ if ( widths )
+ glyph->metrics.horiAdvance = widths[glyph_index] << 6;
+ }
+
+ /* set glyph dimensions */
+ glyph->metrics.width = bbox.xMax - bbox.xMin;
+ glyph->metrics.height = bbox.yMax - bbox.yMin;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Glyph */
+ /* */
+ /* <Description> */
+ /* A function used to load a single glyph within a given glyph slot, */
+ /* for a given size. */
+ /* */
+ /* <Input> */
+ /* glyph :: A handle to a target slot object where the glyph */
+ /* will be loaded. */
+ /* */
+ /* size :: A handle to the source face size at which the glyph */
+ /* must be scaled/loaded. */
+ /* */
+ /* glyph_index :: The index of the glyph in the font file. */
+ /* */
+ /* load_flags :: A flag indicating what to load for this glyph. The */
+ /* FT_LOAD_XXX constants can be used to control the */
+ /* glyph loading process (e.g., whether the outline */
+ /* should be scaled, whether to load bitmaps or not, */
+ /* whether to hint the outline, etc). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_Glyph( TT_Size size,
+ TT_GlyphSlot glyph,
+ FT_UShort glyph_index,
+ FT_UInt load_flags )
+ {
+ SFNT_Interface* sfnt;
+ TT_Face face;
+ FT_Stream stream;
+ FT_Memory memory;
+ FT_Error error;
+ TT_Loader loader;
+
+
+ face = (TT_Face)glyph->face;
+ sfnt = (SFNT_Interface*)face->sfnt;
+ stream = face->root.stream;
+ memory = face->root.memory;
+ error = 0;
+
+ if ( !size || ( load_flags & FT_LOAD_NO_SCALE ) ||
+ ( load_flags & FT_LOAD_NO_RECURSE ) )
+ {
+ size = NULL;
+ load_flags |= FT_LOAD_NO_SCALE |
+ FT_LOAD_NO_HINTING |
+ FT_LOAD_NO_BITMAP;
+ }
+
+ glyph->num_subglyphs = 0;
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+ /* try to load embedded bitmap if any */
+ if ( size &&
+ ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
+ sfnt->load_sbits )
+ {
+ TT_SBit_Metrics metrics;
+
+
+ error = sfnt->load_sbit_image( face,
+ size->root.metrics.x_ppem,
+ size->root.metrics.y_ppem,
+ glyph_index,
+ load_flags,
+ stream,
+ &glyph->bitmap,
+ &metrics );
+ if ( !error )
+ {
+ glyph->outline.n_points = 0;
+ glyph->outline.n_contours = 0;
+
+ glyph->metrics.width = (FT_Pos)metrics.width << 6;
+ glyph->metrics.height = (FT_Pos)metrics.height << 6;
+
+ glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
+ glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
+ glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
+
+ glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
+ glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
+ glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
+
+ glyph->format = ft_glyph_format_bitmap;
+ if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
+ {
+ glyph->bitmap_left = metrics.vertBearingX;
+ glyph->bitmap_top = metrics.vertBearingY;
+ }
+ else
+ {
+ glyph->bitmap_left = metrics.horiBearingX;
+ glyph->bitmap_top = metrics.horiBearingY;
+ }
+ return error;
+ }
+ }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+ /* seek to the beginning of the glyph table. For Type 42 fonts */
+ /* the table might be accessed from a Postscript stream or something */
+ /* else... */
+
+ error = face->goto_table( face, TTAG_glyf, stream, 0 );
+ if ( error )
+ {
+ FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
+ goto Exit;
+ }
+
+ MEM_Set( &loader, 0, sizeof ( loader ) );
+
+ /* update the glyph zone bounds */
+ {
+ FT_GlyphLoader* gloader = FT_FACE_DRIVER(face)->glyph_loader;
+
+
+ loader.gloader = gloader;
+
+ FT_GlyphLoader_Rewind( gloader );
+
+ tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 );
+ tt_prepare_zone( &loader.base, &gloader->base, 0, 0 );
+ }
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+ if ( size )
+ {
+ /* query new execution context */
+ loader.exec = size->debug ? size->context : TT_New_Context( face );
+ if ( !loader.exec )
+ return TT_Err_Could_Not_Find_Context;
+
+ TT_Load_Context( loader.exec, face, size );
+ loader.instructions = loader.exec->glyphIns;
+
+ /* load default graphics state - if needed */
+ if ( size->GS.instruct_control & 2 )
+ loader.exec->GS = tt_default_graphics_state;
+ }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+ /* clear all outline flags, except the `owner' one */
+ glyph->outline.flags = 0;
+
+ if ( size && size->root.metrics.y_ppem < 24 )
+ glyph->outline.flags |= ft_outline_high_precision;
+
+ /* let's initialize the rest of our loader now */
+
+ loader.load_flags = load_flags;
+
+ loader.face = (FT_Face)face;
+ loader.size = (FT_Size)size;
+ loader.glyph = (FT_GlyphSlot)glyph;
+ loader.stream = stream;
+
+ loader.glyf_offset = FILE_Pos();
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+ /* if the cvt program has disabled hinting, the argument */
+ /* is ignored. */
+ if ( size && ( size->GS.instruct_control & 1 ) )
+ loader.load_flags |= FT_LOAD_NO_HINTING;
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+ /* Main loading loop */
+ glyph->format = ft_glyph_format_outline;
+ glyph->num_subglyphs = 0;
+ error = load_truetype_glyph( &loader, glyph_index );
+ if ( !error )
+ compute_glyph_metrics( &loader, glyph_index );
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+ if ( !size || !size->debug )
+ TT_Done_Context( loader.exec );
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+ Exit:
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttgload.h */
+/* */
+/* TrueType Glyph Loader (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef TTGLOAD_H
+#define TTGLOAD_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttobjs.h"
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#include "ttinterp.h"
+#endif
+
+#else /* FT_FLAT_COMPILE */
+
+#include <truetype/ttobjs.h>
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#include <truetype/ttinterp.h>
+#endif
+
+#endif /* FT_FLAT_COMPILE */
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ LOCAL_DEF
+ void TT_Get_Metrics( TT_HoriHeader* header,
+ FT_UInt index,
+ FT_Short* bearing,
+ FT_UShort* advance );
+
+ LOCAL_DEF
+ void TT_Init_Glyph_Loading( TT_Face face );
+
+ LOCAL_DEF
+ FT_Error TT_Load_Glyph( TT_Size size,
+ TT_GlyphSlot glyph,
+ FT_UShort glyph_index,
+ FT_UInt load_flags );
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* TTGLOAD_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttinterp.c */
+/* */
+/* TrueType bytecode interpreter (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/ftsystem.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttinterp.h"
+
+#else
+
+#include <truetype/ttinterp.h>
+
+#endif
+
+
+#include <freetype/internal/tterrors.h>
+
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+
+#define TT_MULFIX FT_MulFix
+#define TT_MULDIV FT_MulDiv
+
+#define TT_INT64 FT_Int64
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttinterp
+
+#undef NO_APPLE_PATENT
+#define APPLE_THRESHOLD 0x4000000L
+
+ /*************************************************************************/
+ /* */
+ /* In order to detect infinite loops in the code, we set up a counter */
+ /* within the run loop. A single stroke of interpretation is now */
+ /* limitet to a maximal number of opcodes defined below. */
+ /* */
+#define MAX_RUNNABLE_OPCODES 1000000L
+
+
+ /*************************************************************************/
+ /* */
+ /* There are two kinds of implementations: */
+ /* */
+ /* a. static implementation */
+ /* */
+ /* The current execution context is a static variable, which fields */
+ /* are accessed directly by the interpreter during execution. The */
+ /* context is named `cur'. */
+ /* */
+ /* This version is non-reentrant, of course. */
+ /* */
+ /* b. indirect implementation */
+ /* */
+ /* The current execution context is passed to _each_ function as its */
+ /* first argument, and each field is thus accessed indirectly. */
+ /* */
+ /* This version is fully re-entrant. */
+ /* */
+ /* The idea is that an indirect implementation may be slower to execute */
+ /* on low-end processors that are used in some systems (like 386s or */
+ /* even 486s). */
+ /* */
+ /* As a consequence, the indirect implementation is now the default, as */
+ /* its performance costs can be considered negligible in our context. */
+ /* Note, however, that we kept the same source with macros because: */
+ /* */
+ /* - The code is kept very close in design to the Pascal code used for */
+ /* development. */
+ /* */
+ /* - It's much more readable that way! */
+ /* */
+ /* - It's still open to experimentation and tuning. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */
+
+#define CUR (*exc) /* see ttobjs.h */
+
+#else /* static implementation */
+
+#define CUR cur
+
+ static
+ TT_ExecContextRec cur; /* static exec. context variable */
+
+ /* apparently, we have a _lot_ of direct indexing when accessing */
+ /* the static `cur', which makes the code bigger (due to all the */
+ /* four bytes addresses). */
+
+#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
+
+
+ /*************************************************************************/
+ /* */
+ /* The instruction argument stack. */
+ /* */
+#define INS_ARG EXEC_OP_ FT_Long* args /* see ttobjs.h for EXEC_OP_ */
+
+
+ /*************************************************************************/
+ /* */
+ /* This macro is used whenever `exec' is unused in a function, to avoid */
+ /* stupid warnings from pedantic compilers. */
+ /* */
+#define FT_UNUSED_EXEC FT_UNUSED( CUR )
+
+
+ /*************************************************************************/
+ /* */
+ /* This macro is used whenever `args' is unused in a function, to avoid */
+ /* stupid warnings from pedantic compilers. */
+ /* */
+#define FT_UNUSED_ARG FT_UNUSED_EXEC; FT_UNUSED( args )
+
+
+ /*************************************************************************/
+ /* */
+ /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to */
+ /* increase readabilty of the code. */
+ /* */
+ /*************************************************************************/
+
+
+#define SKIP_Code() \
+ SkipCode( EXEC_ARG )
+
+#define GET_ShortIns() \
+ GetShortIns( EXEC_ARG )
+
+#define NORMalize( x, y, v ) \
+ Normalize( EXEC_ARG_ x, y, v )
+
+#define SET_SuperRound( scale, flags ) \
+ SetSuperRound( EXEC_ARG_ scale, flags )
+
+#define ROUND_None( d, c ) \
+ Round_None( EXEC_ARG_ d, c )
+
+#define INS_Goto_CodeRange( range, ip ) \
+ Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
+
+#define CUR_Func_project( x, y ) \
+ CUR.func_project( EXEC_ARG_ x, y )
+
+#define CUR_Func_move( z, p, d ) \
+ CUR.func_move( EXEC_ARG_ z, p, d )
+
+#define CUR_Func_dualproj( x, y ) \
+ CUR.func_dualproj( EXEC_ARG_ x, y )
+
+#define CUR_Func_freeProj( x, y ) \
+ CUR.func_freeProj( EXEC_ARG_ x, y )
+
+#define CUR_Func_round( d, c ) \
+ CUR.func_round( EXEC_ARG_ d, c )
+
+#define CUR_Func_read_cvt( index ) \
+ CUR.func_read_cvt( EXEC_ARG_ index )
+
+#define CUR_Func_write_cvt( index, val ) \
+ CUR.func_write_cvt( EXEC_ARG_ index, val )
+
+#define CUR_Func_move_cvt( index, val ) \
+ CUR.func_move_cvt( EXEC_ARG_ index, val )
+
+#define CURRENT_Ratio() \
+ Current_Ratio( EXEC_ARG )
+
+#define CURRENT_Ppem() \
+ Current_Ppem( EXEC_ARG )
+
+#define CUR_Ppem() \
+ Cur_PPEM( EXEC_ARG )
+
+#define CALC_Length() \
+ Calc_Length( EXEC_ARG )
+
+#define INS_SxVTL( a, b, c, d ) \
+ Ins_SxVTL( EXEC_ARG_ a, b, c, d )
+
+#define COMPUTE_Funcs() \
+ Compute_Funcs( EXEC_ARG )
+
+#define COMPUTE_Round( a ) \
+ Compute_Round( EXEC_ARG_ a )
+
+#define COMPUTE_Point_Displacement( a, b, c, d ) \
+ Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )
+
+#define MOVE_Zp2_Point( a, b, c, t ) \
+ Move_Zp2_Point( EXEC_ARG_ a, b, c, t )
+
+
+ /*************************************************************************/
+ /* */
+ /* Instruction dispatch function, as used by the interpreter. */
+ /* */
+ typedef void (*TInstruction_Function)( INS_ARG );
+
+
+ /*************************************************************************/
+ /* */
+ /* A simple bounds-checking macro. */
+ /* */
+#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )
+
+
+#undef SUCCESS
+#define SUCCESS 0
+
+#undef FAILURE
+#define FAILURE 1
+
+
+ /*************************************************************************/
+ /* */
+ /* CODERANGE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Goto_CodeRange */
+ /* */
+ /* <Description> */
+ /* Switches to a new code range (updates the code related elements in */
+ /* `exec', and `IP'). */
+ /* */
+ /* <Input> */
+ /* range :: The new execution code range. */
+ /* */
+ /* IP :: The new IP in the new code range. */
+ /* */
+ /* <InOut> */
+ /* exec :: The target execution context. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Goto_CodeRange( TT_ExecContext exec,
+ FT_Int range,
+ FT_Long IP )
+ {
+ TT_CodeRange* coderange;
+
+
+ FT_Assert( range >= 1 && range <= 3 );
+
+ coderange = &exec->codeRangeTable[range - 1];
+
+ FT_Assert( coderange->base != NULL );
+
+ /* NOTE: Because the last instruction of a program may be a CALL */
+ /* which will return to the first byte *after* the code */
+ /* range, we test for IP <= Size instead of IP < Size. */
+ /* */
+ FT_Assert( (FT_ULong)IP <= coderange->size );
+
+ exec->code = coderange->base;
+ exec->codeSize = coderange->size;
+ exec->IP = IP;
+ exec->curRange = range;
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Set_CodeRange */
+ /* */
+ /* <Description> */
+ /* Sets a code range. */
+ /* */
+ /* <Input> */
+ /* range :: The code range index. */
+ /* */
+ /* base :: The new code base. */
+ /* */
+ /* length :: The range size in bytes. */
+ /* */
+ /* <InOut> */
+ /* exec :: The target execution context. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Set_CodeRange( TT_ExecContext exec,
+ FT_Int range,
+ void* base,
+ FT_Long length )
+ {
+ FT_Assert( range >= 1 && range <= 3 );
+
+ exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
+ exec->codeRangeTable[range - 1].size = length;
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Clear_CodeRange */
+ /* */
+ /* <Description> */
+ /* Clears a code range. */
+ /* */
+ /* <Input> */
+ /* range :: The code range index. */
+ /* */
+ /* <InOut> */
+ /* exec :: The target execution context. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Does not set the Error variable. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Clear_CodeRange( TT_ExecContext exec,
+ FT_Int range )
+ {
+ FT_Assert( range >= 1 && range <= 3 );
+
+ exec->codeRangeTable[range - 1].base = NULL;
+ exec->codeRangeTable[range - 1].size = 0;
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* EXECUTION CONTEXT ROUTINES */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Destroy_Context */
+ /* */
+ /* <Description> */
+ /* Destroys a given context. */
+ /* */
+ /* <Input> */
+ /* exec :: A handle to the target execution context. */
+ /* */
+ /* memory :: A handle to the parent memory object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only the glyph loader and debugger should call this function. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Destroy_Context( TT_ExecContext exec,
+ FT_Memory memory )
+ {
+ /* free composite load stack */
+ FREE( exec->loadStack );
+ exec->loadSize = 0;
+
+ /* points zone */
+ exec->maxPoints = 0;
+ exec->maxContours = 0;
+
+ /* free stack */
+ FREE( exec->stack );
+ exec->stackSize = 0;
+
+ /* free call stack */
+ FREE( exec->callStack );
+ exec->callSize = 0;
+ exec->callTop = 0;
+
+ /* free glyph code range */
+ FREE( exec->glyphIns );
+ exec->glyphSize = 0;
+
+ exec->size = NULL;
+ exec->face = NULL;
+
+ FREE( exec );
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Init_Context */
+ /* */
+ /* <Description> */
+ /* Initializes a context object. */
+ /* */
+ /* <Input> */
+ /* memory :: A handle to the parent memory object. */
+ /* */
+ /* face :: A handle to the source TrueType face object. */
+ /* */
+ /* <InOut> */
+ /* exec :: A handle to the target execution context. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Init_Context( TT_ExecContext exec,
+ TT_Face face,
+ FT_Memory memory )
+ {
+ FT_Error error;
+
+
+ FT_TRACE1(( "Init_Context: new object at 0x%08p, parent = 0x%08p\n",
+ exec, face ));
+
+ exec->memory = memory;
+ exec->callSize = 32;
+
+ if ( ALLOC_ARRAY( exec->callStack, exec->callSize, TT_CallRec ) )
+ goto Fail_Memory;
+
+ /* all values in the context are set to 0 already, but this is */
+ /* here as a remainder */
+ exec->maxPoints = 0;
+ exec->maxContours = 0;
+
+ exec->stackSize = 0;
+ exec->loadSize = 0;
+ exec->glyphSize = 0;
+
+ exec->stack = NULL;
+ exec->loadStack = NULL;
+ exec->glyphIns = NULL;
+
+ exec->face = face;
+ exec->size = NULL;
+
+ return TT_Err_Ok;
+
+ Fail_Memory:
+ FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n",
+ (FT_Long)exec ));
+ TT_Destroy_Context( exec, memory );
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Update_Max */
+ /* */
+ /* <Description> */
+ /* Checks the size of a buffer and reallocates it if necessary. */
+ /* */
+ /* <Input> */
+ /* memory :: A handle to the parent memory object. */
+ /* */
+ /* multiplier :: The size in bytes of each element in the buffer. */
+ /* */
+ /* new_max :: The new capacity (size) of the buffer. */
+ /* */
+ /* <InOut> */
+ /* size :: The address of the buffer's current size expressed */
+ /* in elements. */
+ /* */
+ /* buff :: The address of the buffer base pointer. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Update_Max( FT_Memory memory,
+ FT_ULong* size,
+ FT_Long multiplier,
+ void** buff,
+ FT_ULong new_max )
+ {
+ FT_Error error;
+
+
+ if ( *size < new_max )
+ {
+ FREE( *buff );
+ if ( ALLOC( *buff, new_max * multiplier ) )
+ return error;
+ *size = new_max;
+ }
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Context */
+ /* */
+ /* <Description> */
+ /* Prepare an execution context for glyph hinting. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* size :: A handle to the source size object. */
+ /* */
+ /* <InOut> */
+ /* exec :: A handle to the target execution context. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only the glyph loader and debugger should call this function. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_Context( TT_ExecContext exec,
+ TT_Face face,
+ TT_Size size )
+ {
+ FT_Int i;
+ FT_ULong tmp;
+ TT_MaxProfile* maxp;
+ FT_Error error;
+
+
+ exec->face = face;
+ maxp = &face->max_profile;
+ exec->size = size;
+
+ if ( size )
+ {
+ exec->numFDefs = size->num_function_defs;
+ exec->maxFDefs = size->max_function_defs;
+ exec->numIDefs = size->num_instruction_defs;
+ exec->maxIDefs = size->max_instruction_defs;
+ exec->FDefs = size->function_defs;
+ exec->IDefs = size->instruction_defs;
+ exec->tt_metrics = size->ttmetrics;
+ exec->metrics = size->root.metrics;
+
+ exec->maxFunc = size->max_func;
+ exec->maxIns = size->max_ins;
+
+ for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
+ exec->codeRangeTable[i] = size->codeRangeTable[i];
+
+ /* set graphics state */
+ exec->GS = size->GS;
+
+ exec->cvtSize = size->cvt_size;
+ exec->cvt = size->cvt;
+
+ exec->storeSize = size->storage_size;
+ exec->storage = size->storage;
+
+ exec->twilight = size->twilight;
+ }
+
+ error = Update_Max( exec->memory,
+ &exec->loadSize,
+ sizeof ( TT_SubGlyphRec ),
+ (void**)&exec->loadStack,
+ exec->face->max_components + 1 );
+ if ( error )
+ return error;
+
+ /* XXX: We reserve a little more elements on the stack to deal safely */
+ /* with broken fonts like arialbs, courbs, timesbs, etc. */
+ tmp = exec->stackSize;
+ error = Update_Max( exec->memory,
+ &tmp,
+ sizeof ( FT_F26Dot6 ),
+ (void**)&exec->stack,
+ maxp->maxStackElements + 32 );
+ exec->stackSize = (FT_UInt)tmp;
+ if ( error )
+ return error;
+
+ tmp = exec->glyphSize;
+ error = Update_Max( exec->memory,
+ &tmp,
+ sizeof ( FT_Byte ),
+ (void**)&exec->glyphIns,
+ maxp->maxSizeOfInstructions );
+ exec->glyphSize = (FT_UShort)tmp;
+ if ( error )
+ return error;
+
+ exec->pts.n_points = 0;
+ exec->pts.n_contours = 0;
+
+ exec->instruction_trap = FALSE;
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Save_Context */
+ /* */
+ /* <Description> */
+ /* Saves the code ranges in a `size' object. */
+ /* */
+ /* <Input> */
+ /* exec :: A handle to the source execution context. */
+ /* */
+ /* <InOut> */
+ /* size :: A handle to the target size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only the glyph loader and debugger should call this function. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Save_Context( TT_ExecContext exec,
+ TT_Size size )
+ {
+ FT_Int i;
+
+
+ /* XXXX: Will probably disappear soon with all the code range */
+ /* management, which is now rather obsolete. */
+ /* */
+ size->num_function_defs = exec->numFDefs;
+ size->num_instruction_defs = exec->numIDefs;
+
+ size->max_func = exec->maxFunc;
+ size->max_ins = exec->maxIns;
+
+ for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
+ size->codeRangeTable[i] = exec->codeRangeTable[i];
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Run_Context */
+ /* */
+ /* <Description> */
+ /* Executes one or more instructions in the execution context. */
+ /* */
+ /* <Input> */
+ /* debug :: A Boolean flag. If set, the function sets some internal */
+ /* variables and returns immediately, otherwise TT_RunIns() */
+ /* is called. */
+ /* */
+ /* This is commented out currently. */
+ /* */
+ /* <Input> */
+ /* exec :: A handle to the target execution context. */
+ /* */
+ /* <Return> */
+ /* TrueTyoe error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only the glyph loader and debugger should call this function. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Run_Context( TT_ExecContext exec,
+ FT_Bool debug )
+ {
+ FT_Error error;
+
+
+ if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
+ != TT_Err_Ok )
+ return error;
+
+ exec->zp0 = exec->pts;
+ exec->zp1 = exec->pts;
+ exec->zp2 = exec->pts;
+
+ exec->GS.gep0 = 1;
+ exec->GS.gep1 = 1;
+ exec->GS.gep2 = 1;
+
+ exec->GS.projVector.x = 0x4000;
+ exec->GS.projVector.y = 0x0000;
+
+ exec->GS.freeVector = exec->GS.projVector;
+ exec->GS.dualVector = exec->GS.projVector;
+
+ exec->GS.round_state = 1;
+ exec->GS.loop = 1;
+
+ /* some glyphs leave something on the stack. so we clean it */
+ /* before a new execution. */
+ exec->top = 0;
+ exec->callTop = 0;
+
+#if 1
+ FT_UNUSED( debug );
+
+ return exec->face->interpreter( exec );
+#else
+ if ( !debug )
+ return TT_RunIns( exec );
+ else
+ return TT_Err_Ok;
+#endif
+ }
+
+
+ const TT_GraphicsState tt_default_graphics_state =
+ {
+ 0, 0, 0,
+ { 0x4000, 0 },
+ { 0x4000, 0 },
+ { 0x4000, 0 },
+ 1, 64, 1,
+ TRUE, 68, 0, 0, 9, 3,
+ 0, FALSE, 2, 1, 1, 1
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_New_Context */
+ /* */
+ /* <Description> */
+ /* Queries the face context for a given font. Note that there is */
+ /* now a _single_ execution context in the TrueType driver which is */
+ /* shared among faces. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* <Return> */
+ /* A handle to the execution context. Initialized for `face'. */
+ /* */
+ /* <Note> */
+ /* Only the glyph loader and debugger should call this function. */
+ /* */
+ FT_EXPORT_FUNC( TT_ExecContext ) TT_New_Context( TT_Face face )
+ {
+ TT_Driver driver;
+ TT_ExecContext exec;
+ FT_Memory memory;
+
+
+ if ( !face )
+ return 0;
+
+ driver = (TT_Driver)face->root.driver;
+
+ memory = driver->root.root.memory;
+ exec = driver->context;
+
+ if ( !driver->context )
+ {
+ FT_Error error;
+
+
+ /* allocate object */
+ if ( ALLOC( exec, sizeof ( *exec ) ) )
+ goto Exit;
+
+ /* initialize it */
+ error = Init_Context( exec, face, memory );
+ if ( error )
+ goto Fail;
+
+ /* store it into the driver */
+ driver->context = exec;
+ }
+
+ Exit:
+ return driver->context;
+
+ Fail:
+ FREE( exec );
+
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Done_Context */
+ /* */
+ /* <Description> */
+ /* Discards an execution context. */
+ /* */
+ /* <Input> */
+ /* exec :: A handle to the target execution context. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only the glyph loader and debugger should call this function. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Done_Context( TT_ExecContext exec )
+ {
+ /* Nothing at all for now */
+ FT_UNUSED( exec );
+
+ return TT_Err_Ok;
+ }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+ static FT_F26Dot6 Norm( FT_F26Dot6 X,
+ FT_F26Dot6 Y )
+ {
+ TT_INT64 T1, T2;
+
+
+ MUL_64( X, X, T1 );
+ MUL_64( Y, Y, T2 );
+
+ ADD_64( T1, T2, T1 );
+
+ return (FT_F26Dot6)SQRT_64( T1 );
+ }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+ /*************************************************************************/
+ /* */
+ /* Before an opcode is executed, the interpreter verifies that there are */
+ /* enough arguments on the stack, with the help of the Pop_Push_Count */
+ /* table. */
+ /* */
+ /* For each opcode, the first column gives the number of arguments that */
+ /* are popped from the stack; the second one gives the number of those */
+ /* that are pushed in result. */
+ /* */
+ /* Note that for opcodes with a varying number of parameters, either 0 */
+ /* or 1 arg is verified before execution, depending on the nature of the */
+ /* instruction: */
+ /* */
+ /* - if the number of arguments is given by the bytecode stream or the */
+ /* loop variable, 0 is chosen. */
+ /* */
+ /* - if the first argument is a count n that is followed by arguments */
+ /* a1 .. an, then 1 is chosen. */
+ /* */
+ /*************************************************************************/
+
+
+#undef PACK
+#define PACK( x, y ) ( ( x << 4 ) | y )
+
+
+ static
+ const FT_Byte Pop_Push_Count[256] =
+ {
+ /* opcodes are gathered in groups of 16 */
+ /* please keep the spaces as they are */
+
+ /* SVTCA y */ PACK( 0, 0 ),
+ /* SVTCA x */ PACK( 0, 0 ),
+ /* SPvTCA y */ PACK( 0, 0 ),
+ /* SPvTCA x */ PACK( 0, 0 ),
+ /* SFvTCA y */ PACK( 0, 0 ),
+ /* SFvTCA x */ PACK( 0, 0 ),
+ /* SPvTL // */ PACK( 2, 0 ),
+ /* SPvTL + */ PACK( 2, 0 ),
+ /* SFvTL // */ PACK( 2, 0 ),
+ /* SFvTL + */ PACK( 2, 0 ),
+ /* SPvFS */ PACK( 2, 0 ),
+ /* SFvFS */ PACK( 2, 0 ),
+ /* GPV */ PACK( 0, 2 ),
+ /* GFV */ PACK( 0, 2 ),
+ /* SFvTPv */ PACK( 0, 0 ),
+ /* ISECT */ PACK( 5, 0 ),
+
+ /* SRP0 */ PACK( 1, 0 ),
+ /* SRP1 */ PACK( 1, 0 ),
+ /* SRP2 */ PACK( 1, 0 ),
+ /* SZP0 */ PACK( 1, 0 ),
+ /* SZP1 */ PACK( 1, 0 ),
+ /* SZP2 */ PACK( 1, 0 ),
+ /* SZPS */ PACK( 1, 0 ),
+ /* SLOOP */ PACK( 1, 0 ),
+ /* RTG */ PACK( 0, 0 ),
+ /* RTHG */ PACK( 0, 0 ),
+ /* SMD */ PACK( 1, 0 ),
+ /* ELSE */ PACK( 0, 0 ),
+ /* JMPR */ PACK( 1, 0 ),
+ /* SCvTCi */ PACK( 1, 0 ),
+ /* SSwCi */ PACK( 1, 0 ),
+ /* SSW */ PACK( 1, 0 ),
+
+ /* DUP */ PACK( 1, 2 ),
+ /* POP */ PACK( 1, 0 ),
+ /* CLEAR */ PACK( 0, 0 ),
+ /* SWAP */ PACK( 2, 2 ),
+ /* DEPTH */ PACK( 0, 1 ),
+ /* CINDEX */ PACK( 1, 1 ),
+ /* MINDEX */ PACK( 1, 0 ),
+ /* AlignPTS */ PACK( 2, 0 ),
+ /* INS_$28 */ PACK( 0, 0 ),
+ /* UTP */ PACK( 1, 0 ),
+ /* LOOPCALL */ PACK( 2, 0 ),
+ /* CALL */ PACK( 1, 0 ),
+ /* FDEF */ PACK( 1, 0 ),
+ /* ENDF */ PACK( 0, 0 ),
+ /* MDAP[0] */ PACK( 1, 0 ),
+ /* MDAP[1] */ PACK( 1, 0 ),
+
+ /* IUP[0] */ PACK( 0, 0 ),
+ /* IUP[1] */ PACK( 0, 0 ),
+ /* SHP[0] */ PACK( 0, 0 ),
+ /* SHP[1] */ PACK( 0, 0 ),
+ /* SHC[0] */ PACK( 1, 0 ),
+ /* SHC[1] */ PACK( 1, 0 ),
+ /* SHZ[0] */ PACK( 1, 0 ),
+ /* SHZ[1] */ PACK( 1, 0 ),
+ /* SHPIX */ PACK( 1, 0 ),
+ /* IP */ PACK( 0, 0 ),
+ /* MSIRP[0] */ PACK( 2, 0 ),
+ /* MSIRP[1] */ PACK( 2, 0 ),
+ /* AlignRP */ PACK( 0, 0 ),
+ /* RTDG */ PACK( 0, 0 ),
+ /* MIAP[0] */ PACK( 2, 0 ),
+ /* MIAP[1] */ PACK( 2, 0 ),
+
+ /* NPushB */ PACK( 0, 0 ),
+ /* NPushW */ PACK( 0, 0 ),
+ /* WS */ PACK( 2, 0 ),
+ /* RS */ PACK( 1, 1 ),
+ /* WCvtP */ PACK( 2, 0 ),
+ /* RCvt */ PACK( 1, 1 ),
+ /* GC[0] */ PACK( 1, 1 ),
+ /* GC[1] */ PACK( 1, 1 ),
+ /* SCFS */ PACK( 2, 0 ),
+ /* MD[0] */ PACK( 2, 1 ),
+ /* MD[1] */ PACK( 2, 1 ),
+ /* MPPEM */ PACK( 0, 1 ),
+ /* MPS */ PACK( 0, 1 ),
+ /* FlipON */ PACK( 0, 0 ),
+ /* FlipOFF */ PACK( 0, 0 ),
+ /* DEBUG */ PACK( 1, 0 ),
+
+ /* LT */ PACK( 2, 1 ),
+ /* LTEQ */ PACK( 2, 1 ),
+ /* GT */ PACK( 2, 1 ),
+ /* GTEQ */ PACK( 2, 1 ),
+ /* EQ */ PACK( 2, 1 ),
+ /* NEQ */ PACK( 2, 1 ),
+ /* ODD */ PACK( 1, 1 ),
+ /* EVEN */ PACK( 1, 1 ),
+ /* IF */ PACK( 1, 0 ),
+ /* EIF */ PACK( 0, 0 ),
+ /* AND */ PACK( 2, 1 ),
+ /* OR */ PACK( 2, 1 ),
+ /* NOT */ PACK( 1, 1 ),
+ /* DeltaP1 */ PACK( 1, 0 ),
+ /* SDB */ PACK( 1, 0 ),
+ /* SDS */ PACK( 1, 0 ),
+
+ /* ADD */ PACK( 2, 1 ),
+ /* SUB */ PACK( 2, 1 ),
+ /* DIV */ PACK( 2, 1 ),
+ /* MUL */ PACK( 2, 1 ),
+ /* ABS */ PACK( 1, 1 ),
+ /* NEG */ PACK( 1, 1 ),
+ /* FLOOR */ PACK( 1, 1 ),
+ /* CEILING */ PACK( 1, 1 ),
+ /* ROUND[0] */ PACK( 1, 1 ),
+ /* ROUND[1] */ PACK( 1, 1 ),
+ /* ROUND[2] */ PACK( 1, 1 ),
+ /* ROUND[3] */ PACK( 1, 1 ),
+ /* NROUND[0] */ PACK( 1, 1 ),
+ /* NROUND[1] */ PACK( 1, 1 ),
+ /* NROUND[2] */ PACK( 1, 1 ),
+ /* NROUND[3] */ PACK( 1, 1 ),
+
+ /* WCvtF */ PACK( 2, 0 ),
+ /* DeltaP2 */ PACK( 1, 0 ),
+ /* DeltaP3 */ PACK( 1, 0 ),
+ /* DeltaCn[0] */ PACK( 1, 0 ),
+ /* DeltaCn[1] */ PACK( 1, 0 ),
+ /* DeltaCn[2] */ PACK( 1, 0 ),
+ /* SROUND */ PACK( 1, 0 ),
+ /* S45Round */ PACK( 1, 0 ),
+ /* JROT */ PACK( 2, 0 ),
+ /* JROF */ PACK( 2, 0 ),
+ /* ROFF */ PACK( 0, 0 ),
+ /* INS_$7B */ PACK( 0, 0 ),
+ /* RUTG */ PACK( 0, 0 ),
+ /* RDTG */ PACK( 0, 0 ),
+ /* SANGW */ PACK( 1, 0 ),
+ /* AA */ PACK( 1, 0 ),
+
+ /* FlipPT */ PACK( 0, 0 ),
+ /* FlipRgON */ PACK( 2, 0 ),
+ /* FlipRgOFF */ PACK( 2, 0 ),
+ /* INS_$83 */ PACK( 0, 0 ),
+ /* INS_$84 */ PACK( 0, 0 ),
+ /* ScanCTRL */ PACK( 1, 0 ),
+ /* SDVPTL[0] */ PACK( 2, 0 ),
+ /* SDVPTL[1] */ PACK( 2, 0 ),
+ /* GetINFO */ PACK( 1, 1 ),
+ /* IDEF */ PACK( 1, 0 ),
+ /* ROLL */ PACK( 3, 3 ),
+ /* MAX */ PACK( 2, 1 ),
+ /* MIN */ PACK( 2, 1 ),
+ /* ScanTYPE */ PACK( 1, 0 ),
+ /* InstCTRL */ PACK( 2, 0 ),
+ /* INS_$8F */ PACK( 0, 0 ),
+
+ /* INS_$90 */ PACK( 0, 0 ),
+ /* INS_$91 */ PACK( 0, 0 ),
+ /* INS_$92 */ PACK( 0, 0 ),
+ /* INS_$93 */ PACK( 0, 0 ),
+ /* INS_$94 */ PACK( 0, 0 ),
+ /* INS_$95 */ PACK( 0, 0 ),
+ /* INS_$96 */ PACK( 0, 0 ),
+ /* INS_$97 */ PACK( 0, 0 ),
+ /* INS_$98 */ PACK( 0, 0 ),
+ /* INS_$99 */ PACK( 0, 0 ),
+ /* INS_$9A */ PACK( 0, 0 ),
+ /* INS_$9B */ PACK( 0, 0 ),
+ /* INS_$9C */ PACK( 0, 0 ),
+ /* INS_$9D */ PACK( 0, 0 ),
+ /* INS_$9E */ PACK( 0, 0 ),
+ /* INS_$9F */ PACK( 0, 0 ),
+
+ /* INS_$A0 */ PACK( 0, 0 ),
+ /* INS_$A1 */ PACK( 0, 0 ),
+ /* INS_$A2 */ PACK( 0, 0 ),
+ /* INS_$A3 */ PACK( 0, 0 ),
+ /* INS_$A4 */ PACK( 0, 0 ),
+ /* INS_$A5 */ PACK( 0, 0 ),
+ /* INS_$A6 */ PACK( 0, 0 ),
+ /* INS_$A7 */ PACK( 0, 0 ),
+ /* INS_$A8 */ PACK( 0, 0 ),
+ /* INS_$A9 */ PACK( 0, 0 ),
+ /* INS_$AA */ PACK( 0, 0 ),
+ /* INS_$AB */ PACK( 0, 0 ),
+ /* INS_$AC */ PACK( 0, 0 ),
+ /* INS_$AD */ PACK( 0, 0 ),
+ /* INS_$AE */ PACK( 0, 0 ),
+ /* INS_$AF */ PACK( 0, 0 ),
+
+ /* PushB[0] */ PACK( 0, 1 ),
+ /* PushB[1] */ PACK( 0, 2 ),
+ /* PushB[2] */ PACK( 0, 3 ),
+ /* PushB[3] */ PACK( 0, 4 ),
+ /* PushB[4] */ PACK( 0, 5 ),
+ /* PushB[5] */ PACK( 0, 6 ),
+ /* PushB[6] */ PACK( 0, 7 ),
+ /* PushB[7] */ PACK( 0, 8 ),
+ /* PushW[0] */ PACK( 0, 1 ),
+ /* PushW[1] */ PACK( 0, 2 ),
+ /* PushW[2] */ PACK( 0, 3 ),
+ /* PushW[3] */ PACK( 0, 4 ),
+ /* PushW[4] */ PACK( 0, 5 ),
+ /* PushW[5] */ PACK( 0, 6 ),
+ /* PushW[6] */ PACK( 0, 7 ),
+ /* PushW[7] */ PACK( 0, 8 ),
+
+ /* MDRP[00] */ PACK( 1, 0 ),
+ /* MDRP[01] */ PACK( 1, 0 ),
+ /* MDRP[02] */ PACK( 1, 0 ),
+ /* MDRP[03] */ PACK( 1, 0 ),
+ /* MDRP[04] */ PACK( 1, 0 ),
+ /* MDRP[05] */ PACK( 1, 0 ),
+ /* MDRP[06] */ PACK( 1, 0 ),
+ /* MDRP[07] */ PACK( 1, 0 ),
+ /* MDRP[08] */ PACK( 1, 0 ),
+ /* MDRP[09] */ PACK( 1, 0 ),
+ /* MDRP[10] */ PACK( 1, 0 ),
+ /* MDRP[11] */ PACK( 1, 0 ),
+ /* MDRP[12] */ PACK( 1, 0 ),
+ /* MDRP[13] */ PACK( 1, 0 ),
+ /* MDRP[14] */ PACK( 1, 0 ),
+ /* MDRP[15] */ PACK( 1, 0 ),
+
+ /* MDRP[16] */ PACK( 1, 0 ),
+ /* MDRP[17] */ PACK( 1, 0 ),
+ /* MDRP[18] */ PACK( 1, 0 ),
+ /* MDRP[19] */ PACK( 1, 0 ),
+ /* MDRP[20] */ PACK( 1, 0 ),
+ /* MDRP[21] */ PACK( 1, 0 ),
+ /* MDRP[22] */ PACK( 1, 0 ),
+ /* MDRP[23] */ PACK( 1, 0 ),
+ /* MDRP[24] */ PACK( 1, 0 ),
+ /* MDRP[25] */ PACK( 1, 0 ),
+ /* MDRP[26] */ PACK( 1, 0 ),
+ /* MDRP[27] */ PACK( 1, 0 ),
+ /* MDRP[28] */ PACK( 1, 0 ),
+ /* MDRP[29] */ PACK( 1, 0 ),
+ /* MDRP[30] */ PACK( 1, 0 ),
+ /* MDRP[31] */ PACK( 1, 0 ),
+
+ /* MIRP[00] */ PACK( 2, 0 ),
+ /* MIRP[01] */ PACK( 2, 0 ),
+ /* MIRP[02] */ PACK( 2, 0 ),
+ /* MIRP[03] */ PACK( 2, 0 ),
+ /* MIRP[04] */ PACK( 2, 0 ),
+ /* MIRP[05] */ PACK( 2, 0 ),
+ /* MIRP[06] */ PACK( 2, 0 ),
+ /* MIRP[07] */ PACK( 2, 0 ),
+ /* MIRP[08] */ PACK( 2, 0 ),
+ /* MIRP[09] */ PACK( 2, 0 ),
+ /* MIRP[10] */ PACK( 2, 0 ),
+ /* MIRP[11] */ PACK( 2, 0 ),
+ /* MIRP[12] */ PACK( 2, 0 ),
+ /* MIRP[13] */ PACK( 2, 0 ),
+ /* MIRP[14] */ PACK( 2, 0 ),
+ /* MIRP[15] */ PACK( 2, 0 ),
+
+ /* MIRP[16] */ PACK( 2, 0 ),
+ /* MIRP[17] */ PACK( 2, 0 ),
+ /* MIRP[18] */ PACK( 2, 0 ),
+ /* MIRP[19] */ PACK( 2, 0 ),
+ /* MIRP[20] */ PACK( 2, 0 ),
+ /* MIRP[21] */ PACK( 2, 0 ),
+ /* MIRP[22] */ PACK( 2, 0 ),
+ /* MIRP[23] */ PACK( 2, 0 ),
+ /* MIRP[24] */ PACK( 2, 0 ),
+ /* MIRP[25] */ PACK( 2, 0 ),
+ /* MIRP[26] */ PACK( 2, 0 ),
+ /* MIRP[27] */ PACK( 2, 0 ),
+ /* MIRP[28] */ PACK( 2, 0 ),
+ /* MIRP[29] */ PACK( 2, 0 ),
+ /* MIRP[30] */ PACK( 2, 0 ),
+ /* MIRP[31] */ PACK( 2, 0 )
+ };
+
+
+ static
+ const FT_Char opcode_length[256] =
+ {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ -1,-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 3, 5, 7, 9, 11,13,15,17,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ };
+
+ static
+ const FT_Vector Null_Vector = {0,0};
+
+
+#undef PACK
+
+
+#undef NULL_Vector
+#define NULL_Vector (FT_Vector*)&Null_Vector
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Current_Ratio */
+ /* */
+ /* <Description> */
+ /* Returns the current aspect ratio scaling factor depending on the */
+ /* projection vector's state and device resolutions. */
+ /* */
+ /* <Return> */
+ /* The aspect ratio in 16.16 format, always <= 1.0 . */
+ /* */
+ static
+ FT_Long Current_Ratio( EXEC_OP )
+ {
+ if ( CUR.tt_metrics.ratio )
+ return CUR.tt_metrics.ratio;
+
+ if ( CUR.GS.projVector.y == 0 )
+ CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
+
+ else if ( CUR.GS.projVector.x == 0 )
+ CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
+
+ else
+ {
+ FT_Long x, y;
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+ x = TT_MULDIV( CUR.GS.projVector.x, CUR.tt_metrics.x_ratio, 0x4000 );
+ y = TT_MULDIV( CUR.GS.projVector.y, CUR.tt_metrics.y_ratio, 0x4000 );
+ CUR.tt_metrics.ratio = Norm( x, y );
+
+#else
+
+ x = TT_MULDIV( CUR.GS.projVector.x, CUR.tt_metrics.x_ratio, 0x8000 );
+ y = TT_MULDIV( CUR.GS.projVector.y, CUR.tt_metrics.y_ratio, 0x8000 );
+ CUR.tt_metrics.ratio = FT_Sqrt32( x * x + y * y ) << 1;
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+ }
+
+ return CUR.tt_metrics.ratio;
+ }
+
+
+ static
+ FT_Long Current_Ppem( EXEC_OP )
+ {
+ return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Functions related to the control value table (CVT). */
+ /* */
+ /*************************************************************************/
+
+
+ static
+ FT_F26Dot6 Read_CVT( EXEC_OP_ FT_ULong index )
+ {
+ return CUR.cvt[index];
+ }
+
+
+ static
+ FT_F26Dot6 Read_CVT_Stretched( EXEC_OP_ FT_ULong index )
+ {
+ return TT_MULFIX( CUR.cvt[index], CURRENT_Ratio() );
+ }
+
+
+ static
+ void Write_CVT( EXEC_OP_ FT_ULong index,
+ FT_F26Dot6 value )
+ {
+ CUR.cvt[index] = value;
+ }
+
+
+ static
+ void Write_CVT_Stretched( EXEC_OP_ FT_ULong index,
+ FT_F26Dot6 value )
+ {
+ CUR.cvt[index] = FT_DivFix( value, CURRENT_Ratio() );
+ }
+
+
+ static
+ void Move_CVT( EXEC_OP_ FT_ULong index,
+ FT_F26Dot6 value )
+ {
+ CUR.cvt[index] += value;
+ }
+
+
+ static
+ void Move_CVT_Stretched( EXEC_OP_ FT_ULong index,
+ FT_F26Dot6 value )
+ {
+ CUR.cvt[index] += FT_DivFix( value, CURRENT_Ratio() );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* GetShortIns */
+ /* */
+ /* <Description> */
+ /* Returns a short integer taken from the instruction stream at */
+ /* address IP. */
+ /* */
+ /* <Return> */
+ /* Short read at code[IP]. */
+ /* */
+ /* <Note> */
+ /* This one could become a macro. */
+ /* */
+ static FT_Short GetShortIns( EXEC_OP )
+ {
+ /* Reading a byte stream so there is no endianess (DaveP) */
+ CUR.IP += 2;
+ return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +
+ CUR.code[CUR.IP - 1] );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Ins_Goto_CodeRange */
+ /* */
+ /* <Description> */
+ /* Goes to a certain code range in the instruction stream. */
+ /* */
+ /* <Input> */
+ /* aRange :: The index of the code range. */
+ /* */
+ /* aIP :: The new IP address in the code range. */
+ /* */
+ /* <Return> */
+ /* SUCCESS or FAILURE. */
+ /* */
+ static
+ FT_Bool Ins_Goto_CodeRange( EXEC_OP_ FT_Int aRange,
+ FT_ULong aIP )
+ {
+ TT_CodeRange* range;
+
+
+ if ( aRange < 1 || aRange > 3 )
+ {
+ CUR.error = TT_Err_Bad_Argument;
+ return FAILURE;
+ }
+
+ range = &CUR.codeRangeTable[aRange - 1];
+
+ if ( range->base == NULL ) /* invalid coderange */
+ {
+ CUR.error = TT_Err_Invalid_CodeRange;
+ return FAILURE;
+ }
+
+ /* NOTE: Because the last instruction of a program may be a CALL */
+ /* which will return to the first byte *after* the code */
+ /* range, we test for AIP <= Size, instead of AIP < Size. */
+
+ if ( aIP > range->size )
+ {
+ CUR.error = TT_Err_Code_Overflow;
+ return FAILURE;
+ }
+
+ CUR.code = range->base;
+ CUR.codeSize = range->size;
+ CUR.IP = aIP;
+ CUR.curRange = aRange;
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Direct_Move */
+ /* */
+ /* <Description> */
+ /* Moves a point by a given distance along the freedom vector. The */
+ /* point will be `touched'. */
+ /* */
+ /* <Input> */
+ /* point :: The index of the point to move. */
+ /* */
+ /* distance :: The distance to apply. */
+ /* */
+ /* <InOut> */
+ /* zone :: The affected glyph zone. */
+ /* */
+ static
+ void Direct_Move( EXEC_OP_ TT_GlyphZone* zone,
+ FT_UShort point,
+ FT_F26Dot6 distance )
+ {
+ FT_F26Dot6 v;
+
+
+ v = CUR.GS.freeVector.x;
+
+ if ( v != 0 )
+ {
+
+#ifdef NO_APPLE_PATENT
+
+ if ( ABS( CUR.F_dot_P ) > APPLE_THRESHOLD )
+ zone->cur[point].x += distance;
+
+#else
+
+ zone->cur[point].x += TT_MULDIV( distance,
+ v * 0x10000L,
+ CUR.F_dot_P );
+
+#endif
+
+ zone->tags[point] |= FT_Curve_Tag_Touch_X;
+ }
+
+ v = CUR.GS.freeVector.y;
+
+ if ( v != 0 )
+ {
+
+#ifdef NO_APPLE_PATENT
+
+ if ( ABS( CUR.F_dot_P ) > APPLE_THRESHOLD )
+ zone->cur[point].y += distance;
+
+#else
+
+ zone->cur[point].y += TT_MULDIV( distance,
+ v * 0x10000L,
+ CUR.F_dot_P );
+
+#endif
+
+ zone->tags[point] |= FT_Curve_Tag_Touch_Y;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Special versions of Direct_Move() */
+ /* */
+ /* The following versions are used whenever both vectors are both */
+ /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
+ /* */
+ /*************************************************************************/
+
+
+ static
+ void Direct_Move_X( EXEC_OP_ TT_GlyphZone* zone,
+ FT_UShort point,
+ FT_F26Dot6 distance )
+ {
+ FT_UNUSED_EXEC;
+
+ zone->cur[point].x += distance;
+ zone->tags[point] |= FT_Curve_Tag_Touch_X;
+ }
+
+
+ static
+ void Direct_Move_Y( EXEC_OP_ TT_GlyphZone* zone,
+ FT_UShort point,
+ FT_F26Dot6 distance )
+ {
+ FT_UNUSED_EXEC;
+
+ zone->cur[point].y += distance;
+ zone->tags[point] |= FT_Curve_Tag_Touch_Y;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_None */
+ /* */
+ /* <Description> */
+ /* Does not round, but adds engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance (not) to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* The compensated distance. */
+ /* */
+ /* <Note> */
+ /* The TrueType specification says very few about the relationship */
+ /* between rounding and engine compensation. However, it seems from */
+ /* the description of super round that we should add the compensation */
+ /* before rounding. */
+ /* */
+ static
+ FT_F26Dot6 Round_None( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+ FT_UNUSED_EXEC;
+
+
+ if ( distance >= 0 )
+ {
+ val = distance + compensation;
+ if ( val < 0 )
+ val = 0;
+ }
+ else {
+ val = distance - compensation;
+ if ( val > 0 )
+ val = 0;
+ }
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_To_Grid */
+ /* */
+ /* <Description> */
+ /* Rounds value to grid after adding engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* Rounded distance. */
+ /* */
+ static
+ FT_F26Dot6 Round_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+ FT_UNUSED_EXEC;
+
+
+ if ( distance >= 0 )
+ {
+ val = distance + compensation + 32;
+ if ( val > 0 )
+ val &= ~63;
+ else
+ val = 0;
+ }
+ else
+ {
+ val = -( ( compensation - distance + 32 ) & -64 );
+ if ( val > 0 )
+ val = 0;
+ }
+
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_To_Half_Grid */
+ /* */
+ /* <Description> */
+ /* Rounds value to half grid after adding engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* Rounded distance. */
+ /* */
+ static
+ FT_F26Dot6 Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+ FT_UNUSED_EXEC;
+
+
+ if ( distance >= 0 )
+ {
+ val = ( ( distance + compensation ) & -64 ) + 32;
+ if ( val < 0 )
+ val = 0;
+ }
+ else
+ {
+ val = -( ( (compensation - distance) & -64 ) + 32 );
+ if ( val > 0 )
+ val = 0;
+ }
+
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_Down_To_Grid */
+ /* */
+ /* <Description> */
+ /* Rounds value down to grid after adding engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* Rounded distance. */
+ /* */
+ static
+ FT_F26Dot6 Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+ FT_UNUSED_EXEC;
+
+
+ if ( distance >= 0 )
+ {
+ val = distance + compensation;
+ if ( val > 0 )
+ val &= ~63;
+ else
+ val = 0;
+ }
+ else
+ {
+ val = -( ( compensation - distance ) & -64 );
+ if ( val > 0 )
+ val = 0;
+ }
+
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_Up_To_Grid */
+ /* */
+ /* <Description> */
+ /* Rounds value up to grid after adding engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* Rounded distance. */
+ /* */
+ static
+ FT_F26Dot6 Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+
+ FT_UNUSED_EXEC;
+
+ if ( distance >= 0 )
+ {
+ val = distance + compensation + 63;
+ if ( val > 0 )
+ val &= ~63;
+ else
+ val = 0;
+ }
+ else
+ {
+ val = -( ( compensation - distance + 63 ) & -64 );
+ if ( val > 0 )
+ val = 0;
+ }
+
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_To_Double_Grid */
+ /* */
+ /* <Description> */
+ /* Rounds value to double grid after adding engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* Rounded distance. */
+ /* */
+ static
+ FT_F26Dot6 Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+ FT_UNUSED_EXEC;
+
+
+ if ( distance >= 0 )
+ {
+ val = distance + compensation + 16;
+ if ( val > 0 )
+ val &= ~31;
+ else
+ val = 0;
+ }
+ else
+ {
+ val = -( ( compensation - distance + 16 ) & -32 );
+ if ( val > 0 )
+ val = 0;
+ }
+
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_Super */
+ /* */
+ /* <Description> */
+ /* Super-rounds value to grid after adding engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* Rounded distance. */
+ /* */
+ /* <Note> */
+ /* The TrueType specification says very few about the relationship */
+ /* between rounding and engine compensation. However, it seems from */
+ /* the description of super round that we should add the compensation */
+ /* before rounding. */
+ /* */
+ static
+ FT_F26Dot6 Round_Super( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+
+ if ( distance >= 0 )
+ {
+ val = ( distance - CUR.phase + CUR.threshold + compensation ) &
+ -CUR.period;
+ if ( val < 0 )
+ val = 0;
+ val += CUR.phase;
+ }
+ else
+ {
+ val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &
+ -CUR.period );
+ if ( val > 0 )
+ val = 0;
+ val -= CUR.phase;
+ }
+
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_Super_45 */
+ /* */
+ /* <Description> */
+ /* Super-rounds value to grid after adding engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* Rounded distance. */
+ /* */
+ /* <Note> */
+ /* There is a separate function for Round_Super_45() as we may need */
+ /* greater precision. */
+ /* */
+ static
+ FT_F26Dot6 Round_Super_45( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+
+ if ( distance >= 0 )
+ {
+ val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /
+ CUR.period ) * CUR.period;
+ if ( val < 0 )
+ val = 0;
+ val += CUR.phase;
+ }
+ else
+ {
+ val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /
+ CUR.period ) * CUR.period );
+ if ( val > 0 )
+ val = 0;
+ val -= CUR.phase;
+ }
+
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Compute_Round */
+ /* */
+ /* <Description> */
+ /* Sets the rounding mode. */
+ /* */
+ /* <Input> */
+ /* round_mode :: The rounding mode to be used. */
+ /* */
+ static
+ void Compute_Round( EXEC_OP_ FT_Byte round_mode )
+ {
+ switch ( round_mode )
+ {
+ case TT_Round_Off:
+ CUR.func_round = (TT_Round_Func)Round_None;
+ break;
+
+ case TT_Round_To_Grid:
+ CUR.func_round = (TT_Round_Func)Round_To_Grid;
+ break;
+
+ case TT_Round_Up_To_Grid:
+ CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
+ break;
+
+ case TT_Round_Down_To_Grid:
+ CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
+ break;
+
+ case TT_Round_To_Half_Grid:
+ CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
+ break;
+
+ case TT_Round_To_Double_Grid:
+ CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
+ break;
+
+ case TT_Round_Super:
+ CUR.func_round = (TT_Round_Func)Round_Super;
+ break;
+
+ case TT_Round_Super_45:
+ CUR.func_round = (TT_Round_Func)Round_Super_45;
+ break;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* SetSuperRound */
+ /* */
+ /* <Description> */
+ /* Sets Super Round parameters. */
+ /* */
+ /* <Input> */
+ /* GridPeriod :: Grid period */
+ /* selector :: SROUND opcode */
+ /* */
+ static
+ void SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod,
+ FT_Long selector )
+ {
+ switch ( (FT_Int)( selector & 0xC0 ) )
+ {
+ case 0:
+ CUR.period = GridPeriod / 2;
+ break;
+
+ case 0x40:
+ CUR.period = GridPeriod;
+ break;
+
+ case 0x80:
+ CUR.period = GridPeriod * 2;
+ break;
+
+ /* This opcode is reserved, but... */
+
+ case 0xC0:
+ CUR.period = GridPeriod;
+ break;
+ }
+
+ switch ( (FT_Int)( selector & 0x30 ) )
+ {
+ case 0:
+ CUR.phase = 0;
+ break;
+
+ case 0x10:
+ CUR.phase = CUR.period / 4;
+ break;
+
+ case 0x20:
+ CUR.phase = CUR.period / 2;
+ break;
+
+ case 0x30:
+ CUR.phase = GridPeriod * 3 / 4;
+ break;
+ }
+
+ if ( (selector & 0x0F) == 0 )
+ CUR.threshold = CUR.period - 1;
+ else
+ CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;
+
+ CUR.period /= 256;
+ CUR.phase /= 256;
+ CUR.threshold /= 256;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Project */
+ /* */
+ /* <Description> */
+ /* Computes the projection of vector given by (v2-v1) along the */
+ /* current projection vector. */
+ /* */
+ /* <Input> */
+ /* v1 :: First input vector. */
+ /* v2 :: Second input vector. */
+ /* */
+ /* <Return> */
+ /* The distance in F26dot6 format. */
+ /* */
+ static
+ FT_F26Dot6 Project( EXEC_OP_ FT_Vector* v1,
+ FT_Vector* v2 )
+ {
+ return TT_MULDIV( v1->x - v2->x, CUR.GS.projVector.x, 0x4000 ) +
+ TT_MULDIV( v1->y - v2->y, CUR.GS.projVector.y, 0x4000 );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Dual_Project */
+ /* */
+ /* <Description> */
+ /* Computes the projection of the vector given by (v2-v1) along the */
+ /* current dual vector. */
+ /* */
+ /* <Input> */
+ /* v1 :: First input vector. */
+ /* v2 :: Second input vector. */
+ /* */
+ /* <Return> */
+ /* The distance in F26dot6 format. */
+ /* */
+ static
+ FT_F26Dot6 Dual_Project( EXEC_OP_ FT_Vector* v1,
+ FT_Vector* v2 )
+ {
+ return TT_MULDIV( v1->x - v2->x, CUR.GS.dualVector.x, 0x4000 ) +
+ TT_MULDIV( v1->y - v2->y, CUR.GS.dualVector.y, 0x4000 );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Free_Project */
+ /* */
+ /* <Description> */
+ /* Computes the projection of the vector given by (v2-v1) along the */
+ /* current freedom vector. */
+ /* */
+ /* <Input> */
+ /* v1 :: First input vector. */
+ /* v2 :: Second input vector. */
+ /* */
+ /* <Return> */
+ /* The distance in F26dot6 format. */
+ /* */
+ static
+ FT_F26Dot6 Free_Project( EXEC_OP_ FT_Vector* v1,
+ FT_Vector* v2 )
+ {
+ return TT_MULDIV( v1->x - v2->x, CUR.GS.freeVector.x, 0x4000 ) +
+ TT_MULDIV( v1->y - v2->y, CUR.GS.freeVector.y, 0x4000 );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Project_x */
+ /* */
+ /* <Description> */
+ /* Computes the projection of the vector given by (v2-v1) along the */
+ /* horizontal axis. */
+ /* */
+ /* <Input> */
+ /* v1 :: First input vector. */
+ /* v2 :: Second input vector. */
+ /* */
+ /* <Return> */
+ /* The distance in F26dot6 format. */
+ /* */
+ static
+ FT_F26Dot6 Project_x( EXEC_OP_ FT_Vector* v1,
+ FT_Vector* v2 )
+ {
+ FT_UNUSED_EXEC;
+
+ return ( v1->x - v2->x );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Project_y */
+ /* */
+ /* <Description> */
+ /* Computes the projection of the vector given by (v2-v1) along the */
+ /* vertical axis. */
+ /* */
+ /* <Input> */
+ /* v1 :: First input vector. */
+ /* v2 :: Second input vector. */
+ /* */
+ /* <Return> */
+ /* The distance in F26dot6 format. */
+ /* */
+ static
+ FT_F26Dot6 Project_y( EXEC_OP_ FT_Vector* v1,
+ FT_Vector* v2 )
+ {
+ FT_UNUSED_EXEC;
+
+ return ( v1->y - v2->y );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Compute_Funcs */
+ /* */
+ /* <Description> */
+ /* Computes the projection and movement function pointers according */
+ /* to the current graphics state. */
+ /* */
+ static
+ void Compute_Funcs( EXEC_OP )
+ {
+ if ( CUR.GS.freeVector.x == 0x4000 )
+ {
+ CUR.func_freeProj = (TT_Project_Func)Project_x;
+ CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L;
+ }
+ else
+ {
+ if ( CUR.GS.freeVector.y == 0x4000 )
+ {
+ CUR.func_freeProj = (TT_Project_Func)Project_y;
+ CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L;
+ }
+ else
+ {
+ CUR.func_freeProj = (TT_Project_Func)Free_Project;
+ CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +
+ (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;
+ }
+ }
+
+ if ( CUR.GS.projVector.x == 0x4000 )
+ CUR.func_project = (TT_Project_Func)Project_x;
+ else
+ {
+ if ( CUR.GS.projVector.y == 0x4000 )
+ CUR.func_project = (TT_Project_Func)Project_y;
+ else
+ CUR.func_project = (TT_Project_Func)Project;
+ }
+
+ if ( CUR.GS.dualVector.x == 0x4000 )
+ CUR.func_dualproj = (TT_Project_Func)Project_x;
+ else
+ {
+ if ( CUR.GS.dualVector.y == 0x4000 )
+ CUR.func_dualproj = (TT_Project_Func)Project_y;
+ else
+ CUR.func_dualproj = (TT_Project_Func)Dual_Project;
+ }
+
+ CUR.func_move = (TT_Move_Func)Direct_Move;
+
+ if ( CUR.F_dot_P == 0x40000000L )
+ {
+ if ( CUR.GS.freeVector.x == 0x4000 )
+ CUR.func_move = (TT_Move_Func)Direct_Move_X;
+ else
+ {
+ if ( CUR.GS.freeVector.y == 0x4000 )
+ CUR.func_move = (TT_Move_Func)Direct_Move_Y;
+ }
+ }
+
+ /* at small sizes, F_dot_P can become too small, resulting */
+ /* in overflows and `spikes' in a number of glyphs like `w'. */
+
+ if ( ABS( CUR.F_dot_P ) < 0x4000000L )
+ CUR.F_dot_P = 0x40000000L;
+
+ /* Disable cached aspect ratio */
+ CUR.tt_metrics.ratio = 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Normalize */
+ /* */
+ /* <Description> */
+ /* Norms a vector. */
+ /* */
+ /* <Input> */
+ /* Vx :: The horizontal input vector coordinate. */
+ /* Vy :: The vertical input vector coordinate. */
+ /* */
+ /* <Output> */
+ /* R :: The normed unit vector. */
+ /* */
+ /* <Return> */
+ /* Returns FAILURE if a vector parameter is zero. */
+ /* */
+ /* <Note> */
+ /* In case Vx and Vy are both zero, Normalize() returns SUCCESS, and */
+ /* R is undefined. */
+ /* */
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+ static
+ FT_Bool Normalize( EXEC_OP_ FT_F26Dot6 Vx,
+ FT_F26Dot6 Vy,
+ FT_UnitVector* R )
+ {
+ FT_F26Dot6 W;
+ FT_Bool S1, S2;
+
+ FT_UNUSED_EXEC;
+
+
+ if ( ABS( Vx ) < 0x10000L && ABS( Vy ) < 0x10000L )
+ {
+ Vx *= 0x100;
+ Vy *= 0x100;
+
+ W = Norm( Vx, Vy );
+
+ if ( W == 0 )
+ {
+ /* XXX: UNDOCUMENTED! It seems that it is possible to try */
+ /* to normalize the vector (0,0). Return immediately. */
+ return SUCCESS;
+ }
+
+ R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );
+ R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );
+
+ return SUCCESS;
+ }
+
+ W = Norm( Vx, Vy );
+
+ Vx = FT_MulDiv( Vx, 0x4000L, W );
+ Vy = FT_MulDiv( Vy, 0x4000L, W );
+
+ W = Vx * Vx + Vy * Vy;
+
+ /* Now, we want that Sqrt( W ) = 0x4000 */
+ /* Or 0x1000000 <= W < 0x1004000 */
+
+ if ( Vx < 0 )
+ {
+ Vx = -Vx;
+ S1 = TRUE;
+ }
+ else
+ S1 = FALSE;
+
+ if ( Vy < 0 )
+ {
+ Vy = -Vy;
+ S2 = TRUE;
+ }
+ else
+ S2 = FALSE;
+
+ while ( W < 0x1000000L )
+ {
+ /* We need to increase W by a minimal amount */
+ if ( Vx < Vy )
+ Vx++;
+ else
+ Vy++;
+
+ W = Vx * Vx + Vy * Vy;
+ }
+
+ while ( W >= 0x1004000L )
+ {
+ /* We need to decrease W by a minimal amount */
+ if ( Vx < Vy )
+ Vx--;
+ else
+ Vy--;
+
+ W = Vx * Vx + Vy * Vy;
+ }
+
+ /* Note that in various cases, we can only */
+ /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */
+
+ if ( S1 )
+ Vx = -Vx;
+
+ if ( S2 )
+ Vy = -Vy;
+
+ R->x = (FT_F2Dot14)Vx; /* Type conversion */
+ R->y = (FT_F2Dot14)Vy; /* Type conversion */
+
+ return SUCCESS;
+ }
+
+#else
+
+ static
+ FT_Bool Normalize( EXEC_OP_ FT_F26Dot6 Vx,
+ FT_F26Dot6 Vy,
+ FT_UnitVector* R )
+ {
+ FT_F26Dot6 u, v, d;
+ FT_Int shift;
+ FT_ULong H, L, L2, hi, lo, med;
+
+
+ u = ABS( Vx );
+ v = ABS( Vy );
+
+ if ( u < v )
+ {
+ d = u;
+ u = v;
+ v = d;
+ }
+
+ R->x = 0;
+ R->y = 0;
+
+ /* check that we are not trying to normalise zero! */
+ if ( u == 0 )
+ return SUCCESS;
+
+ /* compute (u*u + v*v) on 64 bits with two 32-bit registers [H:L] */
+ hi = (FT_ULong)u >> 16;
+ lo = (FT_ULong)u & 0xFFFF;
+ med = hi * lo;
+
+ H = hi * hi + ( med >> 15 );
+ med <<= 17;
+ L = lo * lo + med;
+ if ( L < med )
+ H++;
+
+ hi = (FT_ULong)v >> 16;
+ lo = (FT_ULong)v & 0xFFFF;
+ med = hi * lo;
+
+ H += hi * hi + ( med >> 15 );
+ med <<= 17;
+ L2 = lo * lo + med;
+ if ( L2 < med )
+ H++;
+
+ L += L2;
+ if ( L < L2 )
+ H++;
+
+ /* if the value is smaller than 32-bits */
+ if ( H == 0 )
+ {
+ shift = 0;
+ while ( ( L & 0xC0000000L ) == 0 )
+ {
+ L <<= 2;
+ shift++;
+ }
+
+ d = FT_Sqrt32( L );
+ R->x = (FT_F2Dot14)TT_MULDIV( Vx << shift, 0x4000, d );
+ R->y = (FT_F2Dot14)TT_MULDIV( Vy << shift, 0x4000, d );
+ }
+ /* if the value is greater than 64-bits */
+ else
+ {
+ shift = 0;
+ while ( H )
+ {
+ L = ( L >> 2 ) | ( H << 30 );
+ H >>= 2;
+ shift++;
+ }
+
+ d = FT_Sqrt32( L );
+ R->x = (FT_F2Dot14)TT_MULDIV( Vx >> shift, 0x4000, d );
+ R->y = (FT_F2Dot14)TT_MULDIV( Vy >> shift, 0x4000, d );
+ }
+
+ {
+ FT_ULong x, y, w;
+ FT_Int sx, sy;
+
+
+ sx = R->x >= 0 ? 1 : -1;
+ sy = R->y >= 0 ? 1 : -1;
+ x = (FT_ULong)sx * R->x;
+ y = (FT_ULong)sy * R->y;
+
+ w = x * x + y * y;
+
+ /* we now want to adjust (x,y) in order to have sqrt(w) == 0x4000 */
+ /* which means 0x1000000 <= w < 0x1004000 */
+ while ( w <= 0x10000000L )
+ {
+ /* increment the smallest coordinate */
+ if ( x < y )
+ x++;
+ else
+ y++;
+
+ w = x * x + y * y;
+ }
+
+ while ( w >= 0x10040000L )
+ {
+ /* decrement the smallest coordinate */
+ if ( x < y )
+ x--;
+ else
+ y--;
+
+ w = x * x + y * y;
+ }
+
+ R->x = sx * x;
+ R->y = sy * y;
+ }
+
+ return SUCCESS;
+ }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+ /*************************************************************************/
+ /* */
+ /* Here we start with the implementation of the various opcodes. */
+ /* */
+ /*************************************************************************/
+
+
+ static
+ FT_Bool Ins_SxVTL( EXEC_OP_ FT_UShort aIdx1,
+ FT_UShort aIdx2,
+ FT_Int aOpc,
+ FT_UnitVector* Vec )
+ {
+ FT_Long A, B, C;
+ FT_Vector* p1;
+ FT_Vector* p2;
+
+
+ if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
+ BOUNDS( aIdx2, CUR.zp1.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return FAILURE;
+ }
+
+ p1 = CUR.zp1.cur + aIdx2;
+ p2 = CUR.zp2.cur + aIdx1;
+
+ A = p1->x - p2->x;
+ B = p1->y - p2->y;
+
+ if ( ( aOpc & 1 ) != 0 )
+ {
+ C = B; /* counter clockwise rotation */
+ B = A;
+ A = -C;
+ }
+
+ NORMalize( A, B, Vec );
+
+ return SUCCESS;
+ }
+
+
+ /* When not using the big switch statements, the interpreter uses a */
+ /* call table defined later below in this source. Each opcode must */
+ /* thus have a corresponding function, even trivial ones. */
+ /* */
+ /* They are all defined there. */
+
+#define DO_SVTCA \
+ { \
+ FT_Short A, B; \
+ \
+ \
+ A = (FT_Short)( CUR.opcode & 1 ) << 14; \
+ B = A ^ (FT_Short)0x4000; \
+ \
+ CUR.GS.freeVector.x = A; \
+ CUR.GS.projVector.x = A; \
+ CUR.GS.dualVector.x = A; \
+ \
+ CUR.GS.freeVector.y = B; \
+ CUR.GS.projVector.y = B; \
+ CUR.GS.dualVector.y = B; \
+ \
+ COMPUTE_Funcs(); \
+ }
+
+
+#define DO_SPVTCA \
+ { \
+ FT_Short A, B; \
+ \
+ \
+ A = (FT_Short)( CUR.opcode & 1 ) << 14; \
+ B = A ^ (FT_Short)0x4000; \
+ \
+ CUR.GS.projVector.x = A; \
+ CUR.GS.dualVector.x = A; \
+ \
+ CUR.GS.projVector.y = B; \
+ CUR.GS.dualVector.y = B; \
+ \
+ COMPUTE_Funcs(); \
+ }
+
+
+#define DO_SFVTCA \
+ { \
+ FT_Short A, B; \
+ \
+ \
+ A = (FT_Short)( CUR.opcode & 1 ) << 14; \
+ B = A ^ (FT_Short)0x4000; \
+ \
+ CUR.GS.freeVector.x = A; \
+ CUR.GS.freeVector.y = B; \
+ \
+ COMPUTE_Funcs(); \
+ }
+
+
+#define DO_SPVTL \
+ if ( INS_SxVTL( (FT_UShort)args[1], \
+ (FT_UShort)args[0], \
+ CUR.opcode, \
+ &CUR.GS.projVector ) == SUCCESS ) \
+ { \
+ CUR.GS.dualVector = CUR.GS.projVector; \
+ COMPUTE_Funcs(); \
+ }
+
+
+#define DO_SFVTL \
+ if ( INS_SxVTL( (FT_UShort)args[1], \
+ (FT_UShort)args[0], \
+ CUR.opcode, \
+ &CUR.GS.freeVector ) == SUCCESS ) \
+ COMPUTE_Funcs();
+
+
+#define DO_SFVTPV \
+ CUR.GS.freeVector = CUR.GS.projVector; \
+ COMPUTE_Funcs();
+
+
+#define DO_SPVFS \
+ { \
+ FT_Short S; \
+ FT_Long X, Y; \
+ \
+ \
+ /* Only use low 16bits, then sign extend */ \
+ S = (FT_Short)args[1]; \
+ Y = (FT_Long)S; \
+ S = (FT_Short)args[0]; \
+ X = (FT_Long)S; \
+ \
+ NORMalize( X, Y, &CUR.GS.projVector ); \
+ \
+ CUR.GS.dualVector = CUR.GS.projVector; \
+ COMPUTE_Funcs(); \
+ }
+
+
+#define DO_SFVFS \
+ { \
+ FT_Short S; \
+ FT_Long X, Y; \
+ \
+ \
+ /* Only use low 16bits, then sign extend */ \
+ S = (FT_Short)args[1]; \
+ Y = (FT_Long)S; \
+ S = (FT_Short)args[0]; \
+ X = S; \
+ \
+ NORMalize( X, Y, &CUR.GS.freeVector ); \
+ COMPUTE_Funcs(); \
+ }
+
+
+#define DO_GPV \
+ args[0] = CUR.GS.projVector.x; \
+ args[1] = CUR.GS.projVector.y;
+
+
+#define DO_GFV \
+ args[0] = CUR.GS.freeVector.x; \
+ args[1] = CUR.GS.freeVector.y;
+
+
+#define DO_SRP0 \
+ CUR.GS.rp0 = (FT_UShort)args[0];
+
+
+#define DO_SRP1 \
+ CUR.GS.rp1 = (FT_UShort)args[0];
+
+
+#define DO_SRP2 \
+ CUR.GS.rp2 = (FT_UShort)args[0];
+
+
+#define DO_RTHG \
+ CUR.GS.round_state = TT_Round_To_Half_Grid; \
+ CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
+
+
+#define DO_RTG \
+ CUR.GS.round_state = TT_Round_To_Grid; \
+ CUR.func_round = (TT_Round_Func)Round_To_Grid;
+
+
+#define DO_RTDG \
+ CUR.GS.round_state = TT_Round_To_Double_Grid; \
+ CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
+
+
+#define DO_RUTG \
+ CUR.GS.round_state = TT_Round_Up_To_Grid; \
+ CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
+
+
+#define DO_RDTG \
+ CUR.GS.round_state = TT_Round_Down_To_Grid; \
+ CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
+
+
+#define DO_ROFF \
+ CUR.GS.round_state = TT_Round_Off; \
+ CUR.func_round = (TT_Round_Func)Round_None;
+
+
+#define DO_SROUND \
+ SET_SuperRound( 0x4000, args[0] ); \
+ CUR.GS.round_state = TT_Round_Super; \
+ CUR.func_round = (TT_Round_Func)Round_Super;
+
+
+#define DO_S45ROUND \
+ SET_SuperRound( 0x2D41, args[0] ); \
+ CUR.GS.round_state = TT_Round_Super_45; \
+ CUR.func_round = (TT_Round_Func)Round_Super_45;
+
+
+#define DO_SLOOP \
+ if ( args[0] < 0 ) \
+ CUR.error = TT_Err_Bad_Argument; \
+ else \
+ CUR.GS.loop = args[0];
+
+
+#define DO_SMD \
+ CUR.GS.minimum_distance = args[0];
+
+
+#define DO_SCVTCI \
+ CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];
+
+
+#define DO_SSWCI \
+ CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
+
+
+ /* XXX: UNDOCUMENTED! or bug in the Windows engine? */
+ /* */
+ /* It seems that the value that is read here is */
+ /* expressed in 16.16 format rather than in font */
+ /* units. */
+ /* */
+#define DO_SSW \
+ CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );
+
+
+#define DO_FLIPON \
+ CUR.GS.auto_flip = TRUE;
+
+
+#define DO_FLIPOFF \
+ CUR.GS.auto_flip = FALSE;
+
+
+#define DO_SDB \
+ CUR.GS.delta_base = (FT_Short)args[0];
+
+
+#define DO_SDS \
+ CUR.GS.delta_shift = (FT_Short)args[0];
+
+
+#define DO_MD /* nothing */
+
+
+#define DO_MPPEM \
+ args[0] = CURRENT_Ppem();
+
+
+ /* Note: The pointSize should be irrelevant in a given font program; */
+ /* we thus decide to return only the ppem. */
+#if 0
+
+#define DO_MPS \
+ args[0] = CUR.metrics.pointSize;
+
+#else
+
+#define DO_MPS \
+ args[0] = CURRENT_Ppem();
+
+#endif /* 0 */
+
+
+#define DO_DUP \
+ args[1] = args[0];
+
+
+#define DO_CLEAR \
+ CUR.new_top = 0;
+
+
+#define DO_SWAP \
+ { \
+ FT_Long L; \
+ \
+ \
+ L = args[0]; \
+ args[0] = args[1]; \
+ args[1] = L; \
+ }
+
+
+#define DO_DEPTH \
+ args[0] = CUR.top;
+
+
+#define DO_CINDEX \
+ { \
+ FT_Long L; \
+ \
+ \
+ L = args[0]; \
+ \
+ if ( L <= 0 || L > CUR.args ) \
+ CUR.error = TT_Err_Invalid_Reference; \
+ else \
+ args[0] = CUR.stack[CUR.args - L]; \
+ }
+
+
+#define DO_JROT \
+ if ( args[1] != 0 ) \
+ { \
+ CUR.IP += args[0]; \
+ CUR.step_ins = FALSE; \
+ }
+
+
+#define DO_JMPR \
+ CUR.IP += args[0]; \
+ CUR.step_ins = FALSE;
+
+
+#define DO_JROF \
+ if ( args[1] == 0 ) \
+ { \
+ CUR.IP += args[0]; \
+ CUR.step_ins = FALSE; \
+ }
+
+
+#define DO_LT \
+ args[0] = ( args[0] < args[1] );
+
+
+#define DO_LTEQ \
+ args[0] = ( args[0] <= args[1] );
+
+
+#define DO_GT \
+ args[0] = ( args[0] > args[1] );
+
+
+#define DO_GTEQ \
+ args[0] = ( args[0] >= args[1] );
+
+
+#define DO_EQ \
+ args[0] = ( args[0] == args[1] );
+
+
+#define DO_NEQ \
+ args[0] = ( args[0] != args[1] );
+
+
+#define DO_ODD \
+ args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );
+
+
+#define DO_EVEN \
+ args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );
+
+
+#define DO_AND \
+ args[0] = ( args[0] && args[1] );
+
+
+#define DO_OR \
+ args[0] = ( args[0] || args[1] );
+
+
+#define DO_NOT \
+ args[0] = !args[0];
+
+
+#define DO_ADD \
+ args[0] += args[1];
+
+
+#define DO_SUB \
+ args[0] -= args[1];
+
+
+#define DO_DIV \
+ if ( args[1] == 0 ) \
+ CUR.error = TT_Err_Divide_By_Zero; \
+ else \
+ args[0] = TT_MULDIV( args[0], 64L, args[1] );
+
+
+#define DO_MUL \
+ args[0] = TT_MULDIV( args[0], args[1], 64L );
+
+
+#define DO_ABS \
+ args[0] = ABS( args[0] );
+
+
+#define DO_NEG \
+ args[0] = -args[0];
+
+
+#define DO_FLOOR \
+ args[0] &= -64;
+
+
+#define DO_CEILING \
+ args[0] = ( args[0] + 63 ) & -64;
+
+
+#define DO_RS \
+ { \
+ FT_ULong I = (FT_ULong)args[0]; \
+ \
+ \
+ if ( BOUNDS( I, CUR.storeSize ) ) \
+ { \
+ if ( CUR.pedantic_hinting ) \
+ { \
+ ARRAY_BOUND_ERROR; \
+ } \
+ else \
+ args[0] = 0; \
+ } \
+ else \
+ args[0] = CUR.storage[I]; \
+ }
+
+
+#define DO_WS \
+ { \
+ FT_ULong I = (FT_ULong)args[0]; \
+ \
+ \
+ if ( BOUNDS( I, CUR.storeSize ) ) \
+ { \
+ if ( CUR.pedantic_hinting ) \
+ { \
+ ARRAY_BOUND_ERROR; \
+ } \
+ } \
+ else \
+ CUR.storage[I] = args[1]; \
+ }
+
+
+#define DO_RCVT \
+ { \
+ FT_ULong I = (FT_ULong)args[0]; \
+ \
+ \
+ if ( BOUNDS( I, CUR.cvtSize ) ) \
+ { \
+ if ( CUR.pedantic_hinting ) \
+ { \
+ ARRAY_BOUND_ERROR; \
+ } \
+ else \
+ args[0] = 0; \
+ } \
+ else \
+ args[0] = CUR_Func_read_cvt( I ); \
+ }
+
+
+#define DO_WCVTP \
+ { \
+ FT_ULong I = (FT_ULong)args[0]; \
+ \
+ \
+ if ( BOUNDS( I, CUR.cvtSize ) ) \
+ { \
+ if ( CUR.pedantic_hinting ) \
+ { \
+ ARRAY_BOUND_ERROR; \
+ } \
+ } \
+ else \
+ CUR_Func_write_cvt( I, args[1] ); \
+ }
+
+
+#define DO_WCVTF \
+ { \
+ FT_ULong I = (FT_ULong)args[0]; \
+ \
+ \
+ if ( BOUNDS( I, CUR.cvtSize ) ) \
+ { \
+ if ( CUR.pedantic_hinting ) \
+ { \
+ ARRAY_BOUND_ERROR; \
+ } \
+ } \
+ else \
+ CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \
+ }
+
+
+#define DO_DEBUG \
+ CUR.error = TT_Err_Debug_OpCode;
+
+
+#define DO_ROUND \
+ args[0] = CUR_Func_round( \
+ args[0], \
+ CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
+
+
+#define DO_NROUND \
+ args[0] = ROUND_None( args[0], \
+ CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );
+
+
+#define DO_MAX \
+ if ( args[1] > args[0] ) \
+ args[0] = args[1];
+
+
+#define DO_MIN \
+ if ( args[1] < args[0] ) \
+ args[0] = args[1];
+
+
+#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+
+#undef ARRAY_BOUND_ERROR
+#define ARRAY_BOUND_ERROR \
+ { \
+ CUR.error = TT_Err_Invalid_Reference; \
+ return; \
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */
+ /* Opcode range: 0x00-0x01 */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_SVTCA( INS_ARG )
+ {
+ DO_SVTCA
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SPVTCA[a]: Set PVector to Coordinate Axis */
+ /* Opcode range: 0x02-0x03 */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_SPVTCA( INS_ARG )
+ {
+ DO_SPVTCA
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SFVTCA[a]: Set FVector to Coordinate Axis */
+ /* Opcode range: 0x04-0x05 */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_SFVTCA( INS_ARG )
+ {
+ DO_SFVTCA
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SPVTL[a]: Set PVector To Line */
+ /* Opcode range: 0x06-0x07 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static
+ void Ins_SPVTL( INS_ARG )
+ {
+ DO_SPVTL
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SFVTL[a]: Set FVector To Line */
+ /* Opcode range: 0x08-0x09 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static
+ void Ins_SFVTL( INS_ARG )
+ {
+ DO_SFVTL
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SFVTPV[]: Set FVector To PVector */
+ /* Opcode range: 0x0E */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_SFVTPV( INS_ARG )
+ {
+ DO_SFVTPV
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SPVFS[]: Set PVector From Stack */
+ /* Opcode range: 0x0A */
+ /* Stack: f2.14 f2.14 --> */
+ /* */
+ static
+ void Ins_SPVFS( INS_ARG )
+ {
+ DO_SPVFS
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SFVFS[]: Set FVector From Stack */
+ /* Opcode range: 0x0B */
+ /* Stack: f2.14 f2.14 --> */
+ /* */
+ static
+ void Ins_SFVFS( INS_ARG )
+ {
+ DO_SFVFS
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* GPV[]: Get Projection Vector */
+ /* Opcode range: 0x0C */
+ /* Stack: ef2.14 --> ef2.14 */
+ /* */
+ static
+ void Ins_GPV( INS_ARG )
+ {
+ DO_GPV
+ }
+
+
+ /*************************************************************************/
+ /* GFV[]: Get Freedom Vector */
+ /* Opcode range: 0x0D */
+ /* Stack: ef2.14 --> ef2.14 */
+ /* */
+ static
+ void Ins_GFV( INS_ARG )
+ {
+ DO_GFV
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SRP0[]: Set Reference Point 0 */
+ /* Opcode range: 0x10 */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_SRP0( INS_ARG )
+ {
+ DO_SRP0
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SRP1[]: Set Reference Point 1 */
+ /* Opcode range: 0x11 */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_SRP1( INS_ARG )
+ {
+ DO_SRP1
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SRP2[]: Set Reference Point 2 */
+ /* Opcode range: 0x12 */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_SRP2( INS_ARG )
+ {
+ DO_SRP2
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RTHG[]: Round To Half Grid */
+ /* Opcode range: 0x19 */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_RTHG( INS_ARG )
+ {
+ DO_RTHG
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RTG[]: Round To Grid */
+ /* Opcode range: 0x18 */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_RTG( INS_ARG )
+ {
+ DO_RTG
+ }
+
+
+ /*************************************************************************/
+ /* RTDG[]: Round To Double Grid */
+ /* Opcode range: 0x3D */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_RTDG( INS_ARG )
+ {
+ DO_RTDG
+ }
+
+
+ /*************************************************************************/
+ /* RUTG[]: Round Up To Grid */
+ /* Opcode range: 0x7C */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_RUTG( INS_ARG )
+ {
+ DO_RUTG
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RDTG[]: Round Down To Grid */
+ /* Opcode range: 0x7D */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_RDTG( INS_ARG )
+ {
+ DO_RDTG
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ROFF[]: Round OFF */
+ /* Opcode range: 0x7A */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_ROFF( INS_ARG )
+ {
+ DO_ROFF
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SROUND[]: Super ROUND */
+ /* Opcode range: 0x76 */
+ /* Stack: Eint8 --> */
+ /* */
+ static
+ void Ins_SROUND( INS_ARG )
+ {
+ DO_SROUND
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* S45ROUND[]: Super ROUND 45 degrees */
+ /* Opcode range: 0x77 */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_S45ROUND( INS_ARG )
+ {
+ DO_S45ROUND
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SLOOP[]: Set LOOP variable */
+ /* Opcode range: 0x17 */
+ /* Stack: int32? --> */
+ /* */
+ static
+ void Ins_SLOOP( INS_ARG )
+ {
+ DO_SLOOP
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SMD[]: Set Minimum Distance */
+ /* Opcode range: 0x1A */
+ /* Stack: f26.6 --> */
+ /* */
+ static
+ void Ins_SMD( INS_ARG )
+ {
+ DO_SMD
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SCVTCI[]: Set Control Value Table Cut In */
+ /* Opcode range: 0x1D */
+ /* Stack: f26.6 --> */
+ /* */
+ static
+ void Ins_SCVTCI( INS_ARG )
+ {
+ DO_SCVTCI
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SSWCI[]: Set Single Width Cut In */
+ /* Opcode range: 0x1E */
+ /* Stack: f26.6 --> */
+ /* */
+ static
+ void Ins_SSWCI( INS_ARG )
+ {
+ DO_SSWCI
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SSW[]: Set Single Width */
+ /* Opcode range: 0x1F */
+ /* Stack: int32? --> */
+ /* */
+ static
+ void Ins_SSW( INS_ARG )
+ {
+ DO_SSW
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FLIPON[]: Set auto-FLIP to ON */
+ /* Opcode range: 0x4D */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_FLIPON( INS_ARG )
+ {
+ DO_FLIPON
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FLIPOFF[]: Set auto-FLIP to OFF */
+ /* Opcode range: 0x4E */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_FLIPOFF( INS_ARG )
+ {
+ DO_FLIPOFF
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SANGW[]: Set ANGle Weight */
+ /* Opcode range: 0x7E */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_SANGW( INS_ARG )
+ {
+ /* instruction not supported anymore */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SDB[]: Set Delta Base */
+ /* Opcode range: 0x5E */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_SDB( INS_ARG )
+ {
+ DO_SDB
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SDS[]: Set Delta Shift */
+ /* Opcode range: 0x5F */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_SDS( INS_ARG )
+ {
+ DO_SDS
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MPPEM[]: Measure Pixel Per EM */
+ /* Opcode range: 0x4B */
+ /* Stack: --> Euint16 */
+ /* */
+ static
+ void Ins_MPPEM( INS_ARG )
+ {
+ DO_MPPEM
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MPS[]: Measure Point Size */
+ /* Opcode range: 0x4C */
+ /* Stack: --> Euint16 */
+ /* */
+ static
+ void Ins_MPS( INS_ARG )
+ {
+ DO_MPS
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DUP[]: DUPlicate the top stack's element */
+ /* Opcode range: 0x20 */
+ /* Stack: StkElt --> StkElt StkElt */
+ /* */
+ static
+ void Ins_DUP( INS_ARG )
+ {
+ DO_DUP
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* POP[]: POP the stack's top element */
+ /* Opcode range: 0x21 */
+ /* Stack: StkElt --> */
+ /* */
+ static
+ void Ins_POP( INS_ARG )
+ {
+ /* nothing to do */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* CLEAR[]: CLEAR the entire stack */
+ /* Opcode range: 0x22 */
+ /* Stack: StkElt... --> */
+ /* */
+ static
+ void Ins_CLEAR( INS_ARG )
+ {
+ DO_CLEAR
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SWAP[]: SWAP the stack's top two elements */
+ /* Opcode range: 0x23 */
+ /* Stack: 2 * StkElt --> 2 * StkElt */
+ /* */
+ static
+ void Ins_SWAP( INS_ARG )
+ {
+ DO_SWAP
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DEPTH[]: return the stack DEPTH */
+ /* Opcode range: 0x24 */
+ /* Stack: --> uint32 */
+ /* */
+ static
+ void Ins_DEPTH( INS_ARG )
+ {
+ DO_DEPTH
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* CINDEX[]: Copy INDEXed element */
+ /* Opcode range: 0x25 */
+ /* Stack: int32 --> StkElt */
+ /* */
+ static
+ void Ins_CINDEX( INS_ARG )
+ {
+ DO_CINDEX
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* EIF[]: End IF */
+ /* Opcode range: 0x59 */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_EIF( INS_ARG )
+ {
+ /* nothing to do */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* JROT[]: Jump Relative On True */
+ /* Opcode range: 0x78 */
+ /* Stack: StkElt int32 --> */
+ /* */
+ static
+ void Ins_JROT( INS_ARG )
+ {
+ DO_JROT
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* JMPR[]: JuMP Relative */
+ /* Opcode range: 0x1C */
+ /* Stack: int32 --> */
+ /* */
+ static
+ void Ins_JMPR( INS_ARG )
+ {
+ DO_JMPR
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* JROF[]: Jump Relative On False */
+ /* Opcode range: 0x79 */
+ /* Stack: StkElt int32 --> */
+ /* */
+ static
+ void Ins_JROF( INS_ARG )
+ {
+ DO_JROF
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* LT[]: Less Than */
+ /* Opcode range: 0x50 */
+ /* Stack: int32? int32? --> bool */
+ /* */
+ static
+ void Ins_LT( INS_ARG )
+ {
+ DO_LT
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* LTEQ[]: Less Than or EQual */
+ /* Opcode range: 0x51 */
+ /* Stack: int32? int32? --> bool */
+ /* */
+ static
+ void Ins_LTEQ( INS_ARG )
+ {
+ DO_LTEQ
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* GT[]: Greater Than */
+ /* Opcode range: 0x52 */
+ /* Stack: int32? int32? --> bool */
+ /* */
+ static
+ void Ins_GT( INS_ARG )
+ {
+ DO_GT
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* GTEQ[]: Greater Than or EQual */
+ /* Opcode range: 0x53 */
+ /* Stack: int32? int32? --> bool */
+ /* */
+ static
+ void Ins_GTEQ( INS_ARG )
+ {
+ DO_GTEQ
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* EQ[]: EQual */
+ /* Opcode range: 0x54 */
+ /* Stack: StkElt StkElt --> bool */
+ /* */
+ static
+ void Ins_EQ( INS_ARG )
+ {
+ DO_EQ
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* NEQ[]: Not EQual */
+ /* Opcode range: 0x55 */
+ /* Stack: StkElt StkElt --> bool */
+ /* */
+ static
+ void Ins_NEQ( INS_ARG )
+ {
+ DO_NEQ
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ODD[]: Is ODD */
+ /* Opcode range: 0x56 */
+ /* Stack: f26.6 --> bool */
+ /* */
+ static
+ void Ins_ODD( INS_ARG )
+ {
+ DO_ODD
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* EVEN[]: Is EVEN */
+ /* Opcode range: 0x57 */
+ /* Stack: f26.6 --> bool */
+ /* */
+ static
+ void Ins_EVEN( INS_ARG )
+ {
+ DO_EVEN
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* AND[]: logical AND */
+ /* Opcode range: 0x5A */
+ /* Stack: uint32 uint32 --> uint32 */
+ /* */
+ static
+ void Ins_AND( INS_ARG )
+ {
+ DO_AND
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* OR[]: logical OR */
+ /* Opcode range: 0x5B */
+ /* Stack: uint32 uint32 --> uint32 */
+ /* */
+ static
+ void Ins_OR( INS_ARG )
+ {
+ DO_OR
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* NOT[]: logical NOT */
+ /* Opcode range: 0x5C */
+ /* Stack: StkElt --> uint32 */
+ /* */
+ static
+ void Ins_NOT( INS_ARG )
+ {
+ DO_NOT
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ADD[]: ADD */
+ /* Opcode range: 0x60 */
+ /* Stack: f26.6 f26.6 --> f26.6 */
+ /* */
+ static
+ void Ins_ADD( INS_ARG )
+ {
+ DO_ADD
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SUB[]: SUBtract */
+ /* Opcode range: 0x61 */
+ /* Stack: f26.6 f26.6 --> f26.6 */
+ /* */
+ static
+ void Ins_SUB( INS_ARG )
+ {
+ DO_SUB
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DIV[]: DIVide */
+ /* Opcode range: 0x62 */
+ /* Stack: f26.6 f26.6 --> f26.6 */
+ /* */
+ static
+ void Ins_DIV( INS_ARG )
+ {
+ DO_DIV
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MUL[]: MULtiply */
+ /* Opcode range: 0x63 */
+ /* Stack: f26.6 f26.6 --> f26.6 */
+ /* */
+ static
+ void Ins_MUL( INS_ARG )
+ {
+ DO_MUL
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ABS[]: ABSolute value */
+ /* Opcode range: 0x64 */
+ /* Stack: f26.6 --> f26.6 */
+ /* */
+ static
+ void Ins_ABS( INS_ARG )
+ {
+ DO_ABS
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* NEG[]: NEGate */
+ /* Opcode range: 0x65 */
+ /* Stack: f26.6 --> f26.6 */
+ /* */
+ static
+ void Ins_NEG( INS_ARG )
+ {
+ DO_NEG
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FLOOR[]: FLOOR */
+ /* Opcode range: 0x66 */
+ /* Stack: f26.6 --> f26.6 */
+ /* */
+ static
+ void Ins_FLOOR( INS_ARG )
+ {
+ DO_FLOOR
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* CEILING[]: CEILING */
+ /* Opcode range: 0x67 */
+ /* Stack: f26.6 --> f26.6 */
+ /* */
+ static
+ void Ins_CEILING( INS_ARG )
+ {
+ DO_CEILING
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RS[]: Read Store */
+ /* Opcode range: 0x43 */
+ /* Stack: uint32 --> uint32 */
+ /* */
+ static
+ void Ins_RS( INS_ARG )
+ {
+ DO_RS
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* WS[]: Write Store */
+ /* Opcode range: 0x42 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static
+ void Ins_WS( INS_ARG )
+ {
+ DO_WS
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* WCVTP[]: Write CVT in Pixel units */
+ /* Opcode range: 0x44 */
+ /* Stack: f26.6 uint32 --> */
+ /* */
+ static
+ void Ins_WCVTP( INS_ARG )
+ {
+ DO_WCVTP
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* WCVTF[]: Write CVT in Funits */
+ /* Opcode range: 0x70 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static
+ void Ins_WCVTF( INS_ARG )
+ {
+ DO_WCVTF
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RCVT[]: Read CVT */
+ /* Opcode range: 0x45 */
+ /* Stack: uint32 --> f26.6 */
+ /* */
+ static
+ void Ins_RCVT( INS_ARG )
+ {
+ DO_RCVT
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* AA[]: Adjust Angle */
+ /* Opcode range: 0x7F */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_AA( INS_ARG )
+ {
+ /* intentionally no longer supported */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DEBUG[]: DEBUG. Unsupported. */
+ /* Opcode range: 0x4F */
+ /* Stack: uint32 --> */
+ /* */
+ /* Note: The original instruction pops a value from the stack. */
+ /* */
+ static
+ void Ins_DEBUG( INS_ARG )
+ {
+ DO_DEBUG
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ROUND[ab]: ROUND value */
+ /* Opcode range: 0x68-0x6B */
+ /* Stack: f26.6 --> f26.6 */
+ /* */
+ static
+ void Ins_ROUND( INS_ARG )
+ {
+ DO_ROUND
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* NROUND[ab]: No ROUNDing of value */
+ /* Opcode range: 0x6C-0x6F */
+ /* Stack: f26.6 --> f26.6 */
+ /* */
+ static
+ void Ins_NROUND( INS_ARG )
+ {
+ DO_NROUND
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MAX[]: MAXimum */
+ /* Opcode range: 0x68 */
+ /* Stack: int32? int32? --> int32 */
+ /* */
+ static
+ void Ins_MAX( INS_ARG )
+ {
+ DO_MAX
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MIN[]: MINimum */
+ /* Opcode range: 0x69 */
+ /* Stack: int32? int32? --> int32 */
+ /* */
+ static
+ void Ins_MIN( INS_ARG )
+ {
+ DO_MIN
+ }
+
+
+#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
+
+
+ /*************************************************************************/
+ /* */
+ /* The following functions are called as is within the switch statement. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* MINDEX[]: Move INDEXed element */
+ /* Opcode range: 0x26 */
+ /* Stack: int32? --> StkElt */
+ /* */
+ static
+ void Ins_MINDEX( INS_ARG )
+ {
+ FT_Long L, K;
+
+
+ L = args[0];
+
+ if ( L <= 0 || L > CUR.args )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ K = CUR.stack[CUR.args - L];
+
+ MEM_Move( &CUR.stack[CUR.args - L ],
+ &CUR.stack[CUR.args - L + 1],
+ ( L - 1 ) * sizeof ( FT_Long ) );
+
+ CUR.stack[CUR.args - 1] = K;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ROLL[]: ROLL top three elements */
+ /* Opcode range: 0x8A */
+ /* Stack: 3 * StkElt --> 3 * StkElt */
+ /* */
+ static
+ void Ins_ROLL( INS_ARG )
+ {
+ FT_Long A, B, C;
+
+ FT_UNUSED_EXEC;
+
+
+ A = args[2];
+ B = args[1];
+ C = args[0];
+
+ args[2] = C;
+ args[1] = A;
+ args[0] = B;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MANAGING THE FLOW OF CONTROL */
+ /* */
+ /* Instructions appear in the specification's order. */
+ /* */
+ /*************************************************************************/
+
+
+ static
+ FT_Bool SkipCode( EXEC_OP )
+ {
+ CUR.IP += CUR.length;
+
+ if ( CUR.IP < CUR.codeSize )
+ {
+ CUR.opcode = CUR.code[CUR.IP];
+
+ CUR.length = opcode_length[CUR.opcode];
+ if ( CUR.length < 0 )
+ {
+ if ( CUR.IP + 1 > CUR.codeSize )
+ goto Fail_Overflow;
+ CUR.length = CUR.code[CUR.IP + 1] + 2;
+ }
+
+ if ( CUR.IP + CUR.length <= CUR.codeSize )
+ return SUCCESS;
+ }
+
+ Fail_Overflow:
+ CUR.error = TT_Err_Code_Overflow;
+ return FAILURE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* IF[]: IF test */
+ /* Opcode range: 0x58 */
+ /* Stack: StkElt --> */
+ /* */
+ static
+ void Ins_IF( INS_ARG )
+ {
+ FT_Int nIfs;
+ FT_Bool Out;
+
+
+ if ( args[0] != 0 )
+ return;
+
+ nIfs = 1;
+ Out = 0;
+
+ do
+ {
+ if ( SKIP_Code() == FAILURE )
+ return;
+
+ switch ( CUR.opcode )
+ {
+ case 0x58: /* IF */
+ nIfs++;
+ break;
+
+ case 0x1B: /* ELSE */
+ Out = ( nIfs == 1 );
+ break;
+
+ case 0x59: /* EIF */
+ nIfs--;
+ Out = ( nIfs == 0 );
+ break;
+ }
+ } while ( Out == 0 );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ELSE[]: ELSE */
+ /* Opcode range: 0x1B */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_ELSE( INS_ARG )
+ {
+ FT_Int nIfs;
+
+ FT_UNUSED_ARG;
+
+
+ nIfs = 1;
+
+ do
+ {
+ if ( SKIP_Code() == FAILURE )
+ return;
+
+ switch ( CUR.opcode )
+ {
+ case 0x58: /* IF */
+ nIfs++;
+ break;
+
+ case 0x59: /* EIF */
+ nIfs--;
+ break;
+ }
+ } while ( nIfs != 0 );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */
+ /* */
+ /* Instructions appear in the specification's order. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* FDEF[]: Function DEFinition */
+ /* Opcode range: 0x2C */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_FDEF( INS_ARG )
+ {
+ FT_ULong n;
+ TT_DefRecord* rec;
+ TT_DefRecord* limit;
+
+
+ /* some font programs are broken enough to redefine functions! */
+ /* We will then parse the current table. */
+
+ rec = CUR.FDefs;
+ limit = rec + CUR.numFDefs;
+ n = args[0];
+
+ for ( ; rec < limit; rec++ )
+ {
+ if ( rec->opc == n )
+ break;
+ }
+
+ if ( rec == limit )
+ {
+ /* check that there is enough room for new functions */
+ if ( CUR.numFDefs >= CUR.maxFDefs )
+ {
+ CUR.error = TT_Err_Too_Many_Function_Defs;
+ return;
+ }
+ CUR.numFDefs++;
+ }
+
+ rec->range = CUR.curRange;
+ rec->opc = n;
+ rec->start = CUR.IP + 1;
+ rec->active = TRUE;
+
+ if ( n > CUR.maxFunc )
+ CUR.maxFunc = n;
+
+ /* Now skip the whole function definition. */
+ /* We don't allow nested IDEFS & FDEFs. */
+
+ while ( SKIP_Code() == SUCCESS )
+ {
+ switch ( CUR.opcode )
+ {
+ case 0x89: /* IDEF */
+ case 0x2C: /* FDEF */
+ CUR.error = TT_Err_Nested_DEFS;
+ return;
+
+ case 0x2D: /* ENDF */
+ return;
+ }
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ENDF[]: END Function definition */
+ /* Opcode range: 0x2D */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_ENDF( INS_ARG )
+ {
+ TT_CallRec* pRec;
+
+ FT_UNUSED_ARG;
+
+
+ if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */
+ {
+ CUR.error = TT_Err_ENDF_In_Exec_Stream;
+ return;
+ }
+
+ CUR.callTop--;
+
+ pRec = &CUR.callStack[CUR.callTop];
+
+ pRec->Cur_Count--;
+
+ CUR.step_ins = FALSE;
+
+ if ( pRec->Cur_Count > 0 )
+ {
+ CUR.callTop++;
+ CUR.IP = pRec->Cur_Restart;
+ }
+ else
+ /* Loop through the current function */
+ INS_Goto_CodeRange( pRec->Caller_Range,
+ pRec->Caller_IP );
+
+ /* Exit the current call frame. */
+
+ /* NOTE: If the last intruction of a program is a */
+ /* CALL or LOOPCALL, the return address is */
+ /* always out of the code range. This is a */
+ /* valid address, and it is why we do not test */
+ /* the result of Ins_Goto_CodeRange() here! */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* CALL[]: CALL function */
+ /* Opcode range: 0x2B */
+ /* Stack: uint32? --> */
+ /* */
+ static
+ void Ins_CALL( INS_ARG )
+ {
+ FT_ULong F;
+ TT_CallRec* pCrec;
+ TT_DefRecord* def;
+
+
+ /* first of all, check the index */
+
+ F = args[0];
+ if ( BOUNDS( F, CUR.maxFunc + 1 ) )
+ goto Fail;
+
+ /* Except for some old Apple fonts, all functions in a TrueType */
+ /* font are defined in increasing order, starting from 0. This */
+ /* means that we normally have */
+ /* */
+ /* CUR.maxFunc+1 == CUR.numFDefs */
+ /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
+ /* */
+ /* If this isn't true, we need to look up the function table. */
+
+ def = CUR.FDefs + F;
+ if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
+ {
+ /* look up the FDefs table */
+ TT_DefRecord* limit;
+
+
+ def = CUR.FDefs;
+ limit = def + CUR.numFDefs;
+
+ while ( def < limit && def->opc != F )
+ def++;
+
+ if ( def == limit )
+ goto Fail;
+ }
+
+ /* check that the function is active */
+ if ( !def->active )
+ goto Fail;
+
+ /* check the call stack */
+ if ( CUR.callTop >= CUR.callSize )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ return;
+ }
+
+ pCrec = CUR.callStack + CUR.callTop;
+
+ pCrec->Caller_Range = CUR.curRange;
+ pCrec->Caller_IP = CUR.IP + 1;
+ pCrec->Cur_Count = 1;
+ pCrec->Cur_Restart = def->start;
+
+ CUR.callTop++;
+
+ INS_Goto_CodeRange( def->range,
+ def->start );
+
+ CUR.step_ins = FALSE;
+ return;
+
+ Fail:
+ CUR.error = TT_Err_Invalid_Reference;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* LOOPCALL[]: LOOP and CALL function */
+ /* Opcode range: 0x2A */
+ /* Stack: uint32? Eint16? --> */
+ /* */
+ static
+ void Ins_LOOPCALL( INS_ARG )
+ {
+ FT_ULong F;
+ TT_CallRec* pCrec;
+ TT_DefRecord* def;
+
+
+ /* first of all, check the index */
+ F = args[1];
+ if ( BOUNDS( F, CUR.maxFunc + 1 ) )
+ goto Fail;
+
+ /* Except for some old Apple fonts, all functions in a TrueType */
+ /* font are defined in increasing order, starting from 0. This */
+ /* means that we normally have */
+ /* */
+ /* CUR.maxFunc+1 == CUR.numFDefs */
+ /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
+ /* */
+ /* If this isn't true, we need to look up the function table. */
+
+ def = CUR.FDefs + F;
+ if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
+ {
+ /* look up the FDefs table */
+ TT_DefRecord* limit;
+
+
+ def = CUR.FDefs;
+ limit = def + CUR.numFDefs;
+
+ while ( def < limit && def->opc != F )
+ def++;
+
+ if ( def == limit )
+ goto Fail;
+ }
+
+ /* check that the function is active */
+ if ( !def->active )
+ goto Fail;
+
+ /* check stack */
+ if ( CUR.callTop >= CUR.callSize )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ return;
+ }
+
+ if ( args[0] > 0 )
+ {
+ pCrec = CUR.callStack + CUR.callTop;
+
+ pCrec->Caller_Range = CUR.curRange;
+ pCrec->Caller_IP = CUR.IP + 1;
+ pCrec->Cur_Count = (FT_Int)args[0];
+ pCrec->Cur_Restart = def->start;
+
+ CUR.callTop++;
+
+ INS_Goto_CodeRange( def->range, def->start );
+
+ CUR.step_ins = FALSE;
+ }
+ return;
+
+ Fail:
+ CUR.error = TT_Err_Invalid_Reference;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* IDEF[]: Instruction DEFinition */
+ /* Opcode range: 0x89 */
+ /* Stack: Eint8 --> */
+ /* */
+ static
+ void Ins_IDEF( INS_ARG )
+ {
+ TT_DefRecord* def;
+ TT_DefRecord* limit;
+
+
+ /* First of all, look for the same function in our table */
+
+ def = CUR.IDefs;
+ limit = def + CUR.numIDefs;
+
+ for ( ; def < limit; def++ )
+ if ( def->opc == (FT_ULong)args[0] )
+ break;
+
+ if ( def == limit )
+ {
+ /* check that there is enough room for a new instruction */
+ if ( CUR.numIDefs >= CUR.maxIDefs )
+ {
+ CUR.error = TT_Err_Too_Many_Instruction_Defs;
+ return;
+ }
+ CUR.numIDefs++;
+ }
+
+ def->opc = args[0];
+ def->start = CUR.IP+1;
+ def->range = CUR.curRange;
+ def->active = TRUE;
+
+ if ( (FT_ULong)args[0] > CUR.maxIns )
+ CUR.maxIns = args[0];
+
+ /* Now skip the whole function definition. */
+ /* We don't allow nested IDEFs & FDEFs. */
+
+ while ( SKIP_Code() == SUCCESS )
+ {
+ switch ( CUR.opcode )
+ {
+ case 0x89: /* IDEF */
+ case 0x2C: /* FDEF */
+ CUR.error = TT_Err_Nested_DEFS;
+ return;
+ case 0x2D: /* ENDF */
+ return;
+ }
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* PUSHING DATA ONTO THE INTERPRETER STACK */
+ /* */
+ /* Instructions appear in the specification's order. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* NPUSHB[]: PUSH N Bytes */
+ /* Opcode range: 0x40 */
+ /* Stack: --> uint32... */
+ /* */
+ static
+ void Ins_NPUSHB( INS_ARG )
+ {
+ FT_UShort L, K;
+
+
+ L = (FT_UShort)CUR.code[CUR.IP + 1];
+
+ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ return;
+ }
+
+ for ( K = 1; K <= L; K++ )
+ args[K - 1] = CUR.code[CUR.IP + K + 1];
+
+ CUR.new_top += L;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* NPUSHW[]: PUSH N Words */
+ /* Opcode range: 0x41 */
+ /* Stack: --> int32... */
+ /* */
+ static
+ void Ins_NPUSHW( INS_ARG )
+ {
+ FT_UShort L, K;
+
+
+ L = (FT_UShort)CUR.code[CUR.IP + 1];
+
+ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ return;
+ }
+
+ CUR.IP += 2;
+
+ for ( K = 0; K < L; K++ )
+ args[K] = GET_ShortIns();
+
+ CUR.step_ins = FALSE;
+ CUR.new_top += L;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* PUSHB[abc]: PUSH Bytes */
+ /* Opcode range: 0xB0-0xB7 */
+ /* Stack: --> uint32... */
+ /* */
+ static
+ void Ins_PUSHB( INS_ARG )
+ {
+ FT_UShort L, K;
+
+
+ L = (FT_UShort)CUR.opcode - 0xB0 + 1;
+
+ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ return;
+ }
+
+ for ( K = 1; K <= L; K++ )
+ args[K - 1] = CUR.code[CUR.IP + K];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* PUSHW[abc]: PUSH Words */
+ /* Opcode range: 0xB8-0xBF */
+ /* Stack: --> int32... */
+ /* */
+ static
+ void Ins_PUSHW( INS_ARG )
+ {
+ FT_UShort L, K;
+
+
+ L = (FT_UShort)CUR.opcode - 0xB8 + 1;
+
+ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ return;
+ }
+
+ CUR.IP++;
+
+ for ( K = 0; K < L; K++ )
+ args[K] = GET_ShortIns();
+
+ CUR.step_ins = FALSE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MANAGING THE GRAPHICS STATE */
+ /* */
+ /* Instructions appear in the specs' order. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* GC[a]: Get Coordinate projected onto */
+ /* Opcode range: 0x46-0x47 */
+ /* Stack: uint32 --> f26.6 */
+ /* */
+ /* BULLSHIT: Measures from the original glyph must be taken along the */
+ /* dual projection vector! */
+ /* */
+ static void Ins_GC( INS_ARG )
+ {
+ FT_ULong L;
+ FT_F26Dot6 R;
+
+
+ L = (FT_ULong)args[0];
+
+ if ( BOUNDS( L, CUR.zp2.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ else
+ R = 0;
+ }
+ else
+ {
+ if ( CUR.opcode & 1 )
+ R = CUR_Func_dualproj( CUR.zp2.org + L, NULL_Vector );
+ else
+ R = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector );
+ }
+
+ args[0] = R;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SCFS[]: Set Coordinate From Stack */
+ /* Opcode range: 0x48 */
+ /* Stack: f26.6 uint32 --> */
+ /* */
+ /* Formula: */
+ /* */
+ /* OA := OA + ( value - OA.p )/( f.p ) * f */
+ /* */
+ static
+ void Ins_SCFS( INS_ARG )
+ {
+ FT_Long K;
+ FT_UShort L;
+
+
+ L = (FT_UShort)args[0];
+
+ if ( BOUNDS( L, CUR.zp2.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ K = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector );
+
+ CUR_Func_move( &CUR.zp2, L, args[1] - K );
+
+ /* not part of the specs, but here for safety */
+
+ if ( CUR.GS.gep2 == 0 )
+ CUR.zp2.org[L] = CUR.zp2.cur[L];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MD[a]: Measure Distance */
+ /* Opcode range: 0x49-0x4A */
+ /* Stack: uint32 uint32 --> f26.6 */
+ /* */
+ /* BULLSHIT: Measure taken in the original glyph must be along the dual */
+ /* projection vector. */
+ /* */
+ /* Second BULLSHIT: Flag attributes are inverted! */
+ /* 0 => measure distance in original outline */
+ /* 1 => measure distance in grid-fitted outline */
+ /* */
+ /* Third one: `zp0 - zp1', and not `zp2 - zp1! */
+ /* */
+ static
+ void Ins_MD( INS_ARG )
+ {
+ FT_UShort K, L;
+ FT_F26Dot6 D;
+
+
+ K = (FT_UShort)args[1];
+ L = (FT_UShort)args[0];
+
+ if( BOUNDS( L, CUR.zp0.n_points ) ||
+ BOUNDS( K, CUR.zp1.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ D = 0;
+ }
+ else
+ {
+ if ( CUR.opcode & 1 )
+ D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
+ else
+ D = CUR_Func_dualproj( CUR.zp0.org + L, CUR.zp1.org + K );
+ }
+
+ args[0] = D;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SDPVTL[a]: Set Dual PVector to Line */
+ /* Opcode range: 0x86-0x87 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static
+ void Ins_SDPVTL( INS_ARG )
+ {
+ FT_Long A, B, C;
+ FT_UShort p1, p2; /* was FT_Int in pas type ERROR */
+
+
+ p1 = (FT_UShort)args[1];
+ p2 = (FT_UShort)args[0];
+
+ if ( BOUNDS( p2, CUR.zp1.n_points ) ||
+ BOUNDS( p1, CUR.zp2.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ {
+ FT_Vector* v1 = CUR.zp1.org + p2;
+ FT_Vector* v2 = CUR.zp2.org + p1;
+
+
+ A = v1->x - v2->x;
+ B = v1->y - v2->y;
+ }
+
+ if ( ( CUR.opcode & 1 ) != 0 )
+ {
+ C = B; /* counter clockwise rotation */
+ B = A;
+ A = -C;
+ }
+
+ NORMalize( A, B, &CUR.GS.dualVector );
+
+ {
+ FT_Vector* v1 = CUR.zp1.cur + p2;
+ FT_Vector* v2 = CUR.zp2.cur + p1;
+
+
+ A = v1->x - v2->x;
+ B = v1->y - v2->y;
+ }
+
+ if ( ( CUR.opcode & 1 ) != 0 )
+ {
+ C = B; /* counter clockwise rotation */
+ B = A;
+ A = -C;
+ }
+
+ NORMalize( A, B, &CUR.GS.projVector );
+
+ COMPUTE_Funcs();
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SZP0[]: Set Zone Pointer 0 */
+ /* Opcode range: 0x13 */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_SZP0( INS_ARG )
+ {
+ switch ( (FT_Int)args[0] )
+ {
+ case 0:
+ CUR.zp0 = CUR.twilight;
+ break;
+
+ case 1:
+ CUR.zp0 = CUR.pts;
+ break;
+
+ default:
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ CUR.GS.gep0 = (FT_UShort)args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SZP1[]: Set Zone Pointer 1 */
+ /* Opcode range: 0x14 */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_SZP1( INS_ARG )
+ {
+ switch ( (FT_Int)args[0] )
+ {
+ case 0:
+ CUR.zp1 = CUR.twilight;
+ break;
+
+ case 1:
+ CUR.zp1 = CUR.pts;
+ break;
+
+ default:
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ CUR.GS.gep1 = (FT_UShort)args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SZP2[]: Set Zone Pointer 2 */
+ /* Opcode range: 0x15 */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_SZP2( INS_ARG )
+ {
+ switch ( (FT_Int)args[0] )
+ {
+ case 0:
+ CUR.zp2 = CUR.twilight;
+ break;
+
+ case 1:
+ CUR.zp2 = CUR.pts;
+ break;
+
+ default:
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ CUR.GS.gep2 = (FT_UShort)args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SZPS[]: Set Zone PointerS */
+ /* Opcode range: 0x16 */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_SZPS( INS_ARG )
+ {
+ switch ( (FT_Int)args[0] )
+ {
+ case 0:
+ CUR.zp0 = CUR.twilight;
+ break;
+
+ case 1:
+ CUR.zp0 = CUR.pts;
+ break;
+
+ default:
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ CUR.zp1 = CUR.zp0;
+ CUR.zp2 = CUR.zp0;
+
+ CUR.GS.gep0 = (FT_UShort)args[0];
+ CUR.GS.gep1 = (FT_UShort)args[0];
+ CUR.GS.gep2 = (FT_UShort)args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* INSTCTRL[]: INSTruction ConTRoL */
+ /* Opcode range: 0x8e */
+ /* Stack: int32 int32 --> */
+ /* */
+ static
+ void Ins_INSTCTRL( INS_ARG )
+ {
+ FT_Long K, L;
+
+
+ K = args[1];
+ L = args[0];
+
+ if ( K < 1 || K > 2 )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ if ( L != 0 )
+ L = K;
+
+ CUR.GS.instruct_control =
+ (FT_Byte)( CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SCANCTRL[]: SCAN ConTRoL */
+ /* Opcode range: 0x85 */
+ /* Stack: uint32? --> */
+ /* */
+ static
+ void Ins_SCANCTRL( INS_ARG )
+ {
+ FT_Int A;
+
+
+ /* Get Threshold */
+ A = (FT_Int)( args[0] & 0xFF );
+
+ if ( A == 0xFF )
+ {
+ CUR.GS.scan_control = TRUE;
+ return;
+ }
+ else if ( A == 0 )
+ {
+ CUR.GS.scan_control = FALSE;
+ return;
+ }
+
+ A *= 64;
+
+#if 0
+ if ( (args[0] & 0x100) != 0 && CUR.metrics.pointSize <= A )
+ CUR.GS.scan_control = TRUE;
+#endif
+
+ if ( (args[0] & 0x200) != 0 && CUR.tt_metrics.rotated )
+ CUR.GS.scan_control = TRUE;
+
+ if ( (args[0] & 0x400) != 0 && CUR.tt_metrics.stretched )
+ CUR.GS.scan_control = TRUE;
+
+#if 0
+ if ( (args[0] & 0x800) != 0 && CUR.metrics.pointSize > A )
+ CUR.GS.scan_control = FALSE;
+#endif
+
+ if ( (args[0] & 0x1000) != 0 && CUR.tt_metrics.rotated )
+ CUR.GS.scan_control = FALSE;
+
+ if ( (args[0] & 0x2000) != 0 && CUR.tt_metrics.stretched )
+ CUR.GS.scan_control = FALSE;
+}
+
+
+ /*************************************************************************/
+ /* */
+ /* SCANTYPE[]: SCAN TYPE */
+ /* Opcode range: 0x8D */
+ /* Stack: uint32? --> */
+ /* */
+ static
+ void Ins_SCANTYPE( INS_ARG )
+ {
+ /* for compatibility with future enhancements, */
+ /* we must ignore new modes */
+
+ if ( args[0] >= 0 && args[0] <= 5 )
+ {
+ if ( args[0] == 3 )
+ args[0] = 2;
+
+ CUR.GS.scan_type = (FT_Int)args[0];
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MANAGING OUTLINES */
+ /* */
+ /* Instructions appear in the specification's order. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* FLIPPT[]: FLIP PoinT */
+ /* Opcode range: 0x80 */
+ /* Stack: uint32... --> */
+ /* */
+ static
+ void Ins_FLIPPT( INS_ARG )
+ {
+ FT_UShort point;
+
+ FT_UNUSED_ARG;
+
+
+ if ( CUR.top < CUR.GS.loop )
+ {
+ CUR.error = TT_Err_Too_Few_Arguments;
+ return;
+ }
+
+ while ( CUR.GS.loop > 0 )
+ {
+ CUR.args--;
+
+ point = (FT_UShort)CUR.stack[CUR.args];
+
+ if ( BOUNDS( point, CUR.pts.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ }
+ else
+ CUR.pts.tags[point] ^= FT_Curve_Tag_On;
+
+ CUR.GS.loop--;
+ }
+
+ CUR.GS.loop = 1;
+ CUR.new_top = CUR.args;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FLIPRGON[]: FLIP RanGe ON */
+ /* Opcode range: 0x81 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static
+ void Ins_FLIPRGON( INS_ARG )
+ {
+ FT_UShort I, K, L;
+
+
+ K = (FT_UShort)args[1];
+ L = (FT_UShort)args[0];
+
+ if ( BOUNDS( K, CUR.pts.n_points ) ||
+ BOUNDS( L, CUR.pts.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ for ( I = L; I <= K; I++ )
+ CUR.pts.tags[I] |= FT_Curve_Tag_On;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FLIPRGOFF: FLIP RanGe OFF */
+ /* Opcode range: 0x82 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static
+ void Ins_FLIPRGOFF( INS_ARG )
+ {
+ FT_UShort I, K, L;
+
+
+ K = (FT_UShort)args[1];
+ L = (FT_UShort)args[0];
+
+ if ( BOUNDS( K, CUR.pts.n_points ) ||
+ BOUNDS( L, CUR.pts.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ for ( I = L; I <= K; I++ )
+ CUR.pts.tags[I] &= ~FT_Curve_Tag_On;
+ }
+
+
+ static
+ FT_Bool Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6* x,
+ FT_F26Dot6* y,
+ TT_GlyphZone* zone,
+ FT_UShort* refp )
+ {
+ TT_GlyphZone zp;
+ FT_UShort p;
+ FT_F26Dot6 d;
+
+
+ if ( CUR.opcode & 1 )
+ {
+ zp = CUR.zp0;
+ p = CUR.GS.rp1;
+ }
+ else
+ {
+ zp = CUR.zp1;
+ p = CUR.GS.rp2;
+ }
+
+ if ( BOUNDS( p, zp.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return FAILURE;
+ }
+
+ *zone = zp;
+ *refp = p;
+
+ d = CUR_Func_project( zp.cur + p, zp.org + p );
+
+#ifdef NO_APPLE_PATENT
+
+ *x = TT_MULDIV( d, CUR.GS.freeVector.x, 0x4000 );
+ *y = TT_MULDIV( d, CUR.GS.freeVector.y, 0x4000 );
+
+#else
+
+ *x = TT_MULDIV( d,
+ (FT_Long)CUR.GS.freeVector.x * 0x10000L,
+ CUR.F_dot_P );
+ *y = TT_MULDIV( d,
+ (FT_Long)CUR.GS.freeVector.y * 0x10000L,
+ CUR.F_dot_P );
+
+#endif /* NO_APPLE_PATENT */
+
+ return SUCCESS;
+ }
+
+
+ static
+ void Move_Zp2_Point( EXEC_OP_ FT_UShort point,
+ FT_F26Dot6 dx,
+ FT_F26Dot6 dy,
+ FT_Bool touch )
+ {
+ if ( CUR.GS.freeVector.x != 0 )
+ {
+ CUR.zp2.cur[point].x += dx;
+ if ( touch )
+ CUR.zp2.tags[point] |= FT_Curve_Tag_Touch_X;
+ }
+
+ if ( CUR.GS.freeVector.y != 0 )
+ {
+ CUR.zp2.cur[point].y += dy;
+ if ( touch )
+ CUR.zp2.tags[point] |= FT_Curve_Tag_Touch_Y;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SHP[a]: SHift Point by the last point */
+ /* Opcode range: 0x32-0x33 */
+ /* Stack: uint32... --> */
+ /* */
+ static
+ void Ins_SHP( INS_ARG )
+ {
+ TT_GlyphZone zp;
+ FT_UShort refp;
+
+ FT_F26Dot6 dx,
+ dy;
+ FT_UShort point;
+
+ FT_UNUSED_ARG;
+
+
+ if ( CUR.top < CUR.GS.loop )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+ return;
+
+ while ( CUR.GS.loop > 0 )
+ {
+ CUR.args--;
+ point = (FT_UShort)CUR.stack[CUR.args];
+
+ if ( BOUNDS( point, CUR.zp2.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ }
+ else
+ /* XXX: UNDOCUMENTED! SHP touches the points */
+ MOVE_Zp2_Point( point, dx, dy, TRUE );
+
+ CUR.GS.loop--;
+ }
+
+ CUR.GS.loop = 1;
+ CUR.new_top = CUR.args;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SHC[a]: SHift Contour */
+ /* Opcode range: 0x34-35 */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_SHC( INS_ARG )
+ {
+ TT_GlyphZone zp;
+ FT_UShort refp;
+ FT_F26Dot6 dx,
+ dy;
+
+ FT_Short contour;
+ FT_UShort first_point, last_point, i;
+
+
+ contour = (FT_UShort)args[0];
+
+ if ( BOUNDS( contour, CUR.pts.n_contours ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+ return;
+
+ if ( contour == 0 )
+ first_point = 0;
+ else
+ first_point = CUR.pts.contours[contour - 1] + 1;
+
+ last_point = CUR.pts.contours[contour];
+
+ /* XXX: this is probably wrong... at least it prevents memory */
+ /* corruption when zp2 is the twilight zone */
+ if ( last_point > CUR.zp2.n_points )
+ {
+ if ( CUR.zp2.n_points > 0 )
+ last_point = CUR.zp2.n_points - 1;
+ else
+ last_point = 0;
+ }
+
+ /* XXX: UNDOCUMENTED! SHC doesn't touch the points */
+ for ( i = first_point; i <= last_point; i++ )
+ {
+ if ( zp.cur != CUR.zp2.cur || refp != i )
+ MOVE_Zp2_Point( i, dx, dy, FALSE );
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SHZ[a]: SHift Zone */
+ /* Opcode range: 0x36-37 */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_SHZ( INS_ARG )
+ {
+ TT_GlyphZone zp;
+ FT_UShort refp;
+ FT_F26Dot6 dx,
+ dy;
+
+ FT_UShort last_point, i;
+
+
+ if ( BOUNDS( args[0], 2 ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+ return;
+
+ if ( CUR.zp2.n_points > 0 )
+ last_point = CUR.zp2.n_points - 1;
+ else
+ last_point = 0;
+
+ /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
+ for ( i = 0; i <= last_point; i++ )
+ {
+ if ( zp.cur != CUR.zp2.cur || refp != i )
+ MOVE_Zp2_Point( i, dx, dy, FALSE );
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SHPIX[]: SHift points by a PIXel amount */
+ /* Opcode range: 0x38 */
+ /* Stack: f26.6 uint32... --> */
+ /* */
+ static
+ void Ins_SHPIX( INS_ARG )
+ {
+ FT_F26Dot6 dx, dy;
+ FT_UShort point;
+
+
+ if ( CUR.top < CUR.GS.loop + 1 )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ dx = TT_MULDIV( args[0],
+ (FT_Long)CUR.GS.freeVector.x,
+ 0x4000 );
+ dy = TT_MULDIV( args[0],
+ (FT_Long)CUR.GS.freeVector.y,
+ 0x4000 );
+
+ while ( CUR.GS.loop > 0 )
+ {
+ CUR.args--;
+
+ point = (FT_UShort)CUR.stack[CUR.args];
+
+ if ( BOUNDS( point, CUR.zp2.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ }
+ else
+ MOVE_Zp2_Point( point, dx, dy, TRUE );
+
+ CUR.GS.loop--;
+ }
+
+ CUR.GS.loop = 1;
+ CUR.new_top = CUR.args;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MSIRP[a]: Move Stack Indirect Relative Position */
+ /* Opcode range: 0x3A-0x3B */
+ /* Stack: f26.6 uint32 --> */
+ /* */
+ static
+ void Ins_MSIRP( INS_ARG )
+ {
+ FT_UShort point;
+ FT_F26Dot6 distance;
+
+
+ point = (FT_UShort)args[0];
+
+ if ( BOUNDS( point, CUR.zp1.n_points ) ||
+ BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ /* XXX: UNDOCUMENTED! behaviour */
+ if ( CUR.GS.gep0 == 0 ) /* if in twilight zone */
+ {
+ CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
+ CUR.zp1.cur[point] = CUR.zp1.org[point];
+ }
+
+ distance = CUR_Func_project( CUR.zp1.cur + point,
+ CUR.zp0.cur + CUR.GS.rp0 );
+
+ CUR_Func_move( &CUR.zp1, point, args[1] - distance );
+
+ CUR.GS.rp1 = CUR.GS.rp0;
+ CUR.GS.rp2 = point;
+
+ if ( (CUR.opcode & 1) != 0 )
+ CUR.GS.rp0 = point;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MDAP[a]: Move Direct Absolute Point */
+ /* Opcode range: 0x2E-0x2F */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_MDAP( INS_ARG )
+ {
+ FT_UShort point;
+ FT_F26Dot6 cur_dist,
+ distance;
+
+
+ point = (FT_UShort)args[0];
+
+ if ( BOUNDS( point, CUR.zp0.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ /* XXX: Is there some undocumented feature while in the */
+ /* twilight zone? ? */
+ if ( ( CUR.opcode & 1 ) != 0 )
+ {
+ cur_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector );
+ distance = CUR_Func_round( cur_dist,
+ CUR.tt_metrics.compensations[0] ) - cur_dist;
+ }
+ else
+ distance = 0;
+
+ CUR_Func_move( &CUR.zp0, point, distance );
+
+ CUR.GS.rp0 = point;
+ CUR.GS.rp1 = point;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MIAP[a]: Move Indirect Absolute Point */
+ /* Opcode range: 0x3E-0x3F */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static
+ void Ins_MIAP( INS_ARG )
+ {
+ FT_ULong cvtEntry;
+ FT_UShort point;
+ FT_F26Dot6 distance,
+ org_dist;
+
+
+ cvtEntry = (FT_ULong)args[1];
+ point = (FT_UShort)args[0];
+
+ if ( BOUNDS( point, CUR.zp0.n_points ) ||
+ BOUNDS( cvtEntry, CUR.cvtSize ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ /* UNDOCUMENTED! */
+ /* */
+ /* The behaviour of an MIAP instruction is quite */
+ /* different when used in the twilight zone. */
+ /* */
+ /* First, no control value cutin test is performed */
+ /* as it would fail anyway. Second, the original */
+ /* point, i.e. (org_x,org_y) of zp0.point, is set */
+ /* to the absolute, unrounded distance found in */
+ /* the CVT. */
+ /* */
+ /* This is used in the CVT programs of the Microsoft */
+ /* fonts Arial, Times, etc., in order to re-adjust */
+ /* some key font heights. It allows the use of the */
+ /* IP instruction in the twilight zone, which */
+ /* otherwise would be `illegal' according to the */
+ /* specification. */
+ /* */
+ /* We implement it with a special sequence for the */
+ /* twilight zone. This is a bad hack, but it seems */
+ /* to work. */
+
+ distance = CUR_Func_read_cvt( cvtEntry );
+
+ if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */
+ {
+ CUR.zp0.org[point].x = TT_MULDIV( CUR.GS.freeVector.x,
+ distance, 0x4000 );
+ CUR.zp0.org[point].y = TT_MULDIV( CUR.GS.freeVector.y,
+ distance, 0x4000 );
+ CUR.zp0.cur[point] = CUR.zp0.org[point];
+ }
+
+ org_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector );
+
+ if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cutin flag */
+ {
+ if ( ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
+ distance = org_dist;
+
+ distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
+ }
+
+ CUR_Func_move( &CUR.zp0, point, distance - org_dist );
+
+ CUR.GS.rp0 = point;
+ CUR.GS.rp1 = point;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MDRP[abcde]: Move Direct Relative Point */
+ /* Opcode range: 0xC0-0xDF */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_MDRP( INS_ARG )
+ {
+ FT_UShort point;
+ FT_F26Dot6 org_dist, distance;
+
+
+ point = (FT_UShort)args[0];
+
+ if ( BOUNDS( point, CUR.zp1.n_points ) ||
+ BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ /* XXX: Is there some undocumented feature while in the */
+ /* twilight zone? */
+
+ org_dist = CUR_Func_dualproj( CUR.zp1.org + point,
+ CUR.zp0.org + CUR.GS.rp0 );
+
+ /* single width cutin test */
+
+ if ( ABS( org_dist ) < CUR.GS.single_width_cutin )
+ {
+ if ( org_dist >= 0 )
+ org_dist = CUR.GS.single_width_value;
+ else
+ org_dist = -CUR.GS.single_width_value;
+ }
+
+ /* round flag */
+
+ if ( ( CUR.opcode & 4 ) != 0 )
+ distance = CUR_Func_round(
+ org_dist,
+ CUR.tt_metrics.compensations[CUR.opcode & 3] );
+ else
+ distance = ROUND_None(
+ org_dist,
+ CUR.tt_metrics.compensations[CUR.opcode & 3] );
+
+ /* minimum distance flag */
+
+ if ( ( CUR.opcode & 8 ) != 0 )
+ {
+ if ( org_dist >= 0 )
+ {
+ if ( distance < CUR.GS.minimum_distance )
+ distance = CUR.GS.minimum_distance;
+ }
+ else
+ {
+ if ( distance > -CUR.GS.minimum_distance )
+ distance = -CUR.GS.minimum_distance;
+ }
+ }
+
+ /* now move the point */
+
+ org_dist = CUR_Func_project( CUR.zp1.cur + point,
+ CUR.zp0.cur + CUR.GS.rp0 );
+
+ CUR_Func_move( &CUR.zp1, point, distance - org_dist );
+
+ CUR.GS.rp1 = CUR.GS.rp0;
+ CUR.GS.rp2 = point;
+
+ if ( ( CUR.opcode & 16 ) != 0 )
+ CUR.GS.rp0 = point;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MIRP[abcde]: Move Indirect Relative Point */
+ /* Opcode range: 0xE0-0xFF */
+ /* Stack: int32? uint32 --> */
+ /* */
+ static
+ void Ins_MIRP( INS_ARG )
+ {
+ FT_UShort point;
+ FT_ULong cvtEntry;
+
+ FT_F26Dot6 cvt_dist,
+ distance,
+ cur_dist,
+ org_dist;
+
+
+ point = (FT_UShort)args[0];
+ cvtEntry = (FT_ULong)( args[1] + 1 );
+
+ /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
+
+ if ( BOUNDS( point, CUR.zp1.n_points ) ||
+ BOUNDS( cvtEntry, CUR.cvtSize + 1 ) ||
+ BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ if ( !cvtEntry )
+ cvt_dist = 0;
+ else
+ cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
+
+ /* single width test */
+
+ if ( ABS( cvt_dist ) < CUR.GS.single_width_cutin )
+ {
+ if ( cvt_dist >= 0 )
+ cvt_dist = CUR.GS.single_width_value;
+ else
+ cvt_dist = -CUR.GS.single_width_value;
+ }
+
+ /* XXX: UNDOCUMENTED! -- twilight zone */
+
+ if ( CUR.GS.gep1 == 0 )
+ {
+ CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
+ TT_MULDIV( cvt_dist,
+ CUR.GS.freeVector.x,
+ 0x4000 );
+
+ CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
+ TT_MULDIV( cvt_dist,
+ CUR.GS.freeVector.y,
+ 0x4000 );
+
+ CUR.zp1.cur[point] = CUR.zp1.org[point];
+ }
+
+ org_dist = CUR_Func_dualproj( CUR.zp1.org + point,
+ CUR.zp0.org + CUR.GS.rp0 );
+
+ cur_dist = CUR_Func_project( CUR.zp1.cur + point,
+ CUR.zp0.cur + CUR.GS.rp0 );
+
+ /* auto-flip test */
+
+ if ( CUR.GS.auto_flip )
+ {
+ if ( ( org_dist ^ cvt_dist ) < 0 )
+ cvt_dist = -cvt_dist;
+ }
+
+ /* control value cutin and round */
+
+ if ( ( CUR.opcode & 4 ) != 0 )
+ {
+ /* XXX: UNDOCUMENTED! Only perform cut-in test when both points */
+ /* refer to the same zone. */
+
+ if ( CUR.GS.gep0 == CUR.GS.gep1 )
+ if ( ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
+ cvt_dist = org_dist;
+
+ distance = CUR_Func_round(
+ cvt_dist,
+ CUR.tt_metrics.compensations[CUR.opcode & 3] );
+ }
+ else
+ distance = ROUND_None(
+ cvt_dist,
+ CUR.tt_metrics.compensations[CUR.opcode & 3] );
+
+ /* minimum distance test */
+
+ if ( ( CUR.opcode & 8 ) != 0 )
+ {
+ if ( org_dist >= 0 )
+ {
+ if ( distance < CUR.GS.minimum_distance )
+ distance = CUR.GS.minimum_distance;
+ }
+ else
+ {
+ if ( distance > -CUR.GS.minimum_distance )
+ distance = -CUR.GS.minimum_distance;
+ }
+ }
+
+ CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
+
+ CUR.GS.rp1 = CUR.GS.rp0;
+
+ if ( ( CUR.opcode & 16 ) != 0 )
+ CUR.GS.rp0 = point;
+
+ /* XXX: UNDOCUMENTED! */
+
+ CUR.GS.rp2 = point;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ALIGNRP[]: ALIGN Relative Point */
+ /* Opcode range: 0x3C */
+ /* Stack: uint32 uint32... --> */
+ /* */
+ static
+ void Ins_ALIGNRP( INS_ARG )
+ {
+ FT_UShort point;
+ FT_F26Dot6 distance;
+
+ FT_UNUSED_ARG;
+
+
+ if ( CUR.top < CUR.GS.loop ||
+ BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ while ( CUR.GS.loop > 0 )
+ {
+ CUR.args--;
+
+ point = (FT_UShort)CUR.stack[CUR.args];
+
+ if ( BOUNDS( point, CUR.zp1.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ }
+ else
+ {
+ distance = CUR_Func_project( CUR.zp1.cur + point,
+ CUR.zp0.cur + CUR.GS.rp0 );
+
+ CUR_Func_move( &CUR.zp1, point, -distance );
+ }
+
+ CUR.GS.loop--;
+ }
+
+ CUR.GS.loop = 1;
+ CUR.new_top = CUR.args;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ISECT[]: moves point to InterSECTion */
+ /* Opcode range: 0x0F */
+ /* Stack: 5 * uint32 --> */
+ /* */
+ static
+ void Ins_ISECT( INS_ARG )
+ {
+ FT_UShort point,
+ a0, a1,
+ b0, b1;
+
+ FT_F26Dot6 discriminant;
+
+ FT_F26Dot6 dx, dy,
+ dax, day,
+ dbx, dby;
+
+ FT_F26Dot6 val;
+
+ FT_Vector R;
+
+
+ point = (FT_UShort)args[0];
+
+ a0 = (FT_UShort)args[1];
+ a1 = (FT_UShort)args[2];
+ b0 = (FT_UShort)args[3];
+ b1 = (FT_UShort)args[4];
+
+ if ( BOUNDS( b0, CUR.zp0.n_points ) ||
+ BOUNDS( b1, CUR.zp0.n_points ) ||
+ BOUNDS( a0, CUR.zp1.n_points ) ||
+ BOUNDS( a1, CUR.zp1.n_points ) ||
+ BOUNDS( point, CUR.zp2.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
+ dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
+
+ dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;
+ day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;
+
+ dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;
+ dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;
+
+ CUR.zp2.tags[point] |= FT_Curve_Tag_Touch_Both;
+
+ discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
+ TT_MULDIV( day, dbx, 0x40 );
+
+ if ( ABS( discriminant ) >= 0x40 )
+ {
+ val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
+
+ R.x = TT_MULDIV( val, dax, discriminant );
+ R.y = TT_MULDIV( val, day, discriminant );
+
+ CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
+ CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
+ }
+ else
+ {
+ /* else, take the middle of the middles of A and B */
+
+ CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
+ CUR.zp1.cur[a1].x +
+ CUR.zp0.cur[b0].x +
+ CUR.zp0.cur[b1].x ) / 4;
+ CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +
+ CUR.zp1.cur[a1].y +
+ CUR.zp0.cur[b0].y +
+ CUR.zp0.cur[b1].y ) / 4;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ALIGNPTS[]: ALIGN PoinTS */
+ /* Opcode range: 0x27 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static
+ void Ins_ALIGNPTS( INS_ARG )
+ {
+ FT_UShort p1, p2;
+ FT_F26Dot6 distance;
+
+
+ p1 = (FT_UShort)args[0];
+ p2 = (FT_UShort)args[1];
+
+ if ( BOUNDS( args[0], CUR.zp1.n_points ) ||
+ BOUNDS( args[1], CUR.zp0.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ distance = CUR_Func_project( CUR.zp0.cur + p2,
+ CUR.zp1.cur + p1 ) / 2;
+
+ CUR_Func_move( &CUR.zp1, p1, distance );
+ CUR_Func_move( &CUR.zp0, p2, -distance );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* IP[]: Interpolate Point */
+ /* Opcode range: 0x39 */
+ /* Stack: uint32... --> */
+ /* */
+ static
+ void Ins_IP( INS_ARG )
+ {
+ FT_F26Dot6 org_a, org_b, org_x,
+ cur_a, cur_b, cur_x,
+ distance;
+ FT_UShort point;
+
+ FT_UNUSED_ARG;
+
+
+ if ( CUR.top < CUR.GS.loop )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ /* XXX: There are some glyphs in some braindead but popular */
+ /* fonts out there (e.g. [aeu]grave in monotype.ttf) */
+ /* calling IP[] with bad values of rp[12]. */
+ /* Do something sane when this odd thing happens. */
+
+ if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||
+ BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )
+ {
+ org_a = cur_a = 0;
+ org_b = cur_b = 0;
+ }
+ else
+ {
+ org_a = CUR_Func_dualproj( CUR.zp0.org + CUR.GS.rp1, NULL_Vector );
+ org_b = CUR_Func_dualproj( CUR.zp1.org + CUR.GS.rp2, NULL_Vector );
+
+ cur_a = CUR_Func_project( CUR.zp0.cur + CUR.GS.rp1, NULL_Vector );
+ cur_b = CUR_Func_project( CUR.zp1.cur + CUR.GS.rp2, NULL_Vector );
+ }
+
+ while ( CUR.GS.loop > 0 )
+ {
+ CUR.args--;
+
+ point = (FT_UShort)CUR.stack[CUR.args];
+ if ( BOUNDS( point, CUR.zp2.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ }
+ else
+ {
+ org_x = CUR_Func_dualproj( CUR.zp2.org + point, NULL_Vector );
+ cur_x = CUR_Func_project ( CUR.zp2.cur + point, NULL_Vector );
+
+ if ( ( org_a <= org_b && org_x <= org_a ) ||
+ ( org_a > org_b && org_x >= org_a ) )
+
+ distance = ( cur_a - org_a ) + ( org_x - cur_x );
+
+ else if ( ( org_a <= org_b && org_x >= org_b ) ||
+ ( org_a > org_b && org_x < org_b ) )
+
+ distance = ( cur_b - org_b ) + ( org_x - cur_x );
+
+ else
+ /* note: it seems that rounding this value isn't a good */
+ /* idea (cf. width of capital `S' in Times) */
+
+ distance = TT_MULDIV( cur_b - cur_a,
+ org_x - org_a,
+ org_b - org_a ) + ( cur_a - cur_x );
+
+ CUR_Func_move( &CUR.zp2, point, distance );
+ }
+
+ CUR.GS.loop--;
+ }
+
+ CUR.GS.loop = 1;
+ CUR.new_top = CUR.args;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* UTP[a]: UnTouch Point */
+ /* Opcode range: 0x29 */
+ /* Stack: uint32 --> */
+ /* */
+ static
+ void Ins_UTP( INS_ARG )
+ {
+ FT_UShort point;
+ FT_Byte mask;
+
+
+ point = (FT_UShort)args[0];
+
+ if ( BOUNDS( point, CUR.zp0.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ mask = 0xFF;
+
+ if ( CUR.GS.freeVector.x != 0 )
+ mask &= ~FT_Curve_Tag_Touch_X;
+
+ if ( CUR.GS.freeVector.y != 0 )
+ mask &= ~FT_Curve_Tag_Touch_Y;
+
+ CUR.zp0.tags[point] &= mask;
+ }
+
+
+ /* Local variables for Ins_IUP: */
+ struct LOC_Ins_IUP
+ {
+ FT_Vector* orgs; /* original and current coordinate */
+ FT_Vector* curs; /* arrays */
+ };
+
+
+ static
+ void Shift( FT_UInt p1,
+ FT_UInt p2,
+ FT_UInt p,
+ struct LOC_Ins_IUP* LINK )
+ {
+ FT_UInt i;
+ FT_F26Dot6 x;
+
+
+ x = LINK->curs[p].x - LINK->orgs[p].x;
+
+ for ( i = p1; i < p; i++ )
+ LINK->curs[i].x += x;
+
+ for ( i = p + 1; i <= p2; i++ )
+ LINK->curs[i].x += x;
+ }
+
+
+ static
+ void Interp( FT_UInt p1,
+ FT_UInt p2,
+ FT_UInt ref1,
+ FT_UInt ref2,
+ struct LOC_Ins_IUP* LINK )
+ {
+ FT_UInt i;
+ FT_F26Dot6 x, x1, x2, d1, d2;
+
+
+ if ( p1 > p2 )
+ return;
+
+ x1 = LINK->orgs[ref1].x;
+ d1 = LINK->curs[ref1].x - LINK->orgs[ref1].x;
+ x2 = LINK->orgs[ref2].x;
+ d2 = LINK->curs[ref2].x - LINK->orgs[ref2].x;
+
+ if ( x1 == x2 )
+ {
+ for ( i = p1; i <= p2; i++ )
+ {
+ x = LINK->orgs[i].x;
+
+ if ( x <= x1 )
+ x += d1;
+ else
+ x += d2;
+
+ LINK->curs[i].x = x;
+ }
+ return;
+ }
+
+ if ( x1 < x2 )
+ {
+ for ( i = p1; i <= p2; i++ )
+ {
+ x = LINK->orgs[i].x;
+
+ if ( x <= x1 )
+ x += d1;
+ else
+ {
+ if ( x >= x2 )
+ x += d2;
+ else
+ x = LINK->curs[ref1].x +
+ TT_MULDIV( x - x1,
+ LINK->curs[ref2].x - LINK->curs[ref1].x,
+ x2 - x1 );
+ }
+ LINK->curs[i].x = x;
+ }
+ return;
+ }
+
+ /* x2 < x1 */
+
+ for ( i = p1; i <= p2; i++ )
+ {
+ x = LINK->orgs[i].x;
+ if ( x <= x2 )
+ x += d2;
+ else
+ {
+ if ( x >= x1 )
+ x += d1;
+ else
+ x = LINK->curs[ref1].x +
+ TT_MULDIV( x - x1,
+ LINK->curs[ref2].x - LINK->curs[ref1].x,
+ x2 - x1 );
+ }
+ LINK->curs[i].x = x;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* IUP[a]: Interpolate Untouched Points */
+ /* Opcode range: 0x30-0x31 */
+ /* Stack: --> */
+ /* */
+ static
+ void Ins_IUP( INS_ARG )
+ {
+ struct LOC_Ins_IUP V;
+ FT_Byte mask;
+
+ FT_UInt first_point; /* first point of contour */
+ FT_UInt end_point; /* end point (last+1) of contour */
+
+ FT_UInt first_touched; /* first touched point in contour */
+ FT_UInt cur_touched; /* current touched point in contour */
+
+ FT_UInt point; /* current point */
+ FT_Short contour; /* current contour */
+
+ FT_UNUSED_ARG;
+
+
+ if ( CUR.opcode & 1 )
+ {
+ mask = FT_Curve_Tag_Touch_X;
+ V.orgs = CUR.pts.org;
+ V.curs = CUR.pts.cur;
+ }
+ else
+ {
+ mask = FT_Curve_Tag_Touch_Y;
+ V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
+ V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
+ }
+
+ contour = 0;
+ point = 0;
+
+ do
+ {
+ end_point = CUR.pts.contours[contour];
+ first_point = point;
+
+ while ( point <= end_point && (CUR.pts.tags[point] & mask) == 0 )
+ point++;
+
+ if ( point <= end_point )
+ {
+ first_touched = point;
+ cur_touched = point;
+
+ point++;
+
+ while ( point <= end_point )
+ {
+ if ( ( CUR.pts.tags[point] & mask ) != 0 )
+ {
+ if ( point > 0 )
+ Interp( cur_touched + 1,
+ point - 1,
+ cur_touched,
+ point,
+ &V );
+ cur_touched = point;
+ }
+
+ point++;
+ }
+
+ if ( cur_touched == first_touched )
+ Shift( first_point, end_point, cur_touched, &V );
+ else
+ {
+ Interp( (FT_UShort)( cur_touched + 1 ),
+ end_point,
+ cur_touched,
+ first_touched,
+ &V );
+
+ if ( first_touched > 0 )
+ Interp( first_point,
+ first_touched - 1,
+ cur_touched,
+ first_touched,
+ &V );
+ }
+ }
+ contour++;
+ } while ( contour < CUR.pts.n_contours );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DELTAPn[]: DELTA exceptions P1, P2, P3 */
+ /* Opcode range: 0x5D,0x71,0x72 */
+ /* Stack: uint32 (2 * uint32)... --> */
+ /* */
+ static
+ void Ins_DELTAP( INS_ARG )
+ {
+ FT_ULong k, nump;
+ FT_UShort A;
+ FT_ULong C;
+ FT_Long B;
+
+
+ nump = (FT_ULong)args[0]; /* some points theoretically may occur more
+ than once, thus UShort isn't enough */
+
+ for ( k = 1; k <= nump; k++ )
+ {
+ if ( CUR.args < 2 )
+ {
+ CUR.error = TT_Err_Too_Few_Arguments;
+ return;
+ }
+
+ CUR.args -= 2;
+
+ A = (FT_UShort)CUR.stack[CUR.args + 1];
+ B = CUR.stack[CUR.args];
+
+ /* XXX: Because some popular fonts contain some invalid DeltaP */
+ /* instructions, we simply ignore them when the stacked */
+ /* point reference is off limit, rather than returning an */
+ /* error. As a delta instruction doesn't change a glyph */
+ /* in great ways, this shouldn't be a problem. */
+
+ if ( !BOUNDS( A, CUR.zp0.n_points ) )
+ {
+ C = ( (FT_ULong)B & 0xF0 ) >> 4;
+
+ switch ( CUR.opcode )
+ {
+ case 0x5D:
+ break;
+
+ case 0x71:
+ C += 16;
+ break;
+
+ case 0x72:
+ C += 32;
+ break;
+ }
+
+ C += CUR.GS.delta_base;
+
+ if ( CURRENT_Ppem() == (FT_Long)C )
+ {
+ B = ( (FT_ULong)B & 0xF ) - 8;
+ if ( B >= 0 )
+ B++;
+ B = B * 64 / ( 1L << CUR.GS.delta_shift );
+
+ CUR_Func_move( &CUR.zp0, A, B );
+ }
+ }
+ else
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ }
+
+ CUR.new_top = CUR.args;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DELTACn[]: DELTA exceptions C1, C2, C3 */
+ /* Opcode range: 0x73,0x74,0x75 */
+ /* Stack: uint32 (2 * uint32)... --> */
+ /* */
+ static
+ void Ins_DELTAC( INS_ARG )
+ {
+ FT_ULong nump, k;
+ FT_ULong A, C;
+ FT_Long B;
+
+
+ nump = (FT_ULong)args[0];
+
+ for ( k = 1; k <= nump; k++ )
+ {
+ if ( CUR.args < 2 )
+ {
+ CUR.error = TT_Err_Too_Few_Arguments;
+ return;
+ }
+
+ CUR.args -= 2;
+
+ A = (FT_ULong)CUR.stack[CUR.args + 1];
+ B = CUR.stack[CUR.args];
+
+ if ( BOUNDS( A, CUR.cvtSize ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ }
+ else
+ {
+ C = ( (FT_ULong)B & 0xF0 ) >> 4;
+
+ switch ( CUR.opcode )
+ {
+ case 0x73:
+ break;
+
+ case 0x74:
+ C += 16;
+ break;
+
+ case 0x75:
+ C += 32;
+ break;
+ }
+
+ C += CUR.GS.delta_base;
+
+ if ( CURRENT_Ppem() == (FT_Long)C )
+ {
+ B = ( (FT_ULong)B & 0xF ) - 8;
+ if ( B >= 0 )
+ B++;
+ B = B * 64 / ( 1L << CUR.GS.delta_shift );
+
+ CUR_Func_move_cvt( A, B );
+ }
+ }
+ }
+
+ CUR.new_top = CUR.args;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MISC. INSTRUCTIONS */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* GETINFO[]: GET INFOrmation */
+ /* Opcode range: 0x88 */
+ /* Stack: uint32 --> uint32 */
+ /* */
+ /* XXX: According to Apple specs, bits 1 & 2 of the argument ought to be */
+ /* consulted before rotated/stretched info is returned. */
+ static
+ void Ins_GETINFO( INS_ARG )
+ {
+ FT_Long K;
+
+
+ K = 0;
+
+ /* We return then Windows 3.1 version number */
+ /* for the font scaler */
+ if ( ( args[0] & 1 ) != 0 )
+ K = 3;
+
+ /* Has the glyph been rotated ? */
+ if ( CUR.tt_metrics.rotated )
+ K |= 0x80;
+
+ /* Has the glyph been stretched ? */
+ if ( CUR.tt_metrics.stretched )
+ K |= 0x100;
+
+ args[0] = K;
+ }
+
+
+ static
+ void Ins_UNKNOWN( INS_ARG )
+ {
+ TT_DefRecord* def = CUR.IDefs;
+ TT_DefRecord* limit = def + CUR.numIDefs;
+
+ FT_UNUSED_ARG;
+
+
+ for ( ; def < limit; def++ )
+ {
+ if ( def->opc == CUR.opcode && def->active )
+ {
+ TT_CallRec* call;
+
+
+ if ( CUR.callTop >= CUR.callSize )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ return;
+ }
+
+ call = CUR.callStack + CUR.callTop++;
+
+ call->Caller_Range = CUR.curRange;
+ call->Caller_IP = CUR.IP+1;
+ call->Cur_Count = 1;
+ call->Cur_Restart = def->start;
+
+ INS_Goto_CodeRange( def->range, def->start );
+
+ CUR.step_ins = FALSE;
+ return;
+ }
+ }
+
+ CUR.error = TT_Err_Invalid_Opcode;
+ }
+
+
+#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+
+ static
+ TInstruction_Function Instruct_Dispatch[256] =
+ {
+ /* Opcodes are gathered in groups of 16. */
+ /* Please keep the spaces as they are. */
+
+ /* SVTCA y */ Ins_SVTCA,
+ /* SVTCA x */ Ins_SVTCA,
+ /* SPvTCA y */ Ins_SPVTCA,
+ /* SPvTCA x */ Ins_SPVTCA,
+ /* SFvTCA y */ Ins_SFVTCA,
+ /* SFvTCA x */ Ins_SFVTCA,
+ /* SPvTL // */ Ins_SPVTL,
+ /* SPvTL + */ Ins_SPVTL,
+ /* SFvTL // */ Ins_SFVTL,
+ /* SFvTL + */ Ins_SFVTL,
+ /* SPvFS */ Ins_SPVFS,
+ /* SFvFS */ Ins_SFVFS,
+ /* GPV */ Ins_GPV,
+ /* GFV */ Ins_GFV,
+ /* SFvTPv */ Ins_SFVTPV,
+ /* ISECT */ Ins_ISECT,
+
+ /* SRP0 */ Ins_SRP0,
+ /* SRP1 */ Ins_SRP1,
+ /* SRP2 */ Ins_SRP2,
+ /* SZP0 */ Ins_SZP0,
+ /* SZP1 */ Ins_SZP1,
+ /* SZP2 */ Ins_SZP2,
+ /* SZPS */ Ins_SZPS,
+ /* SLOOP */ Ins_SLOOP,
+ /* RTG */ Ins_RTG,
+ /* RTHG */ Ins_RTHG,
+ /* SMD */ Ins_SMD,
+ /* ELSE */ Ins_ELSE,
+ /* JMPR */ Ins_JMPR,
+ /* SCvTCi */ Ins_SCVTCI,
+ /* SSwCi */ Ins_SSWCI,
+ /* SSW */ Ins_SSW,
+
+ /* DUP */ Ins_DUP,
+ /* POP */ Ins_POP,
+ /* CLEAR */ Ins_CLEAR,
+ /* SWAP */ Ins_SWAP,
+ /* DEPTH */ Ins_DEPTH,
+ /* CINDEX */ Ins_CINDEX,
+ /* MINDEX */ Ins_MINDEX,
+ /* AlignPTS */ Ins_ALIGNPTS,
+ /* INS_0x28 */ Ins_UNKNOWN,
+ /* UTP */ Ins_UTP,
+ /* LOOPCALL */ Ins_LOOPCALL,
+ /* CALL */ Ins_CALL,
+ /* FDEF */ Ins_FDEF,
+ /* ENDF */ Ins_ENDF,
+ /* MDAP[0] */ Ins_MDAP,
+ /* MDAP[1] */ Ins_MDAP,
+
+ /* IUP[0] */ Ins_IUP,
+ /* IUP[1] */ Ins_IUP,
+ /* SHP[0] */ Ins_SHP,
+ /* SHP[1] */ Ins_SHP,
+ /* SHC[0] */ Ins_SHC,
+ /* SHC[1] */ Ins_SHC,
+ /* SHZ[0] */ Ins_SHZ,
+ /* SHZ[1] */ Ins_SHZ,
+ /* SHPIX */ Ins_SHPIX,
+ /* IP */ Ins_IP,
+ /* MSIRP[0] */ Ins_MSIRP,
+ /* MSIRP[1] */ Ins_MSIRP,
+ /* AlignRP */ Ins_ALIGNRP,
+ /* RTDG */ Ins_RTDG,
+ /* MIAP[0] */ Ins_MIAP,
+ /* MIAP[1] */ Ins_MIAP,
+
+ /* NPushB */ Ins_NPUSHB,
+ /* NPushW */ Ins_NPUSHW,
+ /* WS */ Ins_WS,
+ /* RS */ Ins_RS,
+ /* WCvtP */ Ins_WCVTP,
+ /* RCvt */ Ins_RCVT,
+ /* GC[0] */ Ins_GC,
+ /* GC[1] */ Ins_GC,
+ /* SCFS */ Ins_SCFS,
+ /* MD[0] */ Ins_MD,
+ /* MD[1] */ Ins_MD,
+ /* MPPEM */ Ins_MPPEM,
+ /* MPS */ Ins_MPS,
+ /* FlipON */ Ins_FLIPON,
+ /* FlipOFF */ Ins_FLIPOFF,
+ /* DEBUG */ Ins_DEBUG,
+
+ /* LT */ Ins_LT,
+ /* LTEQ */ Ins_LTEQ,
+ /* GT */ Ins_GT,
+ /* GTEQ */ Ins_GTEQ,
+ /* EQ */ Ins_EQ,
+ /* NEQ */ Ins_NEQ,
+ /* ODD */ Ins_ODD,
+ /* EVEN */ Ins_EVEN,
+ /* IF */ Ins_IF,
+ /* EIF */ Ins_EIF,
+ /* AND */ Ins_AND,
+ /* OR */ Ins_OR,
+ /* NOT */ Ins_NOT,
+ /* DeltaP1 */ Ins_DELTAP,
+ /* SDB */ Ins_SDB,
+ /* SDS */ Ins_SDS,
+
+ /* ADD */ Ins_ADD,
+ /* SUB */ Ins_SUB,
+ /* DIV */ Ins_DIV,
+ /* MUL */ Ins_MUL,
+ /* ABS */ Ins_ABS,
+ /* NEG */ Ins_NEG,
+ /* FLOOR */ Ins_FLOOR,
+ /* CEILING */ Ins_CEILING,
+ /* ROUND[0] */ Ins_ROUND,
+ /* ROUND[1] */ Ins_ROUND,
+ /* ROUND[2] */ Ins_ROUND,
+ /* ROUND[3] */ Ins_ROUND,
+ /* NROUND[0] */ Ins_NROUND,
+ /* NROUND[1] */ Ins_NROUND,
+ /* NROUND[2] */ Ins_NROUND,
+ /* NROUND[3] */ Ins_NROUND,
+
+ /* WCvtF */ Ins_WCVTF,
+ /* DeltaP2 */ Ins_DELTAP,
+ /* DeltaP3 */ Ins_DELTAP,
+ /* DeltaCn[0] */ Ins_DELTAC,
+ /* DeltaCn[1] */ Ins_DELTAC,
+ /* DeltaCn[2] */ Ins_DELTAC,
+ /* SROUND */ Ins_SROUND,
+ /* S45Round */ Ins_S45ROUND,
+ /* JROT */ Ins_JROT,
+ /* JROF */ Ins_JROF,
+ /* ROFF */ Ins_ROFF,
+ /* INS_0x7B */ Ins_UNKNOWN,
+ /* RUTG */ Ins_RUTG,
+ /* RDTG */ Ins_RDTG,
+ /* SANGW */ Ins_SANGW,
+ /* AA */ Ins_AA,
+
+ /* FlipPT */ Ins_FLIPPT,
+ /* FlipRgON */ Ins_FLIPRGON,
+ /* FlipRgOFF */ Ins_FLIPRGOFF,
+ /* INS_0x83 */ Ins_UNKNOWN,
+ /* INS_0x84 */ Ins_UNKNOWN,
+ /* ScanCTRL */ Ins_SCANCTRL,
+ /* SDPVTL[0] */ Ins_SDPVTL,
+ /* SDPVTL[1] */ Ins_SDPVTL,
+ /* GetINFO */ Ins_GETINFO,
+ /* IDEF */ Ins_IDEF,
+ /* ROLL */ Ins_ROLL,
+ /* MAX */ Ins_MAX,
+ /* MIN */ Ins_MIN,
+ /* ScanTYPE */ Ins_SCANTYPE,
+ /* InstCTRL */ Ins_INSTCTRL,
+ /* INS_0x8F */ Ins_UNKNOWN,
+
+ /* INS_0x90 */ Ins_UNKNOWN,
+ /* INS_0x91 */ Ins_UNKNOWN,
+ /* INS_0x92 */ Ins_UNKNOWN,
+ /* INS_0x93 */ Ins_UNKNOWN,
+ /* INS_0x94 */ Ins_UNKNOWN,
+ /* INS_0x95 */ Ins_UNKNOWN,
+ /* INS_0x96 */ Ins_UNKNOWN,
+ /* INS_0x97 */ Ins_UNKNOWN,
+ /* INS_0x98 */ Ins_UNKNOWN,
+ /* INS_0x99 */ Ins_UNKNOWN,
+ /* INS_0x9A */ Ins_UNKNOWN,
+ /* INS_0x9B */ Ins_UNKNOWN,
+ /* INS_0x9C */ Ins_UNKNOWN,
+ /* INS_0x9D */ Ins_UNKNOWN,
+ /* INS_0x9E */ Ins_UNKNOWN,
+ /* INS_0x9F */ Ins_UNKNOWN,
+
+ /* INS_0xA0 */ Ins_UNKNOWN,
+ /* INS_0xA1 */ Ins_UNKNOWN,
+ /* INS_0xA2 */ Ins_UNKNOWN,
+ /* INS_0xA3 */ Ins_UNKNOWN,
+ /* INS_0xA4 */ Ins_UNKNOWN,
+ /* INS_0xA5 */ Ins_UNKNOWN,
+ /* INS_0xA6 */ Ins_UNKNOWN,
+ /* INS_0xA7 */ Ins_UNKNOWN,
+ /* INS_0xA8 */ Ins_UNKNOWN,
+ /* INS_0xA9 */ Ins_UNKNOWN,
+ /* INS_0xAA */ Ins_UNKNOWN,
+ /* INS_0xAB */ Ins_UNKNOWN,
+ /* INS_0xAC */ Ins_UNKNOWN,
+ /* INS_0xAD */ Ins_UNKNOWN,
+ /* INS_0xAE */ Ins_UNKNOWN,
+ /* INS_0xAF */ Ins_UNKNOWN,
+
+ /* PushB[0] */ Ins_PUSHB,
+ /* PushB[1] */ Ins_PUSHB,
+ /* PushB[2] */ Ins_PUSHB,
+ /* PushB[3] */ Ins_PUSHB,
+ /* PushB[4] */ Ins_PUSHB,
+ /* PushB[5] */ Ins_PUSHB,
+ /* PushB[6] */ Ins_PUSHB,
+ /* PushB[7] */ Ins_PUSHB,
+ /* PushW[0] */ Ins_PUSHW,
+ /* PushW[1] */ Ins_PUSHW,
+ /* PushW[2] */ Ins_PUSHW,
+ /* PushW[3] */ Ins_PUSHW,
+ /* PushW[4] */ Ins_PUSHW,
+ /* PushW[5] */ Ins_PUSHW,
+ /* PushW[6] */ Ins_PUSHW,
+ /* PushW[7] */ Ins_PUSHW,
+
+ /* MDRP[00] */ Ins_MDRP,
+ /* MDRP[01] */ Ins_MDRP,
+ /* MDRP[02] */ Ins_MDRP,
+ /* MDRP[03] */ Ins_MDRP,
+ /* MDRP[04] */ Ins_MDRP,
+ /* MDRP[05] */ Ins_MDRP,
+ /* MDRP[06] */ Ins_MDRP,
+ /* MDRP[07] */ Ins_MDRP,
+ /* MDRP[08] */ Ins_MDRP,
+ /* MDRP[09] */ Ins_MDRP,
+ /* MDRP[10] */ Ins_MDRP,
+ /* MDRP[11] */ Ins_MDRP,
+ /* MDRP[12] */ Ins_MDRP,
+ /* MDRP[13] */ Ins_MDRP,
+ /* MDRP[14] */ Ins_MDRP,
+ /* MDRP[15] */ Ins_MDRP,
+
+ /* MDRP[16] */ Ins_MDRP,
+ /* MDRP[17] */ Ins_MDRP,
+ /* MDRP[18] */ Ins_MDRP,
+ /* MDRP[19] */ Ins_MDRP,
+ /* MDRP[20] */ Ins_MDRP,
+ /* MDRP[21] */ Ins_MDRP,
+ /* MDRP[22] */ Ins_MDRP,
+ /* MDRP[23] */ Ins_MDRP,
+ /* MDRP[24] */ Ins_MDRP,
+ /* MDRP[25] */ Ins_MDRP,
+ /* MDRP[26] */ Ins_MDRP,
+ /* MDRP[27] */ Ins_MDRP,
+ /* MDRP[28] */ Ins_MDRP,
+ /* MDRP[29] */ Ins_MDRP,
+ /* MDRP[30] */ Ins_MDRP,
+ /* MDRP[31] */ Ins_MDRP,
+
+ /* MIRP[00] */ Ins_MIRP,
+ /* MIRP[01] */ Ins_MIRP,
+ /* MIRP[02] */ Ins_MIRP,
+ /* MIRP[03] */ Ins_MIRP,
+ /* MIRP[04] */ Ins_MIRP,
+ /* MIRP[05] */ Ins_MIRP,
+ /* MIRP[06] */ Ins_MIRP,
+ /* MIRP[07] */ Ins_MIRP,
+ /* MIRP[08] */ Ins_MIRP,
+ /* MIRP[09] */ Ins_MIRP,
+ /* MIRP[10] */ Ins_MIRP,
+ /* MIRP[11] */ Ins_MIRP,
+ /* MIRP[12] */ Ins_MIRP,
+ /* MIRP[13] */ Ins_MIRP,
+ /* MIRP[14] */ Ins_MIRP,
+ /* MIRP[15] */ Ins_MIRP,
+
+ /* MIRP[16] */ Ins_MIRP,
+ /* MIRP[17] */ Ins_MIRP,
+ /* MIRP[18] */ Ins_MIRP,
+ /* MIRP[19] */ Ins_MIRP,
+ /* MIRP[20] */ Ins_MIRP,
+ /* MIRP[21] */ Ins_MIRP,
+ /* MIRP[22] */ Ins_MIRP,
+ /* MIRP[23] */ Ins_MIRP,
+ /* MIRP[24] */ Ins_MIRP,
+ /* MIRP[25] */ Ins_MIRP,
+ /* MIRP[26] */ Ins_MIRP,
+ /* MIRP[27] */ Ins_MIRP,
+ /* MIRP[28] */ Ins_MIRP,
+ /* MIRP[29] */ Ins_MIRP,
+ /* MIRP[30] */ Ins_MIRP,
+ /* MIRP[31] */ Ins_MIRP
+ };
+
+
+#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
+
+
+ /*************************************************************************/
+ /* */
+ /* RUN */
+ /* */
+ /* This function executes a run of opcodes. It will exit in the */
+ /* following cases: */
+ /* */
+ /* - Errors (in which case it returns FALSE). */
+ /* */
+ /* - Reaching the end of the main code range (returns TRUE). */
+ /* Reaching the end of a code range within a function call is an */
+ /* error. */
+ /* */
+ /* - After executing one single opcode, if the flag `Instruction_Trap' */
+ /* is set to TRUE (returns TRUE). */
+ /* */
+ /* On exit whith TRUE, test IP < CodeSize to know wether it comes from */
+ /* an instruction trap or a normal termination. */
+ /* */
+ /* */
+ /* Note: The documented DEBUG opcode pops a value from the stack. This */
+ /* behaviour is unsupported; here a DEBUG opcode is always an */
+ /* error. */
+ /* */
+ /* */
+ /* THIS IS THE INTERPRETER'S MAIN LOOP. */
+ /* */
+ /* Instructions appear in the specification's order. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_RunIns */
+ /* */
+ /* <Description> */
+ /* Executes one or more instruction in the execution context. This */
+ /* is the main function of the TrueType opcode interpreter. */
+ /* */
+ /* <Input> */
+ /* exec :: A handle to the target execution context. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only the object manager and debugger should call this function. */
+ /* */
+ /* This function is publicly exported because it is directly */
+ /* invoked by the TrueType debugger. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) TT_RunIns( TT_ExecContext exc )
+ {
+ FT_Long ins_counter = 0; /* executed instructions counter */
+
+
+#ifdef TT_CONFIG_OPTION_STATIC_RASTER
+ cur = *exc;
+#endif
+
+ /* set CVT functions */
+ CUR.tt_metrics.ratio = 0;
+ if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
+ {
+ /* non-square pixels, use the stretched routines */
+ CUR.func_read_cvt = Read_CVT_Stretched;
+ CUR.func_write_cvt = Write_CVT_Stretched;
+ CUR.func_move_cvt = Move_CVT_Stretched;
+ }
+ else
+ {
+ /* square pixels, use normal routines */
+ CUR.func_read_cvt = Read_CVT;
+ CUR.func_write_cvt = Write_CVT;
+ CUR.func_move_cvt = Move_CVT;
+ }
+
+ COMPUTE_Funcs();
+ COMPUTE_Round( (FT_Byte)exc->GS.round_state );
+
+ do
+ {
+ CUR.opcode = CUR.code[CUR.IP];
+
+ if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
+ {
+ if ( CUR.IP + 1 > CUR.codeSize )
+ goto LErrorCodeOverflow_;
+
+ CUR.length = CUR.code[CUR.IP + 1] + 2;
+ }
+
+ if ( CUR.IP + CUR.length > CUR.codeSize )
+ goto LErrorCodeOverflow_;
+
+ /* First, let's check for empty stack and overflow */
+ CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
+
+ /* `args' is the top of the stack once arguments have been popped. */
+ /* One can also interpret it as the index of the last argument. */
+ if ( CUR.args < 0 )
+ {
+ CUR.error = TT_Err_Too_Few_Arguments;
+ goto LErrorLabel_;
+ }
+
+ CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
+
+ /* `new_top' is the new top of the stack, after the instruction's */
+ /* execution. `top' will be set to `new_top' after the `switch' */
+ /* statement. */
+ if ( CUR.new_top > CUR.stackSize )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ goto LErrorLabel_;
+ }
+
+ CUR.step_ins = TRUE;
+ CUR.error = TT_Err_Ok;
+
+#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+ {
+ FT_Long* args = CUR.stack + CUR.args;
+ FT_Byte opcode = CUR.opcode;
+
+
+#undef ARRAY_BOUND_ERROR
+#define ARRAY_BOUND_ERROR goto Set_Invalid_Ref
+
+
+ switch ( opcode )
+ {
+ case 0x00: /* SVTCA y */
+ case 0x01: /* SVTCA x */
+ case 0x02: /* SPvTCA y */
+ case 0x03: /* SPvTCA x */
+ case 0x04: /* SFvTCA y */
+ case 0x05: /* SFvTCA x */
+ {
+ FT_Short AA, BB;
+
+
+ AA = (FT_Short)( opcode & 1 ) << 14;
+ BB = AA ^ (FT_Short)0x4000;
+
+ if ( opcode < 4 )
+ {
+ CUR.GS.projVector.x = AA;
+ CUR.GS.projVector.y = BB;
+
+ CUR.GS.dualVector.x = AA;
+ CUR.GS.dualVector.y = BB;
+ }
+
+ if ( ( opcode & 2 ) == 0 )
+ {
+ CUR.GS.freeVector.x = AA;
+ CUR.GS.freeVector.y = BB;
+ }
+
+ COMPUTE_Funcs();
+ }
+ break;
+
+ case 0x06: /* SPvTL // */
+ case 0x07: /* SPvTL + */
+ DO_SPVTL
+ break;
+
+ case 0x08: /* SFvTL // */
+ case 0x09: /* SFvTL + */
+ DO_SFVTL
+ break;
+
+ case 0x0A: /* SPvFS */
+ DO_SPVFS
+ break;
+
+ case 0x0B: /* SFvFS */
+ DO_SFVFS
+ break;
+
+ case 0x0C: /* GPV */
+ DO_GPV
+ break;
+
+ case 0x0D: /* GFV */
+ DO_GFV
+ break;
+
+ case 0x0E: /* SFvTPv */
+ DO_SFVTPV
+ break;
+
+ case 0x0F: /* ISECT */
+ Ins_ISECT( EXEC_ARG_ args );
+ break;
+
+ case 0x10: /* SRP0 */
+ DO_SRP0
+ break;
+
+ case 0x11: /* SRP1 */
+ DO_SRP1
+ break;
+
+ case 0x12: /* SRP2 */
+ DO_SRP2
+ break;
+
+ case 0x13: /* SZP0 */
+ Ins_SZP0( EXEC_ARG_ args );
+ break;
+
+ case 0x14: /* SZP1 */
+ Ins_SZP1( EXEC_ARG_ args );
+ break;
+
+ case 0x15: /* SZP2 */
+ Ins_SZP2( EXEC_ARG_ args );
+ break;
+
+ case 0x16: /* SZPS */
+ Ins_SZPS( EXEC_ARG_ args );
+ break;
+
+ case 0x17: /* SLOOP */
+ DO_SLOOP
+ break;
+
+ case 0x18: /* RTG */
+ DO_RTG
+ break;
+
+ case 0x19: /* RTHG */
+ DO_RTHG
+ break;
+
+ case 0x1A: /* SMD */
+ DO_SMD
+ break;
+
+ case 0x1B: /* ELSE */
+ Ins_ELSE( EXEC_ARG_ args );
+ break;
+
+ case 0x1C: /* JMPR */
+ DO_JMPR
+ break;
+
+ case 0x1D: /* SCVTCI */
+ DO_SCVTCI
+ break;
+
+ case 0x1E: /* SSWCI */
+ DO_SSWCI
+ break;
+
+ case 0x1F: /* SSW */
+ DO_SSW
+ break;
+
+ case 0x20: /* DUP */
+ DO_DUP
+ break;
+
+ case 0x21: /* POP */
+ /* nothing :-) */
+ break;
+
+ case 0x22: /* CLEAR */
+ DO_CLEAR
+ break;
+
+ case 0x23: /* SWAP */
+ DO_SWAP
+ break;
+
+ case 0x24: /* DEPTH */
+ DO_DEPTH
+ break;
+
+ case 0x25: /* CINDEX */
+ DO_CINDEX
+ break;
+
+ case 0x26: /* MINDEX */
+ Ins_MINDEX( EXEC_ARG_ args );
+ break;
+
+ case 0x27: /* ALIGNPTS */
+ Ins_ALIGNPTS( EXEC_ARG_ args );
+ break;
+
+ case 0x28: /* ???? */
+ Ins_UNKNOWN( EXEC_ARG_ args );
+ break;
+
+ case 0x29: /* UTP */
+ Ins_UTP( EXEC_ARG_ args );
+ break;
+
+ case 0x2A: /* LOOPCALL */
+ Ins_LOOPCALL( EXEC_ARG_ args );
+ break;
+
+ case 0x2B: /* CALL */
+ Ins_CALL( EXEC_ARG_ args );
+ break;
+
+ case 0x2C: /* FDEF */
+ Ins_FDEF( EXEC_ARG_ args );
+ break;
+
+ case 0x2D: /* ENDF */
+ Ins_ENDF( EXEC_ARG_ args );
+ break;
+
+ case 0x2E: /* MDAP */
+ case 0x2F: /* MDAP */
+ Ins_MDAP( EXEC_ARG_ args );
+ break;
+
+
+ case 0x30: /* IUP */
+ case 0x31: /* IUP */
+ Ins_IUP( EXEC_ARG_ args );
+ break;
+
+ case 0x32: /* SHP */
+ case 0x33: /* SHP */
+ Ins_SHP( EXEC_ARG_ args );
+ break;
+
+ case 0x34: /* SHC */
+ case 0x35: /* SHC */
+ Ins_SHC( EXEC_ARG_ args );
+ break;
+
+ case 0x36: /* SHZ */
+ case 0x37: /* SHZ */
+ Ins_SHZ( EXEC_ARG_ args );
+ break;
+
+ case 0x38: /* SHPIX */
+ Ins_SHPIX( EXEC_ARG_ args );
+ break;
+
+ case 0x39: /* IP */
+ Ins_IP( EXEC_ARG_ args );
+ break;
+
+ case 0x3A: /* MSIRP */
+ case 0x3B: /* MSIRP */
+ Ins_MSIRP( EXEC_ARG_ args );
+ break;
+
+ case 0x3C: /* AlignRP */
+ Ins_ALIGNRP( EXEC_ARG_ args );
+ break;
+
+ case 0x3D: /* RTDG */
+ DO_RTDG
+ break;
+
+ case 0x3E: /* MIAP */
+ case 0x3F: /* MIAP */
+ Ins_MIAP( EXEC_ARG_ args );
+ break;
+
+ case 0x40: /* NPUSHB */
+ Ins_NPUSHB( EXEC_ARG_ args );
+ break;
+
+ case 0x41: /* NPUSHW */
+ Ins_NPUSHW( EXEC_ARG_ args );
+ break;
+
+ case 0x42: /* WS */
+ DO_WS
+ break;
+
+ Set_Invalid_Ref:
+ CUR.error = TT_Err_Invalid_Reference;
+ break;
+
+ case 0x43: /* RS */
+ DO_RS
+ break;
+
+ case 0x44: /* WCVTP */
+ DO_WCVTP
+ break;
+
+ case 0x45: /* RCVT */
+ DO_RCVT
+ break;
+
+ case 0x46: /* GC */
+ case 0x47: /* GC */
+ Ins_GC( EXEC_ARG_ args );
+ break;
+
+ case 0x48: /* SCFS */
+ Ins_SCFS( EXEC_ARG_ args );
+ break;
+
+ case 0x49: /* MD */
+ case 0x4A: /* MD */
+ Ins_MD( EXEC_ARG_ args );
+ break;
+
+ case 0x4B: /* MPPEM */
+ DO_MPPEM
+ break;
+
+ case 0x4C: /* MPS */
+ DO_MPS
+ break;
+
+ case 0x4D: /* FLIPON */
+ DO_FLIPON
+ break;
+
+ case 0x4E: /* FLIPOFF */
+ DO_FLIPOFF
+ break;
+
+ case 0x4F: /* DEBUG */
+ DO_DEBUG
+ break;
+
+ case 0x50: /* LT */
+ DO_LT
+ break;
+
+ case 0x51: /* LTEQ */
+ DO_LTEQ
+ break;
+
+ case 0x52: /* GT */
+ DO_GT
+ break;
+
+ case 0x53: /* GTEQ */
+ DO_GTEQ
+ break;
+
+ case 0x54: /* EQ */
+ DO_EQ
+ break;
+
+ case 0x55: /* NEQ */
+ DO_NEQ
+ break;
+
+ case 0x56: /* ODD */
+ DO_ODD
+ break;
+
+ case 0x57: /* EVEN */
+ DO_EVEN
+ break;
+
+ case 0x58: /* IF */
+ Ins_IF( EXEC_ARG_ args );
+ break;
+
+ case 0x59: /* EIF */
+ /* do nothing */
+ break;
+
+ case 0x5A: /* AND */
+ DO_AND
+ break;
+
+ case 0x5B: /* OR */
+ DO_OR
+ break;
+
+ case 0x5C: /* NOT */
+ DO_NOT
+ break;
+
+ case 0x5D: /* DELTAP1 */
+ Ins_DELTAP( EXEC_ARG_ args );
+ break;
+
+ case 0x5E: /* SDB */
+ DO_SDB
+ break;
+
+ case 0x5F: /* SDS */
+ DO_SDS
+ break;
+
+ case 0x60: /* ADD */
+ DO_ADD
+ break;
+
+ case 0x61: /* SUB */
+ DO_SUB
+ break;
+
+ case 0x62: /* DIV */
+ DO_DIV
+ break;
+
+ case 0x63: /* MUL */
+ DO_MUL
+ break;
+
+ case 0x64: /* ABS */
+ DO_ABS
+ break;
+
+ case 0x65: /* NEG */
+ DO_NEG
+ break;
+
+ case 0x66: /* FLOOR */
+ DO_FLOOR
+ break;
+
+ case 0x67: /* CEILING */
+ DO_CEILING
+ break;
+
+ case 0x68: /* ROUND */
+ case 0x69: /* ROUND */
+ case 0x6A: /* ROUND */
+ case 0x6B: /* ROUND */
+ DO_ROUND
+ break;
+
+ case 0x6C: /* NROUND */
+ case 0x6D: /* NROUND */
+ case 0x6E: /* NRRUND */
+ case 0x6F: /* NROUND */
+ DO_NROUND
+ break;
+
+ case 0x70: /* WCVTF */
+ DO_WCVTF
+ break;
+
+ case 0x71: /* DELTAP2 */
+ case 0x72: /* DELTAP3 */
+ Ins_DELTAP( EXEC_ARG_ args );
+ break;
+
+ case 0x73: /* DELTAC0 */
+ case 0x74: /* DELTAC1 */
+ case 0x75: /* DELTAC2 */
+ Ins_DELTAC( EXEC_ARG_ args );
+ break;
+
+ case 0x76: /* SROUND */
+ DO_SROUND
+ break;
+
+ case 0x77: /* S45Round */
+ DO_S45ROUND
+ break;
+
+ case 0x78: /* JROT */
+ DO_JROT
+ break;
+
+ case 0x79: /* JROF */
+ DO_JROF
+ break;
+
+ case 0x7A: /* ROFF */
+ DO_ROFF
+ break;
+
+ case 0x7B: /* ???? */
+ Ins_UNKNOWN( EXEC_ARG_ args );
+ break;
+
+ case 0x7C: /* RUTG */
+ DO_RUTG
+ break;
+
+ case 0x7D: /* RDTG */
+ DO_RDTG
+ break;
+
+ case 0x7E: /* SANGW */
+ case 0x7F: /* AA */
+ /* nothing - obsolete */
+ break;
+
+ case 0x80: /* FLIPPT */
+ Ins_FLIPPT( EXEC_ARG_ args );
+ break;
+
+ case 0x81: /* FLIPRGON */
+ Ins_FLIPRGON( EXEC_ARG_ args );
+ break;
+
+ case 0x82: /* FLIPRGOFF */
+ Ins_FLIPRGOFF( EXEC_ARG_ args );
+ break;
+
+ case 0x83: /* UNKNOWN */
+ case 0x84: /* UNKNOWN */
+ Ins_UNKNOWN( EXEC_ARG_ args );
+ break;
+
+ case 0x85: /* SCANCTRL */
+ Ins_SCANCTRL( EXEC_ARG_ args );
+ break;
+
+ case 0x86: /* SDPVTL */
+ case 0x87: /* SDPVTL */
+ Ins_SDPVTL( EXEC_ARG_ args );
+ break;
+
+ case 0x88: /* GETINFO */
+ Ins_GETINFO( EXEC_ARG_ args );
+ break;
+
+ case 0x89: /* IDEF */
+ Ins_IDEF( EXEC_ARG_ args );
+ break;
+
+ case 0x8A: /* ROLL */
+ Ins_ROLL( EXEC_ARG_ args );
+ break;
+
+ case 0x8B: /* MAX */
+ DO_MAX
+ break;
+
+ case 0x8C: /* MIN */
+ DO_MIN
+ break;
+
+ case 0x8D: /* SCANTYPE */
+ Ins_SCANTYPE( EXEC_ARG_ args );
+ break;
+
+ case 0x8E: /* INSTCTRL */
+ Ins_INSTCTRL( EXEC_ARG_ args );
+ break;
+
+ case 0x8F:
+ Ins_UNKNOWN( EXEC_ARG_ args );
+ break;
+
+ default:
+ if ( opcode >= 0xE0 )
+ Ins_MIRP( EXEC_ARG_ args );
+ else if ( opcode >= 0xC0 )
+ Ins_MDRP( EXEC_ARG_ args );
+ else if ( opcode >= 0xB8 )
+ Ins_PUSHW( EXEC_ARG_ args );
+ else if ( opcode >= 0xB0 )
+ Ins_PUSHB( EXEC_ARG_ args );
+ else
+ Ins_UNKNOWN( EXEC_ARG_ args );
+ }
+
+ }
+
+#else
+
+ Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
+
+#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
+
+ if ( CUR.error != TT_Err_Ok )
+ {
+ switch ( CUR.error )
+ {
+ case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
+ {
+ TT_DefRecord* def = CUR.IDefs;
+ TT_DefRecord* limit = def + CUR.numIDefs;
+
+
+ for ( ; def < limit; def++ )
+ {
+ if ( def->active && CUR.opcode == def->opc )
+ {
+ TT_CallRec* callrec;
+
+
+ if ( CUR.callTop >= CUR.callSize )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ goto LErrorLabel_;
+ }
+
+ callrec = &CUR.callStack[CUR.callTop];
+
+ callrec->Caller_Range = CUR.curRange;
+ callrec->Caller_IP = CUR.IP + 1;
+ callrec->Cur_Count = 1;
+ callrec->Cur_Restart = def->start;
+
+ if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
+ goto LErrorLabel_;
+
+ goto LSuiteLabel_;
+ }
+ }
+ }
+
+ CUR.error = TT_Err_Invalid_Opcode;
+ goto LErrorLabel_;
+
+#if 0
+ break; /* Unreachable code warning suppression. */
+ /* Leave to remind in case a later change the editor */
+ /* to consider break; */
+#endif
+
+ default:
+ goto LErrorLabel_;
+
+#if 0
+ break;
+#endif
+ }
+ }
+
+ CUR.top = CUR.new_top;
+
+ if ( CUR.step_ins )
+ CUR.IP += CUR.length;
+
+ /* increment instruction counter and check if we didn't */
+ /* run this program for too long (e.g. infinite loops). */
+ if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
+ return TT_Err_Execution_Too_Long;
+
+ LSuiteLabel_:
+ if ( CUR.IP >= CUR.codeSize )
+ {
+ if ( CUR.callTop > 0 )
+ {
+ CUR.error = TT_Err_Code_Overflow;
+ goto LErrorLabel_;
+ }
+ else
+ goto LNo_Error_;
+ }
+ } while ( !CUR.instruction_trap );
+
+ LNo_Error_:
+
+#ifdef TT_CONFIG_OPTION_STATIC_RASTER
+ *exc = cur;
+#endif
+
+ return TT_Err_Ok;
+
+ LErrorCodeOverflow_:
+ CUR.error = TT_Err_Code_Overflow;
+
+ LErrorLabel_:
+
+#ifdef TT_CONFIG_OPTION_STATIC_RASTER
+ *exc = cur;
+#endif
+
+ return CUR.error;
+ }
+
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttinterp.h */
+/* */
+/* TrueType bytecode interpreter (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef TTINTERP_H
+#define TTINTERP_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttobjs.h"
+
+#else
+
+#include <truetype/ttobjs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+#ifndef TT_CONFIG_OPTION_STATIC_INTEPRETER /* indirect implementation */
+
+#define EXEC_OP_ TT_ExecContext exc,
+#define EXEC_OP TT_ExecContext exc
+#define EXEC_ARG_ exc,
+#define EXEC_ARG exc
+
+#else /* static implementation */
+
+#define EXEC_OP_ /* void */
+#define EXEC_OP /* void */
+#define EXEC_ARG_ /* void */
+#define EXEC_ARG /* void */
+
+#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
+
+
+ /*************************************************************************/
+ /* */
+ /* Rounding mode constants. */
+ /* */
+#define TT_Round_Off 5
+#define TT_Round_To_Half_Grid 0
+#define TT_Round_To_Grid 1
+#define TT_Round_To_Double_Grid 2
+#define TT_Round_Up_To_Grid 4
+#define TT_Round_Down_To_Grid 3
+#define TT_Round_Super 6
+#define TT_Round_Super_45 7
+
+
+ /*************************************************************************/
+ /* */
+ /* Function types used by the interpreter, depending on various modes */
+ /* (e.g. the rounding mode, whether to render a vertical or horizontal */
+ /* line etc). */
+ /* */
+ /*************************************************************************/
+
+ /* Rounding function */
+ typedef FT_F26Dot6 (*TT_Round_Func)( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation );
+
+ /* Point displacement along the freedom vector routine */
+ typedef void (*TT_Move_Func)( EXEC_OP_ TT_GlyphZone* zone,
+ FT_UInt point,
+ FT_F26Dot6 distance );
+
+ /* Distance projection along one of the projection vectors */
+ typedef FT_F26Dot6 (*TT_Project_Func)( EXEC_OP_ FT_Vector* v1,
+ FT_Vector* v2 );
+
+ /* reading a cvt value. Take care of non-square pixels if necessary */
+ typedef FT_F26Dot6 (*TT_Get_CVT_Func)( EXEC_OP_ FT_ULong index );
+
+ /* setting or moving a cvt value. Take care of non-square pixels */
+ /* if necessary */
+ typedef void (*TT_Set_CVT_Func)( EXEC_OP_ FT_ULong index,
+ FT_F26Dot6 value );
+
+
+ /*************************************************************************/
+ /* */
+ /* This structure defines a call record, used to manage function calls. */
+ /* */
+ typedef struct TT_CallRec_
+ {
+ FT_Int Caller_Range;
+ FT_Long Caller_IP;
+ FT_Long Cur_Count;
+ FT_Long Cur_Restart;
+
+ } TT_CallRec, *TT_CallStack;
+
+
+ /*************************************************************************/
+ /* */
+ /* The main structure for the interpreter which collects all necessary */
+ /* variables and states. */
+ /* */
+ typedef struct TT_ExecContextRec_
+ {
+ TT_Face face;
+ TT_Size size;
+ FT_Memory memory;
+
+ /* instructions state */
+
+ FT_Error error; /* last execution error */
+
+ FT_Long top; /* top of exec. stack */
+
+ FT_UInt stackSize; /* size of exec. stack */
+ FT_Long* stack; /* current exec. stack */
+
+ FT_Long args;
+ FT_UInt new_top; /* new top after exec. */
+
+ TT_GlyphZone zp0, /* zone records */
+ zp1,
+ zp2,
+ pts,
+ twilight;
+
+ FT_Size_Metrics metrics;
+ TT_Size_Metrics tt_metrics; /* size metrics */
+
+ TT_GraphicsState GS; /* current graphics state */
+
+ FT_Int curRange; /* current code range number */
+ FT_Byte* code; /* current code range */
+ FT_Long IP; /* current instruction pointer */
+ FT_Long codeSize; /* size of current range */
+
+ FT_Byte opcode; /* current opcode */
+ FT_Int length; /* length of current opcode */
+
+ FT_Bool step_ins; /* true if the interpreter must */
+ /* increment IP after ins. exec */
+ FT_Long cvtSize;
+ FT_Long* cvt;
+
+ FT_UInt glyphSize; /* glyph instructions buffer size */
+ FT_Byte* glyphIns; /* glyph instructions buffer */
+
+ FT_UInt numFDefs; /* number of function defs */
+ FT_UInt maxFDefs; /* maximum number of function defs */
+ TT_DefArray FDefs; /* table of FDefs entries */
+
+ FT_UInt numIDefs; /* number of instruction defs */
+ FT_UInt maxIDefs; /* maximum number of ins defs */
+ TT_DefArray IDefs; /* table of IDefs entries */
+
+ FT_UInt maxFunc; /* maximum function index */
+ FT_UInt maxIns; /* maximum instruction index */
+
+ FT_Int callTop, /* top of call stack during execution */
+ callSize; /* size of call stack */
+ TT_CallStack callStack; /* call stack */
+
+ FT_UShort maxPoints; /* capacity of this context's `pts' */
+ FT_Short maxContours; /* record, expressed in points and */
+ /* contours. */
+
+ TT_CodeRangeTable codeRangeTable; /* table of valid code ranges */
+ /* useful for the debugger */
+
+ FT_UShort storeSize; /* size of current storage */
+ FT_Long* storage; /* storage area */
+
+ FT_F26Dot6 period; /* values used for the */
+ FT_F26Dot6 phase; /* `SuperRounding' */
+ FT_F26Dot6 threshold;
+
+#if 0
+ /* this seems to be unused */
+ FT_Int cur_ppem; /* ppem along the current proj vector */
+#endif
+
+ FT_Bool instruction_trap; /* If `True', the interpreter will */
+ /* exit after each instruction */
+
+ TT_GraphicsState default_GS; /* graphics state resulting from */
+ /* the prep program */
+ FT_Bool is_composite; /* true if the glyph is composite */
+ FT_Bool pedantic_hinting; /* true for pedantic interpretation */
+
+ /* latest interpreter additions */
+
+ FT_Long F_dot_P; /* dot product of freedom and projection */
+ /* vectors */
+ TT_Round_Func func_round; /* current rounding function */
+
+ TT_Project_Func func_project, /* current projection function */
+ func_dualproj, /* current dual proj. function */
+ func_freeProj; /* current freedom proj. func */
+
+ TT_Move_Func func_move; /* current point move function */
+
+ TT_Get_CVT_Func func_read_cvt; /* read a cvt entry */
+ TT_Set_CVT_Func func_write_cvt; /* write a cvt entry (in pixels) */
+ TT_Set_CVT_Func func_move_cvt; /* incr a cvt entry (in pixels) */
+
+ FT_ULong loadSize;
+ TT_SubGlyph_Stack loadStack; /* loading subglyph stack */
+
+ } TT_ExecContextRec;
+
+
+ extern const TT_GraphicsState tt_default_graphics_state;
+
+
+ LOCAL_DEF
+ FT_Error TT_Goto_CodeRange( TT_ExecContext exec,
+ FT_Int range,
+ FT_Long IP );
+
+ LOCAL_DEF
+ FT_Error TT_Set_CodeRange( TT_ExecContext exec,
+ FT_Int range,
+ void* base,
+ FT_Long length );
+
+ LOCAL_DEF
+ FT_Error TT_Clear_CodeRange( TT_ExecContext exec,
+ FT_Int range );
+
+ FT_EXPORT_DEF( TT_ExecContext ) TT_New_Context( TT_Face face );
+
+ LOCAL_DEF
+ FT_Error TT_Done_Context( TT_ExecContext exec );
+
+ LOCAL_DEF
+ FT_Error TT_Destroy_Context( TT_ExecContext exec,
+ FT_Memory memory );
+
+ LOCAL_DEF
+ FT_Error TT_Load_Context( TT_ExecContext exec,
+ TT_Face face,
+ TT_Size size );
+
+ LOCAL_DEF
+ FT_Error TT_Save_Context( TT_ExecContext exec,
+ TT_Size ins );
+
+ LOCAL_DEF
+ FT_Error TT_Run_Context( TT_ExecContext exec,
+ FT_Bool debug );
+
+ FT_EXPORT_DEF( FT_Error ) TT_RunIns( TT_ExecContext exec );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* TTINTERP_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttobjs.c */
+/* */
+/* Objects manager (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/ttnameid.h>
+#include <freetype/tttags.h>
+
+#include <freetype/internal/sfnt.h>
+#include <freetype/internal/psnames.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttgload.h"
+#include "ttpload.h"
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#include "ttinterp.h"
+#endif
+
+#else /* FT_FLAT_COMPILE */
+
+#include <truetype/ttgload.h>
+#include <truetype/ttpload.h>
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#include <truetype/ttinterp.h>
+#endif
+
+#endif /* FT_FLAT_COMPILE */
+
+
+#include <freetype/internal/tterrors.h>
+
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttobjs
+
+
+ /*************************************************************************/
+ /* */
+ /* GLYPH ZONE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Done_GlyphZone */
+ /* */
+ /* <Description> */
+ /* Deallocates a glyph zone. */
+ /* */
+ /* <Input> */
+ /* zone :: A pointer to the target glyph zone. */
+ /* */
+ LOCAL_FUNC
+ void TT_Done_GlyphZone( TT_GlyphZone* zone )
+ {
+ FT_Memory memory = zone->memory;
+
+
+ FREE( zone->contours );
+ FREE( zone->tags );
+ FREE( zone->cur );
+ FREE( zone->org );
+
+ zone->max_points = zone->n_points = 0;
+ zone->max_contours = zone->n_contours = 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_New_GlyphZone */
+ /* */
+ /* <Description> */
+ /* Allocates a new glyph zone. */
+ /* */
+ /* <Input> */
+ /* memory :: A handle to the current memory object. */
+ /* */
+ /* maxPoints :: The capacity of glyph zone in points. */
+ /* */
+ /* maxContours :: The capacity of glyph zone in contours. */
+ /* */
+ /* <Output> */
+ /* zone :: A pointer to the target glyph zone record. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_New_GlyphZone( FT_Memory memory,
+ FT_UShort maxPoints,
+ FT_Short maxContours,
+ TT_GlyphZone* zone )
+ {
+ FT_Error error;
+
+
+ if ( maxPoints > 0 )
+ maxPoints += 2;
+
+ MEM_Set( zone, 0, sizeof ( *zone ) );
+ zone->memory = memory;
+
+ if ( ALLOC_ARRAY( zone->org, maxPoints * 2, FT_F26Dot6 ) ||
+ ALLOC_ARRAY( zone->cur, maxPoints * 2, FT_F26Dot6 ) ||
+ ALLOC_ARRAY( zone->tags, maxPoints, FT_Byte ) ||
+ ALLOC_ARRAY( zone->contours, maxContours, FT_UShort ) )
+ {
+ TT_Done_GlyphZone( zone );
+ }
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Init_Face */
+ /* */
+ /* <Description> */
+ /* Initializes a given TrueType face object. */
+ /* */
+ /* <Input> */
+ /* stream :: The source font stream. */
+ /* */
+ /* face_index :: The index of the font face in the resource. */
+ /* */
+ /* num_params :: Number of additional generic parameters. Ignored. */
+ /* */
+ /* params :: Additional generic parameters. Ignored. */
+ /* */
+ /* <InOut> */
+ /* face :: The newly built face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_DEF
+ FT_Error TT_Init_Face( FT_Stream stream,
+ TT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error;
+ FT_Library library;
+ SFNT_Interface* sfnt;
+
+
+ library = face->root.driver->root.library;
+ sfnt = (SFNT_Interface*)FT_Get_Module_Interface( library, "sfnt" );
+ if ( !sfnt )
+ goto Bad_Format;
+
+ /* create input stream from resource */
+ if ( FILE_Seek( 0 ) )
+ goto Exit;
+
+ /* check that we have a valid TrueType file */
+ error = sfnt->init_face( stream, face, face_index, num_params, params );
+ if ( error )
+ goto Exit;
+
+ /* We must also be able to accept Mac/GX fonts, as well as OT ones */
+ if ( face->format_tag != 0x00010000L && /* MS fonts */
+ face->format_tag != TTAG_true ) /* Mac fonts */
+ {
+ FT_TRACE2(( "[not a valid TTF font]\n" ));
+ goto Bad_Format;
+ }
+
+ /* If we are performing a simple font format check, exit immediately */
+ if ( face_index < 0 )
+ return TT_Err_Ok;
+
+ /* Load font directory */
+ error = sfnt->load_face( stream, face, face_index, num_params, params );
+ if ( error )
+ goto Exit;
+
+ error = TT_Load_Locations( face, stream ) ||
+ TT_Load_CVT ( face, stream ) ||
+ TT_Load_Programs ( face, stream );
+
+ /* initialize standard glyph loading routines */
+ TT_Init_Glyph_Loading( face );
+
+ Exit:
+ return error;
+
+ Bad_Format:
+ error = FT_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Done_Face */
+ /* */
+ /* <Description> */
+ /* Finalizes a given face object. */
+ /* */
+ /* <Input> */
+ /* face :: A pointer to the face object to destroy. */
+ /* */
+ LOCAL_DEF
+ void TT_Done_Face( TT_Face face )
+ {
+ FT_Memory memory = face->root.memory;
+ FT_Stream stream = face->root.stream;
+
+ SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt;
+
+
+ /* for `extended TrueType formats' (i.e. compressed versions) */
+ if ( face->extra.finalizer )
+ face->extra.finalizer( face->extra.data );
+
+ if ( sfnt )
+ sfnt->done_face( face );
+
+ /* freeing the locations table */
+ FREE( face->glyph_locations );
+ face->num_locations = 0;
+
+ /* freeing the CVT */
+ FREE( face->cvt );
+ face->cvt_size = 0;
+
+ /* freeing the programs */
+ RELEASE_Frame( face->font_program );
+ RELEASE_Frame( face->cvt_program );
+ face->font_program_size = 0;
+ face->cvt_program_size = 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SIZE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Init_Size */
+ /* */
+ /* <Description> */
+ /* Initializes a new TrueType size object. */
+ /* */
+ /* <InOut> */
+ /* size :: A handle to the size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_DEF
+ FT_Error TT_Init_Size( TT_Size size )
+ {
+ FT_Error error = TT_Err_Ok;
+
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+ TT_Face face = (TT_Face)size->root.face;
+ FT_Memory memory = face->root.memory;
+ FT_Int i;
+
+ TT_ExecContext exec;
+ FT_UShort n_twilight;
+ TT_MaxProfile* maxp = &face->max_profile;
+
+
+ size->ttmetrics.valid = FALSE;
+
+ size->max_function_defs = maxp->maxFunctionDefs;
+ size->max_instruction_defs = maxp->maxInstructionDefs;
+
+ size->num_function_defs = 0;
+ size->num_instruction_defs = 0;
+
+ size->max_func = 0;
+ size->max_ins = 0;
+
+ size->cvt_size = face->cvt_size;
+ size->storage_size = maxp->maxStorage;
+
+ /* Set default metrics */
+ {
+ FT_Size_Metrics* metrics = &size->root.metrics;
+ TT_Size_Metrics* metrics2 = &size->ttmetrics;
+
+
+ metrics->x_ppem = 0;
+ metrics->y_ppem = 0;
+
+ metrics2->rotated = FALSE;
+ metrics2->stretched = FALSE;
+
+ /* set default compensation (all 0) */
+ for ( i = 0; i < 4; i++ )
+ metrics2->compensations[i] = 0;
+ }
+
+ /* allocate function defs, instruction defs, cvt, and storage area */
+ if ( ALLOC_ARRAY( size->function_defs,
+ size->max_function_defs,
+ TT_DefRecord ) ||
+
+ ALLOC_ARRAY( size->instruction_defs,
+ size->max_instruction_defs,
+ TT_DefRecord ) ||
+
+ ALLOC_ARRAY( size->cvt,
+ size->cvt_size, FT_Long ) ||
+
+ ALLOC_ARRAY( size->storage,
+ size->storage_size, FT_Long ) )
+
+ goto Fail_Memory;
+
+ /* reserve twilight zone */
+ n_twilight = maxp->maxTwilightPoints;
+ error = TT_New_GlyphZone( memory, n_twilight, 0, &size->twilight );
+ if ( error )
+ goto Fail_Memory;
+
+ size->twilight.n_points = n_twilight;
+
+ /* set `face->interpreter' according to the debug hook present */
+ {
+ FT_Library library = face->root.driver->root.library;
+
+
+ face->interpreter = (TT_Interpreter)
+ library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE];
+ if ( !face->interpreter )
+ face->interpreter = (TT_Interpreter)TT_RunIns;
+ }
+
+ /* Fine, now execute the font program! */
+ exec = size->context;
+ /* size objects used during debugging have their own context */
+ if ( !size->debug )
+ exec = TT_New_Context( face );
+
+ if ( !exec )
+ {
+ error = TT_Err_Could_Not_Find_Context;
+ goto Fail_Memory;
+ }
+
+ size->GS = tt_default_graphics_state;
+ TT_Load_Context( exec, face, size );
+
+ exec->callTop = 0;
+ exec->top = 0;
+
+ exec->period = 64;
+ exec->phase = 0;
+ exec->threshold = 0;
+
+ {
+ FT_Size_Metrics* metrics = &exec->metrics;
+ TT_Size_Metrics* tt_metrics = &exec->tt_metrics;
+
+
+ metrics->x_ppem = 0;
+ metrics->y_ppem = 0;
+ metrics->x_scale = 0;
+ metrics->y_scale = 0;
+
+ tt_metrics->ppem = 0;
+ tt_metrics->scale = 0;
+ tt_metrics->ratio = 0x10000L;
+ }
+
+ exec->instruction_trap = FALSE;
+
+ exec->cvtSize = size->cvt_size;
+ exec->cvt = size->cvt;
+
+ exec->F_dot_P = 0x10000L;
+
+ /* allow font program execution */
+ TT_Set_CodeRange( exec,
+ tt_coderange_font,
+ face->font_program,
+ face->font_program_size );
+
+ /* disable CVT and glyph programs coderange */
+ TT_Clear_CodeRange( exec, tt_coderange_cvt );
+ TT_Clear_CodeRange( exec, tt_coderange_glyph );
+
+ if ( face->font_program_size > 0 )
+ {
+ error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
+ if ( !error )
+ error = face->interpreter( exec );
+
+ if ( error )
+ goto Fail_Exec;
+ }
+ else
+ error = TT_Err_Ok;
+
+ TT_Save_Context( exec, size );
+
+ if ( !size->debug )
+ TT_Done_Context( exec );
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+ size->ttmetrics.valid = FALSE;
+ return error;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+ Fail_Exec:
+ if ( !size->debug )
+ TT_Done_Context( exec );
+
+ Fail_Memory:
+
+#endif
+
+ TT_Done_Size( size );
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Done_Size */
+ /* */
+ /* <Description> */
+ /* The TrueType size object finalizer. */
+ /* */
+ /* <Input> */
+ /* size :: A handle to the target size object. */
+ /* */
+ LOCAL_FUNC
+ void TT_Done_Size( TT_Size size )
+ {
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+ FT_Memory memory = size->root.face->memory;
+
+
+ if ( size->debug )
+ {
+ /* the debug context must be deleted by the debugger itself */
+ size->context = NULL;
+ size->debug = FALSE;
+ }
+
+ FREE( size->cvt );
+ size->cvt_size = 0;
+
+ /* free storage area */
+ FREE( size->storage );
+ size->storage_size = 0;
+
+ /* twilight zone */
+ TT_Done_GlyphZone( &size->twilight );
+
+ FREE( size->function_defs );
+ FREE( size->instruction_defs );
+
+ size->num_function_defs = 0;
+ size->max_function_defs = 0;
+ size->num_instruction_defs = 0;
+ size->max_instruction_defs = 0;
+
+ size->max_func = 0;
+ size->max_ins = 0;
+
+#endif
+
+ size->ttmetrics.valid = FALSE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Reset_Size */
+ /* */
+ /* <Description> */
+ /* Resets a TrueType size when resolutions and character dimensions */
+ /* have been changed. */
+ /* */
+ /* <Input> */
+ /* size :: A handle to the target size object. */
+ /* */
+ LOCAL_DEF
+ FT_Error TT_Reset_Size( TT_Size size )
+ {
+ TT_Face face;
+ FT_Error error = TT_Err_Ok;
+
+ FT_Size_Metrics* metrics;
+
+
+ if ( size->ttmetrics.valid )
+ return TT_Err_Ok;
+
+ face = (TT_Face)size->root.face;
+
+ metrics = &size->root.metrics;
+
+ if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
+ return TT_Err_Invalid_PPem;
+
+ /* compute new transformation */
+ if ( metrics->x_ppem >= metrics->y_ppem )
+ {
+ size->ttmetrics.scale = metrics->x_scale;
+ size->ttmetrics.ppem = metrics->x_ppem;
+ size->ttmetrics.x_ratio = 0x10000L;
+ size->ttmetrics.y_ratio = FT_MulDiv( metrics->y_ppem,
+ 0x10000L,
+ metrics->x_ppem );
+ }
+ else
+ {
+ size->ttmetrics.scale = metrics->y_scale;
+ size->ttmetrics.ppem = metrics->y_ppem;
+ size->ttmetrics.x_ratio = FT_MulDiv( metrics->x_ppem,
+ 0x10000L,
+ metrics->y_ppem );
+ size->ttmetrics.y_ratio = 0x10000L;
+ }
+
+ /* Compute root ascender, descender, test height, and max_advance */
+ metrics->ascender = ( FT_MulFix( face->root.ascender,
+ metrics->y_scale ) + 32 ) & -64;
+ metrics->descender = ( FT_MulFix( face->root.descender,
+ metrics->y_scale ) + 32 ) & -64;
+ metrics->height = ( FT_MulFix( face->root.height,
+ metrics->y_scale ) + 32 ) & -64;
+ metrics->max_advance = ( FT_MulFix( face->root.max_advance_width,
+ metrics->x_scale ) + 32 ) & -64;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+ {
+ TT_ExecContext exec;
+ FT_UInt i, j;
+
+
+ /* Scale the cvt values to the new ppem. */
+ /* We use by default the y ppem to scale the CVT. */
+ for ( i = 0; i < size->cvt_size; i++ )
+ size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
+
+ /* All twilight points are originally zero */
+ for ( j = 0; j < size->twilight.n_points; j++ )
+ {
+ size->twilight.org[j].x = 0;
+ size->twilight.org[j].y = 0;
+ size->twilight.cur[j].x = 0;
+ size->twilight.cur[j].y = 0;
+ }
+
+ /* clear storage area */
+ for ( i = 0; i < size->storage_size; i++ )
+ size->storage[i] = 0;
+
+ size->GS = tt_default_graphics_state;
+
+ /* get execution context and run prep program */
+ if ( size->debug )
+ exec = size->context;
+ else
+ exec = TT_New_Context( face );
+ /* debugging instances have their own context */
+
+ if ( !exec )
+ return TT_Err_Could_Not_Find_Context;
+
+ TT_Load_Context( exec, face, size );
+
+ TT_Set_CodeRange( exec,
+ tt_coderange_cvt,
+ face->cvt_program,
+ face->cvt_program_size );
+
+ TT_Clear_CodeRange( exec, tt_coderange_glyph );
+
+ exec->instruction_trap = FALSE;
+
+ exec->top = 0;
+ exec->callTop = 0;
+
+ if ( face->cvt_program_size > 0 )
+ {
+ error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
+ if ( error )
+ goto End;
+
+ if ( !size->debug )
+ error = face->interpreter( exec );
+ }
+ else
+ error = TT_Err_Ok;
+
+ size->GS = exec->GS;
+ /* save default graphics state */
+
+ End:
+ TT_Save_Context( exec, size );
+
+ if ( !size->debug )
+ TT_Done_Context( exec );
+ /* debugging instances keep their context */
+ }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+ if ( !error )
+ size->ttmetrics.valid = TRUE;
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Init_Driver */
+ /* */
+ /* <Description> */
+ /* Initializes a given TrueType driver object. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target driver object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Init_Driver( TT_Driver driver )
+ {
+ FT_Error error;
+
+
+ /* set `extra' in glyph loader */
+ error = FT_GlyphLoader_Create_Extra( FT_DRIVER( driver )->glyph_loader );
+
+ /* init extension registry if needed */
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+ if ( !error )
+ return TT_Init_Extensions( driver );
+#endif
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Done_Driver */
+ /* */
+ /* <Description> */
+ /* Finalizes a given TrueType driver. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target TrueType driver. */
+ /* */
+ LOCAL_FUNC
+ void TT_Done_Driver( TT_Driver driver )
+ {
+ /* destroy extensions registry if needed */
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+
+ TT_Done_Extensions( driver );
+
+#endif
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+ /* destroy the execution context */
+ if ( driver->context )
+ {
+ TT_Destroy_Context( driver->context, driver->root.root.memory );
+ driver->context = NULL;
+ }
+
+#endif
+
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttobjs.h */
+/* */
+/* Objects manager (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef TTOBJS_H
+#define TTOBJS_H
+
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/tttypes.h>
+#include <freetype/internal/tterrors.h>
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* TT_Driver */
+ /* */
+ /* <Description> */
+ /* A handle to a TrueType driver object. */
+ /* */
+ typedef struct TT_DriverRec_* TT_Driver;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* TT_Instance */
+ /* */
+ /* <Description> */
+ /* A handle to a TrueType size object. */
+ /* */
+ typedef struct TT_SizeRec_* TT_Size;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* TT_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* A handle to a TrueType glyph slot object. */
+ /* */
+ /* <Note> */
+ /* This is a direct typedef of FT_GlyphSlot, as there is nothing */
+ /* specific about the TrueType glyph slot. */
+ /* */
+ typedef FT_GlyphSlot TT_GlyphSlot;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_GraphicsState */
+ /* */
+ /* <Description> */
+ /* The TrueType graphics state used during bytecode interpretation. */
+ /* */
+ typedef struct TT_GraphicsState_
+ {
+ FT_UShort rp0;
+ FT_UShort rp1;
+ FT_UShort rp2;
+
+ FT_UnitVector dualVector;
+ FT_UnitVector projVector;
+ FT_UnitVector freeVector;
+
+ FT_Long loop;
+ FT_F26Dot6 minimum_distance;
+ FT_Int round_state;
+
+ FT_Bool auto_flip;
+ FT_F26Dot6 control_value_cutin;
+ FT_F26Dot6 single_width_cutin;
+ FT_F26Dot6 single_width_value;
+ FT_Short delta_base;
+ FT_Short delta_shift;
+
+ FT_Byte instruct_control;
+ FT_Bool scan_control;
+ FT_Int scan_type;
+
+ FT_UShort gep0;
+ FT_UShort gep1;
+ FT_UShort gep2;
+
+ } TT_GraphicsState;
+
+
+ LOCAL_DEF void TT_Done_GlyphZone( TT_GlyphZone* zone );
+
+ LOCAL_DEF FT_Error TT_New_GlyphZone( FT_Memory memory,
+ FT_UShort maxPoints,
+ FT_Short maxContours,
+ TT_GlyphZone* zone );
+
+
+ /*************************************************************************/
+ /* */
+ /* EXECUTION SUBTABLES */
+ /* */
+ /* These sub-tables relate to instruction execution. */
+ /* */
+ /*************************************************************************/
+
+
+#define TT_MAX_CODE_RANGES 3
+
+
+ /*************************************************************************/
+ /* */
+ /* There can only be 3 active code ranges at once: */
+ /* - the Font Program */
+ /* - the CVT Program */
+ /* - a glyph's instructions set */
+ /* */
+ typedef enum TT_CodeRange_Tag_
+ {
+ tt_coderange_none = 0,
+ tt_coderange_font,
+ tt_coderange_cvt,
+ tt_coderange_glyph
+
+ } TT_CodeRange_Tag;
+
+
+ typedef struct TT_CodeRange_
+ {
+ FT_Byte* base;
+ FT_ULong size;
+
+ } TT_CodeRange;
+
+ typedef TT_CodeRange TT_CodeRangeTable[TT_MAX_CODE_RANGES];
+
+
+ /*************************************************************************/
+ /* */
+ /* Defines a function/instruction definition record. */
+ /* */
+ typedef struct TT_DefRecord_
+ {
+ FT_Int range; /* in which code range is it located? */
+ FT_Long start; /* where does it start? */
+ FT_UInt opc; /* function #, or instruction code */
+ FT_Bool active; /* is it active? */
+
+ } TT_DefRecord, *TT_DefArray;
+
+
+ /*************************************************************************/
+ /* */
+ /* Subglyph transformation record. */
+ /* */
+ typedef struct TT_Transform_
+ {
+ FT_Fixed xx, xy; /* transformation matrix coefficients */
+ FT_Fixed yx, yy;
+ FT_F26Dot6 ox, oy; /* offsets */
+
+ } TT_Transform;
+
+
+ /*************************************************************************/
+ /* */
+ /* Subglyph loading record. Used to load composite components. */
+ /* */
+ typedef struct TT_SubglyphRec_
+ {
+ FT_Long index; /* subglyph index; initialized with -1 */
+ FT_Bool is_scaled; /* is the subglyph scaled? */
+ FT_Bool is_hinted; /* should it be hinted? */
+ FT_Bool preserve_pps; /* preserve phantom points? */
+
+ FT_Long file_offset;
+
+ FT_BBox bbox;
+ FT_Pos left_bearing;
+ FT_Pos advance;
+
+ TT_GlyphZone zone;
+
+ FT_Long arg1; /* first argument */
+ FT_Long arg2; /* second argument */
+
+ FT_UShort element_flag; /* current load element flag */
+
+ TT_Transform transform; /* transformation matrix */
+
+ FT_Vector pp1, pp2; /* phantom points */
+
+ } TT_SubGlyphRec, *TT_SubGlyph_Stack;
+
+
+ /*************************************************************************/
+ /* */
+ /* A note regarding non-squared pixels: */
+ /* */
+ /* (This text will probably go into some docs at some time; for now, it */
+ /* is kept here to explain some definitions in the TIns_Metrics */
+ /* record). */
+ /* */
+ /* The CVT is a one-dimensional array containing values that control */
+ /* certain important characteristics in a font, like the height of all */
+ /* capitals, all lowercase letter, default spacing or stem width/height. */
+ /* */
+ /* These values are found in FUnits in the font file, and must be scaled */
+ /* to pixel coordinates before being used by the CVT and glyph programs. */
+ /* Unfortunately, when using distinct x and y resolutions (or distinct x */
+ /* and y pointsizes), there are two possible scalings. */
+ /* */
+ /* A first try was to implement a `lazy' scheme where all values were */
+ /* scaled when first used. However, while some values are always used */
+ /* in the same direction, some others are used under many different */
+ /* circumstances and orientations. */
+ /* */
+ /* I have found a simpler way to do the same, and it even seems to work */
+ /* in most of the cases: */
+ /* */
+ /* - All CVT values are scaled to the maximum ppem size. */
+ /* */
+ /* - When performing a read or write in the CVT, a ratio factor is used */
+ /* to perform adequate scaling. Example: */
+ /* */
+ /* x_ppem = 14 */
+ /* y_ppem = 10 */
+ /* */
+ /* We choose ppem = x_ppem = 14 as the CVT scaling size. All cvt */
+ /* entries are scaled to it. */
+ /* */
+ /* x_ratio = 1.0 */
+ /* y_ratio = y_ppem/ppem (< 1.0) */
+ /* */
+ /* We compute the current ratio like: */
+ /* */
+ /* - If projVector is horizontal, */
+ /* ratio = x_ratio = 1.0 */
+ /* */
+ /* - if projVector is vertical, */
+ /* ratio = y_ratio */
+ /* */
+ /* - else, */
+ /* ratio = sqrt( (proj.x * x_ratio) ^ 2 + (proj.y * y_ratio) ^ 2 ) */
+ /* */
+ /* Reading a cvt value returns */
+ /* ratio * cvt[index] */
+ /* */
+ /* Writing a cvt value in pixels: */
+ /* cvt[index] / ratio */
+ /* */
+ /* The current ppem is simply */
+ /* ratio * ppem */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* Metrics used by the TrueType size and context objects. */
+ /* */
+ typedef struct TT_Size_Metrics_
+ {
+ /* for non-square pixels */
+ FT_Long x_ratio;
+ FT_Long y_ratio;
+
+ FT_UShort ppem; /* maximum ppem size */
+ FT_Long ratio; /* current ratio */
+ FT_Fixed scale;
+
+ FT_F26Dot6 compensations[4]; /* device-specific compensations */
+
+ FT_Bool valid;
+
+ FT_Bool rotated; /* `is the glyph rotated?'-flag */
+ FT_Bool stretched; /* `is the glyph stretched?'-flag */
+
+ } TT_Size_Metrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* TrueType size class. */
+ /* */
+ typedef struct TT_SizeRec_
+ {
+ FT_SizeRec root;
+
+ TT_Size_Metrics ttmetrics;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+ FT_UInt num_function_defs; /* number of function definitions */
+ FT_UInt max_function_defs;
+ TT_DefArray function_defs; /* table of function definitions */
+
+ FT_UInt num_instruction_defs; /* number of ins. definitions */
+ FT_UInt max_instruction_defs;
+ TT_DefArray instruction_defs; /* table of ins. definitions */
+
+ FT_UInt max_func;
+ FT_UInt max_ins;
+
+ TT_CodeRangeTable codeRangeTable;
+
+ TT_GraphicsState GS;
+
+ FT_ULong cvt_size; /* the scaled control value table */
+ FT_Long* cvt;
+
+ FT_UShort storage_size; /* The storage area is now part of */
+ FT_Long* storage; /* the instance */
+
+ TT_GlyphZone twilight; /* The instance's twilight zone */
+
+ /* debugging variables */
+
+ /* When using the debugger, we must keep the */
+ /* execution context tied to the instance */
+ /* object rather than asking it on demand. */
+
+ FT_Bool debug;
+ TT_ExecContext context;
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+ } TT_SizeRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* TrueType driver class. */
+ /* */
+ typedef struct TT_DriverRec_
+ {
+ FT_DriverRec root;
+ TT_ExecContext context; /* execution context */
+ TT_GlyphZone zone; /* glyph loader points zone */
+
+ void* extension_component;
+
+ } TT_DriverRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* Face functions */
+ /* */
+ LOCAL_DEF
+ FT_Error TT_Init_Face( FT_Stream stream,
+ TT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+ LOCAL_DEF
+ void TT_Done_Face( TT_Face face );
+
+
+ /*************************************************************************/
+ /* */
+ /* Size functions */
+ /* */
+ LOCAL_DEF
+ FT_Error TT_Init_Size( TT_Size size );
+
+ LOCAL_DEF
+ void TT_Done_Size( TT_Size size );
+
+ LOCAL_DEF
+ FT_Error TT_Reset_Size( TT_Size size );
+
+
+ /*************************************************************************/
+ /* */
+ /* Driver functions */
+ /* */
+ LOCAL_DEF
+ FT_Error TT_Init_Driver( TT_Driver driver );
+
+ LOCAL_DEF
+ void TT_Done_Driver( TT_Driver driver );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* TTOBJS_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttpload.h */
+/* */
+/* TrueType glyph data/program tables loader (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/tttags.h>
+
+#ifdef FT_FLAT_COMPILE
+#include "ttpload.h"
+#else
+#include <truetype/ttpload.h>
+#endif
+
+#include <freetype/internal/tterrors.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttpload
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Locations */
+ /* */
+ /* <Description> */
+ /* Loads the locations table. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* <Input> */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_Locations( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_Short LongOffsets;
+ FT_ULong table_len;
+
+
+ FT_TRACE2(( "Locations " ));
+ LongOffsets = face->header.Index_To_Loc_Format;
+
+ error = face->goto_table( face, TTAG_loca, stream, &table_len );
+ if ( error )
+ {
+ error = TT_Err_Locations_Missing;
+ goto Exit;
+ }
+
+ if ( LongOffsets != 0 )
+ {
+ face->num_locations = (FT_UShort)( table_len >> 2 );
+
+ FT_TRACE2(( "(32bit offsets): %12d ", face->num_locations ));
+
+ if ( ALLOC_ARRAY( face->glyph_locations,
+ face->num_locations,
+ FT_Long ) )
+ goto Exit;
+
+ if ( ACCESS_Frame( face->num_locations * 4L ) )
+ goto Exit;
+
+ {
+ FT_Long* loc = face->glyph_locations;
+ FT_Long* limit = loc + face->num_locations;
+
+
+ for ( ; loc < limit; loc++ )
+ *loc = GET_Long();
+ }
+
+ FORGET_Frame();
+ }
+ else
+ {
+ face->num_locations = (FT_UShort)( table_len >> 1 );
+
+ FT_TRACE2(( "(16bit offsets): %12d ", face->num_locations ));
+
+ if ( ALLOC_ARRAY( face->glyph_locations,
+ face->num_locations,
+ FT_Long ) )
+ goto Exit;
+
+ if ( ACCESS_Frame( face->num_locations * 2L ) )
+ goto Exit;
+ {
+ FT_Long* loc = face->glyph_locations;
+ FT_Long* limit = loc + face->num_locations;
+
+
+ for ( ; loc < limit; loc++ )
+ *loc = (FT_Long)( (FT_ULong)GET_UShort() * 2 );
+ }
+ FORGET_Frame();
+ }
+
+ FT_TRACE2(( "loaded\n" ));
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_CVT */
+ /* */
+ /* <Description> */
+ /* Loads the control value table into a face object. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* <Input> */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_CVT( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_ULong table_len;
+
+
+ FT_TRACE2(( "CVT " ));
+
+ error = face->goto_table( face, TTAG_cvt, stream, &table_len );
+ if ( error )
+ {
+ FT_TRACE2(( "is missing!\n" ));
+
+ face->cvt_size = 0;
+ face->cvt = NULL;
+ error = TT_Err_Ok;
+
+ goto Exit;
+ }
+
+ face->cvt_size = table_len / 2;
+
+ if ( ALLOC_ARRAY( face->cvt,
+ face->cvt_size,
+ FT_Short ) )
+ goto Exit;
+
+ if ( ACCESS_Frame( face->cvt_size * 2L ) )
+ goto Exit;
+
+ {
+ FT_Short* cur = face->cvt;
+ FT_Short* limit = cur + face->cvt_size;
+
+
+ for ( ; cur < limit; cur++ )
+ *cur = GET_Short();
+ }
+
+ FORGET_Frame();
+ FT_TRACE2(( "loaded\n" ));
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Progams */
+ /* */
+ /* <Description> */
+ /* Loads the font program and the cvt program. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* <Input> */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error TT_Load_Programs( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_ULong table_len;
+
+
+ FT_TRACE2(( "Font program " ));
+
+ /* The font program is optional */
+ error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
+ if ( error )
+ {
+ face->font_program = NULL;
+ face->font_program_size = 0;
+
+ FT_TRACE2(( "is missing!\n" ));
+ }
+ else
+ {
+ face->font_program_size = table_len;
+ if ( EXTRACT_Frame( table_len, face->font_program ) )
+ goto Exit;
+
+ FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size ));
+ }
+
+ FT_TRACE2(( "Prep program " ));
+
+ error = face->goto_table( face, TTAG_prep, stream, &table_len );
+ if ( error )
+ {
+ face->cvt_program = NULL;
+ face->cvt_program_size = 0;
+ error = TT_Err_Ok;
+
+ FT_TRACE2(( "is missing!\n" ));
+ }
+ else
+ {
+ face->cvt_program_size = table_len;
+ if ( EXTRACT_Frame( table_len, face->cvt_program ) )
+ goto Exit;
+
+ FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size ));
+ }
+
+ Exit:
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ttpload.h */
+/* */
+/* TrueType glyph data/program tables loader (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef TTPLOAD_H
+#define TTPLOAD_H
+
+#include <freetype/internal/tttypes.h>
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ LOCAL_DEF
+ FT_Error TT_Load_Locations( TT_Face face,
+ FT_Stream stream );
+
+ LOCAL_DEF
+ FT_Error TT_Load_CVT( TT_Face face,
+ FT_Stream stream );
+
+ LOCAL_DEF
+ FT_Error TT_Load_Programs( TT_Face face,
+ FT_Stream stream );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* TTPLOAD_H */
+
+
+/* END */
--- /dev/null
+make_module_list: add_type1_driver
+
+add_type1_driver:
+ $(OPEN_DRIVER)t1_driver_class$(CLOSE_DRIVER)
+ $(ECHO_DRIVER)type1 $(ECHO_DRIVER_DESC)Postscript font files with extension *.pfa or *.pfb$(ECHO_DRIVER_DONE)
+
--- /dev/null
+#
+# FreeType 2 Type 1 driver configuration rules
+#
+
+
+# Copyright 1996-2000 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# Type1 driver directory
+#
+T1_DIR := $(SRC_)type1
+T1_DIR_ := $(T1_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+T1_COMPILE := $(FT_COMPILE)
+
+
+# Type1 driver sources (i.e., C files)
+#
+T1_DRV_SRC := $(T1_DIR_)t1objs.c \
+ $(T1_DIR_)t1load.c \
+ $(T1_DIR_)t1parse.c \
+ $(T1_DIR_)t1tokens.c \
+ $(T1_DIR_)t1driver.c \
+ $(T1_DIR_)t1hinter.c \
+ $(T1_DIR_)t1afm.c \
+ $(T1_DIR_)t1gload.c
+
+# Type1 driver headers
+#
+T1_DRV_H := $(T1_DRV_SRC:%.c=%.h)
+
+
+# Type1 driver object(s)
+#
+# T1_DRV_OBJ_M is used during `multi' builds
+# T1_DRV_OBJ_S is used during `single' builds
+#
+T1_DRV_OBJ_M := $(T1_DRV_SRC:$(T1_DIR_)%.c=$(OBJ_)%.$O)
+T1_DRV_OBJ_S := $(OBJ_)type1.$O
+
+# Type1 driver source file for single build
+#
+T1_DRV_SRC_S := $(T1_DIR_)type1.c
+
+
+# Type1 driver - single object
+#
+$(T1_DRV_OBJ_S): $(T1_DRV_SRC_S) $(T1_DRV_SRC) $(FREETYPE_H) $(T1_DRV_H)
+ $(T1_COMPILE) $T$@ $(T1_DRV_SRC_S)
+
+
+# Type1 driver - multiple objects
+#
+$(OBJ_)%.$O: $(T1_DIR_)%.c $(FREETYPE_H) $(T1_DRV_H)
+ $(T1_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(T1_DRV_OBJ_S)
+DRV_OBJS_M += $(T1_DRV_OBJ_M)
+
+
+# EOF
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1afm.c */
+/* */
+/* AFM support for Type 1 fonts (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1afm.h"
+
+#else
+
+#include <type1/t1afm.h>
+
+#endif
+
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1types.h>
+
+#include <stdlib.h> /* for qsort() */
+#include <string.h> /* for strcmp() */
+#include <ctype.h> /* for isalnum() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1afm
+
+
+ LOCAL_FUNC
+ void T1_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 ) ( isalnum( c ) || \
+ 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 && !isdigit( *p ) )
+ {
+ sign = 1;
+ if ( *p == '-' )
+ sign = -1;
+
+ p++;
+ }
+
+ while ( p < limit && isdigit( *p ) )
+ {
+ 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 T1_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 T1_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;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1afm.h */
+/* */
+/* AFM support for Type 1 fonts (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T1AFM_H
+#define T1AFM_H
+
+#include <freetype/internal/ftobjs.h>
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ 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;
+
+
+ LOCAL_DEF
+ FT_Error T1_Read_AFM( FT_Face face,
+ FT_Stream stream );
+
+ LOCAL_DEF
+ void T1_Done_AFM( FT_Memory memory,
+ T1_AFM* afm );
+
+ LOCAL_DEF
+ void T1_Get_Kerning( T1_AFM* afm,
+ FT_UInt glyph1,
+ FT_UInt glyph2,
+ FT_Vector* kerning );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* T1AFM_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1driver.c */
+/* */
+/* Type 1 driver interface (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1driver.h"
+#include "t1gload.h"
+#include "t1afm.h"
+
+#else
+
+#include <type1/t1driver.h>
+#include <type1/t1gload.h>
+#include <type1/t1afm.h>
+
+#endif
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/psnames.h>
+
+#include <string.h> /* for strcmp() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1driver
+
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Kerning */
+ /* */
+ /* <Description> */
+ /* A driver method used to return the kerning vector between two */
+ /* glyphs of the same face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* left_glyph :: The index of the left glyph in the kern pair. */
+ /* */
+ /* right_glyph :: The index of the right glyph in the kern pair. */
+ /* */
+ /* <Output> */
+ /* kerning :: The kerning vector. This is in font units for */
+ /* scalable formats, and in pixels for fixed-sizes */
+ /* formats. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only horizontal layouts (left-to-right & right-to-left) are */
+ /* supported by this function. Other layouts, or more sophisticated */
+ /* kernings are out of scope of this method (the basic driver */
+ /* interface is meant to be simple). */
+ /* */
+ /* They can be implemented by format-specific interfaces. */
+ /* */
+ static
+ FT_Error Get_Kerning( T1_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_Vector* kerning )
+ {
+ T1_AFM* afm;
+
+
+ kerning->x = 0;
+ kerning->y = 0;
+
+ afm = (T1_AFM*)face->afm_data;
+ if ( afm )
+ T1_Get_Kerning( afm, left_glyph, right_glyph, kerning );
+
+ return T1_Err_Ok;
+ }
+
+
+#endif /* T1_CONFIG_OPTION_NO_AFM */
+
+
+ static
+ FT_Error get_t1_glyph_name( T1_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max )
+ {
+ FT_String* gname;
+
+
+ gname = face->type1.glyph_names[glyph_index];
+
+ if ( buffer_max > 0 )
+ {
+ FT_UInt len = strlen( gname );
+
+
+ if ( len >= buffer_max )
+ len = buffer_max - 1;
+
+ MEM_Copy( buffer, gname, len );
+ ((FT_Byte*)buffer)[len] = 0;
+ }
+
+ return T1_Err_Ok;
+ }
+
+
+ static
+ FT_Module_Interface T1_Get_Interface( FT_Module module,
+ const char* interface )
+ {
+ FT_UNUSED( module );
+
+ if ( strcmp( interface, "glyph_name" ) == 0 )
+ return (FT_Module_Interface)get_t1_glyph_name;
+
+ return 0;
+ }
+
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Set_Char_Sizes */
+ /* */
+ /* <Description> */
+ /* A driver method used to reset a size's character sizes (horizontal */
+ /* and vertical) expressed in fractional points. */
+ /* */
+ /* <Input> */
+ /* char_width :: The character width expressed in 26.6 */
+ /* fractional points. */
+ /* */
+ /* char_height :: The character height expressed in 26.6 */
+ /* fractional points. */
+ /* */
+ /* horz_resolution :: The horizontal resolution of the output device. */
+ /* */
+ /* vert_resolution :: The vertical resolution of the output device. */
+ /* */
+ /* <InOut> */
+ /* size :: A handle to the target size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Set_Char_Sizes( T1_Size size,
+ FT_F26Dot6 char_width,
+ FT_F26Dot6 char_height,
+ FT_UInt horz_resolution,
+ FT_UInt vert_resolution )
+ {
+ FT_UNUSED( char_width );
+ FT_UNUSED( char_height );
+ FT_UNUSED( horz_resolution );
+ FT_UNUSED( vert_resolution );
+
+ size->valid = FALSE;
+
+ return T1_Reset_Size( size );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Set_Pixel_Sizes */
+ /* */
+ /* <Description> */
+ /* A driver method used to reset a size's character sizes (horizontal */
+ /* and vertical) expressed in integer pixels. */
+ /* */
+ /* <Input> */
+ /* pixel_width :: The character width expressed in integer pixels. */
+ /* */
+ /* pixel_height :: The character height expressed in integer pixels. */
+ /* */
+ /* <InOut> */
+ /* size :: A handle to the target size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Set_Pixel_Sizes( T1_Size size,
+ FT_Int pixel_width,
+ FT_Int pixel_height )
+ {
+ FT_UNUSED( pixel_width );
+ FT_UNUSED( pixel_height );
+
+ size->valid = FALSE;
+
+ return T1_Reset_Size( size );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Char_Index */
+ /* */
+ /* <Description> */
+ /* Uses a charmap to return a given character code's glyph index. */
+ /* */
+ /* <Input> */
+ /* charmap :: A handle to the source charmap object. */
+ /* charcode :: The character code. */
+ /* */
+ /* <Return> */
+ /* Glyph index. 0 means `undefined character code'. */
+ /* */
+ static
+ FT_UInt Get_Char_Index( FT_CharMap charmap,
+ FT_Long charcode )
+ {
+ T1_Face face;
+ FT_UInt result = 0;
+ PSNames_Interface* psnames;
+
+
+ face = (T1_Face)charmap->face;
+ psnames = (PSNames_Interface*)face->psnames;
+ if ( psnames )
+ switch ( charmap->encoding )
+ {
+ /*******************************************************************/
+ /* */
+ /* Unicode encoding support */
+ /* */
+ case ft_encoding_unicode:
+ /* use the `PSNames' module to synthetize the Unicode charmap */
+ result = psnames->lookup_unicode( &face->unicode_map,
+ (FT_ULong)charcode );
+
+ /* the function returns 0xFFFF if the Unicode charcode has */
+ /* no corresponding glyph */
+ if ( result == 0xFFFF )
+ result = 0;
+ goto Exit;
+
+ /*******************************************************************/
+ /* */
+ /* Custom Type 1 encoding */
+ /* */
+ case ft_encoding_adobe_custom:
+ {
+ T1_Encoding* encoding = &face->type1.encoding;
+
+
+ if ( charcode >= encoding->code_first &&
+ charcode <= encoding->code_last )
+ result = encoding->char_index[charcode];
+ goto Exit;
+ }
+
+ /*******************************************************************/
+ /* */
+ /* Adobe Standard & Expert encoding support */
+ /* */
+ default:
+ if ( charcode < 256 )
+ {
+ FT_UInt code;
+ FT_Int n;
+ const char* glyph_name;
+
+
+ code = psnames->adobe_std_encoding[charcode];
+ if ( charmap->encoding == ft_encoding_adobe_expert )
+ code = psnames->adobe_expert_encoding[charcode];
+
+ glyph_name = psnames->adobe_std_strings( code );
+ if ( !glyph_name )
+ break;
+
+ for ( n = 0; n < face->type1.num_glyphs; n++ )
+ {
+ const char* gname = face->type1.glyph_names[n];
+
+
+ if ( gname && gname[0] == glyph_name[0] &&
+ strcmp( gname, glyph_name ) == 0 )
+ {
+ result = n;
+ break;
+ }
+ }
+ }
+ }
+ Exit:
+ return result;
+ }
+
+
+
+ const FT_Driver_Class t1_driver_class =
+ {
+ {
+ ft_module_font_driver | ft_module_driver_scalable,
+ sizeof( FT_DriverRec ),
+
+ "type1", /* driver name */
+ 0x10000L, /* driver version 1.0 */
+ 0x20000L, /* driver requires FreeType 2.0 or above */
+
+ 0, /* module specific interface */
+
+ (FT_Module_Constructor)0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) T1_Get_Interface
+ },
+
+ sizeof( T1_FaceRec ),
+ sizeof( T1_SizeRec ),
+ sizeof( T1_GlyphSlotRec ),
+
+ (FTDriver_initFace) T1_Init_Face,
+ (FTDriver_doneFace) T1_Done_Face,
+ (FTDriver_initSize) T1_Init_Size,
+ (FTDriver_doneSize) T1_Done_Size,
+ (FTDriver_initGlyphSlot)T1_Init_GlyphSlot,
+ (FTDriver_doneGlyphSlot)T1_Done_GlyphSlot,
+
+ (FTDriver_setCharSizes) Set_Char_Sizes,
+ (FTDriver_setPixelSizes)Set_Pixel_Sizes,
+ (FTDriver_loadGlyph) T1_Load_Glyph,
+ (FTDriver_getCharIndex) Get_Char_Index,
+
+#ifdef T1_CONFIG_OPTION_NO_AFM
+ (FTDriver_getKerning) 0,
+ (FTDriver_attachFile) 0,
+#else
+ (FTDriver_getKerning) Get_Kerning,
+ (FTDriver_attachFile) T1_Read_AFM,
+#endif
+ (FTDriver_getAdvances) 0
+ };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+ EXPORT_FUNC( const FT_Driver_Class* ) getDriverClass( void )
+ {
+ return &t1_driver_class;
+ }
+
+#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1driver.h */
+/* */
+/* High-level Type 1 driver interface (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T1DRIVER_H
+#define T1DRIVER_H
+
+#include <freetype/internal/ftdriver.h>
+
+ FT_EXPORT_VAR( const FT_Driver_Class ) t1_driver_class;
+
+
+#endif /* T1DRIVER_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1gload.c */
+/* */
+/* Type 1 Glyph Loader (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1gload.h"
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+#include "t1hinter.h"
+#endif
+
+#else /* FT_FLAT_COMPILE */
+
+#include <type1/t1gload.h>
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+#include <type1/t1hinter.h>
+#endif
+
+#endif /* FT_FLAT_COMPILE */
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/ftoutln.h>
+
+#include <string.h> /* for strcmp() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1gload
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** GENERIC CHARSTRING PARSING *********/
+ /********** *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static
+ void T1_Reset_Builder( T1_Builder* builder,
+ FT_Bool reset_base )
+ {
+ builder->pos_x = 0;
+ builder->pos_y = 0;
+
+ builder->left_bearing.x = 0;
+ builder->left_bearing.y = 0;
+ builder->advance.x = 0;
+ builder->advance.y = 0;
+
+ builder->pass = 0;
+ builder->hint_point = 0;
+
+ if ( builder->loader )
+ {
+ if ( reset_base )
+ FT_GlyphLoader_Rewind( builder->loader );
+
+ FT_GlyphLoader_Prepare( builder->loader );
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Init_Builder */
+ /* */
+ /* <Description> */
+ /* Initializes a given glyph builder. */
+ /* */
+ /* <InOut> */
+ /* builder :: A pointer to the glyph builder to initialize. */
+ /* */
+ /* <Input> */
+ /* face :: The current face object. */
+ /* */
+ /* size :: The current size object. */
+ /* */
+ /* glyph :: The current glyph object. */
+ /* */
+ /* funcs :: Glyph builder functions (or `methods'). */
+ /* */
+ LOCAL_FUNC
+ void T1_Init_Builder( T1_Builder* builder,
+ T1_Face face,
+ T1_Size size,
+ T1_GlyphSlot glyph,
+ const T1_Builder_Funcs* funcs )
+ {
+ builder->funcs = *funcs;
+ builder->path_begun = 0;
+ builder->load_points = 1;
+
+ builder->face = face;
+ builder->size = size;
+ builder->glyph = glyph;
+ builder->memory = face->root.memory;
+
+ if ( glyph )
+ {
+ FT_GlyphLoader* loader = FT_SLOT( glyph )->loader;
+
+
+ builder->loader = loader;
+ builder->base = &loader->base.outline;
+ builder->current = &loader->current.outline;
+ }
+
+ if ( size )
+ {
+ builder->scale_x = size->root.metrics.x_scale;
+ builder->scale_y = size->root.metrics.y_scale;
+ }
+
+ T1_Reset_Builder( builder, 1 );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Done_Builder */
+ /* */
+ /* <Description> */
+ /* Finalizes a given glyph builder. Its contents can still be used */
+ /* after the call, but the function saves important information */
+ /* within the corresponding glyph slot. */
+ /* */
+ /* <Input> */
+ /* builder :: A pointer to the glyph builder to finalize. */
+ /* */
+ LOCAL_FUNC
+ void T1_Done_Builder( T1_Builder* builder )
+ {
+ T1_GlyphSlot glyph = builder->glyph;
+
+
+ if ( glyph )
+ glyph->root.outline = *builder->base;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Init_Decoder */
+ /* */
+ /* <Description> */
+ /* Initializes a given glyph decoder. */
+ /* */
+ /* <InOut> */
+ /* decoder :: A pointer to the glyph builder to initialize. */
+ /* */
+ /* <Input> */
+ /* funcs :: The hinting functions interface. */
+ /* */
+ LOCAL_FUNC
+ void T1_Init_Decoder( T1_Decoder* decoder,
+ const T1_Hinter_Funcs* funcs )
+ {
+ decoder->hinter = *funcs; /* copy hinter interface */
+ decoder->top = 0;
+ decoder->zone = 0;
+
+ decoder->flex_state = 0;
+ decoder->num_flex_vectors = 0;
+
+ /* Clear loader */
+ MEM_Set( &decoder->builder, 0, sizeof ( decoder->builder ) );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* lookup_glyph_by_stdcharcode */
+ /* */
+ /* <Description> */
+ /* Looks up a given glyph by its StandardEncoding charcode. Used */
+ /* to implement the SEAC Type 1 operator. */
+ /* */
+ /* <Input> */
+ /* face :: The current face object. */
+ /* */
+ /* charcode :: The character code to look for. */
+ /* */
+ /* <Return> */
+ /* A glyph index in the font face. Returns -1 if the corresponding */
+ /* glyph wasn't found. */
+ /* */
+ static
+ FT_Int lookup_glyph_by_stdcharcode( T1_Face face,
+ FT_Int charcode )
+ {
+ FT_Int n;
+ const FT_String* glyph_name;
+ PSNames_Interface* psnames = (PSNames_Interface*)face->psnames;
+
+
+ /* check range of standard char code */
+ if ( charcode < 0 || charcode > 255 )
+ return -1;
+
+ glyph_name = psnames->adobe_std_strings(
+ psnames->adobe_std_encoding[charcode] );
+
+ for ( n = 0; n < face->type1.num_glyphs; n++ )
+ {
+ FT_String* name = (FT_String*)face->type1.glyph_names[n];
+
+
+ if ( name && strcmp( name, glyph_name ) == 0 )
+ return n;
+ }
+
+ return -1;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1operator_seac */
+ /* */
+ /* <Description> */
+ /* Implements the `seac' Type 1 operator for a Type 1 decoder. */
+ /* */
+ /* <Input> */
+ /* decoder :: The current CID decoder. */
+ /* */
+ /* asb :: The accent's side bearing. */
+ /* */
+ /* adx :: The horizontal offset of the accent. */
+ /* */
+ /* ady :: The vertical offset of the accent. */
+ /* */
+ /* bchar :: The base character's StandardEncoding charcode. */
+ /* */
+ /* achar :: The accent character's StandardEncoding charcode. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error t1operator_seac( T1_Decoder* decoder,
+ FT_Pos asb,
+ FT_Pos adx,
+ FT_Pos ady,
+ FT_Int bchar,
+ FT_Int achar )
+ {
+ FT_Error error;
+ FT_Int bchar_index, achar_index, n_base_points;
+ FT_Outline* base = decoder->builder.base;
+ FT_Vector left_bearing, advance;
+ T1_Face face = decoder->builder.face;
+ T1_Font* type1 = &face->type1;
+
+
+ bchar_index = lookup_glyph_by_stdcharcode( face, bchar );
+ achar_index = lookup_glyph_by_stdcharcode( face, achar );
+
+ if ( bchar_index < 0 || achar_index < 0 )
+ {
+ FT_ERROR(( "t1operator_seac:" ));
+ FT_ERROR(( " invalid seac character code arguments\n" ));
+ return T1_Err_Syntax_Error;
+ }
+
+ /* if we are trying to load a composite glyph, do not load the */
+ /* accent character and return the array of subglyphs. */
+ if ( decoder->builder.no_recurse )
+ {
+ FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
+ FT_GlyphLoader* loader = glyph->loader;
+ FT_SubGlyph* subg;
+
+
+ /* reallocate subglyph array if necessary */
+ error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
+ if ( error )
+ goto Exit;
+
+ subg = loader->current.subglyphs;
+
+ /* subglyph 0 = base character */
+ subg->index = bchar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+ FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+ subg->arg1 = 0;
+ subg->arg2 = 0;
+ subg++;
+
+ /* subglyph 1 = accent character */
+ subg->index = achar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+ subg->arg1 = adx - asb;
+ subg->arg2 = ady;
+
+ /* set up remaining glyph fields */
+ glyph->num_subglyphs = 2;
+ glyph->subglyphs = loader->current.subglyphs;
+ glyph->format = ft_glyph_format_composite;
+
+ loader->current.num_subglyphs = 2;
+ goto Exit;
+ }
+
+ /* First load `bchar' in builder */
+ /* now load the unscaled outline */
+
+ if ( decoder->builder.loader )
+ FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
+
+ error = T1_Parse_CharStrings( decoder,
+ type1->charstrings [bchar_index],
+ type1->charstrings_len[bchar_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+ if ( error )
+ goto Exit;
+
+ n_base_points = base->n_points;
+
+ /* save the left bearing and width of the base character */
+ /* as they will be erased by the next load. */
+
+ left_bearing = decoder->builder.left_bearing;
+ advance = decoder->builder.advance;
+
+ decoder->builder.left_bearing.x = 0;
+ decoder->builder.left_bearing.y = 0;
+
+ /* Now load `achar' on top of the base outline */
+ error = T1_Parse_CharStrings( decoder,
+ type1->charstrings [achar_index],
+ type1->charstrings_len[achar_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+ if ( error )
+ return error;
+
+ /* restore the left side bearing and */
+ /* advance width of the base character */
+
+ decoder->builder.left_bearing = left_bearing;
+ decoder->builder.advance = advance;
+
+ /* Finally, move the accent */
+ if ( decoder->builder.load_points )
+ {
+ FT_Outline dummy;
+
+
+ dummy.n_points = base->n_points - n_base_points;
+ dummy.points = base->points + n_base_points;
+
+ FT_Outline_Translate( &dummy, adx - asb, ady );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1operator_flex */
+ /* */
+ /* <Description> */
+ /* Implements the `flex' Type 1 operator for a Type 1 decoder. */
+ /* */
+ /* <Input> */
+ /* decoder :: The current Type 1 decoder. */
+ /* threshold :: The threshold. */
+ /* end_x :: The horizontal position of the final flex point. */
+ /* end_y :: The vertical position of the final flex point. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error t1operator_flex( T1_Decoder* decoder,
+ FT_Pos threshold,
+ FT_Pos end_x,
+ FT_Pos end_y )
+ {
+ FT_Vector vec;
+ FT_Vector* flex = decoder->flex_vectors;
+ FT_Int n;
+
+ FT_UNUSED( threshold );
+ FT_UNUSED( end_x );
+ FT_UNUSED( end_y );
+
+
+ /* we don't even try to test the threshold in the non-hinting */
+ /* builder, even if the flex operator is said to be a path */
+ /* construction statement in the specification. This is better */
+ /* left to the hinter. */
+
+ flex = decoder->flex_vectors;
+ vec = *flex++;
+
+ for ( n = 0; n < 6; n++ )
+ {
+ flex->x += vec.x;
+ flex->y += vec.y;
+
+ vec = *flex++;
+ }
+
+ flex = decoder->flex_vectors;
+
+ return decoder->builder.funcs.rcurve_to( &decoder->builder,
+ flex[0].x, flex[0].y,
+ flex[1].x, flex[1].y,
+ flex[2].x, flex[2].y ) ||
+
+ decoder->builder.funcs.rcurve_to( &decoder->builder,
+ flex[3].x, flex[3].y,
+ flex[4].x, flex[4].y,
+ flex[5].x, flex[5].y );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Parse_CharStrings */
+ /* */
+ /* <Description> */
+ /* Parses a given Type 1 charstrings program. */
+ /* */
+ /* <Input> */
+ /* decoder :: The current Type 1 decoder. */
+ /* */
+ /* charstring_base :: The base address of the charstring stream. */
+ /* */
+ /* charstring_len :: The length in bytes of the charstring stream. */
+ /* */
+ /* num_subrs :: The number of sub-routines. */
+ /* */
+ /* subrs_base :: An array of sub-routines addresses. */
+ /* */
+ /* subrs_len :: An array of sub-routines lengths. */
+ /* */
+ /* <Return> */
+ /* Free error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error T1_Parse_CharStrings( T1_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_Int charstring_len,
+ FT_Int num_subrs,
+ FT_Byte** subrs_base,
+ FT_Int* subrs_len )
+ {
+ FT_Error error;
+ T1_Decoder_Zone* zone;
+ FT_Byte* ip;
+ FT_Byte* limit;
+ T1_Builder* builder = &decoder->builder;
+ T1_Builder_Funcs* builds = &builder->funcs;
+ T1_Hinter_Funcs* hints = &decoder->hinter;
+
+ static
+ const FT_Int args_count[op_max] =
+ {
+ 0, /* none */
+ 0, /* endchar */
+ 2, /* hsbw */
+ 5, /* seac */
+ 4, /* sbw */
+ 0, /* closepath */
+ 1, /* hlineto */
+ 1, /* hmoveto */
+ 4, /* hvcurveto */
+ 2, /* rlineto */
+ 2, /* rmoveto */
+ 6, /* rrcurveto */
+ 4, /* vhcurveto */
+ 1, /* vlineto */
+ 1, /* vmoveto */
+ 0, /* dotsection */
+ 2, /* hstem */
+ 6, /* hstem3 */
+ 2, /* vstem */
+ 6, /* vstem3 */
+ 2, /* div */
+ -1, /* callothersubr */
+ 1, /* callsubr */
+ 0, /* pop */
+ 0, /* return */
+ 2 /* setcurrentpoint */
+ };
+
+
+ /* First of all, initialize the decoder */
+ decoder->top = decoder->stack;
+ decoder->zone = decoder->zones;
+ zone = decoder->zones;
+
+ builder->path_begun = 0;
+
+ zone->base = charstring_base;
+ limit = zone->limit = charstring_base + charstring_len;
+ ip = zone->cursor = zone->base;
+
+ error = T1_Err_Ok;
+
+ /* now, execute loop */
+ while ( ip < limit )
+ {
+ FT_Int* top = decoder->top;
+ T1_Operator op = op_none;
+ FT_Long value = 0;
+
+
+ /* Start with the decompression of operator or value */
+ switch ( *ip++ )
+ {
+ case 1:
+ op = op_hstem;
+ break;
+
+ case 3:
+ op = op_vstem;
+ break;
+ case 4:
+ op = op_vmoveto;
+ break;
+ case 5:
+ op = op_rlineto;
+ break;
+ case 6:
+ op = op_hlineto;
+ break;
+ case 7:
+ op = op_vlineto;
+ break;
+ case 8:
+ op = op_rrcurveto;
+ break;
+ case 9:
+ op = op_closepath;
+ break;
+ case 10:
+ op = op_callsubr;
+ break;
+ case 11:
+ op = op_return;
+ break;
+
+ case 13:
+ op = op_hsbw;
+ break;
+ case 14:
+ op = op_endchar;
+ break;
+
+ case 21:
+ op = op_rmoveto;
+ break;
+ case 22:
+ op = op_hmoveto;
+ break;
+
+ case 30:
+ op = op_vhcurveto;
+ break;
+ case 31:
+ op = op_hvcurveto;
+ break;
+
+ case 12:
+ if ( ip > limit )
+ {
+ FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+EOF)\n" ));
+ goto Syntax_Error;
+ }
+
+ switch ( *ip++ )
+ {
+ case 0:
+ op = op_dotsection;
+ break;
+ case 1:
+ op = op_vstem3;
+ break;
+ case 2:
+ op = op_hstem3;
+ break;
+ case 6:
+ op = op_seac;
+ break;
+ case 7:
+ op = op_sbw;
+ break;
+ case 12:
+ op = op_div;
+ break;
+ case 16:
+ op = op_callothersubr;
+ break;
+ case 17:
+ op = op_pop;
+ break;
+ case 33:
+ op = op_setcurrentpoint;
+ break;
+
+ default:
+ FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+%d)\n",
+ ip[-1] ));
+ goto Syntax_Error;
+ }
+ break;
+
+ case 255: /* four bytes integer */
+ if ( ip + 4 > limit )
+ {
+ FT_ERROR(( "T1_Parse_CharStrings: unexpected EOF in integer\n" ));
+ goto Syntax_Error;
+ }
+
+ value = ( (FT_Long)ip[0] << 24 ) |
+ ( (FT_Long)ip[1] << 16 ) |
+ ( (FT_Long)ip[2] << 8 ) |
+ ip[3];
+ ip += 4;
+ break;
+
+ default:
+ if ( ip[-1] >= 32 )
+ {
+ if ( ip[-1] < 247 )
+ value = (FT_Long)ip[-1] - 139;
+ else
+ {
+ if ( ++ip > limit )
+ {
+ FT_ERROR(( "T1_Parse_CharStrings:" ));
+ FT_ERROR(( " unexpected EOF in integer\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( ip[-2] < 251 )
+ value = ((FT_Long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
+ else
+ value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
+ }
+ }
+ else
+ {
+ FT_ERROR(( "T1_Parse_CharStrings: invalid byte (%d)\n",
+ ip[-1] ));
+ goto Syntax_Error;
+ }
+ }
+
+ /* push value if necessary */
+ if ( op == op_none )
+ {
+ if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
+ {
+ FT_ERROR(( "T1_Parse_CharStrings: stack overflow!\n" ));
+ goto Syntax_Error;
+ }
+
+ *top++ = value;
+ decoder->top = top;
+ }
+
+ else if ( op == op_callothersubr ) /* check arguments differently */
+ {
+ if ( top - decoder->stack < 2 )
+ goto Stack_Underflow;
+
+ top -= 2;
+
+ switch ( top[1] )
+ {
+ case 1: /* start flex feature */
+ if ( top[0] != 0 )
+ goto Unexpected_OtherSubr;
+
+ decoder->flex_state = 1;
+ decoder->num_flex_vectors = 0;
+ decoder->flex_vectors[0].x = 0;
+ decoder->flex_vectors[0].y = 0;
+ break;
+
+ case 2: /* add flex vector */
+ {
+ FT_Int index;
+ FT_Vector* flex;
+
+
+ if ( top[0] != 0 )
+ goto Unexpected_OtherSubr;
+
+ top -= 2;
+ if ( top < decoder->stack )
+ goto Stack_Underflow;
+
+ index = decoder->num_flex_vectors++;
+ if ( index >= 7 )
+ {
+ FT_ERROR(( "T1_Parse_CharStrings: too many flex vectors!\n" ));
+ goto Syntax_Error;
+ }
+
+ flex = decoder->flex_vectors + index;
+ flex->x += top[0];
+ flex->y += top[1];
+ }
+ break;
+
+ case 0: /* end flex feature */
+ if ( decoder->flex_state == 0 ||
+ decoder->num_flex_vectors != 7 )
+ {
+ FT_ERROR(( "T1_Parse_CharStrings: unexpected flex end\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( top[0] != 3 )
+ goto Unexpected_OtherSubr;
+
+ top -= 3;
+ if ( top < decoder->stack )
+ goto Stack_Underflow;
+
+ /* now consume the remaining `pop pop setcurrentpoint' */
+ if ( ip + 6 > limit ||
+ ip[0] != 12 || ip[1] != 17 || /* pop */
+ ip[2] != 12 || ip[3] != 17 || /* pop */
+ ip[4] != 12 || ip[5] != 33 ) /* setcurrentpoint */
+ {
+ FT_ERROR(( "T1_Parse_CharStrings: invalid flex charstring\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->flex_state = 0;
+ decoder->top = top;
+
+ error = t1operator_flex( decoder, top[0], top[1], top[2] );
+ break;
+
+ case 3: /* change hints */
+ if ( top[0] != 1 )
+ goto Unexpected_OtherSubr;
+
+ /* eat the following `pop' */
+ if ( ip + 2 > limit )
+ {
+ FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+%d)\n",
+ ip[-1] ));
+ goto Syntax_Error;
+ }
+
+ if ( ip[0] != 12 || ip[1] != 17 )
+ {
+ FT_ERROR(( "T1_Parse_CharStrings:" ));
+ FT_ERROR(( " `pop' expected, found (%d %d)\n", ip[0], ip[1] ));
+ goto Syntax_Error;
+ }
+
+ ip += 2;
+
+ error = hints->change_hints( builder );
+ break;
+
+ default:
+ /* invalid OtherSubrs call */
+ Unexpected_OtherSubr:
+ FT_ERROR(( "T1_Parse_CharStrings: unexpected OtherSubrs [%d %d]\n",
+ top[0], top[1] ));
+ goto Syntax_Error;
+ }
+ decoder->top = top;
+ }
+ else
+ {
+ FT_Int num_args = args_count[op];
+
+
+ if ( top - decoder->stack < num_args )
+ goto Stack_Underflow;
+
+ top -= num_args;
+
+ switch ( op )
+ {
+ case op_endchar:
+ error = builds->end_char( builder );
+ break;
+
+ case op_hsbw:
+ error = builds->set_bearing_point( builder, top[0], 0,
+ top[1], 0 );
+ break;
+
+ case op_seac:
+ /* return immediately after the processing */
+ return t1operator_seac( decoder, top[0], top[1],
+ top[2], top[3], top[4] );
+
+ case op_sbw:
+ error = builds->set_bearing_point( builder, top[0], top[1],
+ top[2], top[3] );
+ break;
+
+ case op_closepath:
+ error = builds->close_path( builder );
+ break;
+
+ case op_hlineto:
+ error = builds->rline_to( builder, top[0], 0 );
+ break;
+
+ case op_hmoveto:
+ error = builds->rmove_to( builder, top[0], 0 );
+ break;
+
+ case op_hvcurveto:
+ error = builds->rcurve_to( builder, top[0], 0,
+ top[1], top[2],
+ 0, top[3] );
+ break;
+
+ case op_rlineto:
+ error = builds->rline_to( builder, top[0], top[1] );
+ break;
+
+ case op_rmoveto:
+ /* ignore operator when in flex mode */
+ if ( decoder->flex_state == 0 )
+ error = builds->rmove_to( builder, top[0], top[1] );
+ else
+ top += 2;
+ break;
+
+ case op_rrcurveto:
+ error = builds->rcurve_to( builder, top[0], top[1],
+ top[2], top[3],
+ top[4], top[5] );
+ break;
+
+ case op_vhcurveto:
+ error = builds->rcurve_to( builder, 0, top[0],
+ top[1], top[2],
+ top[3], 0 );
+ break;
+
+ case op_vlineto:
+ error = builds->rline_to( builder, 0, top[0] );
+ break;
+
+ case op_vmoveto:
+ error = builds->rmove_to( builder, 0, top[0] );
+ break;
+
+ case op_dotsection:
+ error = hints->dot_section( builder );
+ break;
+
+ case op_hstem:
+ error = hints->stem( builder, top[0], top[1], 0 );
+ break;
+
+ case op_hstem3:
+ error = hints->stem3( builder, top[0], top[1], top[2],
+ top[3], top[4], top[5], 0 );
+ break;
+
+ case op_vstem:
+ error = hints->stem( builder, top[0], top[1], 1 );
+ break;
+
+ case op_vstem3:
+ error = hints->stem3( builder, top[0], top[1], top[2],
+ top[3], top[4], top[5], 1 );
+ break;
+
+ case op_div:
+ if ( top[1] )
+ {
+ *top = top[0] / top[1];
+ ++top;
+ }
+ else
+ {
+ FT_ERROR(( "T1_Parse_CHarStrings: division by 0\n" ));
+ goto Syntax_Error;
+ }
+ break;
+
+ case op_callsubr:
+ {
+ FT_Int index = top[0];
+
+
+ if ( index < 0 || index >= num_subrs )
+ {
+ FT_ERROR(( "T1_Parse_CharStrings: invalid subrs index\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
+ {
+ FT_ERROR(( "T1_Parse_CharStrings: too many nested subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ zone->cursor = ip; /* save current instruction pointer */
+
+ zone++;
+ zone->base = subrs_base[index];
+ zone->limit = zone->base + subrs_len[index];
+ zone->cursor = zone->base;
+
+ if ( !zone->base )
+ {
+ FT_ERROR(( "T1_Parse_CharStrings: invoking empty subrs!\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone = zone;
+ ip = zone->base;
+ limit = zone->limit;
+ }
+ break;
+
+ case op_pop:
+ FT_ERROR(( "T1_Parse_CharStrings: unexpected POP\n" ));
+ goto Syntax_Error;
+
+ case op_return:
+ if ( zone <= decoder->zones )
+ {
+ FT_ERROR(( "T1_Parse_CharStrings: unexpected return\n" ));
+ goto Syntax_Error;
+ }
+
+ zone--;
+ ip = zone->cursor;
+ limit = zone->limit;
+ decoder->zone = zone;
+ break;
+
+ case op_setcurrentpoint:
+ FT_ERROR(( "T1_Parse_CharStrings:" ));
+ FT_ERROR(( " unexpected `setcurrentpoint'\n" ));
+ goto Syntax_Error;
+ break;
+
+ default:
+ FT_ERROR(( "T1_Parse_CharStrings: unhandled opcode %d\n", op ));
+ goto Syntax_Error;
+ }
+
+ decoder->top = top;
+ }
+ }
+
+ return error;
+
+ Syntax_Error:
+ return T1_Err_Syntax_Error;
+
+ Stack_Underflow:
+ return T1_Err_Stack_Underflow;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Add_Points */
+ /* */
+ /* <Description> */
+ /* Checks that there is enough room in the current load glyph outline */
+ /* to accept `num_points' additional outline points. If not, this */
+ /* function grows the load outline's arrays accordingly. */
+ /* */
+ /* <Input> */
+ /* builder :: A pointer to the glyph builder object. */
+ /* */
+ /* num_points :: The number of points that will be added later. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function does NOT update the points count in the glyph */
+ /* builder. This must be done by the caller itself, after this */
+ /* function has been invoked. */
+ /* */
+ LOCAL_FUNC
+ FT_Error T1_Add_Points( T1_Builder* builder,
+ FT_Int num_points )
+ {
+ return FT_GlyphLoader_Check_Points( builder->loader, num_points, 0 );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Add_Contours */
+ /* */
+ /* <Description> */
+ /* Checks that there is enough room in the current load glyph outline */
+ /* to accept `num_contours' additional contours. If not, this */
+ /* function grows the load outline's arrays accordingly. */
+ /* */
+ /* <Input> */
+ /* builder :: A pointer to the glyph builder object. */
+ /* */
+ /* num_contours :: The number of contours that will be added later. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function does NOT update the contours count in the load glyph */
+ /* This must be done by the caller itself, after this function is */
+ /* invoked. */
+ /* */
+ LOCAL_FUNC
+ FT_Error T1_Add_Contours( T1_Builder* builder,
+ FT_Int num_contours )
+ {
+ return FT_GlyphLoader_Check_Points( builder->loader, 0, num_contours );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
+ /********** *********/
+ /********** The following code is in charge of computing *********/
+ /********** the maximum advance width of the font. It *********/
+ /********** quickly processes each glyph charstring to *********/
+ /********** extract the value from either a `sbw' or `seac' *********/
+ /********** operator. *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static
+ FT_Error maxadv_sbw( T1_Decoder* decoder,
+ FT_Pos sbx,
+ FT_Pos sby,
+ FT_Pos wx,
+ FT_Pos wy )
+ {
+ FT_UNUSED( sbx );
+ FT_UNUSED( sby );
+ FT_UNUSED( wy );
+
+ if ( wx > decoder->builder.advance.x )
+ decoder->builder.advance.x = wx;
+
+ return -1; /* return an error code to exit the Type 1 parser */
+ /* immediately. */
+ }
+
+
+ static
+ FT_Int maxadv_error( void )
+ {
+ /* we should never reach this code, unless with a buggy font */
+ return -2;
+ }
+
+
+ /* the maxadv_gbuilder_interface is used when computing the maximum */
+ /* advance width of all glyphs in a given font. We only process the */
+ /* `sbw' operator here, and return an error for all others. */
+
+ /* Note that `seac' is processed by the T1_Decoder. */
+ static
+ const T1_Builder_Funcs maxadv_builder_interface =
+ {
+ (T1_Builder_EndChar) maxadv_error,
+ (T1_Builder_Sbw) maxadv_sbw,
+ (T1_Builder_ClosePath)maxadv_error,
+ (T1_Builder_RLineTo) maxadv_error,
+ (T1_Builder_RMoveTo) maxadv_error,
+ (T1_Builder_RCurveTo) maxadv_error
+ };
+
+
+ /* the maxadv_hinter_interface always return an error. */
+ static
+ const T1_Hinter_Funcs maxadv_hinter_interface =
+ {
+ (T1_Hinter_DotSection) maxadv_error,
+ (T1_Hinter_ChangeHints)maxadv_error,
+ (T1_Hinter_Stem) maxadv_error,
+ (T1_Hinter_Stem3) maxadv_error,
+ };
+
+
+ LOCAL_FUNC
+ FT_Error T1_Compute_Max_Advance( T1_Face face,
+ FT_Int* max_advance )
+ {
+ FT_Error error;
+ T1_Decoder decoder;
+ FT_Int glyph_index;
+ T1_Font* type1 = &face->type1;
+
+
+ *max_advance = 0;
+
+ /* Initialize load decoder */
+ T1_Init_Decoder( &decoder, &maxadv_hinter_interface );
+
+ T1_Init_Builder( &decoder.builder, face, 0, 0,
+ &maxadv_builder_interface );
+
+ /* For each glyph, parse the glyph charstring and extract */
+ /* the advance width. */
+ for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
+ {
+ /* now get load the unscaled outline */
+ error = T1_Parse_CharStrings( &decoder,
+ type1->charstrings [glyph_index],
+ type1->charstrings_len[glyph_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+ /* ignore the error if one occured - skip to next glyph */
+ }
+
+ *max_advance = decoder.builder.advance.x;
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** UNHINTED GLYPH LOADER *********/
+ /********** *********/
+ /********** The following code is in charge of loading a *********/
+ /********** single outline. It completely ignores hinting *********/
+ /********** and is used when FT_LOAD_NO_HINTING is set. *********/
+ /********** *********/
+ /********** The Type 1 hinter is located in `t1hint.c' *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static
+ FT_Error close_open_path( T1_Builder* builder )
+ {
+ FT_Error error;
+ FT_Outline* cur = builder->current;
+ FT_Int num_points;
+ FT_Int first_point;
+
+
+ /* Some fonts, like Hershey, are made of `open paths' which are */
+ /* now managed directly by FreeType. In this case, it is necessary */
+ /* to close the path by duplicating its points in reverse order, */
+ /* which is precisely the purpose of this function. */
+
+ /* first compute the number of points to duplicate */
+ if ( cur->n_contours > 1 )
+ first_point = cur->contours[cur->n_contours - 2] + 1;
+ else
+ first_point = 0;
+
+ num_points = cur->n_points - first_point - 2;
+ if ( num_points > 0 )
+ {
+ FT_Vector* source_point;
+ char* source_tags;
+ FT_Vector* point;
+ char* tags;
+
+
+ error = T1_Add_Points( builder, num_points );
+ if ( error )
+ return error;
+
+ point = cur->points + cur->n_points;
+ tags = cur->tags + cur->n_points;
+
+ source_point = point - 2;
+ source_tags = tags - 2;
+
+ cur->n_points += num_points;
+
+ if ( builder->load_points )
+ do
+ {
+ *point++ = *source_point--;
+ *tags++ = *source_tags--;
+ num_points--;
+
+ } while ( num_points > 0 );
+ }
+
+ builder->path_begun = 0;
+ return T1_Err_Ok;
+ }
+
+
+ static
+ FT_Error gload_closepath( T1_Builder* builder )
+ {
+ FT_Outline* cur = builder->current;
+
+
+ /* XXXX: We must not include the last point in the path if it */
+ /* is located on the first point. */
+ if ( cur->n_points > 1 )
+ {
+ FT_Int first = 0;
+ FT_Vector* p1 = cur->points + first;
+ FT_Vector* p2 = cur->points + cur->n_points - 1;
+
+
+ if ( cur->n_contours > 1 )
+ {
+ first = cur->contours[cur->n_contours - 2] + 1;
+ p1 = cur->points + first;
+ }
+
+ if ( p1->x == p2->x && p1->y == p2->y )
+ cur->n_points--;
+ }
+
+ /* save current contour, if any */
+ if ( cur->n_contours > 0 )
+ cur->contours[cur->n_contours - 1] = cur->n_points - 1;
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+ /* hint last points if necessary -- this is not strictly required */
+ /* there, but it helps for debugging, and doesn't affect performance */
+ if ( builder->pass == 1 )
+ T1_Hint_Points( builder );
+#endif
+
+ builder->path_begun = 0;
+ return T1_Err_Ok;
+ }
+
+
+ static
+ FT_Error gload_endchar( T1_Builder* builder )
+ {
+ FT_Error error;
+
+
+ /* close path if needed */
+ if ( builder->path_begun )
+ {
+ error = close_open_path( builder );
+ if ( error )
+ return error;
+ }
+
+ error = gload_closepath( builder );
+
+ FT_GlyphLoader_Add( builder->loader );
+
+ return error;
+ }
+
+
+ static
+ FT_Error gload_sbw( T1_Builder* builder,
+ FT_Pos sbx,
+ FT_Pos sby,
+ FT_Pos wx,
+ FT_Pos wy )
+ {
+ builder->left_bearing.x += sbx;
+ builder->left_bearing.y += sby;
+ builder->advance.x = wx;
+ builder->advance.y = wy;
+
+ builder->last.x = sbx;
+ builder->last.y = sby;
+
+ return 0;
+ }
+
+
+ static
+ FT_Error gload_rlineto( T1_Builder* builder,
+ FT_Pos dx,
+ FT_Pos dy )
+ {
+ FT_Error error;
+ FT_Outline* cur = builder->current;
+ FT_Vector vec;
+
+
+ /* grow buffer if necessary */
+ error = T1_Add_Points( builder, 1 );
+ if ( error )
+ return error;
+
+ if ( builder->load_points )
+ {
+ /* save point */
+ vec.x = builder->last.x + dx;
+ vec.y = builder->last.y + dy;
+
+ cur->points[cur->n_points] = vec;
+ cur->tags [cur->n_points] = FT_Curve_Tag_On;
+
+ builder->last = vec;
+ }
+ cur->n_points++;
+
+ builder->path_begun = 1;
+
+ return T1_Err_Ok;
+ }
+
+
+ static
+ FT_Error gload_rmoveto( T1_Builder* builder,
+ FT_Pos dx,
+ FT_Pos dy )
+ {
+ FT_Error error;
+ FT_Outline* cur = builder->current;
+ FT_Vector vec;
+
+
+ /* in the case where `path_begun' is set, we have an `rmoveto' */
+ /* after some normal path definition. If the face's paint type */
+ /* is set to 1, this means that we have an `open path', also */
+ /* called a `stroke'. The FreeType raster doesn't support */
+ /* opened paths, so we'll close it explicitely there. */
+
+ if ( builder->path_begun && builder->face->type1.paint_type == 1 )
+ {
+ if ( builder->face->type1.paint_type == 1 )
+ {
+ error = close_open_path( builder );
+ if ( error )
+ return error;
+ }
+ }
+
+ /* grow buffer if necessary */
+ error = T1_Add_Contours( builder, 1 ) ||
+ T1_Add_Points ( builder, 1 );
+ if ( error )
+ return error;
+
+ /* save current contour, if any */
+ if ( cur->n_contours > 0 )
+ cur->contours[cur->n_contours - 1] = cur->n_points - 1;
+
+ if ( builder->load_points )
+ {
+ /* save point */
+ vec.x = builder->last.x + dx;
+ vec.y = builder->last.y + dy;
+ cur->points[cur->n_points] = vec;
+ cur->tags [cur->n_points] = FT_Curve_Tag_On;
+
+ builder->last = vec;
+ }
+
+ cur->n_contours++;
+ cur->n_points++;
+
+ return T1_Err_Ok;
+ }
+
+
+ static
+ FT_Error gload_rrcurveto( T1_Builder* builder,
+ FT_Pos dx1,
+ FT_Pos dy1,
+ FT_Pos dx2,
+ FT_Pos dy2,
+ FT_Pos dx3,
+ FT_Pos dy3 )
+ {
+ FT_Error error;
+ FT_Outline* cur = builder->current;
+ FT_Vector vec;
+ FT_Vector* points;
+ char* tags;
+
+
+ /* grow buffer if necessary */
+ error = T1_Add_Points( builder, 3 );
+ if ( error )
+ return error;
+
+ if ( builder->load_points )
+ {
+ /* save point */
+ points = cur->points + cur->n_points;
+ tags = cur->tags + cur->n_points;
+
+ vec.x = builder->last.x + dx1;
+ vec.y = builder->last.y + dy1;
+ points[0] = vec;
+ tags[0] = FT_Curve_Tag_Cubic;
+
+ vec.x += dx2;
+ vec.y += dy2;
+ points[1] = vec;
+ tags[1] = FT_Curve_Tag_Cubic;
+
+ vec.x += dx3;
+ vec.y += dy3;
+ points[2] = vec;
+ tags[2] = FT_Curve_Tag_On;
+
+ builder->last = vec;
+ }
+
+ cur->n_points += 3;
+ builder->path_begun = 1;
+
+ return T1_Err_Ok;
+ }
+
+
+ static
+ FT_Error gload_ignore( void )
+ {
+ return 0;
+ }
+
+
+ static
+ const T1_Builder_Funcs gload_builder_interface =
+ {
+ gload_endchar,
+ gload_sbw,
+ gload_closepath,
+ gload_rlineto,
+ gload_rmoveto,
+ gload_rrcurveto
+ };
+
+
+ static
+ const T1_Builder_Funcs gload_builder_interface_null =
+ {
+ (T1_Builder_EndChar) gload_ignore,
+ (T1_Builder_Sbw) gload_sbw, /* record left bearing */
+ (T1_Builder_ClosePath)gload_ignore,
+ (T1_Builder_RLineTo) gload_ignore,
+ (T1_Builder_RMoveTo) gload_ignore,
+ (T1_Builder_RCurveTo) gload_ignore
+ };
+
+
+ static
+ const T1_Hinter_Funcs gload_hinter_interface =
+ {
+ (T1_Hinter_DotSection) gload_ignore, /* dotsection */
+ (T1_Hinter_ChangeHints)gload_ignore, /* changehints */
+ (T1_Hinter_Stem) gload_ignore, /* hstem & vstem */
+ (T1_Hinter_Stem3) gload_ignore, /* hstem3 & vestem3 */
+ };
+
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+
+
+ /*************************************************************************/
+ /* */
+ /* Hinter overview: */
+ /* */
+ /* This is a two-pass hinter. On the first pass, the hints are all */
+ /* recorded by the hinter, and no point is loaded in the outline. */
+ /* */
+ /* When the first pass is finished, all stems hints are grid-fitted */
+ /* at once. */
+ /* */
+ /* Then, a second pass is performed to load the outline points as */
+ /* well as hint/scale them correctly. */
+ /* */
+ /*************************************************************************/
+
+
+ static
+ FT_Error t1_load_hinted_glyph( T1_Decoder* decoder,
+ FT_UInt glyph_index,
+ FT_Bool recurse )
+ {
+ T1_Builder* builder = &decoder->builder;
+ T1_GlyphSlot glyph = builder->glyph;
+ T1_Font* type1 = &builder->face->type1;
+ FT_UInt old_points, old_contours;
+ FT_GlyphLoader* loader = decoder->builder.loader;
+ FT_Error error;
+
+
+ /* Pass 1 -- try to load first glyph, simply recording points */
+ old_points = loader->base.outline.n_points;
+ old_contours = loader->base.outline.n_contours;
+
+ FT_GlyphLoader_Prepare( decoder->builder.loader );
+
+ T1_Reset_Builder( builder, 0 );
+
+ builder->no_recurse = recurse;
+ builder->pass = 0;
+ glyph->hints->hori_stems.num_stems = 0;
+ glyph->hints->vert_stems.num_stems = 0;
+
+ error = T1_Parse_CharStrings( decoder,
+ type1->charstrings [glyph_index],
+ type1->charstrings_len[glyph_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+ if ( error )
+ goto Exit;
+
+ /* check for composite (i.e. `seac' operator) */
+ if ( glyph->root.format == ft_glyph_format_composite )
+ {
+ /* this is a composite glyph, we must then load the first one, */
+ /* then load the second one on top of it and translate it by a */
+ /* fixed amount. */
+ FT_UInt n_base_points;
+ FT_SubGlyph* subglyph = loader->base.subglyphs;
+ T1_Size size = builder->size;
+ FT_Pos dx, dy;
+ FT_Vector left_bearing, advance;
+
+
+ /* clean glyph format */
+ glyph->root.format = ft_glyph_format_none;
+
+ /* First load `bchar' in builder */
+ builder->no_recurse = 0;
+ error = t1_load_hinted_glyph( decoder, subglyph->index, 0 );
+ if ( error )
+ goto Exit;
+
+ /* save the left bearing and width of the base character */
+ /* as they will be erased by the next load */
+ left_bearing = builder->left_bearing;
+ advance = builder->advance;
+
+ /* Then load `achar' in builder */
+ n_base_points = builder->base->n_points;
+ subglyph++;
+ error = t1_load_hinted_glyph( decoder, subglyph->index, 0 );
+ if ( error )
+ goto Exit;
+
+ /* Finally, move the accent */
+ dx = FT_MulFix( subglyph->arg1, size->root.metrics.x_scale );
+ dy = FT_MulFix( subglyph->arg2, size->root.metrics.y_scale );
+ dx = ( dx + 32 ) & -64;
+ dy = ( dy + 32 ) & -64;
+ {
+ FT_Outline dummy;
+
+
+ dummy.n_points = loader->base.outline.n_points - n_base_points;
+ dummy.points = loader->base.outline.points + n_base_points;
+
+ FT_Outline_Translate( &dummy, dx, dy );
+ }
+
+ /* restore the left side bearing and */
+ /* advance width of the base character */
+ builder->left_bearing = left_bearing;
+ builder->advance = advance;
+ }
+ else
+ {
+ /* All right, pass 1 is finished, now grid-fit all stem hints */
+ T1_Hint_Stems( &decoder->builder );
+
+ /* undo the end-char */
+ builder->base->n_points = old_points;
+ builder->base->n_contours = old_contours;
+
+ /* Pass 2 -- record and scale/hint the points */
+ T1_Reset_Builder( builder, 0 );
+
+ builder->pass = 1;
+ builder->no_recurse = 0;
+
+ error = T1_Parse_CharStrings( decoder,
+ type1->charstrings [glyph_index],
+ type1->charstrings_len[glyph_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+ }
+
+ /* save new glyph tables */
+ if ( recurse )
+ T1_Done_Builder( builder );
+
+ Exit:
+ return error;
+ }
+
+
+#endif /* !T1_CONFIG_OPTION_DISABLE_HINTER */
+
+
+ LOCAL_FUNC
+ FT_Error T1_Load_Glyph( T1_GlyphSlot glyph,
+ T1_Size size,
+ FT_Int glyph_index,
+ FT_Int load_flags )
+ {
+ FT_Error error;
+ T1_Decoder decoder;
+ T1_Face face = (T1_Face)glyph->root.face;
+ FT_Bool hinting;
+ T1_Font* type1 = &face->type1;
+
+
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+ glyph->x_scale = size->root.metrics.x_scale;
+ glyph->y_scale = size->root.metrics.y_scale;
+
+ glyph->root.outline.n_points = 0;
+ glyph->root.outline.n_contours = 0;
+
+ glyph->root.format = ft_glyph_format_outline; /* by default */
+
+ hinting = 0;
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+
+ hinting = ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0;
+
+ if ( hinting )
+ {
+ T1_Init_Decoder( &decoder, &t1_hinter_funcs );
+ T1_Init_Builder( &decoder.builder, face, size, glyph,
+ &gload_builder_interface );
+
+ error = t1_load_hinted_glyph( &decoder, glyph_index, 1 );
+ }
+ else
+
+#endif /* !T1_CONFIG_OPTION_DISABLE_HINTER */
+
+ {
+ T1_Init_Decoder( &decoder, &gload_hinter_interface );
+
+ T1_Init_Builder( &decoder.builder, face, size, glyph,
+ &gload_builder_interface );
+
+ decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0;
+
+ /* now load the unscaled outline */
+ error = T1_Parse_CharStrings( &decoder,
+ type1->charstrings [glyph_index],
+ type1->charstrings_len[glyph_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+
+ /* save new glyph tables */
+ T1_Done_Builder( &decoder.builder );
+ }
+
+ /* Now, set the metrics -- this is rather simple, as */
+ /* the left side bearing is the xMin, and the top side */
+ /* bearing the yMax */
+ if ( !error )
+ {
+ /* for composite glyphs, return only the left side bearing and the */
+ /* advance width */
+ if ( glyph->root.format == ft_glyph_format_composite )
+ {
+ glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+ glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
+ }
+ else
+ {
+ FT_BBox cbox;
+ FT_Glyph_Metrics* metrics = &glyph->root.metrics;
+
+
+ /* apply the font matrix */
+ FT_Outline_Transform( &glyph->root.outline,
+ &face->type1.font_matrix );
+
+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+ /* grid fit the bounding box if necessary */
+ if ( hinting )
+ {
+ cbox.xMin &= -64;
+ cbox.yMin &= -64;
+ cbox.xMax = ( cbox.xMax + 63 ) & -64;
+ cbox.yMax = ( cbox.yMax + 63 ) & -64;
+ }
+
+ metrics->width = cbox.xMax - cbox.xMin;
+ metrics->height = cbox.yMax - cbox.yMin;
+
+ metrics->horiBearingX = cbox.xMin;
+ metrics->horiBearingY = cbox.yMax;
+
+ /* copy the _unscaled_ advance width */
+ metrics->horiAdvance = decoder.builder.advance.x;
+
+ /* make up vertical metrics */
+ metrics->vertBearingX = 0;
+ metrics->vertBearingY = 0;
+ metrics->vertAdvance = 0;
+
+ glyph->root.format = ft_glyph_format_outline;
+
+ glyph->root.outline.flags = 0;
+
+ if ( size->root.metrics.y_ppem < 24 )
+ glyph->root.outline.flags |= ft_outline_high_precision;
+
+ glyph->root.outline.flags |= ft_outline_reverse_fill;
+
+ if ( hinting )
+ {
+ /* adjust the advance width */
+ /* XXX TODO: consider stem hints grid-fit */
+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance,
+ glyph->x_scale );
+ }
+ else if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ /* scale the outline and the metrics */
+ FT_Int n;
+ FT_Outline* cur = decoder.builder.base;
+ FT_Vector* vec = cur->points;
+ FT_Fixed x_scale = glyph->x_scale;
+ FT_Fixed y_scale = glyph->y_scale;
+
+
+ /* First of all, scale the points */
+ for ( n = cur->n_points; n > 0; n--, vec++ )
+ {
+ vec->x = FT_MulFix( vec->x, x_scale );
+ vec->y = FT_MulFix( vec->y, y_scale );
+ }
+
+ /* Then scale the metrics */
+ metrics->width = FT_MulFix( metrics->width, x_scale );
+ metrics->height = FT_MulFix( metrics->height, y_scale );
+
+ metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale );
+ metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale );
+
+ metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+ metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+
+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
+ }
+ }
+ }
+
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1gload.h */
+/* */
+/* Type 1 Glyph Loader (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T1GLOAD_H
+#define T1GLOAD_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1objs.h"
+
+#else
+
+#include <type1/t1objs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ typedef struct T1_Builder_ T1_Builder;
+
+ typedef FT_Error (*T1_Builder_EndChar)( T1_Builder* loader );
+
+ typedef FT_Error (*T1_Builder_Sbw)( T1_Builder* loader,
+ FT_Pos sbx,
+ FT_Pos sby,
+ FT_Pos wx,
+ FT_Pos wy );
+
+ typedef FT_Error (*T1_Builder_ClosePath)( T1_Builder* loader );
+
+ typedef FT_Error (*T1_Builder_RLineTo)( T1_Builder* loader,
+ FT_Pos dx,
+ FT_Pos dy );
+
+ typedef FT_Error (*T1_Builder_RMoveTo)( T1_Builder* loader,
+ FT_Pos dx,
+ FT_Pos dy );
+
+ typedef FT_Error (*T1_Builder_RCurveTo)( T1_Builder* loader,
+ FT_Pos dx1,
+ FT_Pos dy1,
+ FT_Pos dx2,
+ FT_Pos dy2,
+ FT_Pos dx3,
+ FT_Pos dy3 );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Structure> */
+ /* T1_Builder_Funcs */
+ /* */
+ /* <Description> */
+ /* A structure to store the address of various functions used by a */
+ /* glyph builder to implement the outline's `path construction'. */
+ /* */
+ typedef struct T1_Builder_Funcs_
+ {
+ T1_Builder_EndChar end_char;
+ T1_Builder_Sbw set_bearing_point;
+ T1_Builder_ClosePath close_path;
+ T1_Builder_RLineTo rline_to;
+ T1_Builder_RMoveTo rmove_to;
+ T1_Builder_RCurveTo rcurve_to;
+
+ } T1_Builder_Funcs;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Structure> */
+ /* T1_Builder */
+ /* */
+ /* <Description> */
+ /* A structure used during glyph loading to store its outline. */
+ /* */
+ /* <Fields> */
+ /* memory :: The current memory object. */
+ /* */
+ /* face :: The current face object. */
+ /* */
+ /* size :: The current size object. */
+ /* */
+ /* glyph :: The current glyph slot. */
+ /* */
+ /* loader :: The current glyph loader. */
+ /* */
+ /* current :: The current glyph outline. */
+ /* */
+ /* base :: The base glyph outline. */
+ /* */
+ /* last :: The last point position. */
+ /* */
+ /* scale_x :: The horizontal scale (FUnits to sub-pixels). */
+ /* */
+ /* scale_y :: The vertical scale (FUnits to sub-pixels). */
+ /* */
+ /* pos_x :: The horizontal translation (for composite glyphs). */
+ /* */
+ /* pos_y :: The vertical translation (for composite glyphs). */
+ /* */
+ /* left_bearing :: The left side bearing point. */
+ /* */
+ /* advance :: The horizontal advance vector. */
+ /* */
+ /* no_recurse :: */
+ /* */
+ /* bbox :: The glyph's bounding box. */
+ /* */
+ /* path_begun :: A flag which indicates that a new path has begun. */
+ /* */
+ /* load_points :: A flag which indicates, if not set, that no points */
+ /* are loaded. */
+ /* */
+ /* pass :: The pass number for multi-pass hinters. */
+ /* */
+ /* hint_point :: The index of the next point to hint. */
+ /* */
+ /* funcs :: A table of builder functions used to perform the */
+ /* outline's path construction. */
+ /* */
+ struct T1_Builder_
+ {
+ FT_Memory memory;
+ T1_Face face;
+ T1_Size size;
+ T1_GlyphSlot glyph;
+ FT_GlyphLoader* loader;
+
+ FT_Outline* current; /* the current glyph outline */
+ FT_Outline* base; /* the composite glyph outline */
+
+ FT_Vector last;
+
+ FT_Fixed scale_x;
+ FT_Fixed scale_y;
+
+ FT_Pos pos_x;
+ FT_Pos pos_y;
+
+ FT_Vector left_bearing;
+ FT_Vector advance;
+ FT_Bool no_recurse;
+
+ FT_BBox bbox; /* bounding box */
+ FT_Bool path_begun;
+ FT_Bool load_points;
+
+ FT_Int pass;
+ FT_Int hint_point;
+
+ /* path construction function interface */
+ T1_Builder_Funcs funcs;
+ };
+
+
+ typedef FT_Error (*T1_Hinter_ChangeHints)( T1_Builder* builder );
+
+ typedef FT_Error (*T1_Hinter_DotSection)( T1_Builder* builder );
+
+ typedef FT_Error (*T1_Hinter_Stem)( T1_Builder* builder,
+ FT_Pos pos,
+ FT_Pos width,
+ FT_Bool vertical );
+
+ typedef FT_Error (*T1_Hinter_Stem3)( T1_Builder* builder,
+ FT_Pos pos0,
+ FT_Pos width0,
+ FT_Pos pos1,
+ FT_Pos width1,
+ FT_Pos pos2,
+ FT_Pos width2,
+ FT_Bool vertical );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Structure> */
+ /* T1_Hinter_Funcs */
+ /* */
+ /* <Description> */
+ /* A structure to store the address of various functions used by a */
+ /* Type 1 hinter to perform outline hinting. */
+ /* */
+ typedef struct T1_Hinter_Func_
+ {
+ T1_Hinter_ChangeHints change_hints;
+ T1_Hinter_DotSection dot_section;
+ T1_Hinter_Stem stem;
+ T1_Hinter_Stem3 stem3;
+
+ } T1_Hinter_Funcs;
+
+
+ typedef enum T1_Operator_
+ {
+ op_none = 0,
+ op_endchar,
+ op_hsbw,
+ op_seac,
+ op_sbw,
+ op_closepath,
+ op_hlineto,
+ op_hmoveto,
+ op_hvcurveto,
+ op_rlineto,
+ op_rmoveto,
+ op_rrcurveto,
+ op_vhcurveto,
+ op_vlineto,
+ op_vmoveto,
+ op_dotsection,
+ op_hstem,
+ op_hstem3,
+ op_vstem,
+ op_vstem3,
+ op_div,
+ op_callothersubr,
+ op_callsubr,
+ op_pop,
+ op_return,
+ op_setcurrentpoint,
+
+ op_max /* never remove this one */
+
+ } T1_Operator;
+
+
+ /* execution context charstring zone */
+ typedef struct T1_Decoder_Zone_
+ {
+ FT_Byte* base;
+ FT_Byte* limit;
+ FT_Byte* cursor;
+
+ } T1_Decoder_Zone;
+
+
+ typedef struct T1_Decoder_
+ {
+ T1_Builder builder;
+ T1_Hinter_Funcs hinter;
+
+ FT_Int stack[T1_MAX_CHARSTRINGS_OPERANDS];
+ FT_Int* top;
+
+ T1_Decoder_Zone zones[T1_MAX_SUBRS_CALLS + 1];
+ T1_Decoder_Zone* zone;
+
+ FT_Int flex_state;
+ FT_Int num_flex_vectors;
+ FT_Vector flex_vectors[7];
+
+ } T1_Decoder;
+
+
+ LOCAL_DEF
+ void T1_Init_Builder( T1_Builder* builder,
+ T1_Face face,
+ T1_Size size,
+ T1_GlyphSlot glyph,
+ const T1_Builder_Funcs* funcs );
+
+ LOCAL_DEF
+ void T1_Done_Builder( T1_Builder* builder );
+
+ LOCAL_DEF
+ void T1_Init_Decoder( T1_Decoder* decoder,
+ const T1_Hinter_Funcs* funcs );
+
+ LOCAL_DEF
+ FT_Error T1_Compute_Max_Advance( T1_Face face,
+ FT_Int* max_advance );
+
+ LOCAL_DEF
+ FT_Error T1_Parse_CharStrings( T1_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_Int charstring_len,
+ FT_Int num_subrs,
+ FT_Byte** subrs_base,
+ FT_Int* subrs_len );
+
+ LOCAL_DEF
+ FT_Error T1_Add_Points( T1_Builder* builder,
+ FT_Int num_points );
+
+ LOCAL_DEF
+ FT_Error T1_Add_Contours( T1_Builder* builder,
+ FT_Int num_contours );
+
+ LOCAL_DEF
+ FT_Error T1_Load_Glyph( T1_GlyphSlot glyph,
+ T1_Size size,
+ FT_Int glyph_index,
+ FT_Int load_flags );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* T1GLOAD_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1hinter.c */
+/* */
+/* Type 1 hinter (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* The Hinter is in charge of fitting th scaled outline to the pixel */
+ /* grid in order to considerably improve the quality of the Type 1 font */
+ /* driver's output. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1objs.h"
+#include "t1hinter.h"
+
+#else
+
+#include <type1/t1objs.h>
+#include <type1/t1hinter.h>
+
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1hint
+
+
+#undef ONE_PIXEL
+#define ONE_PIXEL 64
+
+#undef ROUND
+#define ROUND( x ) ( ( x + ONE_PIXEL / 2 ) & -ONE_PIXEL )
+
+#undef SCALE
+#define SCALE( val ) FT_MulFix( val, scale )
+
+/* various constants used to describe the alignment of a horizontal */
+/* stem with regards to the blue zones */
+
+#define T1_ALIGN_NONE 0
+#define T1_ALIGN_BOTTOM 1
+#define T1_ALIGN_TOP 2
+#define T1_ALIGN_BOTH 3
+
+
+ /* very simple bubble sort (not a lot of elements, mostly */
+ /* pre-sorted, no need for quicksort) */
+
+ static
+ void t1_sort_blues( FT_Int* blues,
+ FT_Int count )
+ {
+ FT_Int i, swap;
+ FT_Int* cur;
+
+
+ for ( i = 2; i < count; i += 2 )
+ {
+ cur = blues + i;
+ do
+ {
+ if ( cur[-1] < cur[0] )
+ break;
+
+ swap = cur[-2]; cur[-2] = cur[0]; cur[0] = swap;
+ swap = cur[-1]; cur[-1] = cur[1]; cur[1] = swap;
+ cur -= 2;
+
+ } while ( cur > blues );
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1_set_blue_zones */
+ /* */
+ /* <Description> */
+ /* Sets a size object's blue zones during reset. This will compute */
+ /* the `snap' zone corresponding to each blue zone. */
+ /* */
+ /* <InOut> */
+ /* size :: A handle to target size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This functions does the following: */
+ /* */
+ /* 1. It extracts the bottom and top blue zones from the face object. */
+ /* */
+ /* 2. Each zone is then grown by `BlueFuzz', overlapping is */
+ /* eliminated by adjusting the zone edges appropriately. */
+ /* */
+ /* 3. For each zone, we keep its original font units position, its */
+ /* original scaled position, as well as its grown/adjusted edges. */
+ /* */
+ static
+ FT_Error t1_set_blue_zones( T1_Size size )
+ {
+ T1_Face face = (T1_Face)size->root.face;
+ T1_Private* priv = &face->type1.private_dict;
+ FT_Int n;
+ FT_Int blues[24];
+ FT_Int num_bottom;
+ FT_Int num_top;
+ FT_Int num_blues;
+ T1_Size_Hints* hints = size->hints;
+ T1_Snap_Zone* zone;
+ FT_Pos pix, orus;
+ FT_Pos min, max, threshold;
+ FT_Fixed scale;
+ FT_Bool is_bottom;
+
+
+ /***********************************************************************/
+ /* */
+ /* copy bottom and top blue zones in local arrays */
+ /* */
+
+ /* First of all, check the sizes of the /BlueValues and /OtherBlues */
+ /* tables. They all must contain an even number of arguments. */
+ if ( priv->num_other_blues & 1 ||
+ priv->num_blue_values & 1 )
+ {
+ FT_ERROR(( "t1_set_blue_zones: odd number of blue values\n" ));
+ return T1_Err_Syntax_Error;
+ }
+
+ /* copy the bottom blue zones from /OtherBlues */
+ num_top = 0;
+ num_bottom = priv->num_other_blues;
+
+ for ( n = 0; n < num_bottom; n++ )
+ blues[n] = priv->other_blues[n];
+
+ /* add the first blue zone in /BlueValues to the table */
+ num_top = priv->num_blue_values - 2;
+ if ( num_top >= 0 )
+ {
+ blues[num_bottom ] = priv->blue_values[0];
+ blues[num_bottom + 1] = priv->blue_values[1];
+
+ num_bottom += 2;
+ }
+
+ /* sort the bottom blue zones */
+ t1_sort_blues( blues, num_bottom );
+
+ hints->num_bottom_zones = num_bottom >> 1;
+
+ /* now copy the /BlueValues to the top of the blues array */
+ if ( num_top > 0 )
+ {
+ for ( n = 0; n < num_top; n++ )
+ blues[num_bottom + n] = priv->blue_values[n + 2];
+
+ /* sort the top blue zones */
+ t1_sort_blues( blues + num_bottom, num_top );
+ }
+ else
+ num_top = 0;
+
+ num_blues = num_top + num_bottom;
+ hints->num_blue_zones = ( num_blues ) >> 1;
+
+ /***********************************************************************/
+ /* */
+ /* build blue snap zones from the local blues arrays */
+ /* */
+
+ scale = size->root.metrics.y_scale;
+ zone = hints->blue_zones;
+ threshold = ONE_PIXEL / 4; /* 0.25 pixels */
+
+ for ( n = 0; n < num_blues; n += 2, zone++ )
+ {
+ is_bottom = n < num_bottom ? 1 : 0;
+
+ orus = blues[n + is_bottom]; /* get alignement coordinate */
+ pix = SCALE( orus ); /* scale it */
+
+ min = SCALE( blues[n ] - priv->blue_fuzz );
+ max = SCALE( blues[n + 1] + priv->blue_fuzz );
+
+ if ( min > pix - threshold )
+ min = pix - threshold;
+ if ( max < pix + threshold )
+ max = pix + threshold;
+
+ zone->orus = orus;
+ zone->pix = pix;
+ zone->min = min;
+ zone->max = max;
+ }
+
+ /* adjust edges in case of overlap */
+ zone = hints->blue_zones;
+ for ( n = 0; n < num_blues - 2; n += 2, zone++ )
+ {
+ if ( n != num_bottom - 2 &&
+ zone[0].max > zone[1].min )
+ zone[0].max = zone[1].min = ( zone[0].pix + zone[1].pix ) / 2;
+ }
+
+ /* compare the current pixel size with the BlueScale value */
+ /* to know whether to supress overshoots */
+
+ hints->supress_overshoots =
+ size->root.metrics.y_ppem < FT_MulFix( 1000, priv->blue_scale );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+ /* now print the new blue values in tracing mode */
+
+ FT_TRACE2(( "Blue Zones for size object at $%08lx:\n", (long)size ));
+ FT_TRACE2(( " orus pix min max\n" ));
+ FT_TRACE2(( "-------------------------------\n" ));
+
+ zone = hints->blue_zones;
+ for ( n = 0; n < hints->num_blue_zones; n++ )
+ {
+ FT_TRACE2(( " %3d %.2f %.2f %.2f\n",
+ zone->orus,
+ zone->pix / 64.0,
+ zone->min / 64.0,
+ zone->max / 64.0 ));
+ zone++;
+ }
+ FT_TRACE2(( "\nOvershoots are %s\n\n",
+ hints->supress_overshoots ? "supressed" : "active" ));
+
+#endif /* DEBUG_LEVEL_TRACE */
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1_set_snap_zones */
+ /* */
+ /* <Description> */
+ /* This function set a size object's stem snap zones. */
+ /* */
+ /* <InOut> */
+ /* size :: A handle to the target size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function performs the following: */
+ /* */
+ /* 1. It reads and scales the stem snap widths from the parent face. */
+ /* */
+ /* 2. A `snap zone' is computed for each snap width, by `growing' it */
+ /* with a threshold of 1/2 pixel. Overlapping is avoided through */
+ /* proper edge adjustment. */
+ /* */
+ /* 3. Each width whose zone contain the scaled standard set width is */
+ /* removed from the table. */
+ /* */
+ /* 4. Finally, the standard set width is scaled, and its correponding */
+ /* `snap zone' is inserted into the sorted snap zones table. */
+ /* */
+ static
+ FT_Error t1_set_snap_zones( T1_Size size )
+ {
+ FT_Int n, direction, n_zones, num_zones;
+ T1_Snap_Zone* zone;
+ T1_Snap_Zone* base_zone;
+ FT_Short* orgs;
+ FT_Pos standard_width;
+ FT_Fixed scale;
+
+ T1_Face face = (T1_Face)size->root.face;
+ T1_Private* priv = &face->type1.private_dict;
+ T1_Size_Hints* hints = size->hints;
+
+
+ /* start with horizontal snap zones */
+ direction = 0;
+ standard_width = priv->standard_width[0];
+ n_zones = priv->num_snap_widths;
+ base_zone = hints->snap_widths;
+ orgs = priv->snap_widths;
+ scale = size->root.metrics.x_scale;
+
+ while ( direction < 2 )
+ {
+ /*********************************************************************/
+ /* */
+ /* Read and scale stem snap widths table from the physical font */
+ /* record. */
+ /* */
+
+ FT_Pos prev, orus, pix, min, max, threshold;
+
+
+ threshold = ONE_PIXEL / 4;
+ zone = base_zone;
+
+ if ( n_zones > 0 )
+ {
+ orus = *orgs++;
+ pix = SCALE( orus );
+ min = pix - threshold;
+ max = pix + threshold;
+
+ zone->orus = orus;
+ zone->pix = pix;
+ zone->min = min;
+ prev = pix;
+
+ for ( n = 1; n < n_zones; n++ )
+ {
+ orus = *orgs++;
+ pix = SCALE( orus );
+
+ if ( pix - prev < 2 * threshold )
+ {
+ min = max = ( pix + prev ) / 2;
+ }
+ else
+ min = pix - threshold;
+
+ zone->max = max;
+ zone++;
+ zone->orus = orus;
+ zone->pix = pix;
+ zone->min = min;
+
+ max = pix + threshold;
+ prev = pix;
+ }
+ zone->max = max;
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+ /* print the scaled stem snap values in tracing mode */
+
+ FT_TRACE2(( "Set_Snap_Zones: first %s pass\n",
+ direction ? "vertical" : "horizontal" ));
+
+ FT_TRACE2(( "Scaled original stem snap zones:\n" ));
+ FT_TRACE2(( " orus pix min max\n" ));
+ FT_TRACE2(( "-----------------------------\n" ));
+
+ zone = base_zone;
+ for ( n = 0; n < n_zones; n++, zone++ )
+ FT_TRACE2(( " %3d %.2f %.2f %.2f\n",
+ zone->orus,
+ zone->pix / 64.0,
+ zone->min / 64.0,
+ zone->max / 64.0 ));
+ FT_TRACE2(( "\n" ));
+
+ FT_TRACE2(( "Standard width = %d\n", standard_width ));
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+ /*********************************************************************/
+ /* */
+ /* Now, each snap width which is in the range of the standard set */
+ /* width will be removed from the list. */
+ /* */
+
+ if ( standard_width > 0 )
+ {
+ T1_Snap_Zone* parent;
+ FT_Pos std_pix, std_min, std_max;
+
+
+ std_pix = SCALE( standard_width );
+
+ std_min = std_pix - threshold;
+ std_max = std_pix + threshold;
+
+ num_zones = 0;
+ zone = base_zone;
+ parent = base_zone;
+
+ for ( n = 0; n < n_zones; n++ )
+ {
+ if ( zone->pix >= std_min && zone->pix <= std_max )
+ {
+ /* this zone must be removed from the list */
+ if ( std_min > zone->min )
+ std_min = zone->min;
+ if ( std_max < zone->max )
+ std_max = zone->max;
+ }
+ else
+ {
+ *parent++ = *zone;
+ num_zones++;
+ }
+ zone++;
+ }
+
+ /*******************************************************************/
+ /* */
+ /* Now, insert the standard width zone */
+ /* */
+
+ zone = base_zone + num_zones;
+ while ( zone > base_zone && zone[-1].pix > std_max )
+ {
+ zone[0] = zone[-1];
+ zone--;
+ }
+
+ /* check border zones */
+ if ( zone > base_zone && zone[-1].max > std_min )
+ zone[-1].max = std_min;
+
+ if ( zone < base_zone + num_zones && zone[1].min < std_max )
+ zone[1].min = std_max;
+
+ zone->orus = standard_width;
+ zone->pix = std_pix;
+ zone->min = std_min;
+ zone->max = std_max;
+
+ num_zones++;
+ }
+ else
+ num_zones = n_zones;
+
+ /* save total number of stem snaps now */
+ if ( direction )
+ hints->num_snap_heights = num_zones;
+ else
+ hints->num_snap_widths = num_zones;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+ /* print the scaled stem snap values in tracing mode */
+
+ FT_TRACE2(( "Set_Snap_Zones: second %s pass\n",
+ direction ? "vertical" : "horizontal" ));
+
+ FT_TRACE2(( "Scaled clipped stem snap zones:\n" ));
+ FT_TRACE2(( " orus pix min max\n" ));
+ FT_TRACE2(( "-----------------------------\n" ));
+
+ zone = base_zone;
+ for ( n = 0; n < num_zones; n++, zone++ )
+ FT_TRACE2(( " %3d %.2f %.2f %.2f\n",
+ zone->orus,
+ zone->pix / 64.0,
+ zone->min / 64.0,
+ zone->max / 64.0 ));
+ FT_TRACE2(( "\n" ));
+
+ FT_TRACE2(( "Standard width = %d\n", standard_width ));
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+ /* continue with vertical snap zone */
+ direction++;
+ standard_width = priv->standard_height[0];
+ n_zones = priv->num_snap_heights;
+ base_zone = hints->snap_heights;
+ orgs = priv->snap_heights;
+ scale = size->root.metrics.y_scale;
+ }
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_New_Size_Hinter */
+ /* */
+ /* <Description> */
+ /* Allocates a new hinter structure for a given size object. */
+ /* */
+ /* <InOut> */
+ /* size :: A handle to the target size object. */
+ /* */
+ /* <Return> */
+ /* FreeType Error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error T1_New_Size_Hinter( T1_Size size )
+ {
+ FT_Memory memory = size->root.face->memory;
+
+
+ return MEM_Alloc( size->hints, sizeof ( *size->hints ) );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Done_Size_Hinter */
+ /* */
+ /* <Description> */
+ /* Releases a given size object's hinter structure. */
+ /* */
+ /* <Input> */
+ /* size :: A handle to the target size object. */
+ /* */
+ LOCAL_FUNC
+ void T1_Done_Size_Hinter( T1_Size size )
+ {
+ FT_Memory memory = size->root.face->memory;
+
+
+ FREE( size->hints );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Reset_Size_Hinter */
+ /* */
+ /* <Description> */
+ /* Recomputes hinting information when a given size object has */
+ /* changed its resolutions/char sizes/pixel sizes. */
+ /* */
+ /* <InOut> */
+ /* size :: A handle to the size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error T1_Reset_Size_Hinter( T1_Size size )
+ {
+ return t1_set_blue_zones( size ) || t1_set_snap_zones( size );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_New_Glyph_Hinter */
+ /* */
+ /* <Description> */
+ /* Allocates a new hinter structure for a given glyph slot. */
+ /* */
+ /* <InOut> */
+ /* glyph :: A handle to the target glyph slot. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error T1_New_Glyph_Hinter( T1_GlyphSlot glyph )
+ {
+ FT_Memory memory = glyph->root.face->memory;
+
+
+ return MEM_Alloc( glyph->hints, sizeof ( *glyph->hints ) );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Done_Glyph_Hinter */
+ /* */
+ /* <Description> */
+ /* Releases a given glyph slot's hinter structure. */
+ /* */
+ /* <Input> */
+ /* glyph :: A handle to the glyph slot. */
+ /* */
+ LOCAL_FUNC
+ void T1_Done_Glyph_Hinter( T1_GlyphSlot glyph )
+ {
+ FT_Memory memory = glyph->root.face->memory;
+
+
+ FREE( glyph->hints );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** **********/
+ /********** HINTED GLYPH LOADER **********/
+ /********** **********/
+ /********** The following code is in charge of the first **********/
+ /********** and second pass when loading a single outline **********/
+ /********** **********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static
+ FT_Error t1_hinter_ignore( void )
+ {
+ /* do nothing, used for `dotsection' which is unsupported for now */
+ return 0;
+ }
+
+
+ static
+ FT_Error t1_hinter_stem( T1_Builder* builder,
+ FT_Pos pos,
+ FT_Int width,
+ FT_Bool vertical )
+ {
+ T1_Stem_Table* stem_table;
+ T1_Stem_Hint* stems;
+ T1_Stem_Hint* cur_stem;
+ FT_Int min, max, n, num_stems;
+ FT_Bool new_stem;
+ T1_Glyph_Hints* hinter = builder->glyph->hints;
+
+
+ /* select the appropriate stem array */
+ stem_table = vertical ? &hinter->vert_stems : &hinter->hori_stems;
+ stems = stem_table->stems;
+ num_stems = stem_table->num_stems;
+
+ /* Compute minimum and maximum coord for the stem */
+ min = pos + ( vertical
+ ? builder->left_bearing.x
+ : builder->left_bearing.y );
+
+ if ( width >= 0 )
+ max = min + width;
+ else
+ {
+ /* a negative width indicates a `ghost' stem */
+ if ( width == -21 )
+ min += width;
+
+ max = min;
+ }
+
+ /* Now scan the array. If we find a stem with the same borders */
+ /* simply activate it. */
+ cur_stem = stems;
+ new_stem = 1;
+
+ for ( n = 0; n < num_stems; n++, cur_stem++ )
+ {
+ if ( cur_stem->min_edge.orus == min &&
+ cur_stem->max_edge.orus == max )
+ {
+ /* This stem is already in the table, simply activate it */
+ if ( ( cur_stem->hint_flags & T1_HINT_FLAG_ACTIVE ) == 0 )
+ {
+ cur_stem->hint_flags |= T1_HINT_FLAG_ACTIVE;
+ stem_table->num_active++;
+ }
+ new_stem = 0;
+ break;
+ }
+ }
+
+ /* add a new stem to the array if necessary */
+ if ( new_stem )
+ {
+ if ( cur_stem >= stems + T1_HINTER_MAX_EDGES )
+ {
+ FT_ERROR(( "t1_hinter_stem: too many stems in glyph charstring\n" ));
+ return T1_Err_Syntax_Error;
+ }
+
+ /* on the first pass, we record the stem, otherwise, this is */
+ /* a bug in the glyph loader! */
+ if ( builder->pass == 0 )
+ {
+ cur_stem->min_edge.orus = min;
+ cur_stem->max_edge.orus = max;
+ cur_stem->hint_flags = T1_HINT_FLAG_ACTIVE;
+
+ stem_table->num_stems++;
+ stem_table->num_active++;
+ }
+ else
+ {
+ FT_ERROR(( "t1_hinter_stem:" ));
+ FT_ERROR(( " fatal glyph loader bug -- pass2-stem\n" ));
+ return T1_Err_Syntax_Error;
+ }
+ }
+
+ return T1_Err_Ok;
+ }
+
+
+ static
+ FT_Error t1_hinter_stem3( T1_Builder* builder,
+ FT_Pos pos0,
+ FT_Int width0,
+ FT_Pos pos1,
+ FT_Int width1,
+ FT_Pos pos2,
+ FT_Int width2,
+ FT_Bool vertical )
+ {
+ /* For now, simply call `stem' 3 times */
+ return t1_hinter_stem( builder, pos0, width0, vertical ) ||
+ t1_hinter_stem( builder, pos1, width1, vertical ) ||
+ t1_hinter_stem( builder, pos2, width2, vertical );
+ }
+
+
+ static
+ FT_Error t1_hinter_changehints( T1_Builder* builder )
+ {
+ FT_Int dimension;
+ T1_Stem_Table* stem_table;
+ T1_Glyph_Hints* hinter = builder->glyph->hints;
+
+
+ /* If we are in the second pass of glyph hinting, we must */
+ /* call the function T1_Hint_Points() on the builder in order */
+ /* to force the fit the latest points to the pixel grid. */
+ if ( builder->pass == 1 )
+ T1_Hint_Points( builder );
+
+ /* Simply de-activate all hints in all arrays */
+ stem_table = &hinter->hori_stems;
+
+ for ( dimension = 2; dimension > 0; dimension-- )
+ {
+ T1_Stem_Hint* cur = stem_table->stems;
+ T1_Stem_Hint* limit = cur + stem_table->num_stems;
+
+
+ for ( ; cur < limit; cur++ )
+ cur->hint_flags &= ~T1_HINT_FLAG_ACTIVE;
+
+ stem_table->num_active = 0;
+ stem_table = &hinter->vert_stems;
+ }
+
+ return T1_Err_Ok;
+ }
+
+
+ const T1_Hinter_Funcs t1_hinter_funcs =
+ {
+ (T1_Hinter_ChangeHints)t1_hinter_changehints,
+ (T1_Hinter_DotSection) t1_hinter_ignore,
+ (T1_Hinter_Stem) t1_hinter_stem,
+ (T1_Hinter_Stem3) t1_hinter_stem3
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** STEM HINTS MANAGEMENT *********/
+ /********** *********/
+ /********** The following code is in charge of computing *********/
+ /********** the placement of each scaled stem hint. *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1_sort_hints */
+ /* */
+ /* <Description> */
+ /* Sorta the list of active stems in increasing order, through the */
+ /* `sort' indexing table. */
+ /* */
+ /* <InOut> */
+ /* table :: A stem hints table. */
+ /* */
+ static
+ void t1_sort_hints( T1_Stem_Table* table )
+ {
+ FT_Int num_stems = table->num_stems;
+ FT_Int num_active = 0;
+ FT_Int* sort = table->sort;
+ T1_Stem_Hint* stems = table->stems;
+ FT_Int n;
+
+
+ /* record active stems in sort table */
+ for ( n = 0; n < num_stems; n++ )
+ {
+ if ( stems[n].hint_flags & T1_HINT_FLAG_ACTIVE )
+ sort[num_active++] = n;
+ }
+
+ /* Now sort the indices. There are usually very few stems, */
+ /* and they are pre-sorted in 90% cases, so we choose a */
+ /* simple bubble sort (quicksort would be slower). */
+ for ( n = 1; n < num_active; n++ )
+ {
+ FT_Int p = n - 1;
+ T1_Stem_Hint* cur = stems + sort[n];
+
+
+ do
+ {
+ FT_Int swap;
+ T1_Stem_Hint* prev = stems + sort[p];
+
+
+ /* note that by definition, the active stems cannot overlap */
+ /* so we simply compare their `min' to sort them (we could compare */
+ /* their max values also; this wouldn't change anything). */
+ if ( prev->min_edge.orus <= cur->min_edge.orus )
+ break;
+
+ /* swap elements */
+ swap = sort[p ];
+ sort[p ] = sort[p + 1];
+ sort[p + 1] = swap;
+ p--;
+
+ } while ( p >= 0 );
+ }
+
+ table->num_active = num_active;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1_hint_horizontal_stems */
+ /* */
+ /* <Description> */
+ /* Computes the location of each scaled horizontal stem hint. This */
+ /* takes care of the blue zones and the horizontal stem snap table. */
+ /* */
+ /* <Input> */
+ /* table :: The horizontal stem hints table. */
+ /* */
+ /* hints :: The current size's hint structure. */
+ /* */
+ /* blueShift :: The value of the /BlueShift as taken from the face */
+ /* object. */
+ /* */
+ /* scale :: The 16.16 scale used to convert outline units to */
+ /* 26.6 pixels. */
+ /* */
+ /* <Note> */
+ /* For now, all stems are hinted independently from each other. It */
+ /* might be necessary, for better performance, to introduce the */
+ /* notion of `controlled' hints describing things like counter-stems, */
+ /* stem3, as well as overlapping stems control. */
+ /* */
+ static
+ void t1_hint_horizontal_stems( T1_Stem_Table* table,
+ T1_Size_Hints* hints,
+ FT_Pos blueShift,
+ FT_Fixed scale )
+ {
+ T1_Stem_Hint* stem = table->stems;
+ T1_Stem_Hint* limit = stem + table->num_stems;
+
+
+ /* first of all, scale the blueShift */
+ blueShift = SCALE( blueShift );
+
+ /* then scan the horizontal stem table */
+ for ( ; stem < limit; stem++ )
+ {
+ FT_Pos bottom_orus = stem->min_edge.orus;
+ FT_Pos top_orus = stem->max_edge.orus;
+
+ FT_Pos top_pix = SCALE( top_orus );
+ FT_Pos bottom_pix = SCALE( bottom_orus );
+ FT_Pos width_pix = top_pix - bottom_pix;
+
+ FT_Pos bottom = bottom_pix;
+ FT_Pos top = top_pix;
+ FT_Int align = T1_ALIGN_NONE;
+
+
+ /*********************************************************************/
+ /* */
+ /* Snap pixel width if in stem snap range */
+ /* */
+
+ {
+ T1_Snap_Zone* zone = hints->snap_heights;
+ T1_Snap_Zone* zone_limit = zone + hints->num_snap_heights;
+ FT_Pos best_dist = 32000;
+ T1_Snap_Zone* best_zone = 0;
+
+
+ for ( ; zone < zone_limit; zone++ )
+ {
+ FT_Pos dist;
+
+
+ dist = width_pix - zone->min;
+ if ( dist < 0 )
+ dist = -dist;
+ if ( dist < best_dist )
+ {
+ best_zone = zone;
+ best_dist = dist;
+ }
+ }
+
+ if ( best_zone )
+ {
+ if ( width_pix > best_zone->pix )
+ {
+ width_pix -= 0x20;
+ if ( width_pix < best_zone->pix )
+ width_pix = best_zone->pix;
+ }
+ else
+ {
+ width_pix += 0x20;
+ if ( width_pix > best_zone->pix )
+ width_pix = best_zone->pix;
+ }
+ }
+ }
+
+ /*********************************************************************/
+ /* */
+ /* round width - minimum 1 pixel if this isn't a ghost stem */
+ /* */
+
+ if ( width_pix > 0 )
+ width_pix = width_pix < ONE_PIXEL ? ONE_PIXEL : ROUND( width_pix );
+
+
+ /*********************************************************************/
+ /* */
+ /* Now check for bottom blue zones alignement */
+ /* */
+
+ {
+ FT_Int num_blues = hints->num_bottom_zones;
+ T1_Snap_Zone* blue = hints->blue_zones;
+ T1_Snap_Zone* blue_limit = blue + num_blues;
+
+
+ for ( ; blue < blue_limit; blue++ )
+ {
+ if ( bottom_pix < blue->min )
+ break;
+
+ if ( bottom_pix <= blue->max )
+ {
+ align = T1_ALIGN_BOTTOM;
+ bottom = ROUND( blue->pix );
+
+ /* implement blue shift */
+ if ( !hints->supress_overshoots )
+ {
+ FT_Pos delta = blue->pix - bottom_pix;
+
+
+ delta = delta < blueShift ? 0 : ROUND( delta );
+ bottom -= delta;
+ }
+ }
+ }
+ }
+
+ /*********************************************************************/
+ /* */
+ /* check for top blue zones alignement */
+ /* */
+
+ {
+ FT_Int num_blues = hints->num_blue_zones -
+ hints->num_bottom_zones;
+
+ T1_Snap_Zone* blue = hints->blue_zones +
+ hints->num_bottom_zones;
+
+ T1_Snap_Zone* blue_limit = blue + num_blues;
+
+
+ for ( ; blue < blue_limit; blue++ )
+ {
+ if ( top_pix < blue->min )
+ break;
+
+ if ( top_pix <= blue->max )
+ {
+ align |= T1_ALIGN_TOP;
+ top = ROUND( blue->pix );
+
+ /* implement blue shift */
+ if ( !hints->supress_overshoots )
+ {
+ FT_Pos delta = top - blue->pix;
+
+
+ delta = delta < blueShift ? 0 : ROUND( delta );
+ top += delta;
+ }
+ }
+ }
+ }
+
+ /*********************************************************************/
+ /* */
+ /* compute the hinted stem position, according to its alignment */
+ /* */
+
+ switch ( align )
+ {
+ case T1_ALIGN_BOTTOM: /* bottom zone alignment */
+ bottom_pix = bottom;
+ top_pix = bottom + width_pix;
+ break;
+
+ case T1_ALIGN_TOP: /* top zone alignment */
+ top_pix = top;
+ bottom_pix = top - width_pix;
+ break;
+
+ case T1_ALIGN_BOTH: /* bottom+top zone alignment */
+ bottom_pix = bottom;
+ top_pix = top;
+ break;
+
+ default: /* no alignment */
+ /* XXX TODO: Add management of controlled stems */
+ bottom = ( SCALE( bottom_orus + top_orus ) - width_pix ) / 2;
+
+ bottom_pix = ROUND( bottom );
+ top_pix = bottom_pix + width_pix;
+ }
+
+ stem->min_edge.pix = bottom_pix;
+ stem->max_edge.pix = top_pix;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1_hint_vertical_stems */
+ /* */
+ /* <Description> */
+ /* Computes the location of each scaled vertical stem hint. This */
+ /* takes care of the vertical stem snap table. */
+ /* */
+ /* <Input> */
+ /* table :: The vertical stem hints table. */
+ /* hints :: The current size's hint structure. */
+ /* scale :: The 16.16 scale used to convert outline units to */
+ /* 26.6 pixels. */
+ /* */
+ /* <Note> */
+ /* For now, all stems are hinted independently from each other. It */
+ /* might be necessary, for better performance, to introduce the */
+ /* notion of `controlled' hints describing things like counter-stems, */
+ /* stem3 as well as overlapping stems control. */
+ /* */
+ static
+ void t1_hint_vertical_stems( T1_Stem_Table* table,
+ T1_Size_Hints* hints,
+ FT_Fixed scale )
+ {
+ T1_Stem_Hint* stem = table->stems;
+ T1_Stem_Hint* limit = stem + table->num_stems;
+
+
+ for ( ; stem < limit; stem++ )
+ {
+ FT_Pos stem_left = stem->min_edge.orus;
+ FT_Pos stem_right = stem->max_edge.orus;
+ FT_Pos width_pix, left;
+
+
+ width_pix = SCALE( stem_right - stem_left );
+
+ /* Snap pixel width if in stem snap range */
+ {
+ T1_Snap_Zone* zone = hints->snap_heights;
+ T1_Snap_Zone* zone_limit = zone + hints->num_snap_heights;
+ FT_Pos best_dist = 32000;
+ T1_Snap_Zone* best_zone = 0;
+
+
+ for ( ; zone < zone_limit; zone++ )
+ {
+ FT_Pos dist;
+
+
+ dist = width_pix - zone->min;
+ if ( dist < 0 )
+ dist = -dist;
+ if ( dist < best_dist )
+ {
+ best_zone = zone;
+ best_dist = dist;
+ }
+ }
+
+ if ( best_zone )
+ {
+ if ( width_pix > best_zone->pix )
+ {
+ width_pix -= 0x20;
+ if ( width_pix < best_zone->pix )
+ width_pix = best_zone->pix;
+ }
+ else
+ {
+ width_pix += 0x20;
+ if ( width_pix > best_zone->pix )
+ width_pix = best_zone->pix;
+ }
+ }
+ }
+
+ /* round width - minimum 1 pixel if this isn't a ghost stem */
+ if ( width_pix > 0 )
+ width_pix = width_pix < ONE_PIXEL ? ONE_PIXEL
+ : ROUND( width_pix );
+
+ /* now place the snapped and rounded stem */
+
+ /* XXX TODO: implement controlled stems for the overlapping */
+ /* cases */
+
+ left = ( SCALE( stem_left + stem_right ) - width_pix ) / 2;
+
+ stem->min_edge.pix = ROUND( left );
+ stem->max_edge.pix = stem->min_edge.pix + width_pix;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1_hint_point */
+ /* */
+ /* <Description> */
+ /* Grid-fit a coordinate with regards to a given stem hints table. */
+ /* */
+ /* <Input> */
+ /* table :: The source stem hints table. */
+ /* coord :: The original coordinate, expressed in font units. */
+ /* scale :: The 16.16 scale used to convert font units into */
+ /* 26.6 pixels. */
+ /* */
+ /* <Return> */
+ /* The hinted/scaled value in 26.6 pixels. */
+ /* */
+ /* <Note> */
+ /* For now, all stems are hinted independently from each other. It */
+ /* might be necessary, for better performance, to introduce the */
+ /* notion of `controlled' hints describing things like counter-stems, */
+ /* stem3 as well as overlapping stems control. */
+ /* */
+ static
+ FT_Pos t1_hint_point( T1_Stem_Table* table,
+ FT_Pos coord,
+ FT_Fixed scale )
+ {
+ FT_Int num_active = table->num_active;
+ FT_Int n;
+ T1_Stem_Hint* prev = 0;
+ T1_Stem_Hint* cur = 0;
+ T1_Edge* min;
+ T1_Edge* max;
+ FT_Pos delta;
+
+
+ /* only hint when there is at least one stem defined */
+ if ( num_active <= 0 )
+ return SCALE( coord );
+
+ /* scan the stem table to determine placement of coordinate */
+ /* relative to the list of sorted and stems */
+ for ( n = 0; n < num_active; n++, prev = cur )
+ {
+ cur = table->stems + table->sort[n];
+
+ /* is it on the left of the current edge? */
+ delta = cur->min_edge.orus - coord;
+ if ( delta == 0 )
+ return cur->min_edge.pix;
+
+ if ( delta > 0 )
+ {
+ /* if this is the left of the first edge, simply shift */
+ if ( !prev )
+ return cur->min_edge.pix - SCALE( delta );
+
+ /* otherwise, interpolate between the maximum of the */
+ /* previous stem, and the minimum of the current one */
+ min = &prev->max_edge;
+ max = &cur->min_edge;
+
+ goto Interpolate;
+ }
+
+ /* is it within the current edge? */
+ delta = cur->max_edge.orus - coord;
+ if ( delta == 0 )
+ return cur->max_edge.pix;
+
+ if ( delta > 0 )
+ {
+ /* interpolate within the stem */
+ min = &cur->min_edge;
+ max = &cur->max_edge;
+
+ goto Interpolate;
+ }
+ }
+
+ /* apparently, this coordinate is on the right of the last stem */
+ delta = coord - cur->max_edge.orus;
+ return cur->max_edge.pix + SCALE( delta );
+
+ Interpolate:
+ return min->pix + FT_MulDiv( coord - min->orus,
+ max->pix - min->pix,
+ max->orus - min->orus );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Hint_Points */
+ /* */
+ /* <Description> */
+ /* This function grid-fits several points in a given Type 1 builder */
+ /* at once. */
+ /* */
+ /* <Input> */
+ /* builder :: A handle to target Type 1 builder. */
+ /* */
+ LOCAL_FUNC
+ void T1_Hint_Points( T1_Builder* builder )
+ {
+ FT_Int first = builder->hint_point;
+ FT_Int last = builder->current->n_points - 1;
+
+ T1_Size size = builder->size;
+ FT_Fixed scale_x = size->root.metrics.x_scale;
+ FT_Fixed scale_y = size->root.metrics.y_scale;
+
+ T1_Glyph_Hints* hints = builder->glyph->hints;
+ T1_Stem_Table* hori_stems = &hints->hori_stems;
+ T1_Stem_Table* vert_stems = &hints->vert_stems;
+
+ FT_Vector* cur = builder->current->points + first;
+ FT_Vector* limit = cur + last - first + 1;
+
+
+ /* first of all, sort the active stem hints */
+ t1_sort_hints( hori_stems );
+ t1_sort_hints( vert_stems );
+
+ for ( ; cur < limit; cur++ )
+ {
+ cur->x = t1_hint_point( vert_stems, cur->x, scale_x );
+ cur->y = t1_hint_point( hori_stems, cur->y, scale_y );
+ }
+
+ builder->hint_point = builder->current->n_points;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Hint_Stems */
+ /* */
+ /* <Description> */
+ /* This function is used to compute the location of each stem hint */
+ /* between the first and second passes of the glyph loader on the */
+ /* charstring. */
+ /* */
+ /* <Input> */
+ /* builder :: A handle to the target builder. */
+ /* */
+ LOCAL_FUNC
+ void T1_Hint_Stems( T1_Builder* builder )
+ {
+ T1_Glyph_Hints* hints = builder->glyph->hints;
+ T1_Private* priv = &builder->face->type1.private_dict;
+
+ T1_Size size = builder->size;
+ FT_Fixed scale_x = size->root.metrics.x_scale;
+ FT_Fixed scale_y = size->root.metrics.y_scale;
+
+
+ t1_hint_horizontal_stems( &hints->hori_stems,
+ builder->size->hints,
+ priv->blue_shift,
+ scale_y );
+
+ t1_hint_vertical_stems( &hints->vert_stems,
+ builder->size->hints,
+ scale_x );
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1hinter.h */
+/* */
+/* Type 1 hinter (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T1HINTER_H
+#define T1HINTER_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1objs.h"
+#include "t1gload.h"
+
+#else
+
+#include <type1/t1objs.h>
+#include <type1/t1gload.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_Snap_Zone */
+ /* */
+ /* <Description> */
+ /* A `snap zone' is used to model either a blue zone or a stem width */
+ /* at a given character size. It is made of a minimum and maximum */
+ /* edge, defined in 26.6 pixels, as well as an `original' and */
+ /* `scaled' position. */
+ /* */
+ /* The position corresponds to the stem width (for stem snap zones) */
+ /* or to the blue position (for blue zones). */
+ /* */
+ /* <Fields> */
+ /* orus :: The original position in font units. */
+ /* */
+ /* pix :: The current position in sub-pixel units. */
+ /* */
+ /* min :: The minimum boundary in sub-pixel units. */
+ /* */
+ /* max :: The maximum boundary in sub-pixel units. */
+ /* */
+ typedef struct T1_Snap_Zone_
+ {
+ FT_Pos orus;
+ FT_Pos pix;
+ FT_Pos min;
+ FT_Pos max;
+
+ } T1_Snap_Zone;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_Edge */
+ /* */
+ /* <Description> */
+ /* A very simple structure used to model a stem edge. */
+ /* */
+ /* <Fields> */
+ /* orus :: The original edge position in font units. */
+ /* */
+ /* pix :: The scaled edge position in sub-pixel units. */
+ /* */
+ typedef struct T1_Edge_
+ {
+ FT_Pos orus;
+ FT_Pos pix;
+
+ } T1_Edge;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_Stem_Hint */
+ /* */
+ /* <Description> */
+ /* A simple structure used to model a stem hint. */
+ /* */
+ /* <Fields> */
+ /* min_edge :: The hint's minimum edge. */
+ /* */
+ /* max_edge :: The hint's maximum edge. */
+ /* */
+ /* hint_flags :: Some flags describing the stem properties. */
+ /* */
+ /* <Note> */
+ /* The min and max edges of a ghost stem have the same position, even */
+ /* if they are coded in a weird way in the charstrings. */
+ /* */
+ typedef struct T1_Stem_Hint_
+ {
+ T1_Edge min_edge;
+ T1_Edge max_edge;
+ FT_Int hint_flags;
+
+ } T1_Stem_Hint;
+
+
+#define T1_HINT_FLAG_ACTIVE 1 /* indicates an active stem */
+#define T1_HINT_FLAG_MIN_BORDER 2 /* unused for now */
+#define T1_HINT_FLAG_MAX_BORDER 4 /* unused for now */
+
+ /* hinter's configuration constants */
+#define T1_HINTER_MAX_BLUES 24 /* maximum number of blue zones */
+#define T1_HINTER_MAX_SNAPS 16 /* maximum number of stem snap zones */
+#define T1_HINTER_MAX_EDGES 64 /* maximum number of stem hints */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_Size_Hints */
+ /* */
+ /* <Description> */
+ /* A structure used to model the hinting information related to a size */
+ /* object. */
+ /* */
+ /* <Fields> */
+ /* supress_overshoots :: A boolean flag to tell whether overshoot */
+ /* supression should occur. */
+ /* */
+ /* num_blue_zones :: The total number of blue zones (top+bottom). */
+ /* */
+ /* num_bottom_zones :: The number of bottom zones. */
+ /* */
+ /* blue_zones :: The blue zones table. Bottom zones are */
+ /* stored first in the table, followed by all */
+ /* top zones. */
+ /* */
+ /* num_snap_widths :: The number of horizontal stem snap zones. */
+ /* */
+ /* snap_widths :: An array of horizontal stem snap zones. */
+ /* */
+ /* num_snap_heights :: The number of vertical stem snap zones. */
+ /* */
+ /* snap_heights :: An array of vertical stem snap zones. */
+ /* */
+ struct T1_Size_Hints_
+ {
+ FT_Bool supress_overshoots;
+
+ FT_Int num_blue_zones;
+ FT_Int num_bottom_zones;
+ T1_Snap_Zone blue_zones[T1_HINTER_MAX_BLUES];
+
+ FT_Int num_snap_widths;
+ T1_Snap_Zone snap_widths[T1_HINTER_MAX_SNAPS];
+
+ FT_Int num_snap_heights;
+ T1_Snap_Zone snap_heights[T1_HINTER_MAX_SNAPS];
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_Stem_Table */
+ /* */
+ /* <Description> */
+ /* A simple structure used to model a set of stem hints in a single */
+ /* direction during the loading of a given glyph outline. Not all */
+ /* stem hints are active at a time. Moreover, stems must be sorted */
+ /* regularly. */
+ /* */
+ /* <Fields> */
+ /* num_stems :: The total number of stems in the table. */
+ /* */
+ /* num_active :: The number of active stems in the table. */
+ /* */
+ /* stems :: A table of all stems. */
+ /* */
+ /* sort :: A table of indices into the stems table, used to */
+ /* keep a sorted list of the active stems. */
+ /* */
+ typedef struct T1_Stem_Table_
+ {
+ FT_Int num_stems;
+ FT_Int num_active;
+
+ T1_Stem_Hint stems[T1_HINTER_MAX_EDGES];
+ FT_Int sort [T1_HINTER_MAX_EDGES];
+
+ } T1_Stem_Table;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_Glyph_Hints */
+ /* */
+ /* <Description> */
+ /* A structure used to model the stem hints of a given glyph outline */
+ /* during glyph loading. */
+ /* */
+ /* <Fields> */
+ /* hori_stems :: The horizontal stem hints table. */
+ /* vert_stems :: The vertical stem hints table. */
+ /* */
+ struct T1_Glyph_Hints_
+ {
+ T1_Stem_Table hori_stems;
+ T1_Stem_Table vert_stems;
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* <Data> */
+ /* t1_hinter_funcs */
+ /* */
+ /* <Description> */
+ /* A table containing the address of various functions used during */
+ /* the loading of an hinted scaled outline. */
+ /* */
+ extern const T1_Hinter_Funcs t1_hinter_funcs;
+
+
+ LOCAL_DEF
+ FT_Error T1_New_Size_Hinter( T1_Size size );
+
+ LOCAL_DEF
+ void T1_Done_Size_Hinter( T1_Size size );
+
+ LOCAL_DEF
+ FT_Error T1_Reset_Size_Hinter( T1_Size size );
+
+ LOCAL_DEF
+ FT_Error T1_New_Glyph_Hinter( T1_GlyphSlot glyph );
+
+ LOCAL_DEF
+ void T1_Done_Glyph_Hinter( T1_GlyphSlot glyph );
+
+
+ LOCAL_DEF
+ void T1_Hint_Points( T1_Builder* builder );
+
+ LOCAL_DEF
+ void T1_Hint_Stems( T1_Builder* builder );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* T1HINTER_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1load.c */
+/* */
+/* Type 1 font loader (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/t1types.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1tokens.h"
+#include "t1parse.h"
+
+#else
+
+#include <type1/t1tokens.h>
+#include <type1/t1parse.h>
+
+#endif
+
+
+#include <stdio.h>
+
+#include <string.h> /* for strncpy(), strncmp(), strlen() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1load
+
+
+ typedef FT_Error (*T1_Parse_Func)( T1_Parser* parser );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Init_T1_Parser */
+ /* */
+ /* <Description> */
+ /* Initializes a given parser object to build a given T1_Face. */
+ /* */
+ /* <InOut> */
+ /* parser :: A handle to the newly built parser object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target Type 1 face object. */
+ /* */
+ /* tokenizer :: A handle to the target Type 1 token manager. */
+ /* */
+ LOCAL_FUNC
+ void Init_T1_Parser( T1_Parser* parser,
+ T1_Face face,
+ T1_Tokenizer tokenizer )
+ {
+ parser->error = 0;
+ parser->face = face;
+ parser->tokenizer = tokenizer;
+ parser->top = parser->stack;
+ parser->limit = parser->stack + T1_MAX_STACK_DEPTH;
+
+ parser->state_index = 0;
+ parser->state_stack[0] = dict_none;
+
+ parser->encoding_type = t1_encoding_none;
+ parser->encoding_names = 0;
+ parser->encoding_offsets = 0;
+ parser->encoding_lengths = 0;
+
+ parser->dump_tokens = 0;
+ face->type1.private_dict.lenIV = 4; /* XXX : is it sure? */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Next_T1_Token */
+ /* */
+ /* <Description> */
+ /* Grabs the next significant token from a parser's input stream. */
+ /* This function ignores a number of tokens, and translates */
+ /* alternate forms into their common ones. */
+ /* */
+ /* <Input> */
+ /* parser :: A handle to the source parser. */
+ /* */
+ /* <Output> */
+ /* token :: The extracted token descriptor. */
+ /* */
+ /* <Return> */
+ /* FreeTyoe error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error Next_T1_Token( T1_Parser* parser,
+ T1_Token* token )
+ {
+ FT_Error error;
+ T1_Tokenizer tokzer = parser->tokenizer;
+
+
+ L1:
+ error = Read_Token( tokzer );
+ if ( error )
+ return error;
+
+ /* we now must ignore a number of tokens like `dup', `executeonly', */
+ /* `readonly', etc. */
+ *token = tokzer->token;
+ if ( token->kind == tok_keyword )
+ switch( token->kind2 )
+ {
+ case key_dup:
+ case key_execonly:
+ case key_readonly:
+ case key_noaccess:
+ case key_userdict:
+ /* do nothing - loop */
+ goto L1;
+
+ /* we also translate some other keywords from their alternative */
+ /* to their `normal' form */
+
+ case key_NP_alternate:
+ token->kind2 = key_NP;
+ break;
+
+ case key_RD_alternate:
+ token->kind2 = key_RD;
+ break;
+
+ case key_ND_alternate:
+ token->kind2 = key_ND;
+ break;
+
+ default:
+ ;
+ }
+
+#if defined( FT_DEBUG_LEVEL_ERROR ) || defined( FT_DEBUG_LEVEL_TRACE )
+
+ /* Dump the token when requested. This feature is only available */
+ /* in the `error' and `trace' debug levels. */
+ if ( parser->dump_tokens )
+ {
+ FT_String temp_string[128];
+ FT_Int len;
+
+
+ len = token->len;
+ if ( len > 127 )
+ len = 127;
+ strncpy( temp_string,
+ (FT_String*)tokzer->base + token->start,
+ len );
+ temp_string[len] = '\0';
+ FT_ERROR(( "%s\n", temp_string ));
+ }
+
+#endif /* FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE */
+
+ return T1_Err_Ok;
+ }
+
+
+ static
+ FT_Error Expect_Keyword( T1_Parser* parser,
+ T1_TokenType keyword )
+ {
+ T1_Token token;
+ FT_Error error;
+
+
+ error = Next_T1_Token( parser, &token );
+ if ( error )
+ goto Exit;
+
+ if ( token.kind != tok_keyword ||
+ token.kind2 != keyword )
+ {
+ error = T1_Err_Syntax_Error;
+ FT_ERROR(( "Expect_Keyword: keyword `%s' expected.\n",
+ t1_keywords[keyword - key_first_] ));
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ FT_Error Expect_Keyword2( T1_Parser* parser,
+ T1_TokenType keyword1,
+ T1_TokenType keyword2 )
+ {
+ T1_Token token;
+ FT_Error error;
+
+
+ error = Next_T1_Token( parser, &token );
+ if ( error )
+ goto Exit;
+
+ if ( token.kind != tok_keyword ||
+ ( token.kind2 != keyword1 &&
+ token.kind2 != keyword2 ) )
+ {
+ error = T1_Err_Syntax_Error;
+ FT_ERROR(( "Expect_Keyword2: keyword `%s' or `%s' expected.\n",
+ t1_keywords[keyword1 - key_first_],
+ t1_keywords[keyword2 - key_first_] ));
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ void Parse_Encoding( T1_Parser* parser )
+ {
+ T1_Token* token = parser->top+1;
+ FT_Memory memory = parser->face->root.memory;
+ T1_Encoding* encode = &parser->face->type1.encoding;
+ FT_Error error = 0;
+
+
+ if ( token->kind == tok_keyword &&
+ ( token->kind2 == key_StandardEncoding ||
+ token->kind2 == key_ExpertEncoding ) )
+ {
+ encode->num_chars = 256;
+ encode->code_first = 32;
+ encode->code_last = 255;
+
+ if ( ALLOC_ARRAY( encode->char_index, 256, FT_Short ) )
+ goto Exit;
+
+ encode->char_name = 0; /* no need to store glyph names */
+
+ /* Now copy the encoding */
+ switch ( token->kind2 )
+ {
+ case key_ExpertEncoding:
+ parser->encoding_type = t1_encoding_expert;
+ break;
+
+ default:
+ parser->encoding_type = t1_encoding_standard;
+ break;
+ }
+ }
+ else
+ {
+ FT_ERROR(( "Parse_Encoding: invalid encoding type\n" ));
+ error = T1_Err_Syntax_Error;
+ }
+
+ Exit:
+ parser->error = error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* */
+ /* IMPLEMENTATION OF THE `DEF' KEYWORD DEPENDING ON */
+ /* CURRENT DICTIONARY STATE */
+ /* */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Do_Def_Font */
+ /* */
+ /* <Description> */
+ /* This function performs a `def' if in the Font dictionary. Its */
+ /* purpose is to build the T1_Face attributes directly from the */
+ /* stream. */
+ /* */
+ /* <InOut> */
+ /* parser :: A handle to the current parser. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Do_Def_Font( T1_Parser* parser )
+ {
+ T1_Token* top = parser->top;
+ T1_Face face = parser->face;
+ T1_Font* type1 = &face->type1;
+
+
+ switch ( top[0].kind2 )
+ {
+ case imm_FontName:
+ /* in some cases, the /FontName is an immediate like */
+ /* /TimesNewRoman. In this case, we simply copy the */
+ /* token string (without the /). */
+ if ( top[1].kind == tok_immediate )
+ {
+ FT_Memory memory = parser->tokenizer->memory;
+ FT_Error error;
+ FT_Int len = top[1].len;
+
+
+ if ( ALLOC( type1->font_name, len + 1 ) )
+ {
+ parser->error = error;
+ return error;
+ }
+
+ MEM_Copy( type1->font_name,
+ parser->tokenizer->base + top[1].start,
+ len );
+ type1->font_name[len] = '\0';
+ }
+ else
+ type1->font_name = CopyString( parser );
+ break;
+
+ case imm_Encoding:
+ Parse_Encoding( parser );
+ break;
+
+ case imm_PaintType:
+ type1->paint_type = (FT_Byte)CopyInteger( parser );
+ break;
+
+ case imm_FontType:
+ type1->font_type = (FT_Byte)CopyInteger( parser );
+ break;
+
+ case imm_FontMatrix:
+ CopyMatrix( parser, &type1->font_matrix );
+ break;
+
+ case imm_FontBBox:
+ CopyBBox( parser, &type1->font_bbox );
+ break;
+
+ case imm_UniqueID:
+ type1->private_dict.unique_id = CopyInteger( parser );
+ break;
+
+ case imm_StrokeWidth:
+ type1->stroke_width = CopyInteger( parser );
+ break;
+
+ case imm_FontID:
+ type1->font_id = CopyInteger( parser );
+ break;
+
+ default:
+ /* ignore all other things */
+ parser->error = T1_Err_Ok;
+ }
+
+ return parser->error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Do_Def_FontInfo */
+ /* */
+ /* <Description> */
+ /* This function performs a `def' if in the FontInfo dictionary. Its */
+ /* purpose is to build the T1_FontInfo structure directly from the */
+ /* stream. */
+ /* */
+ /* <InOut> */
+ /* parser :: A handle to the current parser. */
+ /* */
+ /* <Return> */
+ /* FreeTyoe error code. 0 means success. */
+ /* */
+ static
+ FT_Error Do_Def_FontInfo( T1_Parser* parser )
+ {
+ T1_Token* top = parser->top;
+ T1_FontInfo* info = &parser->face->type1.font_info;
+
+
+ switch ( top[0].kind2 )
+ {
+ case imm_version:
+ info->version = CopyString( parser );
+ break;
+
+ case imm_Notice:
+ info->notice = CopyString( parser );
+ break;
+
+ case imm_FullName:
+ info->full_name = CopyString( parser );
+ break;
+
+ case imm_FamilyName:
+ info->family_name = CopyString( parser );
+ break;
+
+ case imm_Weight:
+ info->weight = CopyString( parser );
+ break;
+
+ case imm_ItalicAngle:
+ info->italic_angle = CopyInteger( parser );
+ break;
+
+ case imm_isFixedPitch:
+ info->is_fixed_pitch = CopyBoolean( parser );
+ break;
+
+ case imm_UnderlinePosition:
+ info->underline_position = (FT_Short)CopyInteger( parser );
+ break;
+
+ case imm_UnderlineThickness:
+ info->underline_thickness = (FT_Short)CopyInteger( parser );
+ break;
+
+ default:
+ /* ignore all other things */
+ parser->error = T1_Err_Ok;
+ }
+
+ return parser->error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Do_Def_Private */
+ /* */
+ /* <Description> */
+ /* This function performs a `def' if in the Private dictionary. Its */
+ /* purpose is to build the T1_Private structure directly from the */
+ /* stream. */
+ /* */
+ /* <InOut> */
+ /* parser :: A handle to the current parser. */
+ /* */
+ /* <Return> */
+ /* FreeTyoe error code. 0 means success. */
+ /* */
+ static
+ FT_Error Do_Def_Private( T1_Parser* parser )
+ {
+ T1_Token* top = parser->top;
+ T1_Private* priv = &parser->face->type1.private_dict;
+
+
+ switch ( top[0].kind2 )
+ {
+ /* Ignore the definitions of RD, NP, ND, and their alternate forms */
+ case imm_RD:
+ case imm_RD_alternate:
+ case imm_ND:
+ case imm_ND_alternate:
+ case imm_NP:
+ case imm_NP_alternate:
+ parser->error = T1_Err_Ok;
+ break;
+
+ case imm_BlueValues:
+ CopyArray( parser, &priv->num_blue_values,
+ priv->blue_values, 14 );
+ break;
+
+ case imm_OtherBlues:
+ CopyArray( parser, &priv->num_other_blues,
+ priv->other_blues, 10 );
+ break;
+
+ case imm_FamilyBlues:
+ CopyArray( parser, &priv->num_family_blues,
+ priv->family_blues, 14 );
+ break;
+
+ case imm_FamilyOtherBlues:
+ CopyArray( parser, &priv->num_family_other_blues,
+ priv->family_other_blues, 10 );
+ break;
+
+ case imm_BlueScale:
+ priv->blue_scale = CopyFloat( parser, 0x10000L );
+ break;
+
+ case imm_BlueShift:
+ priv->blue_shift = CopyInteger( parser );
+ break;
+
+ case imm_BlueFuzz:
+ priv->blue_fuzz = CopyInteger( parser );
+ break;
+
+ case imm_StdHW:
+ CopyArray( parser, 0, (FT_Short*)&priv->standard_width, 1 );
+ break;
+
+ case imm_StdVW:
+ CopyArray( parser, 0, (FT_Short*)&priv->standard_height, 1 );
+ break;
+
+ case imm_StemSnapH:
+ CopyArray( parser, &priv->num_snap_widths,
+ priv->snap_widths, 12 );
+ break;
+
+ case imm_StemSnapV:
+ CopyArray( parser, &priv->num_snap_heights,
+ priv->snap_heights, 12 );
+ break;
+
+ case imm_ForceBold:
+ priv->force_bold = CopyBoolean( parser );
+ break;
+
+ case imm_LanguageGroup:
+ priv->language_group = CopyInteger( parser );
+ break;
+
+ case imm_password:
+ priv->password = CopyInteger( parser );
+ break;
+
+ case imm_UniqueID:
+ priv->unique_id = CopyInteger( parser );
+ break;
+
+ case imm_lenIV:
+ priv->lenIV = CopyInteger( parser );
+ break;
+
+ case imm_MinFeature:
+ CopyArray( parser, 0, priv->min_feature, 2 );
+ break;
+
+ default:
+ /* ignore all other things */
+ parser->error = T1_Err_Ok;
+ }
+
+ return parser->error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Do_Def_Error */
+ /* */
+ /* <Description> */
+ /* This function returns a simple syntax error when invoked. It is */
+ /* used for the `def' keyword if in the `encoding', `subrs', */
+ /* `othersubrs', and `charstrings' dictionary states. */
+ /* */
+ /* <InOut> */
+ /* parser :: A handle to the current parser. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Do_Def_Error( T1_Parser* parser )
+ {
+ FT_ERROR(( "Do_Def_Error:" ));
+ FT_ERROR(( " `def' keyword encountered in bad dictionary/array\n" ));
+
+ parser->error = T1_Err_Syntax_Error;
+
+ return parser->error;
+ }
+
+
+ static
+ FT_Error Do_Def_Ignore( T1_Parser* parser )
+ {
+ FT_UNUSED( parser );
+ return T1_Err_Ok;
+ }
+
+
+ static
+ T1_Parse_Func def_funcs[dict_max] =
+ {
+ Do_Def_Error,
+ Do_Def_Font,
+ Do_Def_FontInfo,
+ Do_Def_Ignore,
+ Do_Def_Private,
+ Do_Def_Ignore,
+ Do_Def_Ignore,
+ Do_Def_Ignore,
+ Do_Def_Ignore,
+ Do_Def_Ignore,
+ Do_Def_Ignore,
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* */
+ /* IMPLEMENTATION OF THE `PUT' KEYWORD DEPENDING ON */
+ /* CURRENT DICTIONARY STATE */
+ /* */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Do_Put_Encoding */
+ /* */
+ /* <Description> */
+ /* This function performs a `put' if in the Encoding array. The */
+ /* glyph name is copied into the T1 recorder, and the charcode and */
+ /* glyph name pointer are written into the face object encoding. */
+ /* */
+ /* <InOut> */
+ /* parser :: A handle to the current parser. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Do_Put_Encoding( T1_Parser* parser )
+ {
+ FT_Error error = T1_Err_Ok;
+ T1_Face face = parser->face;
+ T1_Token* top = parser->top;
+ T1_Encoding* encode = &face->type1.encoding;
+ FT_Int index;
+
+
+ /* record and check the character code */
+ if ( top[0].kind != tok_number )
+ {
+ FT_TRACE4(( "Do_Put_Encoding: number expected\n" ));
+ goto Syntax_Error;
+ }
+ index = (FT_Int)CopyInteger( parser );
+ if ( parser->error )
+ return parser->error;
+
+ if ( index < 0 || index >= encode->num_chars )
+ {
+ FT_TRACE4(( "Do_Put_Encoding: invalid character code\n" ));
+ goto Syntax_Error;
+ }
+
+ /* record the immediate name */
+ if ( top[1].kind != tok_immediate )
+ {
+ FT_TRACE4(( "Do_Put_Encoding: immediate name expected\n" ));
+ goto Syntax_Error;
+ }
+
+ /* if the glyph name is `.notdef', store a NULL char name; */
+ /* otherwise, record the glyph name */
+ if ( top[1].kind == imm_notdef )
+ {
+ parser->table.elements[index] = 0;
+ parser->table.lengths [index] = 0;
+ }
+ else
+ {
+ FT_String temp_name[128];
+ T1_Token* token = top + 1;
+ FT_Int len = token->len - 1;
+
+
+ /* copy immediate name */
+ if ( len > 127 )
+ len = 127;
+ MEM_Copy( temp_name, parser->tokenizer->base + token->start + 1, len );
+ temp_name[len] = '\0';
+
+ error = T1_Add_Table( &parser->table, index,
+ (FT_Byte*)temp_name, len + 1 );
+
+ /* adjust code_first and code_last */
+ if ( index < encode->code_first ) encode->code_first = index;
+ if ( index > encode->code_last ) encode->code_last = index;
+ }
+ return error;
+
+ Syntax_Error:
+ /* ignore the error, and simply clear the stack */
+ FT_TRACE4(( "Do_Put_Encoding: invalid syntax encountered\n" ));
+ parser->top = parser->stack;
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* */
+ /* IMPLEMENTATION OF THE "RD" KEYWORD DEPENDING ON */
+ /* CURRENT DICTIONARY STATE */
+ /* */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Do_RD_Subrs */
+ /* */
+ /* <Description> */
+ /* This function performs an `RD' if in the Subrs dictionary. It */
+ /* simply records the array of bytecodes/charstrings corresponding to */
+ /* the sub-routine. */
+ /* */
+ /* <InOut> */
+ /* parser :: A handle to the current parser. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Do_RD_Subrs( T1_Parser* parser )
+ {
+ FT_Error error = T1_Err_Ok;
+ T1_Face face = parser->face;
+ T1_Token* top = parser->top;
+ T1_Tokenizer tokzer = parser->tokenizer;
+ FT_Int index, count;
+
+
+ /* record and check the character code */
+ if ( top[0].kind != tok_number ||
+ top[1].kind != tok_number )
+ {
+ FT_ERROR(( "Do_RD_Subrs: number expected\n" ));
+ goto Syntax_Error;
+ }
+ index = (FT_Int)CopyInteger( parser );
+ error = parser->error;
+ if ( error )
+ goto Exit;
+
+ count = (FT_Int)CopyInteger( parser );
+ error = parser->error;
+ if ( error )
+ goto Exit;
+
+ if ( index < 0 || index >= face->type1.num_subrs )
+ {
+ FT_ERROR(( "Do_RD_Subrs: invalid character code\n" ));
+ goto Syntax_Error;
+ }
+
+ /* decrypt charstring and skip it */
+ {
+ FT_Byte* base = tokzer->base + tokzer->cursor;
+
+
+ tokzer->cursor += count;
+
+ /* some fonts use a value of -1 for lenIV to indicate that */
+ /* the charstrings are unencoded. */
+ /* */
+ /* Thanks to Tom Kacvinsky for pointing this out. */
+ /* */
+ if ( face->type1.private_dict.lenIV >= 0 )
+ {
+ t1_decrypt( base, count, 4330 );
+
+ base += face->type1.private_dict.lenIV;
+ count -= face->type1.private_dict.lenIV;
+ }
+
+ error = T1_Add_Table( &parser->table, index, base, count );
+ }
+
+ /* consume the closing NP or `put' */
+ error = Expect_Keyword2( parser, key_NP, key_put );
+
+ Exit:
+ return error;
+
+ Syntax_Error:
+ return T1_Err_Syntax_Error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Do_RD_CharStrings */
+ /* */
+ /* <Description> */
+ /* This function performs an `RD' if in the CharStrings dictionary. */
+ /* It simply records the array of bytecodes/charstrings corresponding */
+ /* to the glyph program string. */
+ /* */
+ /* <InOut> */
+ /* parser :: A handle to the current parser. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error Do_RD_Charstrings( T1_Parser* parser )
+ {
+ FT_Error error = T1_Err_Ok;
+ T1_Face face = parser->face;
+ T1_Token* top = parser->top;
+ T1_Tokenizer tokzer = parser->tokenizer;
+ FT_Int index, count;
+
+
+ /* check the character name argument */
+ if ( top[0].kind != tok_immediate )
+ {
+ FT_ERROR(( "Do_RD_Charstrings: immediate character name expected\n" ));
+ goto Syntax_Error;
+ }
+
+ /* check the count argument */
+ if ( top[1].kind != tok_number )
+ {
+ FT_ERROR(( "Do_RD_Charstrings: number expected\n" ));
+ goto Syntax_Error;
+ }
+
+ parser->args++;
+ count = (FT_Int)CopyInteger( parser );
+ error = parser->error;
+ if ( error )
+ goto Exit;
+
+ /* record the glyph name and get the corresponding glyph index */
+ if ( top[0].kind2 == imm_notdef )
+ index = 0;
+ else
+ {
+ FT_String temp_name[128];
+ T1_Token* token = top;
+ FT_Int len = token->len - 1;
+
+
+ /* copy immediate name */
+ if ( len > 127 )
+ len = 127;
+ MEM_Copy( temp_name, parser->tokenizer->base + token->start + 1, len );
+ temp_name[len] = '\0';
+
+ index = parser->cur_name++;
+ error = T1_Add_Table( &parser->table, index * 2,
+ (FT_Byte*)temp_name, len + 1 );
+ if ( error )
+ goto Exit;
+ }
+
+ /* decrypt and record charstring, then skip them */
+ {
+ FT_Byte* base = tokzer->base + tokzer->cursor;
+
+
+ tokzer->cursor += count; /* skip */
+
+ if ( face->type1.private_dict.lenIV >= 0 )
+ {
+ t1_decrypt( base, count, 4330 );
+
+ base += face->type1.private_dict.lenIV;
+ count -= face->type1.private_dict.lenIV;
+ }
+
+ error = T1_Add_Table( &parser->table, index * 2 + 1, base, count );
+ }
+
+ /* consume the closing `ND' */
+ if ( !error )
+ error = Expect_Keyword( parser, key_ND );
+
+ Exit:
+ return error;
+
+ Syntax_Error:
+ return T1_Err_Syntax_Error;
+ }
+
+
+ static
+ FT_Error Expect_Dict_Arguments( T1_Parser* parser,
+ FT_Int num_args,
+ T1_TokenType immediate,
+ T1_DictState new_state,
+ FT_Int* count )
+ {
+ /* check that we have enough arguments in the stack, including */
+ /* the `dict' keyword */
+ if ( parser->top - parser->stack < num_args )
+ {
+ FT_ERROR(( "Expect_Dict_Arguments: expecting at least %d arguments",
+ num_args ));
+ goto Syntax_Error;
+ }
+
+ /* check that we have the correct immediate, if needed */
+ if ( num_args == 2 )
+ {
+ if ( parser->top[-2].kind != tok_immediate ||
+ parser->top[-2].kind2 != immediate )
+ {
+ FT_ERROR(( "Expect_Dict_Arguments: expecting `/%s' dictionary\n",
+ t1_immediates[immediate - imm_first_] ));
+ goto Syntax_Error;
+ }
+ }
+
+ parser->args = parser->top-1;
+
+ /* check that the count argument is a number */
+ if ( parser->args->kind != tok_number )
+ {
+ FT_ERROR(( "Expect_Dict_Arguments:" ));
+ FT_ERROR(( " expecting numerical count argument for `dict'\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( count )
+ {
+ *count = CopyInteger( parser );
+ if ( parser->error )
+ return parser->error;
+ }
+
+ /* save the dictionary state */
+ parser->state_stack[++parser->state_index] = new_state;
+
+ /* consume the `begin' keyword and clear the stack */
+ parser->top -= num_args;
+ return Expect_Keyword( parser, key_begin );
+
+ Syntax_Error:
+ return T1_Err_Syntax_Error;
+ }
+
+
+ static
+ FT_Error Expect_Array_Arguments( T1_Parser* parser )
+ {
+ T1_Token* top = parser->top;
+ FT_Error error = T1_Err_Ok;
+ T1_DictState new_state;
+ FT_Int count;
+ T1_Face face = parser->face;
+ FT_Memory memory = face->root.memory;
+
+
+ /* Check arguments format */
+ if ( top - parser->stack < 2 )
+ {
+ FT_ERROR(( "Expect_Array_Arguments: two arguments expected\n" ));
+ error = T1_Err_Stack_Underflow;
+ goto Exit;
+ }
+
+ parser->top -= 2;
+ top -= 2;
+ parser->args = top + 1;
+
+ if ( top[0].kind != tok_immediate )
+ {
+ FT_ERROR(( "Expect_Array_Arguments:" ));
+ FT_ERROR(( " first argument must be an immediate name\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( top[1].kind != tok_number )
+ {
+ FT_ERROR(( "Expect_Array_Arguments:" ));
+ FT_ERROR(( " second argument must be a number\n" ));
+ goto Syntax_Error;
+ }
+
+ count = (FT_Int)CopyInteger( parser );
+
+ /* Is this an array we know about? */
+ switch ( top[0].kind2 )
+ {
+ case imm_Encoding:
+ {
+ T1_Encoding* encode = &face->type1.encoding;
+
+
+ new_state = dict_encoding;
+
+ encode->code_first = count;
+ encode->code_last = 0;
+ encode->num_chars = count;
+
+ /* Allocate the table of character indices. The table of */
+ /* character names is allocated through init_t1_recorder(). */
+ if ( ALLOC_ARRAY( encode->char_index, count, FT_Short ) )
+ return error;
+
+ error = T1_New_Table( &parser->table, count, memory );
+ if ( error )
+ goto Exit;
+
+ parser->encoding_type = t1_encoding_array;
+ }
+ break;
+
+ case imm_Subrs:
+ new_state = dict_subrs;
+ face->type1.num_subrs = count;
+
+ error = T1_New_Table( &parser->table, count, memory );
+ if ( error )
+ goto Exit;
+ break;
+
+ case imm_CharStrings:
+ new_state = dict_charstrings;
+ break;
+
+ default:
+ new_state = dict_unknown_array;
+ }
+
+ parser->state_stack[++parser->state_index] = new_state;
+
+ Exit:
+ return error;
+
+ Syntax_Error:
+ return T1_Err_Syntax_Error;
+ }
+
+
+ static
+ FT_Error Finalize_Parsing( T1_Parser* parser )
+ {
+ T1_Face face = parser->face;
+ T1_Font* type1 = &face->type1;
+ FT_Memory memory = face->root.memory;
+ T1_Table* strings = &parser->table;
+ PSNames_Interface* psnames = (PSNames_Interface*)face->psnames;
+
+ FT_Int num_glyphs;
+ FT_Int n;
+ FT_Error error;
+
+
+ num_glyphs = type1->num_glyphs = parser->cur_name;
+
+ /* allocate glyph names and charstrings arrays */
+ if ( ALLOC_ARRAY( type1->glyph_names, num_glyphs, FT_String* ) ||
+ ALLOC_ARRAY( type1->charstrings, num_glyphs, FT_Byte* ) ||
+ ALLOC_ARRAY( type1->charstrings_len, num_glyphs, FT_Int* ) )
+ return error;
+
+ /* copy glyph names and charstrings offsets and lengths */
+ type1->charstrings_block = strings->block;
+ for ( n = 0; n < num_glyphs; n++ )
+ {
+ type1->glyph_names[n] = (FT_String*)strings->elements[2 * n];
+ type1->charstrings[n] = strings->elements[2 * n + 1];
+ type1->charstrings_len[n] = strings->lengths [2 * n + 1];
+ }
+
+ /* now free the old tables */
+ FREE( strings->elements );
+ FREE( strings->lengths );
+
+ if ( !psnames )
+ {
+ FT_ERROR(( "Finalize_Parsing: `PSNames' module missing!\n" ));
+ return T1_Err_Unimplemented_Feature;
+ }
+
+ /* compute encoding if required */
+ if ( parser->encoding_type == t1_encoding_none )
+ {
+ FT_ERROR(( "Finalize_Parsing: no encoding specified in font file\n" ));
+ return T1_Err_Syntax_Error;
+ }
+
+ {
+ FT_Int n;
+ T1_Encoding* encode = &type1->encoding;
+
+
+ encode->code_first = encode->num_chars - 1;
+ encode->code_last = 0;
+
+ for ( n = 0; n < encode->num_chars; n++ )
+ {
+ FT_String** names;
+ FT_Int index;
+ FT_Int m;
+
+
+ switch ( parser->encoding_type )
+ {
+ case t1_encoding_standard:
+ index = psnames->adobe_std_encoding[n];
+ names = 0;
+ break;
+
+ case t1_encoding_expert:
+ index = psnames->adobe_expert_encoding[n];
+ names = 0;
+ break;
+
+ default:
+ index = n;
+ names = (FT_String**)parser->encoding_offsets;
+ }
+
+ encode->char_index[n] = 0;
+
+ if ( index )
+ {
+ FT_String* name;
+
+
+ if ( names )
+ name = names[index];
+ else
+ name = (FT_String*)psnames->adobe_std_strings(index);
+
+ if ( name )
+ {
+ FT_Int len = strlen( name );
+
+
+ /* lookup glyph index from name */
+ for ( m = 0; m < num_glyphs; m++ )
+ {
+ if ( strncmp( type1->glyph_names[m], name, len ) == 0 )
+ {
+ encode->char_index[n] = m;
+ break;
+ }
+ }
+
+ if ( n < encode->code_first ) encode->code_first = n;
+ if ( n > encode->code_last ) encode->code_last = n;
+ }
+ }
+ }
+
+ parser->encoding_type = t1_encoding_none;
+
+ FREE( parser->encoding_names );
+ FREE( parser->encoding_lengths );
+ FREE( parser->encoding_offsets );
+ }
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Parse_T1_FontProgram */
+ /* */
+ /* <Description> */
+ /* Parses a given Type 1 font file and builds its face object. */
+ /* */
+ /* <InOut> */
+ /* parser :: A handle to the target parser object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The parser contains a handle to the target face object. */
+ /* */
+ LOCAL_FUNC
+ FT_Error Parse_T1_FontProgram( T1_Parser* parser )
+ {
+ FT_Error error;
+ T1_Font* type1 = &parser->face->type1;
+
+
+ for (;;)
+ {
+ T1_Token token;
+ T1_Token* top;
+ T1_DictState dict_state;
+ FT_Int dict_index;
+
+
+ error = Next_T1_Token( parser, &token );
+ top = parser->top;
+ dict_index = parser->state_index;
+ dict_state = parser->state_stack[dict_index];
+
+ switch ( token.kind )
+ {
+ /* a keyword has been detected */
+ case tok_keyword:
+ switch ( token.kind2 )
+ {
+ case key_dict:
+ switch ( dict_state )
+ {
+ case dict_none:
+ /* All right, we are beginning the font dictionary. */
+ /* Check that we only have one number argument, then */
+ /* consume the `begin' and change to `dict_font' */
+ /* state. */
+ error = Expect_Dict_Arguments( parser, 1, tok_error,
+ dict_font, 0 );
+ if ( error )
+ goto Exit;
+
+ /* clear stack from all the previous content. This */
+ /* could be some stupid Postscript code. */
+ parser->top = parser->stack;
+ break;
+
+ case dict_font:
+ /* This must be the /FontInfo dictionary, so check */
+ /* that we have at least two arguments, that they */
+ /* are `/FontInfo' and a number, then change the */
+ /* dictionary state. */
+ error = Expect_Dict_Arguments( parser, 2, imm_FontInfo,
+ dict_fontinfo, 0 );
+ if ( error )
+ goto Exit;
+ break;
+
+ case dict_none2:
+ error = Expect_Dict_Arguments( parser, 2, imm_Private,
+ dict_private, 0 );
+ if ( error )
+ goto Exit;
+ break;
+
+ case dict_private:
+ {
+ T1_Face face = parser->face;
+ FT_Int count;
+
+
+ error = Expect_Dict_Arguments( parser, 2, imm_CharStrings,
+ dict_charstrings, &count );
+ if ( error )
+ goto Exit;
+
+ type1->num_glyphs = count;
+ error = T1_New_Table( &parser->table, count * 2,
+ face->root.memory );
+ if ( error )
+ goto Exit;
+
+ /* record `.notdef' as the first glyph in the font */
+ error = T1_Add_Table( &parser->table, 0,
+ (FT_Byte*)".notdef", 8 );
+ parser->cur_name = 1;
+ /* XXX: DO SOMETHING HERE */
+ }
+ break;
+
+ default:
+ /* All other uses are invalid */
+ FT_ERROR(( "Parse_T1_FontProgram:" ));
+ FT_ERROR(( " invalid use of `dict' keyword\n" ));
+ goto Syntax_Error;
+ }
+ break;
+
+ case key_array:
+ /* Are we in an array yet? If so, raise an error */
+ switch ( dict_state )
+ {
+ case dict_encoding:
+ case dict_subrs:
+ case dict_othersubrs:
+ case dict_charstrings:
+ case dict_unknown_array:
+ FT_ERROR(( "Parse_T1_FontProgram: nested array definitions\n" ));
+ goto Syntax_Error;
+
+ default:
+ ;
+ }
+ error = Expect_Array_Arguments( parser );
+ if ( error )
+ goto Exit;
+ break;
+
+ case key_ND:
+ case key_NP:
+ case key_def:
+ /* Are we in an array? If so, finalize it. */
+ switch ( dict_state )
+ {
+ case dict_encoding: /* finish encoding array */
+ /* copy table names to the face object */
+ T1_Done_Table( &parser->table );
+
+ parser->encoding_names = parser->table.block;
+ parser->encoding_lengths = parser->table.lengths;
+ parser->encoding_offsets = parser->table.elements;
+
+ parser->state_index--;
+ break;
+
+ case dict_subrs:
+ /* copy recorder sub-routines */
+ T1_Done_Table( &parser->table );
+
+ parser->subrs = parser->table.block;
+ type1->subrs = parser->table.elements;
+ type1->subrs_len = parser->table.lengths;
+ type1->subrs_block = parser->table.block;
+
+ parser->state_index--;
+ break;
+
+ case dict_charstrings:
+ case dict_othersubrs:
+ case dict_unknown_array:
+ FT_ERROR(( "Parse_T1_FontProgram: unsupported array\n" ));
+ goto Syntax_Error;
+ break;
+
+ default: /* normal `def' processing */
+ /* Check that we have sufficient operands in the stack */
+ if ( top >= parser->stack + 2 )
+ {
+ /* Now check that the first operand is an immediate. */
+ /* If so, call the appropriate `def' routine based */
+ /* on the current parser state. */
+ if ( top[-2].kind == tok_immediate )
+ {
+ parser->top -= 2;
+ parser->args = parser->top + 1;
+ error = def_funcs[dict_state](parser);
+ }
+ else
+ {
+ /* This is an error, but some fonts contain */
+ /* stupid Postscript code. We simply ignore */
+ /* an invalid `def' by clearing the stack. */
+#if 0
+ FT_ERROR(( "Parse_T1_FontProgram: immediate expected\n" ));
+ goto Syntax_Error;
+#else
+ parser->top = parser->stack;
+#endif
+ }
+ }
+ else
+ {
+ FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
+ goto Stack_Underflow;
+ }
+ }
+ break;
+
+ case key_index:
+ if ( top <= parser->stack )
+ {
+ FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
+ goto Stack_Underflow;
+ }
+
+ /* simply ignore? */
+ parser->top --;
+ break;
+
+ case key_put:
+ /* Check that we have sufficient operands in stack */
+ if ( top < parser->stack + 2 )
+ {
+ FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
+ goto Stack_Underflow;
+ }
+
+ parser->top -= 2;
+ parser->args = parser->top;
+
+ switch ( dict_state )
+ {
+ case dict_encoding:
+ error = Do_Put_Encoding( parser );
+ if ( error )
+ goto Exit;
+ break;
+
+ case dict_unknown_array: /* ignore the `put' */
+ break;
+
+ default:
+#if 0
+ FT_ERROR(( "Parse_T1_FontProgram: invalid context\n" ));
+ goto Syntax_Error;
+#else
+ /* invalid context; simply ignore the `put' and */
+ /* clear the stack (stupid Postscript code) */
+ FT_TRACE4(( "Parse_T1_FontProgram: invalid context ignored.\n" ));
+ parser->top = parser->stack;
+#endif
+ }
+ break;
+
+ case key_RD:
+ /* Check that we have sufficient operands in stack */
+ if ( top < parser->stack + 2 )
+ {
+ FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
+ goto Stack_Underflow;
+ }
+
+ parser->top -= 2;
+ parser->args = parser->top;
+ switch ( dict_state )
+ {
+ case dict_subrs:
+ error = Do_RD_Subrs( parser );
+ if ( error )
+ goto Exit;
+ break;
+
+ case dict_charstrings:
+ error = Do_RD_Charstrings( parser );
+ if ( error )
+ goto Exit;
+ break;
+
+ default:
+ FT_ERROR(( "Parse_T1_FontProgram: invalid context\n" ));
+ goto Syntax_Error;
+ }
+ break;
+
+ case key_end:
+ /* Were we in a dictionary or in an array? */
+ if ( dict_index <= 0 )
+ {
+ FT_ERROR(( "Parse_T1_FontProgram: no dictionary defined\n" ));
+ goto Syntax_Error;
+ }
+
+ switch ( dict_state )
+ {
+ /* jump to the private dictionary if we are closing the */
+ /* `/Font' dictionary */
+ case dict_font:
+ goto Open_Private;
+
+ /* exit the parser when closing the CharStrings dictionary */
+ case dict_charstrings:
+ return Finalize_Parsing( parser );
+
+ default:
+ /* Pop the current dictionary state and return to previous */
+ /* one. Consume the `def'. */
+
+ /* Because some buggy fonts (BitStream) have incorrect */
+ /* syntax, we never escape from the private dictionary */
+ if ( dict_state != dict_private )
+ parser->state_index--;
+
+ /* many fonts use `NP' instead of `def' or `put', so */
+ /* we simply ignore the next token */
+#if 0
+ error = Expect_Keyword2( parser, key_def, key_put );
+ if ( error )
+ goto Exit;
+#else
+ (void)Expect_Keyword2( parser, key_def, key_put );
+#endif
+ }
+ break;
+
+ case key_for:
+ /* check that we have four arguments and simply */
+ /* ignore them */
+ if ( top - parser->stack < 4 )
+ {
+ FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
+ goto Stack_Underflow;
+ }
+
+ parser->top -= 4;
+ break;
+
+ case key_currentdict:
+ Open_Private:
+ parser->state_index = 0;
+ parser->state_stack[0] = dict_none2;
+ error = Open_PrivateDict( parser->tokenizer );
+ if ( error )
+ goto Exit;
+ break;
+
+ case key_true:
+ case key_false:
+ case key_StandardEncoding:
+ case key_ExpertEncoding:
+ goto Push_Element;
+
+ default:
+ FT_ERROR(( "Parse_T1_FontProgram:" ));
+ FT_ERROR(( " invalid keyword in context\n" ));
+ error = T1_Err_Syntax_Error;
+ }
+ break;
+
+ /* check for the presence of `/BlendAxisTypes' -- we cannot deal */
+ /* with multiple master fonts, so we must return a correct error */
+ /* code to allow another driver to load them */
+ case tok_immediate:
+ if ( token.kind2 == imm_BlendAxisTypes )
+ {
+ error = FT_Err_Unknown_File_Format;
+ goto Exit;
+ }
+ /* fallthrough */
+
+ /* A number was detected */
+ case tok_string:
+ case tok_program:
+ case tok_array:
+ case tok_hexarray:
+ case tok_any:
+ case tok_number: /* push number on stack */
+
+ Push_Element:
+ if ( top >= parser->limit )
+ {
+ error = T1_Err_Stack_Overflow;
+ goto Exit;
+ }
+ else
+ *parser->top++ = token;
+ break;
+
+ /* anything else is an error per se the spec, but we */
+ /* frequently encounter stupid postscript code in fonts, */
+ /* so just ignore them */
+ default:
+ error = T1_Err_Ok; /* ignore token */
+ }
+
+ if ( error )
+ return error;
+ }
+
+ Exit:
+ return error;
+
+ Syntax_Error:
+ return T1_Err_Syntax_Error;
+
+ Stack_Underflow:
+ return T1_Err_Stack_Underflow;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1load.h */
+/* */
+/* Type 1 font loader (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T1LOAD_H
+#define T1LOAD_H
+
+#include <freetype/internal/ftstream.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1parse.h"
+
+#else
+
+#include <type1/t1parse.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+ LOCAL_DEF
+ void Init_T1_Parser( T1_Parser* parser,
+ T1_Face face,
+ T1_Tokenizer tokenizer );
+
+
+ LOCAL_DEF
+ FT_Error Parse_T1_FontProgram( T1_Parser* parser );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* T1LOAD_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1objs.c */
+/* */
+/* Type 1 objects manager (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1gload.h"
+#include "t1load.h"
+#include "t1afm.h"
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+#include "t1hinter.h"
+#endif
+
+#else /* FT_FLAT_COMPILE */
+
+#include <type1/t1gload.h>
+#include <type1/t1load.h>
+#include <type1/t1afm.h>
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+#include <type1/t1hinter.h>
+#endif
+
+#endif /* FT_FLAT_COMPILE */
+
+
+#include <freetype/internal/psnames.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1objs
+
+
+ /*************************************************************************/
+ /* */
+ /* SIZE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Done_Size */
+ /* */
+ /* <Description> */
+ /* The Type 1 size object destructor. Used to discard a given size */
+ /* object. */
+ /* */
+ /* <Input> */
+ /* size :: A handle to the target size object. */
+ /* */
+ LOCAL_FUNC
+ void T1_Done_Size( T1_Size size )
+ {
+ if ( size )
+ {
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+ T1_Done_Size_Hinter( size );
+#endif
+
+ size->valid = 0;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Init_Size */
+ /* */
+ /* <Description> */
+ /* The size object initializer. */
+ /* */
+ /* <Input> */
+ /* size :: A handle to the target size object. */
+ /* */
+ /* <Return> */
+ /* FreeTrue error code. 0 means success. */
+ /* */
+ LOCAL_DEF
+ FT_Error T1_Init_Size( T1_Size size )
+ {
+ FT_Error error;
+
+
+ size->valid = 0;
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+ error = T1_New_Size_Hinter( size );
+
+ return error;
+#else
+
+ FT_UNUSED( error );
+
+ return T1_Err_Ok;
+
+#endif
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Reset_Size */
+ /* */
+ /* <Description> */
+ /* Resets an instance to a new pointsize/transform. This function is */
+ /* in charge of resetting the blue zones,a s well as the stem snap */
+ /* tables for a given size. */
+ /* */
+ /* <Input> */
+ /* size :: The target size object. */
+ /* */
+ /* <Output> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error T1_Reset_Size( T1_Size size )
+ {
+ /* recompute ascender, descender, etc. */
+ T1_Face face = (T1_Face)size->root.face;
+ FT_Size_Metrics* metrics = &size->root.metrics;
+
+
+ if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
+ return FT_Err_Invalid_Argument;
+
+ /* Compute root ascender, descender, test height, and max_advance */
+ metrics->ascender = ( FT_MulFix( face->root.ascender,
+ metrics->y_scale ) + 32 ) & -64;
+ metrics->descender = ( FT_MulFix( face->root.descender,
+ metrics->y_scale ) + 32 ) & -64;
+ metrics->height = ( FT_MulFix( face->root.height,
+ metrics->y_scale ) + 32 ) & -64;
+ metrics->max_advance = ( FT_MulFix( face->root.max_advance_width,
+ metrics->x_scale ) + 32 ) & -64;
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+ return T1_Reset_Size_Hinter( size );
+#else
+ return 0;
+#endif
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FACE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Done_Face */
+ /* */
+ /* <Description> */
+ /* The face object destructor. */
+ /* */
+ /* <Input> */
+ /* face :: A typeless pointer to the face object to destroy. */
+ /* */
+ LOCAL_FUNC
+ void T1_Done_Face( T1_Face face )
+ {
+ FT_Memory memory;
+ T1_Font* type1 = &face->type1;
+
+
+ if ( face )
+ {
+ memory = face->root.memory;
+
+ /* release font info strings */
+ {
+ T1_FontInfo* info = &type1->font_info;
+
+
+ FREE( info->version );
+ FREE( info->notice );
+ FREE( info->full_name );
+ FREE( info->family_name );
+ FREE( info->weight );
+ }
+
+ /* release top dictionary */
+ FREE( type1->charstrings_len );
+ FREE( type1->charstrings );
+ FREE( type1->glyph_names );
+
+ FREE( type1->subrs );
+ FREE( type1->subrs_len );
+
+ FREE( type1->subrs_block );
+ FREE( type1->charstrings_block );
+ FREE( type1->glyph_names_block );
+
+ FREE( type1->encoding.char_index );
+ FREE( type1->font_name );
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+ /* release afm data if present */
+ if ( face->afm_data )
+ T1_Done_AFM( memory, (T1_AFM*)face->afm_data );
+#endif
+
+ /* release unicode map, if any */
+ FREE( face->unicode_map.maps );
+ face->unicode_map.num_maps = 0;
+
+ face->root.family_name = 0;
+ face->root.style_name = 0;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Init_Face */
+ /* */
+ /* <Description> */
+ /* The face object constructor. */
+ /* */
+ /* <Input> */
+ /* stream :: input stream where to load font data. */
+ /* */
+ /* face_index :: The index of the font face in the resource. */
+ /* */
+ /* num_params :: Number of additional generic parameters. Ignored. */
+ /* */
+ /* params :: Additional generic parameters. Ignored. */
+ /* */
+ /* <InOut> */
+ /* face :: The face record to build. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error T1_Init_Face( FT_Stream stream,
+ T1_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ T1_Tokenizer tokenizer;
+ FT_Error error;
+ PSNames_Interface* psnames;
+
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+ FT_UNUSED( face_index );
+ FT_UNUSED( face );
+
+
+ face->root.num_faces = 1;
+
+ psnames = (PSNames_Interface*)face->psnames;
+ if ( !psnames )
+ {
+ psnames = (PSNames_Interface*)
+ FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
+ "psnames" );
+
+ face->psnames = psnames;
+ }
+
+ /* open the tokenizer, this will also check the font format */
+ error = New_Tokenizer( stream, &tokenizer );
+ if ( error )
+ goto Fail;
+
+ /* if we just wanted to check the format, leave successfully now */
+ if ( face_index < 0 )
+ goto Leave;
+
+ /* check the face index */
+ if ( face_index != 0 )
+ {
+ FT_ERROR(( "T1_Init_Face: invalid face index\n" ));
+ error = T1_Err_Invalid_Argument;
+ goto Leave;
+ }
+
+ /* Now, load the font program into the face object */
+ {
+ T1_Parser parser;
+
+
+ Init_T1_Parser( &parser, face, tokenizer );
+ error = Parse_T1_FontProgram( &parser );
+ if ( error )
+ goto Leave;
+
+ /* Init the face object fields */
+ /* Now set up root face fields */
+ {
+ FT_Face root = (FT_Face)&face->root;
+ T1_Font* type1 = &face->type1;
+
+
+ root->num_glyphs = type1->num_glyphs;
+ root->num_charmaps = 1;
+
+ root->face_index = face_index;
+ root->face_flags = FT_FACE_FLAG_SCALABLE;
+
+ root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
+
+ root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
+
+ if ( type1->font_info.is_fixed_pitch )
+ root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ /* XXX: TODO -- add kerning with .afm support */
+
+ /* get style name - be careful, some broken fonts only */
+ /* have a `/FontName' dictionary entry! */
+ root->family_name = type1->font_info.family_name;
+ if ( root->family_name )
+ {
+ char* full = type1->font_info.full_name;
+ char* family = root->family_name;
+
+
+ while ( *family && *full == *family )
+ {
+ family++;
+ full++;
+ }
+
+ root->style_name = ( *full == ' ' ? full + 1
+ : (char *)"Regular" );
+ }
+ else
+ {
+ /* do we have a `/FontName'? */
+ if (type1->font_name)
+ {
+ root->family_name = type1->font_name;
+ root->style_name = "Regular";
+ }
+ }
+
+ /* no embedded bitmap support */
+ root->num_fixed_sizes = 0;
+ root->available_sizes = 0;
+
+ root->bbox = type1->font_bbox;
+ root->units_per_EM = 1000;
+ root->ascender = (FT_Short)type1->font_bbox.yMax;
+ root->descender = -(FT_Short)type1->font_bbox.yMin;
+ root->height = ( ( root->ascender + root->descender) * 12 )
+ / 10;
+
+ /* now compute the maximum advance width */
+
+ root->max_advance_width = type1->private_dict.standard_width[0];
+
+ /* compute max advance width for proportional fonts */
+ if ( !type1->font_info.is_fixed_pitch )
+ {
+ FT_Int max_advance;
+
+
+ error = T1_Compute_Max_Advance( face, &max_advance );
+
+ /* in case of error, keep the standard width */
+ if ( !error )
+ root->max_advance_width = max_advance;
+ else
+ error = 0; /* clear error */
+ }
+
+ root->max_advance_height = root->height;
+
+ root->underline_position = type1->font_info.underline_position;
+ root->underline_thickness = type1->font_info.underline_thickness;
+
+ root->max_points = 0;
+ root->max_contours = 0;
+ }
+ }
+
+ /* charmap support - synthetize unicode charmap when possible */
+ {
+ FT_Face root = &face->root;
+ FT_CharMap charmap = face->charmaprecs;
+
+
+ /* synthesize a Unicode charmap if there is support in the `PSNames' */
+ /* module.. */
+ if ( face->psnames )
+ {
+ PSNames_Interface* psnames = (PSNames_Interface*)face->psnames;
+
+
+ if ( psnames->unicode_value )
+ {
+ error = psnames->build_unicodes(
+ root->memory,
+ face->type1.num_glyphs,
+ (const char**)face->type1.glyph_names,
+ &face->unicode_map );
+ if ( !error )
+ {
+ root->charmap = charmap;
+ charmap->face = (FT_Face)face;
+ charmap->encoding = ft_encoding_unicode;
+ charmap->platform_id = 3;
+ charmap->encoding_id = 1;
+ charmap++;
+ }
+
+ /* simply clear the error in case of failure (which really) */
+ /* means that out of memory or no unicode glyph names */
+ error = 0;
+ }
+ }
+
+ /* now, support either the standard, expert, or custom encodings */
+ charmap->face = (FT_Face)face;
+ charmap->platform_id = 7; /* a new platform id for Adobe fonts ?? */
+
+ switch ( face->type1.encoding_type )
+ {
+ case t1_encoding_standard:
+ charmap->encoding = ft_encoding_adobe_standard;
+ charmap->encoding_id = 0;
+ break;
+
+ case t1_encoding_expert:
+ charmap->encoding = ft_encoding_adobe_expert;
+ charmap->encoding_id = 1;
+ break;
+
+ default:
+ charmap->encoding = ft_encoding_adobe_custom;
+ charmap->encoding_id = 2;
+ break;
+ }
+
+ root->charmaps = face->charmaps;
+ root->num_charmaps = charmap - face->charmaprecs + 1;
+ face->charmaps[0] = &face->charmaprecs[0];
+ face->charmaps[1] = &face->charmaprecs[1];
+ }
+
+ Leave:
+ Done_Tokenizer( tokenizer );
+
+ Fail:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Done_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* The glyph slot object destructor. */
+ /* */
+ /* <Input> */
+ /* glyph :: The glyph slot handle to destroy. */
+ /* */
+ LOCAL_FUNC
+ void T1_Done_GlyphSlot( T1_GlyphSlot glyph )
+ {
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+
+ T1_Done_Glyph_Hinter( glyph );
+
+#else
+
+ FT_UNUSED( glyph );
+
+#endif
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Init_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* The glyph slot object constructor. */
+ /* */
+ /* <Input> */
+ /* glyph :: The glyph slot handle to initialize. */
+ /* */
+ LOCAL_FUNC
+ FT_Error T1_Init_GlyphSlot( T1_GlyphSlot glyph )
+ {
+ FT_Error error = FT_Err_Ok;
+
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+
+ error = T1_New_Glyph_Hinter( glyph );
+
+#else
+
+ FT_UNUSED( glyph );
+
+#endif
+
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1objs.h */
+/* */
+/* Type 1 objects manager (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T1OBJS_H
+#define T1OBJS_H
+
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/t1types.h>
+
+#include <freetype/internal/t1errors.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /* The following structures must be defined by the hinter */
+ typedef struct T1_Size_Hints_ T1_Size_Hints;
+ typedef struct T1_Glyph_Hints_ T1_Glyph_Hints;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_Driver */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 driver object. */
+ /* */
+ typedef struct T1_DriverRec_* T1_Driver;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_Size */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 size object. */
+ /* */
+ typedef struct T1_SizeRec_* T1_Size;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 glyph slot object. */
+ /* */
+ typedef struct T1_GlyphSlotRec_* T1_GlyphSlot;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_CharMap */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 character mapping object. */
+ /* */
+ /* <Note> */
+ /* The Type 1 format doesn't use a charmap but an encoding table. */
+ /* The driver is responsible for making up charmap objects */
+ /* corresponding to these tables. */
+ /* */
+ typedef struct T1_CharMapRec_* T1_CharMap;
+
+
+ /*************************************************************************/
+ /* */
+ /* HERE BEGINS THE TYPE1 SPECIFIC STUFF */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_SizeRec */
+ /* */
+ /* <Description> */
+ /* Type 1 size record. */
+ /* */
+ typedef struct T1_SizeRec_
+ {
+ FT_SizeRec root;
+ FT_Bool valid;
+ T1_Size_Hints* hints; /* defined in the hinter. This allows */
+ /* us to experiment with different */
+ /* hinting schemes without having to */
+ /* change `t1objs' each time. */
+ } T1_SizeRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_GlyphSlotRec */
+ /* */
+ /* <Description> */
+ /* Type 1 glyph slot record. */
+ /* */
+ typedef struct T1_GlyphSlotRec_
+ {
+ FT_GlyphSlotRec root;
+
+ FT_Bool hint;
+ FT_Bool scaled;
+
+ FT_Int max_points;
+ FT_Int max_contours;
+
+ FT_Fixed x_scale;
+ FT_Fixed y_scale;
+
+ T1_Glyph_Hints* hints; /* defined in the hinter */
+
+ } T1_GlyphSlotRec;
+
+
+ LOCAL_DEF
+ FT_Error T1_Init_Face( FT_Stream stream,
+ T1_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+ LOCAL_DEF
+ void T1_Done_Face( T1_Face face );
+
+ LOCAL_DEF
+ FT_Error T1_Init_Size( T1_Size size );
+
+ LOCAL_DEF
+ void T1_Done_Size( T1_Size size );
+
+ LOCAL_DEF
+ FT_Error T1_Reset_Size( T1_Size size );
+
+ LOCAL_DEF
+ FT_Error T1_Init_GlyphSlot( T1_GlyphSlot slot );
+
+ LOCAL_DEF
+ void T1_Done_GlyphSlot( T1_GlyphSlot slot );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* T1OBJS_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1parse.c */
+/* */
+/* Type 1 parser (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/t1types.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1parse.h"
+
+#else
+
+#include <type1/t1parse.h>
+
+#endif
+
+
+#include <stdio.h> /* for sscanf() */
+#include <string.h> /* for strncpy() */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_New_Table */
+ /* */
+ /* <Description> */
+ /* Initializes a T1_Table structure. */
+ /* */
+ /* <InOut> */
+ /* table :: The address of the target table. */
+ /* */
+ /* <Input> */
+ /* count :: The table size (i.e. maximum number of elements). */
+ /* memory :: The memory object to use for all subsequent */
+ /* reallocations. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error T1_New_Table( T1_Table* table,
+ FT_Int count,
+ FT_Memory memory )
+ {
+ FT_Error error;
+
+
+ table->memory = memory;
+
+ if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) )
+ return error;
+
+ if ( ALLOC_ARRAY( table->lengths, count, FT_Byte* ) )
+ {
+ FREE( table->elements );
+ return error;
+ }
+
+ table->max_elems = count;
+ table->num_elems = 0;
+
+ table->block = 0;
+ table->capacity = 0;
+ table->cursor = 0;
+
+ return error;
+ }
+
+
+ static
+ FT_Error reallocate_t1_table( T1_Table* table,
+ FT_Int new_size )
+ {
+ FT_Memory memory = table->memory;
+ FT_Byte* old_base = table->block;
+ FT_Error error;
+
+
+ /* reallocate the base block */
+ if ( REALLOC( table->block, table->capacity, new_size ) )
+ return error;
+ table->capacity = new_size;
+
+ /* shift all offsets if necessary */
+ if ( old_base )
+ {
+ FT_Long delta = table->block - old_base;
+ FT_Byte** offset = table->elements;
+ FT_Byte** limit = offset + table->max_elems;
+
+
+ if ( delta )
+ for ( ; offset < limit; offset ++ )
+ if (offset[0])
+ offset[0] += delta;
+ }
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Add_Table */
+ /* */
+ /* <Description> */
+ /* Adds an object to a T1_Table, possibly growing its memory block. */
+ /* */
+ /* <InOut> */
+ /* table :: The target table. */
+ /* */
+ /* <Input> */
+ /* index :: The index of the object in the table. */
+ /* */
+ /* object :: The address of the object to copy in memory. */
+ /* */
+ /* length :: The length in bytes of the source object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. An error is returned if a */
+ /* reallocation failed. */
+ /* */
+ LOCAL_FUNC
+ FT_Error T1_Add_Table( T1_Table* table,
+ FT_Int index,
+ void* object,
+ FT_Int length )
+ {
+ if ( index < 0 || index > table->max_elems )
+ {
+ FT_ERROR(( "T1_Add_Table: invalid index\n" ));
+ return T1_Err_Syntax_Error;
+ }
+
+ /* grow the base block if needed */
+ if ( table->cursor + length > table->capacity )
+ {
+ FT_Error error;
+ FT_Int new_size = table->capacity;
+
+
+ while ( new_size < table->cursor + length )
+ new_size += 1024;
+
+ error = reallocate_t1_table( table, new_size );
+ if ( error )
+ return error;
+ }
+
+ /* add the object to the base block and adjust offset */
+ table->elements[index] = table->block + table->cursor;
+ table->lengths [index] = length;
+ MEM_Copy( table->block + table->cursor, object, length );
+
+ table->cursor += length;
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Done_Table */
+ /* */
+ /* <Description> */
+ /* Finalize a T1_Table (reallocate it to its current cursor). */
+ /* */
+ /* <Input> */
+ /* table :: The target table. */
+ /* */
+ /* <Note> */
+ /* This function does NOT release the heap's memory block. It is up */
+ /* to the caller to clean it, or reference it in its own structures. */
+ /* */
+ LOCAL_FUNC
+ void T1_Done_Table( T1_Table* table )
+ {
+ FT_Memory memory = table->memory;
+ FT_Error error;
+ FT_Byte* old_base;
+
+
+ /* should never fail, as rec.cursor <= rec.size */
+ old_base = table->block;
+ if ( !old_base )
+ return;
+
+ (void)REALLOC( table->block, table->capacity, table->cursor );
+ table->capacity = table->cursor;
+
+ if ( old_base != table->block )
+ {
+ FT_Long delta = table->block - old_base;
+ FT_Byte** element = table->elements;
+ FT_Byte** limit = element + table->max_elems;
+
+
+ for ( ; element < limit; element++ )
+ if ( element[0] )
+ element[0] += delta;
+ }
+ }
+
+
+ LOCAL_FUNC
+ FT_String* CopyString( T1_Parser* parser )
+ {
+ FT_String* string = NULL;
+ T1_Token* token = parser->args++;
+ FT_Memory memory = parser->tokenizer->memory;
+ FT_Error error;
+
+
+ if ( token->kind == tok_string )
+ {
+ FT_Int len = token->len - 2;
+
+
+ if ( ALLOC( string, len + 1 ) )
+ {
+ parser->error = error;
+ return 0;
+ }
+
+ MEM_Copy( string, parser->tokenizer->base + token->start + 1, len );
+ string[len] = '\0';
+
+ parser->error = T1_Err_Ok;
+ }
+ else
+ {
+ FT_ERROR(( "T1_CopyString: syntax error, string token expected!\n" ));
+ parser->error = T1_Err_Syntax_Error;
+ }
+
+ return string;
+ }
+
+
+ static
+ FT_Error parse_int( FT_Byte* base,
+ FT_Byte* limit,
+ FT_Long* result )
+ {
+ FT_Bool sign = 0;
+ FT_Long sum = 0;
+
+
+ if ( base >= limit )
+ goto Fail;
+
+ /* check sign */
+ if ( *base == '+' )
+ base++;
+
+ else if ( *base == '-' )
+ {
+ sign++;
+ base++;
+ }
+
+ /* parse digits */
+ if ( base >= limit )
+ goto Fail;
+
+ do
+ {
+ sum = ( 10 * sum + ( *base++ - '0' ) );
+
+ } while ( base < limit );
+
+ if ( sign )
+ sum = -sum;
+
+ *result = sum;
+ return T1_Err_Ok;
+
+ Fail:
+ FT_ERROR(( "parse_int: integer expected\n" ));
+ *result = 0;
+ return T1_Err_Syntax_Error;
+ }
+
+
+ static
+ FT_Error parse_float( FT_Byte* base,
+ FT_Byte* limit,
+ FT_Long scale,
+ FT_Long* result )
+ {
+#if 1
+
+ /* XXX: We are simply much too lazy to code this function */
+ /* properly for now. We will do that when the rest of */
+ /* the driver works properly. */
+ char temp[32];
+ int len = limit - base;
+ double value;
+
+
+ if ( len > 31 )
+ goto Fail;
+
+ strncpy( temp, (char*)base, len );
+ temp[len] = '\0';
+ if ( sscanf( temp, "%lf", &value ) != 1 )
+ goto Fail;
+
+ *result = (FT_Long)( scale * value );
+ return 0;
+
+#else
+
+ FT_Byte* cur;
+ FT_Bool sign = 0; /* sign */
+ FT_Long number_int = 0; /* integer part */
+ FT_Long number_frac = 0; /* fractional part */
+ FT_Long exponent = 0; /* exponent value */
+ FT_Int num_frac = 0; /* number of fractional digits */
+
+
+ /* check sign */
+ if ( *base == '+' )
+ base++;
+
+ else if ( *base == '-' )
+ {
+ sign++;
+ base++;
+ }
+
+ /* find integer part */
+ cur = base;
+ while ( cur < limit )
+ {
+ FT_Byte c = *cur;
+
+
+ if ( c == '.' || c == 'e' || c == 'E' )
+ break;
+
+ cur++;
+ }
+
+ if ( cur > base )
+ {
+ error = parse_integer( base, cur, &number_int );
+ if ( error )
+ goto Fail;
+ }
+
+ /* read fractional part, if any */
+ if ( *cur == '.' )
+ {
+ cur++;
+ base = cur;
+ while ( cur < limit )
+ {
+ FT_Byte c = *cur;
+
+
+ if ( c == 'e' || c == 'E' )
+ break;
+ cur++;
+ }
+
+ num_frac = cur - base;
+
+ if ( cur > base )
+ {
+ error = parse_integer( base, cur, &number_frac );
+ if ( error )
+ goto Fail;
+ base = cur;
+ }
+ }
+
+ /* read exponent, if any */
+ if ( *cur == 'e' || *cur == 'E' )
+ {
+ cur++;
+ base = cur;
+ error = parse_integer( base, limit, &exponent );
+ if ( error )
+ goto Fail;
+
+ /* now check that exponent is within `correct bounds' */
+ /* i.e. between -6 and 6 */
+ if ( exponent < -6 || exponent > 6 )
+ goto Fail;
+ }
+
+ /* now adjust integer value and exponent for fractional part */
+ while ( num_frac > 0 )
+ {
+ number_int *= 10;
+ exponent--;
+ num_frac--;
+ }
+
+ number_int += num_frac;
+
+ /* skip point if any, read fractional part */
+ if ( cur + 1 < limit )
+ {
+ if (*cur..
+ }
+
+ /* now compute scaled float value */
+ /* XXX: incomplete! */
+
+#endif /* 1 */
+
+ Fail:
+ FT_ERROR(( "parse_float: syntax error!\n" ));
+ return T1_Err_Syntax_Error;
+ }
+
+
+ static
+ FT_Error parse_integer( FT_Byte* base,
+ FT_Byte* limit,
+ FT_Long* result )
+ {
+ FT_Byte* cur;
+
+
+ /* the lexical analyser accepts floats as well as integers */
+ /* now; check that we really have an int in this token */
+ cur = base;
+ while ( cur < limit )
+ {
+ FT_Byte c = *cur++;
+
+
+ if ( c == '.' || c == 'e' || c == 'E' )
+ goto Float_Number;
+ }
+
+ /* now read the number's value */
+ return parse_int( base, limit, result );
+
+ Float_Number:
+ /* we really have a float there; simply call parse_float in this */
+ /* case with a scale of `10' to perform round */
+ {
+ FT_Error error;
+
+
+ error = parse_float( base, limit, 10, result );
+ if ( !error )
+ {
+ if ( *result >= 0 )
+ *result = ( *result + 5 ) / 10; /* round value */
+ else
+ *result = -( ( 5 - *result ) / 10 );
+ }
+ return error;
+ }
+ }
+
+
+ LOCAL_FUNC
+ FT_Long CopyInteger( T1_Parser* parser )
+ {
+ FT_Long sum = 0;
+ T1_Token* token = parser->args++;
+
+
+ if ( token->kind == tok_number )
+ {
+ FT_Byte* base = parser->tokenizer->base + token->start;
+ FT_Byte* limit = base + token->len;
+
+
+ /* now read the number's value */
+ parser->error = parse_integer( base, limit, &sum );
+ return sum;
+ }
+
+ FT_ERROR(( "CopyInteger: number expected\n" ));
+ parser->args--;
+ parser->error = T1_Err_Syntax_Error;
+ return 0;
+ }
+
+
+ LOCAL_FUNC
+ FT_Bool CopyBoolean( T1_Parser* parser )
+ {
+ FT_Error error = T1_Err_Ok;
+ FT_Bool result = 0;
+ T1_Token* token = parser->args++;
+
+
+ if ( token->kind == tok_keyword )
+ {
+ if ( token->kind2 == key_false )
+ result = 0;
+
+ else if ( token->kind2 == key_true )
+ result = !0;
+
+ else
+ goto Fail;
+ }
+ else
+ {
+ Fail:
+ FT_ERROR(( "CopyBoolean:" ));
+ FT_ERROR(( " syntax error; `false' or `true' expected\n" ));
+ error = T1_Err_Syntax_Error;
+ }
+ parser->error = error;
+ return result;
+ }
+
+
+ LOCAL_FUNC
+ FT_Long CopyFloat( T1_Parser* parser,
+ FT_Int scale )
+ {
+ FT_Error error;
+ FT_Long sum = 0;
+ T1_Token* token = parser->args++;
+
+
+ if ( token->kind == tok_number )
+ {
+ FT_Byte* base = parser->tokenizer->base + token->start;
+ FT_Byte* limit = base + token->len;
+
+
+ error = parser->error = parse_float( base, limit, scale, &sum );
+ if ( error )
+ goto Fail;
+
+ return sum;
+ }
+
+ Fail:
+ FT_ERROR(( "CopyFloat: syntax error!\n" ));
+ parser->error = T1_Err_Syntax_Error;
+ return 0;
+ }
+
+
+ LOCAL_FUNC
+ void CopyBBox( T1_Parser* parser,
+ FT_BBox* bbox )
+ {
+ T1_Token* token = parser->args++;
+ FT_Int n;
+ FT_Error error;
+
+
+ if ( token->kind == tok_program ||
+ token->kind == tok_array )
+ {
+ /* get rid of `['/`]', or `{'/`}' */
+ FT_Byte* base = parser->tokenizer->base + token->start + 1;
+ FT_Byte* limit = base + token->len - 2;
+ FT_Byte* cur;
+ FT_Byte* start;
+
+
+ /* read each parameter independently */
+ cur = base;
+ for ( n = 0; n < 4; n++ )
+ {
+ FT_Long* result;
+
+
+ /* skip whitespace */
+ while ( cur < limit && *cur == ' ' )
+ cur++;
+
+ /* skip numbers */
+ start = cur;
+ while ( cur < limit && *cur != ' ' )
+ cur++;
+
+ /* compute result address */
+ switch ( n )
+ {
+ case 0:
+ result = &bbox->xMin;
+ break;
+ case 1:
+ result = &bbox->yMin;
+ break;
+ case 2:
+ result = &bbox->xMax;
+ break;
+ default:
+ result = &bbox->yMax;
+ }
+
+ error = parse_integer( start, cur, result );
+ if ( error )
+ goto Fail;
+ }
+ parser->error = 0;
+ return;
+ }
+
+ Fail:
+ FT_ERROR(( "CopyBBox: syntax error!\n" ));
+ parser->error = T1_Err_Syntax_Error;
+ }
+
+
+ LOCAL_FUNC
+ void CopyMatrix( T1_Parser* parser,
+ FT_Matrix* matrix )
+ {
+ T1_Token* token = parser->args++;
+ FT_Error error;
+
+
+ if ( token->kind == tok_array )
+ {
+ /* get rid of `[' and `]' */
+ FT_Byte* base = parser->tokenizer->base + token->start + 1;
+ FT_Byte* limit = base + token->len - 2;
+ FT_Byte* cur;
+ FT_Byte* start;
+ FT_Int n;
+
+
+ /* read each parameter independently */
+ cur = base;
+ for ( n = 0; n < 4; n++ )
+ {
+ FT_Long* result;
+
+
+ /* skip whitespace */
+ while ( cur < limit && *cur == ' ' )
+ cur++;
+
+ /* skip numbers */
+ start = cur;
+ while ( cur < limit && *cur != ' ')
+ cur++;
+
+ /* compute result address */
+ switch ( n )
+ {
+ case 0:
+ result = &matrix->xx;
+ break;
+ case 1:
+ result = &matrix->yx;
+ break;
+ case 2:
+ result = &matrix->xy;
+ break;
+ default:
+ result = &matrix->yy;
+ }
+
+ error = parse_float( start, cur, 65536000L, result );
+ if ( error )
+ goto Fail;
+ }
+ parser->error = 0;
+ return;
+ }
+
+ Fail:
+ FT_ERROR(( "CopyMatrix: syntax error!\n" ));
+ parser->error = T1_Err_Syntax_Error;
+ }
+
+
+ LOCAL_FUNC
+ void CopyArray( T1_Parser* parser,
+ FT_Byte* num_elements,
+ FT_Short* elements,
+ FT_Int max_elements )
+ {
+ T1_Token* token = parser->args++;
+ FT_Error error;
+
+
+ if ( token->kind == tok_array ||
+ token->kind == tok_program ) /* in the case of MinFeature */
+ {
+ /* get rid of `['/`]', or `{'/`}' */
+ FT_Byte* base = parser->tokenizer->base + token->start + 1;
+ FT_Byte* limit = base + token->len - 2;
+ FT_Byte* cur;
+ FT_Byte* start;
+ FT_Int n;
+
+
+ /* read each parameter independently */
+ cur = base;
+ for ( n = 0; n < max_elements; n++ )
+ {
+ FT_Long result;
+
+
+ /* test end of string */
+ if ( cur >= limit )
+ break;
+
+ /* skip whitespace */
+ while ( cur < limit && *cur == ' ' )
+ cur++;
+
+ /* end of list? */
+ if ( cur >= limit )
+ break;
+
+ /* skip numbers */
+ start = cur;
+ while ( cur < limit && *cur != ' ' )
+ cur++;
+
+ error = parse_integer( start, cur, &result );
+ if ( error )
+ goto Fail;
+
+ *elements++ = (FT_Short)result;
+ }
+
+ if ( num_elements )
+ *num_elements = (FT_Byte)n;
+
+ parser->error = 0;
+ return;
+ }
+
+ Fail:
+ FT_ERROR(( "CopyArray: syntax error!\n" ));
+ parser->error = T1_Err_Syntax_Error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1parse.h */
+/* */
+/* Type 1 parser (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* The Type1 parser component is in charge of simply parsing the font */
+ /* input stream and convert simple tokens and elements into integers, */
+ /* floats, matrices, strings, etc. */
+ /* */
+ /* It is used by the Type1 loader. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef T1PARSE_H
+#define T1PARSE_H
+
+#include <freetype/internal/ftstream.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1tokens.h"
+
+#else
+
+#include <type1/t1tokens.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* T1_DictState */
+ /* */
+ /* <Description> */
+ /* An enumeration used to describe the Type 1 parser's state, i.e. */
+ /* which dictionary (or array) it is scanning and processing at the */
+ /* current moment. */
+ /* */
+ typedef enum T1_DictState_
+ {
+ dict_none = 0,
+ dict_font, /* parsing the font dictionary */
+ dict_fontinfo, /* parsing the font info dictionary */
+ dict_none2, /* beginning to parse the encrypted section */
+ dict_private, /* parsing the private dictionary */
+ dict_encoding, /* parsing the encoding array */
+ dict_subrs, /* parsing the subrs array */
+ dict_othersubrs, /* parsing the othersubrs array (?) */
+ dict_charstrings, /* parsing the charstrings dictionary */
+ dict_unknown_array, /* parsing/ignoring an unknown array */
+ dict_unknown_dict, /* parsing/ignoring an unknown dictionary */
+
+ dict_max /* do not remove from list */
+
+ } T1_DictState;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_Table */
+ /* */
+ /* <Description> */
+ /* A T1_Table is a simple object used to store an array of objects in */
+ /* a single memory block. */
+ /* */
+ /* <Fields> */
+ /* block :: The address in memory of the growheap's block. This */
+ /* can change between two object adds, due to */
+ /* reallocation. */
+ /* */
+ /* cursor :: The current top of the grow heap within its block. */
+ /* */
+ /* capacity :: The current size of the heap block. Increments by */
+ /* 1kByte chunks. */
+ /* */
+ /* max_elems :: The maximum number of elements in table. */
+ /* */
+ /* num_elems :: The current number of elements in table. */
+ /* */
+ /* elements :: A table of element addresses within the block. */
+ /* */
+ /* lengths :: A table of element sizes within the block. */
+ /* */
+ /* memory :: The object used for memory operations */
+ /* (alloc/realloc). */
+ /* */
+ typedef struct T1_Table_
+ {
+ FT_Byte* block; /* current memory block */
+ FT_Int cursor; /* current cursor in memory block */
+ FT_Int capacity; /* current size of memory block */
+
+ FT_Int max_elems;
+ FT_Int num_elems;
+ FT_Byte** elements; /* addresses of table elements */
+ FT_Int* lengths; /* lengths of table elements */
+
+ FT_Memory memory;
+
+ } T1_Table;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_Parser */
+ /* */
+ /* <Description> */
+ /* A Type 1 parser. This object is in charge of parsing Type 1 ASCII */
+ /* streams and builds dictionaries for a T1_Face object. */
+ /* */
+ /* <Fields> */
+ /* error :: The current error code. 0 means success. */
+ /* */
+ /* face :: The target T1_Face object being built. */
+ /* */
+ /* tokenizer :: The tokenizer (lexical analyser) used for */
+ /* processing the input stream. */
+ /* */
+ /* dump_tokens :: XXX */
+ /* */
+ /* stack :: The current token stack. Note that we don't */
+ /* use intermediate Postscript objects here! */
+ /* */
+ /* top :: The current top of token stack. */
+ /* */
+ /* limit :: The current upper bound of the token stack. */
+ /* Used for overflow checks. */
+ /* */
+ /* args :: The arguments of a given operator. Used and */
+ /* increased by the various CopyXXX() functions. */
+ /* */
+ /* state_index :: The index of the top of the dictionary state */
+ /* stack. */
+ /* */
+ /* state_stack :: The dictionary states stack. */
+ /* */
+ /* table :: A T1_Table object used to record various kinds */
+ /* of dictionaries or arrays (like `/Encoding', */
+ /* `/Subrs', `/CharStrings'). */
+ /* */
+ /* cur_name :: XXX */
+ /* */
+ /* encoding_type :: XXX */
+ /* */
+ /* encoding_names :: XXX */
+ /* */
+ /* encoding_lengths :: XXX */
+ /* */
+ /* encoding_offsets :: XXX */
+ /* */
+ /* subrs :: XXX */
+ /* */
+ /* charstrings :: XXX */
+ /* */
+ typedef struct T1_Parser_
+ {
+ FT_Error error;
+ T1_Face face;
+
+ T1_Tokenizer tokenizer;
+ FT_Bool dump_tokens;
+
+ T1_Token stack[T1_MAX_STACK_DEPTH];
+ T1_Token* top;
+ T1_Token* limit;
+ T1_Token* args;
+
+ FT_Int state_index;
+ T1_DictState state_stack[T1_MAX_DICT_DEPTH];
+
+ T1_Table table;
+
+ FT_Int cur_name;
+
+ T1_EncodingType encoding_type;
+ FT_Byte* encoding_names;
+ FT_Int* encoding_lengths;
+ FT_Byte** encoding_offsets;
+
+ FT_Byte* subrs;
+ FT_Byte* charstrings;
+
+ } T1_Parser;
+
+
+ LOCAL_DEF
+ FT_Error T1_New_Table( T1_Table* table,
+ FT_Int count,
+ FT_Memory memory );
+
+ LOCAL_DEF
+ FT_Error T1_Add_Table( T1_Table* table,
+ FT_Int index,
+ void* object,
+ FT_Int length );
+
+ LOCAL_DEF
+ void T1_Done_Table( T1_Table* table );
+
+
+ LOCAL_DEF
+ FT_String* CopyString( T1_Parser* parser );
+
+ LOCAL_DEF
+ FT_Long CopyInteger( T1_Parser* parser );
+
+ LOCAL_DEF
+ FT_Bool CopyBoolean( T1_Parser* parser );
+
+ LOCAL_DEF
+ FT_Long CopyFloat( T1_Parser* parser,
+ FT_Int scale );
+
+ LOCAL_DEF
+ void CopyBBox( T1_Parser* parser,
+ FT_BBox* bbox );
+
+ LOCAL_DEF
+ void CopyMatrix( T1_Parser* parser,
+ FT_Matrix* matrix );
+
+ LOCAL_DEF
+ void CopyArray( T1_Parser* parser,
+ FT_Byte* num_elements,
+ FT_Short* elements,
+ FT_Int max_elements );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* T1PARSE_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1parse.c */
+/* */
+/* Type 1 parser (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* The tokenizer is in charge of loading and reading a Type1 font file */
+ /* (either in PFB or PFA format), and extracting successive tokens and */
+ /* keywords from its two streams (i.e. the font program, and the private */
+ /* dictionary). */
+ /* */
+ /* Eexec decryption is performed automatically when entering the private */
+ /* dictionary, or when retrieving char strings. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/ftdebug.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1tokens.h"
+#include "t1load.h"
+
+#else
+
+#include <type1/t1tokens.h>
+#include <type1/t1load.h>
+
+#endif
+
+
+#include <string.h> /* for strncmp() */
+
+
+#undef READ_BUFFER_INCREMENT
+#define READ_BUFFER_INCREMENT 0x400
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1load
+
+
+ /* An array of Type1 keywords supported by this engine. This table */
+ /* places the keyword in lexicographical order. It should always */
+ /* correspond to the enums `key_xxx'! */
+ /* */
+ const char* t1_keywords[key_max - key_first_] =
+ {
+ "-|", "ExpertEncoding", "ND", "NP", "RD", "StandardEncoding", "array",
+ "begin", "closefile", "currentdict", "currentfile", "def", "dict", "dup",
+ "eexec", "end", "executeonly", "false", "for", "index", "noaccess",
+ "put", "readonly", "true", "userdict", "|", "|-"
+ };
+
+
+ const char* t1_immediates[imm_max - imm_first_] =
+ {
+ "-|", ".notdef", "BlendAxisTypes", "BlueFuzz", "BlueScale", "BlueShift",
+ "BlueValues", "CharStrings", "Encoding", "FamilyBlues", "FamilyName",
+ "FamilyOtherBlues", "FID", "FontBBox", "FontID", "FontInfo", "FontMatrix",
+ "FontName", "FontType", "ForceBold", "FullName", "ItalicAngle",
+ "LanguageGroup", "Metrics", "MinFeature", "ND", "NP", "Notice",
+ "OtherBlues", "OtherSubrs", "PaintType", "Private", "RD", "RndStemUp",
+ "StdHW", "StdVW", "StemSnapH", "StemSnapV", "StrokeWidth", "Subrs",
+ "UnderlinePosition", "UnderlineThickness", "UniqueID", "Weight",
+ "isFixedPitch", "lenIV", "password", "version", "|", "|-"
+ };
+
+
+ /* lexicographic comparison of two strings */
+ static
+ int lexico_strcmp( const char* str1,
+ int str1_len,
+ const char* str2 )
+ {
+ int c2 = 0;
+
+
+ for ( ; str1_len > 0; str1_len-- )
+ {
+ int c1, diff;
+
+
+ c1 = *str1++;
+ c2 = *str2++;
+
+ diff = c1 - c2;
+ if ( diff )
+ return diff;
+ };
+
+ return -*str2;
+ }
+
+
+ /* find a given token/name, performing binary search */
+ static
+ int Find_Name( char* base,
+ int length,
+ const char** table,
+ int table_len )
+ {
+ int left, right;
+
+
+ left = 0;
+ right = table_len - 1;
+
+ while ( right - left > 1 )
+ {
+ int middle = left + ( ( right - left ) >> 1 );
+ int cmp;
+
+
+ cmp = lexico_strcmp( base, length, table[middle] );
+ if ( !cmp )
+ return middle;
+
+ if ( cmp < 0 )
+ right = middle;
+ else
+ left = middle;
+ }
+
+ if ( !lexico_strcmp( base, length, table[left ] ) )
+ return left;
+ if ( !lexico_strcmp( base, length, table[right] ) )
+ return right;
+
+ return -1;
+ }
+
+
+ /* read the small PFB section header */
+ static
+ FT_Error Read_PFB_Tag( FT_Stream stream,
+ FT_UShort* atag,
+ FT_ULong* asize )
+ {
+ FT_UShort tag;
+ FT_ULong size;
+ FT_Error error;
+
+
+ FT_TRACE2(( "Read_PFB_Tag: reading\n" ));
+
+ if ( ACCESS_Frame( 6L ) )
+ return error;
+
+ tag = GET_UShort();
+ size = GET_ULong();
+
+ FORGET_Frame();
+
+ *atag = tag;
+ *asize = ( ( size & 0xFF ) << 24 ) |
+ ( ( ( size >> 8 ) & 0xFF ) << 16 ) |
+ ( ( ( size >> 16 ) & 0xFF ) << 8 ) |
+ ( ( ( size >> 24 ) & 0xFF ) );
+
+ FT_TRACE2(( " tag = %04x\n", tag ));
+ FT_TRACE4(( " asze = %08x\n", size ));
+ FT_TRACE2(( " size = %08x\n", *asize ));
+
+ return T1_Err_Ok;
+ }
+
+
+ static
+ FT_Error grow( T1_Tokenizer tokzer )
+ {
+ FT_Error error;
+ FT_Long left_bytes;
+ FT_Memory memory = tokzer->memory;
+
+
+ left_bytes = tokzer->max - tokzer->limit;
+
+ if ( left_bytes > 0 )
+ {
+ FT_Stream stream = tokzer->stream;
+
+
+ if ( left_bytes > READ_BUFFER_INCREMENT )
+ left_bytes = READ_BUFFER_INCREMENT;
+
+ FT_TRACE2(( "Growing tokenizer buffer by %d bytes\n", left_bytes ));
+
+ if ( !REALLOC( tokzer->base, tokzer->limit,
+ tokzer->limit + left_bytes ) &&
+ !FILE_Read( tokzer->base + tokzer->limit, left_bytes ) )
+ tokzer->limit += left_bytes;
+ }
+ else
+ {
+ FT_ERROR(( "Unexpected end of Type1 fragment!\n" ));
+ error = T1_Err_Invalid_File_Format;
+ }
+
+ tokzer->error = error;
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1_decrypt */
+ /* */
+ /* <Description> */
+ /* Performs the Type 1 charstring decryption process. */
+ /* */
+ /* <Input> */
+ /* buffer :: The base address of the data to decrypt. */
+ /* length :: The number of bytes to decrypt (beginning from the base */
+ /* address. */
+ /* seed :: The encryption seed (4330 for charstrings). */
+ /* */
+ LOCAL_FUNC
+ void t1_decrypt( FT_Byte* buffer,
+ FT_Int length,
+ FT_UShort seed )
+ {
+ while ( length > 0 )
+ {
+ FT_Byte plain;
+
+
+ plain = ( *buffer ^ ( seed >> 8 ) );
+ seed = ( *buffer + seed ) * 52845 + 22719;
+ *buffer++ = plain;
+ length--;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* New_Tokenizer */
+ /* */
+ /* <Description> */
+ /* Creates a new tokenizer from a given input stream. This function */
+ /* automatically recognizes `pfa' or `pfb' files. The function */
+ /* Read_Token() can then be used to extract successive tokens from */
+ /* the stream. */
+ /* */
+ /* <Input> */
+ /* stream :: The input stream. */
+ /* */
+ /* <Output> */
+ /* tokenizer :: A handle to a new tokenizer object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function copies the stream handle within the object. Callers */
+ /* should not discard `stream'. This is done by the Done_Tokenizer() */
+ /* function. */
+ /* */
+ LOCAL_FUNC
+ FT_Error New_Tokenizer( FT_Stream stream,
+ T1_Tokenizer* tokenizer )
+ {
+ FT_Memory memory = stream->memory;
+ T1_Tokenizer tokzer;
+ FT_Error error;
+ FT_UShort tag;
+ FT_ULong size;
+
+ FT_Byte* tok_base;
+ FT_ULong tok_limit;
+ FT_ULong tok_max;
+
+
+ *tokenizer = 0;
+
+ /* allocate object */
+ if ( FILE_Seek( 0L ) ||
+ ALLOC( tokzer, sizeof ( *tokzer ) ) )
+ return error;
+
+ tokzer->stream = stream;
+ tokzer->memory = stream->memory;
+
+ tokzer->in_pfb = 0;
+ tokzer->in_private = 0;
+
+ tok_base = 0;
+ tok_limit = 0;
+ tok_max = stream->size;
+
+ error = Read_PFB_Tag( stream, &tag, &size );
+ if ( error )
+ goto Fail;
+
+ if ( tag != 0x8001 )
+ {
+ /* assume that it is a PFA file -- an error will be produced later */
+ /* if a character with value > 127 is encountered */
+
+ /* rewind to start of file */
+ if ( FILE_Seek( 0L ) )
+ goto Fail;
+
+ size = stream->size;
+ }
+ else
+ tokzer->in_pfb = 1;
+
+ /* if it is a memory-based resource, set up pointer */
+ if ( !stream->read )
+ {
+ tok_base = (FT_Byte*)stream->base + stream->pos;
+ tok_limit = size;
+ tok_max = size;
+
+ /* check that the `size' field is valid */
+ if ( FILE_Skip( size ) )
+ goto Fail;
+ }
+ else if ( tag == 0x8001 )
+ {
+ /* read segment in memory */
+ if ( ALLOC( tok_base, size ) )
+ goto Fail;
+
+ if ( FILE_Read( tok_base, size ) )
+ {
+ FREE( tok_base );
+ goto Fail;
+ }
+
+ tok_limit = size;
+ tok_max = size;
+ }
+
+ tokzer->base = tok_base;
+ tokzer->limit = tok_limit;
+ tokzer->max = tok_max;
+ tokzer->cursor = 0;
+
+ *tokenizer = tokzer;
+
+ /* now check font format; we must see `%!PS-AdobeFont-1' */
+ /* or `%!FontType' */
+ {
+ if ( 16 > tokzer->limit )
+ grow( tokzer );
+
+ if ( tokzer->limit <= 16 ||
+ ( strncmp( (const char*)tokzer->base, "%!PS-AdobeFont-1", 16 ) &&
+ strncmp( (const char*)tokzer->base, "%!FontType", 10 ) ) )
+ {
+ FT_TRACE2(( "[not a Type1 font]\n" ));
+ error = FT_Err_Unknown_File_Format;
+ goto Fail;
+ }
+ }
+ return T1_Err_Ok;
+
+ Fail:
+ FREE( tokzer->base );
+ FREE( tokzer );
+ return error;
+ }
+
+
+ /* return the value of an hexadecimal digit */
+ static
+ int hexa_value( char c )
+ {
+ unsigned int d;
+
+
+ d = (unsigned int)( c - '0' );
+ if ( d <= 9 )
+ return (int)d;
+
+ d = (unsigned int)( c - 'a' );
+ if ( d <= 5 )
+ return (int)( d + 10 );
+
+ d = (unsigned int)( c - 'A' );
+ if ( d <= 5 )
+ return (int)( d + 10 );
+
+ return -1;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Done_Tokenizer */
+ /* */
+ /* <Description> */
+ /* Closes a given tokenizer. This function will also close the */
+ /* stream embedded in the object. */
+ /* */
+ /* <Input> */
+ /* tokenizer :: The target tokenizer object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error Done_Tokenizer( T1_Tokenizer tokenizer )
+ {
+ FT_Memory memory = tokenizer->memory;
+
+
+ /* clear read buffer if needed (disk-based resources) */
+ if ( tokenizer->in_private || !tokenizer->stream->base )
+ FREE( tokenizer->base );
+
+ FREE( tokenizer );
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Open_PrivateDict */
+ /* */
+ /* <Description> */
+ /* This function must be called to set the tokenizer to the private */
+ /* section of the Type1 file. It recognizes automatically the */
+ /* the kind of eexec encryption used (ascii or binary). */
+ /* */
+ /* <Input> */
+ /* tokenizer :: The target tokenizer object. */
+ /* lenIV :: The value of the `lenIV' variable. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error Open_PrivateDict( T1_Tokenizer tokenizer )
+ {
+ T1_Tokenizer tokzer = tokenizer;
+ FT_Stream stream = tokzer->stream;
+ FT_Memory memory = tokzer->memory;
+ FT_Error error = 0;
+
+ FT_UShort tag;
+ FT_ULong size;
+
+ FT_Byte* private_dict;
+
+ /* are we already in the private dictionary ? */
+ if ( tokzer->in_private )
+ return 0;
+
+ if ( tokzer->in_pfb )
+ {
+ /* in the case of the PFB format, the private dictionary can be */
+ /* made of several segments. We thus first read the number of */
+ /* segments to compute the total size of the private dictionary */
+ /* then re-read them into memory. */
+ FT_Long start_pos = FILE_Pos();
+ FT_ULong private_dict_size = 0;
+
+
+ for (;;)
+ {
+ error = Read_PFB_Tag( stream, &tag, &size );
+ if ( error || tag != 0x8002 )
+ break;
+
+ private_dict_size += size;
+
+ if ( FILE_Skip( size ) )
+ goto Fail;
+ }
+
+ /* check that we have a private dictionary there */
+ /* and allocate private dictionary buffer */
+ if ( private_dict_size == 0 )
+ {
+ FT_ERROR(( "Open_PrivateDict:" ));
+ FT_ERROR(( " invalid private dictionary section\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ if ( ALLOC( private_dict, private_dict_size ) )
+ goto Fail;
+
+ /* read all sections into buffer */
+ if ( FILE_Seek( start_pos ) )
+ goto Fail_Private;
+
+ private_dict_size = 0;
+ for (;;)
+ {
+ error = Read_PFB_Tag( stream, &tag, &size );
+ if ( error || tag != 0x8002 )
+ {
+ error = 0;
+ break;
+ }
+
+ if ( FILE_Read( private_dict + private_dict_size, size ) )
+ goto Fail_Private;
+
+ private_dict_size += size;
+ }
+
+ /* we must free the field `tokzer.base' if we are in a disk-based */
+ /* PFB file. */
+ if ( stream->read )
+ FREE( tokzer->base );
+
+ tokzer->base = private_dict;
+ tokzer->cursor = 0;
+ tokzer->limit = private_dict_size;
+ tokzer->max = private_dict_size;
+ }
+ else
+ {
+ char* base;
+
+
+ /* we are in a PFA file; read each token until we find `eexec' */
+ while ( tokzer->token.kind2 != key_eexec )
+ {
+ error = Read_Token( tokzer );
+ if ( error )
+ goto Fail;
+ }
+
+ /* now determine whether the private dictionary is encoded in binary */
+ /* or hexadecimal ASCII format. */
+
+ /* we need to access the next 4 bytes (after the final \r following */
+ /* the `eexec' keyword); if they all are hexadecimal digits, then */
+ /* we have a case of ASCII storage. */
+ while ( tokzer->cursor + 5 > tokzer->limit )
+ {
+ error = grow( tokzer );
+ if ( error )
+ goto Fail;
+ }
+
+ /* skip whitespace/line feed after `eexec' */
+ base = (char*)tokzer->base + tokzer->cursor + 1;
+ if ( ( hexa_value( base[0] ) | hexa_value( base[1] ) |
+ hexa_value( base[2] ) | hexa_value( base[3] ) ) < 0 )
+ {
+ /* binary encoding -- `simply' read the stream */
+
+ /* if it is a memory-based resource, we need to allocate a new */
+ /* storage buffer for the private dictionary, as it must be */
+ /* decrypted later */
+ if ( stream->base )
+ {
+ size = stream->size - tokzer->cursor - 1; /* remaining bytes */
+
+ if ( ALLOC( private_dict, size ) ) /* alloc private dict buffer */
+ goto Fail;
+
+ /* copy eexec-encrypted bytes */
+ MEM_Copy( private_dict, tokzer->base + tokzer->cursor + 1, size );
+
+ /* reset pointers - forget about file mapping */
+ tokzer->base = private_dict;
+ tokzer->limit = size;
+ tokzer->max = size;
+ tokzer->cursor = 0;
+ }
+ /* On the opposite, for disk based resources, we simply grow */
+ /* the current buffer until its completion, and decrypt the */
+ /* bytes within it. In all cases, the `base' buffer will be */
+ /* discarded on DoneTokenizer if we are in the private dict. */
+ else
+ {
+ /* grow the read buffer to the full file */
+ while ( tokzer->limit < tokzer->max )
+ {
+ error = grow( tokenizer );
+ if ( error )
+ goto Fail;
+ }
+
+ /* set up cursor to first encrypted byte */
+ tokzer->cursor++;
+ }
+ }
+ else
+ {
+ /* ASCII hexadecimal encoding. This sucks... */
+ FT_Byte* write;
+ FT_Byte* cur;
+ FT_Byte* limit;
+ FT_Int count;
+
+
+ /* allocate a buffer, read each one byte at a time */
+ count = stream->size - tokzer->cursor;
+ size = count / 2;
+
+ if ( ALLOC( private_dict, size ) ) /* alloc private dict buffer */
+ goto Fail;
+
+ write = private_dict;
+ cur = tokzer->base + tokzer->cursor;
+ limit = tokzer->base + tokzer->limit;
+
+ /* read each bytes */
+ while ( count > 0 )
+ {
+ /* ensure that we can read the next 2 bytes! */
+ while ( cur + 2 > limit )
+ {
+ int cursor = cur - tokzer->base;
+
+
+ error = grow( tokzer );
+ if ( error )
+ goto Fail_Private;
+ cur = tokzer->base + cursor;
+ limit = tokzer->base + tokzer->limit;
+ }
+
+ /* check for new line */
+ if ( cur[0] == '\r' || cur[0] == '\n' )
+ {
+ cur++;
+ count--;
+ }
+ else
+ {
+ int hex1 = hexa_value(cur[0]);
+
+
+ /* exit if we have a non-hexadecimal digit which isn't */
+ /* a new-line character */
+ if ( hex1 < 0 )
+ break;
+
+ /* otherwise, store byte */
+ *write++ = ( hex1 << 4 ) | hexa_value( cur[1] );
+ cur += 2;
+ count -= 2;
+ }
+ }
+
+ /* get rid of old buffer in the case of disk-based resources */
+ if ( !stream->base )
+ FREE( tokzer->base );
+
+ /* set up pointers */
+ tokzer->base = private_dict;
+ tokzer->limit = size;
+ tokzer->max = size;
+ tokzer->cursor = 0;
+ }
+ }
+
+ /* finally, decrypt the private dictionary - and skip the lenIV bytes */
+ t1_decrypt( tokzer->base, tokzer->limit, 55665 );
+ tokzer->cursor += 4;
+
+ Fail:
+ return error;
+
+ Fail_Private:
+ FREE( private_dict );
+ goto Fail;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Read_Token */
+ /* */
+ /* <Description> */
+ /* Reads a new token from the current input stream. This function */
+ /* extracts a token from the font program until Open_PrivateDict() */
+ /* has been called. After this, it returns tokens from the */
+ /* (eexec-encrypted) private dictionary. */
+ /* */
+ /* <Input> */
+ /* tokenizer :: The target tokenizer object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Use the function Read_CharStrings() to read the binary charstrings */
+ /* from the private dict. */
+ /* */
+ LOCAL_FUNC
+ FT_Error Read_Token( T1_Tokenizer tokenizer )
+ {
+ T1_Tokenizer tok = tokenizer;
+ FT_Long cur, limit;
+ FT_Byte* base;
+ char c, starter, ender;
+ FT_Bool token_started;
+
+ T1_TokenType kind;
+
+
+ tok->error = T1_Err_Ok;
+ tok->token.kind = tok_any;
+
+ base = tok->base;
+ limit = tok->limit;
+ cur = tok->cursor;
+
+ token_started = 0;
+
+ for (;;)
+ {
+ if ( cur >= limit )
+ {
+ if ( grow( tok ) )
+ goto Exit;
+ base = tok->base;
+ limit = tok->limit;
+ }
+
+ c = (char)base[cur++];
+
+ /* check that we have an ASCII character */
+ if ( (FT_Byte)c > 127 )
+ {
+ FT_ERROR(( "Read_Token:" ));
+ FT_ERROR(( " unexpected binary data in Type1 fragment!\n" ));
+ tok->error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ switch ( c )
+ {
+ case '\r':
+ case '\n':
+ case ' ' :
+ case '\t': /* skip initial whitespace => skip to next */
+ if ( token_started )
+ {
+ /* possibly a name, keyword, wathever */
+ tok->token.kind = tok_any;
+ tok->token.len = cur-tok->token.start - 1;
+ goto Exit;
+ }
+ /* otherwise, skip everything */
+ break;
+
+ case '%': /* this is a comment -- skip everything */
+ for (;;)
+ {
+ FT_Int left = limit - cur;
+
+
+ while ( left > 0 )
+ {
+ c = (char)base[cur++];
+ if ( c == '\r' || c == '\n' )
+ goto Next;
+ left--;
+ }
+
+ if ( grow( tokenizer ) )
+ goto Exit;
+ base = tok->base;
+ limit = tok->limit;
+ }
+
+ case '(': /* a Postscript string */
+ kind = tok_string;
+ ender = ')';
+
+ L1:
+ if ( !token_started )
+ {
+ token_started = 1;
+ tok->token.start = cur - 1;
+ }
+
+ {
+ FT_Int nest_level = 1;
+
+
+ starter = c;
+ for (;;)
+ {
+ FT_Int left = limit - cur;
+
+
+ while ( left > 0 )
+ {
+ c = (char)base[cur++];
+
+ if ( c == starter )
+ nest_level++;
+
+ else if ( c == ender )
+ {
+ nest_level--;
+ if ( nest_level <= 0 )
+ {
+ tok->token.kind = kind;
+ tok->token.len = cur - tok->token.start;
+ goto Exit;
+ }
+ }
+ left--;
+ }
+
+ if ( grow( tok ) )
+ goto Exit;
+ base = tok->base;
+ limit = tok->limit;
+ }
+ }
+
+ case '[': /* a Postscript array */
+ if ( token_started )
+ goto Any_Token;
+
+ kind = tok_array;
+ ender = ']';
+ goto L1;
+ break;
+
+ case '{': /* a Postscript program */
+ if ( token_started )
+ goto Any_Token;
+
+ kind = tok_program;
+ ender = '}';
+ goto L1;
+ break;
+
+ case '<': /* a Postscript hex byte array? */
+ if ( token_started )
+ goto Any_Token;
+
+ kind = tok_hexarray;
+ ender = '>';
+ goto L1;
+ break;
+
+ case '0': /* any number */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if ( token_started )
+ goto Next;
+
+ tok->token.kind = tok_number;
+ token_started = 1;
+ tok->token.start = cur - 1;
+
+ L2:
+ for (;;)
+ {
+ FT_Int left = limit-cur;
+
+
+ while ( left > 0 )
+ {
+ c = (char)base[cur++];
+
+ switch ( c )
+ {
+ case '[': /* ] */
+ case '{': /* } */
+ case '(': /* ) */
+ case '<':
+ case '/':
+ goto Any_Token;
+
+ case ' ':
+ case '\r':
+ case '\t':
+ case '\n':
+ tok->token.len = cur - tok->token.start - 1;
+ goto Exit;
+
+ default:
+ ;
+ }
+ left--;
+ }
+
+ if ( grow( tok ) )
+ goto Exit;
+ base = tok->base;
+ limit = tok->limit;
+ }
+
+ case '.': /* maybe a number */
+ case '-':
+ case '+':
+ if ( token_started )
+ goto Next;
+
+ token_started = 1;
+ tok->token.start = cur - 1;
+
+ for (;;)
+ {
+ FT_Int left = limit - cur;
+
+
+ if ( left > 0 )
+ {
+ /* test for any following digit, interpreted as number */
+ c = (char)base[cur];
+ tok->token.kind = ( c >= '0' && c <= '9' ? tok_number : tok_any );
+ goto L2;
+ }
+
+ if ( grow( tok ) )
+ goto Exit;
+ base = tok->base;
+ limit = tok->limit;
+ }
+
+ case '/': /* maybe an immediate name */
+ if ( !token_started )
+ {
+ token_started = 1;
+ tok->token.start = cur - 1;
+
+ for (;;)
+ {
+ FT_Int left = limit - cur;
+
+
+ if ( left > 0 )
+ {
+ /* test for single '/', interpreted as garbage */
+ c = (char)base[cur];
+ tok->token.kind = ( c == ' ' || c == '\t' ||
+ c == '\r' || c == '\n' ) ? tok_any
+ : tok_immediate;
+ goto L2;
+ }
+
+ if ( grow( tok ) )
+ goto Exit;
+ base = tok->base;
+ limit = tok->limit;
+ }
+ }
+ else
+ {
+ Any_Token: /* possibly a name or wathever */
+ cur--;
+ tok->token.len = cur - tok->token.start;
+ goto Exit;
+ }
+
+ default:
+ if ( !token_started )
+ {
+ token_started = 1;
+ tok->token.start = cur - 1;
+ }
+ }
+
+ Next:
+ ;
+ }
+
+ Exit:
+ tok->cursor = cur;
+
+ if ( !tok->error )
+ {
+ /* now, tries to match keywords and immediate names */
+ FT_Int index;
+
+
+ switch ( tok->token.kind )
+ {
+ case tok_immediate: /* immediate name */
+ index = Find_Name( (char*)( tok->base + tok->token.start + 1 ),
+ tok->token.len - 1,
+ t1_immediates,
+ imm_max - imm_first_ );
+ tok->token.kind2 = ( index >= 0 )
+ ? (T1_TokenType)( imm_first_ + index )
+ : tok_error;
+ break;
+
+ case tok_any: /* test for keyword */
+ index = Find_Name( (char*)( tok->base + tok->token.start ),
+ tok->token.len,
+ t1_keywords,
+ key_max - key_first_ );
+ if ( index >= 0 )
+ {
+ tok->token.kind = tok_keyword;
+ tok->token.kind2 = (T1_TokenType)( key_first_ + index );
+ }
+ else
+ tok->token.kind2 = tok_error;
+ break;
+
+ default:
+ tok->token.kind2 = tok_error;
+ }
+ }
+ return tokenizer->error;
+ }
+
+
+#if 0
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Read_CharStrings */
+ /* */
+ /* <Description> */
+ /* Reads a charstrings element from the current input stream. These */
+ /* are binary bytes that encode each individual glyph outline. */
+ /* */
+ /* The caller is responsible for skipping the `lenIV' bytes at the */
+ /* start of the record. */
+ /* */
+ /* <Input> */
+ /* tokenizer :: The target tokenizer object. */
+ /* num_chars :: The number of binary bytes to read. */
+ /* */
+ /* <Output> */
+ /* buffer :: The target array of bytes. These are */
+ /* eexec-decrypted. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Use the function Read_CharStrings() to read binary charstrings */
+ /* from the private dict. */
+ /* */
+ LOCAL_FUNC
+ FT_Error Read_CharStrings( T1_Tokenizer tokenizer,
+ FT_Int num_chars,
+ FT_Byte* buffer )
+ {
+ for (;;)
+ {
+ FT_Int left = tokenizer->limit - tokenizer->cursor;
+
+
+ if ( left >= num_chars )
+ {
+ MEM_Copy( buffer, tokenizer->base + tokenizer->cursor, num_chars );
+ t1_decrypt( buffer, num_chars, 4330 );
+ tokenizer->cursor += num_chars;
+ return T1_Err_Ok;
+ }
+
+ if ( grow( tokenizer ) )
+ return tokenizer->error;
+ }
+ }
+
+#endif /* 0 */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* t1tokens.h */
+/* */
+/* Type 1 tokenizer (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T1TOKENS_H
+#define T1TOKENS_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1objs.h"
+
+#else
+
+#include <type1/t1objs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /* enum value of first keyword */
+#define key_first_ 100
+
+ /* enum value of first immediate name */
+#define imm_first_ 200
+
+
+ typedef enum T1_TokenType_
+ {
+ tok_error = 0,
+
+ tok_eof, /* end of file */
+
+ /* simple token types */
+
+ tok_keyword, /* keyword */
+ tok_number, /* number (integer or real) */
+ tok_string, /* postscript string */
+ tok_program, /* postscript program */
+ tok_immediate, /* any immediate name */
+ tok_array, /* matrix, array, etc.. */
+ tok_hexarray, /* array of hexadecimal nibbles */
+ tok_any, /* anything else */
+
+ /* Postscript keywords -- placed in lexicographical order */
+
+ key_RD_alternate = key_first_, /* `-|' = alternate form of RD */
+ key_ExpertEncoding,
+ key_ND,
+ key_NP,
+ key_RD,
+ key_StandardEncoding,
+ key_array,
+ key_begin,
+ key_closefile,
+ key_currentdict,
+ key_currentfile,
+ key_def,
+ key_dict,
+ key_dup,
+ key_eexec,
+ key_end,
+ key_execonly,
+ key_false,
+ key_for,
+ key_index,
+ key_noaccess,
+ key_put,
+ key_readonly,
+ key_true,
+ key_userdict,
+ key_NP_alternate, /* `|' = alternate form of NP */
+ key_ND_alternate, /* `|-' = alternate form of ND */
+
+ key_max, /* always keep this value there */
+
+ /* Postscript immediate names -- other names will be ignored, except */
+ /* in charstrings */
+
+ imm_RD_alternate = imm_first_, /* `-|' = alternate form of RD */
+ imm_notdef, /* `/.notdef' immediate */
+ imm_BlendAxisTypes,
+ imm_BlueFuzz,
+ imm_BlueScale,
+ imm_BlueShift,
+ imm_BlueValues,
+ imm_CharStrings,
+ imm_Encoding,
+ imm_FamilyBlues,
+ imm_FamilyName,
+ imm_FamilyOtherBlues,
+ imm_FID,
+ imm_FontBBox,
+ imm_FontID,
+ imm_FontInfo,
+ imm_FontMatrix,
+ imm_FontName,
+ imm_FontType,
+ imm_ForceBold,
+ imm_FullName,
+ imm_ItalicAngle,
+ imm_LanguageGroup,
+ imm_Metrics,
+ imm_MinFeature,
+ imm_ND,
+ imm_NP,
+ imm_Notice,
+ imm_OtherBlues,
+ imm_OtherSubrs,
+ imm_PaintType,
+ imm_Private,
+ imm_RD,
+ imm_RndStemUp,
+ imm_StdHW,
+ imm_StdVW,
+ imm_StemSnapH,
+ imm_StemSnapV,
+ imm_StrokeWidth,
+ imm_Subrs,
+ imm_UnderlinePosition,
+ imm_UnderlineThickness,
+ imm_UniqueID,
+ imm_Weight,
+
+ imm_isFixedPitch,
+ imm_lenIV,
+ imm_password,
+ imm_version,
+
+ imm_NP_alternate, /* `|' = alternate form of NP */
+ imm_ND_alternate, /* `|-' = alternate form of ND */
+
+ imm_max /* always keep this value here */
+
+ } T1_TokenType;
+
+
+ /* these arrays are visible for debugging purposes */
+ extern const char* t1_keywords[];
+ extern const char* t1_immediates[];
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_Token */
+ /* */
+ /* <Description> */
+ /* A structure used to describe a token in the current input stream. */
+ /* Note that the Type1 driver doesn't try to interpret tokens until */
+ /* it really needs to. */
+ /* */
+ /* <Fields> */
+ /* kind :: The token type. Describes the token to the loader. */
+ /* */
+ /* kind2 :: Detailed token type. */
+ /* */
+ /* start :: The index of the first character of token in the input */
+ /* stream. */
+ /* */
+ /* len :: The length of the token in characters. */
+ /* */
+ typedef struct T1_Token_
+ {
+ T1_TokenType kind; /* simple type */
+ T1_TokenType kind2; /* detailed type */
+ FT_Int start; /* index of first token character */
+ FT_Int len; /* length of token in chars */
+
+ } T1_Token;
+
+
+ typedef struct T1_TokenParser_
+ {
+ FT_Memory memory;
+ FT_Stream stream;
+
+ FT_Bool in_pfb; /* true if PFB file, PFA otherwise */
+ FT_Bool in_private; /* true if in private dictionary */
+
+ FT_Byte* base; /* base address of current read buffer */
+ FT_Long cursor; /* current position in read buffer */
+ FT_Long limit; /* limit of current read buffer */
+ FT_Long max; /* maximum size of read buffer */
+
+ FT_Error error; /* last error */
+ T1_Token token; /* last token read */
+
+ } T1_TokenParser;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_Tokenizer */
+ /* */
+ /* <Description> */
+ /* A handle to an object used to extract tokens from the input. The */
+ /* object is able to perform PFA/PFB recognition, eexec decryption of */
+ /* the private dictionary, as well as eexec decryption of the */
+ /* charstrings. */
+ /* */
+ typedef T1_TokenParser* T1_Tokenizer;
+
+
+ LOCAL_DEF
+ FT_Error New_Tokenizer( FT_Stream stream,
+ T1_Tokenizer* tokenizer );
+
+ LOCAL_DEF
+ FT_Error Done_Tokenizer( T1_Tokenizer tokenizer );
+
+ LOCAL_DEF
+ FT_Error Open_PrivateDict( T1_Tokenizer tokenizer );
+
+ LOCAL_DEF
+ FT_Error Read_Token( T1_Tokenizer tokenizer );
+
+
+#if 0
+ LOCAL_DEF
+ FT_Error Read_CharStrings( T1_Tokenizer tokenizer,
+ FT_Int num_chars,
+ FT_Byte* buffer );
+#endif /* 0 */
+
+ LOCAL_DEF
+ void t1_decrypt( FT_Byte* buffer,
+ FT_Int length,
+ FT_UShort seed );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* T1TOKENS_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* type1.c */
+/* */
+/* FreeType Type 1 driver component (body only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1driver.c"
+#include "t1objs.c"
+#include "t1load.c"
+#include "t1gload.c"
+#include "t1tokens.c"
+#include "t1parse.c"
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+#include "t1hinter.c"
+#endif
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include "t1afm.c"
+#endif
+
+#else /* FT_FLAT_COMPILE */
+
+#include <type1/t1driver.c>
+#include <type1/t1objs.c>
+#include <type1/t1load.c>
+#include <type1/t1gload.c>
+#include <type1/t1tokens.c>
+#include <type1/t1parse.c>
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+#include <type1/t1hinter.c>
+#endif
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include <type1/t1afm.c>
+#endif
+
+#endif /* FT_FLAT_COMPILE */
+
+
+/* END */
--- /dev/null
+This directory contains an experimental Type 1 driver that will ultimately
+replace the "official" one in "src/type1".
+
+This driver doesn't provide a mini Postscript interpreter, but uses
+pattern matching in order to load data from fonts. It works better and
+faster than the official driver, but will replace it only when we finish
+the auto-hinting module..
+
+You don't need to compile it to support Type 1 fonts, the driver should
+co-exist peacefully with the rest of the engine however..
--- /dev/null
+make_module_list: add_type1_driver
+
+add_type1_driver:
+ $(OPEN_DRIVER)t1_driver_class$(CLOSE_DRIVER)
+ $(ECHO_DRIVER)type1 $(ECHO_DRIVER_DESC)Postscript font files with extension *.pfa or *.pfb$(ECHO_DRIVER_DONE)
+
+# EOF
--- /dev/null
+#
+# FreeType 2 Type1z driver configuration rules
+#
+
+
+# Copyright 1996-2000 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# Type1z driver directory
+#
+T1Z_DIR := $(SRC_)type1z
+T1Z_DIR_ := $(T1Z_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+T1Z_COMPILE := $(FT_COMPILE)
+
+
+# Type1 driver sources (i.e., C files)
+#
+T1Z_DRV_SRC := $(T1Z_DIR_)z1parse.c \
+ $(T1Z_DIR_)z1load.c \
+ $(T1Z_DIR_)z1driver.c \
+ $(T1Z_DIR_)z1afm.c \
+ $(T1Z_DIR_)z1gload.c \
+ $(T1Z_DIR_)z1objs.c
+
+# Type1 driver headers
+#
+T1Z_DRV_H := $(T1Z_DRV_SRC:%.c=%.h) \
+ $(T1Z_DIR_)z1tokens.h
+
+
+# Type1z driver object(s)
+#
+# T1Z_DRV_OBJ_M is used during `multi' builds
+# T1Z_DRV_OBJ_S is used during `single' builds
+#
+T1Z_DRV_OBJ_M := $(T1Z_DRV_SRC:$(T1Z_DIR_)%.c=$(OBJ_)%.$O)
+T1Z_DRV_OBJ_S := $(OBJ_)type1z.$O
+
+# Type1z driver source file for single build
+#
+T1Z_DRV_SRC_S := $(T1Z_DIR_)type1z.c
+
+
+# Type1z driver - single object
+#
+$(T1Z_DRV_OBJ_S): $(T1Z_DRV_SRC_S) $(T1Z_DRV_SRC) $(FREETYPE_H) $(T1Z_DRV_H)
+ $(T1Z_COMPILE) $T$@ $(T1Z_DRV_SRC_S)
+
+
+# Type1z driver - multiple objects
+#
+$(OBJ_)%.$O: $(T1Z_DIR_)%.c $(FREETYPE_H) $(T1Z_DRV_H)
+ $(T1Z_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(T1Z_DRV_OBJ_S)
+DRV_OBJS_M += $(T1Z_DRV_OBJ_M)
+
+# EOF
--- /dev/null
+/***************************************************************************/
+/* */
+/* type1z.c */
+/* */
+/* FreeType experimental Type 1 driver component (body only). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1parse.c"
+#include "z1load.c"
+#include "z1objs.c"
+#include "z1driver.c"
+#include "z1gload.c"
+
+#ifndef Z1_CONFIG_OPTION_NO_AFM
+#include "z1afm.c"
+#endif
+
+#else /* FT_FLAT_COMPILE */
+
+#include <type1z/z1parse.c>
+#include <type1z/z1load.c>
+#include <type1z/z1objs.c>
+#include <type1z/z1driver.c>
+#include <type1z/z1gload.c>
+
+#ifndef Z1_CONFIG_OPTION_NO_AFM
+#include <type1z/z1afm.c>
+#endif
+
+#endif /* FT_FLAT_COMPILE */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* z1afm.c */
+/* */
+/* AFM support for Type 1 fonts (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1afm.h"
+
+#else
+
+#include <type1z/z1afm.h>
+
+#endif
+
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1types.h>
+
+#include <stdlib.h> /* for qsort() */
+#include <string.h> /* for strcmp() */
+#include <ctype.h> /* for isalnum() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_z1afm
+
+
+ LOCAL_FUNC
+ void Z1_Done_AFM( FT_Memory memory,
+ Z1_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 ) ( isalnum( c ) || \
+ 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 && !isdigit( *p ) )
+ {
+ sign = 1;
+ if ( *p == '-' )
+ sign = -1;
+
+ p++;
+ }
+
+ while ( p < limit && isdigit( *p ) )
+ {
+ 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 )
+ {
+ Z1_Kern_Pair* pair1 = (Z1_Kern_Pair*)a;
+ Z1_Kern_Pair* pair2 = (Z1_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 Z1_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;
+ Z1_Kern_Pair* pair;
+ T1_Font* type1 = &((T1_Face)t1_face)->type1;
+ Z1_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, Z1_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 ( Z1_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 Z1_Get_Kerning( Z1_AFM* afm,
+ FT_UInt glyph1,
+ FT_UInt glyph2,
+ FT_Vector* kerning )
+ {
+ Z1_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;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* z1afm.h */
+/* */
+/* AFM support for Type 1 fonts (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef Z1AFM_H
+#define Z1AFM_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1objs.h"
+
+#else
+
+#include <type1z/z1objs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ typedef struct Z1_Kern_Pair_
+ {
+ FT_UInt glyph1;
+ FT_UInt glyph2;
+ FT_Vector kerning;
+
+ } Z1_Kern_Pair;
+
+
+ typedef struct Z1_AFM_
+ {
+ FT_Int num_pairs;
+ Z1_Kern_Pair* kern_pairs;
+
+ } Z1_AFM;
+
+
+ LOCAL_DEF
+ FT_Error Z1_Read_AFM( FT_Face face,
+ FT_Stream stream );
+
+ LOCAL_DEF
+ void Z1_Done_AFM( FT_Memory memory,
+ Z1_AFM* afm );
+
+ LOCAL_DEF
+ void Z1_Get_Kerning( Z1_AFM* afm,
+ FT_UInt glyph1,
+ FT_UInt glyph2,
+ FT_Vector* kerning );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* Z1AFM_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* z1driver.c */
+/* */
+/* Experimental Type 1 driver interface (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1driver.h"
+#include "z1gload.h"
+#include "z1load.h"
+#include "z1afm.h"
+
+#else
+
+#include <type1z/z1driver.h>
+#include <type1z/z1gload.h>
+#include <type1z/z1load.h>
+#include <type1z/z1afm.h>
+
+#endif
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/psnames.h>
+
+#include <string.h> /* for strcmp() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_z1driver
+
+
+ static
+ FT_Error get_z1_glyph_name( T1_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max )
+ {
+ FT_String* gname;
+
+
+ gname = face->type1.glyph_names[glyph_index];
+
+ if ( buffer_max > 0 )
+ {
+ FT_UInt len = strlen( gname );
+
+
+ if (len >= buffer_max)
+ len = buffer_max - 1;
+
+ MEM_Copy( buffer, gname, len );
+ ((FT_Byte*)buffer)[len] = 0;
+ }
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Interface */
+ /* */
+ /* <Description> */
+ /* Each driver can provide one or more extensions to the base */
+ /* FreeType API. These can be used to access format specific */
+ /* features (e.g., all TrueType/OpenType resources share a common */
+ /* file structure and common tables which can be accessed through the */
+ /* `sfnt' interface), or more simply generic ones (e.g., the */
+ /* `postscript names' interface which can be used to retrieve the */
+ /* PostScript name of a given glyph index). */
+ /* */
+ /* <InOut> */
+ /* driver :: A handle to a driver object. */
+ /* */
+ /* <Input> */
+ /* interface :: A string designing the interface. Examples are */
+ /* `sfnt', `post_names', `charmaps', etc. */
+ /* */
+ /* <Return> */
+ /* A typeless pointer to the extension's interface (normally a table */
+ /* of function pointers). Returns NULL if the requested extension */
+ /* isn't available (i.e., wasn't compiled in the driver at build */
+ /* time). */
+ /* */
+ static
+ FT_Module_Interface Get_Interface( FT_Driver driver,
+ const FT_String* interface )
+ {
+ FT_UNUSED( driver );
+ FT_UNUSED( interface );
+
+ if ( strcmp( (const char*)interface, "glyph_name" ) == 0 )
+ return (FT_Module_Interface)get_z1_glyph_name;
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+ if ( strcmp( (const char*)interface, "get_mm" ) == 0 )
+ return (FT_Module_Interface)Z1_Get_Multi_Master;
+
+ if ( strcmp( (const char*)interface, "set_mm_design") == 0 )
+ return (FT_Module_Interface)Z1_Set_MM_Design;
+
+ if ( strcmp( (const char*)interface, "set_mm_blend") == 0 )
+ return (FT_Module_Interface)Z1_Set_MM_Blend;
+#endif
+ return 0;
+ }
+
+
+#ifndef Z1_CONFIG_OPTION_NO_AFM
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Kerning */
+ /* */
+ /* <Description> */
+ /* A driver method used to return the kerning vector between two */
+ /* glyphs of the same face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* left_glyph :: The index of the left glyph in the kern pair. */
+ /* */
+ /* right_glyph :: The index of the right glyph in the kern pair. */
+ /* */
+ /* <Output> */
+ /* kerning :: The kerning vector. This is in font units for */
+ /* scalable formats, and in pixels for fixed-sizes */
+ /* formats. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only horizontal layouts (left-to-right & right-to-left) are */
+ /* supported by this function. Other layouts, or more sophisticated */
+ /* kernings are out of scope of this method (the basic driver */
+ /* interface is meant to be simple). */
+ /* */
+ /* They can be implemented by format-specific interfaces. */
+ /* */
+ static
+ FT_Error Get_Kerning( T1_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_Vector* kerning )
+ {
+ Z1_AFM* afm;
+
+
+ kerning->x = 0;
+ kerning->y = 0;
+
+ afm = (Z1_AFM*)face->afm_data;
+ if ( afm )
+ Z1_Get_Kerning( afm, left_glyph, right_glyph, kerning );
+
+ return T1_Err_Ok;
+ }
+
+
+#endif /* T1_CONFIG_OPTION_NO_AFM */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Char_Index */
+ /* */
+ /* <Description> */
+ /* Uses a charmap to return a given character code's glyph index. */
+ /* */
+ /* <Input> */
+ /* charmap :: A handle to the source charmap object. */
+ /* charcode :: The character code. */
+ /* */
+ /* <Return> */
+ /* Glyph index. 0 means `undefined character code'. */
+ /* */
+ static
+ FT_UInt Get_Char_Index( FT_CharMap charmap,
+ FT_Long charcode )
+ {
+ T1_Face face;
+ FT_UInt result = 0;
+ PSNames_Interface* psnames;
+
+
+ face = (T1_Face)charmap->face;
+ psnames = (PSNames_Interface*)face->psnames;
+ if ( psnames )
+ switch ( charmap->encoding )
+ {
+ /*******************************************************************/
+ /* */
+ /* Unicode encoding support */
+ /* */
+ case ft_encoding_unicode:
+ /* use the `PSNames' module to synthetize the Unicode charmap */
+ result = psnames->lookup_unicode( &face->unicode_map,
+ (FT_ULong)charcode );
+
+ /* the function returns 0xFFFF if the Unicode charcode has */
+ /* no corresponding glyph */
+ if ( result == 0xFFFF )
+ result = 0;
+ goto Exit;
+
+ /*******************************************************************/
+ /* */
+ /* Custom Type 1 encoding */
+ /* */
+ case ft_encoding_adobe_custom:
+ {
+ T1_Encoding* encoding = &face->type1.encoding;
+
+
+ if ( charcode >= encoding->code_first &&
+ charcode <= encoding->code_last )
+ result = encoding->char_index[charcode];
+ goto Exit;
+ }
+
+ /*******************************************************************/
+ /* */
+ /* Adobe Standard & Expert encoding support */
+ /* */
+ default:
+ if ( charcode < 256 )
+ {
+ FT_UInt code;
+ FT_Int n;
+ const char* glyph_name;
+
+
+ code = psnames->adobe_std_encoding[charcode];
+ if ( charmap->encoding == ft_encoding_adobe_expert )
+ code = psnames->adobe_expert_encoding[charcode];
+
+ glyph_name = psnames->adobe_std_strings( code );
+ if ( !glyph_name )
+ break;
+
+ for ( n = 0; n < face->type1.num_glyphs; n++ )
+ {
+ const char* gname = face->type1.glyph_names[n];
+
+
+ if ( gname && gname[0] == glyph_name[0] &&
+ strcmp( gname, glyph_name ) == 0 )
+ {
+ result = n;
+ break;
+ }
+ }
+ }
+ }
+ Exit:
+ return result;
+ }
+
+
+ const FT_Driver_Class t1_driver_class =
+ {
+ {
+ ft_module_font_driver | ft_module_driver_scalable,
+ sizeof( FT_DriverRec ),
+
+ "type1",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* format interface */
+
+ (FT_Module_Constructor)Z1_Init_Driver,
+ (FT_Module_Destructor) Z1_Done_Driver,
+ (FT_Module_Requester) Get_Interface,
+ },
+
+ sizeof( T1_FaceRec ),
+ sizeof( Z1_SizeRec ),
+ sizeof( Z1_GlyphSlotRec ),
+
+ (FTDriver_initFace) Z1_Init_Face,
+ (FTDriver_doneFace) Z1_Done_Face,
+ (FTDriver_initSize) 0,
+ (FTDriver_doneSize) 0,
+ (FTDriver_initGlyphSlot)0,
+ (FTDriver_doneGlyphSlot)0,
+
+ (FTDriver_setCharSizes) 0,
+ (FTDriver_setPixelSizes)0,
+ (FTDriver_loadGlyph) Z1_Load_Glyph,
+ (FTDriver_getCharIndex) Get_Char_Index,
+
+#ifdef Z1_CONFIG_OPTION_NO_AFM
+ (FTDriver_getKerning) 0,
+ (FTDriver_attachFile) 0,
+#else
+ (FTDriver_getKerning) Get_Kerning,
+ (FTDriver_attachFile) Z1_Read_AFM,
+#endif
+ (FTDriver_getAdvances) 0
+ };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+ EXPORT_FUNC( const FT_Driver_Class* ) getDriverClass( void )
+ {
+ return &t1z_driver_class;
+ }
+
+#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* z1driver.h */
+/* */
+/* High-level experimental Type 1 driver interface (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef Z1DRIVER_H
+#define Z1DRIVER_H
+
+#include <freetype/internal/ftdriver.h>
+
+ FT_EXPORT_VAR( const FT_Driver_Class ) t1_driver_class;
+
+#endif /* Z1DRIVER_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* z1gload.c */
+/* */
+/* Experimental Type 1 Glyph Loader (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1gload.h"
+
+#else
+
+#include <type1z/z1gload.h>
+
+#endif
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/ftoutln.h>
+
+#include <string.h> /* for strcmp() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_z1gload
+
+
+ typedef enum Z1_Operator_
+ {
+ op_none = 0,
+ op_endchar,
+ op_hsbw,
+ op_seac,
+ op_sbw,
+ op_closepath,
+ op_hlineto,
+ op_hmoveto,
+ op_hvcurveto,
+ op_rlineto,
+ op_rmoveto,
+ op_rrcurveto,
+ op_vhcurveto,
+ op_vlineto,
+ op_vmoveto,
+ op_dotsection,
+ op_hstem,
+ op_hstem3,
+ op_vstem,
+ op_vstem3,
+ op_div,
+ op_callothersubr,
+ op_callsubr,
+ op_pop,
+ op_return,
+ op_setcurrentpoint,
+
+ op_max /* never remove this one */
+
+ } Z1_Operator;
+
+ static
+ const FT_Int t1_args_count[op_max] =
+ {
+ 0, /* none */
+ 0, /* endchar */
+ 2, /* hsbw */
+ 5, /* seac */
+ 4, /* sbw */
+ 0, /* closepath */
+ 1, /* hlineto */
+ 1, /* hmoveto */
+ 4, /* hvcurveto */
+ 2, /* rlineto */
+ 2, /* rmoveto */
+ 6, /* rrcurveto */
+ 4, /* vhcurveto */
+ 1, /* vlineto */
+ 1, /* vmoveto */
+ 0, /* dotsection */
+ 2, /* hstem */
+ 6, /* hstem3 */
+ 2, /* vstem */
+ 6, /* vstem3 */
+ 2, /* div */
+ -1, /* callothersubr */
+ 1, /* callsubr */
+ 0, /* pop */
+ 0, /* return */
+ 2 /* setcurrentpoint */
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** GENERIC CHARSTRING PARSING *********/
+ /********** *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Z1_Init_Builder */
+ /* */
+ /* <Description> */
+ /* Initializes a given glyph builder. */
+ /* */
+ /* <InOut> */
+ /* builder :: A pointer to the glyph builder to initialize. */
+ /* */
+ /* <Input> */
+ /* face :: The current face object. */
+ /* */
+ /* size :: The current size object. */
+ /* */
+ /* glyph :: The current glyph object. */
+ /* */
+ LOCAL_FUNC
+ void Z1_Init_Builder( Z1_Builder* builder,
+ T1_Face face,
+ Z1_Size size,
+ Z1_GlyphSlot glyph )
+ {
+ builder->path_begun = 0;
+ builder->load_points = 1;
+
+ builder->face = face;
+ builder->glyph = glyph;
+ builder->memory = face->root.memory;
+
+ if ( glyph )
+ {
+ FT_GlyphLoader* loader = glyph->root.loader;
+
+
+ builder->loader = loader;
+ builder->current = &loader->current.outline;
+ builder->base = &loader->base.outline;
+
+ FT_GlyphLoader_Rewind( loader );
+ }
+
+ if ( size )
+ {
+ builder->scale_x = size->root.metrics.x_scale;
+ builder->scale_y = size->root.metrics.y_scale;
+ }
+
+ builder->pos_x = 0;
+ builder->pos_y = 0;
+
+ builder->left_bearing.x = 0;
+ builder->left_bearing.y = 0;
+ builder->advance.x = 0;
+ builder->advance.y = 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Z1_Done_Builder */
+ /* */
+ /* <Description> */
+ /* Finalizes a given glyph builder. Its contents can still be used */
+ /* after the call, but the function saves important information */
+ /* within the corresponding glyph slot. */
+ /* */
+ /* <Input> */
+ /* builder :: A pointer to the glyph builder to finalize. */
+ /* */
+ LOCAL_FUNC
+ void Z1_Done_Builder( Z1_Builder* builder )
+ {
+ Z1_GlyphSlot glyph = builder->glyph;
+
+
+ if ( glyph )
+ glyph->root.outline = *builder->base;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Z1_Init_Decoder */
+ /* */
+ /* <Description> */
+ /* Initializes a given glyph decoder. */
+ /* */
+ /* <InOut> */
+ /* decoder :: A pointer to the glyph builder to initialize. */
+ /* */
+ LOCAL_FUNC
+ void Z1_Init_Decoder( Z1_Decoder* decoder )
+ {
+ decoder->top = 0;
+ decoder->zone = 0;
+ decoder->flex_state = 0;
+ decoder->num_flex_vectors = 0;
+ decoder->blend = 0;
+
+ /* Clear loader */
+ MEM_Set( &decoder->builder, 0, sizeof ( decoder->builder ) );
+ }
+
+
+ /* check that there is enough space for `count' more points */
+ static
+ FT_Error check_points( Z1_Builder* builder,
+ FT_Int count )
+ {
+ return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
+ }
+
+
+ /* add a new point; do not check space */
+ static
+ void add_point( Z1_Builder* builder,
+ FT_Pos x,
+ FT_Pos y,
+ FT_Byte flag )
+ {
+ FT_Outline* outline = builder->current;
+
+
+ if ( builder->load_points )
+ {
+ FT_Vector* point = outline->points + outline->n_points;
+ FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
+
+
+ point->x = x;
+ point->y = y;
+ *control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic;
+
+ builder->last = *point;
+ }
+
+ outline->n_points++;
+ }
+
+
+ /* check space for a new on-curve point, then add it */
+ static
+ FT_Error add_point1( Z1_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ FT_Error error;
+
+
+ error = check_points( builder, 1 );
+ if ( !error )
+ add_point( builder, x, y, 1 );
+
+ return error;
+ }
+
+
+ /* check space for a new contour, then add it */
+ static
+ FT_Error add_contour( Z1_Builder* builder )
+ {
+ FT_Outline* outline = builder->current;
+ FT_Error error;
+
+
+ if ( !builder->load_points )
+ {
+ outline->n_contours++;
+ return FT_Err_Ok;
+ }
+
+ /* reallocate contours array if necessary */
+ error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
+ if ( !error )
+ {
+ if ( outline->n_contours > 0 )
+ outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+
+ outline->n_contours++;
+ }
+
+ return error;
+ }
+
+
+ /* if a path was begun, add its first on-curve point */
+ static
+ FT_Error start_point( Z1_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ /* test whether we are building a new contour */
+ if ( !builder->path_begun )
+ {
+ FT_Error error;
+
+
+ builder->path_begun = 1;
+ error = add_contour( builder );
+ if ( error )
+ return error;
+ }
+ return add_point1( builder, x, y );
+ }
+
+
+ /* close the current contour */
+ static
+ void close_contour( Z1_Builder* builder )
+ {
+ FT_Outline* outline = builder->current;
+
+
+ /* XXX: we must not include the last point in the path if it */
+ /* is located on the first point */
+ if ( outline->n_points > 1 )
+ {
+ FT_Int first = 0;
+ FT_Vector* p1 = outline->points + first;
+ FT_Vector* p2 = outline->points + outline->n_points-1;
+
+
+ if ( outline->n_contours > 1 )
+ {
+ first = outline->contours[outline->n_contours - 2] + 1;
+ p1 = outline->points + first;
+ }
+
+ if ( p1->x == p2->x && p1->y == p2->y )
+ outline->n_points--;
+ }
+
+ if ( outline->n_contours > 0 )
+ outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* lookup_glyph_by_stdcharcode */
+ /* */
+ /* <Description> */
+ /* Looks up a given glyph by its StandardEncoding charcode. Used */
+ /* to implement the SEAC Type 1 operator. */
+ /* */
+ /* <Input> */
+ /* face :: The current face object. */
+ /* */
+ /* charcode :: The character code to look for. */
+ /* */
+ /* <Return> */
+ /* A glyph index in the font face. Returns -1 if the corresponding */
+ /* glyph wasn't found. */
+ /* */
+ static
+ FT_Int lookup_glyph_by_stdcharcode( T1_Face face,
+ FT_Int charcode )
+ {
+ FT_Int n;
+ const FT_String* glyph_name;
+ PSNames_Interface* psnames = (PSNames_Interface*)face->psnames;
+
+
+ /* check range of standard char code */
+ if ( charcode < 0 || charcode > 255 )
+ return -1;
+
+ glyph_name = psnames->adobe_std_strings(
+ psnames->adobe_std_encoding[charcode]);
+
+ for ( n = 0; n < face->type1.num_glyphs; n++ )
+ {
+ FT_String* name = (FT_String*)face->type1.glyph_names[n];
+
+
+ if ( name && strcmp( name,glyph_name ) == 0 )
+ return n;
+ }
+
+ return -1;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1operator_seac */
+ /* */
+ /* <Description> */
+ /* Implements the `seac' Type 1 operator for a Type 1 decoder. */
+ /* */
+ /* <Input> */
+ /* decoder :: The current CID decoder. */
+ /* */
+ /* asb :: The accent's side bearing. */
+ /* */
+ /* adx :: The horizontal offset of the accent. */
+ /* */
+ /* ady :: The vertical offset of the accent. */
+ /* */
+ /* bchar :: The base character's StandardEncoding charcode. */
+ /* */
+ /* achar :: The accent character's StandardEncoding charcode. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static
+ FT_Error t1operator_seac( Z1_Decoder* decoder,
+ FT_Pos asb,
+ FT_Pos adx,
+ FT_Pos ady,
+ FT_Int bchar,
+ FT_Int achar )
+ {
+ FT_Error error;
+ FT_Int bchar_index, achar_index, n_base_points;
+ FT_Outline* base = decoder->builder.base;
+ FT_Vector left_bearing, advance;
+ T1_Face face = decoder->builder.face;
+ T1_Font* type1 = &face->type1;
+
+
+ bchar_index = lookup_glyph_by_stdcharcode( face, bchar );
+ achar_index = lookup_glyph_by_stdcharcode( face, achar );
+
+ if ( bchar_index < 0 || achar_index < 0 )
+ {
+ FT_ERROR(( "t1operator_seac:" ));
+ FT_ERROR(( " invalid seac character code arguments\n" ));
+ return T1_Err_Syntax_Error;
+ }
+
+ /* if we are trying to load a composite glyph, do not load the */
+ /* accent character and return the array of subglyphs. */
+ if ( decoder->builder.no_recurse )
+ {
+ FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
+ FT_GlyphLoader* loader = glyph->loader;
+ FT_SubGlyph* subg;
+
+
+ /* reallocate subglyph array if necessary */
+ error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
+ if ( error )
+ goto Exit;
+
+ subg = loader->current.subglyphs;
+
+ /* subglyph 0 = base character */
+ subg->index = bchar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+ FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+ subg->arg1 = 0;
+ subg->arg2 = 0;
+ subg++;
+
+ /* subglyph 1 = accent character */
+ subg->index = achar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+ subg->arg1 = adx - asb;
+ subg->arg2 = ady;
+
+ /* set up remaining glyph fields */
+ glyph->num_subglyphs = 2;
+ glyph->subglyphs = loader->base.subglyphs;
+ glyph->format = ft_glyph_format_composite;
+
+ loader->current.num_subglyphs = 2;
+ }
+
+ /* First load `bchar' in builder */
+ /* now load the unscaled outline */
+
+ FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
+
+ error = Z1_Parse_CharStrings( decoder,
+ type1->charstrings [bchar_index],
+ type1->charstrings_len[bchar_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+ if ( error )
+ goto Exit;
+
+ n_base_points = base->n_points;
+
+ /* save the left bearing and width of the base character */
+ /* as they will be erased by the next load. */
+
+ left_bearing = decoder->builder.left_bearing;
+ advance = decoder->builder.advance;
+
+ decoder->builder.left_bearing.x = 0;
+ decoder->builder.left_bearing.y = 0;
+
+ /* Now load `achar' on top of */
+ /* the base outline */
+ error = Z1_Parse_CharStrings( decoder,
+ type1->charstrings [achar_index],
+ type1->charstrings_len[achar_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+ if ( error )
+ return error;
+
+ /* restore the left side bearing and */
+ /* advance width of the base character */
+
+ decoder->builder.left_bearing = left_bearing;
+ decoder->builder.advance = advance;
+
+ /* Finally, move the accent */
+ if ( decoder->builder.load_points )
+ {
+ FT_Outline dummy;
+
+
+ dummy.n_points = base->n_points - n_base_points;
+ dummy.points = base->points + n_base_points;
+ FT_Outline_Translate( &dummy, adx - asb, ady );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+#define USE_ARGS( n ) do \
+ { \
+ top -= n; \
+ if ( top < decoder->stack ) \
+ goto Stack_Underflow; \
+ } while ( 0 )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Z1_Parse_CharStrings */
+ /* */
+ /* <Description> */
+ /* Parses a given Type 1 charstrings program. */
+ /* */
+ /* <Input> */
+ /* decoder :: The current Type 1 decoder. */
+ /* */
+ /* charstring_base :: The base address of the charstring stream. */
+ /* */
+ /* charstring_len :: The length in bytes of the charstring stream. */
+ /* */
+ /* num_subrs :: The number of sub-routines. */
+ /* */
+ /* subrs_base :: An array of sub-routines addresses. */
+ /* */
+ /* subrs_len :: An array of sub-routines lengths. */
+ /* */
+ /* <Return> */
+ /* Free error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error Z1_Parse_CharStrings( Z1_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_Int charstring_len,
+ FT_Int num_subrs,
+ FT_Byte** subrs_base,
+ FT_Int* subrs_len )
+ {
+ FT_Error error;
+ Z1_Decoder_Zone* zone;
+ FT_Byte* ip;
+ FT_Byte* limit;
+ Z1_Builder* builder = &decoder->builder;
+ FT_Outline* outline;
+ FT_Pos x, y;
+
+
+ /* First of all, initialize the decoder */
+ decoder->top = decoder->stack;
+ decoder->zone = decoder->zones;
+ zone = decoder->zones;
+
+ builder->path_begun = 0;
+
+ zone->base = charstring_base;
+ limit = zone->limit = charstring_base + charstring_len;
+ ip = zone->cursor = zone->base;
+
+ error = T1_Err_Ok;
+ outline = builder->current;
+
+ x = builder->pos_x;
+ y = builder->pos_y;
+
+ /* now, execute loop */
+ while ( ip < limit )
+ {
+ FT_Int* top = decoder->top;
+ Z1_Operator op = op_none;
+ FT_Long value = 0;
+
+
+ /*********************************************************************/
+ /* */
+ /* Decode operator or operand */
+ /* */
+ /* */
+
+ /* first of all, decompress operator or value */
+ switch ( *ip++ )
+ {
+ case 1:
+ op = op_hstem;
+ break;
+
+ case 3:
+ op = op_vstem;
+ break;
+ case 4:
+ op = op_vmoveto;
+ break;
+ case 5:
+ op = op_rlineto;
+ break;
+ case 6:
+ op = op_hlineto;
+ break;
+ case 7:
+ op = op_vlineto;
+ break;
+ case 8:
+ op = op_rrcurveto;
+ break;
+ case 9:
+ op = op_closepath;
+ break;
+ case 10:
+ op = op_callsubr;
+ break;
+ case 11:
+ op = op_return;
+ break;
+
+ case 13:
+ op = op_hsbw;
+ break;
+ case 14:
+ op = op_endchar;
+ break;
+
+ case 21:
+ op = op_rmoveto;
+ break;
+ case 22:
+ op = op_hmoveto;
+ break;
+
+ case 30:
+ op = op_vhcurveto;
+ break;
+ case 31:
+ op = op_hvcurveto;
+ break;
+
+ case 12:
+ if ( ip > limit )
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+EOF)\n" ));
+ goto Syntax_Error;
+ }
+
+ switch ( *ip++ )
+ {
+ case 0:
+ op = op_dotsection;
+ break;
+ case 1:
+ op = op_vstem3;
+ break;
+ case 2:
+ op = op_hstem3;
+ break;
+ case 6:
+ op = op_seac;
+ break;
+ case 7:
+ op = op_sbw;
+ break;
+ case 12:
+ op = op_div;
+ break;
+ case 16:
+ op = op_callothersubr;
+ break;
+ case 17:
+ op = op_pop;
+ break;
+ case 33:
+ op = op_setcurrentpoint;
+ break;
+
+ default:
+ FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n",
+ ip[-1] ));
+ goto Syntax_Error;
+ }
+ break;
+
+ case 255: /* four bytes integer */
+ if ( ip + 4 > limit )
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings: unexpected EOF in integer\n" ));
+ goto Syntax_Error;
+ }
+
+ value = ( (FT_Long)ip[0] << 24 ) |
+ ( (FT_Long)ip[1] << 16 ) |
+ ( (FT_Long)ip[2] << 8 ) |
+ ip[3];
+ ip += 4;
+ break;
+
+ default:
+ if ( ip[-1] >= 32 )
+ {
+ if ( ip[-1] < 247 )
+ value = (FT_Long)ip[-1] - 139;
+ else
+ {
+ if ( ++ip > limit )
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings:" ));
+ FT_ERROR(( " unexpected EOF in integer\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( ip[-2] < 251 )
+ value = ( (FT_Long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
+ else
+ value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
+ }
+ }
+ else
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings: invalid byte (%d)\n",
+ ip[-1] ));
+ goto Syntax_Error;
+ }
+ }
+
+ /*********************************************************************/
+ /* */
+ /* Push value on stack, or process operator */
+ /* */
+ /* */
+ if ( op == op_none )
+ {
+ if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings: stack overflow!\n" ));
+ goto Syntax_Error;
+ }
+
+ FT_TRACE4(( " %ld", value ));
+
+ *top++ = value;
+ decoder->top = top;
+ }
+ else if ( op == op_callothersubr ) /* callothersubr */
+ {
+ FT_TRACE4(( " callothersubr" ));
+
+ if ( top - decoder->stack < 2 )
+ goto Stack_Underflow;
+
+ top -= 2;
+ switch ( top[1] )
+ {
+ case 1: /* start flex feature */
+ if ( top[0] != 0 )
+ goto Unexpected_OtherSubr;
+
+ decoder->flex_state = 1;
+ decoder->num_flex_vectors = 0;
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, 6 ) )
+ goto Memory_Error;
+ break;
+
+ case 2: /* add flex vectors */
+ {
+ FT_Int index;
+
+ if ( top[0] != 0 )
+ goto Unexpected_OtherSubr;
+
+ /* note that we should not add a point for index 0; */
+ /* this will move our current position to the flex */
+ /* point without adding any point to the outline */
+ index = decoder->num_flex_vectors++;
+ if ( index > 0 && index < 7 )
+ add_point( builder,
+ x,
+ y,
+ (FT_Byte)( index == 3 || index == 6 ) );
+ }
+ break;
+
+ case 0: /* end flex feature */
+ if ( top[0] != 3 )
+ goto Unexpected_OtherSubr;
+
+ if ( decoder->flex_state == 0 ||
+ decoder->num_flex_vectors != 7 )
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings: unexpected flex end\n" ));
+ goto Syntax_Error;
+ }
+
+ /* now consume the remaining `pop pop setcurpoint' */
+ if ( ip + 6 > limit ||
+ ip[0] != 12 || ip[1] != 17 || /* pop */
+ ip[2] != 12 || ip[3] != 17 || /* pop */
+ ip[4] != 12 || ip[5] != 33 ) /* setcurpoint */
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings: invalid flex charstring\n" ));
+ goto Syntax_Error;
+ }
+
+ ip += 6;
+ decoder->flex_state = 0;
+ break;
+
+ case 3: /* change hints */
+ if ( top[0] != 1 )
+ goto Unexpected_OtherSubr;
+
+ /* eat the following `pop' */
+ if ( ip + 2 > limit )
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n",
+ ip[-1] ));
+ goto Syntax_Error;
+ }
+
+ if ( ip[0] != 12 || ip[1] != 17 )
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings:" ));
+ FT_ERROR(( " `pop' expected, found (%d %d)\n",
+ ip[0], ip[1] ));
+ goto Syntax_Error;
+ }
+ ip += 2;
+ break;
+
+ case 12:
+ case 13:
+ /* counter control hints, clear stack */
+ top = decoder->stack;
+ break;
+
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18: /* multiple masters */
+ {
+ T1_Blend* blend = decoder->blend;
+ FT_UInt num_points, nn, mm;
+ FT_Int* delta;
+ FT_Int* values;
+
+
+ if ( !blend )
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings:" ));
+ FT_ERROR(( " unexpected multiple masters operator!\n" ));
+ goto Syntax_Error;
+ }
+
+ num_points = top[1] - 13 + ( top[1] == 18 );
+ if ( top[0] != (FT_Int)( num_points * blend->num_designs ) )
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings:" ));
+ FT_ERROR(( " incorrect number of mm arguments\n" ));
+ goto Syntax_Error;
+ }
+
+ top -= blend->num_designs*num_points;
+ if ( top < decoder->stack )
+ goto Stack_Underflow;
+
+ /* we want to compute: */
+ /* */
+ /* a0*w0 + a1*w1 + ... + ak*wk */
+ /* */
+ /* but we only have the a0, a1-a0, a2-a0, .. ak-a0 */
+ /* however, given that w0 + w1 + ... + wk == 1, we can */
+ /* rewrite it easily as: */
+ /* */
+ /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */
+ /* */
+ /* where k == num_designs-1 */
+ /* */
+ /* I guess that's why it's written in this `compact' */
+ /* form. */
+ /* */
+ delta = top + num_points;
+ values = top;
+ for ( nn = 0; nn < num_points; nn++ )
+ {
+ FT_Int x = values[0];
+
+
+ for ( mm = 1; mm < blend->num_designs; mm++ )
+ x += FT_MulFix( *delta++, blend->weight_vector[mm] );
+
+ *values++ = x;
+ }
+ /* note that `top' will be incremented later by calls to `pop' */
+ break;
+ }
+
+ default:
+ Unexpected_OtherSubr:
+ FT_ERROR(( "Z1_Parse_CharStrings: invalid othersubr [%d %d]!\n",
+ top[0], top[1] ));
+ goto Syntax_Error;
+ }
+ decoder->top = top;
+ }
+ else /* general operator */
+ {
+ FT_Int num_args = t1_args_count[op];
+
+
+ if ( top - decoder->stack < num_args )
+ goto Stack_Underflow;
+
+ top -= num_args;
+
+ switch ( op )
+ {
+ case op_endchar:
+ FT_TRACE4(( " endchar" ));
+
+ close_contour( builder );
+
+ /* add current outline to the glyph slot */
+ FT_GlyphLoader_Add( builder->loader );
+
+ /* return now! */
+ FT_TRACE4(( "\n\n" ));
+ return T1_Err_Ok;
+
+ case op_hsbw:
+ FT_TRACE4(( " hsbw" ));
+
+ builder->left_bearing.x += top[0];
+ builder->advance.x = top[1];
+ builder->advance.y = 0;
+
+ builder->last.x = x = top[0];
+ builder->last.y = y = 0;
+
+ /* the `metrics_only' indicates that we only want to compute */
+ /* the glyph's metrics (lsb + advance width), not load the */
+ /* rest of it; so exit immediately */
+ if ( builder->metrics_only )
+ return T1_Err_Ok;
+
+ break;
+
+ case op_seac:
+ /* return immediately after the processing */
+ return t1operator_seac( decoder, top[0], top[1],
+ top[2], top[3], top[4] );
+
+ case op_sbw:
+ FT_TRACE4(( " sbw" ));
+
+ builder->left_bearing.x += top[0];
+ builder->left_bearing.y += top[1];
+ builder->advance.x = top[2];
+ builder->advance.y = top[3];
+
+ builder->last.x = x = top[0];
+ builder->last.y = y = top[1];
+
+ /* the `metrics_only' indicates that we only want to compute */
+ /* the glyph's metrics (lsb + advance width), not load the */
+ /* rest of it; so exit immediately */
+ if ( builder->metrics_only )
+ return T1_Err_Ok;
+
+ break;
+
+ case op_closepath:
+ FT_TRACE4(( " closepath" ));
+
+ close_contour( builder );
+ builder->path_begun = 0;
+ break;
+
+ case op_hlineto:
+ FT_TRACE4(( " hlineto" ));
+
+ if ( start_point( builder, x, y ) )
+ goto Memory_Error;
+
+ x += top[0];
+ goto Add_Line;
+
+ case op_hmoveto:
+ FT_TRACE4(( " hmoveto" ));
+
+ x += top[0];
+ break;
+
+ case op_hvcurveto:
+ FT_TRACE4(( " hvcurveto" ));
+
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, 3 ) )
+ goto Memory_Error;
+
+ x += top[0];
+ add_point( builder, x, y, 0 );
+ x += top[1];
+ y += top[2];
+ add_point( builder, x, y, 0 );
+ y += top[3];
+ add_point( builder, x, y, 1 );
+ break;
+
+ case op_rlineto:
+ FT_TRACE4(( " rlineto" ));
+
+ if ( start_point( builder, x, y ) )
+ goto Memory_Error;
+
+ x += top[0];
+ y += top[1];
+
+ Add_Line:
+ if ( add_point1( builder, x, y ) )
+ goto Memory_Error;
+ break;
+
+ case op_rmoveto:
+ FT_TRACE4(( " rmoveto" ));
+
+ x += top[0];
+ y += top[1];
+ break;
+
+ case op_rrcurveto:
+ FT_TRACE4(( " rcurveto" ));
+
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, 3 ) )
+ goto Memory_Error;
+
+ x += top[0];
+ y += top[1];
+ add_point( builder, x, y, 0 );
+
+ x += top[2];
+ y += top[3];
+ add_point( builder, x, y, 0 );
+
+ x += top[4];
+ y += top[5];
+ add_point( builder, x, y, 1 );
+ break;
+
+ case op_vhcurveto:
+ FT_TRACE4(( " vhcurveto" ));
+
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, 3 ) )
+ goto Memory_Error;
+
+ y += top[0];
+ add_point( builder, x, y, 0 );
+ x += top[1];
+ y += top[2];
+ add_point( builder, x, y, 0 );
+ x += top[3];
+ add_point( builder, x, y, 1 );
+ break;
+
+ case op_vlineto:
+ FT_TRACE4(( " vlineto" ));
+
+ if ( start_point( builder, x, y ) )
+ goto Memory_Error;
+
+ y += top[0];
+ goto Add_Line;
+
+ case op_vmoveto:
+ FT_TRACE4(( " vmoveto" ));
+
+ y += top[0];
+ break;
+
+ case op_div:
+ FT_TRACE4(( " div" ));
+
+ if ( top[1] )
+ {
+ *top = top[0] / top[1];
+ ++top;
+ }
+ else
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings: division by 0\n" ));
+ goto Syntax_Error;
+ }
+ break;
+
+ case op_callsubr:
+ {
+ FT_Int index;
+
+
+ FT_TRACE4(( " callsubr" ));
+
+ index = top[0];
+ if ( index < 0 || index >= num_subrs )
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings: invalid subrs index\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings: too many nested subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ zone->cursor = ip; /* save current instruction pointer */
+
+ zone++;
+ zone->base = subrs_base[index];
+ zone->limit = zone->base + subrs_len[index];
+ zone->cursor = zone->base;
+
+ if ( !zone->base )
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings: invoking empty subrs!\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone = zone;
+ ip = zone->base;
+ limit = zone->limit;
+ break;
+ }
+
+ case op_pop:
+ FT_TRACE4(( " pop" ));
+
+ /* theorically, the arguments are already on the stack */
+ top++;
+ break;
+
+ case op_return:
+ FT_TRACE4(( " return" ));
+
+ if ( zone <= decoder->zones )
+ {
+ FT_ERROR(( "Z1_Parse_CharStrings: unexpected return\n" ));
+ goto Syntax_Error;
+ }
+
+ zone--;
+ ip = zone->cursor;
+ limit = zone->limit;
+ decoder->zone = zone;
+ break;
+
+ case op_dotsection:
+ FT_TRACE4(( " dotsection" ));
+
+ break;
+
+ case op_hstem:
+ FT_TRACE4(( " hstem" ));
+
+ break;
+
+ case op_hstem3:
+ FT_TRACE4(( " hstem3" ));
+
+ break;
+
+ case op_vstem:
+ FT_TRACE4(( " vstem" ));
+
+ break;
+
+ case op_vstem3:
+ FT_TRACE4(( " vstem3" ));
+
+ break;
+
+ case op_setcurrentpoint:
+ FT_TRACE4(( " setcurrentpoint" ));
+
+ FT_ERROR(( "Z1_Parse_CharStrings:" ));
+ FT_ERROR(( " unexpected `setcurrentpoint'\n" ));
+ goto Syntax_Error;
+
+ default:
+ FT_ERROR(( "Z1_Parse_CharStrings: unhandled opcode %d\n", op ));
+ goto Syntax_Error;
+ }
+
+ decoder->top = top;
+
+ } /* general operator processing */
+
+ } /* while ip < limit */
+
+ FT_TRACE4(( "..end..\n\n" ));
+ return error;
+
+ Syntax_Error:
+ return T1_Err_Syntax_Error;
+
+ Stack_Underflow:
+ return T1_Err_Stack_Underflow;
+
+ Memory_Error:
+ return builder->error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
+ /********** *********/
+ /********** The following code is in charge of computing *********/
+ /********** the maximum advance width of the font. It *********/
+ /********** quickly processes each glyph charstring to *********/
+ /********** extract the value from either a `sbw' or `seac' *********/
+ /********** operator. *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ LOCAL_FUNC
+ FT_Error Z1_Compute_Max_Advance( T1_Face face,
+ FT_Int* max_advance )
+ {
+ FT_Error error;
+ Z1_Decoder decoder;
+ FT_Int glyph_index;
+ T1_Font* type1 = &face->type1;
+
+
+ *max_advance = 0;
+
+ /* Initialize load decoder */
+ Z1_Init_Decoder( &decoder );
+ Z1_Init_Builder( &decoder.builder, face, 0, 0 );
+
+ decoder.blend = face->blend;
+ decoder.builder.metrics_only = 1;
+ decoder.builder.load_points = 0;
+
+ /* for each glyph, parse the glyph charstring and extract */
+ /* the advance width */
+ for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
+ {
+ /* now get load the unscaled outline */
+ error = Z1_Parse_CharStrings( &decoder,
+ type1->charstrings [glyph_index],
+ type1->charstrings_len[glyph_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+ /* ignore the error if one occured - skip to next glyph */
+ }
+
+ *max_advance = decoder.builder.advance.x;
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** UNHINTED GLYPH LOADER *********/
+ /********** *********/
+ /********** The following code is in charge of loading a *********/
+ /********** single outline. It completely ignores hinting *********/
+ /********** and is used when FT_LOAD_NO_HINTING is set. *********/
+ /********** *********/
+ /********** The Type 1 hinter is located in `t1hint.c' *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ LOCAL_FUNC
+ FT_Error Z1_Load_Glyph( Z1_GlyphSlot glyph,
+ Z1_Size size,
+ FT_Int glyph_index,
+ FT_Int load_flags )
+ {
+ FT_Error error;
+ Z1_Decoder decoder;
+ T1_Face face = (T1_Face)glyph->root.face;
+ FT_Bool hinting;
+ T1_Font* type1 = &face->type1;
+
+
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+ glyph->x_scale = size->root.metrics.x_scale;
+ glyph->y_scale = size->root.metrics.y_scale;
+
+ glyph->root.outline.n_points = 0;
+ glyph->root.outline.n_contours = 0;
+
+ hinting = ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
+ ( load_flags & FT_LOAD_NO_HINTING ) == 0;
+
+ glyph->root.format = ft_glyph_format_outline;
+
+ Z1_Init_Decoder( &decoder );
+ Z1_Init_Builder( &decoder.builder, face, size, glyph );
+
+ decoder.blend = ((T1_Face)glyph->root.face)->blend;
+ decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0;
+
+ /* now load the unscaled outline */
+ error = Z1_Parse_CharStrings( &decoder,
+ type1->charstrings [glyph_index],
+ type1->charstrings_len[glyph_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+
+ /* save new glyph tables */
+ Z1_Done_Builder( &decoder.builder );
+
+ /* now, set the metrics -- this is rather simple, as */
+ /* the left side bearing is the xMin, and the top side */
+ /* bearing the yMax */
+ if ( !error )
+ {
+ glyph->root.outline.flags &= ft_outline_owner;
+ glyph->root.outline.flags |= ft_outline_reverse_fill;
+
+ /* for composite glyphs, return only left side bearing and */
+ /* advance width */
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ {
+ glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+ glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
+ }
+ else
+ {
+ FT_BBox cbox;
+ FT_Glyph_Metrics* metrics = &glyph->root.metrics;
+
+
+ /* copy the _unscaled_ advance width */
+ metrics->horiAdvance = decoder.builder.advance.x;
+
+ /* make up vertical metrics */
+ metrics->vertBearingX = 0;
+ metrics->vertBearingY = 0;
+ metrics->vertAdvance = 0;
+
+ glyph->root.format = ft_glyph_format_outline;
+
+ if ( size && size->root.metrics.y_ppem < 24 )
+ glyph->root.outline.flags |= ft_outline_high_precision;
+
+#if 0
+ glyph->root.outline.second_pass = TRUE;
+ glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24;
+ glyph->root.outline.dropout_mode = 2;
+#endif /* 0 */
+
+ if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ /* scale the outline and the metrics */
+ FT_Int n;
+ FT_Outline* cur = decoder.builder.base;
+ FT_Vector* vec = cur->points;
+ FT_Fixed x_scale = glyph->x_scale;
+ FT_Fixed y_scale = glyph->y_scale;
+
+
+ /* First of all, scale the points */
+ for ( n = cur->n_points; n > 0; n--, vec++ )
+ {
+ vec->x = FT_MulFix( vec->x, x_scale );
+ vec->y = FT_MulFix( vec->y, y_scale );
+ }
+
+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+ /* Then scale the metrics */
+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
+
+ metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+ metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+ }
+
+ /* apply the font matrix */
+ FT_Outline_Transform( &glyph->root.outline,
+ &face->type1.font_matrix );
+
+ /* compute the other metrics */
+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+ /* grid fit the bounding box if necessary */
+ if ( hinting )
+ {
+ cbox.xMin &= -64;
+ cbox.yMin &= -64;
+ cbox.xMax = ( cbox.xMax+63 ) & -64;
+ cbox.yMax = ( cbox.yMax+63 ) & -64;
+ }
+
+ metrics->width = cbox.xMax - cbox.xMin;
+ metrics->height = cbox.yMax - cbox.yMin;
+
+ metrics->horiBearingX = cbox.xMin;
+ metrics->horiBearingY = cbox.yMax;
+ }
+ }
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* z1gload.h */
+/* */
+/* Experimental Type 1 Glyph Loader (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef Z1GLOAD_H
+#define Z1GLOAD_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1objs.h"
+
+#else
+
+#include <type1z/z1objs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Structure> */
+ /* Z1_Builder */
+ /* */
+ /* <Description> */
+ /* A structure used during glyph loading to store its outline. */
+ /* */
+ /* <Fields> */
+ /* memory :: The current memory object. */
+ /* */
+ /* face :: The current face object. */
+ /* */
+ /* glyph :: The current glyph slot. */
+ /* */
+ /* loader :: The current glyph loader. */
+ /* */
+ /* current :: The current glyph outline. */
+ /* */
+ /* base :: The base glyph outline. */
+ /* */
+ /* last :: The last point position. */
+ /* */
+ /* scale_x :: The horizontal scale (FUnits to sub-pixels). */
+ /* */
+ /* scale_y :: The vertical scale (FUnits to sub-pixels). */
+ /* */
+ /* pos_x :: The horizontal translation (for composite glyphs). */
+ /* */
+ /* pos_y :: The vertical translation (for composite glyphs). */
+ /* */
+ /* left_bearing :: The left side bearing point. */
+ /* */
+ /* advance :: The horizontal advance vector. */
+ /* */
+ /* no_recurse :: */
+ /* */
+ /* bbox :: The glyph's bounding box. */
+ /* */
+ /* path_begun :: A flag which indicates that a new path has begun. */
+ /* */
+ /* load_points :: A flag which indicates, if not set, that no points */
+ /* are loaded. */
+ /* */
+ /* error :: The current error code. */
+ /* */
+ /* metrics_only :: A flag whether to compute metrics only. */
+ /* */
+ typedef struct Z1_Builder_
+ {
+ FT_Memory memory;
+ T1_Face face;
+ Z1_GlyphSlot glyph;
+ FT_GlyphLoader* loader;
+
+ FT_Outline* current; /* the current glyph outline */
+ FT_Outline* base; /* the composite glyph outline */
+
+ FT_Vector last;
+
+ FT_Fixed scale_x;
+ FT_Fixed scale_y;
+
+ FT_Pos pos_x;
+ FT_Pos pos_y;
+
+ FT_Vector left_bearing;
+ FT_Vector advance;
+
+ FT_BBox bbox; /* bounding box */
+ FT_Bool path_begun;
+ FT_Bool load_points;
+ FT_Bool no_recurse;
+
+ FT_Error error; /* only used for memory errors */
+ FT_Bool metrics_only;
+
+ } Z1_Builder;
+
+
+ /* execution context charstring zone */
+ typedef struct Z1_Decoder_Zone_
+ {
+ FT_Byte* base;
+ FT_Byte* limit;
+ FT_Byte* cursor;
+
+ } Z1_Decoder_Zone;
+
+
+ typedef struct Z1_Decoder_
+ {
+ Z1_Builder builder;
+
+ FT_Int stack[T1_MAX_CHARSTRINGS_OPERANDS];
+ FT_Int* top;
+
+ Z1_Decoder_Zone zones[T1_MAX_SUBRS_CALLS + 1];
+ Z1_Decoder_Zone* zone;
+
+ FT_Int flex_state;
+ FT_Int num_flex_vectors;
+ FT_Vector flex_vectors[7];
+
+ T1_Blend* blend; /* for multiple masters */
+
+ } Z1_Decoder;
+
+
+ LOCAL_DEF
+ void Z1_Init_Builder( Z1_Builder* builder,
+ T1_Face face,
+ Z1_Size size,
+ Z1_GlyphSlot glyph );
+
+ LOCAL_DEF
+ void Z1_Done_Builder( Z1_Builder* builder );
+
+ LOCAL_DEF
+ void Z1_Init_Decoder( Z1_Decoder* decoder );
+
+ LOCAL_DEF
+ FT_Error Z1_Compute_Max_Advance( T1_Face face,
+ FT_Int* max_advance );
+
+ LOCAL_DEF
+ FT_Error Z1_Parse_CharStrings( Z1_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_Int charstring_len,
+ FT_Int num_subrs,
+ FT_Byte** subrs_base,
+ FT_Int* subrs_len );
+
+ LOCAL_DEF
+ FT_Error Z1_Load_Glyph( Z1_GlyphSlot glyph,
+ Z1_Size size,
+ FT_Int glyph_index,
+ FT_Int load_flags );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* Z1GLOAD_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* z1load.c */
+/* */
+/* Experimental Type 1 font loader (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This is the new and improved Type 1 data loader for FreeType 2. The */
+ /* old loader has several problems: it is slow, complex, difficult to */
+ /* maintain, and contains incredible hacks to make it accept some */
+ /* ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of */
+ /* the Type 1 fonts on my machine still aren't loaded correctly by it. */
+ /* */
+ /* This version is much simpler, much faster and also easier to read and */
+ /* maintain by a great order of magnitude. The idea behind it is to */
+ /* _not_ try to read the Type 1 token stream with a state machine (i.e. */
+ /* a Postscript-like interpreter) but rather to perform simple pattern */
+ /* matching. */
+ /* */
+ /* Indeed, nearly all data definitions follow a simple pattern like */
+ /* */
+ /* ... /Field <data> ... */
+ /* */
+ /* where <data> can be a number, a boolean, a string, or an array of */
+ /* numbers. There are a few exceptions, namely the encoding, font name, */
+ /* charstrings, and subrs; they are handled with a special pattern */
+ /* matching routine. */
+ /* */
+ /* All other common cases are handled very simply. The matching rules */
+ /* are defined in the file `t1tokens.h' through the use of several */
+ /* macros calls PARSE_XXX. */
+ /* */
+ /* This file is included twice here; the first time to generate parsing */
+ /* callback functions, the second to generate a table of keywords (with */
+ /* pointers to the associated callback). */
+ /* */
+ /* The function `parse_dict' simply scans *linearly* a given dictionary */
+ /* (either the top-level or private one) and calls the appropriate */
+ /* callback when it encounters an immediate keyword. */
+ /* */
+ /* This is by far the fastest way one can find to parse and read all */
+ /* data. */
+ /* */
+ /* This led to tremendous code size reduction. Note that later, the */
+ /* glyph loader will also be _greatly_ simplified, and the automatic */
+ /* hinter will replace the clumsy `t1hinter'. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/config/ftconfig.h>
+#include <freetype/ftmm.h>
+
+#include <freetype/internal/t1types.h>
+#include <freetype/internal/t1errors.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1load.h"
+
+#else
+
+#include <type1z/z1load.h>
+
+#endif
+
+
+#include <string.h> /* for strncmp(), strcmp() */
+#include <ctype.h> /* for isalnum() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_z1load
+
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** MULTIPLE MASTERS SUPPORT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static
+ FT_Error t1_allocate_blend( T1_Face face,
+ FT_UInt num_designs,
+ FT_UInt num_axis )
+ {
+ T1_Blend* blend;
+ FT_Memory memory = face->root.memory;
+ FT_Error error = 0;
+
+
+ blend = face->blend;
+ if ( !blend )
+ {
+ if ( ALLOC( blend, sizeof ( *blend ) ) )
+ goto Exit;
+
+ face->blend = blend;
+ }
+
+ /* allocate design data if needed */
+ if ( num_designs > 0 )
+ {
+ if ( blend->num_designs == 0 )
+ {
+ FT_UInt nn;
+
+
+ /* allocate the blend `private' and `font_info' dictionaries */
+ if ( ALLOC_ARRAY( blend->font_infos[1], num_designs, T1_FontInfo ) ||
+ ALLOC_ARRAY( blend->privates[1], num_designs, T1_Private ) ||
+ ALLOC_ARRAY( blend->weight_vector, num_designs * 2, FT_Fixed ) )
+ goto Exit;
+
+ blend->default_weight_vector = blend->weight_vector + num_designs;
+
+ blend->font_infos[0] = &face->type1.font_info;
+ blend->privates [0] = &face->type1.private_dict;
+
+ for ( nn = 2; nn <= num_designs; nn++ )
+ {
+ blend->privates[nn] = blend->privates [nn - 1] + 1;
+ blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;
+ }
+
+ blend->num_designs = num_designs;
+ }
+ else if ( blend->num_designs != num_designs )
+ goto Fail;
+ }
+
+ /* allocate axis data if needed */
+ if ( num_axis > 0 )
+ {
+ if ( blend->num_axis != 0 && blend->num_axis != num_axis )
+ goto Fail;
+
+ blend->num_axis = num_axis;
+ }
+
+ /* allocate the blend design pos table if needed */
+ num_designs = blend->num_designs;
+ num_axis = blend->num_axis;
+ if ( num_designs && num_axis && blend->design_pos[0] == 0 )
+ {
+ FT_UInt n;
+
+
+ if ( ALLOC_ARRAY( blend->design_pos[0],
+ num_designs * num_axis, FT_Fixed ) )
+ goto Exit;
+
+ for ( n = 1; n < num_designs; n++ )
+ blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
+ }
+
+ Exit:
+ return error;
+
+ Fail:
+ error = -1;
+ goto Exit;
+ }
+
+
+ LOCAL_FUNC
+ FT_Error Z1_Get_Multi_Master( T1_Face face,
+ FT_Multi_Master* master )
+ {
+ T1_Blend* blend = face->blend;
+ FT_UInt n;
+ FT_Error error;
+
+
+ error = T1_Err_Invalid_Argument;
+
+ if ( blend )
+ {
+ master->num_axis = blend->num_axis;
+ master->num_designs = blend->num_designs;
+
+ for ( n = 0; n < blend->num_axis; n++ )
+ {
+ FT_MM_Axis* axis = master->axis + n;
+ T1_DesignMap* map = blend->design_map + n;
+
+
+ axis->name = blend->axis_names[n];
+ axis->minimum = map->design_points[0];
+ axis->maximum = map->design_points[map->num_points - 1];
+ }
+ error = 0;
+ }
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ FT_Error Z1_Set_MM_Blend( T1_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ T1_Blend* blend = face->blend;
+ FT_Error error;
+ FT_UInt n, m;
+
+
+ error = T1_Err_Invalid_Argument;
+
+ if ( blend && blend->num_axis == num_coords )
+ {
+ /* recompute the weight vector from the blend coordinates */
+ error = FT_Err_Ok;
+
+ for ( n = 0; n < blend->num_designs; n++ )
+ {
+ FT_Fixed result = 0x10000L; /* 1.0 fixed */
+
+
+ for ( m = 0; m < blend->num_axis; m++ )
+ {
+ FT_Fixed factor;
+
+
+ /* get current blend axis position */
+ factor = coords[m];
+ if ( factor < 0 ) factor = 0;
+ if ( factor > 0x10000L ) factor = 0x10000L;
+
+ if ( ( n & ( 1 << m ) ) == 0 )
+ factor = 0x10000L - factor;
+
+ result = FT_MulFix( result, factor );
+ }
+ blend->weight_vector[n] = result;
+ }
+
+ error = FT_Err_Ok;
+ }
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ FT_Error Z1_Set_MM_Design( T1_Face face,
+ FT_UInt num_coords,
+ FT_Long* coords )
+ {
+ T1_Blend* blend = face->blend;
+ FT_Error error;
+ FT_UInt n, p;
+
+
+ error = T1_Err_Invalid_Argument;
+ if ( blend && blend->num_axis == num_coords )
+ {
+ /* compute the blend coordinates through the blend design map */
+ FT_Fixed final_blends[T1_MAX_MM_DESIGNS];
+
+
+ for ( n = 0; n < blend->num_axis; n++ )
+ {
+ FT_Long design = coords[n];
+ FT_Fixed the_blend;
+ T1_DesignMap* map = blend->design_map + n;
+ FT_Fixed* designs = map->design_points;
+ FT_Fixed* blends = map->blend_points;
+ FT_Int before = -1, after = -1;
+
+ for ( p = 0; p < map->num_points; p++ )
+ {
+ FT_Fixed p_design = designs[p];
+
+
+ /* exact match ? */
+ if ( design == p_design )
+ {
+ the_blend = blends[p];
+ goto Found;
+ }
+
+ if ( design < p_design )
+ {
+ after = p;
+ break;
+ }
+
+ before = p;
+ }
+
+ /* now, interpolate if needed */
+ if ( before < 0 )
+ the_blend = blends[0];
+
+ else if ( after < 0 )
+ the_blend = blends[map->num_points - 1];
+
+ else
+ the_blend = FT_MulDiv( design - designs[before],
+ blends [after] - blends [before],
+ designs[after] - designs[before] );
+
+ Found:
+ final_blends[n] = the_blend;
+ }
+
+ error = Z1_Set_MM_Blend( face, num_coords, final_blends );
+ }
+
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ void Z1_Done_Blend( T1_Face face )
+ {
+ FT_Memory memory = face->root.memory;
+ T1_Blend* blend = face->blend;
+
+
+ if ( blend )
+ {
+ FT_UInt num_designs = blend->num_designs;
+ FT_UInt num_axis = blend->num_axis;
+ FT_UInt n;
+
+
+ /* release design pos table */
+ FREE( blend->design_pos[0] );
+ for ( n = 1; n < num_designs; n++ )
+ blend->design_pos[n] = 0;
+
+ /* release blend `private' and `font info' dictionaries */
+ FREE( blend->privates[1] );
+ FREE( blend->font_infos[1] );
+
+ for ( n = 0; n < num_designs; n++ )
+ {
+ blend->privates [n] = 0;
+ blend->font_infos[n] = 0;
+ }
+
+ /* release weight vectors */
+ FREE( blend->weight_vector );
+ blend->default_weight_vector = 0;
+
+ /* release axis names */
+ for ( n = 0; n < num_axis; n++ )
+ FREE( blend->axis_names[n] );
+
+ /* release design map */
+ for ( n = 0; n < num_axis; n++ )
+ {
+ T1_DesignMap* dmap = blend->design_map + n;
+
+
+ FREE( dmap->design_points );
+ dmap->num_points = 0;
+ }
+
+ FREE( face->blend );
+ }
+ }
+
+
+ static
+ void parse_blend_axis_types( T1_Face face,
+ Z1_Loader* loader )
+ {
+ Z1_Token_Rec axis_tokens[ T1_MAX_MM_AXIS ];
+ FT_Int n, num_axis;
+ FT_Error error = 0;
+ T1_Blend* blend;
+ FT_Memory memory;
+
+
+ /* take an array of objects */
+ Z1_ToTokenArray( &loader->parser, axis_tokens,
+ T1_MAX_MM_AXIS, &num_axis );
+ if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
+ {
+ FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
+ num_axis ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* allocate blend if necessary */
+ error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
+ if ( error )
+ goto Exit;
+
+ blend = face->blend;
+ memory = face->root.memory;
+
+ /* each token is an immediate containing the name of the axis */
+ for ( n = 0; n < num_axis; n++ )
+ {
+ Z1_Token_Rec* token = axis_tokens + n;
+ FT_Byte* name;
+ FT_Int len;
+
+ /* skip first slash, if any */
+ if (token->start[0] == '/')
+ token->start++;
+
+ len = token->limit - token->start;
+ if ( len <= 0 )
+ {
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ if ( ALLOC( blend->axis_names[n], len + 1 ) )
+ goto Exit;
+
+ name = (FT_Byte*)blend->axis_names[n];
+ MEM_Copy( name, token->start, len );
+ name[len] = 0;
+ }
+
+ Exit:
+ loader->parser.error = error;
+ }
+
+
+ static
+ void parse_blend_design_positions( T1_Face face,
+ Z1_Loader* loader )
+ {
+ Z1_Token_Rec design_tokens[ T1_MAX_MM_DESIGNS ];
+ FT_Int num_designs;
+ FT_Int num_axis;
+ Z1_Parser* parser = &loader->parser;
+
+ FT_Error error = 0;
+ T1_Blend* blend;
+
+
+ /* get the array of design tokens - compute number of designs */
+ Z1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs );
+ if ( num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS )
+ {
+ FT_ERROR(( "parse_blend_design_positions:" ));
+ FT_ERROR(( " incorrect number of designs: %d\n",
+ num_designs ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ {
+ FT_Byte* old_cursor = parser->cursor;
+ FT_Byte* old_limit = parser->limit;
+ FT_UInt n;
+
+
+ blend = face->blend;
+ num_axis = 0; /* make compiler happy */
+
+ for ( n = 0; n < (FT_UInt)num_designs; n++ )
+ {
+ Z1_Token_Rec axis_tokens[ T1_MAX_MM_DESIGNS ];
+ Z1_Token_Rec* token;
+ FT_Int axis, n_axis;
+
+
+ /* read axis/coordinates tokens */
+ token = design_tokens + n;
+ parser->cursor = token->start - 1;
+ parser->limit = token->limit + 1;
+ Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
+
+ if ( n == 0 )
+ {
+ num_axis = n_axis;
+ error = t1_allocate_blend( face, num_designs, num_axis );
+ if ( error )
+ goto Exit;
+ blend = face->blend;
+ }
+ else if ( n_axis != num_axis )
+ {
+ FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* now, read each axis token into the design position */
+ for ( axis = 0; axis < n_axis; axis++ )
+ {
+ Z1_Token_Rec* token2 = axis_tokens + axis;
+
+
+ parser->cursor = token2->start;
+ parser->limit = token2->limit;
+ blend->design_pos[n][axis] = Z1_ToFixed( parser, 0 );
+ }
+ }
+
+ loader->parser.cursor = old_cursor;
+ loader->parser.limit = old_limit;
+ }
+
+ Exit:
+ loader->parser.error = error;
+ }
+
+
+ static
+ void parse_blend_design_map( T1_Face face,
+ Z1_Loader* loader )
+ {
+ FT_Error error = 0;
+ Z1_Parser* parser = &loader->parser;
+ T1_Blend* blend;
+ Z1_Token_Rec axis_tokens[ T1_MAX_MM_AXIS ];
+ FT_Int n, num_axis;
+ FT_Byte* old_cursor;
+ FT_Byte* old_limit;
+ FT_Memory memory = face->root.memory;
+
+
+ Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
+ if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
+ {
+ FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
+ num_axis ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+ old_cursor = parser->cursor;
+ old_limit = parser->limit;
+
+ error = t1_allocate_blend( face, 0, num_axis );
+ if ( error )
+ goto Exit;
+ blend = face->blend;
+
+ /* now, read each axis design map */
+ for ( n = 0; n < num_axis; n++ )
+ {
+ T1_DesignMap* map = blend->design_map + n;
+ Z1_Token_Rec* token;
+ FT_Int p, num_points;
+
+
+ token = axis_tokens + n;
+ parser->cursor = token->start;
+ parser->limit = token->limit;
+
+ /* count the number of map points */
+ {
+ FT_Byte* p = token->start;
+ FT_Byte* limit = token->limit;
+
+
+ num_points = 0;
+ for ( ; p < limit; p++ )
+ if ( p[0] == '[' )
+ num_points++;
+ }
+ if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
+ {
+ FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* allocate design map data */
+ if ( ALLOC_ARRAY( map->design_points, num_points * 2, FT_Fixed ) )
+ goto Exit;
+ map->blend_points = map->design_points + num_points;
+ map->num_points = (FT_Byte)num_points;
+
+ for ( p = 0; p < num_points; p++ )
+ {
+ map->design_points[p] = Z1_ToInt( parser );
+ map->blend_points [p] = Z1_ToFixed( parser, 0 );
+ }
+ }
+
+ parser->cursor = old_cursor;
+ parser->limit = old_limit;
+
+ Exit:
+ parser->error = error;
+ }
+
+
+ static
+ void parse_weight_vector( T1_Face face,
+ Z1_Loader* loader )
+ {
+ FT_Error error = 0;
+ Z1_Parser* parser = &loader->parser;
+ T1_Blend* blend = face->blend;
+ Z1_Token_Rec master;
+ FT_UInt n;
+ FT_Byte* old_cursor;
+ FT_Byte* old_limit;
+
+
+ if ( !blend || blend->num_designs == 0 )
+ {
+ FT_ERROR(( "parse_weight_vector: too early!\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ Z1_ToToken( parser, &master );
+ if ( master.type != t1_token_array )
+ {
+ FT_ERROR(( "parse_weight_vector: incorrect format!\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ old_cursor = parser->cursor;
+ old_limit = parser->limit;
+
+ parser->cursor = master.start;
+ parser->limit = master.limit;
+
+ for ( n = 0; n < blend->num_designs; n++ )
+ {
+ blend->default_weight_vector[n] =
+ blend->weight_vector[n] = Z1_ToFixed( parser, 0 );
+ }
+
+ parser->cursor = old_cursor;
+ parser->limit = old_limit;
+
+ Exit:
+ parser->error = error;
+ }
+
+
+ /* the keyword `/shareddict' appears in some multiple master fonts */
+ /* with a lot of Postscript garbage behind it (that's completely out */
+ /* of spec!); we detect it and terminate the parsing */
+ /* */
+ static
+ void parse_shared_dict( T1_Face face,
+ Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+
+ FT_UNUSED( face );
+
+
+ parser->cursor = parser->limit;
+ parser->error = 0;
+ }
+
+#endif /* Z1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** TYPE 1 SYMBOL PARSING *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* First of all, define the token field static variables. This is a set */
+ /* of Z1_Field_Rec variables used later. */
+ /* */
+ /*************************************************************************/
+
+#define Z1_NEW_STRING( _name, _field ) \
+ static \
+ const Z1_Field_Rec t1_field_ ## _field = \
+ Z1_FIELD_STRING( T1TYPE, _field );
+
+#define Z1_NEW_BOOL( _name, _field ) \
+ static \
+ const Z1_Field_Rec t1_field_ ## _field = \
+ Z1_FIELD_BOOL( T1TYPE, _field );
+
+#define Z1_NEW_NUM( _name, _field ) \
+ static \
+ const Z1_Field_Rec t1_field_ ## _field = \
+ Z1_FIELD_NUM( T1TYPE, _field );
+
+#define Z1_NEW_FIXED( _name, _field ) \
+ static \
+ const Z1_Field_Rec t1_field_ ## _field = \
+ Z1_FIELD_FIXED( T1TYPE, _field, _power );
+
+#define Z1_NEW_NUM_TABLE( _name, _field, _max, _count ) \
+ static \
+ const Z1_Field_Rec t1_field_ ## _field = \
+ Z1_FIELD_NUM_ARRAY( T1TYPE, _field, _count, _max );
+
+#define Z1_NEW_FIXED_TABLE( _name, _field, _max, _count ) \
+ static \
+ const Z1_Field_Rec t1_field_ ## _field = \
+ Z1_FIELD_FIXED_ARRAY( T1TYPE, _field, _count, _max );
+
+#define Z1_NEW_NUM_TABLE2( _name, _field, _max ) \
+ static \
+ const Z1_Field_Rec t1_field_ ## _field = \
+ Z1_FIELD_NUM_ARRAY2( T1TYPE, _field, _max );
+
+#define Z1_NEW_FIXED_TABLE2( _name, _field, _max ) \
+ static \
+ const Z1_Field_Rec t1_field_ ## _field = \
+ Z1_FIELD_FIXED_ARRAY2( T1TYPE, _field, _max );
+
+
+#define Z1_FONTINFO_STRING( n, f ) Z1_NEW_STRING( n, f )
+#define Z1_FONTINFO_NUM( n, f ) Z1_NEW_NUM( n, f )
+#define Z1_FONTINFO_BOOL( n, f ) Z1_NEW_BOOL( n, f )
+#define Z1_PRIVATE_NUM( n, f ) Z1_NEW_NUM( n, f )
+#define Z1_PRIVATE_FIXED( n, f ) Z1_NEW_FIXED( n, f )
+#define Z1_PRIVATE_NUM_TABLE( n, f, m, c ) Z1_NEW_NUM_TABLE( n, f, m, c )
+#define Z1_PRIVATE_NUM_TABLE2( n, f, m ) Z1_NEW_NUM_TABLE2( n, f, m )
+#define Z1_TOPDICT_NUM( n, f ) Z1_NEW_NUM( n, f )
+#define Z1_TOPDICT_NUM_FIXED2( n, f, m ) Z1_NEW_FIXED_TABLE2( n, f, m )
+
+
+ /* including this file defines all field variables */
+#ifdef FT_FLAT_COMPILE
+
+#include "z1tokens.h"
+
+#else
+
+#include <type1z/z1tokens.h>
+
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* Second, define the keyword variables. This is a set of Z1_KeyWord */
+ /* structures used to model the way each keyword is `loaded'. */
+ /* */
+ /*************************************************************************/
+
+ typedef void (*Z1_Parse_Func)( T1_Face face,
+ Z1_Loader* loader );
+
+
+ typedef enum Z1_KeyWord_Type_
+ {
+ t1_keyword_callback = 0,
+ t1_keyword_field,
+ t1_keyword_field_table
+
+ } Z1_KeyWord_Type;
+
+
+ typedef enum Z1_KeyWord_Location_
+ {
+ t1_keyword_type1 = 0,
+ t1_keyword_font_info,
+ t1_keyword_private
+
+ } Z1_KeyWord_Location;
+
+
+ typedef struct Z1_KeyWord_
+ {
+ const char* name;
+ Z1_KeyWord_Type type;
+ Z1_KeyWord_Location location;
+ Z1_Parse_Func parsing;
+ const Z1_Field_Rec* field;
+
+ } Z1_KeyWord;
+
+
+#define Z1_KEYWORD_CALLBACK( name, callback ) \
+ { \
+ name, t1_keyword_callback, t1_keyword_type1, callback, 0 \
+ }
+
+#define Z1_KEYWORD_TYPE1( name, f ) \
+ { \
+ name, t1_keyword_field, t1_keyword_type1, 0, &t1_field_ ## f \
+ }
+
+#define Z1_KEYWORD_FONTINFO( name, f ) \
+ { \
+ name, t1_keyword_field, t1_keyword_font_info, 0, &t1_field_ ## f \
+ }
+
+#define Z1_KEYWORD_PRIVATE( name, f ) \
+ { \
+ name, t1_keyword_field, t1_keyword_private, 0, &t1_field_ ## f \
+ }
+
+#define Z1_KEYWORD_FONTINFO_TABLE( name, f ) \
+ { \
+ name, t1_keyword_field_table, t1_keyword_font_info, 0, \
+ &t1_field_ ## f \
+ }
+
+#define Z1_KEYWORD_PRIVATE_TABLE( name, f ) \
+ { \
+ name, t1_keyword_field_table, t1_keyword_private, 0, \
+ &t1_field_ ## f \
+ }
+
+
+#undef Z1_FONTINFO_STRING
+#undef Z1_FONTINFO_NUM
+#undef Z1_FONTINFO_BOOL
+#undef Z1_PRIVATE_NUM
+#undef Z1_PRIVATE_FIXED
+#undef Z1_PRIVATE_NUM_TABLE
+#undef Z1_PRIVATE_NUM_TABLE2
+#undef Z1_TOPDICT_NUM
+#undef Z1_TOPDICT_NUM_FIXED2
+
+#define Z1_FONTINFO_STRING( n, f ) Z1_KEYWORD_FONTINFO( n, f ),
+#define Z1_FONTINFO_NUM( n, f ) Z1_KEYWORD_FONTINFO( n, f ),
+#define Z1_FONTINFO_BOOL( n, f ) Z1_KEYWORD_FONTINFO( n, f ),
+#define Z1_PRIVATE_NUM( n, f ) Z1_KEYWORD_PRIVATE( n, f ),
+#define Z1_PRIVATE_FIXED( n, f ) Z1_KEYWORD_PRIVATE( n, f ),
+#define Z1_PRIVATE_NUM_TABLE( n, f, m, c ) Z1_KEYWORD_PRIVATE_TABLE( n, f ),
+#define Z1_PRIVATE_NUM_TABLE2( n, f, m ) Z1_KEYWORD_PRIVATE_TABLE( n, f ),
+#define Z1_TOPDICT_NUM( n, f ) Z1_KEYWORD_TYPE1( n, f ),
+#define Z1_TOPDICT_NUM_FIXED2( n, f, m ) Z1_KEYWORD_TYPE1( n, f ),
+
+
+ static
+ FT_Error t1_load_keyword( T1_Face face,
+ Z1_Loader* loader,
+ Z1_KeyWord* keyword )
+ {
+ FT_Error error;
+ void* dummy_object;
+ void** objects;
+ FT_UInt max_objects;
+ T1_Blend* blend = face->blend;
+
+
+ /* if the keyword has a dedicated callback, call it */
+ if ( keyword->type == t1_keyword_callback )
+ {
+ keyword->parsing( face, loader );
+ error = loader->parser.error;
+ goto Exit;
+ }
+
+ /* now, the keyword is either a simple field, or a table of fields; */
+ /* we are now going to take care of it */
+ switch ( keyword->location )
+ {
+ case t1_keyword_font_info:
+ dummy_object = &face->type1.font_info;
+ objects = &dummy_object;
+ max_objects = 0;
+
+ if ( blend )
+ {
+ objects = (void**)blend->font_infos;
+ max_objects = blend->num_designs;
+ }
+ break;
+
+ case t1_keyword_private:
+ dummy_object = &face->type1.private_dict;
+ objects = &dummy_object;
+ max_objects = 0;
+
+ if ( blend )
+ {
+ objects = (void**)blend->privates;
+ max_objects = blend->num_designs;
+ }
+ break;
+
+ default:
+ dummy_object = &face->type1;
+ objects = &dummy_object;
+ max_objects = 0;
+ }
+
+ if ( keyword->type == t1_keyword_field_table )
+ error = Z1_Load_Field_Table( &loader->parser, keyword->field,
+ objects, max_objects, 0 );
+ else
+ error = Z1_Load_Field( &loader->parser, keyword->field,
+ objects, max_objects, 0 );
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ int is_space( char c )
+ {
+ return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
+ }
+
+
+ static
+ int is_alpha( char c )
+ {
+ return ( isalnum( c ) ||
+ ( c == '.' ) ||
+ ( c == '_' ) );
+ }
+
+
+ static
+ void skip_whitespace( Z1_Parser* parser )
+ {
+ FT_Byte* cur = parser->cursor;
+
+
+ while ( cur < parser->limit && is_space( *cur ) )
+ cur++;
+
+ parser->cursor = cur;
+ }
+
+
+ static
+ void skip_blackspace( Z1_Parser* parser )
+ {
+ FT_Byte* cur = parser->cursor;
+
+ while ( cur < parser->limit && !is_space( *cur ) )
+ cur++;
+
+ parser->cursor = cur;
+ }
+
+
+ static
+ int read_binary_data( Z1_Parser* parser,
+ FT_Int* size,
+ FT_Byte** base )
+ {
+ FT_Byte* cur;
+ FT_Byte* limit = parser->limit;
+
+
+ /* the binary data has the following format */
+ /* */
+ /* `size' [white*] RD white ....... ND */
+ /* */
+
+ skip_whitespace( parser );
+ cur = parser->cursor;
+
+ if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 )
+ {
+ *size = Z1_ToInt( parser );
+
+ skip_whitespace( parser );
+ skip_blackspace( parser ); /* `RD' or `-|' or something else */
+
+ /* there is only one whitespace char after the */
+ /* `RD' or `-|' token */
+ *base = parser->cursor + 1;
+
+ parser->cursor += *size+1;
+ return 1;
+ }
+
+ FT_ERROR(( "read_binary_data: invalid size field\n" ));
+ parser->error = T1_Err_Invalid_File_Format;
+ return 0;
+ }
+
+
+ /* we will now define the routines used to handle */
+ /* the `/Encoding', `/Subrs', and `/CharStrings' */
+ /* dictionaries */
+
+ static
+ void parse_font_name( T1_Face face,
+ Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+ FT_Error error;
+ FT_Memory memory = parser->memory;
+ FT_Int len;
+ FT_Byte* cur;
+ FT_Byte* cur2;
+ FT_Byte* limit;
+
+
+ skip_whitespace( parser );
+
+ cur = parser->cursor;
+ limit = parser->limit;
+
+ if ( cur >= limit - 1 || *cur != '/' )
+ return;
+
+ cur++;
+ cur2 = cur;
+ while ( cur2 < limit && is_alpha( *cur2 ) )
+ cur2++;
+
+ len = cur2 - cur;
+ if ( len > 0 )
+ {
+ if ( ALLOC( face->type1.font_name, len + 1 ) )
+ {
+ parser->error = error;
+ return;
+ }
+
+ MEM_Copy( face->type1.font_name, cur, len );
+ face->type1.font_name[len] = '\0';
+ }
+ parser->cursor = cur2;
+ }
+
+
+ static
+ void parse_font_bbox( T1_Face face,
+ Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+ FT_Short temp[4];
+ FT_BBox* bbox = &face->type1.font_bbox;
+
+
+ (void)Z1_ToCoordArray( parser, 4, temp );
+ bbox->xMin = temp[0];
+ bbox->yMin = temp[1];
+ bbox->xMax = temp[2];
+ bbox->yMax = temp[3];
+ }
+
+
+ static
+ void parse_font_matrix( T1_Face face,
+ Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+ FT_Matrix* matrix = &face->type1.font_matrix;
+ FT_Fixed temp[4];
+
+
+ (void)Z1_ToFixedArray( parser, 4, temp, 3 );
+ matrix->xx = temp[0];
+ matrix->yx = temp[1];
+ matrix->xy = temp[2];
+ matrix->yy = temp[3];
+ }
+
+
+ static
+ void parse_encoding( T1_Face face,
+ Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+ FT_Byte* cur = parser->cursor;
+ FT_Byte* limit = parser->limit;
+
+
+ /* skip whitespace */
+ while ( is_space( *cur ) )
+ {
+ cur++;
+ if ( cur >= limit )
+ {
+ FT_ERROR(( "parse_encoding: out of bounds!\n" ));
+ parser->error = T1_Err_Invalid_File_Format;
+ return;
+ }
+ }
+
+ /* if we have a number, then the encoding is an array, */
+ /* and we must load it now */
+ if ( (FT_Byte)( *cur - '0' ) < 10 )
+ {
+ T1_Encoding* encode = &face->type1.encoding;
+ FT_Int count, n;
+ Z1_Table* char_table = &loader->encoding_table;
+ FT_Memory memory = parser->memory;
+ FT_Error error;
+
+
+ /* read the number of entries in the encoding, should be 256 */
+ count = Z1_ToInt( parser );
+ if ( parser->error )
+ return;
+
+ /* we use a Z1_Table to store our charnames */
+ encode->num_chars = count;
+ if ( ALLOC_ARRAY( encode->char_index, count, FT_Short ) ||
+ ALLOC_ARRAY( encode->char_name, count, FT_String* ) ||
+ ( error = Z1_New_Table( char_table, count, memory ) ) != 0 )
+ {
+ parser->error = error;
+ return;
+ }
+
+ /* Now, we will need to read a record of the form */
+ /* ... charcode /charname ... for each entry in our table */
+ /* */
+ /* We simply look for a number followed by an immediate */
+ /* name. Note that this ignores correctly the sequence */
+ /* that is often seen in type1 fonts: */
+ /* */
+ /* 0 1 255 { 1 index exch /.notdef put } for dup */
+ /* */
+ /* used to clean the encoding array before anything else. */
+ /* */
+ /* We stop when we encounter a `def'. */
+
+ cur = parser->cursor;
+ limit = parser->limit;
+ n = 0;
+
+ for ( ; cur < limit; )
+ {
+ FT_Byte c;
+
+
+ c = *cur;
+
+ /* we stop when we encounter a `def' */
+ if ( c == 'd' && cur + 3 < limit )
+ {
+ if ( cur[1] == 'e' &&
+ cur[2] == 'f' &&
+ is_space(cur[-1]) &&
+ is_space(cur[3]) )
+ {
+ FT_TRACE6(( "encoding end\n" ));
+ break;
+ }
+ }
+
+ /* otherwise, we must find a number before anything else */
+ if ( (FT_Byte)( c - '0' ) < 10 )
+ {
+ FT_Int charcode;
+
+
+ parser->cursor = cur;
+ charcode = Z1_ToInt( parser );
+ cur = parser->cursor;
+
+ /* skip whitespace */
+ while ( cur < limit && is_space( *cur ) )
+ cur++;
+
+ if ( cur < limit && *cur == '/' )
+ {
+ /* bingo, we have an immediate name -- it must be a */
+ /* character name */
+ FT_Byte* cur2 = cur + 1;
+ FT_Int len;
+
+
+ while ( cur2 < limit && is_alpha( *cur2 ) )
+ cur2++;
+
+ len = cur2 - cur - 1;
+
+ parser->error = Z1_Add_Table( char_table, charcode,
+ cur + 1, len + 1 );
+ char_table->elements[charcode][len] = '\0';
+ if ( parser->error )
+ return;
+
+ cur = cur2;
+ }
+ }
+ else
+ cur++;
+ }
+
+ face->type1.encoding_type = t1_encoding_array;
+ parser->cursor = cur;
+ }
+ /* Otherwise, we should have either `StandardEncoding' or */
+ /* `ExpertEncoding' */
+ else
+ {
+ if ( cur + 17 < limit &&
+ strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
+ face->type1.encoding_type = t1_encoding_standard;
+
+ else if ( cur + 15 < limit &&
+ strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
+ face->type1.encoding_type = t1_encoding_expert;
+
+ else
+ {
+ FT_ERROR(( "parse_encoding: invalid token!\n" ));
+ parser->error = T1_Err_Invalid_File_Format;
+ }
+ }
+ }
+
+
+ static
+ void parse_subrs( T1_Face face,
+ Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+ Z1_Table* table = &loader->subrs;
+ FT_Memory memory = parser->memory;
+ FT_Error error;
+ FT_Int n;
+
+
+ loader->num_subrs = Z1_ToInt( parser );
+ if ( parser->error )
+ return;
+
+ /* position the parser right before the `dup' of the first subr */
+ skip_whitespace( parser );
+ skip_blackspace( parser ); /* `array' */
+ skip_whitespace( parser );
+
+ /* initialize subrs array */
+ error = Z1_New_Table( table, loader->num_subrs, memory );
+ if ( error )
+ goto Fail;
+
+ /* the format is simple: */
+ /* */
+ /* `index' + binary data */
+ /* */
+
+ for ( n = 0; n < loader->num_subrs; n++ )
+ {
+ FT_Int index, size;
+ FT_Byte* base;
+
+
+ /* If the next token isn't `dup', we are also done. This */
+ /* happens when there are `holes' in the Subrs array. */
+ if ( strncmp( (char*)parser->cursor, "dup", 3 ) != 0 )
+ break;
+
+ index = Z1_ToInt( parser );
+
+ if ( !read_binary_data( parser, &size, &base ) )
+ return;
+
+ /* The binary string is followed by one token, e.g. `NP' */
+ /* (bound to `noaccess put') or by two separate tokens: */
+ /* `noaccess' & `put'. We position the parser right */
+ /* before the next `dup', if any. */
+ skip_whitespace( parser );
+ skip_blackspace( parser ); /* `NP' or `I' or `noaccess' */
+ skip_whitespace( parser );
+
+ if ( strncmp( (char*)parser->cursor, "put", 3 ) == 0 )
+ {
+ skip_blackspace( parser ); /* skip `put' */
+ skip_whitespace( parser );
+ }
+
+ /* some fonts use a value of -1 for lenIV to indicate that */
+ /* the charstrings are unencoded */
+ /* */
+ /* thanks to Tom Kacvinsky for pointing this out */
+ /* */
+ if ( face->type1.private_dict.lenIV >= 0 )
+ {
+ Z1_Decrypt( base, size, 4330 );
+ size -= face->type1.private_dict.lenIV;
+ base += face->type1.private_dict.lenIV;
+ }
+
+ error = Z1_Add_Table( table, index, base, size );
+ if ( error )
+ goto Fail;
+ }
+ return;
+
+ Fail:
+ parser->error = error;
+ }
+
+
+ static
+ void parse_charstrings( T1_Face face,
+ Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+ Z1_Table* code_table = &loader->charstrings;
+ Z1_Table* name_table = &loader->glyph_names;
+ FT_Memory memory = parser->memory;
+ FT_Error error;
+
+ FT_Byte* cur;
+ FT_Byte* limit = parser->limit;
+ FT_Int n;
+
+
+ loader->num_glyphs = Z1_ToInt( parser );
+ if ( parser->error )
+ return;
+
+ /* initialize tables */
+ error = Z1_New_Table( code_table, loader->num_glyphs, memory ) ||
+ Z1_New_Table( name_table, loader->num_glyphs, memory );
+ if ( error )
+ goto Fail;
+
+ n = 0;
+ for (;;)
+ {
+ FT_Int size;
+ FT_Byte* base;
+
+
+ /* the format is simple: */
+ /* `/glyphname' + binary data */
+ /* */
+ /* note that we stop when we find a `def' */
+ /* */
+ skip_whitespace( parser );
+
+ cur = parser->cursor;
+ if ( cur >= limit )
+ break;
+
+ /* we stop when we find a `def' or `end' keyword */
+ if ( *cur == 'd' &&
+ cur + 3 < limit &&
+ cur[1] == 'e' &&
+ cur[2] == 'f' )
+ break;
+
+ if ( *cur == 'e' &&
+ cur + 3 < limit &&
+ cur[1] == 'n' &&
+ cur[2] == 'd' )
+ break;
+
+ if ( *cur != '/' )
+ skip_blackspace( parser );
+ else
+ {
+ FT_Byte* cur2 = cur + 1;
+ FT_Int len;
+
+
+ while ( cur2 < limit && is_alpha( *cur2 ) )
+ cur2++;
+ len = cur2 - cur - 1;
+
+ error = Z1_Add_Table( name_table, n, cur + 1, len + 1 );
+ if ( error )
+ goto Fail;
+
+ /* add a trailing zero to the name table */
+ name_table->elements[n][len] = '\0';
+
+ parser->cursor = cur2;
+ if ( !read_binary_data( parser, &size, &base ) )
+ return;
+
+ if ( face->type1.private_dict.lenIV >= 0 )
+ {
+ Z1_Decrypt( base, size, 4330 );
+ size -= face->type1.private_dict.lenIV;
+ base += face->type1.private_dict.lenIV;
+ }
+
+ error = Z1_Add_Table( code_table, n, base, size );
+ if ( error )
+ goto Fail;
+
+ n++;
+ if ( n >= loader->num_glyphs )
+ break;
+ }
+ }
+ loader->num_glyphs = n;
+ return;
+
+ Fail:
+ parser->error = error;
+ }
+
+
+ static
+ const Z1_KeyWord t1_keywords[] =
+ {
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1tokens.h"
+
+#else
+
+#include <type1z/z1tokens.h>
+
+#endif
+
+ /* now add the special functions... */
+ Z1_KEYWORD_CALLBACK( "FontName", parse_font_name ),
+ Z1_KEYWORD_CALLBACK( "FontBBox", parse_font_bbox ),
+ Z1_KEYWORD_CALLBACK( "FontMatrix", parse_font_matrix ),
+ Z1_KEYWORD_CALLBACK( "Encoding", parse_encoding ),
+ Z1_KEYWORD_CALLBACK( "Subrs", parse_subrs ),
+ Z1_KEYWORD_CALLBACK( "CharStrings", parse_charstrings ),
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+ Z1_KEYWORD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions ),
+ Z1_KEYWORD_CALLBACK( "BlendDesignMap", parse_blend_design_map ),
+ Z1_KEYWORD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types ),
+ Z1_KEYWORD_CALLBACK( "WeightVector", parse_weight_vector ),
+ Z1_KEYWORD_CALLBACK( "shareddict", parse_shared_dict ),
+#endif
+
+ Z1_KEYWORD_CALLBACK( 0, 0 )
+ };
+
+
+ static
+ FT_Error parse_dict( T1_Face face,
+ Z1_Loader* loader,
+ FT_Byte* base,
+ FT_Long size )
+ {
+ Z1_Parser* parser = &loader->parser;
+
+
+ parser->cursor = base;
+ parser->limit = base + size;
+ parser->error = 0;
+
+ {
+ FT_Byte* cur = base;
+ FT_Byte* limit = cur + size;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ /* look for `FontDirectory', which causes problems on some fonts */
+ if ( *cur == 'F' && cur + 25 < limit &&
+ strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
+ {
+ FT_Byte* cur2;
+
+
+ /* skip the `FontDirectory' keyword */
+ cur += 13;
+ cur2 = cur;
+
+ /* lookup the `known' keyword */
+ while ( cur < limit && *cur != 'k' &&
+ strncmp( (char*)cur, "known", 5 ) )
+ cur++;
+
+ if ( cur < limit )
+ {
+ Z1_Token_Rec token;
+
+
+ /* skip the `known' keyword and the token following it */
+ cur += 5;
+ loader->parser.cursor = cur;
+ Z1_ToToken( &loader->parser, &token );
+
+ /* if the last token was an array, skip it! */
+ if ( token.type == t1_token_array )
+ cur2 = parser->cursor;
+ }
+ cur = cur2;
+ }
+ /* look for immediates */
+ else if ( *cur == '/' && cur + 2 < limit )
+ {
+ FT_Byte* cur2;
+ FT_Int len;
+
+
+ cur++;
+ cur2 = cur;
+ while ( cur2 < limit && is_alpha( *cur2 ) )
+ cur2++;
+
+ len = cur2 - cur;
+ if ( len > 0 && len < 22 )
+ {
+ if ( !loader->fontdata )
+ {
+ if ( strncmp( (char*)cur, "FontInfo", 8 ) == 0 )
+ loader->fontdata = 1;
+ }
+ else
+ {
+ /* now, compare the immediate name to the keyword table */
+ Z1_KeyWord* keyword = (Z1_KeyWord*)t1_keywords;
+
+
+ for (;;)
+ {
+ FT_Byte* name;
+
+
+ name = (FT_Byte*)keyword->name;
+ if ( !name )
+ break;
+
+ if ( cur[0] == name[0] &&
+ len == (FT_Int)strlen( (const char*)name ) )
+ {
+ FT_Int n;
+
+
+ for ( n = 1; n < len; n++ )
+ if ( cur[n] != name[n] )
+ break;
+
+ if ( n >= len )
+ {
+ /* we found it -- run the parsing callback! */
+ parser->cursor = cur2;
+ skip_whitespace( parser );
+ parser->error = t1_load_keyword( face, loader, keyword );
+ if ( parser->error )
+ return parser->error;
+
+ cur = parser->cursor;
+ break;
+ }
+ }
+ keyword++;
+ }
+ }
+ }
+ }
+ }
+ }
+ return parser->error;
+ }
+
+
+ static
+ void t1_init_loader( Z1_Loader* loader,
+ T1_Face face )
+ {
+ FT_UNUSED( face );
+
+ MEM_Set( loader, 0, sizeof ( *loader ) );
+ loader->num_glyphs = 0;
+ loader->num_chars = 0;
+
+ /* initialize the tables -- simply set their `init' field to 0 */
+ loader->encoding_table.init = 0;
+ loader->charstrings.init = 0;
+ loader->glyph_names.init = 0;
+ loader->subrs.init = 0;
+ loader->fontdata = 0;
+ }
+
+
+ static
+ void t1_done_loader( Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+
+
+ /* finalize tables */
+ Z1_Release_Table( &loader->encoding_table );
+ Z1_Release_Table( &loader->charstrings );
+ Z1_Release_Table( &loader->glyph_names );
+ Z1_Release_Table( &loader->subrs );
+
+ /* finalize parser */
+ Z1_Done_Parser( parser );
+ }
+
+
+ LOCAL_FUNC
+ FT_Error Z1_Open_Face( T1_Face face )
+ {
+ Z1_Loader loader;
+ Z1_Parser* parser;
+ T1_Font* type1 = &face->type1;
+ FT_Error error;
+
+
+ t1_init_loader( &loader, face );
+
+ /* default lenIV */
+ type1->private_dict.lenIV = 4;
+
+ parser = &loader.parser;
+ error = Z1_New_Parser( parser, face->root.stream, face->root.memory );
+ if ( error )
+ goto Exit;
+
+ error = parse_dict( face, &loader, parser->base_dict, parser->base_len );
+ if ( error )
+ goto Exit;
+
+ error = Z1_Get_Private_Dict( parser );
+ if ( error )
+ goto Exit;
+
+ error = parse_dict( face, &loader, parser->private_dict,
+ parser->private_len );
+ if ( error )
+ goto Exit;
+
+ /* now, propagate the subrs, charstrings, and glyphnames tables */
+ /* to the Type1 data */
+ type1->num_glyphs = loader.num_glyphs;
+
+ if ( !loader.subrs.init )
+ {
+ FT_ERROR(( "Z1_Open_Face: no subrs array in face!\n" ));
+ error = T1_Err_Invalid_File_Format;
+ }
+
+ if ( !loader.charstrings.init )
+ {
+ FT_ERROR(( "Z1_Open_Face: no charstrings array in face!\n" ));
+ error = T1_Err_Invalid_File_Format;
+ }
+
+ loader.subrs.init = 0;
+ type1->num_subrs = loader.num_subrs;
+ type1->subrs_block = loader.subrs.block;
+ type1->subrs = loader.subrs.elements;
+ type1->subrs_len = loader.subrs.lengths;
+
+ loader.charstrings.init = 0;
+ type1->charstrings_block = loader.charstrings.block;
+ type1->charstrings = loader.charstrings.elements;
+ type1->charstrings_len = loader.charstrings.lengths;
+
+ /* we copy the glyph names `block' and `elements' fields; */
+ /* the `lengths' field must be released later */
+ type1->glyph_names_block = loader.glyph_names.block;
+ type1->glyph_names = (FT_String**)loader.glyph_names.elements;
+ loader.glyph_names.block = 0;
+ loader.glyph_names.elements = 0;
+
+ /* we must now build type1.encoding when we have a custom */
+ /* array.. */
+ if ( type1->encoding_type == t1_encoding_array )
+ {
+ FT_Int charcode, index, min_char, max_char;
+ FT_Byte* char_name;
+ FT_Byte* glyph_name;
+
+
+ /* OK, we do the following: for each element in the encoding */
+ /* table, look up the index of the glyph having the same name */
+ /* the index is then stored in type1.encoding.char_index, and */
+ /* a the name to type1.encoding.char_name */
+
+ min_char = +32000;
+ max_char = -32000;
+
+ charcode = 0;
+ for ( ; charcode < loader.encoding_table.num_elems; charcode++ )
+ {
+ type1->encoding.char_index[charcode] = 0;
+ type1->encoding.char_name [charcode] = ".notdef";
+
+ char_name = loader.encoding_table.elements[charcode];
+ if ( char_name )
+ for ( index = 0; index < type1->num_glyphs; index++ )
+ {
+ glyph_name = (FT_Byte*)type1->glyph_names[index];
+ if ( strcmp( (const char*)char_name,
+ (const char*)glyph_name ) == 0 )
+ {
+ type1->encoding.char_index[charcode] = index;
+ type1->encoding.char_name [charcode] = (char*)glyph_name;
+
+ if (charcode < min_char) min_char = charcode;
+ if (charcode > max_char) max_char = charcode;
+ break;
+ }
+ }
+ }
+ type1->encoding.code_first = min_char;
+ type1->encoding.code_last = max_char;
+ type1->encoding.num_chars = loader.num_chars;
+ }
+
+ Exit:
+ t1_done_loader( &loader );
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* z1load.h */
+/* */
+/* Experimental Type 1 font loader (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef Z1LOAD_H
+#define Z1LOAD_H
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1types.h>
+#include <freetype/ftmm.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1parse.h"
+
+#else
+
+#include <type1z/z1parse.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+ typedef struct Z1_Loader_
+ {
+ Z1_Parser parser; /* parser used to read the stream */
+
+ FT_Int num_chars; /* number of characters in encoding */
+ Z1_Table encoding_table; /* Z1_Table used to store the */
+ /* encoding character names */
+
+ FT_Int num_glyphs;
+ Z1_Table glyph_names;
+ Z1_Table charstrings;
+
+ FT_Int num_subrs;
+ Z1_Table subrs;
+ FT_Bool fontdata;
+
+ } Z1_Loader;
+
+
+ LOCAL_DEF
+ FT_Error Z1_Open_Face( T1_Face face );
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+
+ LOCAL_DEF
+ FT_Error Z1_Get_Multi_Master( T1_Face face,
+ FT_Multi_Master* master );
+
+ LOCAL_DEF
+ FT_Error Z1_Set_MM_Blend( T1_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+ LOCAL_DEF
+ FT_Error Z1_Set_MM_Design( T1_Face face,
+ FT_UInt num_coords,
+ FT_Long* coords );
+
+ LOCAL_DEF
+ void Z1_Done_Blend( T1_Face face );
+
+#endif /* !Z1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* Z1LOAD_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* z1objs.c */
+/* */
+/* Experimental Type 1 objects manager (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1gload.h"
+#include "z1load.h"
+#include "z1afm.h"
+
+#else
+
+#include <type1z/z1gload.h>
+#include <type1z/z1load.h>
+#include <type1z/z1afm.h>
+
+#endif
+
+
+#include <freetype/internal/psnames.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_z1objs
+
+
+ /*************************************************************************/
+ /* */
+ /* FACE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Z1_Done_Face */
+ /* */
+ /* <Description> */
+ /* The face object destructor. */
+ /* */
+ /* <Input> */
+ /* face :: A typeless pointer to the face object to destroy. */
+ /* */
+ LOCAL_FUNC
+ void Z1_Done_Face( T1_Face face )
+ {
+ FT_Memory memory;
+ T1_Font* type1 = &face->type1;
+
+
+ if ( face )
+ {
+ memory = face->root.memory;
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+ /* release multiple masters information */
+ Z1_Done_Blend( face );
+ face->blend = 0;
+#endif
+
+ /* release font info strings */
+ {
+ T1_FontInfo* info = &type1->font_info;
+
+
+ FREE( info->version );
+ FREE( info->notice );
+ FREE( info->full_name );
+ FREE( info->family_name );
+ FREE( info->weight );
+ }
+
+ /* release top dictionary */
+ FREE( type1->charstrings_len );
+ FREE( type1->charstrings );
+ FREE( type1->glyph_names );
+
+ FREE( type1->subrs );
+ FREE( type1->subrs_len );
+
+ FREE( type1->subrs_block );
+ FREE( type1->charstrings_block );
+ FREE( type1->glyph_names_block );
+
+ FREE( type1->encoding.char_index );
+ FREE( type1->font_name );
+
+#ifndef Z1_CONFIG_OPTION_NO_AFM
+ /* release afm data if present */
+ if ( face->afm_data )
+ Z1_Done_AFM( memory, (Z1_AFM*)face->afm_data );
+#endif
+
+ /* release unicode map, if any */
+ FREE( face->unicode_map.maps );
+ face->unicode_map.num_maps = 0;
+
+ face->root.family_name = 0;
+ face->root.style_name = 0;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Z1_Init_Face */
+ /* */
+ /* <Description> */
+ /* The face object constructor. */
+ /* */
+ /* <Input> */
+ /* stream :: input stream where to load font data. */
+ /* */
+ /* face_index :: The index of the font face in the resource. */
+ /* */
+ /* num_params :: Number of additional generic parameters. Ignored. */
+ /* */
+ /* params :: Additional generic parameters. Ignored. */
+ /* */
+ /* <InOut> */
+ /* face :: The face record to build. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error Z1_Init_Face( FT_Stream stream,
+ T1_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error;
+ PSNames_Interface* psnames;
+
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+ FT_UNUSED( face_index );
+ FT_UNUSED( stream );
+
+
+ face->root.num_faces = 1;
+
+ psnames = (PSNames_Interface*)face->psnames;
+ if ( !psnames )
+ {
+ psnames = (PSNames_Interface*)
+ FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psnames" );
+
+ face->psnames = psnames;
+ }
+
+ /* open the tokenizer, this will also check the font format */
+ error = Z1_Open_Face( face );
+ if ( error )
+ goto Exit;
+
+ /* if we just wanted to check the format, leave successfully now */
+ if ( face_index < 0 )
+ goto Exit;
+
+ /* check the face index */
+ if ( face_index != 0 )
+ {
+ FT_ERROR(( "Z1_Init_Face: invalid face index\n" ));
+ error = T1_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* Now, load the font program into the face object */
+
+ /* Init the face object fields */
+ /* Now set up root face fields */
+ {
+ FT_Face root = (FT_Face)&face->root;
+
+
+ root->num_glyphs = face->type1.num_glyphs;
+ root->num_charmaps = 1;
+
+ root->face_index = face_index;
+ root->face_flags = FT_FACE_FLAG_SCALABLE;
+
+ root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
+
+ root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
+
+ if ( face->type1.font_info.is_fixed_pitch )
+ root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ if ( face->blend )
+ root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
+
+ /* XXX: TODO -- add kerning with .afm support */
+
+ /* get style name -- be careful, some broken fonts only */
+ /* have a `/FontName' dictionary entry! */
+ root->family_name = face->type1.font_info.family_name;
+ if ( root->family_name )
+ {
+ char* full = face->type1.font_info.full_name;
+ char* family = root->family_name;
+
+
+ while ( *family && *full == *family )
+ {
+ family++;
+ full++;
+ }
+
+ root->style_name = ( *full == ' ' ? full + 1
+ : (char *)"Regular" );
+ }
+ else
+ {
+ /* do we have a `/FontName'? */
+ if ( face->type1.font_name )
+ {
+ root->family_name = face->type1.font_name;
+ root->style_name = "Regular";
+ }
+ }
+
+ /* no embedded bitmap support */
+ root->num_fixed_sizes = 0;
+ root->available_sizes = 0;
+
+ root->bbox = face->type1.font_bbox;
+ root->units_per_EM = 1000;
+ root->ascender = (FT_Short)face->type1.font_bbox.yMax;
+ root->descender = -(FT_Short)face->type1.font_bbox.yMin;
+ root->height = ( ( root->ascender + root->descender ) * 12 ) / 10;
+
+ /* now compute the maximum advance width */
+
+ root->max_advance_width = face->type1.private_dict.standard_width[0];
+
+ /* compute max advance width for proportional fonts */
+ if ( !face->type1.font_info.is_fixed_pitch )
+ {
+ FT_Int max_advance;
+
+
+ error = Z1_Compute_Max_Advance( face, &max_advance );
+
+ /* in case of error, keep the standard width */
+ if ( !error )
+ root->max_advance_width = max_advance;
+ else
+ error = 0; /* clear error */
+ }
+
+ root->max_advance_height = root->height;
+
+ root->underline_position = face->type1.font_info.underline_position;
+ root->underline_thickness = face->type1.font_info.underline_thickness;
+
+ root->max_points = 0;
+ root->max_contours = 0;
+ }
+
+ /* charmap support -- synthetize unicode charmap if possible */
+ {
+ FT_Face root = &face->root;
+ FT_CharMap charmap = face->charmaprecs;
+
+
+ /* synthesize a Unicode charmap if there is support in the `PSNames' */
+ /* module */
+ if ( face->psnames )
+ {
+ PSNames_Interface* psnames = (PSNames_Interface*)face->psnames;
+
+
+ if ( psnames->unicode_value )
+ {
+ error = psnames->build_unicodes(
+ root->memory,
+ face->type1.num_glyphs,
+ (const char**)face->type1.glyph_names,
+ &face->unicode_map );
+ if ( !error )
+ {
+ root->charmap = charmap;
+ charmap->face = (FT_Face)face;
+ charmap->encoding = ft_encoding_unicode;
+ charmap->platform_id = 3;
+ charmap->encoding_id = 1;
+ charmap++;
+ }
+
+ /* simply clear the error in case of failure (which really) */
+ /* means that out of memory or no unicode glyph names */
+ error = FT_Err_Ok;
+ }
+ }
+
+ /* now, support either the standard, expert, or custom encoding */
+ charmap->face = (FT_Face)face;
+ charmap->platform_id = 7; /* a new platform id for Adobe fonts? */
+
+ switch ( face->type1.encoding_type )
+ {
+ case t1_encoding_standard:
+ charmap->encoding = ft_encoding_adobe_standard;
+ charmap->encoding_id = 0;
+ break;
+
+ case t1_encoding_expert:
+ charmap->encoding = ft_encoding_adobe_expert;
+ charmap->encoding_id = 1;
+ break;
+
+ default:
+ charmap->encoding = ft_encoding_adobe_custom;
+ charmap->encoding_id = 2;
+ break;
+ }
+
+ root->charmaps = face->charmaps;
+ root->num_charmaps = charmap - face->charmaprecs + 1;
+ face->charmaps[0] = &face->charmaprecs[0];
+ face->charmaps[1] = &face->charmaprecs[1];
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Z1_Init_Driver */
+ /* */
+ /* <Description> */
+ /* Initializes a given Type 1 driver object. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target driver object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error Z1_Init_Driver( Z1_Driver driver )
+ {
+ FT_UNUSED( driver );
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Z1_Done_Driver */
+ /* */
+ /* <Description> */
+ /* Finalizes a given Type 1 driver. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target Type 1 driver. */
+ /* */
+ LOCAL_DEF
+ void Z1_Done_Driver( Z1_Driver driver )
+ {
+ FT_UNUSED( driver );
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* z1objs.h */
+/* */
+/* Experimental Type 1 objects manager (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef Z1OBJS_H
+#define Z1OBJS_H
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/t1errors.h>
+#include <freetype/internal/t1types.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+ /* The following structures must be defined by the hinter */
+ typedef struct Z1_Size_Hints_ Z1_Size_Hints;
+ typedef struct Z1_Glyph_Hints_ Z1_Glyph_Hints;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* Z1_Driver */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 driver object. */
+ /* */
+ typedef struct Z1_DriverRec_ *Z1_Driver;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* Z1_Size */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 size object. */
+ /* */
+ typedef struct Z1_SizeRec_* Z1_Size;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* Z1_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 glyph slot object. */
+ /* */
+ typedef struct Z1_GlyphSlotRec_* Z1_GlyphSlot;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* Z1_CharMap */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 character mapping object. */
+ /* */
+ /* <Note> */
+ /* The Type 1 format doesn't use a charmap but an encoding table. */
+ /* The driver is responsible for making up charmap objects */
+ /* corresponding to these tables. */
+ /* */
+ typedef struct Z1_CharMapRec_* Z1_CharMap;
+
+
+ /*************************************************************************/
+ /* */
+ /* HERE BEGINS THE TYPE1 SPECIFIC STUFF */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* Z1_SizeRec */
+ /* */
+ /* <Description> */
+ /* Type 1 size record. */
+ /* */
+ typedef struct Z1_SizeRec_
+ {
+ FT_SizeRec root;
+ FT_Bool valid;
+ Z1_Size_Hints* hints; /* defined in the hinter. This allows */
+ /* us to experiment with different */
+ /* hinting schemes without having to */
+ /* change `z1objs' each time. */
+ } Z1_SizeRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* Z1_GlyphSlotRec */
+ /* */
+ /* <Description> */
+ /* Type 1 glyph slot record. */
+ /* */
+ typedef struct Z1_GlyphSlotRec_
+ {
+ FT_GlyphSlotRec root;
+
+ FT_Bool hint;
+ FT_Bool scaled;
+
+ FT_Int max_points;
+ FT_Int max_contours;
+
+ FT_Fixed x_scale;
+ FT_Fixed y_scale;
+
+ Z1_Glyph_Hints* hints; /* defined in the hinter */
+
+ } Z1_GlyphSlotRec;
+
+
+ LOCAL_DEF
+ FT_Error Z1_Init_Face( FT_Stream stream,
+ T1_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+ LOCAL_DEF
+ void Z1_Done_Face( T1_Face face );
+
+ LOCAL_DEF
+ FT_Error Z1_Init_Driver( Z1_Driver driver );
+
+ LOCAL_DEF
+ void Z1_Done_Driver( Z1_Driver driver );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* Z1OBJS_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* z1parse.c */
+/* */
+/* Experimental Type 1 parser (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* The Type 1 parser is in charge of the following: */
+ /* */
+ /* - provide an implementation of a growing sequence of objects called */
+ /* a `Z1_Table' (used to build various tables needed by the loader). */
+ /* */
+ /* - opening .pfb and .pfa files to extract their top-level and private */
+ /* dictionaries. */
+ /* */
+ /* - read numbers, arrays & strings from any dictionary. */
+ /* */
+ /* See `z1load.c' to see how data is loaded from the font file. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1errors.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1parse.h"
+
+#else
+
+#include <type1z/z1parse.h>
+
+#endif
+
+
+#include <string.h> /* for strncmp() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_z1parse
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** IMPLEMENTATION OF Z1_TABLE OBJECT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Z1_New_Table */
+ /* */
+ /* <Description> */
+ /* Initialises a Z1_Table. */
+ /* */
+ /* <InOut> */
+ /* table :: The address of the target table. */
+ /* */
+ /* <Input> */
+ /* count :: The table size = the maximum number of elements. */
+ /* */
+ /* memory :: The memory object to use for all subsequent */
+ /* reallocations. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error Z1_New_Table( Z1_Table* table,
+ FT_Int count,
+ FT_Memory memory )
+ {
+ FT_Error error;
+
+
+ table->memory = memory;
+ if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) ||
+ ALLOC_ARRAY( table->lengths, count, FT_Byte* ) )
+ goto Exit;
+
+ table->max_elems = count;
+ table->init = 0xdeadbeef;
+ table->num_elems = 0;
+ table->block = 0;
+ table->capacity = 0;
+ table->cursor = 0;
+
+ Exit:
+ if ( error )
+ FREE( table->elements );
+
+ return error;
+ }
+
+
+ static
+ void shift_elements( Z1_Table* table,
+ FT_Byte* old_base )
+ {
+ FT_Long delta = table->block - old_base;
+ FT_Byte** offset = table->elements;
+ FT_Byte** limit = offset + table->max_elems;
+
+
+ if ( delta )
+ for ( ; offset < limit; offset++ )
+ {
+ if ( offset[0] )
+ offset[0] += delta;
+ }
+ }
+
+
+ static
+ FT_Error reallocate_t1_table( Z1_Table* table,
+ FT_Int new_size )
+ {
+ FT_Memory memory = table->memory;
+ FT_Byte* old_base = table->block;
+ FT_Error error;
+
+
+ /* reallocate the base block */
+ if ( REALLOC( table->block, table->capacity, new_size ) )
+ return error;
+
+ table->capacity = new_size;
+
+ /* shift all offsets if necessary */
+ if ( old_base )
+ shift_elements( table, old_base );
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Z1_Add_Table */
+ /* */
+ /* <Description> */
+ /* Adds an object to a Z1_Table, possibly growing its memory block. */
+ /* */
+ /* <InOut> */
+ /* table :: The target table. */
+ /* */
+ /* <Input> */
+ /* index :: The index of the object in the table. */
+ /* */
+ /* object :: The address of the object to copy in memory. */
+ /* */
+ /* length :: The length in bytes of the source object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. An error is returned if a */
+ /* reallocation fails. */
+ /* */
+ LOCAL_FUNC
+ FT_Error Z1_Add_Table( Z1_Table* table,
+ FT_Int index,
+ void* object,
+ FT_Int length )
+ {
+ if ( index < 0 || index > table->max_elems )
+ {
+ FT_ERROR(( "Z1_Add_Table: invalid index\n" ));
+ return T1_Err_Syntax_Error;
+ }
+
+ /* grow the base block if needed */
+ if ( table->cursor + length > table->capacity )
+ {
+ FT_Error error;
+ FT_Int new_size = table->capacity;
+
+
+ while ( new_size < table->cursor + length )
+ new_size += 1024;
+
+ error = reallocate_t1_table( table, new_size );
+ if ( error )
+ return error;
+ }
+
+ /* add the object to the base block and adjust offset */
+ table->elements[index] = table->block + table->cursor;
+ table->lengths [index] = length;
+ MEM_Copy( table->block + table->cursor, object, length );
+
+ table->cursor += length;
+ return T1_Err_Ok;
+ }
+
+
+#if 0
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Z1_Done_Table */
+ /* */
+ /* <Description> */
+ /* Finalizes a Z1_Table (i.e., reallocate it to its current cursor). */
+ /* */
+ /* <InOut> */
+ /* table :: The target table. */
+ /* */
+ /* <Note> */
+ /* This function does NOT release the heap's memory block. It is up */
+ /* to the caller to clean it, or reference it in its own structures. */
+ /* */
+ LOCAL_FUNC
+ void Z1_Done_Table( Z1_Table* table )
+ {
+ FT_Memory memory = table->memory;
+ FT_Error error;
+ FT_Byte* old_base;
+
+
+ /* should never fail, as rec.cursor <= rec.size */
+ old_base = table->block;
+ if ( !old_base )
+ return;
+
+ (void)REALLOC( table->block, table->capacity, table->cursor );
+ table->capacity = table->cursor;
+
+ if ( old_base != table->block )
+ shift_elements( table, old_base );
+ }
+
+#endif /* 0 */
+
+
+ LOCAL_FUNC
+ void Z1_Release_Table( Z1_Table* table )
+ {
+ FT_Memory memory = table->memory;
+
+
+ if ( table->init == (FT_Long)0xDEADBEEF )
+ {
+ FREE( table->block );
+ FREE( table->elements );
+ FREE( table->lengths );
+ table->init = 0;
+ }
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** INPUT STREAM PARSER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#define IS_Z1_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' )
+#define IS_Z1_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' )
+
+#define IS_Z1_SPACE( c ) ( IS_Z1_WHITESPACE( c ) || IS_Z1_LINESPACE( c ) )
+
+
+ LOCAL_FUNC
+ void Z1_Skip_Spaces( Z1_Parser* parser )
+ {
+ FT_Byte* cur = parser->cursor;
+ FT_Byte* limit = parser->limit;
+
+
+ while ( cur < limit )
+ {
+ FT_Byte c = *cur;
+
+
+ if ( !IS_Z1_SPACE( c ) )
+ break;
+ cur++;
+ }
+ parser->cursor = cur;
+ }
+
+
+ LOCAL_FUNC
+ void Z1_ToToken( Z1_Parser* parser,
+ Z1_Token_Rec* token )
+ {
+ FT_Byte* cur;
+ FT_Byte* limit;
+ FT_Byte starter, ender;
+ FT_Int embed;
+
+
+ token->type = t1_token_none;
+ token->start = 0;
+ token->limit = 0;
+
+ /* first of all, skip space */
+ Z1_Skip_Spaces( parser );
+
+ cur = parser->cursor;
+ limit = parser->limit;
+
+ if ( cur < limit )
+ {
+ switch ( *cur )
+ {
+ /************* check for strings ***********************/
+ case '(':
+ token->type = t1_token_string;
+ ender = ')';
+ goto Lookup_Ender;
+
+ /************* check for programs/array ****************/
+ case '{':
+ token->type = t1_token_array;
+ ender = '}';
+ goto Lookup_Ender;
+
+ /************* check for table/array ******************/
+ case '[':
+ token->type = t1_token_array;
+ ender = ']';
+
+ Lookup_Ender:
+ embed = 1;
+ starter = *cur++;
+ token->start = cur;
+ while ( cur < limit )
+ {
+ if ( *cur == starter )
+ embed++;
+ else if ( *cur == ender )
+ {
+ embed--;
+ if ( embed <= 0 )
+ {
+ token->limit = cur++;
+ break;
+ }
+ }
+ cur++;
+ }
+ break;
+
+ /* **************** otherwise, it's any token **********/
+ default:
+ token->start = cur++;
+ token->type = t1_token_any;
+ while ( cur < limit && !IS_Z1_SPACE( *cur ) )
+ cur++;
+
+ token->limit = cur;
+ }
+
+ if ( !token->limit )
+ {
+ token->start = 0;
+ token->type = t1_token_none;
+ }
+
+ parser->cursor = cur;
+ }
+ }
+
+
+ LOCAL_FUNC
+ void Z1_ToTokenArray( Z1_Parser* parser,
+ Z1_Token_Rec* tokens,
+ FT_UInt max_tokens,
+ FT_Int* pnum_tokens )
+ {
+ Z1_Token_Rec master;
+
+
+ *pnum_tokens = -1;
+
+ Z1_ToToken( parser, &master );
+ if ( master.type == t1_token_array )
+ {
+ FT_Byte* old_cursor = parser->cursor;
+ FT_Byte* old_limit = parser->limit;
+ Z1_Token_Rec* cur = tokens;
+ Z1_Token_Rec* limit = cur + max_tokens;
+
+
+ parser->cursor = master.start;
+ parser->limit = master.limit;
+
+ while ( parser->cursor < parser->limit )
+ {
+ Z1_Token_Rec token;
+
+
+ Z1_ToToken( parser, &token );
+ if ( !token.type )
+ break;
+
+ if ( cur < limit )
+ *cur = token;
+
+ cur++;
+ }
+
+ *pnum_tokens = cur - tokens;
+
+ parser->cursor = old_cursor;
+ parser->limit = old_limit;
+ }
+ }
+
+
+ static
+ FT_Long t1_toint( FT_Byte** cursor,
+ FT_Byte* limit )
+ {
+ FT_Long result = 0;
+ FT_Byte* cur = *cursor;
+ FT_Byte c, d;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ c = *cur;
+ d = (FT_Byte)( c - '0' );
+ if ( d < 10 )
+ break;
+
+ if ( c == '-' )
+ {
+ cur++;
+ break;
+ }
+ }
+
+ if ( cur < limit )
+ {
+ do
+ {
+ d = (FT_Byte)( cur[0] - '0' );
+ if ( d >= 10 )
+ break;
+
+ result = result * 10 + d;
+ cur++;
+
+ } while ( cur < limit );
+
+ if ( c == '-' )
+ result = -result;
+ }
+
+ *cursor = cur;
+ return result;
+ }
+
+
+ static
+ FT_Long t1_tofixed( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Long power_ten )
+ {
+ FT_Byte* cur = *cursor;
+ FT_Long num, divider, result;
+ FT_Int sign = 0;
+ FT_Byte d;
+
+
+ if ( cur >= limit )
+ return 0;
+
+ /* first of all, read the integer part */
+ result = t1_toint( &cur, limit ) << 16;
+ num = 0;
+ divider = 1;
+
+ if ( result < 0 )
+ {
+ sign = 1;
+ result = -result;
+ }
+
+ if ( cur >= limit )
+ goto Exit;
+
+ /* read decimal part, if any */
+ if ( *cur == '.' && cur + 1 < limit )
+ {
+ cur++;
+
+ for (;;)
+ {
+ d = (FT_Byte)( *cur - '0' );
+ if ( d >= 10 )
+ break;
+
+ if ( divider < 10000000L )
+ {
+ num = num * 10 + d;
+ divider *= 10;
+ }
+
+ cur++;
+ if ( cur >= limit )
+ break;
+ }
+ }
+
+ /* read exponent, if any */
+ if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) )
+ {
+ cur++;
+ power_ten += t1_toint( &cur, limit );
+ }
+
+ Exit:
+ /* raise to power of ten if needed */
+ while ( power_ten > 0 )
+ {
+ result = result * 10;
+ num = num * 10;
+ power_ten--;
+ }
+
+ while ( power_ten < 0 )
+ {
+ result = result / 10;
+ divider = divider * 10;
+ power_ten++;
+ }
+
+ if ( num )
+ result += FT_DivFix( num, divider );
+
+ if ( sign )
+ result = -result;
+
+ *cursor = cur;
+ return result;
+ }
+
+
+ static
+ FT_Int t1_tocoordarray( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Int max_coords,
+ FT_Short* coords )
+ {
+ FT_Byte* cur = *cursor;
+ FT_Int count = 0;
+ FT_Byte c, ender;
+
+
+ if ( cur >= limit )
+ goto Exit;
+
+ /* check for the beginning of an array. If not, only one number will */
+ /* be read */
+ c = *cur;
+ ender = 0;
+
+ if ( c == '[' )
+ ender = ']';
+
+ if ( c == '{' )
+ ender = '}';
+
+ if ( ender )
+ cur++;
+
+ /* now, read the coordinates */
+ for ( ; cur < limit; )
+ {
+ /* skip whitespace in front of data */
+ for (;;)
+ {
+ c = *cur;
+ if ( c != ' ' && c != '\t' )
+ break;
+
+ cur++;
+ if ( cur >= limit )
+ goto Exit;
+ }
+
+ if ( count >= max_coords || c == ender )
+ break;
+
+ coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 );
+ count++;
+
+ if ( !ender )
+ break;
+ }
+
+ Exit:
+ *cursor = cur;
+ return count;
+ }
+
+
+ static
+ FT_Int t1_tofixedarray( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Int max_values,
+ FT_Fixed* values,
+ FT_Int power_ten )
+ {
+ FT_Byte* cur = *cursor;
+ FT_Int count = 0;
+ FT_Byte c, ender;
+
+
+ if ( cur >= limit ) goto Exit;
+
+ /* check for the beginning of an array. If not, only one number will */
+ /* be read */
+ c = *cur;
+ ender = 0;
+
+ if ( c == '[' )
+ ender = ']';
+
+ if ( c == '{' )
+ ender = '}';
+
+ if ( ender )
+ cur++;
+
+ /* now, read the values */
+ for ( ; cur < limit; )
+ {
+ /* skip whitespace in front of data */
+ for (;;)
+ {
+ c = *cur;
+ if ( c != ' ' && c != '\t' )
+ break;
+
+ cur++;
+ if ( cur >= limit )
+ goto Exit;
+ }
+
+ if ( count >= max_values || c == ender )
+ break;
+
+ values[count] = t1_tofixed( &cur, limit, power_ten );
+ count++;
+
+ if ( !ender )
+ break;
+ }
+
+ Exit:
+ *cursor = cur;
+ return count;
+ }
+
+
+#if 0
+
+ static
+ FT_String* t1_tostring( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Memory memory )
+ {
+ FT_Byte* cur = *cursor;
+ FT_Int len = 0;
+ FT_Int count;
+ FT_String* result;
+ FT_Error error;
+
+
+ /* XXX: some stupid fonts have a `Notice' or `Copyright' string */
+ /* that simply doesn't begin with an opening parenthesis, even */
+ /* though they have a closing one! E.g. "amuncial.pfb" */
+ /* */
+ /* We must deal with these ill-fated cases there. Note that */
+ /* these fonts didn't work with the old Type 1 driver as the */
+ /* notice/copyright was not recognized as a valid string token */
+ /* and made the old token parser commit errors. */
+
+ while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
+ cur++;
+ if ( cur + 1 >= limit )
+ return 0;
+
+ if ( *cur == '(' )
+ cur++; /* skip the opening parenthesis, if there is one */
+
+ *cursor = cur;
+ count = 0;
+
+ /* then, count its length */
+ for ( ; cur < limit; cur++ )
+ {
+ if ( *cur == '(' )
+ count++;
+
+ else if ( *cur == ')' )
+ {
+ count--;
+ if ( count < 0 )
+ break;
+ }
+ }
+
+ len = cur - *cursor;
+ if ( cur >= limit || ALLOC( result, len + 1 ) )
+ return 0;
+
+ /* now copy the string */
+ MEM_Copy( result, *cursor, len );
+ result[len] = '\0';
+ *cursor = cur;
+ return result;
+ }
+
+#endif /* 0 */
+
+
+ static
+ int t1_tobool( FT_Byte** cursor,
+ FT_Byte* limit )
+ {
+ FT_Byte* cur = *cursor;
+ FT_Bool result = 0;
+
+
+ /* return 1 if we find `true', 0 otherwise */
+ if ( cur + 3 < limit &&
+ cur[0] == 't' &&
+ cur[1] == 'r' &&
+ cur[2] == 'u' &&
+ cur[3] == 'e' )
+ {
+ result = 1;
+ cur += 5;
+ }
+ else if ( cur + 4 < limit &&
+ cur[0] == 'f' &&
+ cur[1] == 'a' &&
+ cur[2] == 'l' &&
+ cur[3] == 's' &&
+ cur[4] == 'e' )
+ {
+ result = 0;
+ cur += 6;
+ }
+
+ *cursor = cur;
+ return result;
+ }
+
+
+ /* Load a simple field (i.e. non-table) into the current list of objects */
+ LOCAL_FUNC
+ FT_Error Z1_Load_Field( Z1_Parser* parser,
+ const Z1_Field_Rec* field,
+ void** objects,
+ FT_UInt max_objects,
+ FT_ULong* pflags )
+ {
+ Z1_Token_Rec token;
+ FT_Byte* cur;
+ FT_Byte* limit;
+ FT_UInt count;
+ FT_UInt index;
+ FT_Error error;
+
+
+ Z1_ToToken( parser, &token );
+ if ( !token.type )
+ goto Fail;
+
+ count = 1;
+ index = 0;
+ cur = token.start;
+ limit = token.limit;
+
+ if ( token.type == t1_token_array )
+ {
+ /* if this is an array, and we have no blend, an error occurs */
+ if ( max_objects == 0 )
+ goto Fail;
+
+ count = max_objects;
+ index = 1;
+ }
+
+ for ( ; count > 0; count--, index++ )
+ {
+ FT_Byte* q = (FT_Byte*)objects[index] + field->offset;
+ FT_Long val;
+ FT_String* string;
+
+ switch ( field->type )
+ {
+ case t1_field_bool:
+ val = t1_tobool( &cur, limit );
+ goto Store_Integer;
+
+ case t1_field_fixed:
+ val = t1_tofixed( &cur, limit, 3 );
+ goto Store_Integer;
+
+ case t1_field_integer:
+ val = t1_toint( &cur, limit );
+
+ Store_Integer:
+ switch ( field->size )
+ {
+ case 1:
+ *(FT_Byte*)q = (FT_Byte)val;
+ break;
+
+ case 2:
+ *(FT_UShort*)q = (FT_UShort)val;
+ break;
+
+ case 4:
+ *(FT_UInt32*)q = (FT_UInt32)val;
+ break;
+
+ default: /* for 64-bit systems */
+ *(FT_Long*)q = val;
+ }
+ break;
+
+ case t1_field_string:
+ {
+ FT_Memory memory = parser->memory;
+ FT_UInt len = limit-cur;
+
+ if ( ALLOC( string, len + 1 ) )
+ goto Exit;
+
+ MEM_Copy( string, cur, len );
+ string[len] = 0;
+
+ *(FT_String**)q = string;
+ }
+ break;
+
+ default:
+ /* an error occured */
+ goto Fail;
+ }
+ }
+
+ if ( pflags )
+ *pflags |= 1L << field->flag_bit;
+
+ error = FT_Err_Ok;
+
+ Exit:
+ return error;
+
+ Fail:
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+
+#define T1_MAX_TABLE_ELEMENTS 32
+
+
+ LOCAL_FUNC
+ FT_Error Z1_Load_Field_Table( Z1_Parser* parser,
+ const Z1_Field_Rec* field,
+ void** objects,
+ FT_UInt max_objects,
+ FT_ULong* pflags )
+ {
+ Z1_Token_Rec elements[T1_MAX_TABLE_ELEMENTS];
+ Z1_Token_Rec* token;
+ FT_Int num_elements;
+ FT_Error error = 0;
+ FT_Byte* old_cursor;
+ FT_Byte* old_limit;
+ Z1_Field_Rec fieldrec = *(Z1_Field_Rec*)field;
+
+
+ Z1_ToTokenArray( parser, elements, 32, &num_elements );
+ if ( num_elements < 0 )
+ goto Fail;
+
+ if ( num_elements > T1_MAX_TABLE_ELEMENTS )
+ num_elements = T1_MAX_TABLE_ELEMENTS;
+
+ old_cursor = parser->cursor;
+ old_limit = parser->limit;
+
+ /* we store the elements count */
+ *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) = num_elements;
+
+ /* we now load each element, adjusting the field.offset on each one */
+ token = elements;
+ for ( ; num_elements > 0; num_elements--, token++ )
+ {
+ parser->cursor = token->start;
+ parser->limit = token->limit;
+ Z1_Load_Field( parser, &fieldrec, objects, max_objects, 0 );
+ fieldrec.offset += fieldrec.size;
+ }
+
+ if ( pflags )
+ *pflags |= 1L << field->flag_bit;
+
+ parser->cursor = old_cursor;
+ parser->limit = old_limit;
+
+ Exit:
+ return error;
+
+ Fail:
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+
+ LOCAL_FUNC
+ FT_Long Z1_ToInt ( Z1_Parser* parser )
+ {
+ return t1_toint( &parser->cursor, parser->limit );
+ }
+
+
+ LOCAL_FUNC
+ FT_Long Z1_ToFixed( Z1_Parser* parser,
+ FT_Int power_ten )
+ {
+ return t1_tofixed( &parser->cursor, parser->limit, power_ten );
+ }
+
+
+ LOCAL_FUNC
+ FT_Int Z1_ToCoordArray( Z1_Parser* parser,
+ FT_Int max_coords,
+ FT_Short* coords )
+ {
+ return t1_tocoordarray( &parser->cursor, parser->limit,
+ max_coords, coords );
+ }
+
+
+ LOCAL_FUNC
+ FT_Int Z1_ToFixedArray( Z1_Parser* parser,
+ FT_Int max_values,
+ FT_Fixed* values,
+ FT_Int power_ten )
+ {
+ return t1_tofixedarray( &parser->cursor, parser->limit,
+ max_values, values, power_ten );
+ }
+
+
+#if 0
+
+ LOCAL_FUNC
+ FT_String* Z1_ToString( Z1_Parser* parser )
+ {
+ return t1_tostring( &parser->cursor, parser->limit, parser->memory );
+ }
+
+
+ LOCAL_FUNC
+ FT_Bool Z1_ToBool( Z1_Parser* parser )
+ {
+ return t1_tobool( &parser->cursor, parser->limit );
+ }
+
+#endif /* 0 */
+
+
+ static
+ FT_Error read_pfb_tag( FT_Stream stream,
+ FT_UShort* tag,
+ FT_Long* size )
+ {
+ FT_Error error;
+
+
+ if ( READ_UShort( *tag ) )
+ goto Exit;
+
+ if ( *tag == 0x8001 || *tag == 0x8002 )
+ {
+ FT_Long asize;
+
+
+ if ( READ_ULong( asize ) )
+ goto Exit;
+
+ /* swap between big and little endianness */
+ *size = ( ( asize & 0xFF000000L ) >> 24 ) |
+ ( ( asize & 0x00FF0000L ) >> 8 ) |
+ ( ( asize & 0x0000FF00L ) << 8 ) |
+ ( ( asize & 0x000000FFL ) << 24 );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ FT_Error Z1_New_Parser( Z1_Parser* parser,
+ FT_Stream stream,
+ FT_Memory memory )
+ {
+ FT_Error error;
+ FT_UShort tag;
+ FT_Long size;
+
+
+ parser->stream = stream;
+ parser->memory = memory;
+ parser->base_len = 0;
+ parser->base_dict = 0;
+ parser->private_len = 0;
+ parser->private_dict = 0;
+ parser->in_pfb = 0;
+ parser->in_memory = 0;
+ parser->single_block = 0;
+
+ parser->cursor = 0;
+ parser->limit = 0;
+
+ /******************************************************************/
+ /* */
+ /* Here a short summary of what is going on: */
+ /* */
+ /* When creating a new Type 1 parser, we try to locate and load */
+ /* the base dictionary if this is possible (i.e. for PFB */
+ /* files). Otherwise, we load the whole font into memory. */
+ /* */
+ /* When `loading' the base dictionary, we only setup pointers */
+ /* in the case of a memory-based stream. Otherwise, we */
+ /* allocate and load the base dictionary in it. */
+ /* */
+ /* parser->in_pfb is set if we are in a binary (".pfb") font. */
+ /* parser->in_memory is set if we have a memory stream. */
+ /* */
+
+ /* try to compute the size of the base dictionary; */
+ /* look for a Postscript binary file tag, i.e 0x8001 */
+ if ( FILE_Seek( 0L ) )
+ goto Exit;
+
+ error = read_pfb_tag( stream, &tag, &size );
+ if ( error )
+ goto Exit;
+
+ if ( tag != 0x8001 )
+ {
+ /* assume that this is a PFA file for now; an error will */
+ /* be produced later when more things are checked */
+ (void)FILE_Seek( 0L );
+ size = stream->size;
+ }
+ else
+ parser->in_pfb = 1;
+
+ /* now, try to load `size' bytes of the `base' dictionary we */
+ /* found previously */
+
+ /* if it is a memory-based resource, set up pointers */
+ if ( !stream->read )
+ {
+ parser->base_dict = (FT_Byte*)stream->base + stream->pos;
+ parser->base_len = size;
+ parser->in_memory = 1;
+
+ /* check that the `size' field is valid */
+ if ( FILE_Skip( size ) )
+ goto Exit;
+ }
+ else
+ {
+ /* read segment in memory */
+ if ( ALLOC( parser->base_dict, size ) ||
+ FILE_Read( parser->base_dict, size ) )
+ goto Exit;
+ parser->base_len = size;
+ }
+
+ /* Now check font format; we must see `%!PS-AdobeFont-1' */
+ /* or `%!FontType' */
+ {
+ if ( size <= 16 ||
+ ( strncmp( (const char*)parser->base_dict,
+ "%!PS-AdobeFont-1", 16 ) &&
+ strncmp( (const char*)parser->base_dict,
+ "%!FontType", 10 ) ) )
+ {
+ FT_TRACE2(( "[not a Type1 font]\n" ));
+ error = FT_Err_Unknown_File_Format;
+ }
+ else
+ {
+ parser->cursor = parser->base_dict;
+ parser->limit = parser->cursor + parser->base_len;
+ }
+ }
+
+ Exit:
+ if ( error && !parser->in_memory )
+ FREE( parser->base_dict );
+
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ void Z1_Done_Parser( Z1_Parser* parser )
+ {
+ FT_Memory memory = parser->memory;
+
+
+ /* always free the private dictionary */
+ FREE( parser->private_dict );
+
+ /* free the base dictionary only when we have a disk stream */
+ if ( !parser->in_memory )
+ FREE( parser->base_dict );
+ }
+
+
+ /* return the value of an hexadecimal digit */
+ static
+ int hexa_value( char c )
+ {
+ unsigned int d;
+
+
+ d = (unsigned int)( c - '0' );
+ if ( d <= 9 )
+ return (int)d;
+
+ d = (unsigned int)( c - 'a' );
+ if ( d <= 5 )
+ return (int)( d + 10 );
+
+ d = (unsigned int)( c - 'A' );
+ if ( d <= 5 )
+ return (int)( d + 10 );
+
+ return -1;
+ }
+
+
+ LOCAL_FUNC
+ void Z1_Decrypt( FT_Byte* buffer,
+ FT_Int length,
+ FT_UShort seed )
+ {
+ while ( length > 0 )
+ {
+ FT_Byte plain;
+
+
+ plain = ( *buffer ^ ( seed >> 8 ) );
+ seed = ( *buffer + seed ) * 52845 + 22719;
+ *buffer++ = plain;
+ length--;
+ }
+ }
+
+
+ LOCAL_FUNC
+ FT_Error Z1_Get_Private_Dict( Z1_Parser* parser )
+ {
+ FT_Stream stream = parser->stream;
+ FT_Memory memory = parser->memory;
+ FT_Error error = 0;
+ FT_Long size;
+
+
+ if ( parser->in_pfb )
+ {
+ /* in the case of the PFB format, the private dictionary can be */
+ /* made of several segments. We thus first read the number of */
+ /* segments to compute the total size of the private dictionary */
+ /* then re-read them into memory. */
+ FT_Long start_pos = FILE_Pos();
+ FT_UShort tag;
+ FT_Long size;
+
+
+ parser->private_len = 0;
+ for (;;)
+ {
+ error = read_pfb_tag( stream, &tag, &size );
+ if ( error )
+ goto Fail;
+
+ if ( tag != 0x8002 )
+ break;
+
+ parser->private_len += size;
+
+ if ( FILE_Skip( size ) )
+ goto Fail;
+ }
+
+ /* Check that we have a private dictionary there */
+ /* and allocate private dictionary buffer */
+ if ( parser->private_len == 0 )
+ {
+ FT_ERROR(( "Z1_Get_Private_Dict:" ));
+ FT_ERROR(( " invalid private dictionary section\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ if ( FILE_Seek( start_pos ) ||
+ ALLOC( parser->private_dict, parser->private_len ) )
+ goto Fail;
+
+ parser->private_len = 0;
+ for (;;)
+ {
+ error = read_pfb_tag( stream, &tag, &size );
+ if ( error || tag != 0x8002 )
+ {
+ error = FT_Err_Ok;
+ break;
+ }
+
+ if ( FILE_Read( parser->private_dict + parser->private_len, size ) )
+ goto Fail;
+
+ parser->private_len += size;
+ }
+ }
+ else
+ {
+ /* we have already `loaded' the whole PFA font file into memory; */
+ /* if this is a memory resource, allocate a new block to hold */
+ /* the private dict. Otherwise, simply overwrite into the base */
+ /* dictionary block in the heap. */
+
+ /* first of all, look at the `eexec' keyword */
+ FT_Byte* cur = parser->base_dict;
+ FT_Byte* limit = cur + parser->base_len;
+ FT_Byte c;
+
+
+ for (;;)
+ {
+ c = cur[0];
+ if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */
+ /* newline + 4 chars */
+ {
+ if ( cur[1] == 'e' && cur[2] == 'x' &&
+ cur[3] == 'e' && cur[4] == 'c' )
+ {
+ cur += 6; /* we skip the newling after the `eexec' */
+
+ /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n; we need to */
+ /* skip the extra \n if we find it */
+ if ( cur[0] == '\n' )
+ cur++;
+
+ break;
+ }
+ }
+ cur++;
+ if ( cur >= limit )
+ {
+ FT_ERROR(( "Z1_Get_Private_Dict:" ));
+ FT_ERROR(( " could not find `eexec' keyword\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+ }
+
+ /* now determine where to write the _encrypted_ binary private */
+ /* dictionary. We overwrite the base dictionary for disk-based */
+ /* resources and allocate a new block otherwise */
+
+ size = parser->base_len - ( cur - parser->base_dict);
+
+ if ( parser->in_memory )
+ {
+ /* note that we allocate one more byte to put a terminating `0' */
+ if ( ALLOC( parser->private_dict, size + 1 ) )
+ goto Fail;
+ parser->private_len = size;
+ }
+ else
+ {
+ parser->single_block = 1;
+ parser->private_dict = parser->base_dict;
+ parser->private_len = size;
+ parser->base_dict = 0;
+ parser->base_len = 0;
+ }
+
+ /* now determine whether the private dictionary is encoded in binary */
+ /* or hexadecimal ASCII format -- decode it accordingly */
+
+ /* we need to access the next 4 bytes (after the final \r following */
+ /* the `eexec' keyword); if they all are hexadecimal digits, then */
+ /* we have a case of ASCII storage */
+
+ if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) |
+ hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 )
+
+ /* binary encoding -- `simply' copy the private dict */
+ MEM_Copy( parser->private_dict, cur, size );
+
+ else
+ {
+ /* ASCII hexadecimal encoding */
+
+ FT_Byte* write;
+ FT_Int count;
+
+
+ write = parser->private_dict;
+ count = 0;
+
+ for ( ;cur < limit; cur++ )
+ {
+ int hex1;
+
+
+ /* check for newline */
+ if ( cur[0] == '\r' || cur[0] == '\n' )
+ continue;
+
+ /* exit if we have a non-hexadecimal digit that isn't a newline */
+ hex1 = hexa_value( cur[0] );
+ if ( hex1 < 0 || cur + 1 >= limit )
+ break;
+
+ /* otherwise, store byte */
+ *write++ = ( hex1 << 4 ) | hexa_value( cur[1] );
+ count++;
+ cur++;
+ }
+
+ /* put a safeguard */
+ parser->private_len = write - parser->private_dict;
+ *write++ = 0;
+ }
+ }
+
+ /* we now decrypt the encoded binary private dictionary */
+ Z1_Decrypt( parser->private_dict, parser->private_len, 55665 );
+ parser->cursor = parser->private_dict;
+ parser->limit = parser->cursor + parser->private_len;
+
+ Fail:
+ Exit:
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* z1parse.h */
+/* */
+/* Experimental Type 1 parser (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef Z1PARSE_H
+#define Z1PARSE_H
+
+#include <freetype/internal/t1types.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /* simple enumeration type used to identify token types */
+ typedef enum Z1_Token_Type_
+ {
+ t1_token_none = 0,
+ t1_token_any,
+ t1_token_string,
+ t1_token_array,
+
+ /* do not remove */
+ t1_token_max
+
+ } Z1_Token_Type;
+
+
+ /* a simple structure used to identify tokens */
+ typedef struct Z1_Token_Rec_
+ {
+ FT_Byte* start; /* first character of token in input stream */
+ FT_Byte* limit; /* first character after the token */
+ Z1_Token_Type type; /* type of token.. */
+
+ } Z1_Token_Rec;
+
+
+ /* enumeration type used to identify object fields */
+ typedef enum Z1_Field_Type_
+ {
+ t1_field_none = 0,
+ t1_field_bool,
+ t1_field_integer,
+ t1_field_fixed,
+ t1_field_string,
+ t1_field_integer_array,
+ t1_field_fixed_array,
+
+ /* do not remove */
+ t1_field_max
+
+ } Z1_Field_Type;
+
+
+ /* structure type used to model object fields */
+ typedef struct Z1_Field_Rec_
+ {
+ Z1_Field_Type type; /* type of field */
+ FT_UInt offset; /* offset of field in object */
+ FT_UInt size; /* size of field in bytes */
+ FT_UInt array_max; /* maximum number of elements for array */
+ FT_UInt count_offset; /* offset of element count for arrays */
+ FT_Int flag_bit; /* bit number for field flag */
+
+ } Z1_Field_Rec;
+
+
+#define Z1_FIELD_REF( s, f ) ( ((s*)0)->f )
+
+#define Z1_FIELD_BOOL( _ftype, _fname ) \
+ { \
+ t1_field_bool, \
+ (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \
+ sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \
+ 0, 0, 0 \
+ }
+
+#define Z1_FIELD_NUM( _ftype, _fname ) \
+ { \
+ t1_field_integer, \
+ (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \
+ sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \
+ 0, 0, 0 \
+ }
+
+#define Z1_FIELD_FIXED( _ftype, _fname, _power ) \
+ { \
+ t1_field_fixed, \
+ (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \
+ sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \
+ 0, 0, 0 \
+ }
+
+#define Z1_FIELD_STRING( _ftype, _fname ) \
+ { \
+ t1_field_string, \
+ (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \
+ sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \
+ 0, 0, 0 \
+ }
+
+#define Z1_FIELD_NUM_ARRAY( _ftype, _fname, _fcount, _fmax ) \
+ { \
+ t1_field_integer, \
+ (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \
+ sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \
+ _fmax, \
+ (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fcount ), \
+ 0 \
+ }
+
+#define Z1_FIELD_FIXED_ARRAY( _ftype, _fname, _fcount, _fmax ) \
+ { \
+ t1_field_fixed, \
+ (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \
+ sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \
+ _fmax, \
+ (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fcount ), \
+ 0 \
+ }
+
+#define Z1_FIELD_NUM_ARRAY2( _ftype, _fname, _fmax ) \
+ { \
+ t1_field_integer, \
+ (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \
+ sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \
+ _fmax, \
+ 0, 0 \
+ }
+
+#define Z1_FIELD_FIXED_ARRAY2( _ftype, _fname, _fmax ) \
+ { \
+ t1_field_fixed, \
+ (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \
+ sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \
+ _fmax, \
+ 0, 0 \
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* Z1_Table */
+ /* */
+ /* <Description> */
+ /* A Z1_Table is a simple object used to store an array of objects in */
+ /* a single memory block. */
+ /* */
+ /* <Fields> */
+ /* block :: The address in memory of the growheap's block. This */
+ /* can change between two object adds, due to the use of */
+ /* reallocation. */
+ /* */
+ /* cursor :: The current top of the grow heap within its block. */
+ /* */
+ /* capacity :: The current size of the heap block. Increments in */
+ /* 1kByte blocks. */
+ /* */
+ /* init :: A boolean. Set when the table has been initialized */
+ /* (the table user should set this field). */
+ /* */
+ /* max_elems :: The maximum number of elements in the table. */
+ /* */
+ /* num_elems :: The current number of elements in the table. */
+ /* */
+ /* elements :: A table of element addresses within the block. */
+ /* */
+ /* lengths :: A table of element sizes within the block. */
+ /* */
+ /* memory :: The memory object used for memory operations */
+ /* (allocation/reallocation). */
+ /* */
+ typedef struct Z1_Table_
+ {
+ FT_Byte* block; /* current memory block */
+ FT_Int cursor; /* current cursor in memory block */
+ FT_Int capacity; /* current size of memory block */
+ FT_Long init;
+
+ FT_Int max_elems;
+ FT_Int num_elems;
+ FT_Byte** elements; /* addresses of table elements */
+ FT_Int* lengths; /* lengths of table elements */
+
+ FT_Memory memory;
+
+ } Z1_Table;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* Z1_Parser */
+ /* */
+ /* <Description> */
+ /* A Z1_Parser is an object used to parse a Type 1 fonts very */
+ /* quickly. */
+ /* */
+ /* <Fields> */
+ /* stream :: The current input stream. */
+ /* */
+ /* memory :: The current memory object. */
+ /* */
+ /* base_dict :: A pointer to the top-level dictionary. */
+ /* */
+ /* base_len :: The length in bytes of the top dictionary. */
+ /* */
+ /* private_dict :: A pointer to the private dictionary. */
+ /* */
+ /* private_len :: The length in bytes of the private dictionary. */
+ /* */
+ /* in_pfb :: A boolean. Indicates that we are handling a PFB */
+ /* file. */
+ /* */
+ /* in_memory :: A boolean. Indicates a memory-based stream. */
+ /* */
+ /* single_block :: A boolean. Indicates that the private dictionary */
+ /* is stored in lieu of the base dictionary. */
+ /* */
+ /* cursor :: The current parser cursor. */
+ /* */
+ /* limit :: The current parser limit (first byte after the */
+ /* current dictionary). */
+ /* */
+ /* error :: The current parsing error. */
+ /* */
+ typedef struct Z1_Parser_
+ {
+ FT_Stream stream;
+ FT_Memory memory;
+
+ FT_Byte* base_dict;
+ FT_Int base_len;
+
+ FT_Byte* private_dict;
+ FT_Int private_len;
+
+ FT_Byte in_pfb;
+ FT_Byte in_memory;
+ FT_Byte single_block;
+
+ FT_Byte* cursor;
+ FT_Byte* limit;
+ FT_Error error;
+
+ } Z1_Parser;
+
+
+ LOCAL_DEF
+ FT_Error Z1_New_Table( Z1_Table* table,
+ FT_Int count,
+ FT_Memory memory );
+
+
+ LOCAL_DEF
+ FT_Error Z1_Add_Table( Z1_Table* table,
+ FT_Int index,
+ void* object,
+ FT_Int length );
+
+#if 0
+ LOCAL_DEF
+ void Z1_Done_Table( Z1_Table* table );
+#endif
+
+ LOCAL_DEF
+ void Z1_Release_Table( Z1_Table* table );
+
+ LOCAL_DEF
+ FT_Long Z1_ToInt( Z1_Parser* parser );
+
+ LOCAL_DEF
+ FT_Long Z1_ToFixed( Z1_Parser* parser,
+ FT_Int power_ten );
+
+ LOCAL_DEF
+ FT_Int Z1_ToCoordArray( Z1_Parser* parser,
+ FT_Int max_coords,
+ FT_Short* coords );
+
+ LOCAL_DEF
+ FT_Int Z1_ToFixedArray( Z1_Parser* parser,
+ FT_Int max_values,
+ FT_Fixed* values,
+ FT_Int power_ten );
+
+#if 0
+ LOCAL_DEF
+ FT_String* Z1_ToString( Z1_Parser* parser );
+
+ LOCAL_DEF
+ FT_Bool Z1_ToBool( Z1_Parser* parser );
+#endif
+
+
+ LOCAL_DEF
+ void Z1_Skip_Spaces( Z1_Parser* parser );
+
+ LOCAL_DEF
+ void Z1_ToToken( Z1_Parser* parser,
+ Z1_Token_Rec* token );
+
+ LOCAL_FUNC
+ void Z1_ToTokenArray( Z1_Parser* parser,
+ Z1_Token_Rec* tokens,
+ FT_UInt max_tokens,
+ FT_Int* pnum_tokens );
+
+ LOCAL_DEF
+ FT_Error Z1_Load_Field( Z1_Parser* parser,
+ const Z1_Field_Rec* field,
+ void** objects,
+ FT_UInt max_objects,
+ FT_ULong* pflags );
+
+ LOCAL_DEF
+ FT_Error Z1_Load_Field_Table( Z1_Parser* parser,
+ const Z1_Field_Rec* field,
+ void** objects,
+ FT_UInt max_objects,
+ FT_ULong* pflags );
+
+
+ LOCAL_DEF
+ FT_Error Z1_New_Parser( Z1_Parser* parser,
+ FT_Stream stream,
+ FT_Memory memory );
+
+ LOCAL_DEF
+ FT_Error Z1_Get_Private_Dict( Z1_Parser* parser );
+
+ LOCAL_DEF
+ void Z1_Decrypt( FT_Byte* buffer,
+ FT_Int length,
+ FT_UShort seed );
+
+ LOCAL_DEF
+ void Z1_Done_Parser( Z1_Parser* parser );
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* Z1PARSE_H */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* z1tokens.h */
+/* */
+/* Experimental Type 1 tokenizer (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#undef T1TYPE
+#define T1TYPE T1_FontInfo
+
+ Z1_FONTINFO_STRING( "version", version )
+ Z1_FONTINFO_STRING( "Notice", notice )
+ Z1_FONTINFO_STRING( "FullName", full_name )
+ Z1_FONTINFO_STRING( "FamilyName", family_name )
+ Z1_FONTINFO_STRING( "Weight", weight )
+
+ Z1_FONTINFO_NUM ( "ItalicAngle", italic_angle )
+ Z1_FONTINFO_BOOL ( "isFixedPitch", is_fixed_pitch )
+ Z1_FONTINFO_NUM ( "UnderlinePosition", underline_position )
+ Z1_FONTINFO_NUM ( "UnderlineThickness", underline_thickness )
+
+
+#undef T1TYPE
+#define T1TYPE T1_Private
+
+ Z1_PRIVATE_NUM ( "UniqueID", unique_id )
+ Z1_PRIVATE_NUM ( "lenIV", lenIV )
+ Z1_PRIVATE_NUM ( "LanguageGroup", language_group )
+ Z1_PRIVATE_NUM ( "password", password )
+
+ Z1_PRIVATE_FIXED ( "BlueScale", blue_scale )
+ Z1_PRIVATE_NUM ( "BlueShift", blue_shift )
+ Z1_PRIVATE_NUM ( "BlueFuzz", blue_fuzz )
+
+ Z1_PRIVATE_NUM_TABLE ( "BlueValues", blue_values, 14, num_blue_values )
+ Z1_PRIVATE_NUM_TABLE ( "OtherBlues", other_blues, 10, num_other_blues )
+ Z1_PRIVATE_NUM_TABLE ( "FamilyBlues", family_blues, 14, num_family_blues )
+ Z1_PRIVATE_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10, \
+ num_family_other_blues )
+
+ Z1_PRIVATE_NUM_TABLE2( "StdHW", standard_width, 1 )
+ Z1_PRIVATE_NUM_TABLE2( "StdVW", standard_height, 1 )
+ Z1_PRIVATE_NUM_TABLE2( "MinFeature", min_feature, 2 )
+
+ Z1_PRIVATE_NUM_TABLE ( "StemSnapH", snap_widths, 12, num_snap_widths )
+ Z1_PRIVATE_NUM_TABLE ( "StemSnapV", snap_heights, 12, num_snap_heights )
+
+
+#undef T1TYPE
+#define T1TYPE T1_Font
+
+ Z1_TOPDICT_NUM( "PaintType", paint_type )
+ Z1_TOPDICT_NUM( "FontType", font_type )
+ Z1_TOPDICT_NUM( "StrokeWidth", stroke_width )
+
+
+#if 0
+
+ /* define the font info dictionary parsing callbacks */
+#undef FACE
+#define FACE (face->type1.font_info)
+
+ PARSE_STRING( "version", version )
+ PARSE_STRING( "Notice", notice )
+ PARSE_STRING( "FullName", full_name )
+ PARSE_STRING( "FamilyName", family_name )
+ PARSE_STRING( "Weight", weight )
+
+ PARSE_INT ( "ItalicAngle", italic_angle )
+ PARSE_BOOL ( "isFixedPitch", is_fixed_pitch )
+ PARSE_NUM ( "UnderlinePosition", underline_position, FT_Short )
+ PARSE_NUM ( "UnderlineThickness", underline_thickness, FT_UShort )
+
+
+ /* define the private dict parsing callbacks */
+#undef FACE
+#define FACE (face->type1.private_dict)
+
+ PARSE_INT ("UniqueID", unique_id )
+ PARSE_INT ("lenIV", lenIV )
+
+ PARSE_COORDS ( "BlueValues", num_blues, 14, blue_values)
+ PARSE_COORDS ( "OtherBlues", num_other_blues, 10, other_blues)
+
+ PARSE_COORDS ( "FamilyBlues", num_family_blues, 14, family_blues )
+ PARSE_COORDS ( "FamilyOtherBlues", num_family_other_blues, 10,
+ family_other_blues )
+
+ PARSE_FIXED ( "BlueScale", blue_scale )
+ PARSE_INT ( "BlueShift", blue_shift )
+
+ PARSE_INT ( "BlueFuzz", blue_fuzz )
+
+ PARSE_COORDS2( "StdHW", 1, standard_width )
+ PARSE_COORDS2( "StdVW", 1, standard_height )
+
+ PARSE_COORDS ( "StemSnapH", num_snap_widths, 12, stem_snap_widths )
+ PARSE_COORDS ( "StemSnapV", num_snap_heights, 12, stem_snap_heights )
+
+ PARSE_INT ( "LanguageGroup", language_group )
+ PARSE_INT ( "password", password )
+ PARSE_COORDS2( "MinFeature", 2, min_feature )
+
+
+ /* define the top-level dictionary parsing callbacks */
+#undef FACE
+#define FACE (face->type1)
+
+/*PARSE_STRING ( "FontName", font_name ) -- handled by special routine */
+ PARSE_NUM ( "PaintType", paint_type, FT_Byte )
+ PARSE_NUM ( "FontType", font_type, FT_Byte )
+ PARSE_FIXEDS2( "FontMatrix", 4, font_matrix )
+/*PARSE_COORDS2( "FontBBox", 4, font_bbox ) -- handled by special routine */
+ PARSE_INT ( "StrokeWidth", stroke_width )
+
+#undef FACE
+
+#endif /* 0 */
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* ftsystem.c */
+/* */
+/* Unix-specific FreeType low-level system interface (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ftconfig.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/ftsystem.h>
+#include <freetype/fterrors.h>
+#include <freetype/fttypes.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+ /* memory-mapping includes and definitions */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sys/mman.h>
+#ifndef MAP_FILE
+#define MAP_FILE 0x00
+#endif
+
+ /*************************************************************************/
+ /* */
+ /* The prototype for munmap() is not provided on SunOS. This needs to */
+ /* have a check added later to see if the GNU C library is being used. */
+ /* If so, then this prototype is not needed. */
+ /* */
+#if defined( __sun__ ) && !defined( SVR4 ) && !defined( __SVR4 )
+ extern int munmap( caddr_t addr,
+ int len );
+#endif
+
+#include <sys/stat.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* MEMORY MANAGEMENT INTERFACE */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_alloc */
+ /* */
+ /* <Description> */
+ /* The memory allocation function. */
+ /* */
+ /* <Input> */
+ /* memory :: A pointer to the memory object. */
+ /* size :: The requested size in bytes. */
+ /* */
+ /* <Return> */
+ /* block :: The address of newly allocated block. */
+ /* */
+ static
+ void* ft_alloc( FT_Memory memory,
+ long size )
+ {
+ FT_UNUSED( memory );
+
+ return malloc( size );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_realloc */
+ /* */
+ /* <Description> */
+ /* The memory reallocation function. */
+ /* */
+ /* <Input> */
+ /* memory :: A pointer to the memory object. */
+ /* */
+ /* cur_size :: The current size of the allocated memory block. */
+ /* */
+ /* new_size :: The newly requested size in bytes. */
+ /* */
+ /* block :: The current address of the block in memory. */
+ /* */
+ /* <Return> */
+ /* The address of the reallocated memory block. */
+ /* */
+ static
+ void* ft_realloc( FT_Memory memory,
+ long cur_size,
+ long new_size,
+ void* block )
+ {
+ FT_UNUSED( memory );
+ FT_UNUSED( cur_size );
+
+ return realloc( block, new_size );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_free */
+ /* */
+ /* <Description> */
+ /* The memory release function. */
+ /* */
+ /* <Input> */
+ /* memory :: A pointer to the memory object. */
+ /* */
+ /* block :: The address of block in memory to be freed. */
+ /* */
+ static
+ void ft_free( FT_Memory memory,
+ void* block )
+ {
+ FT_UNUSED( memory );
+
+ free( block );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RESOURCE MANAGEMENT INTERFACE */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_io
+
+ /* We use the macro STREAM_FILE for convenience to extract the */
+ /* system-specific stream handle from a given FreeType stream object */
+#define STREAM_FILE( stream ) ( (FILE*)stream->descriptor.pointer )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_close_stream */
+ /* */
+ /* <Description> */
+ /* The function to close a stream. */
+ /* */
+ /* <Input> */
+ /* stream :: A pointer to the stream object. */
+ /* */
+ static
+ void ft_close_stream( FT_Stream stream )
+ {
+ munmap ( stream->descriptor.pointer, stream->size );
+
+ stream->descriptor.pointer = NULL;
+ stream->size = 0;
+ stream->base = 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Stream */
+ /* */
+ /* <Description> */
+ /* Creates a new stream object. */
+ /* */
+ /* <Input> */
+ /* filepathname :: The name of the stream (usually a file) to be */
+ /* opened. */
+ /* */
+ /* stream :: A pointer to the stream object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_New_Stream( const char* filepathname,
+ FT_Stream stream )
+ {
+ int file;
+ struct stat stat_buf;
+
+
+ if ( !stream )
+ return FT_Err_Invalid_Stream_Handle;
+
+ /* open the file */
+ file = open( filepathname, O_RDONLY );
+ if ( file < 0 )
+ {
+ FT_ERROR(( "FT_New_Stream:" ));
+ FT_ERROR(( " could not open `%s'\n", filepathname ));
+ return FT_Err_Cannot_Open_Resource;
+ }
+
+ if ( fstat( file, &stat_buf ) < 0 )
+ {
+ FT_ERROR(( "FT_New_Stream:" ));
+ FT_ERROR(( " could not `fstat' file `%s'\n", filepathname ));
+ goto Fail_Map;
+ }
+
+ stream->size = stat_buf.st_size;
+ stream->pos = 0;
+ stream->base = mmap( NULL,
+ stream->size,
+ PROT_READ,
+ MAP_FILE | MAP_PRIVATE,
+ file,
+ 0 );
+
+ if ( (long)stream->base == -1 )
+ {
+ FT_ERROR(( "FT_New_Stream:" ));
+ FT_ERROR(( " could not `mmap' file `%s'\n", filepathname ));
+ goto Fail_Map;
+ }
+
+ close( file );
+
+ stream->descriptor.pointer = stream->base;
+ stream->pathname.pointer = (char*)filepathname;
+
+ stream->close = ft_close_stream;
+ stream->read = 0;
+
+ FT_TRACE1(( "FT_New_Stream:" ));
+ FT_TRACE1(( " opened `%s' (%d bytes) successfully\n",
+ filepathname, stream->size ));
+
+ return FT_Err_Ok;
+
+ Fail_Map:
+ close( file );
+
+ stream->base = NULL;
+ stream->size = 0;
+ stream->pos = 0;
+
+ return FT_Err_Cannot_Open_Stream;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Memory */
+ /* */
+ /* <Description> */
+ /* Creates a new memory object. */
+ /* */
+ /* <Return> */
+ /* A pointer to the new memory object. 0 in case of error. */
+ /* */
+ FT_EXPORT_FUNC( FT_Memory ) FT_New_Memory( void )
+ {
+ FT_Memory memory;
+
+
+ memory = (FT_Memory)malloc( sizeof ( *memory ) );
+ if ( memory )
+ {
+ memory->user = 0;
+ memory->alloc = ft_alloc;
+ memory->realloc = ft_realloc;
+ memory->free = ft_free;
+ }
+
+ return memory;
+ }
+
+
+/* END */
--- /dev/null
+make_module_list: add_windows_driver
+
+add_windows_driver:
+ $(OPEN_DRIVER)winfnt_driver_class$(CLOSE_DRIVER)
+ $(ECHO_DRIVER)winfnt $(ECHO_DRIVER_DESC)Windows bitmap fonts with extension *.fnt or *.fon$(ECHO_DRIVER_DONE)
+
--- /dev/null
+#
+# FreeType 2 Windows FNT/FON driver configuration rules
+#
+
+
+# Copyright 1996-2000 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# Windows driver directory
+#
+FNT_DIR := $(SRC_)winfonts
+FNT_DIR_ := $(FNT_DIR)$(SEP)
+
+
+FNT_COMPILE := $(FT_COMPILE)
+
+
+# Windows driver sources (i.e., C files)
+#
+FNT_DRV_SRC := $(FNT_DIR_)winfnt.c
+
+# Windows driver headers
+#
+FNT_DRV_H := $(FNT_DRV_SRC:%.c=%.h)
+
+
+# Windows driver object(s)
+#
+# FNT_DRV_OBJ_M is used during `multi' builds
+# FNT_DRV_OBJ_S is used during `single' builds
+#
+FNT_DRV_OBJ_M := $(FNT_DRV_SRC:$(FNT_DIR_)%.c=$(OBJ_)%.$O)
+FNT_DRV_OBJ_S := $(OBJ_)winfnt.$O
+
+# Windows driver source file for single build
+#
+FNT_DRV_SRC_S := $(FNT_DIR_)winfnt.c
+
+
+# Windows driver - single object
+#
+$(FNT_DRV_OBJ_S): $(FNT_DRV_SRC_S) $(FNT_DRV_SRC) $(FREETYPE_H) $(FNT_DRV_H)
+ $(FNT_COMPILE) $T$@ $(FNT_DRV_SRC_S)
+
+
+# Windows driver - multiple objects
+#
+$(OBJ_)%.$O: $(FNT_DIR_)%.c $(FREETYPE_H) $(FNT_DRV_H)
+ $(FNT_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(FNT_DRV_OBJ_S)
+DRV_OBJS_M += $(FNT_DRV_OBJ_M)
+
+# EOF
--- /dev/null
+/***************************************************************************/
+/* */
+/* winfnt.c */
+/* */
+/* FreeType font driver for Windows FNT/FON files */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "winfnt.h"
+
+#else
+
+#include <winfonts/winfnt.h>
+
+#endif
+
+
+#include <freetype/fterrors.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftobjs.h>
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_winfnt
+
+
+ static
+ const FT_Frame_Field winmz_header_fields[] =
+ {
+ FT_FRAME_START( 64 ),
+ FT_FRAME_USHORT_LE ( WinMZ_Header, magic ),
+ FT_FRAME_SKIP_BYTES( 29 * 2 ),
+ FT_FRAME_ULONG_LE ( WinMZ_Header, lfanew ),
+ FT_FRAME_END
+ };
+
+ static
+ const FT_Frame_Field winne_header_fields[] =
+ {
+ FT_FRAME_START( 40 ),
+ FT_FRAME_USHORT_LE ( WinNE_Header, magic ),
+ FT_FRAME_SKIP_BYTES( 34 ),
+ FT_FRAME_USHORT_LE ( WinNE_Header, resource_tab_offset ),
+ FT_FRAME_USHORT_LE ( WinNE_Header, rname_tab_offset ),
+ FT_FRAME_END
+ };
+
+ static
+ const FT_Frame_Field winfnt_header_fields[] =
+ {
+ FT_FRAME_START( 134 ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, version ),
+ FT_FRAME_ULONG_LE ( WinFNT_Header, file_size ),
+ FT_FRAME_BYTES ( WinFNT_Header, copyright, 60 ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, file_type ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, nominal_point_size ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, vertical_resolution ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, horizontal_resolution ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, ascent ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, internal_leading ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, external_leading ),
+ FT_FRAME_BYTE ( WinFNT_Header, italic ),
+ FT_FRAME_BYTE ( WinFNT_Header, underline ),
+ FT_FRAME_BYTE ( WinFNT_Header, strike_out ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, weight ),
+ FT_FRAME_BYTE ( WinFNT_Header, charset ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, pixel_width ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, pixel_height ),
+ FT_FRAME_BYTE ( WinFNT_Header, pitch_and_family ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, avg_width ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, max_width ),
+ FT_FRAME_BYTE ( WinFNT_Header, first_char ),
+ FT_FRAME_BYTE ( WinFNT_Header, last_char ),
+ FT_FRAME_BYTE ( WinFNT_Header, default_char ),
+ FT_FRAME_BYTE ( WinFNT_Header, break_char ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, bytes_per_row ),
+ FT_FRAME_ULONG_LE ( WinFNT_Header, device_offset ),
+ FT_FRAME_ULONG_LE ( WinFNT_Header, face_name_offset ),
+ FT_FRAME_ULONG_LE ( WinFNT_Header, bits_pointer ),
+ FT_FRAME_ULONG_LE ( WinFNT_Header, bits_offset ),
+ FT_FRAME_BYTE ( WinFNT_Header, reserved ),
+ FT_FRAME_ULONG_LE ( WinFNT_Header, flags ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, A_space ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, B_space ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, C_space ),
+ FT_FRAME_USHORT_LE( WinFNT_Header, color_table_offset ),
+ FT_FRAME_BYTES ( WinFNT_Header, reserved, 4 ),
+ FT_FRAME_END
+ };
+
+
+ static
+ void fnt_done_font( FT_Stream stream,
+ FNT_Font* font )
+ {
+ if ( font->fnt_frame )
+ RELEASE_Frame( font->fnt_frame );
+
+ font->fnt_size = 0;
+ font->fnt_frame = 0;
+ }
+
+
+ static
+ FT_Error fnt_load_font( FT_Stream stream,
+ FNT_Font* font )
+ {
+ FT_Error error;
+ WinFNT_Header* header = &font->header;
+
+
+ /* first of all, read the FNT header */
+ if ( FILE_Seek( font->offset ) ||
+ READ_Fields( winfnt_header_fields, header ) )
+ goto Exit;
+
+ /* check header */
+ if ( header->version != 0x200 &&
+ header->version != 0x300 )
+ {
+ FT_TRACE2(( "[not a valid FNT file]\n" ));
+ error = FT_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ if ( header->file_type & 1 )
+ {
+ FT_TRACE2(( "can't handle vector FNT fonts\n" ));
+ error = FT_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ /* small fixup -- some fonts have the `pixel_width' field set to 0 */
+ if ( header->pixel_width == 0 )
+ header->pixel_width = header->pixel_height;
+
+ /* this is a FNT file/table, we now extract its frame */
+ if ( FILE_Seek( font->offset ) ||
+ EXTRACT_Frame( header->file_size, font->fnt_frame ) )
+ goto Exit;
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ void fnt_done_fonts( FNT_Face face )
+ {
+ FT_Memory memory = FT_FACE(face)->memory;
+ FT_Stream stream = FT_FACE(face)->stream;
+ FNT_Font* cur = face->fonts;
+ FNT_Font* limit = cur + face->num_fonts;
+
+
+ for ( ; cur < limit; cur++ )
+ fnt_done_font( stream, cur );
+
+ FREE( face->fonts );
+ face->num_fonts = 0;
+ }
+
+ static
+ FT_Error fnt_get_dll_fonts( FNT_Face face )
+ {
+ FT_Error error;
+ FT_Stream stream = FT_FACE(face)->stream;
+ FT_Memory memory = FT_FACE(face)->memory;
+ WinMZ_Header mz_header;
+
+
+ face->fonts = 0;
+ face->num_fonts = 0;
+
+ /* does it begin with a MZ header? */
+ if ( FILE_Seek( 0 ) ||
+ READ_Fields( winmz_header_fields, &mz_header ) )
+ goto Exit;
+
+ error = FT_Err_Unknown_File_Format;
+ if ( mz_header.magic == WINFNT_MZ_MAGIC )
+ {
+ /* yes, now look for a NE header in the file */
+ WinNE_Header ne_header;
+
+
+ if ( FILE_Seek( mz_header.lfanew ) ||
+ READ_Fields( winne_header_fields, &ne_header ) )
+ goto Exit;
+
+ error = FT_Err_Unknown_File_Format;
+ if ( ne_header.magic == WINFNT_NE_MAGIC )
+ {
+ /* good, now look in the resource table for each FNT resource */
+ FT_ULong res_offset = mz_header.lfanew +
+ ne_header.resource_tab_offset;
+
+ FT_UShort size_shift;
+ FT_UShort font_count = 0;
+ FT_ULong font_offset = 0;
+
+
+ if ( FILE_Seek( res_offset ) ||
+ ACCESS_Frame( ne_header.rname_tab_offset -
+ ne_header.resource_tab_offset ) )
+ goto Exit;
+
+ size_shift = GET_UShortLE();
+
+ for (;;)
+ {
+ FT_UShort type_id, count;
+
+
+ type_id = GET_UShortLE();
+ if ( !type_id )
+ break;
+
+ count = GET_UShortLE();
+
+ if ( type_id == 0x8008 )
+ {
+ font_count = count;
+ font_offset = FILE_Pos() + 4 + ( stream->cursor - stream->limit );
+ break;
+ }
+
+ stream->cursor += 4 + count * 12;
+ }
+ FORGET_Frame();
+
+ if ( !font_count || !font_offset )
+ {
+ FT_TRACE2(( "this file doesn't contain any FNT resources!\n" ));
+ error = FT_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ if ( FILE_Seek( font_offset ) ||
+ ALLOC_ARRAY( face->fonts, font_count, FNT_Font ) )
+ goto Exit;
+
+ face->num_fonts = font_count;
+
+ if ( ACCESS_Frame( (FT_Long)font_count * 12 ) )
+ goto Exit;
+
+ /* now read the offset and position of each FNT font */
+ {
+ FNT_Font* cur = face->fonts;
+ FNT_Font* limit = cur + font_count;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ cur->offset = (FT_ULong)GET_UShortLE() << size_shift;
+ cur->fnt_size = (FT_ULong)GET_UShortLE() << size_shift;
+ cur->size_shift = size_shift;
+ stream->cursor += 8;
+ }
+ }
+ FORGET_Frame();
+
+ /* finally, try to load each font there */
+ {
+ FNT_Font* cur = face->fonts;
+ FNT_Font* limit = cur + font_count;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ error = fnt_load_font( stream, cur );
+ if ( error )
+ goto Fail;
+ }
+ }
+ }
+ }
+
+ Fail:
+ if ( error )
+ fnt_done_fonts( face );
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ void FNT_Done_Face( FNT_Face face )
+ {
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+
+ fnt_done_fonts( face );
+
+ FREE( face->root.available_sizes );
+ face->root.num_fixed_sizes = 0;
+ }
+
+
+ static
+ FT_Error FNT_Init_Face( FT_Stream stream,
+ FNT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error;
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+ FT_UNUSED( face_index );
+
+
+ /* try to load several fonts from a DLL */
+ error = fnt_get_dll_fonts( face );
+ if ( error )
+ {
+ /* this didn't work, now try to load a single FNT font */
+ FT_Memory memory = FT_FACE_MEMORY( face );
+ FNT_Font* font;
+
+ if ( ALLOC( face->fonts, sizeof ( *face->fonts ) ) )
+ goto Exit;
+
+ face->num_fonts = 1;
+ font = face->fonts;
+
+ font->offset = 0;
+ font->fnt_size = stream->size;
+
+ error = fnt_load_font( stream, font );
+ if ( error )
+ goto Fail;
+ }
+
+ /* all right, one or more fonts were loaded; we now need to */
+ /* fill the root FT_Face fields with relevant information */
+ {
+ FT_Face root = FT_FACE( face );
+ FNT_Font* fonts = face->fonts;
+ FNT_Font* limit = fonts + face->num_fonts;
+ FNT_Font* cur;
+
+
+ root->num_faces = 1;
+ root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
+ FT_FACE_FLAG_HORIZONTAL;
+
+ if ( fonts->header.avg_width == fonts->header.max_width )
+ root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ if ( fonts->header.italic )
+ root->style_flags |= FT_STYLE_FLAG_ITALIC;
+
+ if ( fonts->header.weight >= 800 )
+ root->style_flags |= FT_STYLE_FLAG_BOLD;
+
+ /* Setup the `fixed_sizes' array */
+ if ( ALLOC_ARRAY( root->available_sizes, face->num_fonts,
+ FT_Bitmap_Size ) )
+ goto Fail;
+
+ root->num_fixed_sizes = face->num_fonts;
+
+ {
+ FT_Bitmap_Size* size = root->available_sizes;
+
+
+ for ( cur = fonts; cur < limit; cur++, size++ )
+ {
+ size->width = cur->header.pixel_width;
+ size->height = cur->header.pixel_height;
+ }
+ }
+
+ /* Setup the `charmaps' array */
+ root->charmaps = &face->charmap_handle;
+ root->num_charmaps = 1;
+
+ face->charmap.encoding = ft_encoding_unicode;
+ face->charmap.platform_id = 3;
+ face->charmap.encoding_id = 1;
+ face->charmap.face = root;
+
+ face->charmap_handle = &face->charmap;
+
+ root->charmap = face->charmap_handle;
+
+ /* setup remaining flags */
+ root->num_glyphs = fonts->header.last_char -
+ fonts->header.first_char + 1;
+
+ root->family_name = (FT_String*)fonts->fnt_frame +
+ fonts->header.face_name_offset;
+ root->style_name = "Regular";
+
+ if ( root->style_flags & FT_STYLE_FLAG_BOLD )
+ {
+ if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
+ root->style_name = "Bold Italic";
+ else
+ root->style_name = "Bold";
+ }
+ else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
+ root->style_name = "Italic";
+ }
+
+ Fail:
+ if ( error )
+ FNT_Done_Face( face );
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ FT_Error FNT_Set_Pixel_Size( FNT_Size size )
+ {
+ /* look up a font corresponding to the current pixel size */
+ FNT_Face face = (FNT_Face)FT_SIZE_FACE( size );
+ FNT_Font* cur = face->fonts;
+ FNT_Font* limit = cur + face->num_fonts;
+
+
+ size->font = 0;
+ for ( ; cur < limit; cur++ )
+ {
+ /* we only compare the character height, as fonts used some strange */
+ /* values */
+ if ( cur->header.pixel_height == size->root.metrics.y_ppem )
+ {
+ size->font = cur;
+
+ size->root.metrics.ascender = cur->header.ascent * 64;
+ size->root.metrics.descender = ( cur->header.pixel_height -
+ cur->header.ascent ) * 64;
+ size->root.metrics.height = cur->header.pixel_height * 64;
+ break;
+ }
+ }
+
+ return ( size->font ? FT_Err_Ok : FT_Err_Invalid_Argument );
+ }
+
+
+ static
+ FT_UInt FNT_Get_Char_Index( FT_CharMap charmap,
+ FT_ULong char_code )
+ {
+ FT_UInt result = char_code;
+
+
+ if ( charmap )
+ {
+ FNT_Font* font = ((FNT_Face)charmap->face)->fonts;
+ FT_UInt first = font->header.first_char;
+ FT_UInt count = font->header.last_char - first + 1;
+
+
+ char_code -= first;
+ if ( char_code < count )
+ result = char_code + 1;
+ else
+ result = 0;
+ }
+
+ return result;
+ }
+
+
+ static
+ FT_Error FNT_Load_Glyph( FT_GlyphSlot slot,
+ FNT_Size size,
+ FT_UInt glyph_index,
+ FT_Int load_flags )
+ {
+ FNT_Font* font = size->font;
+ FT_Error error = 0;
+ FT_Byte* p;
+ FT_Int len;
+ FT_Bitmap* bitmap = &slot->bitmap;
+ FT_ULong offset;
+ FT_Bool new_format;
+
+ FT_UNUSED( slot );
+ FT_UNUSED( load_flags );
+
+
+ if ( !font )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ if ( glyph_index > 0 )
+ glyph_index--;
+ else
+ glyph_index = font->header.default_char - font->header.first_char;
+
+ new_format = font->header.version == 0x300;
+ len = new_format ? 6 : 4;
+
+ /* jump to glyph entry */
+ p = font->fnt_frame + 118 + len * glyph_index;
+
+ bitmap->width = NEXT_ShortLE(p);
+
+ if ( new_format )
+ offset = NEXT_ULongLE(p);
+ else
+ offset = NEXT_UShortLE(p);
+
+ /* jump to glyph data */
+ p = font->fnt_frame + /* font->header.bits_offset */ + offset;
+
+ /* allocate and build bitmap */
+ {
+ FT_Memory memory = FT_FACE_MEMORY( slot->face );
+ FT_Int pitch = ( bitmap->width + 7 ) >> 3;
+ FT_Byte* column;
+ FT_Byte* write;
+
+
+ bitmap->pitch = pitch;
+ bitmap->rows = font->header.pixel_height;
+ bitmap->pixel_mode = ft_pixel_mode_mono;
+
+ if ( ALLOC( bitmap->buffer, pitch * bitmap->rows ) )
+ goto Exit;
+
+ column = (FT_Byte*)bitmap->buffer;
+
+ for ( ; pitch > 0; pitch--, column++ )
+ {
+ FT_Byte* limit = p + bitmap->rows;
+
+
+ for ( write = column; p < limit; p++, write += bitmap->pitch )
+ write[0] = p[0];
+ }
+ }
+
+ slot->flags = ft_glyph_own_bitmap;
+ slot->bitmap_left = 0;
+ slot->bitmap_top = font->header.ascent;
+ slot->format = ft_glyph_format_bitmap;
+
+ /* now set up metrics */
+ slot->metrics.horiAdvance = bitmap->width << 6;
+ slot->metrics.horiBearingX = 0;
+ slot->metrics.horiBearingY = slot->bitmap_top << 6;
+
+ slot->linearHoriAdvance = (FT_Fixed)bitmap->width << 16;
+
+ Exit:
+ return error;
+ }
+
+
+ const FT_Driver_Class winfnt_driver_class =
+ {
+ {
+ ft_module_font_driver,
+ sizeof ( FT_DriverRec ),
+
+ "winfonts",
+ 0x10000L,
+ 0x20000L,
+
+ 0,
+
+ (FT_Module_Constructor)0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+ },
+
+ sizeof( FNT_FaceRec ),
+ sizeof( FNT_SizeRec ),
+ sizeof( FT_GlyphSlotRec ),
+
+ (FTDriver_initFace) FNT_Init_Face,
+ (FTDriver_doneFace) FNT_Done_Face,
+ (FTDriver_initSize) 0,
+ (FTDriver_doneSize) 0,
+ (FTDriver_initGlyphSlot)0,
+ (FTDriver_doneGlyphSlot)0,
+
+ (FTDriver_setCharSizes) FNT_Set_Pixel_Size,
+ (FTDriver_setPixelSizes)FNT_Set_Pixel_Size,
+
+ (FTDriver_loadGlyph) FNT_Load_Glyph,
+ (FTDriver_getCharIndex) FNT_Get_Char_Index,
+
+ (FTDriver_getKerning) 0,
+ (FTDriver_attachFile) 0,
+ (FTDriver_getAdvances) 0
+ };
+
+
+/* END */
--- /dev/null
+/***************************************************************************/
+/* */
+/* winfnt.h */
+/* */
+/* FreeType font driver for Windows FNT/FON files */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef WINFNT_H
+#define WINFNT_H
+
+#include <freetype/internal/ftdriver.h>
+
+
+ typedef struct WinMZ_Header_
+ {
+ FT_UShort magic;
+ /* skipped content */
+ FT_UShort lfanew;
+
+ } WinMZ_Header;
+
+
+ typedef struct WinNE_Header_
+ {
+ FT_UShort magic;
+ /* skipped content */
+ FT_UShort resource_tab_offset;
+ FT_UShort rname_tab_offset;
+
+ } WinNE_Header;
+
+
+ typedef struct WinNameInfo_
+ {
+ FT_UShort offset;
+ FT_UShort length;
+ FT_UShort flags;
+ FT_UShort id;
+ FT_UShort handle;
+ FT_UShort usage;
+
+ } WinNameInfo;
+
+
+ typedef struct WinResourceInfo_
+ {
+ FT_UShort type_id;
+ FT_UShort count;
+
+ } WinResourceInfo;
+
+
+#define WINFNT_MZ_MAGIC 0x5A4D
+#define WINFNT_NE_MAGIC 0x454E
+
+
+ typedef struct WinFNT_Header_
+ {
+ FT_UShort version;
+ FT_ULong file_size;
+ FT_Byte copyright[60];
+ FT_UShort file_type;
+ FT_UShort nominal_point_size;
+ FT_UShort vertical_resolution;
+ FT_UShort horizontal_resolution;
+ FT_UShort ascent;
+ FT_UShort internal_leading;
+ FT_UShort external_leading;
+ FT_Byte italic;
+ FT_Byte underline;
+ FT_Byte strike_out;
+ FT_UShort weight;
+ FT_Byte charset;
+ FT_UShort pixel_width;
+ FT_UShort pixel_height;
+ FT_Byte pitch_and_family;
+ FT_UShort avg_width;
+ FT_UShort max_width;
+ FT_Byte first_char;
+ FT_Byte last_char;
+ FT_Byte default_char;
+ FT_Byte break_char;
+ FT_UShort bytes_per_row;
+ FT_ULong device_offset;
+ FT_ULong face_name_offset;
+ FT_ULong bits_pointer;
+ FT_ULong bits_offset;
+ FT_Byte reserved;
+ FT_ULong flags;
+ FT_UShort A_space;
+ FT_UShort B_space;
+ FT_UShort C_space;
+ FT_UShort color_table_offset;
+ FT_Byte reserved2[4];
+
+ } WinFNT_Header;
+
+
+ typedef struct FNT_Font_
+ {
+ FT_ULong offset;
+ FT_Int size_shift;
+
+ WinFNT_Header header;
+
+ FT_Byte* fnt_frame;
+ FT_ULong fnt_size;
+
+ } FNT_Font;
+
+
+ typedef struct FNT_SizeRec_
+ {
+ FT_SizeRec root;
+ FNT_Font* font;
+
+ } FNT_SizeRec, *FNT_Size;
+
+
+ typedef struct FNT_FaceRec_
+ {
+ FT_FaceRec root;
+
+ FT_UInt num_fonts;
+ FNT_Font* fonts;
+
+ FT_CharMap charmap_handle;
+ FT_CharMapRec charmap; /* a single charmap per face */
+
+ } FNT_FaceRec, *FNT_Face;
+
+
+ FT_EXPORT_VAR( const FT_Driver_Class ) winfnt_driver_class;
+
+
+#endif /* WINFNT_H */
+
+
+/* END */