1 /***************************************************************************/
2 /* */
3 /* cidgload.c */
4 /* */
5 /* CID-keyed Type1 Glyph Loader (body). */
6 /* */
7 /* Copyright 1996-2001 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 /***************************************************************************/
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
26 #include "ciderrs.h"
29 /*************************************************************************/
30 /* */
31 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
32 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
33 /* messages during execution. */
34 /* */
35 #undef FT_COMPONENT
36 #define FT_COMPONENT trace_cidgload
39 FT_CALLBACK_DEF( FT_Error )
40 cid_load_glyph( T1_Decoder* decoder,
41 FT_UInt glyph_index )
42 {
43 CID_Face face = (CID_Face)decoder->builder.face;
44 CID_Info* cid = &face->cid;
45 FT_Byte* p;
46 FT_UInt entry_len = cid->fd_bytes + cid->gd_bytes;
47 FT_UInt fd_select;
48 FT_ULong off1, glyph_len;
49 FT_Stream stream = face->root.stream;
50 FT_Error error = 0;
53 /* read the CID font dict index and charstring offset from the CIDMap */
54 if ( FILE_Seek( cid->data_offset + cid->cidmap_offset +
55 glyph_index * entry_len ) ||
56 ACCESS_Frame( 2 * entry_len ) )
57 goto Exit;
59 p = (FT_Byte*)stream->cursor;
60 fd_select = (FT_UInt) cid_get_offset( &p, (FT_Byte)cid->fd_bytes );
61 off1 = (FT_ULong)cid_get_offset( &p, (FT_Byte)cid->gd_bytes );
62 p += cid->fd_bytes;
63 glyph_len = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1;
65 FORGET_Frame();
67 /* now, if the glyph is not empty, set up the subrs array, and parse */
68 /* the charstrings */
69 if ( glyph_len > 0 )
70 {
71 CID_FontDict* dict;
72 CID_Subrs* cid_subrs = face->subrs + fd_select;
73 FT_Byte* charstring;
74 FT_Memory memory = face->root.memory;
77 /* setup subrs */
78 decoder->num_subrs = cid_subrs->num_subrs;
79 decoder->subrs = cid_subrs->code;
80 decoder->subrs_len = 0;
82 /* setup font matrix */
83 dict = cid->font_dicts + fd_select;
85 decoder->font_matrix = dict->font_matrix;
86 decoder->font_offset = dict->font_offset;
87 decoder->lenIV = dict->private_dict.lenIV;
89 /* the charstrings are encoded (stupid!) */
90 /* load the charstrings, then execute it */
92 if ( ALLOC( charstring, glyph_len ) )
93 goto Exit;
95 if ( !FILE_Read_At( cid->data_offset + off1, charstring, glyph_len ) )
96 {
97 FT_Int cs_offset;
100 /* Adjustment for seed bytes. */
101 cs_offset = ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
103 /* Decrypt only if lenIV >= 0. */
104 if ( decoder->lenIV >= 0 )
105 cid_decrypt( charstring, glyph_len, 4330 );
107 error = decoder->funcs.parse_charstrings( decoder,
108 charstring + cs_offset,
109 glyph_len - cs_offset );
110 }
112 FREE( charstring );
113 }
115 Exit:
116 return error;
117 }
120 #if 0
123 /*************************************************************************/
124 /*************************************************************************/
125 /*************************************************************************/
126 /********** *********/
127 /********** *********/
128 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
129 /********** *********/
130 /********** The following code is in charge of computing *********/
131 /********** the maximum advance width of the font. It *********/
132 /********** quickly processes each glyph charstring to *********/
133 /********** extract the value from either a `sbw' or `seac' *********/
134 /********** operator. *********/
135 /********** *********/
136 /*************************************************************************/
137 /*************************************************************************/
138 /*************************************************************************/
141 FT_LOCAL_DEF FT_Error
142 CID_Compute_Max_Advance( CID_Face face,
143 FT_Int* max_advance )
144 {
145 FT_Error error;
146 T1_Decoder decoder;
147 FT_Int glyph_index;
149 PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
152 *max_advance = 0;
154 /* Initialize load decoder */
155 error = psaux->t1_decoder_funcs->init( &decoder,
156 (FT_Face)face,
157 0, /* size */
158 0, /* glyph slot */
159 0, /* glyph names! XXX */
160 0, /* blend == 0 */
161 cid_load_glyph );
162 if ( error )
163 return error;
165 decoder.builder.metrics_only = 1;
166 decoder.builder.load_points = 0;
168 /* for each glyph, parse the glyph charstring and extract */
169 /* the advance width */
170 for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
171 glyph_index++ )
172 {
173 /* now get load the unscaled outline */
174 error = cid_load_glyph( &decoder, glyph_index );
175 /* ignore the error if one occurred - skip to next glyph */
176 }
178 *max_advance = decoder.builder.advance.x;
180 return CID_Err_Ok;
181 }
184 #endif /* 0 */
187 /*************************************************************************/
188 /*************************************************************************/
189 /*************************************************************************/
190 /********** *********/
191 /********** *********/
192 /********** UNHINTED GLYPH LOADER *********/
193 /********** *********/
194 /********** The following code is in charge of loading a *********/
195 /********** single outline. It completely ignores hinting *********/
196 /********** and is used when FT_LOAD_NO_HINTING is set. *********/
197 /********** *********/
198 /*************************************************************************/
199 /*************************************************************************/
200 /*************************************************************************/
203 FT_LOCAL_DEF FT_Error
204 CID_Load_Glyph( CID_GlyphSlot glyph,
205 CID_Size size,
206 FT_Int glyph_index,
207 FT_Int load_flags )
208 {
209 FT_Error error;
210 T1_Decoder decoder;
211 CID_Face face = (CID_Face)glyph->root.face;
212 FT_Bool hinting;
214 PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
215 FT_Matrix font_matrix;
216 FT_Vector font_offset;
219 if ( load_flags & FT_LOAD_NO_RECURSE )
220 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
222 glyph->x_scale = size->root.metrics.x_scale;
223 glyph->y_scale = size->root.metrics.y_scale;
225 glyph->root.outline.n_points = 0;
226 glyph->root.outline.n_contours = 0;
228 hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
229 ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
231 glyph->root.format = ft_glyph_format_outline;
233 {
234 error = psaux->t1_decoder_funcs->init( &decoder,
235 (FT_Face)face,
236 (FT_Size)size,
237 (FT_GlyphSlot)glyph,
238 0, /* glyph names -- XXX */
239 0, /* blend == 0 */
240 cid_load_glyph );
242 /* set up the decoder */
243 decoder.builder.no_recurse = FT_BOOL(
244 ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ) );
246 error = cid_load_glyph( &decoder, glyph_index );
248 font_matrix = decoder.font_matrix;
249 font_offset = decoder.font_offset;
251 /* save new glyph tables */
252 psaux->t1_decoder_funcs->done( &decoder );
253 }
255 /* now, set the metrics -- this is rather simple, as */
256 /* the left side bearing is the xMin, and the top side */
257 /* bearing the yMax */
258 if ( !error )
259 {
260 glyph->root.outline.flags &= ft_outline_owner;
261 glyph->root.outline.flags |= ft_outline_reverse_fill;
263 /* for composite glyphs, return only left side bearing and */
264 /* advance width */
265 if ( load_flags & FT_LOAD_NO_RECURSE )
266 {
267 FT_Slot_Internal internal = glyph->root.internal;
270 glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
271 glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
273 internal->glyph_matrix = font_matrix;
274 internal->glyph_delta = font_offset;
275 internal->glyph_transformed = 1;
276 }
277 else
278 {
279 FT_BBox cbox;
280 FT_Glyph_Metrics* metrics = &glyph->root.metrics;
283 /* copy the _unscaled_ advance width */
284 metrics->horiAdvance = decoder.builder.advance.x;
285 glyph->root.linearHoriAdvance = decoder.builder.advance.x;
286 glyph->root.internal->glyph_transformed = 0;
288 /* make up vertical metrics */
289 metrics->vertBearingX = 0;
290 metrics->vertBearingY = 0;
291 metrics->vertAdvance = 0;
293 glyph->root.linearVertAdvance = 0;
294 glyph->root.format = ft_glyph_format_outline;
296 if ( size && size->root.metrics.y_ppem < 24 )
297 glyph->root.outline.flags |= ft_outline_high_precision;
299 /* apply the font matrix */
300 FT_Outline_Transform( &glyph->root.outline, &font_matrix );
302 FT_Outline_Translate( &glyph->root.outline,
303 font_offset.x,
304 font_offset.y );
306 if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
307 {
308 /* scale the outline and the metrics */
309 FT_Int n;
310 FT_Outline* cur = decoder.builder.base;
311 FT_Vector* vec = cur->points;
312 FT_Fixed x_scale = glyph->x_scale;
313 FT_Fixed y_scale = glyph->y_scale;
316 /* First of all, scale the points */
317 for ( n = cur->n_points; n > 0; n--, vec++ )
318 {
319 vec->x = FT_MulFix( vec->x, x_scale );
320 vec->y = FT_MulFix( vec->y, y_scale );
321 }
323 FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
325 /* Then scale the metrics */
326 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
327 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
329 metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
330 metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
331 }
333 /* compute the other metrics */
334 FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
336 /* grid fit the bounding box if necessary */
337 if ( hinting )
338 {
339 cbox.xMin &= -64;
340 cbox.yMin &= -64;
341 cbox.xMax = ( cbox.xMax + 63 ) & -64;
342 cbox.yMax = ( cbox.yMax + 63 ) & -64;
343 }
345 metrics->width = cbox.xMax - cbox.xMin;
346 metrics->height = cbox.yMax - cbox.yMin;
348 metrics->horiBearingX = cbox.xMin;
349 metrics->horiBearingY = cbox.yMax;
350 }
351 }
352 return error;
353 }
356 /* END */