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