]> git.saurik.com Git - wxWidgets.git/blame - src/freetype/truetype/ttgload.c
fix for rather mysterious problem when deleting the list ctrl
[wxWidgets.git] / src / freetype / truetype / ttgload.c
CommitLineData
cabec872
RR
1/***************************************************************************/
2/* */
3/* ttgload.c */
4/* */
5/* TrueType Glyph Loader (body). */
6/* */
7/* Copyright 1996-2000 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 <freetype/internal/ftdebug.h>
20#include <freetype/internal/ftcalc.h>
21#include <freetype/internal/ftstream.h>
22#include <freetype/internal/sfnt.h>
23#include <freetype/tttags.h>
24#include <freetype/ftoutln.h>
25
26
27#ifdef FT_FLAT_COMPILE
28
29#include "ttgload.h"
30
31#else
32
33#include <truetype/ttgload.h>
34
35#endif
36
37
38 /*************************************************************************/
39 /* */
40 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
41 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
42 /* messages during execution. */
43 /* */
44#undef FT_COMPONENT
45#define FT_COMPONENT trace_ttgload
46
47
48 /*************************************************************************/
49 /* */
50 /* Composite font flags. */
51 /* */
52#define ARGS_ARE_WORDS 0x001
53#define ARGS_ARE_XY_VALUES 0x002
54#define ROUND_XY_TO_GRID 0x004
55#define WE_HAVE_A_SCALE 0x008
56/* reserved 0x010 */
57#define MORE_COMPONENTS 0x020
58#define WE_HAVE_AN_XY_SCALE 0x040
59#define WE_HAVE_A_2X2 0x080
60#define WE_HAVE_INSTR 0x100
61#define USE_MY_METRICS 0x200
62
63
64
65 /*************************************************************************/
66 /* */
67 /* <Function> */
68 /* TT_Get_Metrics */
69 /* */
70 /* <Description> */
71 /* Returns the horizontal or vertical metrics in font units for a */
72 /* given glyph. The metrics are the left side bearing (resp. top */
73 /* side bearing) and advance width (resp. advance height). */
74 /* */
75 /* <Input> */
76 /* header :: A pointer to either the horizontal or vertical metrics */
77 /* structure. */
78 /* */
79 /* index :: The glyph index. */
80 /* */
81 /* <Output> */
82 /* bearing :: The bearing, either left side or top side. */
83 /* */
84 /* advance :: The advance width resp. advance height. */
85 /* */
86 /* <Note> */
87 /* This function will much probably move to another component in the */
88 /* near future, but I haven't decided which yet. */
89 /* */
90 LOCAL_FUNC
91 void TT_Get_Metrics( TT_HoriHeader* header,
92 FT_UInt index,
93 FT_Short* bearing,
94 FT_UShort* advance )
95 {
96 TT_LongMetrics* longs_m;
97 FT_UShort k = header->number_Of_HMetrics;
98
99
100 if ( index < k )
101 {
102 longs_m = (TT_LongMetrics*)header->long_metrics + index;
103 *bearing = longs_m->bearing;
104 *advance = longs_m->advance;
105 }
106 else
107 {
108 *bearing = ((TT_ShortMetrics*)header->short_metrics)[index - k];
109 *advance = ((TT_LongMetrics*)header->long_metrics)[k - 1].advance;
110 }
111 }
112
113
114 /*************************************************************************/
115 /* */
116 /* Returns the horizontal metrics in font units for a given glyph. If */
117 /* `check' is true, take care of monospaced fonts by returning the */
118 /* advance width maximum. */
119 /* */
120 static
121 void Get_HMetrics( TT_Face face,
122 FT_UInt index,
123 FT_Bool check,
124 FT_Short* lsb,
125 FT_UShort* aw )
126 {
127 TT_Get_Metrics( &face->horizontal, index, lsb, aw );
128
129 if ( check && face->postscript.isFixedPitch )
130 *aw = face->horizontal.advance_Width_Max;
131 }
132
133
134 /*************************************************************************/
135 /* */
136 /* Returns the advance width table for a given pixel size if it is */
137 /* found in the font's `hdmx' table (if any). */
138 /* */
139 static
140 FT_Byte* Get_Advance_Widths( TT_Face face,
141 FT_UShort ppem )
142 {
143 FT_UShort n;
144
145 for ( n = 0; n < face->hdmx.num_records; n++ )
146 if ( face->hdmx.records[n].ppem == ppem )
147 return face->hdmx.records[n].widths;
148
149 return NULL;
150 }
151
152
153#define cur_to_org( n, zone ) \
154 MEM_Copy( (zone)->org, (zone)->cur, n * sizeof ( FT_Vector ) )
155
156#define org_to_cur( n, zone ) \
157 MEM_Copy( (zone)->cur, (zone)->org, n * sizeof ( FT_Vector ) )
158
159
160 /*************************************************************************/
161 /* */
162 /* Translates an array of coordinates. */
163 /* */
164 static
165 void translate_array( FT_UInt n,
166 FT_Vector* coords,
167 FT_Pos delta_x,
168 FT_Pos delta_y )
169 {
170 FT_UInt k;
171
172
173 if ( delta_x )
174 for ( k = 0; k < n; k++ )
175 coords[k].x += delta_x;
176
177 if ( delta_y )
178 for ( k = 0; k < n; k++ )
179 coords[k].y += delta_y;
180 }
181
182
183 static
184 void tt_prepare_zone( TT_GlyphZone* zone,
185 FT_GlyphLoad* load,
186 FT_UInt start_point,
187 FT_UInt start_contour )
188 {
189 zone->n_points = load->outline.n_points - start_point;
190 zone->n_contours = load->outline.n_contours - start_contour;
191 zone->org = load->extra_points + start_point;
192 zone->cur = load->outline.points + start_point;
193 zone->tags = (FT_Byte*)load->outline.tags + start_point;
194 zone->contours = (FT_UShort*)load->outline.contours + start_contour;
195 }
196
197
198#undef IS_HINTED
199#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
200
201
202 /*************************************************************************/
203 /* */
204 /* The following functions are used by default with TrueType fonts. */
205 /* However, they can be replaced by alternatives if we need to support */
206 /* TrueType-compressed formats (like MicroType) in the future. */
207 /* */
208 /*************************************************************************/
209
210 static
211 FT_Error TT_Access_Glyph_Frame( TT_Loader* loader,
212 FT_UInt glyph_index,
213 FT_ULong offset,
214 FT_UInt byte_count )
215 {
216 FT_Error error;
217 FT_Stream stream = loader->stream;
218
219
220 /* the following line sets the `error' variable through macros! */
221 (void)( FILE_Seek( offset ) || ACCESS_Frame( byte_count ) );
222
223 FT_TRACE5(( "Glyph %ld\n", glyph_index ));
224 return error;
225 }
226
227
228 static
229 void TT_Forget_Glyph_Frame( TT_Loader* loader )
230 {
231 FT_Stream stream = loader->stream;
232
233
234 FORGET_Frame();
235 }
236
237
238 static
239 FT_Error TT_Load_Glyph_Header( TT_Loader* loader )
240 {
241 FT_Stream stream = loader->stream;
242
243
244 loader->n_contours = GET_Short();
245
246 loader->bbox.xMin = GET_Short();
247 loader->bbox.yMin = GET_Short();
248 loader->bbox.xMax = GET_Short();
249 loader->bbox.yMax = GET_Short();
250
251 FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
252 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
253 loader->bbox.xMax ));
254 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
255 loader->bbox.yMax ));
256
257 return FT_Err_Ok;
258 }
259
260
261 static
262 FT_Error TT_Load_Simple_Glyph( TT_Loader* load )
263 {
264 FT_Error error;
265 FT_Stream stream = load->stream;
266 FT_GlyphLoader* gloader = load->gloader;
267 FT_Int n_contours = load->n_contours;
268 FT_Outline* outline;
269 TT_Face face = (TT_Face)load->face;
270 TT_GlyphSlot slot = (TT_GlyphSlot)load->glyph;
271 FT_UShort n_ins;
272 FT_Int n, n_points;
273
274
275 /* reading the contours endpoints & number of points */
276 {
277 short* cur = gloader->current.outline.contours;
278 short* limit = cur + n_contours;
279
280
281 for ( ; cur < limit; cur++ )
282 cur[0] = GET_UShort();
283
284 n_points = 0;
285 if ( n_contours > 0 )
286 n_points = cur[-1] + 1;
287
288 error = FT_GlyphLoader_Check_Points( gloader, n_points + 2, 0 );
289 if ( error )
290 goto Fail;
291
292 outline = &gloader->current.outline;
293 }
294
295 /* reading the bytecode instructions */
296 slot->control_len = 0;
297 slot->control_data = 0;
298
299 n_ins = GET_UShort();
300
301 FT_TRACE5(( " Instructions size: %d\n", n_ins ));
302
303 if ( n_ins > face->max_profile.maxSizeOfInstructions )
304 {
305 FT_TRACE0(( "ERROR: Too many instructions!\n" ));
306 error = TT_Err_Too_Many_Ins;
307 goto Fail;
308 }
309
310 if ( stream->cursor + n_ins > stream->limit )
311 {
312 FT_TRACE0(( "ERROR: Instruction count mismatch!\n" ));
313 error = TT_Err_Too_Many_Ins;
314 goto Fail;
315 }
316
317#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
318
319 if ( ( load->load_flags &
320 ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 &&
321 load->instructions )
322 {
323 slot->control_len = n_ins;
324 slot->control_data = load->instructions;
325
326 MEM_Copy( load->instructions, stream->cursor, n_ins );
327 }
328
329#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
330
331 stream->cursor += n_ins;
332
333 /* reading the point tags */
334
335 {
336 FT_Byte* flag = (FT_Byte*)outline->tags;
337 FT_Byte* limit = flag + n_points;
338 FT_Byte c, count;
339
340
341 for ( ; flag < limit; flag++ )
342 {
343 *flag = c = GET_Byte();
344 if ( c & 8 )
345 {
346 for ( count = GET_Byte(); count > 0; count-- )
347 *++flag = c;
348 }
349 }
350 }
351
352 /* reading the X coordinates */
353
354 {
355 FT_Vector* vec = outline->points;
356 FT_Vector* limit = vec + n_points;
357 FT_Byte* flag = (FT_Byte*)outline->tags;
358 FT_Pos x = 0;
359
360
361 for ( ; vec < limit; vec++, flag++ )
362 {
363 FT_Pos y = 0;
364
365
366 if ( *flag & 2 )
367 {
368 y = GET_Byte();
369 if ( ( *flag & 16 ) == 0 )
370 y = -y;
371 }
372 else if ( ( *flag & 16 ) == 0 )
373 y = GET_Short();
374
375 x += y;
376 vec->x = x;
377 }
378 }
379
380 /* reading the Y coordinates */
381
382 {
383 FT_Vector* vec = gloader->current.outline.points;
384 FT_Vector* limit = vec + n_points;
385 FT_Byte* flag = (FT_Byte*)outline->tags;
386 FT_Pos x = 0;
387
388
389 for ( ; vec < limit; vec++, flag++ )
390 {
391 FT_Pos y = 0;
392
393
394 if ( *flag & 4 )
395 {
396 y = GET_Byte();
397 if ( ( *flag & 32 ) == 0 )
398 y = -y;
399 }
400 else if ( ( *flag & 32 ) == 0 )
401 y = GET_Short();
402
403 x += y;
404 vec->y = x;
405 }
406 }
407
408 /* clear the touch tags */
409 for ( n = 0; n < n_points; n++ )
410 outline->tags[n] &= FT_Curve_Tag_On;
411
412 outline->n_points = n_points;
413 outline->n_contours = n_contours;
414
415 Fail:
416 return error;
417 }
418
419
420 static
421 FT_Error TT_Load_Composite_Glyph( TT_Loader* loader )
422 {
423 FT_Error error;
424 FT_Stream stream = loader->stream;
425 FT_GlyphLoader* gloader = loader->gloader;
426 FT_SubGlyph* subglyph;
427 FT_UInt num_subglyphs;
428
429
430 num_subglyphs = 0;
431
432 do
433 {
434 FT_Fixed xx, xy, yy, yx;
435
436
437 /* check that we can load a new subglyph */
438 error = FT_GlyphLoader_Check_Subglyphs( gloader, num_subglyphs + 1 );
439 if ( error )
440 goto Fail;
441
442 subglyph = gloader->current.subglyphs + num_subglyphs;
443
444 subglyph->arg1 = subglyph->arg2 = 0;
445
446 subglyph->flags = GET_UShort();
447 subglyph->index = GET_UShort();
448
449 /* read arguments */
450 if ( subglyph->flags & ARGS_ARE_WORDS )
451 {
452 subglyph->arg1 = GET_Short();
453 subglyph->arg2 = GET_Short();
454 }
455 else
456 {
457 subglyph->arg1 = GET_Char();
458 subglyph->arg2 = GET_Char();
459 }
460
461 /* read transform */
462 xx = yy = 0x10000L;
463 xy = yx = 0;
464
465 if ( subglyph->flags & WE_HAVE_A_SCALE )
466 {
467 xx = (FT_Fixed)GET_Short() << 2;
468 yy = xx;
469 }
470 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
471 {
472 xx = (FT_Fixed)GET_Short() << 2;
473 yy = (FT_Fixed)GET_Short() << 2;
474 }
475 else if ( subglyph->flags & WE_HAVE_A_2X2 )
476 {
477 xx = (FT_Fixed)GET_Short() << 2;
478 xy = (FT_Fixed)GET_Short() << 2;
479 yx = (FT_Fixed)GET_Short() << 2;
480 yy = (FT_Fixed)GET_Short() << 2;
481 }
482
483 subglyph->transform.xx = xx;
484 subglyph->transform.xy = xy;
485 subglyph->transform.yx = yx;
486 subglyph->transform.yy = yy;
487
488 num_subglyphs++;
489
490 } while ( subglyph->flags & MORE_COMPONENTS );
491
492 gloader->current.num_subglyphs = num_subglyphs;
493
494#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
495 {
496 /* we must undo the ACCESS_Frame in order to point to the */
497 /* composite instructions, if we find some. */
498 /* we will process them later... */
499 /* */
500 loader->ins_pos = FILE_Pos() + stream->cursor - stream->limit;
501 }
502#endif
503
504 Fail:
505 return error;
506 }
507
508
509 LOCAL_FUNC
510 void TT_Init_Glyph_Loading( TT_Face face )
511 {
512 face->access_glyph_frame = TT_Access_Glyph_Frame;
513 face->read_glyph_header = TT_Load_Glyph_Header;
514 face->read_simple_glyph = TT_Load_Simple_Glyph;
515 face->read_composite_glyph = TT_Load_Composite_Glyph;
516 face->forget_glyph_frame = TT_Forget_Glyph_Frame;
517 }
518
519
520 /*************************************************************************/
521 /* */
522 /* <Function> */
523 /* TT_Process_Simple_Glyph */
524 /* */
525 /* <Description> */
526 /* Once a simple glyph has been loaded, it needs to be processed. */
527 /* Usually, this means scaling and hinting through bytecode */
528 /* interpretation. */
529 /* */
530 static
531 FT_Error TT_Process_Simple_Glyph( TT_Loader* load,
532 FT_Bool debug )
533 {
534 FT_GlyphLoader* gloader = load->gloader;
535 FT_Outline* outline = &gloader->current.outline;
536 FT_UInt n_points = outline->n_points;
537 FT_UInt n_ins;
538 TT_GlyphZone* zone = &load->zone;
539 FT_Error error = FT_Err_Ok;
540
541
542 n_ins = load->glyph->control_len;
543
544 /* add shadow points */
545
546 /* Now add the two shadow points at n and n + 1. */
547 /* We need the left side bearing and advance width. */
548
549 {
550 FT_Vector* pp1;
551 FT_Vector* pp2;
552
553
554 /* pp1 = xMin - lsb */
555 pp1 = outline->points + n_points;
556 pp1->x = load->bbox.xMin - load->left_bearing;
557 pp1->y = 0;
558
559 /* pp2 = pp1 + aw */
560 pp2 = pp1 + 1;
561 pp2->x = pp1->x + load->advance;
562 pp2->y = 0;
563
564 outline->tags[n_points ] = 0;
565 outline->tags[n_points + 1] = 0;
566 }
567
568 /* Note that we return two more points that are not */
569 /* part of the glyph outline. */
570
571 n_points += 2;
572
573 /* set up zone for hinting */
574 tt_prepare_zone( zone, &gloader->current, 0, 0 );
575
576 /* eventually scale the glyph */
577 if ( !( load->load_flags & FT_LOAD_NO_SCALE ) )
578 {
579 FT_Vector* vec = zone->cur;
580 FT_Vector* limit = vec + n_points;
581 FT_Fixed x_scale = load->size->metrics.x_scale;
582 FT_Fixed y_scale = load->size->metrics.y_scale;
583
584
585 /* first scale the glyph points */
586 for ( ; vec < limit; vec++ )
587 {
588 vec->x = FT_MulFix( vec->x, x_scale );
589 vec->y = FT_MulFix( vec->y, y_scale );
590 }
591 }
592
593 cur_to_org( n_points, zone );
594
595 /* eventually hint the glyph */
596 if ( IS_HINTED( load->load_flags ) )
597 {
598 FT_Pos x = zone->org[n_points-2].x;
599
600
601 x = ( ( x + 32 ) & -64 ) - x;
602 translate_array( n_points, zone->org, x, 0 );
603
604 org_to_cur( n_points, zone );
605
606 zone->cur[n_points - 1].x = ( zone->cur[n_points - 1].x + 32 ) & -64;
607
608#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
609
610 /* now consider hinting */
611 if ( n_ins > 0 )
612 {
613 error = TT_Set_CodeRange( load->exec, tt_coderange_glyph,
614 load->exec->glyphIns, n_ins );
615 if ( error )
616 goto Exit;
617
618 load->exec->is_composite = FALSE;
619 load->exec->pedantic_hinting = (FT_Bool)( load->load_flags &
620 FT_LOAD_PEDANTIC );
621 load->exec->pts = *zone;
622 load->exec->pts.n_points += 2;
623
624 error = TT_Run_Context( load->exec, debug );
625 if ( error && load->exec->pedantic_hinting )
626 goto Exit;
627
628 error = FT_Err_Ok; /* ignore bytecode errors in non-pedantic mode */
629 }
630
631#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
632
633 }
634
635 /* save glyph phantom points */
636 if ( !load->preserve_pps )
637 {
638 load->pp1 = zone->cur[n_points - 2];
639 load->pp2 = zone->cur[n_points - 1];
640 }
641
642#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
643 Exit:
644#endif
645 return error;
646 }
647
648
649 /*************************************************************************/
650 /* */
651 /* <Function> */
652 /* load_truetype_glyph */
653 /* */
654 /* <Description> */
655 /* Loads a given truetype glyph. Handles composites and uses a */
656 /* TT_Loader object. */
657 /* */
658 static
659 FT_Error load_truetype_glyph( TT_Loader* loader,
660 FT_UInt glyph_index )
661 {
662 FT_Stream stream = loader->stream;
663 FT_Error error;
664 TT_Face face = (TT_Face)loader->face;
665 FT_ULong offset;
666 FT_Int contours_count;
667 FT_UInt index, num_points, num_contours, count;
668 FT_Fixed x_scale, y_scale;
669 FT_ULong ins_offset;
670 FT_GlyphLoader* gloader = loader->gloader;
671 FT_Bool opened_frame = 0;
672
673
674 /* check glyph index */
675 index = glyph_index;
676 if ( index >= (FT_UInt)face->root.num_glyphs )
677 {
678 error = TT_Err_Invalid_Glyph_Index;
679 goto Exit;
680 }
681
682 loader->glyph_index = glyph_index;
683 num_contours = 0;
684 num_points = 0;
685 ins_offset = 0;
686
687 x_scale = 0x10000L;
688 y_scale = 0x10000L;
689 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
690 {
691 x_scale = loader->size->metrics.x_scale;
692 y_scale = loader->size->metrics.y_scale;
693 }
694
695 /* get horizontal metrics */
696 {
697 FT_Short left_bearing;
698 FT_UShort advance_width;
699
700
701 Get_HMetrics( face, index,
702 (FT_Bool)!(loader->load_flags &
703 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH),
704 &left_bearing,
705 &advance_width );
706
707 loader->left_bearing = left_bearing;
708 loader->advance = advance_width;
709 }
710
711 offset = face->glyph_locations[index];
712 count = 0;
713
714 if ( index < (FT_UInt)face->num_locations - 1 )
715 count = face->glyph_locations[index + 1] - offset;
716
717 if ( count == 0 )
718 {
719 /* as described by Frederic Loyer, these are spaces, and */
720 /* not the unknown glyph. */
721 loader->bbox.xMin = 0;
722 loader->bbox.xMax = 0;
723 loader->bbox.yMin = 0;
724 loader->bbox.yMax = 0;
725
726 loader->pp1.x = 0;
727 loader->pp2.x = loader->advance;
728
729 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
730 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
731
732#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
733
734 if ( loader->exec )
735 loader->exec->glyphSize = 0;
736
737#endif
738
739 error = FT_Err_Ok;
740 goto Exit;
741 }
742
743 offset = loader->glyf_offset + offset;
744
745 /* access glyph frame */
746 error = face->access_glyph_frame( loader, glyph_index, offset, count );
747 if ( error )
748 goto Exit;
749
750 opened_frame = 1;
751
752 /* read first glyph header */
753 error = face->read_glyph_header( loader );
754 if ( error )
755 goto Fail;
756
757 contours_count = loader->n_contours;
758
759 count -= 10;
760
761 loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
762 loader->pp1.y = 0;
763 loader->pp2.x = loader->pp1.x + loader->advance;
764 loader->pp2.y = 0;
765
766 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
767 {
768 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
769 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
770 }
771
772 /***********************************************************************/
773 /***********************************************************************/
774 /***********************************************************************/
775
776 /* if it is a simple glyph, load it */
777
778 if ( contours_count >= 0 )
779 {
780 /* check that we can add the contours to the glyph */
781 error = FT_GlyphLoader_Check_Points( gloader, 0, contours_count );
782 if ( error )
783 goto Fail;
784
785 error = face->read_simple_glyph( loader );
786 if ( error )
787 goto Fail;
788
789#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
790
791 {
792 TT_Size size = (TT_Size)loader->size;
793
794
795 error = TT_Process_Simple_Glyph( loader,
796 (FT_Bool)( size && size->debug ) );
797 }
798
799#else
800
801 error = TT_Process_Simple_Glyph( loader, 0 );
802
803#endif
804
805 if ( error )
806 goto Fail;
807
808 FT_GlyphLoader_Add( gloader );
809
810 /* Note: We could have put the simple loader source there */
811 /* but the code is fat enough already :-) */
812 }
813
814 /***********************************************************************/
815 /***********************************************************************/
816 /***********************************************************************/
817
818 /* otherwise, load a composite! */
819 else
820 {
821 TT_GlyphSlot glyph = (TT_GlyphSlot)loader->glyph;
822 FT_UInt start_point, start_contour;
823 FT_ULong ins_pos; /* position of composite instructions, if any */
824
825
826 /* for each subglyph, read composite header */
827 start_point = gloader->base.outline.n_points;
828 start_contour = gloader->base.outline.n_contours;
829
830 error = face->read_composite_glyph( loader );
831 if ( error )
832 goto Fail;
833
834 ins_pos = loader->ins_pos;
835 face->forget_glyph_frame( loader );
836 opened_frame = 0;
837
838 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
839 /* `as is' in the glyph slot (the client application will be */
840 /* responsible for interpreting this data)... */
841 /* */
842 if ( loader->load_flags & FT_LOAD_NO_RECURSE )
843 {
844 /* set up remaining glyph fields */
845 FT_GlyphLoader_Add( gloader );
846
847 glyph->num_subglyphs = gloader->base.num_subglyphs;
848 glyph->format = ft_glyph_format_composite;
849 glyph->subglyphs = gloader->base.subglyphs;
850
851 goto Exit;
852 }
853
854 /*********************************************************************/
855 /*********************************************************************/
856 /*********************************************************************/
857
858 /* Now, read each subglyph independently. */
859 {
860 FT_Int n, num_base_points, num_new_points;
861 FT_SubGlyph* subglyph = 0;
862
863 FT_UInt num_subglyphs = gloader->current.num_subglyphs;
864 FT_UInt num_base_subgs = gloader->base.num_subglyphs;
865
866
867 FT_GlyphLoader_Add( gloader );
868
869 for ( n = 0; n < (FT_Int)num_subglyphs; n++ )
870 {
871 FT_Vector pp1, pp2;
872 FT_Pos x, y;
873
874
875 /* Each time we call load_truetype_glyph in this loop, the */
876 /* value of `gloader.base.subglyphs' can change due to table */
877 /* reallocations. We thus need to recompute the subglyph */
878 /* pointer on each iteration. */
879 subglyph = gloader->base.subglyphs + num_base_subgs + n;
880
881 pp1 = loader->pp1;
882 pp2 = loader->pp2;
883
884 num_base_points = gloader->base.outline.n_points;
885
886 error = load_truetype_glyph( loader, subglyph->index );
887 if ( error )
888 goto Fail;
889
890 subglyph = gloader->base.subglyphs + num_base_subgs + n;
891
892 if ( subglyph->flags & USE_MY_METRICS )
893 {
894 pp1 = loader->pp1;
895 pp2 = loader->pp2;
896 }
897 else
898 {
899 loader->pp1 = pp1;
900 loader->pp2 = pp2;
901 }
902
903 num_points = gloader->base.outline.n_points;
904
905 num_new_points = num_points - num_base_points;
906
907 /* now perform the transform required for this subglyph */
908
909 if ( subglyph->flags & ( WE_HAVE_A_SCALE |
910 WE_HAVE_AN_XY_SCALE |
911 WE_HAVE_A_2X2 ) )
912 {
913 FT_Vector* cur = gloader->base.outline.points +
914 num_base_points;
915 FT_Vector* org = gloader->base.extra_points +
916 num_base_points;
917 FT_Vector* limit = cur + num_new_points;
918
919
920 for ( ; cur < limit; cur++, org++ )
921 {
922 FT_Vector_Transform( cur, &subglyph->transform );
923 FT_Vector_Transform( org, &subglyph->transform );
924 }
925 }
926
927 /* apply offset */
928
929 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
930 {
931 FT_UInt k = subglyph->arg1;
932 FT_UInt l = subglyph->arg2;
933 FT_Vector* p1;
934 FT_Vector* p2;
935
936
937 if ( start_point + k >= (FT_UInt)num_base_points ||
938 l >= (FT_UInt)num_new_points )
939 {
940 error = TT_Err_Invalid_Composite;
941 goto Fail;
942 }
943
944 l += num_base_points;
945
946 p1 = gloader->base.outline.points + start_point + k;
947 p2 = gloader->base.outline.points + start_point + l;
948
949 x = p1->x - p2->x;
950 y = p1->y - p2->y;
951 }
952 else
953 {
954 x = subglyph->arg1;
955 y = subglyph->arg2;
956
957 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
958 {
959 x = FT_MulFix( x, x_scale );
960 y = FT_MulFix( y, y_scale );
961
962 if ( subglyph->flags & ROUND_XY_TO_GRID )
963 {
964 x = ( x + 32 ) & -64;
965 y = ( y + 32 ) & -64;
966 }
967 }
968 }
969
970 translate_array( num_new_points, loader->zone.cur, x, y );
971 cur_to_org( num_new_points, &loader->zone );
972 }
973
974 /*******************************************************************/
975 /*******************************************************************/
976 /*******************************************************************/
977
978 /* we have finished loading all sub-glyphs; now, look for */
979 /* instructions for this composite! */
980
981#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
982
983 if ( num_subglyphs > 0 &&
984 loader->exec &&
985 ins_pos > 0 &&
986 subglyph->flags & WE_HAVE_INSTR )
987 {
988 FT_UShort n_ins;
989 TT_ExecContext exec = loader->exec;
990 TT_GlyphZone* pts;
991 FT_Vector* pp1;
992
993
994 /* read size of instructions */
995 if ( FILE_Seek( ins_pos ) ||
996 READ_UShort( n_ins ) )
997 goto Fail;
998 FT_TRACE5(( " Instructions size = %d\n", n_ins ));
999
1000 /* in some fonts? */
1001 if ( n_ins == 0xFFFF )
1002 n_ins = 0;
1003
1004 /* check it */
1005 if ( n_ins > face->max_profile.maxSizeOfInstructions )
1006 {
1007 FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n",
1008 n_ins, subglyph->index ));
1009 return TT_Err_Too_Many_Ins;
1010 }
1011
1012 /* read the instructions */
1013 if ( FILE_Read( exec->glyphIns, n_ins ) )
1014 goto Fail;
1015
1016 glyph->control_data = exec->glyphIns;
1017 glyph->control_len = n_ins;
1018
1019 error = TT_Set_CodeRange( exec,
1020 tt_coderange_glyph,
1021 exec->glyphIns,
1022 n_ins );
1023 if ( error )
1024 goto Fail;
1025
1026 /* prepare the execution context */
1027 tt_prepare_zone( &exec->pts, &gloader->base,
1028 start_point, start_contour );
1029 pts = &exec->pts;
1030
1031 pts->n_points = num_points + 2;
1032 pts->n_contours = gloader->base.outline.n_contours;
1033
1034 /* add phantom points */
1035 pp1 = pts->cur + num_points;
1036 pp1[0] = loader->pp1;
1037 pp1[1] = loader->pp2;
1038
1039 pts->tags[num_points ] = 0;
1040 pts->tags[num_points + 1] = 0;
1041
1042 /* if hinting, round the phantom points */
1043 if ( IS_HINTED( loader->load_flags ) )
1044 {
1045 pp1[0].x = ( ( loader->pp1.x + 32 ) & -64 );
1046 pp1[1].x = ( ( loader->pp2.x + 32 ) & -64 );
1047 }
1048
1049 {
1050 FT_UInt k;
1051
1052
1053 for ( k = 0; k < num_points; k++ )
1054 pts->tags[k] &= FT_Curve_Tag_On;
1055 }
1056
1057 cur_to_org( num_points + 2, pts );
1058
1059 /* now consider hinting */
1060 if ( IS_HINTED( loader->load_flags ) && n_ins > 0 )
1061 {
1062 exec->is_composite = TRUE;
1063 exec->pedantic_hinting =
1064 (FT_Bool)( loader->load_flags & FT_LOAD_PEDANTIC );
1065
1066 error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug );
1067 if ( error && exec->pedantic_hinting )
1068 goto Fail;
1069 }
1070
1071 /* save glyph origin and advance points */
1072 loader->pp1 = pp1[0];
1073 loader->pp2 = pp1[1];
1074 }
1075
1076#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1077
1078 }
1079 /* end of composite loading */
1080 }
1081
1082 /***********************************************************************/
1083 /***********************************************************************/
1084 /***********************************************************************/
1085
1086 Fail:
1087 if ( opened_frame )
1088 face->forget_glyph_frame( loader );
1089
1090 Exit:
1091 return error;
1092 }
1093
1094
1095 static
1096 void compute_glyph_metrics( TT_Loader* loader,
1097 FT_UInt glyph_index )
1098 {
1099 FT_BBox bbox;
1100 TT_Face face = (TT_Face)loader->face;
1101 FT_Fixed x_scale, y_scale;
1102 TT_GlyphSlot glyph = loader->glyph;
1103 TT_Size size = (TT_Size)loader->size;
1104
1105
1106 x_scale = 0x10000L;
1107 y_scale = 0x10000L;
1108 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1109 {
1110 x_scale = size->root.metrics.x_scale;
1111 y_scale = size->root.metrics.y_scale;
1112 }
1113
1114 if ( glyph->format != ft_glyph_format_composite )
1115 {
1116 glyph->outline.flags &= ~ft_outline_single_pass;
1117
1118 /* copy outline to our glyph slot */
1119 FT_GlyphLoader_Copy_Points( glyph->loader, loader->gloader );
1120 glyph->outline = glyph->loader->base.outline;
1121
1122 /* translate array so that (0,0) is the glyph's origin */
1123 FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 );
1124
1125 FT_Outline_Get_CBox( &glyph->outline, &bbox );
1126
1127 if ( IS_HINTED( loader->load_flags ) )
1128 {
1129 /* grid-fit the bounding box */
1130 bbox.xMin &= -64;
1131 bbox.yMin &= -64;
1132 bbox.xMax = ( bbox.xMax + 63 ) & -64;
1133 bbox.yMax = ( bbox.yMax + 63 ) & -64;
1134 }
1135 }
1136 else
1137 bbox = loader->bbox;
1138
1139 /* get the device-independent horizontal advance. It is scaled later */
1140 /* by the base layer. */
1141 {
1142 FT_Pos advance = loader->advance;
1143
1144
1145 /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
1146 /* correctly support DynaLab fonts, which have an incorrect */
1147 /* `advance_Width_Max' field! It is used, to my knowledge, */
1148 /* exclusively in the X-TrueType font server. */
1149 /* */
1150 if ( face->postscript.isFixedPitch &&
1151 ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
1152 advance = face->horizontal.advance_Width_Max;
1153
1154 /* we need to return the advance in font units in linearHoriAdvance, */
1155 /* it will be scaled later by the base layer. */
1156 glyph->linearHoriAdvance = advance;
1157 }
1158
1159 glyph->metrics.horiBearingX = bbox.xMin;
1160 glyph->metrics.horiBearingY = bbox.yMax;
1161 glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
1162
1163 /* Now take care of vertical metrics. In the case where there is */
1164 /* no vertical information within the font (relatively common), make */
1165 /* up some metrics by `hand'... */
1166
1167 {
1168 FT_Short top_bearing; /* vertical top side bearing (EM units) */
1169 FT_UShort advance_height; /* vertical advance height (EM units) */
1170
1171 FT_Pos left; /* scaled vertical left side bearing */
1172 FT_Pos Top; /* scaled original vertical top side bearing */
1173 FT_Pos top; /* scaled vertical top side bearing */
1174 FT_Pos advance; /* scaled vertical advance height */
1175
1176
1177 /* Get the unscaled `tsb' and `ah' */
1178 if ( face->vertical_info &&
1179 face->vertical.number_Of_VMetrics > 0 )
1180 {
1181 /* Don't assume that both the vertical header and vertical */
1182 /* metrics are present in the same font :-) */
1183
1184 TT_Get_Metrics( (TT_HoriHeader*)&face->vertical,
1185 glyph_index,
1186 &top_bearing,
1187 &advance_height );
1188 }
1189 else
1190 {
1191 /* Make up the distances from the horizontal header. */
1192
1193 /* NOTE: The OS/2 values are the only `portable' ones, */
1194 /* which is why we use them, if there is an OS/2 */
1195 /* table in the font. Otherwise, we use the */
1196 /* values defined in the horizontal header. */
1197 /* */
1198 /* NOTE2: The sTypoDescender is negative, which is why */
1199 /* we compute the baseline-to-baseline distance */
1200 /* here with: */
1201 /* ascender - descender + linegap */
1202 /* */
1203 if ( face->os2.version != 0xFFFF )
1204 {
1205 top_bearing = face->os2.sTypoLineGap / 2;
1206 advance_height = (FT_UShort)( face->os2.sTypoAscender -
1207 face->os2.sTypoDescender +
1208 face->os2.sTypoLineGap );
1209 }
1210 else
1211 {
1212 top_bearing = face->horizontal.Line_Gap / 2;
1213 advance_height = (FT_UShort)( face->horizontal.Ascender +
1214 face->horizontal.Descender +
1215 face->horizontal.Line_Gap );
1216 }
1217 }
1218
1219 /* We must adjust the top_bearing value from the bounding box given */
1220 /* in the glyph header to te bounding box calculated with */
1221 /* FT_Get_Outline_CBox(). */
1222
1223 /* scale the metrics */
1224 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1225 {
1226 Top = FT_MulFix( top_bearing, y_scale );
1227 top = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale )
1228 - bbox.yMax;
1229 advance = FT_MulFix( advance_height, y_scale );
1230 }
1231 else
1232 {
1233 Top = top_bearing;
1234 top = top_bearing + loader->bbox.yMax - bbox.yMax;
1235 advance = advance_height;
1236 }
1237
1238 /* set the advance height in design units. It is scaled later by */
1239 /* the base layer. */
1240 glyph->linearVertAdvance = advance_height;
1241
1242 /* XXX: for now, we have no better algorithm for the lsb, but it */
1243 /* should work fine. */
1244 /* */
1245 left = ( bbox.xMin - bbox.xMax ) / 2;
1246
1247 /* grid-fit them if necessary */
1248 if ( IS_HINTED( loader->load_flags ) )
1249 {
1250 left &= -64;
1251 top = ( top + 63 ) & -64;
1252 advance = ( advance + 32 ) & -64;
1253 }
1254
1255 glyph->metrics.vertBearingX = left;
1256 glyph->metrics.vertBearingY = top;
1257 glyph->metrics.vertAdvance = advance;
1258 }
1259
1260 /* adjust advance width to the value contained in the hdmx table */
1261 if ( !face->postscript.isFixedPitch && size &&
1262 IS_HINTED( loader->load_flags ) )
1263 {
1264 FT_Byte* widths = Get_Advance_Widths( face,
1265 size->root.metrics.x_ppem );
1266
1267
1268 if ( widths )
1269 glyph->metrics.horiAdvance = widths[glyph_index] << 6;
1270 }
1271
1272 /* set glyph dimensions */
1273 glyph->metrics.width = bbox.xMax - bbox.xMin;
1274 glyph->metrics.height = bbox.yMax - bbox.yMin;
1275 }
1276
1277
1278 /*************************************************************************/
1279 /* */
1280 /* <Function> */
1281 /* TT_Load_Glyph */
1282 /* */
1283 /* <Description> */
1284 /* A function used to load a single glyph within a given glyph slot, */
1285 /* for a given size. */
1286 /* */
1287 /* <Input> */
1288 /* glyph :: A handle to a target slot object where the glyph */
1289 /* will be loaded. */
1290 /* */
1291 /* size :: A handle to the source face size at which the glyph */
1292 /* must be scaled/loaded. */
1293 /* */
1294 /* glyph_index :: The index of the glyph in the font file. */
1295 /* */
1296 /* load_flags :: A flag indicating what to load for this glyph. The */
1297 /* FT_LOAD_XXX constants can be used to control the */
1298 /* glyph loading process (e.g., whether the outline */
1299 /* should be scaled, whether to load bitmaps or not, */
1300 /* whether to hint the outline, etc). */
1301 /* */
1302 /* <Return> */
1303 /* FreeType error code. 0 means success. */
1304 /* */
1305 LOCAL_FUNC
1306 FT_Error TT_Load_Glyph( TT_Size size,
1307 TT_GlyphSlot glyph,
1308 FT_UShort glyph_index,
1309 FT_UInt load_flags )
1310 {
1311 SFNT_Interface* sfnt;
1312 TT_Face face;
1313 FT_Stream stream;
1314 FT_Memory memory;
1315 FT_Error error;
1316 TT_Loader loader;
1317
1318
1319 face = (TT_Face)glyph->face;
1320 sfnt = (SFNT_Interface*)face->sfnt;
1321 stream = face->root.stream;
1322 memory = face->root.memory;
1323 error = 0;
1324
1325 if ( !size || ( load_flags & FT_LOAD_NO_SCALE ) ||
1326 ( load_flags & FT_LOAD_NO_RECURSE ) )
1327 {
1328 size = NULL;
1329 load_flags |= FT_LOAD_NO_SCALE |
1330 FT_LOAD_NO_HINTING |
1331 FT_LOAD_NO_BITMAP;
1332 }
1333
1334 glyph->num_subglyphs = 0;
1335
1336#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1337
1338 /* try to load embedded bitmap if any */
1339 if ( size &&
1340 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
1341 sfnt->load_sbits )
1342 {
1343 TT_SBit_Metrics metrics;
1344
1345
1346 error = sfnt->load_sbit_image( face,
1347 size->root.metrics.x_ppem,
1348 size->root.metrics.y_ppem,
1349 glyph_index,
1350 load_flags,
1351 stream,
1352 &glyph->bitmap,
1353 &metrics );
1354 if ( !error )
1355 {
1356 glyph->outline.n_points = 0;
1357 glyph->outline.n_contours = 0;
1358
1359 glyph->metrics.width = (FT_Pos)metrics.width << 6;
1360 glyph->metrics.height = (FT_Pos)metrics.height << 6;
1361
1362 glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
1363 glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
1364 glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
1365
1366 glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
1367 glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
1368 glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
1369
1370 glyph->format = ft_glyph_format_bitmap;
1371 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
1372 {
1373 glyph->bitmap_left = metrics.vertBearingX;
1374 glyph->bitmap_top = metrics.vertBearingY;
1375 }
1376 else
1377 {
1378 glyph->bitmap_left = metrics.horiBearingX;
1379 glyph->bitmap_top = metrics.horiBearingY;
1380 }
1381 return error;
1382 }
1383 }
1384
1385#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1386
1387 /* seek to the beginning of the glyph table. For Type 42 fonts */
1388 /* the table might be accessed from a Postscript stream or something */
1389 /* else... */
1390
1391 error = face->goto_table( face, TTAG_glyf, stream, 0 );
1392 if ( error )
1393 {
1394 FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
1395 goto Exit;
1396 }
1397
1398 MEM_Set( &loader, 0, sizeof ( loader ) );
1399
1400 /* update the glyph zone bounds */
1401 {
1402 FT_GlyphLoader* gloader = FT_FACE_DRIVER(face)->glyph_loader;
1403
1404
1405 loader.gloader = gloader;
1406
1407 FT_GlyphLoader_Rewind( gloader );
1408
1409 tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 );
1410 tt_prepare_zone( &loader.base, &gloader->base, 0, 0 );
1411 }
1412
1413#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
1414
1415 if ( size )
1416 {
1417 /* query new execution context */
1418 loader.exec = size->debug ? size->context : TT_New_Context( face );
1419 if ( !loader.exec )
1420 return TT_Err_Could_Not_Find_Context;
1421
1422 TT_Load_Context( loader.exec, face, size );
1423 loader.instructions = loader.exec->glyphIns;
1424
1425 /* load default graphics state - if needed */
1426 if ( size->GS.instruct_control & 2 )
1427 loader.exec->GS = tt_default_graphics_state;
1428 }
1429
1430#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1431
1432 /* clear all outline flags, except the `owner' one */
1433 glyph->outline.flags = 0;
1434
1435 if ( size && size->root.metrics.y_ppem < 24 )
1436 glyph->outline.flags |= ft_outline_high_precision;
1437
1438 /* let's initialize the rest of our loader now */
1439
1440 loader.load_flags = load_flags;
1441
1442 loader.face = (FT_Face)face;
1443 loader.size = (FT_Size)size;
1444 loader.glyph = (FT_GlyphSlot)glyph;
1445 loader.stream = stream;
1446
1447 loader.glyf_offset = FILE_Pos();
1448
1449#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
1450
1451 /* if the cvt program has disabled hinting, the argument */
1452 /* is ignored. */
1453 if ( size && ( size->GS.instruct_control & 1 ) )
1454 loader.load_flags |= FT_LOAD_NO_HINTING;
1455
1456#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1457
1458 /* Main loading loop */
1459 glyph->format = ft_glyph_format_outline;
1460 glyph->num_subglyphs = 0;
1461 error = load_truetype_glyph( &loader, glyph_index );
1462 if ( !error )
1463 compute_glyph_metrics( &loader, glyph_index );
1464
1465#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
1466
1467 if ( !size || !size->debug )
1468 TT_Done_Context( loader.exec );
1469
1470#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1471
1472 Exit:
1473 return error;
1474 }
1475
1476
1477/* END */