1/****************************************************************************
2 *
3 * psft.c
4 *
5 * FreeType Glue Component to Adobe's Interpreter (body).
6 *
7 * Copyright 2013-2014 Adobe Systems Incorporated.
8 *
9 * This software, and all works of authorship, whether in source or
10 * object code form as indicated by the copyright notice(s) included
11 * herein (collectively, the "Work") is made available, and may only be
12 * used, modified, and distributed under the FreeType Project License,
13 * LICENSE.TXT. Additionally, subject to the terms and conditions of the
14 * FreeType Project License, each contributor to the Work hereby grants
15 * to any individual or legal entity exercising permissions granted by
16 * the FreeType Project License and this section (hereafter, "You" or
17 * "Your") a perpetual, worldwide, non-exclusive, no-charge,
18 * royalty-free, irrevocable (except as stated in this section) patent
19 * license to make, have made, use, offer to sell, sell, import, and
20 * otherwise transfer the Work, where such license applies only to those
21 * patent claims licensable by such contributor that are necessarily
22 * infringed by their contribution(s) alone or by combination of their
23 * contribution(s) with the Work to which such contribution(s) was
24 * submitted. If You institute patent litigation against any entity
25 * (including a cross-claim or counterclaim in a lawsuit) alleging that
26 * the Work or a contribution incorporated within the Work constitutes
27 * direct or contributory patent infringement, then any patent licenses
28 * granted to You under this License for that Work shall terminate as of
29 * the date such litigation is filed.
30 *
31 * By using, modifying, or distributing the Work you indicate that you
32 * have read and understood the terms and conditions of the
33 * FreeType Project License as well as those provided in this section,
34 * and you accept them fully.
35 *
36 */
37
38
39#include "psft.h"
40#include <freetype/internal/ftdebug.h>
41
42#include "psfont.h"
43#include "pserror.h"
44#include "psobjs.h"
45#include "cffdecode.h"
46
47#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
48#include <freetype/ftmm.h>
49#include <freetype/internal/services/svmm.h>
50#endif
51
52#include <freetype/internal/services/svcfftl.h>
53
54
55#define CF2_MAX_SIZE cf2_intToFixed( 2000 ) /* max ppem */
56
57
58 /*
59 * This check should avoid most internal overflow cases. Clients should
60 * generally respond to `Glyph_Too_Big' by getting a glyph outline
61 * at EM size, scaling it and filling it as a graphics operation.
62 *
63 */
64 static FT_Error
65 cf2_checkTransform( const CF2_Matrix* transform,
66 CF2_Int unitsPerEm )
67 {
68 CF2_Fixed maxScale;
69
70
71 if ( transform->a <= 0 || transform->d <= 0 )
72 return FT_THROW( Invalid_Size_Handle );
73
74 FT_ASSERT( unitsPerEm > 0 );
75 FT_ASSERT( transform->b == 0 && transform->c == 0 );
76 FT_ASSERT( transform->tx == 0 && transform->ty == 0 );
77
78 if ( unitsPerEm > 0x7FFF )
79 return FT_THROW( Glyph_Too_Big );
80
81 maxScale = FT_DivFix( CF2_MAX_SIZE, cf2_intToFixed( unitsPerEm ) );
82
83 if ( transform->a > maxScale || transform->d > maxScale )
84 return FT_THROW( Glyph_Too_Big );
85
86 return FT_Err_Ok;
87 }
88
89
90 static void
91 cf2_setGlyphWidth( CF2_Outline outline,
92 CF2_Fixed width )
93 {
94 PS_Decoder* decoder = outline->decoder;
95
96
97 FT_ASSERT( decoder );
98
99 if ( !decoder->builder.is_t1 )
100 *decoder->glyph_width = cf2_fixedToInt( width );
101 }
102
103
104 /* Clean up font instance. */
105 static void
106 cf2_free_instance( void* ptr )
107 {
108 CF2_Font font = (CF2_Font)ptr;
109
110
111 if ( font )
112 {
113 FT_Memory memory = font->memory;
114
115
116 FT_FREE( font->blend.lastNDV );
117 FT_FREE( font->blend.BV );
118 }
119 }
120
121
122 /*********************************************
123 *
124 * functions for handling client outline;
125 * FreeType uses coordinates in 26.6 format
126 *
127 */
128
129 static void
130 cf2_builder_moveTo( CF2_OutlineCallbacks callbacks,
131 const CF2_CallbackParams params )
132 {
133 /* downcast the object pointer */
134 CF2_Outline outline = (CF2_Outline)callbacks;
135 PS_Builder* builder;
136
137 (void)params; /* only used in debug mode */
138
139
140 FT_ASSERT( outline && outline->decoder );
141 FT_ASSERT( params->op == CF2_PathOpMoveTo );
142
143 builder = &outline->decoder->builder;
144
145 /* note: two successive moves simply close the contour twice */
146 ps_builder_close_contour( builder );
147 builder->path_begun = 0;
148 }
149
150
151 static void
152 cf2_builder_lineTo( CF2_OutlineCallbacks callbacks,
153 const CF2_CallbackParams params )
154 {
155 FT_Error error;
156
157 /* downcast the object pointer */
158 CF2_Outline outline = (CF2_Outline)callbacks;
159 PS_Builder* builder;
160
161
162 FT_ASSERT( outline && outline->decoder );
163 FT_ASSERT( params->op == CF2_PathOpLineTo );
164
165 builder = &outline->decoder->builder;
166
167 if ( !builder->path_begun )
168 {
169 /* record the move before the line; also check points and set */
170 /* `path_begun' */
171 error = ps_builder_start_point( builder,
172 params->pt0.x,
173 params->pt0.y );
174 if ( error )
175 {
176 if ( !*callbacks->error )
177 *callbacks->error = error;
178 return;
179 }
180 }
181
182 /* `ps_builder_add_point1' includes a check_points call for one point */
183 error = ps_builder_add_point1( builder,
184 params->pt1.x,
185 params->pt1.y );
186 if ( error )
187 {
188 if ( !*callbacks->error )
189 *callbacks->error = error;
190 return;
191 }
192 }
193
194
195 static void
196 cf2_builder_cubeTo( CF2_OutlineCallbacks callbacks,
197 const CF2_CallbackParams params )
198 {
199 FT_Error error;
200
201 /* downcast the object pointer */
202 CF2_Outline outline = (CF2_Outline)callbacks;
203 PS_Builder* builder;
204
205
206 FT_ASSERT( outline && outline->decoder );
207 FT_ASSERT( params->op == CF2_PathOpCubeTo );
208
209 builder = &outline->decoder->builder;
210
211 if ( !builder->path_begun )
212 {
213 /* record the move before the line; also check points and set */
214 /* `path_begun' */
215 error = ps_builder_start_point( builder,
216 params->pt0.x,
217 params->pt0.y );
218 if ( error )
219 {
220 if ( !*callbacks->error )
221 *callbacks->error = error;
222 return;
223 }
224 }
225
226 /* prepare room for 3 points: 2 off-curve, 1 on-curve */
227 error = ps_builder_check_points( builder, 3 );
228 if ( error )
229 {
230 if ( !*callbacks->error )
231 *callbacks->error = error;
232 return;
233 }
234
235 ps_builder_add_point( builder,
236 params->pt1.x,
237 params->pt1.y, 0 );
238 ps_builder_add_point( builder,
239 params->pt2.x,
240 params->pt2.y, 0 );
241 ps_builder_add_point( builder,
242 params->pt3.x,
243 params->pt3.y, 1 );
244 }
245
246
247 static void
248 cf2_outline_init( CF2_Outline outline,
249 FT_Memory memory,
250 FT_Error* error )
251 {
252 FT_ZERO( outline );
253
254 outline->root.memory = memory;
255 outline->root.error = error;
256
257 outline->root.moveTo = cf2_builder_moveTo;
258 outline->root.lineTo = cf2_builder_lineTo;
259 outline->root.cubeTo = cf2_builder_cubeTo;
260 }
261
262
263 /* get scaling and hint flag from GlyphSlot */
264 static void
265 cf2_getScaleAndHintFlag( PS_Decoder* decoder,
266 CF2_Fixed* x_scale,
267 CF2_Fixed* y_scale,
268 FT_Bool* hinted,
269 FT_Bool* scaled )
270 {
271 FT_ASSERT( decoder && decoder->builder.glyph );
272
273 /* note: FreeType scale includes a factor of 64 */
274 *hinted = decoder->builder.glyph->hint;
275 *scaled = decoder->builder.glyph->scaled;
276
277 if ( *hinted )
278 {
279 *x_scale = ADD_INT32( decoder->builder.glyph->x_scale, 32 ) / 64;
280 *y_scale = ADD_INT32( decoder->builder.glyph->y_scale, 32 ) / 64;
281 }
282 else
283 {
284 /* for unhinted outlines, `cff_slot_load' does the scaling, */
285 /* thus render at `unity' scale */
286
287 *x_scale = 0x0400; /* 1/64 as 16.16 */
288 *y_scale = 0x0400;
289 }
290 }
291
292
293 /* get units per em from `FT_Face' */
294 /* TODO: should handle font matrix concatenation? */
295 static FT_UShort
296 cf2_getUnitsPerEm( PS_Decoder* decoder )
297 {
298 FT_ASSERT( decoder && decoder->builder.face );
299
300 return decoder->builder.face->units_per_EM;
301 }
302
303
304 /* Main entry point: Render one glyph. */
305 FT_LOCAL_DEF( FT_Error )
306 cf2_decoder_parse_charstrings( PS_Decoder* decoder,
307 FT_Byte* charstring_base,
308 FT_ULong charstring_len )
309 {
310 FT_Memory memory;
311 FT_Error error = FT_Err_Ok;
312 CF2_Font font;
313
314 FT_Bool is_t1 = decoder->builder.is_t1;
315
316
317 FT_ASSERT( decoder &&
318 ( is_t1 || decoder->cff ) );
319
320 if ( is_t1 && !decoder->current_subfont )
321 {
322 FT_ERROR(( "cf2_decoder_parse_charstrings (Type 1): "
323 "SubFont missing. Use `t1_make_subfont' first\n" ));
324 return FT_THROW( Invalid_Table );
325 }
326
327 memory = decoder->builder.memory;
328
329 /* CF2 data is saved here across glyphs */
330 font = (CF2_Font)decoder->cf2_instance->data;
331
332 /* on first glyph, allocate instance structure */
333 if ( !decoder->cf2_instance->data )
334 {
335 decoder->cf2_instance->finalizer =
336 (FT_Generic_Finalizer)cf2_free_instance;
337
338 if ( FT_ALLOC( decoder->cf2_instance->data,
339 sizeof ( CF2_FontRec ) ) )
340 return FT_THROW( Out_Of_Memory );
341
342 font = (CF2_Font)decoder->cf2_instance->data;
343
344 font->memory = memory;
345
346 if ( !is_t1 )
347 font->cffload = (FT_Service_CFFLoad)decoder->cff->cffload;
348
349 /* initialize a client outline, to be shared by each glyph rendered */
350 cf2_outline_init( &font->outline, font->memory, &font->error );
351 }
352
353 /* save decoder; it is a stack variable and will be different on each */
354 /* call */
355 font->decoder = decoder;
356 font->outline.decoder = decoder;
357
358 {
359 /* build parameters for Adobe engine */
360
361 PS_Builder* builder = &decoder->builder;
362 PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face );
363
364 FT_Bool no_stem_darkening_driver =
365 driver->no_stem_darkening;
366 FT_Char no_stem_darkening_font =
367 builder->face->internal->no_stem_darkening;
368
369 /* local error */
370 FT_Error error2 = FT_Err_Ok;
371 CF2_BufferRec buf;
372 CF2_Matrix transform;
373 CF2_F16Dot16 glyphWidth;
374
375 FT_Bool hinted;
376 FT_Bool scaled;
377
378
379 /* FreeType has already looked up the GID; convert to */
380 /* `RegionBuffer', assuming that the input has been validated */
381 FT_ASSERT( charstring_base + charstring_len >= charstring_base );
382
383 FT_ZERO( &buf );
384 buf.start =
385 buf.ptr = charstring_base;
386 buf.end = FT_OFFSET( charstring_base, charstring_len );
387
388 FT_ZERO( &transform );
389
390 cf2_getScaleAndHintFlag( decoder,
391 &transform.a,
392 &transform.d,
393 &hinted,
394 &scaled );
395
396 if ( is_t1 )
397 font->isCFF2 = FALSE;
398 else
399 {
400 /* copy isCFF2 boolean from TT_Face to CF2_Font */
401 font->isCFF2 = ((TT_Face)builder->face)->is_cff2;
402 }
403 font->isT1 = is_t1;
404
405 font->renderingFlags = 0;
406 if ( hinted )
407 font->renderingFlags |= CF2_FlagsHinted;
408 if ( scaled && ( !no_stem_darkening_font ||
409 ( no_stem_darkening_font < 0 &&
410 !no_stem_darkening_driver ) ) )
411 font->renderingFlags |= CF2_FlagsDarkened;
412
413 font->darkenParams[0] = driver->darken_params[0];
414 font->darkenParams[1] = driver->darken_params[1];
415 font->darkenParams[2] = driver->darken_params[2];
416 font->darkenParams[3] = driver->darken_params[3];
417 font->darkenParams[4] = driver->darken_params[4];
418 font->darkenParams[5] = driver->darken_params[5];
419 font->darkenParams[6] = driver->darken_params[6];
420 font->darkenParams[7] = driver->darken_params[7];
421
422 /* now get an outline for this glyph; */
423 /* also get units per em to validate scale */
424 font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder );
425
426 if ( scaled )
427 {
428 error2 = cf2_checkTransform( &transform, font->unitsPerEm );
429 if ( error2 )
430 return error2;
431 }
432
433 error2 = cf2_getGlyphOutline( font, &buf, &transform, &glyphWidth );
434 if ( error2 )
435 return FT_ERR( Invalid_File_Format );
436
437 cf2_setGlyphWidth( &font->outline, glyphWidth );
438
439 return FT_Err_Ok;
440 }
441 }
442
443
444 /* get pointer to current FreeType subfont (based on current glyphID) */
445 FT_LOCAL_DEF( CFF_SubFont )
446 cf2_getSubfont( PS_Decoder* decoder )
447 {
448 FT_ASSERT( decoder && decoder->current_subfont );
449
450 return decoder->current_subfont;
451 }
452
453
454 /* get pointer to VStore structure */
455 FT_LOCAL_DEF( CFF_VStore )
456 cf2_getVStore( PS_Decoder* decoder )
457 {
458 FT_ASSERT( decoder && decoder->cff );
459
460 return &decoder->cff->vstore;
461 }
462
463
464 /* get maxstack value from CFF2 Top DICT */
465 FT_LOCAL_DEF( FT_UInt )
466 cf2_getMaxstack( PS_Decoder* decoder )
467 {
468 FT_ASSERT( decoder && decoder->cff );
469
470 return decoder->cff->top_font.font_dict.maxstack;
471 }
472
473
474#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
475 /* Get normalized design vector for current render request; */
476 /* return pointer and length. */
477 /* */
478 /* Note: Uses FT_Fixed not CF2_Fixed for the vector. */
479 FT_LOCAL_DEF( FT_Error )
480 cf2_getNormalizedVector( PS_Decoder* decoder,
481 CF2_UInt *len,
482 FT_Fixed* *vec )
483 {
484 TT_Face face;
485 FT_Service_MultiMasters mm;
486
487
488 FT_ASSERT( decoder && decoder->builder.face );
489 FT_ASSERT( vec && len );
490 FT_ASSERT( !decoder->builder.is_t1 );
491
492 face = (TT_Face)decoder->builder.face;
493 mm = (FT_Service_MultiMasters)face->mm;
494
495 return mm->get_var_blend( FT_FACE( face ), len, NULL, vec, NULL );
496 }
497#endif
498
499
500 /* get `y_ppem' from `CFF_Size' */
501 FT_LOCAL_DEF( CF2_Fixed )
502 cf2_getPpemY( PS_Decoder* decoder )
503 {
504 FT_ASSERT( decoder &&
505 decoder->builder.face &&
506 decoder->builder.face->size );
507
508 /*
509 * Note that `y_ppem' can be zero if there wasn't a call to
510 * `FT_Set_Char_Size' or something similar. However, this isn't a
511 * problem since we come to this place in the code only if
512 * FT_LOAD_NO_SCALE is set (the other case gets caught by
513 * `cf2_checkTransform'). The ppem value is needed to compute the stem
514 * darkening, which is disabled for getting the unscaled outline.
515 *
516 */
517 return cf2_intToFixed(
518 decoder->builder.face->size->metrics.y_ppem );
519 }
520
521
522 /* get standard stem widths for the current subfont; */
523 /* FreeType stores these as integer font units */
524 /* (note: variable names seem swapped) */
525 FT_LOCAL_DEF( CF2_Fixed )
526 cf2_getStdVW( PS_Decoder* decoder )
527 {
528 FT_ASSERT( decoder && decoder->current_subfont );
529
530 return cf2_intToFixed(
531 decoder->current_subfont->private_dict.standard_height );
532 }
533
534
535 FT_LOCAL_DEF( CF2_Fixed )
536 cf2_getStdHW( PS_Decoder* decoder )
537 {
538 FT_ASSERT( decoder && decoder->current_subfont );
539
540 return cf2_intToFixed(
541 decoder->current_subfont->private_dict.standard_width );
542 }
543
544
545 /* note: FreeType stores 1000 times the actual value for `BlueScale' */
546 FT_LOCAL_DEF( void )
547 cf2_getBlueMetrics( PS_Decoder* decoder,
548 CF2_Fixed* blueScale,
549 CF2_Fixed* blueShift,
550 CF2_Fixed* blueFuzz )
551 {
552 FT_ASSERT( decoder && decoder->current_subfont );
553
554 *blueScale = FT_DivFix(
555 decoder->current_subfont->private_dict.blue_scale,
556 cf2_intToFixed( 1000 ) );
557 *blueShift = cf2_intToFixed(
558 decoder->current_subfont->private_dict.blue_shift );
559 *blueFuzz = cf2_intToFixed(
560 decoder->current_subfont->private_dict.blue_fuzz );
561 }
562
563
564 /* get blue values counts and arrays; the FreeType parser has validated */
565 /* the counts and verified that each is an even number */
566 FT_LOCAL_DEF( void )
567 cf2_getBlueValues( PS_Decoder* decoder,
568 size_t* count,
569 FT_Pos* *data )
570 {
571 FT_ASSERT( decoder && decoder->current_subfont );
572
573 *count = decoder->current_subfont->private_dict.num_blue_values;
574 *data = (FT_Pos*)
575 &decoder->current_subfont->private_dict.blue_values;
576 }
577
578
579 FT_LOCAL_DEF( void )
580 cf2_getOtherBlues( PS_Decoder* decoder,
581 size_t* count,
582 FT_Pos* *data )
583 {
584 FT_ASSERT( decoder && decoder->current_subfont );
585
586 *count = decoder->current_subfont->private_dict.num_other_blues;
587 *data = (FT_Pos*)
588 &decoder->current_subfont->private_dict.other_blues;
589 }
590
591
592 FT_LOCAL_DEF( void )
593 cf2_getFamilyBlues( PS_Decoder* decoder,
594 size_t* count,
595 FT_Pos* *data )
596 {
597 FT_ASSERT( decoder && decoder->current_subfont );
598
599 *count = decoder->current_subfont->private_dict.num_family_blues;
600 *data = (FT_Pos*)
601 &decoder->current_subfont->private_dict.family_blues;
602 }
603
604
605 FT_LOCAL_DEF( void )
606 cf2_getFamilyOtherBlues( PS_Decoder* decoder,
607 size_t* count,
608 FT_Pos* *data )
609 {
610 FT_ASSERT( decoder && decoder->current_subfont );
611
612 *count = decoder->current_subfont->private_dict.num_family_other_blues;
613 *data = (FT_Pos*)
614 &decoder->current_subfont->private_dict.family_other_blues;
615 }
616
617
618 FT_LOCAL_DEF( CF2_Int )
619 cf2_getLanguageGroup( PS_Decoder* decoder )
620 {
621 FT_ASSERT( decoder && decoder->current_subfont );
622
623 return decoder->current_subfont->private_dict.language_group;
624 }
625
626
627 /* convert unbiased subroutine index to `CF2_Buffer' and */
628 /* return 0 on success */
629 FT_LOCAL_DEF( CF2_Int )
630 cf2_initGlobalRegionBuffer( PS_Decoder* decoder,
631 CF2_Int subrNum,
632 CF2_Buffer buf )
633 {
634 CF2_UInt idx;
635
636
637 FT_ASSERT( decoder );
638
639 FT_ZERO( buf );
640
641 idx = (CF2_UInt)( subrNum + decoder->globals_bias );
642 if ( idx >= decoder->num_globals )
643 return TRUE; /* error */
644
645 FT_ASSERT( decoder->globals );
646
647 buf->start =
648 buf->ptr = decoder->globals[idx];
649 buf->end = decoder->globals[idx + 1];
650
651 return FALSE; /* success */
652 }
653
654
655 /* convert AdobeStandardEncoding code to CF2_Buffer; */
656 /* used for seac component */
657 FT_LOCAL_DEF( FT_Error )
658 cf2_getSeacComponent( PS_Decoder* decoder,
659 CF2_Int code,
660 CF2_Buffer buf )
661 {
662 CF2_Int gid;
663 FT_Byte* charstring;
664 FT_ULong len;
665 FT_Error error;
666
667
668 FT_ASSERT( decoder );
669 FT_ASSERT( !decoder->builder.is_t1 );
670
671 FT_ZERO( buf );
672
673#ifdef FT_CONFIG_OPTION_INCREMENTAL
674 /* Incremental fonts don't necessarily have valid charsets. */
675 /* They use the character code, not the glyph index, in this case. */
676 if ( decoder->builder.face->internal->incremental_interface )
677 gid = code;
678 else
679#endif /* FT_CONFIG_OPTION_INCREMENTAL */
680 {
681 gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code );
682 if ( gid < 0 )
683 return FT_THROW( Invalid_Glyph_Format );
684 }
685
686 error = decoder->get_glyph_callback( (TT_Face)decoder->builder.face,
687 (CF2_UInt)gid,
688 &charstring,
689 &len );
690 /* TODO: for now, just pass the FreeType error through */
691 if ( error )
692 return error;
693
694 /* assume input has been validated */
695 FT_ASSERT( charstring + len >= charstring );
696
697 buf->start = charstring;
698 buf->end = FT_OFFSET( charstring, len );
699 buf->ptr = buf->start;
700
701 return FT_Err_Ok;
702 }
703
704
705 FT_LOCAL_DEF( void )
706 cf2_freeSeacComponent( PS_Decoder* decoder,
707 CF2_Buffer buf )
708 {
709 FT_ASSERT( decoder );
710 FT_ASSERT( !decoder->builder.is_t1 );
711
712 decoder->free_glyph_callback( (TT_Face)decoder->builder.face,
713 (FT_Byte**)&buf->start,
714 (FT_ULong)( buf->end - buf->start ) );
715 }
716
717
718 FT_LOCAL_DEF( FT_Error )
719 cf2_getT1SeacComponent( PS_Decoder* decoder,
720 FT_UInt glyph_index,
721 CF2_Buffer buf )
722 {
723 FT_Data glyph_data;
724 FT_Error error = FT_Err_Ok;
725 T1_Face face = (T1_Face)decoder->builder.face;
726 T1_Font type1 = &face->type1;
727
728#ifdef FT_CONFIG_OPTION_INCREMENTAL
729 FT_Incremental_InterfaceRec *inc =
730 face->root.internal->incremental_interface;
731
732
733 /* For incremental fonts get the character data using the */
734 /* callback function. */
735 if ( inc )
736 error = inc->funcs->get_glyph_data( inc->object,
737 glyph_index, &glyph_data );
738 else
739#endif
740 /* For ordinary fonts get the character data stored in the face record. */
741 {
742 glyph_data.pointer = type1->charstrings[glyph_index];
743 glyph_data.length = type1->charstrings_len[glyph_index];
744 }
745
746 if ( !error )
747 {
748 FT_Byte* charstring_base = (FT_Byte*)glyph_data.pointer;
749 FT_ULong charstring_len = glyph_data.length;
750
751
752 FT_ASSERT( charstring_base + charstring_len >= charstring_base );
753
754 FT_ZERO( buf );
755 buf->start =
756 buf->ptr = charstring_base;
757 buf->end = charstring_base + charstring_len;
758 }
759
760 return error;
761 }
762
763
764 FT_LOCAL_DEF( void )
765 cf2_freeT1SeacComponent( PS_Decoder* decoder,
766 CF2_Buffer buf )
767 {
768#ifdef FT_CONFIG_OPTION_INCREMENTAL
769
770 T1_Face face;
771 FT_Data data;
772
773
774 FT_ASSERT( decoder );
775
776 face = (T1_Face)decoder->builder.face;
777
778 data.pointer = buf->start;
779 data.length = (FT_UInt)( buf->end - buf->start );
780
781 if ( face->root.internal->incremental_interface )
782 face->root.internal->incremental_interface->funcs->free_glyph_data(
783 face->root.internal->incremental_interface->object,
784 &data );
785
786#else /* !FT_CONFIG_OPTION_INCREMENTAL */
787
788 FT_UNUSED( decoder );
789 FT_UNUSED( buf );
790
791#endif /* !FT_CONFIG_OPTION_INCREMENTAL */
792 }
793
794
795 FT_LOCAL_DEF( CF2_Int )
796 cf2_initLocalRegionBuffer( PS_Decoder* decoder,
797 CF2_Int subrNum,
798 CF2_Buffer buf )
799 {
800 CF2_UInt idx;
801
802
803 FT_ASSERT( decoder );
804
805 FT_ZERO( buf );
806
807 idx = (CF2_UInt)( subrNum + decoder->locals_bias );
808 if ( idx >= decoder->num_locals )
809 return TRUE; /* error */
810
811 FT_ASSERT( decoder->locals );
812
813 buf->start = decoder->locals[idx];
814
815 if ( decoder->builder.is_t1 )
816 {
817 /* The Type 1 driver stores subroutines without the seed bytes. */
818 /* The CID driver stores subroutines with seed bytes. This */
819 /* case is taken care of when decoder->subrs_len == 0. */
820 if ( decoder->locals_len )
821 buf->end = FT_OFFSET( buf->start, decoder->locals_len[idx] );
822 else
823 {
824 /* We are using subroutines from a CID font. We must adjust */
825 /* for the seed bytes. */
826 buf->start += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
827 buf->end = decoder->locals[idx + 1];
828 }
829
830 if ( !buf->start )
831 {
832 FT_ERROR(( "cf2_initLocalRegionBuffer (Type 1 mode):"
833 " invoking empty subrs\n" ));
834 }
835 }
836 else
837 {
838 buf->end = decoder->locals[idx + 1];
839 }
840
841 buf->ptr = buf->start;
842
843 return FALSE; /* success */
844 }
845
846
847 FT_LOCAL_DEF( CF2_Fixed )
848 cf2_getDefaultWidthX( PS_Decoder* decoder )
849 {
850 FT_ASSERT( decoder && decoder->current_subfont );
851
852 return cf2_intToFixed(
853 decoder->current_subfont->private_dict.default_width );
854 }
855
856
857 FT_LOCAL_DEF( CF2_Fixed )
858 cf2_getNominalWidthX( PS_Decoder* decoder )
859 {
860 FT_ASSERT( decoder && decoder->current_subfont );
861
862 return cf2_intToFixed(
863 decoder->current_subfont->private_dict.nominal_width );
864 }
865
866
867 FT_LOCAL_DEF( void )
868 cf2_outline_reset( CF2_Outline outline )
869 {
870 PS_Decoder* decoder = outline->decoder;
871
872
873 FT_ASSERT( decoder );
874
875 outline->root.windingMomentum = 0;
876
877 FT_GlyphLoader_Rewind( decoder->builder.loader );
878 }
879
880
881 FT_LOCAL_DEF( void )
882 cf2_outline_close( CF2_Outline outline )
883 {
884 PS_Decoder* decoder = outline->decoder;
885
886
887 FT_ASSERT( decoder );
888
889 ps_builder_close_contour( &decoder->builder );
890
891 FT_GlyphLoader_Add( decoder->builder.loader );
892 }
893
894
895/* END */
896