3 |
#include "afglobal.h" |
#include "afglobal.h" |
4 |
#include "aflatin.h" |
#include "aflatin.h" |
5 |
|
|
6 |
|
|
7 |
FT_LOCAL_DEF( FT_Error ) |
FT_LOCAL_DEF( FT_Error ) |
8 |
af_loader_init( AF_Loader loader, |
af_loader_init( AF_Loader loader, |
9 |
FT_Memory memory ) |
FT_Memory memory ) |
10 |
{ |
{ |
11 |
FT_Error error; |
FT_Error error; |
12 |
|
|
13 |
|
|
14 |
FT_ZERO( loader ); |
FT_ZERO( loader ); |
15 |
|
|
16 |
af_glyph_hints_init( &loader->hints, memory ); |
af_glyph_hints_init( &loader->hints, memory ); |
30 |
|
|
31 |
|
|
32 |
FT_LOCAL_DEF( FT_Error ) |
FT_LOCAL_DEF( FT_Error ) |
33 |
af_loader_reset( AF_Loader loader, |
af_loader_reset( AF_Loader loader, |
34 |
FT_Face face ) |
FT_Face face ) |
35 |
{ |
{ |
36 |
FT_Error error = 0; |
FT_Error error = FT_Err_Ok; |
37 |
|
|
38 |
|
|
39 |
loader->face = face; |
loader->face = face; |
40 |
loader->globals = (AF_FaceGlobals) face->autohint.data; |
loader->globals = (AF_FaceGlobals)face->autohint.data; |
41 |
|
|
42 |
FT_GlyphLoader_Rewind( loader->gloader ); |
FT_GlyphLoader_Rewind( loader->gloader ); |
43 |
|
|
46 |
error = af_face_globals_new( face, &loader->globals ); |
error = af_face_globals_new( face, &loader->globals ); |
47 |
if ( !error ) |
if ( !error ) |
48 |
{ |
{ |
49 |
face->autohint.data = (FT_Pointer) loader->globals; |
face->autohint.data = |
50 |
face->autohint.finalizer = (FT_Generic_Finalizer) af_face_globals_free; |
(FT_Pointer)loader->globals; |
51 |
|
face->autohint.finalizer = |
52 |
|
(FT_Generic_Finalizer)af_face_globals_free; |
53 |
} |
} |
54 |
} |
} |
55 |
|
|
56 |
return error; |
return error; |
57 |
} |
} |
58 |
|
|
59 |
|
|
60 |
FT_LOCAL_DEF( void ) |
FT_LOCAL_DEF( void ) |
61 |
af_loader_done( AF_Loader loader ) |
af_loader_done( AF_Loader loader ) |
62 |
{ |
{ |
63 |
af_glyph_hints_done( &loader->hints ); |
af_glyph_hints_done( &loader->hints ); |
64 |
|
|
77 |
FT_Int32 load_flags, |
FT_Int32 load_flags, |
78 |
FT_UInt depth ) |
FT_UInt depth ) |
79 |
{ |
{ |
80 |
FT_Error error = 0; |
FT_Error error; |
81 |
FT_Face face = loader->face; |
FT_Face face = loader->face; |
82 |
FT_GlyphLoader gloader = loader->gloader; |
FT_GlyphLoader gloader = loader->gloader; |
83 |
AF_ScriptMetrics metrics = loader->metrics; |
AF_ScriptMetrics metrics = loader->metrics; |
85 |
FT_GlyphSlot slot = face->glyph; |
FT_GlyphSlot slot = face->glyph; |
86 |
FT_Slot_Internal internal = slot->internal; |
FT_Slot_Internal internal = slot->internal; |
87 |
|
|
88 |
|
|
89 |
error = FT_Load_Glyph( face, glyph_index, load_flags ); |
error = FT_Load_Glyph( face, glyph_index, load_flags ); |
90 |
if ( error ) |
if ( error ) |
91 |
goto Exit; |
goto Exit; |
95 |
{ |
{ |
96 |
FT_Matrix inverse; |
FT_Matrix inverse; |
97 |
|
|
98 |
|
|
99 |
loader->trans_matrix = internal->glyph_matrix; |
loader->trans_matrix = internal->glyph_matrix; |
100 |
loader->trans_delta = internal->glyph_delta; |
loader->trans_delta = internal->glyph_delta; |
101 |
|
|
110 |
|
|
111 |
switch ( slot->format ) |
switch ( slot->format ) |
112 |
{ |
{ |
113 |
case FT_GLYPH_FORMAT_OUTLINE: |
case FT_GLYPH_FORMAT_OUTLINE: |
114 |
/* translate the loaded glyph when an internal transform |
/* translate the loaded glyph when an internal transform is needed */ |
115 |
* is needed |
if ( loader->transformed ) |
116 |
*/ |
FT_Outline_Translate( &slot->outline, |
117 |
if ( loader->transformed ) |
loader->trans_delta.x, |
118 |
FT_Outline_Translate( &slot->outline, |
loader->trans_delta.y ); |
119 |
loader->trans_delta.x, |
|
120 |
loader->trans_delta.y ); |
/* copy the outline points in the loader's current */ |
121 |
|
/* extra points which is used to keep original glyph coordinates */ |
122 |
/* copy the outline points in the loader's current */ |
error = FT_GlyphLoader_CheckPoints( gloader, |
123 |
/* extra points which is used to keep original glyph coordinates */ |
slot->outline.n_points + 4, |
124 |
error = FT_GlyphLoader_CheckPoints( gloader, |
slot->outline.n_contours ); |
125 |
slot->outline.n_points + 4, |
if ( error ) |
126 |
slot->outline.n_contours ); |
goto Exit; |
|
if ( error ) |
|
|
goto Exit; |
|
127 |
|
|
128 |
FT_ARRAY_COPY( gloader->current.outline.points, |
FT_ARRAY_COPY( gloader->current.outline.points, |
129 |
slot->outline.points, |
slot->outline.points, |
130 |
slot->outline.n_points ); |
slot->outline.n_points ); |
131 |
|
|
132 |
FT_ARRAY_COPY( gloader->current.extra_points, |
FT_ARRAY_COPY( gloader->current.extra_points, |
133 |
slot->outline.points, |
slot->outline.points, |
134 |
slot->outline.n_points ); |
slot->outline.n_points ); |
135 |
|
|
136 |
FT_ARRAY_COPY( gloader->current.outline.contours, |
FT_ARRAY_COPY( gloader->current.outline.contours, |
137 |
slot->outline.contours, |
slot->outline.contours, |
138 |
slot->outline.n_contours ); |
slot->outline.n_contours ); |
139 |
|
|
140 |
FT_ARRAY_COPY( gloader->current.outline.tags, |
FT_ARRAY_COPY( gloader->current.outline.tags, |
141 |
slot->outline.tags, |
slot->outline.tags, |
142 |
slot->outline.n_points ); |
slot->outline.n_points ); |
143 |
|
|
144 |
gloader->current.outline.n_points = slot->outline.n_points; |
gloader->current.outline.n_points = slot->outline.n_points; |
145 |
gloader->current.outline.n_contours = slot->outline.n_contours; |
gloader->current.outline.n_contours = slot->outline.n_contours; |
146 |
|
|
147 |
/* compute original horizontal phantom points (and ignore */ |
/* compute original horizontal phantom points (and ignore */ |
148 |
/* vertical ones) */ |
/* vertical ones) */ |
149 |
loader->pp1.x = hints->x_delta; |
loader->pp1.x = hints->x_delta; |
150 |
loader->pp1.y = hints->y_delta; |
loader->pp1.y = hints->y_delta; |
151 |
loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance, |
loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance, |
152 |
hints->x_scale ) + hints->x_delta; |
hints->x_scale ) + hints->x_delta; |
153 |
loader->pp2.y = hints->y_delta; |
loader->pp2.y = hints->y_delta; |
154 |
|
|
155 |
/* be sure to check for spacing glyphs */ |
/* be sure to check for spacing glyphs */ |
156 |
if ( slot->outline.n_points == 0 ) |
if ( slot->outline.n_points == 0 ) |
157 |
goto Hint_Metrics; |
goto Hint_Metrics; |
158 |
|
|
159 |
/* now load the slot image into the auto-outline and run the */ |
/* now load the slot image into the auto-outline and run the */ |
160 |
/* automatic hinting process */ |
/* automatic hinting process */ |
161 |
metrics->clazz->script_hints_apply( hints, |
metrics->clazz->script_hints_apply( hints, |
162 |
&gloader->current.outline, |
&gloader->current.outline, |
163 |
metrics ); |
metrics ); |
164 |
|
|
165 |
/* we now need to hint the metrics according to the change in */ |
/* we now need to hint the metrics according to the change in */ |
166 |
/* width/positioning that occured during the hinting process */ |
/* width/positioning that occured during the hinting process */ |
167 |
{ |
{ |
168 |
FT_Pos old_advance, old_rsb, old_lsb, new_lsb; |
FT_Pos old_advance, old_rsb, old_lsb, new_lsb; |
169 |
FT_Pos pp1x_uh, pp2x_uh; |
FT_Pos pp1x_uh, pp2x_uh; |
170 |
AF_AxisHints axis = &hints->axis[ AF_DIMENSION_HORZ ]; |
AF_AxisHints axis = &hints->axis[ AF_DIMENSION_HORZ ]; |
171 |
AF_Edge edge1 = axis->edges; /* leftmost edge */ |
AF_Edge edge1 = axis->edges; /* leftmost edge */ |
172 |
AF_Edge edge2 = edge1 + |
AF_Edge edge2 = edge1 + |
173 |
axis->num_edges - 1; /* rightmost edge */ |
axis->num_edges - 1; /* rightmost edge */ |
174 |
|
|
175 |
|
|
176 |
if ( axis->num_edges > 1 ) |
if ( axis->num_edges > 1 ) |
177 |
{ |
{ |
178 |
old_advance = loader->pp2.x; |
old_advance = loader->pp2.x; |
179 |
old_rsb = old_advance - edge2->opos; |
old_rsb = old_advance - edge2->opos; |
180 |
old_lsb = edge1->opos; |
old_lsb = edge1->opos; |
181 |
new_lsb = edge1->pos; |
new_lsb = edge1->pos; |
182 |
|
|
183 |
/* remember unhinted values to later account */ |
/* remember unhinted values to later account */ |
184 |
/* for rounding errors */ |
/* for rounding errors */ |
185 |
|
|
186 |
pp1x_uh = new_lsb - old_lsb; |
pp1x_uh = new_lsb - old_lsb; |
187 |
pp2x_uh = edge2->pos + old_rsb; |
pp2x_uh = edge2->pos + old_rsb; |
188 |
|
|
189 |
/* prefer too much space over too little space */ |
/* prefer too much space over too little space */ |
190 |
/* for very small sizes */ |
/* for very small sizes */ |
191 |
|
|
192 |
if ( old_lsb < 24 ) |
if ( old_lsb < 24 ) |
193 |
pp1x_uh -= 5; |
pp1x_uh -= 5; |
194 |
|
|
195 |
if ( old_rsb < 24 ) |
if ( old_rsb < 24 ) |
196 |
pp2x_uh += 5; |
pp2x_uh += 5; |
197 |
|
|
198 |
loader->pp1.x = FT_PIX_ROUND( pp1x_uh ); |
loader->pp1.x = FT_PIX_ROUND( pp1x_uh ); |
199 |
loader->pp2.x = FT_PIX_ROUND( pp2x_uh ); |
loader->pp2.x = FT_PIX_ROUND( pp2x_uh ); |
200 |
|
|
201 |
slot->lsb_delta = loader->pp1.x - pp1x_uh; |
slot->lsb_delta = loader->pp1.x - pp1x_uh; |
202 |
slot->rsb_delta = loader->pp2.x - pp2x_uh; |
slot->rsb_delta = loader->pp2.x - pp2x_uh; |
203 |
|
|
204 |
#if 0 |
#if 0 |
205 |
/* try to fix certain bad advance computations */ |
/* try to fix certain bad advance computations */ |
206 |
if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 ) |
if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 ) |
207 |
loader->pp2.x += 64; |
loader->pp2.x += 64; |
208 |
#endif |
#endif |
209 |
} |
|
210 |
else |
} |
211 |
{ |
else |
212 |
loader->pp1.x = FT_PIX_ROUND( loader->pp1.x ); |
{ |
213 |
loader->pp2.x = FT_PIX_ROUND( loader->pp2.x ); |
loader->pp1.x = FT_PIX_ROUND( loader->pp1.x ); |
214 |
} |
loader->pp2.x = FT_PIX_ROUND( loader->pp2.x ); |
215 |
} |
} |
216 |
|
} |
217 |
|
|
218 |
/* good, we simply add the glyph to our loader's base */ |
/* good, we simply add the glyph to our loader's base */ |
219 |
FT_GlyphLoader_Add( gloader ); |
FT_GlyphLoader_Add( gloader ); |
220 |
break; |
break; |
221 |
|
|
222 |
case FT_GLYPH_FORMAT_COMPOSITE: |
case FT_GLYPH_FORMAT_COMPOSITE: |
223 |
{ |
{ |
238 |
num_subglyphs ); |
num_subglyphs ); |
239 |
|
|
240 |
gloader->current.num_subglyphs = num_subglyphs; |
gloader->current.num_subglyphs = num_subglyphs; |
241 |
num_base_subgs = gloader->base.num_subglyphs; |
num_base_subgs = gloader->base.num_subglyphs; |
242 |
|
|
243 |
/* now, read each subglyph independently */ |
/* now, read each subglyph independently */ |
244 |
for ( nn = 0; nn < num_subglyphs; nn++ ) |
for ( nn = 0; nn < num_subglyphs; nn++ ) |
332 |
x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta; |
x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta; |
333 |
y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta; |
y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta; |
334 |
|
|
335 |
x = FT_PIX_ROUND(x); |
x = FT_PIX_ROUND( x ); |
336 |
y = FT_PIX_ROUND(y); |
y = FT_PIX_ROUND( y ); |
337 |
} |
} |
338 |
|
|
339 |
{ |
{ |
371 |
|
|
372 |
FT_Outline_Get_CBox( &gloader->base.outline, &bbox ); |
FT_Outline_Get_CBox( &gloader->base.outline, &bbox ); |
373 |
|
|
374 |
bbox.xMin = FT_PIX_FLOOR( bbox.xMin ); |
bbox.xMin = FT_PIX_FLOOR( bbox.xMin ); |
375 |
bbox.yMin = FT_PIX_FLOOR( bbox.yMin ); |
bbox.yMin = FT_PIX_FLOOR( bbox.yMin ); |
376 |
bbox.xMax = FT_PIX_CEIL( bbox.xMax ); |
bbox.xMax = FT_PIX_CEIL( bbox.xMax ); |
377 |
bbox.yMax = FT_PIX_CEIL( bbox.yMax ); |
bbox.yMax = FT_PIX_CEIL( bbox.yMax ); |
378 |
|
|
379 |
slot->metrics.width = bbox.xMax - bbox.xMin; |
slot->metrics.width = bbox.xMax - bbox.xMin; |
380 |
slot->metrics.height = bbox.yMax - bbox.yMin; |
slot->metrics.height = bbox.yMax - bbox.yMin; |
390 |
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance, |
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance, |
391 |
x_scale ); |
x_scale ); |
392 |
#else |
#else |
|
/* for mono-width fonts (like Andale, Courier, etc.) we need */ |
|
|
/* to keep the original rounded advance width */ |
|
393 |
if ( !FT_IS_FIXED_WIDTH( slot->face ) ) |
if ( !FT_IS_FIXED_WIDTH( slot->face ) ) |
394 |
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; |
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; |
395 |
else |
else |
418 |
} |
} |
419 |
|
|
420 |
|
|
|
|
|
|
|
|
421 |
FT_LOCAL_DEF( FT_Error ) |
FT_LOCAL_DEF( FT_Error ) |
422 |
af_loader_load_glyph( AF_Loader loader, |
af_loader_load_glyph( AF_Loader loader, |
423 |
FT_Face face, |
FT_Face face, |
428 |
FT_Size size = face->size; |
FT_Size size = face->size; |
429 |
AF_ScalerRec scaler; |
AF_ScalerRec scaler; |
430 |
|
|
431 |
|
|
432 |
if ( !size ) |
if ( !size ) |
433 |
return FT_Err_Invalid_Argument; |
return FT_Err_Invalid_Argument; |
434 |
|
|
448 |
{ |
{ |
449 |
AF_ScriptMetrics metrics; |
AF_ScriptMetrics metrics; |
450 |
|
|
451 |
error = af_face_globals_get_metrics( loader->globals, gindex, &metrics ); |
|
452 |
|
error = af_face_globals_get_metrics( loader->globals, gindex, |
453 |
|
&metrics ); |
454 |
if ( !error ) |
if ( !error ) |
455 |
{ |
{ |
456 |
loader->metrics = metrics; |
loader->metrics = metrics; |
473 |
Exit: |
Exit: |
474 |
return error; |
return error; |
475 |
} |
} |
476 |
|
|
477 |
|
|
478 |
|
/* END */ |