1 |
|
/***************************************************************************/ |
2 |
|
/* */ |
3 |
|
/* afglobal.c */ |
4 |
|
/* */ |
5 |
|
/* Auto-fitter routines to compute global hinting values (body). */ |
6 |
|
/* */ |
7 |
|
/* Copyright 2003, 2004, 2005 by */ |
8 |
|
/* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
9 |
|
/* */ |
10 |
|
/* This file is part of the FreeType project, and may only be used, */ |
11 |
|
/* modified, and distributed under the terms of the FreeType project */ |
12 |
|
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
13 |
|
/* this file you indicate that you have read the license and */ |
14 |
|
/* understand and accept it fully. */ |
15 |
|
/* */ |
16 |
|
/***************************************************************************/ |
17 |
|
|
18 |
|
|
19 |
#include "afglobal.h" |
#include "afglobal.h" |
20 |
#include "afdummy.h" |
#include "afdummy.h" |
21 |
#include "aflatin.h" |
#include "aflatin.h" |
22 |
|
|
23 |
/* populate this list when you add new scripts |
|
24 |
*/ |
/* populate this list when you add new scripts */ |
25 |
static AF_ScriptClass const af_script_classes[] = |
static AF_ScriptClass const af_script_classes[] = |
26 |
{ |
{ |
27 |
& af_dummy_script_class, |
&af_dummy_script_class, |
28 |
& af_latin_script_class, |
&af_latin_script_class, |
29 |
|
|
30 |
NULL /* do not remove */ |
NULL /* do not remove */ |
31 |
}; |
}; |
32 |
|
|
33 |
#define AF_SCRIPT_LIST_DEFAULT 1 /* index of default script in 'af_script_classes' */ |
/* index of default script in `af_script_classes' */ |
34 |
#define AF_SCRIPT_LIST_NONE 255 /* indicates an uncovered glyph */ |
#define AF_SCRIPT_LIST_DEFAULT 1 |
35 |
|
/* indicates an uncovered glyph */ |
36 |
|
#define AF_SCRIPT_LIST_NONE 255 |
37 |
|
|
|
/* |
|
|
* note that glyph_scripts[] is used to map each glyph into |
|
|
* an index into the 'af_script_classes' array. |
|
|
* |
|
|
*/ |
|
|
typedef struct AF_FaceGlobalsRec_ |
|
|
{ |
|
|
FT_Face face; |
|
|
FT_UInt glyph_count; /* same as face->num_glyphs */ |
|
|
FT_Byte* glyph_scripts; |
|
38 |
|
|
39 |
AF_ScriptMetrics metrics[ AF_SCRIPT_MAX ]; |
/* |
40 |
|
* Note that glyph_scripts[] is used to map each glyph into |
41 |
|
* an index into the `af_script_classes' array. |
42 |
|
* |
43 |
|
*/ |
44 |
|
typedef struct AF_FaceGlobalsRec_ |
45 |
|
{ |
46 |
|
FT_Face face; |
47 |
|
FT_UInt glyph_count; /* same as face->num_glyphs */ |
48 |
|
FT_Byte* glyph_scripts; |
49 |
|
|
50 |
} AF_FaceGlobalsRec; |
AF_ScriptMetrics metrics[AF_SCRIPT_MAX]; |
51 |
|
|
52 |
|
} AF_FaceGlobalsRec; |
53 |
|
|
54 |
|
|
55 |
|
/* Compute the script index of each glyph within a given face. */ |
56 |
|
|
|
/* this function is used to compute the script index of each glyph |
|
|
* within a given face |
|
|
*/ |
|
57 |
static FT_Error |
static FT_Error |
58 |
af_face_globals_compute_script_coverage( AF_FaceGlobals globals ) |
af_face_globals_compute_script_coverage( AF_FaceGlobals globals ) |
59 |
{ |
{ |
60 |
FT_Error error = 0; |
FT_Error error = FT_Err_Ok; |
61 |
FT_Face face = globals->face; |
FT_Face face = globals->face; |
62 |
FT_CharMap old_charmap = face->charmap; |
FT_CharMap old_charmap = face->charmap; |
63 |
FT_Byte* gscripts = globals->glyph_scripts; |
FT_Byte* gscripts = globals->glyph_scripts; |
64 |
FT_UInt ss; |
FT_UInt ss; |
65 |
|
|
66 |
/* the value 255 means "uncovered glyph" |
|
67 |
*/ |
/* the value 255 means `uncovered glyph' */ |
68 |
FT_MEM_SET( globals->glyph_scripts, |
FT_MEM_SET( globals->glyph_scripts, |
69 |
AF_SCRIPT_LIST_NONE, |
AF_SCRIPT_LIST_NONE, |
70 |
globals->glyph_count ); |
globals->glyph_count ); |
72 |
error = FT_Select_Charmap( face, FT_ENCODING_UNICODE ); |
error = FT_Select_Charmap( face, FT_ENCODING_UNICODE ); |
73 |
if ( error ) |
if ( error ) |
74 |
{ |
{ |
75 |
/* ignore this error, we'll simply use Latin as the standard |
/* |
76 |
* script. XXX: Shouldn't we rather disable hinting ?? |
* Ignore this error; we simply use Latin as the standard |
77 |
|
* script. XXX: Shouldn't we rather disable hinting? |
78 |
*/ |
*/ |
79 |
error = 0; |
error = FT_Err_Ok; |
80 |
goto Exit; |
goto Exit; |
81 |
} |
} |
82 |
|
|
83 |
/* scan each script in a Unicode charmap |
/* scan each script in a Unicode charmap */ |
|
*/ |
|
84 |
for ( ss = 0; af_script_classes[ss]; ss++ ) |
for ( ss = 0; af_script_classes[ss]; ss++ ) |
85 |
{ |
{ |
86 |
AF_ScriptClass clazz = af_script_classes[ss]; |
AF_ScriptClass clazz = af_script_classes[ss]; |
87 |
AF_Script_UniRange range; |
AF_Script_UniRange range; |
88 |
|
|
89 |
|
|
90 |
if ( clazz->script_uni_ranges == NULL ) |
if ( clazz->script_uni_ranges == NULL ) |
91 |
continue; |
continue; |
92 |
|
|
93 |
/* scan all unicode points in the range, and set the corresponding |
/* |
94 |
* glyph script index |
* Scan all unicode points in the range and set the corresponding |
95 |
*/ |
* glyph script index. |
96 |
|
*/ |
97 |
for ( range = clazz->script_uni_ranges; range->first != 0; range++ ) |
for ( range = clazz->script_uni_ranges; range->first != 0; range++ ) |
98 |
{ |
{ |
99 |
FT_ULong charcode = range->first; |
FT_ULong charcode = range->first; |
100 |
FT_UInt gindex; |
FT_UInt gindex; |
101 |
|
|
102 |
|
|
103 |
gindex = FT_Get_Char_Index( face, charcode ); |
gindex = FT_Get_Char_Index( face, charcode ); |
104 |
|
|
105 |
if ( gindex != 0 && |
if ( gindex != 0 && |
106 |
gindex < globals->glyph_count && |
gindex < globals->glyph_count && |
107 |
gscripts[ gindex ] == AF_SCRIPT_LIST_NONE ) |
gscripts[gindex] == AF_SCRIPT_LIST_NONE ) |
108 |
{ |
{ |
109 |
gscripts[ gindex ] = (FT_Byte) ss; |
gscripts[gindex] = (FT_Byte)ss; |
110 |
} |
} |
111 |
|
|
112 |
for (;;) |
for (;;) |
113 |
{ |
{ |
114 |
charcode = FT_Get_Next_Char( face, charcode, &gindex ); |
charcode = FT_Get_Next_Char( face, charcode, &gindex ); |
116 |
if ( gindex == 0 || charcode > range->last ) |
if ( gindex == 0 || charcode > range->last ) |
117 |
break; |
break; |
118 |
|
|
119 |
if ( gindex < globals->glyph_count && |
if ( gindex < globals->glyph_count && |
120 |
gscripts[ gindex ] == AF_SCRIPT_LIST_NONE ) |
gscripts[gindex] == AF_SCRIPT_LIST_NONE ) |
121 |
{ |
{ |
122 |
gscripts[ gindex ] = (FT_Byte) ss; |
gscripts[gindex] = (FT_Byte)ss; |
123 |
} |
} |
124 |
} |
} |
125 |
} |
} |
126 |
} |
} |
127 |
|
|
128 |
Exit: |
Exit: |
129 |
/* by default, all uncovered glyphs are set to the latin script |
/* |
130 |
* XXX: shouldnt' we disable hinting or do something similar ? |
* By default, all uncovered glyphs are set to the latin script. |
131 |
*/ |
* XXX: Shouldnt' we disable hinting or do something similar? |
132 |
|
*/ |
133 |
{ |
{ |
134 |
FT_UInt nn; |
FT_UInt nn; |
135 |
|
|
136 |
|
|
137 |
for ( nn = 0; nn < globals->glyph_count; nn++ ) |
for ( nn = 0; nn < globals->glyph_count; nn++ ) |
138 |
{ |
{ |
139 |
if ( gscripts[ nn ] == AF_SCRIPT_LIST_NONE ) |
if ( gscripts[nn] == AF_SCRIPT_LIST_NONE ) |
140 |
gscripts[ nn ] = AF_SCRIPT_LIST_DEFAULT; |
gscripts[nn] = AF_SCRIPT_LIST_DEFAULT; |
141 |
} |
} |
142 |
} |
} |
143 |
|
|
146 |
} |
} |
147 |
|
|
148 |
|
|
|
|
|
149 |
FT_LOCAL_DEF( FT_Error ) |
FT_LOCAL_DEF( FT_Error ) |
150 |
af_face_globals_new( FT_Face face, |
af_face_globals_new( FT_Face face, |
151 |
AF_FaceGlobals *aglobals ) |
AF_FaceGlobals *aglobals ) |
154 |
FT_Memory memory; |
FT_Memory memory; |
155 |
AF_FaceGlobals globals; |
AF_FaceGlobals globals; |
156 |
|
|
157 |
|
|
158 |
memory = face->memory; |
memory = face->memory; |
159 |
|
|
160 |
if ( !FT_ALLOC( globals, sizeof(*globals) + |
if ( !FT_ALLOC( globals, sizeof ( *globals ) + |
161 |
face->num_glyphs*sizeof(FT_Byte) ) ) |
face->num_glyphs * sizeof ( FT_Byte ) ) ) |
162 |
{ |
{ |
163 |
globals->face = face; |
globals->face = face; |
164 |
globals->glyph_count = face->num_glyphs; |
globals->glyph_count = face->num_glyphs; |
165 |
globals->glyph_scripts = (FT_Byte*)( globals+1 ); |
globals->glyph_scripts = (FT_Byte*)( globals + 1 ); |
166 |
|
|
167 |
error = af_face_globals_compute_script_coverage( globals ); |
error = af_face_globals_compute_script_coverage( globals ); |
168 |
if ( error ) |
if ( error ) |
185 |
FT_Memory memory = globals->face->memory; |
FT_Memory memory = globals->face->memory; |
186 |
FT_UInt nn; |
FT_UInt nn; |
187 |
|
|
188 |
|
|
189 |
for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ ) |
for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ ) |
190 |
{ |
{ |
191 |
if ( globals->metrics[nn] ) |
if ( globals->metrics[nn] ) |
192 |
{ |
{ |
193 |
AF_ScriptClass clazz = af_script_classes[nn]; |
AF_ScriptClass clazz = af_script_classes[nn]; |
194 |
|
|
195 |
|
|
196 |
FT_ASSERT( globals->metrics[nn]->clazz == clazz ); |
FT_ASSERT( globals->metrics[nn]->clazz == clazz ); |
197 |
|
|
198 |
if ( clazz->script_metrics_done ) |
if ( clazz->script_metrics_done ) |
203 |
} |
} |
204 |
|
|
205 |
globals->glyph_count = 0; |
globals->glyph_count = 0; |
206 |
globals->glyph_scripts = NULL; /* no need to free this one !! */ |
globals->glyph_scripts = NULL; /* no need to free this one! */ |
207 |
globals->face = NULL; |
globals->face = NULL; |
208 |
|
|
209 |
FT_FREE( globals ); |
FT_FREE( globals ); |
210 |
} |
} |
211 |
} |
} |
221 |
AF_ScriptClass clazz; |
AF_ScriptClass clazz; |
222 |
FT_Error error = 0; |
FT_Error error = 0; |
223 |
|
|
224 |
|
|
225 |
if ( gindex >= globals->glyph_count ) |
if ( gindex >= globals->glyph_count ) |
226 |
{ |
{ |
227 |
error = FT_Err_Invalid_Argument; |
error = FT_Err_Invalid_Argument; |
228 |
goto Exit; |
goto Exit; |
229 |
} |
} |
230 |
|
|
231 |
index = globals->glyph_scripts[ gindex ]; |
index = globals->glyph_scripts[gindex]; |
232 |
clazz = af_script_classes[ index ]; |
clazz = af_script_classes[index]; |
233 |
metrics = globals->metrics[ clazz->script ]; |
metrics = globals->metrics[clazz->script]; |
234 |
if ( metrics == NULL ) |
if ( metrics == NULL ) |
235 |
{ |
{ |
236 |
/* create the global metrics object when needed |
/* create the global metrics object when needed */ |
|
*/ |
|
237 |
FT_Memory memory = globals->face->memory; |
FT_Memory memory = globals->face->memory; |
238 |
|
|
239 |
|
|
240 |
if ( FT_ALLOC( metrics, clazz->script_metrics_size ) ) |
if ( FT_ALLOC( metrics, clazz->script_metrics_size ) ) |
241 |
goto Exit; |
goto Exit; |
242 |
|
|
255 |
} |
} |
256 |
} |
} |
257 |
|
|
258 |
globals->metrics[ clazz->script ] = metrics; |
globals->metrics[clazz->script] = metrics; |
259 |
} |
} |
260 |
|
|
261 |
Exit: |
Exit: |
262 |
*ametrics = metrics; |
*ametrics = metrics; |
263 |
|
|
264 |
return error; |
return error; |
265 |
} |
} |
266 |
|
|
267 |
|
|
268 |
|
/* END */ |