• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  *
3  * cidgload.c
4  *
5  *   CID-keyed Type1 Glyph Loader (body).
6  *
7  * Copyright 1996-2018 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 "cidload.h"
21 #include "cidgload.h"
22 #include FT_INTERNAL_DEBUG_H
23 #include FT_INTERNAL_STREAM_H
24 #include FT_OUTLINE_H
25 #include FT_INTERNAL_CALC_H
26 
27 #include FT_INTERNAL_POSTSCRIPT_AUX_H
28 #include FT_INTERNAL_CFF_TYPES_H
29 #include FT_DRIVER_H
30 
31 #include "ciderrs.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  trace_cidgload
42 
43 
44   FT_CALLBACK_DEF( FT_Error )
cid_load_glyph(T1_Decoder decoder,FT_UInt glyph_index)45   cid_load_glyph( T1_Decoder  decoder,
46                   FT_UInt     glyph_index )
47   {
48     CID_Face       face = (CID_Face)decoder->builder.face;
49     CID_FaceInfo   cid  = &face->cid;
50     FT_Byte*       p;
51     FT_ULong       fd_select;
52     FT_Stream      stream       = face->cid_stream;
53     FT_Error       error        = FT_Err_Ok;
54     FT_Byte*       charstring   = NULL;
55     FT_Memory      memory       = face->root.memory;
56     FT_ULong       glyph_length = 0;
57     PSAux_Service  psaux        = (PSAux_Service)face->psaux;
58 
59     FT_Bool  force_scaling = FALSE;
60 
61 #ifdef FT_CONFIG_OPTION_INCREMENTAL
62     FT_Incremental_InterfaceRec  *inc =
63                                    face->root.internal->incremental_interface;
64 #endif
65 
66 
67     FT_TRACE1(( "cid_load_glyph: glyph index %d\n", glyph_index ));
68 
69 #ifdef FT_CONFIG_OPTION_INCREMENTAL
70 
71     /* For incremental fonts get the character data using */
72     /* the callback function.                             */
73     if ( inc )
74     {
75       FT_Data  glyph_data;
76 
77 
78       error = inc->funcs->get_glyph_data( inc->object,
79                                           glyph_index, &glyph_data );
80       if ( error )
81         goto Exit;
82 
83       p         = (FT_Byte*)glyph_data.pointer;
84       fd_select = cid_get_offset( &p, (FT_Byte)cid->fd_bytes );
85 
86       if ( glyph_data.length != 0 )
87       {
88         glyph_length = (FT_ULong)( glyph_data.length - cid->fd_bytes );
89         (void)FT_ALLOC( charstring, glyph_length );
90         if ( !error )
91           ft_memcpy( charstring, glyph_data.pointer + cid->fd_bytes,
92                      glyph_length );
93       }
94 
95       inc->funcs->free_glyph_data( inc->object, &glyph_data );
96 
97       if ( error )
98         goto Exit;
99     }
100 
101     else
102 
103 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
104 
105     /* For ordinary fonts read the CID font dictionary index */
106     /* and charstring offset from the CIDMap.                */
107     {
108       FT_UInt   entry_len = (FT_UInt)( cid->fd_bytes + cid->gd_bytes );
109       FT_ULong  off1, off2;
110 
111 
112       if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset +
113                            glyph_index * entry_len )               ||
114            FT_FRAME_ENTER( 2 * entry_len )                         )
115         goto Exit;
116 
117       p         = (FT_Byte*)stream->cursor;
118       fd_select = cid_get_offset( &p, (FT_Byte)cid->fd_bytes );
119       off1      = cid_get_offset( &p, (FT_Byte)cid->gd_bytes );
120       p        += cid->fd_bytes;
121       off2      = cid_get_offset( &p, (FT_Byte)cid->gd_bytes );
122       FT_FRAME_EXIT();
123 
124       if ( fd_select >= (FT_ULong)cid->num_dicts ||
125            off2 > stream->size                   ||
126            off1 > off2                           )
127       {
128         FT_TRACE0(( "cid_load_glyph: invalid glyph stream offsets\n" ));
129         error = FT_THROW( Invalid_Offset );
130         goto Exit;
131       }
132 
133       glyph_length = off2 - off1;
134       if ( glyph_length == 0 )
135         goto Exit;
136       if ( FT_ALLOC( charstring, glyph_length ) )
137         goto Exit;
138       if ( FT_STREAM_READ_AT( cid->data_offset + off1,
139                               charstring, glyph_length ) )
140         goto Exit;
141     }
142 
143     /* Now set up the subrs array and parse the charstrings. */
144     {
145       CID_FaceDict  dict;
146       CID_Subrs     cid_subrs = face->subrs + fd_select;
147       FT_UInt       cs_offset;
148 
149 
150       /* Set up subrs */
151       decoder->num_subrs  = cid_subrs->num_subrs;
152       decoder->subrs      = cid_subrs->code;
153       decoder->subrs_len  = 0;
154       decoder->subrs_hash = NULL;
155 
156       /* Set up font matrix */
157       dict                 = cid->font_dicts + fd_select;
158 
159       decoder->font_matrix = dict->font_matrix;
160       decoder->font_offset = dict->font_offset;
161       decoder->lenIV       = dict->private_dict.lenIV;
162 
163       /* Decode the charstring. */
164 
165       /* Adjustment for seed bytes. */
166       cs_offset = decoder->lenIV >= 0 ? (FT_UInt)decoder->lenIV : 0;
167       if ( cs_offset > glyph_length )
168       {
169         FT_TRACE0(( "cid_load_glyph: invalid glyph stream offsets\n" ));
170         error = FT_THROW( Invalid_Offset );
171         goto Exit;
172       }
173 
174       /* Decrypt only if lenIV >= 0. */
175       if ( decoder->lenIV >= 0 )
176         psaux->t1_decrypt( charstring, glyph_length, 4330 );
177 
178       /* choose which renderer to use */
179 #ifdef T1_CONFIG_OPTION_OLD_ENGINE
180       if ( ( (PS_Driver)FT_FACE_DRIVER( face ) )->hinting_engine ==
181                FT_HINTING_FREETYPE                                  ||
182            decoder->builder.metrics_only                            )
183         error = psaux->t1_decoder_funcs->parse_charstrings_old(
184                   decoder,
185                   charstring + cs_offset,
186                   glyph_length - cs_offset );
187 #else
188       if ( decoder->builder.metrics_only )
189         error = psaux->t1_decoder_funcs->parse_metrics(
190                   decoder,
191                   charstring + cs_offset,
192                   glyph_length - cs_offset );
193 #endif
194       else
195       {
196         PS_Decoder      psdecoder;
197         CFF_SubFontRec  subfont;
198 
199 
200         psaux->ps_decoder_init( &psdecoder, decoder, TRUE );
201 
202         psaux->t1_make_subfont( FT_FACE( face ),
203                                 &dict->private_dict,
204                                 &subfont );
205         psdecoder.current_subfont = &subfont;
206 
207         error = psaux->t1_decoder_funcs->parse_charstrings(
208                   &psdecoder,
209                   charstring + cs_offset,
210                   glyph_length - cs_offset );
211 
212         /* Adobe's engine uses 16.16 numbers everywhere;              */
213         /* as a consequence, glyphs larger than 2000ppem get rejected */
214         if ( FT_ERR_EQ( error, Glyph_Too_Big ) )
215         {
216           /* this time, we retry unhinted and scale up the glyph later on */
217           /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */
218           /* 0x400 for both `x_scale' and `y_scale' in this case)         */
219           ((CID_GlyphSlot)decoder->builder.glyph)->hint = FALSE;
220 
221           force_scaling = TRUE;
222 
223           error = psaux->t1_decoder_funcs->parse_charstrings(
224                     &psdecoder,
225                     charstring + cs_offset,
226                     glyph_length - cs_offset );
227         }
228       }
229     }
230 
231 #ifdef FT_CONFIG_OPTION_INCREMENTAL
232 
233     /* Incremental fonts can optionally override the metrics. */
234     if ( !error && inc && inc->funcs->get_glyph_metrics )
235     {
236       FT_Incremental_MetricsRec  metrics;
237 
238 
239       metrics.bearing_x = FIXED_TO_INT( decoder->builder.left_bearing.x );
240       metrics.bearing_y = 0;
241       metrics.advance   = FIXED_TO_INT( decoder->builder.advance.x );
242       metrics.advance_v = FIXED_TO_INT( decoder->builder.advance.y );
243 
244       error = inc->funcs->get_glyph_metrics( inc->object,
245                                              glyph_index, FALSE, &metrics );
246 
247       decoder->builder.left_bearing.x = INT_TO_FIXED( metrics.bearing_x );
248       decoder->builder.advance.x      = INT_TO_FIXED( metrics.advance );
249       decoder->builder.advance.y      = INT_TO_FIXED( metrics.advance_v );
250     }
251 
252 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
253 
254   Exit:
255     FT_FREE( charstring );
256 
257     ((CID_GlyphSlot)decoder->builder.glyph)->scaled = force_scaling;
258 
259     return error;
260   }
261 
262 
263 #if 0
264 
265 
266   /*************************************************************************/
267   /*************************************************************************/
268   /*************************************************************************/
269   /**********                                                      *********/
270   /**********                                                      *********/
271   /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
272   /**********                                                      *********/
273   /**********    The following code is in charge of computing      *********/
274   /**********    the maximum advance width of the font.  It        *********/
275   /**********    quickly processes each glyph charstring to        *********/
276   /**********    extract the value from either a `sbw' or `seac'   *********/
277   /**********    operator.                                         *********/
278   /**********                                                      *********/
279   /*************************************************************************/
280   /*************************************************************************/
281   /*************************************************************************/
282 
283 
284   FT_LOCAL_DEF( FT_Error )
285   cid_face_compute_max_advance( CID_Face  face,
286                                 FT_Int*   max_advance )
287   {
288     FT_Error       error;
289     T1_DecoderRec  decoder;
290     FT_Int         glyph_index;
291 
292     PSAux_Service  psaux = (PSAux_Service)face->psaux;
293 
294 
295     *max_advance = 0;
296 
297     /* Initialize load decoder */
298     error = psaux->t1_decoder_funcs->init( &decoder,
299                                            (FT_Face)face,
300                                            0, /* size       */
301                                            0, /* glyph slot */
302                                            0, /* glyph names! XXX */
303                                            0, /* blend == 0 */
304                                            0, /* hinting == 0 */
305                                            cid_load_glyph );
306     if ( error )
307       return error;
308 
309     /* TODO: initialize decoder.len_buildchar and decoder.buildchar */
310     /*       if we ever support CID-keyed multiple master fonts     */
311 
312     decoder.builder.metrics_only = 1;
313     decoder.builder.load_points  = 0;
314 
315     /* for each glyph, parse the glyph charstring and extract */
316     /* the advance width                                      */
317     for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
318           glyph_index++ )
319     {
320       /* now get load the unscaled outline */
321       error = cid_load_glyph( &decoder, glyph_index );
322       /* ignore the error if one occurred - skip to next glyph */
323     }
324 
325     *max_advance = FIXED_TO_INT( decoder.builder.advance.x );
326 
327     psaux->t1_decoder_funcs->done( &decoder );
328 
329     return FT_Err_Ok;
330   }
331 
332 
333 #endif /* 0 */
334 
335 
336   FT_LOCAL_DEF( FT_Error )
cid_slot_load_glyph(FT_GlyphSlot cidglyph,FT_Size cidsize,FT_UInt glyph_index,FT_Int32 load_flags)337   cid_slot_load_glyph( FT_GlyphSlot  cidglyph,      /* CID_GlyphSlot */
338                        FT_Size       cidsize,       /* CID_Size      */
339                        FT_UInt       glyph_index,
340                        FT_Int32      load_flags )
341   {
342     CID_GlyphSlot  glyph = (CID_GlyphSlot)cidglyph;
343     FT_Error       error;
344     T1_DecoderRec  decoder;
345     CID_Face       face = (CID_Face)cidglyph->face;
346     FT_Bool        hinting;
347     FT_Bool        scaled;
348 
349     PSAux_Service  psaux = (PSAux_Service)face->psaux;
350     FT_Matrix      font_matrix;
351     FT_Vector      font_offset;
352     FT_Bool        must_finish_decoder = FALSE;
353 
354 
355     if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
356     {
357       error = FT_THROW( Invalid_Argument );
358       goto Exit;
359     }
360 
361     if ( load_flags & FT_LOAD_NO_RECURSE )
362       load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
363 
364     glyph->x_scale = cidsize->metrics.x_scale;
365     glyph->y_scale = cidsize->metrics.y_scale;
366 
367     cidglyph->outline.n_points   = 0;
368     cidglyph->outline.n_contours = 0;
369 
370     hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
371                        ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
372     scaled  = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 );
373 
374     glyph->hint      = hinting;
375     glyph->scaled    = scaled;
376     cidglyph->format = FT_GLYPH_FORMAT_OUTLINE;
377 
378     error = psaux->t1_decoder_funcs->init( &decoder,
379                                            cidglyph->face,
380                                            cidsize,
381                                            cidglyph,
382                                            0, /* glyph names -- XXX */
383                                            0, /* blend == 0 */
384                                            hinting,
385                                            FT_LOAD_TARGET_MODE( load_flags ),
386                                            cid_load_glyph );
387     if ( error )
388       goto Exit;
389 
390     /* TODO: initialize decoder.len_buildchar and decoder.buildchar */
391     /*       if we ever support CID-keyed multiple master fonts     */
392 
393     must_finish_decoder = TRUE;
394 
395     /* set up the decoder */
396     decoder.builder.no_recurse = FT_BOOL(
397       ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ) );
398 
399     error = cid_load_glyph( &decoder, glyph_index );
400     if ( error )
401       goto Exit;
402 
403     /* copy flags back for forced scaling */
404     hinting = glyph->hint;
405     scaled  = glyph->scaled;
406 
407     font_matrix = decoder.font_matrix;
408     font_offset = decoder.font_offset;
409 
410     /* save new glyph tables */
411     psaux->t1_decoder_funcs->done( &decoder );
412 
413     must_finish_decoder = FALSE;
414 
415     /* now set the metrics -- this is rather simple, as    */
416     /* the left side bearing is the xMin, and the top side */
417     /* bearing the yMax                                    */
418     cidglyph->outline.flags &= FT_OUTLINE_OWNER;
419     cidglyph->outline.flags |= FT_OUTLINE_REVERSE_FILL;
420 
421     /* for composite glyphs, return only left side bearing and */
422     /* advance width                                           */
423     if ( load_flags & FT_LOAD_NO_RECURSE )
424     {
425       FT_Slot_Internal  internal = cidglyph->internal;
426 
427 
428       cidglyph->metrics.horiBearingX =
429         FIXED_TO_INT( decoder.builder.left_bearing.x );
430       cidglyph->metrics.horiAdvance =
431         FIXED_TO_INT( decoder.builder.advance.x );
432 
433       internal->glyph_matrix      = font_matrix;
434       internal->glyph_delta       = font_offset;
435       internal->glyph_transformed = 1;
436     }
437     else
438     {
439       FT_BBox            cbox;
440       FT_Glyph_Metrics*  metrics = &cidglyph->metrics;
441 
442 
443       /* copy the _unscaled_ advance width */
444       metrics->horiAdvance =
445         FIXED_TO_INT( decoder.builder.advance.x );
446       cidglyph->linearHoriAdvance =
447         FIXED_TO_INT( decoder.builder.advance.x );
448       cidglyph->internal->glyph_transformed = 0;
449 
450       /* make up vertical ones */
451       metrics->vertAdvance        = ( face->cid.font_bbox.yMax -
452                                       face->cid.font_bbox.yMin ) >> 16;
453       cidglyph->linearVertAdvance = metrics->vertAdvance;
454 
455       cidglyph->format            = FT_GLYPH_FORMAT_OUTLINE;
456 
457       if ( cidsize->metrics.y_ppem < 24 )
458         cidglyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
459 
460       /* apply the font matrix, if any */
461       if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L ||
462            font_matrix.xy != 0        || font_matrix.yx != 0        )
463       {
464         FT_Outline_Transform( &cidglyph->outline, &font_matrix );
465 
466         metrics->horiAdvance = FT_MulFix( metrics->horiAdvance,
467                                           font_matrix.xx );
468         metrics->vertAdvance = FT_MulFix( metrics->vertAdvance,
469                                           font_matrix.yy );
470       }
471 
472       if ( font_offset.x || font_offset.y )
473       {
474         FT_Outline_Translate( &cidglyph->outline,
475                               font_offset.x,
476                               font_offset.y );
477 
478         metrics->horiAdvance += font_offset.x;
479         metrics->vertAdvance += font_offset.y;
480       }
481 
482       if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || scaled )
483       {
484         /* scale the outline and the metrics */
485         FT_Int       n;
486         FT_Outline*  cur = decoder.builder.base;
487         FT_Vector*   vec = cur->points;
488         FT_Fixed     x_scale = glyph->x_scale;
489         FT_Fixed     y_scale = glyph->y_scale;
490 
491 
492         /* First of all, scale the points */
493         if ( !hinting || !decoder.builder.hints_funcs )
494           for ( n = cur->n_points; n > 0; n--, vec++ )
495           {
496             vec->x = FT_MulFix( vec->x, x_scale );
497             vec->y = FT_MulFix( vec->y, y_scale );
498           }
499 
500         /* Then scale the metrics */
501         metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
502         metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
503       }
504 
505       /* compute the other metrics */
506       FT_Outline_Get_CBox( &cidglyph->outline, &cbox );
507 
508       metrics->width  = cbox.xMax - cbox.xMin;
509       metrics->height = cbox.yMax - cbox.yMin;
510 
511       metrics->horiBearingX = cbox.xMin;
512       metrics->horiBearingY = cbox.yMax;
513 
514       if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
515       {
516         /* make up vertical ones */
517         ft_synthesize_vertical_metrics( metrics,
518                                         metrics->vertAdvance );
519       }
520     }
521 
522   Exit:
523 
524     if ( must_finish_decoder )
525       psaux->t1_decoder_funcs->done( &decoder );
526 
527     return error;
528   }
529 
530 
531 /* END */
532