1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* cidgload.c */ 4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* CID-keyed Type1 Glyph Loader (body). */ 6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 7ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann/* Copyright 1996-2015 by */ 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* This file is part of the FreeType project, and may only be used, */ 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* modified, and distributed under the terms of the FreeType project */ 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* this file you indicate that you have read the license and */ 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* understand and accept it fully. */ 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 19e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include <ft2build.h> 20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cidload.h" 21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cidgload.h" 22e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_INTERNAL_DEBUG_H 23e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_INTERNAL_STREAM_H 24e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_OUTLINE_H 25e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_INTERNAL_CALC_H 26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ciderrs.h" 28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* messages during execution. */ 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef FT_COMPONENT 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_COMPONENT trace_cidgload 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_load_glyph( T1_Decoder decoder, 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt glyph_index ) 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Face face = (CID_Face)decoder->builder.face; 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_FaceInfo cid = &face->cid; 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p; 47ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann FT_ULong fd_select; 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream stream = face->cid_stream; 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error = FT_Err_Ok; 50ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann FT_Byte* charstring = NULL; 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = face->root.memory; 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong glyph_length = 0; 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PSAux_Service psaux = (PSAux_Service)face->psaux; 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_CONFIG_OPTION_INCREMENTAL 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Incremental_InterfaceRec *inc = 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->root.internal->incremental_interface; 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 61e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FT_TRACE1(( "cid_load_glyph: glyph index %d\n", glyph_index )); 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_CONFIG_OPTION_INCREMENTAL 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* For incremental fonts get the character data using */ 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the callback function. */ 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( inc ) 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Data glyph_data; 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = inc->funcs->get_glyph_data( inc->object, 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_index, &glyph_data ); 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = (FT_Byte*)glyph_data.pointer; 78ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann fd_select = cid_get_offset( &p, (FT_Byte)cid->fd_bytes ); 79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( glyph_data.length != 0 ) 81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 82ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann glyph_length = (FT_ULong)( glyph_data.length - cid->fd_bytes ); 83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (void)FT_ALLOC( charstring, glyph_length ); 84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error ) 85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_memcpy( charstring, glyph_data.pointer + cid->fd_bytes, 86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_length ); 87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov inc->funcs->free_glyph_data( inc->object, &glyph_data ); 90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* For ordinary fonts read the CID font dictionary index */ 100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* and charstring offset from the CIDMap. */ 101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 102ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann FT_UInt entry_len = (FT_UInt)( cid->fd_bytes + cid->gd_bytes ); 103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong off1; 104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset + 107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_index * entry_len ) || 108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_ENTER( 2 * entry_len ) ) 109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = (FT_Byte*)stream->cursor; 112ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann fd_select = cid_get_offset( &p, (FT_Byte)cid->fd_bytes ); 113ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann off1 = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ); 114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += cid->fd_bytes; 115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_length = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1; 116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_EXIT(); 117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 118ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann if ( fd_select >= (FT_ULong)cid->num_dicts ) 119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Invalid_Offset ); 121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( glyph_length == 0 ) 124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_ALLOC( charstring, glyph_length ) ) 126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_STREAM_READ_AT( cid->data_offset + off1, 128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charstring, glyph_length ) ) 129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Now set up the subrs array and parse the charstrings. */ 133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_FaceDict dict; 135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Subrs cid_subrs = face->subrs + fd_select; 136ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann FT_UInt cs_offset; 137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Set up subrs */ 140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->num_subrs = cid_subrs->num_subrs; 141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->subrs = cid_subrs->code; 142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->subrs_len = 0; 143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Set up font matrix */ 145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dict = cid->font_dicts + fd_select; 146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->font_matrix = dict->font_matrix; 148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->font_offset = dict->font_offset; 149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->lenIV = dict->private_dict.lenIV; 150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Decode the charstring. */ 152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Adjustment for seed bytes. */ 154ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann cs_offset = decoder->lenIV >= 0 ? (FT_UInt)decoder->lenIV : 0; 155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Decrypt only if lenIV >= 0. */ 157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( decoder->lenIV >= 0 ) 158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov psaux->t1_decrypt( charstring, glyph_length, 4330 ); 159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = decoder->funcs.parse_charstrings( 161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder, charstring + cs_offset, 162ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann glyph_length - cs_offset ); 163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( charstring ); 166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_CONFIG_OPTION_INCREMENTAL 168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Incremental fonts can optionally override the metrics. */ 170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error && inc && inc->funcs->get_glyph_metrics ) 171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Incremental_MetricsRec metrics; 173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics.bearing_x = FIXED_TO_INT( decoder->builder.left_bearing.x ); 176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics.bearing_y = 0; 177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics.advance = FIXED_TO_INT( decoder->builder.advance.x ); 178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics.advance_v = FIXED_TO_INT( decoder->builder.advance.y ); 179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = inc->funcs->get_glyph_metrics( inc->object, 181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_index, FALSE, &metrics ); 182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->builder.left_bearing.x = INT_TO_FIXED( metrics.bearing_x ); 184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->builder.advance.x = INT_TO_FIXED( metrics.advance ); 185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->builder.advance.y = INT_TO_FIXED( metrics.advance_v ); 186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if 0 196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** *********/ 202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** *********/ 203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ 204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** *********/ 205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** The following code is in charge of computing *********/ 206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** the maximum advance width of the font. It *********/ 207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** quickly processes each glyph charstring to *********/ 208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** extract the value from either a `sbw' or `seac' *********/ 209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** operator. *********/ 210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** *********/ 211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_face_compute_max_advance( CID_Face face, 218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int* max_advance ) 219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov T1_DecoderRec decoder; 222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int glyph_index; 223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PSAux_Service psaux = (PSAux_Service)face->psaux; 225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *max_advance = 0; 228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Initialize load decoder */ 230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = psaux->t1_decoder_funcs->init( &decoder, 231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Face)face, 232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, /* size */ 233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, /* glyph slot */ 234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, /* glyph names! XXX */ 235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, /* blend == 0 */ 236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, /* hinting == 0 */ 237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_load_glyph ); 238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TODO: initialize decoder.len_buildchar and decoder.buildchar */ 242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if we ever support CID-keyed multiple master fonts */ 243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder.builder.metrics_only = 1; 245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder.builder.load_points = 0; 246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* for each glyph, parse the glyph charstring and extract */ 248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the advance width */ 249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( glyph_index = 0; glyph_index < face->root.num_glyphs; 250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_index++ ) 251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* now get load the unscaled outline */ 253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cid_load_glyph( &decoder, glyph_index ); 254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ignore the error if one occurred - skip to next glyph */ 255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *max_advance = FIXED_TO_INT( decoder.builder.advance.x ); 258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov psaux->t1_decoder_funcs->done( &decoder ); 260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* 0 */ 266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_slot_load_glyph( FT_GlyphSlot cidglyph, /* CID_GlyphSlot */ 270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Size cidsize, /* CID_Size */ 271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt glyph_index, 272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int32 load_flags ) 273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_GlyphSlot glyph = (CID_GlyphSlot)cidglyph; 275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov T1_DecoderRec decoder; 277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Face face = (CID_Face)cidglyph->face; 278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bool hinting; 279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PSAux_Service psaux = (PSAux_Service)face->psaux; 281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Matrix font_matrix; 282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector font_offset; 283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) 286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Invalid_Argument ); 288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( load_flags & FT_LOAD_NO_RECURSE ) 292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; 293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->x_scale = cidsize->metrics.x_scale; 295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->y_scale = cidsize->metrics.y_scale; 296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cidglyph->outline.n_points = 0; 298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cidglyph->outline.n_contours = 0; 299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && 301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); 302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cidglyph->format = FT_GLYPH_FORMAT_OUTLINE; 304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = psaux->t1_decoder_funcs->init( &decoder, 306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cidglyph->face, 307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cidsize, 308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cidglyph, 309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, /* glyph names -- XXX */ 310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, /* blend == 0 */ 311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hinting, 312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOAD_TARGET_MODE( load_flags ), 313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_load_glyph ); 314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TODO: initialize decoder.len_buildchar and decoder.buildchar */ 318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if we ever support CID-keyed multiple master fonts */ 319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* set up the decoder */ 321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder.builder.no_recurse = FT_BOOL( 322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ) ); 323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cid_load_glyph( &decoder, glyph_index ); 325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov font_matrix = decoder.font_matrix; 329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov font_offset = decoder.font_offset; 330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* save new glyph tables */ 332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov psaux->t1_decoder_funcs->done( &decoder ); 333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* now set the metrics -- this is rather simple, as */ 335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the left side bearing is the xMin, and the top side */ 336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* bearing the yMax */ 337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cidglyph->outline.flags &= FT_OUTLINE_OWNER; 338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cidglyph->outline.flags |= FT_OUTLINE_REVERSE_FILL; 339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* for composite glyphs, return only left side bearing and */ 341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* advance width */ 342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( load_flags & FT_LOAD_NO_RECURSE ) 343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Slot_Internal internal = cidglyph->internal; 345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cidglyph->metrics.horiBearingX = 348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FIXED_TO_INT( decoder.builder.left_bearing.x ); 349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cidglyph->metrics.horiAdvance = 350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FIXED_TO_INT( decoder.builder.advance.x ); 351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov internal->glyph_matrix = font_matrix; 353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov internal->glyph_delta = font_offset; 354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov internal->glyph_transformed = 1; 355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_BBox cbox; 359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Glyph_Metrics* metrics = &cidglyph->metrics; 360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* copy the _unscaled_ advance width */ 363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->horiAdvance = 364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FIXED_TO_INT( decoder.builder.advance.x ); 365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cidglyph->linearHoriAdvance = 366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FIXED_TO_INT( decoder.builder.advance.x ); 367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cidglyph->internal->glyph_transformed = 0; 368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* make up vertical ones */ 370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->vertAdvance = ( face->cid.font_bbox.yMax - 371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->cid.font_bbox.yMin ) >> 16; 372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cidglyph->linearVertAdvance = metrics->vertAdvance; 373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cidglyph->format = FT_GLYPH_FORMAT_OUTLINE; 375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cidsize->metrics.y_ppem < 24 ) 377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cidglyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; 378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 379ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann /* apply the font matrix, if any */ 380ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L || 381ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann font_matrix.xy != 0 || font_matrix.yx != 0 ) 382ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann { 383ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann FT_Outline_Transform( &cidglyph->outline, &font_matrix ); 384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 385ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, 386ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann font_matrix.xx ); 387ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, 388ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann font_matrix.yy ); 389ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann } 390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 391ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann if ( font_offset.x || font_offset.y ) 392ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann { 393ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann FT_Outline_Translate( &cidglyph->outline, 394ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann font_offset.x, 395ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann font_offset.y ); 396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 397ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann metrics->horiAdvance += font_offset.x; 398ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann metrics->vertAdvance += font_offset.y; 399ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann } 400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) 402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* scale the outline and the metrics */ 404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int n; 405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline* cur = decoder.builder.base; 406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* vec = cur->points; 407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed x_scale = glyph->x_scale; 408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed y_scale = glyph->y_scale; 409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* First of all, scale the points */ 412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !hinting || !decoder.builder.hints_funcs ) 413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = cur->n_points; n > 0; n--, vec++ ) 414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->x = FT_MulFix( vec->x, x_scale ); 416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->y = FT_MulFix( vec->y, y_scale ); 417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Then scale the metrics */ 420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); 421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); 422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* compute the other metrics */ 425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Get_CBox( &cidglyph->outline, &cbox ); 426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->width = cbox.xMax - cbox.xMin; 428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->height = cbox.yMax - cbox.yMin; 429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->horiBearingX = cbox.xMin; 431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->horiBearingY = cbox.yMax; 432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* make up vertical ones */ 436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_synthesize_vertical_metrics( metrics, 437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->vertAdvance ); 438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* END */ 447