1 | /**************************************************************************** |
2 | * |
3 | * cffgload.c |
4 | * |
5 | * OpenType Glyph Loader (body). |
6 | * |
7 | * Copyright (C) 1996-2023 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 <freetype/internal/ftdebug.h> |
20 | #include <freetype/internal/ftstream.h> |
21 | #include <freetype/internal/sfnt.h> |
22 | #include <freetype/internal/ftcalc.h> |
23 | #include <freetype/internal/psaux.h> |
24 | #include <freetype/ftoutln.h> |
25 | #include <freetype/ftdriver.h> |
26 | |
27 | #include "cffload.h" |
28 | #include "cffgload.h" |
29 | |
30 | #include "cfferrs.h" |
31 | |
32 | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
33 | #define IS_DEFAULT_INSTANCE( _face ) \ |
34 | ( !( FT_IS_NAMED_INSTANCE( _face ) || \ |
35 | FT_IS_VARIATION( _face ) ) ) |
36 | #else |
37 | #define IS_DEFAULT_INSTANCE( _face ) 1 |
38 | #endif |
39 | |
40 | |
41 | /************************************************************************** |
42 | * |
43 | * The macro FT_COMPONENT is used in trace mode. It is an implicit |
44 | * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log |
45 | * messages during execution. |
46 | */ |
47 | #undef FT_COMPONENT |
48 | #define FT_COMPONENT cffgload |
49 | |
50 | |
51 | FT_LOCAL_DEF( FT_Error ) |
52 | cff_get_glyph_data( TT_Face face, |
53 | FT_UInt glyph_index, |
54 | FT_Byte** pointer, |
55 | FT_ULong* length ) |
56 | { |
57 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
58 | /* For incremental fonts get the character data using the */ |
59 | /* callback function. */ |
60 | if ( face->root.internal->incremental_interface ) |
61 | { |
62 | FT_Data data; |
63 | FT_Error error = |
64 | face->root.internal->incremental_interface->funcs->get_glyph_data( |
65 | face->root.internal->incremental_interface->object, |
66 | glyph_index, &data ); |
67 | |
68 | |
69 | *pointer = (FT_Byte*)data.pointer; |
70 | *length = data.length; |
71 | |
72 | return error; |
73 | } |
74 | else |
75 | #endif /* FT_CONFIG_OPTION_INCREMENTAL */ |
76 | |
77 | { |
78 | CFF_Font cff = (CFF_Font)( face->extra.data ); |
79 | |
80 | |
81 | return cff_index_access_element( &cff->charstrings_index, glyph_index, |
82 | pointer, length ); |
83 | } |
84 | } |
85 | |
86 | |
87 | FT_LOCAL_DEF( void ) |
88 | cff_free_glyph_data( TT_Face face, |
89 | FT_Byte** pointer, |
90 | FT_ULong length ) |
91 | { |
92 | #ifndef FT_CONFIG_OPTION_INCREMENTAL |
93 | FT_UNUSED( length ); |
94 | #endif |
95 | |
96 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
97 | /* For incremental fonts get the character data using the */ |
98 | /* callback function. */ |
99 | if ( face->root.internal->incremental_interface ) |
100 | { |
101 | FT_Data data; |
102 | |
103 | |
104 | data.pointer = *pointer; |
105 | data.length = (FT_UInt)length; |
106 | |
107 | face->root.internal->incremental_interface->funcs->free_glyph_data( |
108 | face->root.internal->incremental_interface->object, &data ); |
109 | } |
110 | else |
111 | #endif /* FT_CONFIG_OPTION_INCREMENTAL */ |
112 | |
113 | { |
114 | CFF_Font cff = (CFF_Font)( face->extra.data ); |
115 | |
116 | |
117 | cff_index_forget_element( &cff->charstrings_index, pointer ); |
118 | } |
119 | } |
120 | |
121 | |
122 | /*************************************************************************/ |
123 | /*************************************************************************/ |
124 | /*************************************************************************/ |
125 | /********** *********/ |
126 | /********** *********/ |
127 | /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ |
128 | /********** *********/ |
129 | /********** The following code is in charge of computing *********/ |
130 | /********** the maximum advance width of the font. It *********/ |
131 | /********** quickly processes each glyph charstring to *********/ |
132 | /********** extract the value from either a `sbw' or `seac' *********/ |
133 | /********** operator. *********/ |
134 | /********** *********/ |
135 | /*************************************************************************/ |
136 | /*************************************************************************/ |
137 | /*************************************************************************/ |
138 | |
139 | |
140 | #if 0 /* unused until we support pure CFF fonts */ |
141 | |
142 | |
143 | FT_LOCAL_DEF( FT_Error ) |
144 | cff_compute_max_advance( TT_Face face, |
145 | FT_Int* max_advance ) |
146 | { |
147 | FT_Error error = FT_Err_Ok; |
148 | CFF_Decoder decoder; |
149 | FT_Int glyph_index; |
150 | CFF_Font cff = (CFF_Font)face->other; |
151 | |
152 | PSAux_Service psaux = (PSAux_Service)face->psaux; |
153 | const CFF_Decoder_Funcs decoder_funcs = psaux->cff_decoder_funcs; |
154 | |
155 | |
156 | *max_advance = 0; |
157 | |
158 | /* Initialize load decoder */ |
159 | decoder_funcs->init( &decoder, face, 0, 0, 0, 0, 0, 0 ); |
160 | |
161 | decoder.builder.metrics_only = 1; |
162 | decoder.builder.load_points = 0; |
163 | |
164 | /* For each glyph, parse the glyph charstring and extract */ |
165 | /* the advance width. */ |
166 | for ( glyph_index = 0; glyph_index < face->root.num_glyphs; |
167 | glyph_index++ ) |
168 | { |
169 | FT_Byte* charstring; |
170 | FT_ULong charstring_len; |
171 | |
172 | |
173 | /* now get load the unscaled outline */ |
174 | error = cff_get_glyph_data( face, glyph_index, |
175 | &charstring, &charstring_len ); |
176 | if ( !error ) |
177 | { |
178 | error = decoder_funcs->prepare( &decoder, size, glyph_index ); |
179 | if ( !error ) |
180 | error = decoder_funcs->parse_charstrings_old( &decoder, |
181 | charstring, |
182 | charstring_len, |
183 | 0 ); |
184 | |
185 | cff_free_glyph_data( face, &charstring, &charstring_len ); |
186 | } |
187 | |
188 | /* ignore the error if one has occurred -- skip to next glyph */ |
189 | error = FT_Err_Ok; |
190 | } |
191 | |
192 | *max_advance = decoder.builder.advance.x; |
193 | |
194 | return FT_Err_Ok; |
195 | } |
196 | |
197 | |
198 | #endif /* 0 */ |
199 | |
200 | |
201 | FT_LOCAL_DEF( FT_Error ) |
202 | cff_slot_load( CFF_GlyphSlot glyph, |
203 | CFF_Size size, |
204 | FT_UInt glyph_index, |
205 | FT_Int32 load_flags ) |
206 | { |
207 | FT_Error error; |
208 | CFF_Decoder decoder; |
209 | PS_Decoder psdecoder; |
210 | TT_Face face = (TT_Face)glyph->root.face; |
211 | FT_Bool hinting, scaled, force_scaling; |
212 | CFF_Font cff = (CFF_Font)face->extra.data; |
213 | |
214 | PSAux_Service psaux = (PSAux_Service)face->psaux; |
215 | const CFF_Decoder_Funcs decoder_funcs = psaux->cff_decoder_funcs; |
216 | |
217 | FT_Matrix font_matrix; |
218 | FT_Vector font_offset; |
219 | |
220 | |
221 | force_scaling = FALSE; |
222 | |
223 | /* in a CID-keyed font, consider `glyph_index' as a CID and map */ |
224 | /* it immediately to the real glyph_index -- if it isn't a */ |
225 | /* subsetted font, glyph_indices and CIDs are identical, though */ |
226 | if ( cff->top_font.font_dict.cid_registry != 0xFFFFU && |
227 | cff->charset.cids ) |
228 | { |
229 | /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */ |
230 | if ( glyph_index != 0 ) |
231 | { |
232 | glyph_index = cff_charset_cid_to_gindex( &cff->charset, |
233 | glyph_index ); |
234 | if ( glyph_index == 0 ) |
235 | return FT_THROW( Invalid_Argument ); |
236 | } |
237 | } |
238 | else if ( glyph_index >= cff->num_glyphs ) |
239 | return FT_THROW( Invalid_Argument ); |
240 | |
241 | if ( load_flags & FT_LOAD_NO_RECURSE ) |
242 | load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; |
243 | |
244 | glyph->x_scale = 0x10000L; |
245 | glyph->y_scale = 0x10000L; |
246 | if ( size ) |
247 | { |
248 | glyph->x_scale = size->root.metrics.x_scale; |
249 | glyph->y_scale = size->root.metrics.y_scale; |
250 | } |
251 | |
252 | #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS |
253 | |
254 | /* try to load embedded bitmap if any */ |
255 | /* */ |
256 | /* XXX: The convention should be emphasized in */ |
257 | /* the documents because it can be confusing. */ |
258 | if ( size ) |
259 | { |
260 | CFF_Face cff_face = (CFF_Face)size->root.face; |
261 | SFNT_Service sfnt = (SFNT_Service)cff_face->sfnt; |
262 | FT_Stream stream = cff_face->root.stream; |
263 | |
264 | |
265 | if ( size->strike_index != 0xFFFFFFFFUL && |
266 | ( load_flags & FT_LOAD_NO_BITMAP ) == 0 && |
267 | IS_DEFAULT_INSTANCE( size->root.face ) ) |
268 | { |
269 | TT_SBit_MetricsRec metrics; |
270 | |
271 | |
272 | error = sfnt->load_sbit_image( face, |
273 | size->strike_index, |
274 | glyph_index, |
275 | (FT_UInt)load_flags, |
276 | stream, |
277 | &glyph->root.bitmap, |
278 | &metrics ); |
279 | |
280 | if ( !error ) |
281 | { |
282 | FT_Bool has_vertical_info; |
283 | FT_UShort advance; |
284 | FT_Short dummy; |
285 | |
286 | |
287 | glyph->root.outline.n_points = 0; |
288 | glyph->root.outline.n_contours = 0; |
289 | |
290 | glyph->root.metrics.width = (FT_Pos)metrics.width * 64; |
291 | glyph->root.metrics.height = (FT_Pos)metrics.height * 64; |
292 | |
293 | glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX * 64; |
294 | glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY * 64; |
295 | glyph->root.metrics.horiAdvance = (FT_Pos)metrics.horiAdvance * 64; |
296 | |
297 | glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX * 64; |
298 | glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY * 64; |
299 | glyph->root.metrics.vertAdvance = (FT_Pos)metrics.vertAdvance * 64; |
300 | |
301 | glyph->root.format = FT_GLYPH_FORMAT_BITMAP; |
302 | |
303 | if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) |
304 | { |
305 | glyph->root.bitmap_left = metrics.vertBearingX; |
306 | glyph->root.bitmap_top = metrics.vertBearingY; |
307 | } |
308 | else |
309 | { |
310 | glyph->root.bitmap_left = metrics.horiBearingX; |
311 | glyph->root.bitmap_top = metrics.horiBearingY; |
312 | } |
313 | |
314 | /* compute linear advance widths */ |
315 | |
316 | (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 0, |
317 | glyph_index, |
318 | &dummy, |
319 | &advance ); |
320 | glyph->root.linearHoriAdvance = advance; |
321 | |
322 | has_vertical_info = FT_BOOL( |
323 | face->vertical_info && |
324 | face->vertical.number_Of_VMetrics > 0 ); |
325 | |
326 | /* get the vertical metrics from the vmtx table if we have one */ |
327 | if ( has_vertical_info ) |
328 | { |
329 | (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 1, |
330 | glyph_index, |
331 | &dummy, |
332 | &advance ); |
333 | glyph->root.linearVertAdvance = advance; |
334 | } |
335 | else |
336 | { |
337 | /* make up vertical ones */ |
338 | if ( face->os2.version != 0xFFFFU ) |
339 | glyph->root.linearVertAdvance = (FT_Pos) |
340 | ( face->os2.sTypoAscender - face->os2.sTypoDescender ); |
341 | else |
342 | glyph->root.linearVertAdvance = (FT_Pos) |
343 | ( face->horizontal.Ascender - face->horizontal.Descender ); |
344 | } |
345 | |
346 | return error; |
347 | } |
348 | } |
349 | } |
350 | |
351 | #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ |
352 | |
353 | /* return immediately if we only want the embedded bitmaps */ |
354 | if ( load_flags & FT_LOAD_SBITS_ONLY ) |
355 | return FT_THROW( Invalid_Argument ); |
356 | |
357 | #ifdef FT_CONFIG_OPTION_SVG |
358 | /* check for OT-SVG */ |
359 | if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 && |
360 | ( load_flags & FT_LOAD_COLOR ) && |
361 | face->svg ) |
362 | { |
363 | /* |
364 | * We load the SVG document and try to grab the advances from the |
365 | * table. For the bearings we rely on the presetting hook to do that. |
366 | */ |
367 | |
368 | SFNT_Service sfnt = (SFNT_Service)face->sfnt; |
369 | |
370 | |
371 | if ( size && (size->root.metrics.x_ppem < 1 || |
372 | size->root.metrics.y_ppem < 1 ) ) |
373 | { |
374 | error = FT_THROW( Invalid_Size_Handle ); |
375 | return error; |
376 | } |
377 | |
378 | FT_TRACE3(( "Trying to load SVG glyph\n" )); |
379 | |
380 | error = sfnt->load_svg_doc( (FT_GlyphSlot)glyph, glyph_index ); |
381 | if ( !error ) |
382 | { |
383 | FT_Fixed x_scale = size->root.metrics.x_scale; |
384 | FT_Fixed y_scale = size->root.metrics.y_scale; |
385 | |
386 | FT_Short dummy; |
387 | FT_UShort advanceX; |
388 | FT_UShort advanceY; |
389 | |
390 | |
391 | FT_TRACE3(( "Successfully loaded SVG glyph\n" )); |
392 | |
393 | glyph->root.format = FT_GLYPH_FORMAT_SVG; |
394 | |
395 | /* |
396 | * If horizontal or vertical advances are not present in the table, |
397 | * this is a problem with the font since the standard requires them. |
398 | * However, we are graceful and calculate the values by ourselves |
399 | * for the vertical case. |
400 | */ |
401 | sfnt->get_metrics( face, |
402 | FALSE, |
403 | glyph_index, |
404 | &dummy, |
405 | &advanceX ); |
406 | sfnt->get_metrics( face, |
407 | TRUE, |
408 | glyph_index, |
409 | &dummy, |
410 | &advanceY ); |
411 | |
412 | glyph->root.linearHoriAdvance = advanceX; |
413 | glyph->root.linearVertAdvance = advanceY; |
414 | |
415 | glyph->root.metrics.horiAdvance = FT_MulFix( advanceX, x_scale ); |
416 | glyph->root.metrics.vertAdvance = FT_MulFix( advanceY, y_scale ); |
417 | |
418 | return error; |
419 | } |
420 | |
421 | FT_TRACE3(( "Failed to load SVG glyph\n" )); |
422 | } |
423 | |
424 | #endif /* FT_CONFIG_OPTION_SVG */ |
425 | |
426 | /* if we have a CID subfont, use its matrix (which has already */ |
427 | /* been multiplied with the root matrix) */ |
428 | |
429 | /* this scaling is only relevant if the PS hinter isn't active */ |
430 | if ( cff->num_subfonts ) |
431 | { |
432 | FT_Long top_upm, sub_upm; |
433 | FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, |
434 | glyph_index ); |
435 | |
436 | |
437 | if ( fd_index >= cff->num_subfonts ) |
438 | fd_index = (FT_Byte)( cff->num_subfonts - 1 ); |
439 | |
440 | top_upm = (FT_Long)cff->top_font.font_dict.units_per_em; |
441 | sub_upm = (FT_Long)cff->subfonts[fd_index]->font_dict.units_per_em; |
442 | |
443 | font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix; |
444 | font_offset = cff->subfonts[fd_index]->font_dict.font_offset; |
445 | |
446 | if ( top_upm != sub_upm ) |
447 | { |
448 | glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm ); |
449 | glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm ); |
450 | |
451 | force_scaling = TRUE; |
452 | } |
453 | } |
454 | else |
455 | { |
456 | font_matrix = cff->top_font.font_dict.font_matrix; |
457 | font_offset = cff->top_font.font_dict.font_offset; |
458 | } |
459 | |
460 | glyph->root.outline.n_points = 0; |
461 | glyph->root.outline.n_contours = 0; |
462 | |
463 | /* top-level code ensures that FT_LOAD_NO_HINTING is set */ |
464 | /* if FT_LOAD_NO_SCALE is active */ |
465 | hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); |
466 | scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); |
467 | |
468 | glyph->hint = hinting; |
469 | glyph->scaled = scaled; |
470 | glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */ |
471 | |
472 | { |
473 | #ifdef CFF_CONFIG_OPTION_OLD_ENGINE |
474 | PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( face ); |
475 | #endif |
476 | |
477 | FT_Byte* charstring; |
478 | FT_ULong charstring_len; |
479 | |
480 | |
481 | decoder_funcs->init( &decoder, face, size, glyph, hinting, |
482 | FT_LOAD_TARGET_MODE( load_flags ), |
483 | cff_get_glyph_data, |
484 | cff_free_glyph_data ); |
485 | |
486 | /* this is for pure CFFs */ |
487 | if ( load_flags & FT_LOAD_ADVANCE_ONLY ) |
488 | decoder.width_only = TRUE; |
489 | |
490 | decoder.builder.no_recurse = |
491 | FT_BOOL( load_flags & FT_LOAD_NO_RECURSE ); |
492 | |
493 | /* this function also checks for a valid subfont index */ |
494 | error = decoder_funcs->prepare( &decoder, size, glyph_index ); |
495 | if ( error ) |
496 | goto Glyph_Build_Finished; |
497 | |
498 | /* now load the unscaled outline */ |
499 | error = cff_get_glyph_data( face, glyph_index, |
500 | &charstring, &charstring_len ); |
501 | if ( error ) |
502 | goto Glyph_Build_Finished; |
503 | |
504 | #ifdef CFF_CONFIG_OPTION_OLD_ENGINE |
505 | /* choose which CFF renderer to use */ |
506 | if ( driver->hinting_engine == FT_HINTING_FREETYPE ) |
507 | error = decoder_funcs->parse_charstrings_old( &decoder, |
508 | charstring, |
509 | charstring_len, |
510 | 0 ); |
511 | else |
512 | #endif |
513 | { |
514 | psaux->ps_decoder_init( &psdecoder, &decoder, FALSE ); |
515 | |
516 | error = decoder_funcs->parse_charstrings( &psdecoder, |
517 | charstring, |
518 | charstring_len ); |
519 | |
520 | /* Adobe's engine uses 16.16 numbers everywhere; */ |
521 | /* as a consequence, glyphs larger than 2000ppem get rejected */ |
522 | if ( FT_ERR_EQ( error, Glyph_Too_Big ) ) |
523 | { |
524 | /* this time, we retry unhinted and scale up the glyph later on */ |
525 | /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */ |
526 | /* 0x400 for both `x_scale' and `y_scale' in this case) */ |
527 | hinting = FALSE; |
528 | force_scaling = TRUE; |
529 | glyph->hint = hinting; |
530 | |
531 | error = decoder_funcs->parse_charstrings( &psdecoder, |
532 | charstring, |
533 | charstring_len ); |
534 | } |
535 | } |
536 | |
537 | cff_free_glyph_data( face, &charstring, charstring_len ); |
538 | |
539 | if ( error ) |
540 | goto Glyph_Build_Finished; |
541 | |
542 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
543 | /* Control data and length may not be available for incremental */ |
544 | /* fonts. */ |
545 | if ( face->root.internal->incremental_interface ) |
546 | { |
547 | glyph->root.control_data = NULL; |
548 | glyph->root.control_len = 0; |
549 | } |
550 | else |
551 | #endif /* FT_CONFIG_OPTION_INCREMENTAL */ |
552 | |
553 | /* We set control_data and control_len if charstrings is loaded. */ |
554 | /* See how charstring loads at cff_index_access_element() in */ |
555 | /* cffload.c. */ |
556 | { |
557 | CFF_Index csindex = &cff->charstrings_index; |
558 | |
559 | |
560 | if ( csindex->offsets ) |
561 | { |
562 | glyph->root.control_data = csindex->bytes + |
563 | csindex->offsets[glyph_index] - 1; |
564 | glyph->root.control_len = (FT_Long)charstring_len; |
565 | } |
566 | } |
567 | |
568 | Glyph_Build_Finished: |
569 | /* save new glyph tables, if no error */ |
570 | if ( !error ) |
571 | decoder.builder.funcs.done( &decoder.builder ); |
572 | /* XXX: anything to do for broken glyph entry? */ |
573 | } |
574 | |
575 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
576 | |
577 | /* Incremental fonts can optionally override the metrics. */ |
578 | if ( !error && |
579 | face->root.internal->incremental_interface && |
580 | face->root.internal->incremental_interface->funcs->get_glyph_metrics ) |
581 | { |
582 | FT_Incremental_MetricsRec metrics; |
583 | |
584 | |
585 | metrics.bearing_x = decoder.builder.left_bearing.x; |
586 | metrics.bearing_y = 0; |
587 | metrics.advance = decoder.builder.advance.x; |
588 | metrics.advance_v = decoder.builder.advance.y; |
589 | |
590 | error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( |
591 | face->root.internal->incremental_interface->object, |
592 | glyph_index, FALSE, &metrics ); |
593 | |
594 | decoder.builder.left_bearing.x = metrics.bearing_x; |
595 | decoder.builder.advance.x = metrics.advance; |
596 | decoder.builder.advance.y = metrics.advance_v; |
597 | } |
598 | |
599 | #endif /* FT_CONFIG_OPTION_INCREMENTAL */ |
600 | |
601 | if ( !error ) |
602 | { |
603 | /* Now, set the metrics -- this is rather simple, as */ |
604 | /* the left side bearing is the xMin, and the top side */ |
605 | /* bearing the yMax. */ |
606 | |
607 | /* For composite glyphs, return only left side bearing and */ |
608 | /* advance width. */ |
609 | if ( load_flags & FT_LOAD_NO_RECURSE ) |
610 | { |
611 | FT_Slot_Internal internal = glyph->root.internal; |
612 | |
613 | |
614 | glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; |
615 | glyph->root.metrics.horiAdvance = decoder.glyph_width; |
616 | internal->glyph_matrix = font_matrix; |
617 | internal->glyph_delta = font_offset; |
618 | internal->glyph_transformed = 1; |
619 | } |
620 | else |
621 | { |
622 | FT_BBox cbox; |
623 | FT_Glyph_Metrics* metrics = &glyph->root.metrics; |
624 | FT_Bool has_vertical_info; |
625 | |
626 | |
627 | if ( face->horizontal.number_Of_HMetrics ) |
628 | { |
629 | FT_Short horiBearingX = 0; |
630 | FT_UShort horiAdvance = 0; |
631 | |
632 | |
633 | ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, |
634 | glyph_index, |
635 | &horiBearingX, |
636 | &horiAdvance ); |
637 | metrics->horiAdvance = horiAdvance; |
638 | metrics->horiBearingX = horiBearingX; |
639 | glyph->root.linearHoriAdvance = horiAdvance; |
640 | } |
641 | else |
642 | { |
643 | /* copy the _unscaled_ advance width */ |
644 | metrics->horiAdvance = decoder.glyph_width; |
645 | glyph->root.linearHoriAdvance = decoder.glyph_width; |
646 | } |
647 | |
648 | glyph->root.internal->glyph_transformed = 0; |
649 | |
650 | has_vertical_info = FT_BOOL( face->vertical_info && |
651 | face->vertical.number_Of_VMetrics > 0 ); |
652 | |
653 | /* get the vertical metrics from the vmtx table if we have one */ |
654 | if ( has_vertical_info ) |
655 | { |
656 | FT_Short vertBearingY = 0; |
657 | FT_UShort vertAdvance = 0; |
658 | |
659 | |
660 | ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, |
661 | glyph_index, |
662 | &vertBearingY, |
663 | &vertAdvance ); |
664 | metrics->vertBearingY = vertBearingY; |
665 | metrics->vertAdvance = vertAdvance; |
666 | } |
667 | else |
668 | { |
669 | /* make up vertical ones */ |
670 | if ( face->os2.version != 0xFFFFU ) |
671 | metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender - |
672 | face->os2.sTypoDescender ); |
673 | else |
674 | metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender - |
675 | face->horizontal.Descender ); |
676 | } |
677 | |
678 | glyph->root.linearVertAdvance = metrics->vertAdvance; |
679 | |
680 | glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; |
681 | |
682 | glyph->root.outline.flags = 0; |
683 | if ( size && size->root.metrics.y_ppem < 24 ) |
684 | glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION; |
685 | |
686 | glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL; |
687 | |
688 | /* apply the font matrix, if any */ |
689 | if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L || |
690 | font_matrix.xy != 0 || font_matrix.yx != 0 ) |
691 | { |
692 | FT_Outline_Transform( &glyph->root.outline, &font_matrix ); |
693 | |
694 | metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, |
695 | font_matrix.xx ); |
696 | metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, |
697 | font_matrix.yy ); |
698 | } |
699 | |
700 | if ( font_offset.x || font_offset.y ) |
701 | { |
702 | FT_Outline_Translate( &glyph->root.outline, |
703 | font_offset.x, |
704 | font_offset.y ); |
705 | |
706 | metrics->horiAdvance += font_offset.x; |
707 | metrics->vertAdvance += font_offset.y; |
708 | } |
709 | |
710 | if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling ) |
711 | { |
712 | /* scale the outline and the metrics */ |
713 | FT_Int n; |
714 | FT_Outline* cur = &glyph->root.outline; |
715 | FT_Vector* vec = cur->points; |
716 | FT_Fixed x_scale = glyph->x_scale; |
717 | FT_Fixed y_scale = glyph->y_scale; |
718 | |
719 | |
720 | /* First of all, scale the points */ |
721 | if ( !hinting || !decoder.builder.hints_funcs ) |
722 | for ( n = cur->n_points; n > 0; n--, vec++ ) |
723 | { |
724 | vec->x = FT_MulFix( vec->x, x_scale ); |
725 | vec->y = FT_MulFix( vec->y, y_scale ); |
726 | } |
727 | |
728 | /* Then scale the metrics */ |
729 | metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); |
730 | metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); |
731 | } |
732 | |
733 | /* compute the other metrics */ |
734 | FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); |
735 | |
736 | metrics->width = cbox.xMax - cbox.xMin; |
737 | metrics->height = cbox.yMax - cbox.yMin; |
738 | |
739 | metrics->horiBearingX = cbox.xMin; |
740 | metrics->horiBearingY = cbox.yMax; |
741 | |
742 | if ( has_vertical_info ) |
743 | { |
744 | metrics->vertBearingX = metrics->horiBearingX - |
745 | metrics->horiAdvance / 2; |
746 | metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, |
747 | glyph->y_scale ); |
748 | } |
749 | else |
750 | { |
751 | if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) |
752 | ft_synthesize_vertical_metrics( metrics, |
753 | metrics->vertAdvance ); |
754 | } |
755 | } |
756 | } |
757 | |
758 | return error; |
759 | } |
760 | |
761 | |
762 | /* END */ |
763 | |