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