1 /***************************************************************************/
2 /* */
3 /* ttobjs.c */
4 /* */
5 /* Objects manager (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 FT_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_CALC_H
22 #include FT_INTERNAL_STREAM_H
23 #include FT_TRUETYPE_IDS_H
24 #include FT_TRUETYPE_TAGS_H
25 #include FT_INTERNAL_SFNT_H
26 #include FT_INTERNAL_POSTSCRIPT_NAMES_H
28 #include "ttgload.h"
29 #include "ttpload.h"
31 #include "tterrors.h"
33 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
34 #include "ttinterp.h"
35 #endif
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_ttobjs
48 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
50 /*************************************************************************/
51 /* */
52 /* GLYPH ZONE FUNCTIONS */
53 /* */
54 /*************************************************************************/
57 /*************************************************************************/
58 /* */
59 /* <Function> */
60 /* TT_Done_GlyphZone */
61 /* */
62 /* <Description> */
63 /* Deallocates a glyph zone. */
64 /* */
65 /* <Input> */
66 /* zone :: A pointer to the target glyph zone. */
67 /* */
68 FT_LOCAL_DEF void
69 TT_Done_GlyphZone( TT_GlyphZone* zone )
70 {
71 FT_Memory memory = zone->memory;
74 FREE( zone->contours );
75 FREE( zone->tags );
76 FREE( zone->cur );
77 FREE( zone->org );
79 zone->max_points = zone->n_points = 0;
80 zone->max_contours = zone->n_contours = 0;
81 }
84 /*************************************************************************/
85 /* */
86 /* <Function> */
87 /* TT_New_GlyphZone */
88 /* */
89 /* <Description> */
90 /* Allocates a new glyph zone. */
91 /* */
92 /* <Input> */
93 /* memory :: A handle to the current memory object. */
94 /* */
95 /* maxPoints :: The capacity of glyph zone in points. */
96 /* */
97 /* maxContours :: The capacity of glyph zone in contours. */
98 /* */
99 /* <Output> */
100 /* zone :: A pointer to the target glyph zone record. */
101 /* */
102 /* <Return> */
103 /* FreeType error code. 0 means success. */
104 /* */
105 FT_LOCAL_DEF FT_Error
106 TT_New_GlyphZone( FT_Memory memory,
107 FT_UShort maxPoints,
108 FT_Short maxContours,
109 TT_GlyphZone* zone )
110 {
111 FT_Error error;
114 if ( maxPoints > 0 )
115 maxPoints += 2;
117 MEM_Set( zone, 0, sizeof ( *zone ) );
118 zone->memory = memory;
120 if ( ALLOC_ARRAY( zone->org, maxPoints * 2, FT_F26Dot6 ) ||
121 ALLOC_ARRAY( zone->cur, maxPoints * 2, FT_F26Dot6 ) ||
122 ALLOC_ARRAY( zone->tags, maxPoints, FT_Byte ) ||
123 ALLOC_ARRAY( zone->contours, maxContours, FT_UShort ) )
124 {
125 TT_Done_GlyphZone( zone );
126 }
128 return error;
129 }
130 #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
133 /*************************************************************************/
134 /* */
135 /* <Function> */
136 /* TT_Init_Face */
137 /* */
138 /* <Description> */
139 /* Initializes a given TrueType face object. */
140 /* */
141 /* <Input> */
142 /* stream :: The source font stream. */
143 /* */
144 /* face_index :: The index of the font face in the resource. */
145 /* */
146 /* num_params :: Number of additional generic parameters. Ignored. */
147 /* */
148 /* params :: Additional generic parameters. Ignored. */
149 /* */
150 /* <InOut> */
151 /* face :: The newly built face object. */
152 /* */
153 /* <Return> */
154 /* FreeType error code. 0 means success. */
155 /* */
156 FT_LOCAL_DEF FT_Error
157 TT_Init_Face( FT_Stream stream,
158 TT_Face face,
159 FT_Int face_index,
160 FT_Int num_params,
161 FT_Parameter* params )
162 {
163 FT_Error error;
164 FT_Library library;
165 SFNT_Interface* sfnt;
168 library = face->root.driver->root.library;
169 sfnt = (SFNT_Interface*)FT_Get_Module_Interface( library, "sfnt" );
170 if ( !sfnt )
171 goto Bad_Format;
173 /* create input stream from resource */
174 if ( FILE_Seek( 0 ) )
175 goto Exit;
177 /* check that we have a valid TrueType file */
178 error = sfnt->init_face( stream, face, face_index, num_params, params );
179 if ( error )
180 goto Exit;
182 /* We must also be able to accept Mac/GX fonts, as well as OT ones */
183 if ( face->format_tag != 0x00010000L && /* MS fonts */
184 face->format_tag != TTAG_true ) /* Mac fonts */
185 {
186 FT_TRACE2(( "[not a valid TTF font]\n" ));
187 goto Bad_Format;
188 }
190 /* If we are performing a simple font format check, exit immediately */
191 if ( face_index < 0 )
192 return TT_Err_Ok;
194 /* Load font directory */
195 error = sfnt->load_face( stream, face, face_index, num_params, params );
196 if ( error )
197 goto Exit;
199 if ( face->root.face_flags & FT_FACE_FLAG_SCALABLE )
200 error = TT_Load_Locations( face, stream ) ||
201 TT_Load_CVT ( face, stream ) ||
202 TT_Load_Programs ( face, stream );
204 /* initialize standard glyph loading routines */
205 TT_Init_Glyph_Loading( face );
207 Exit:
208 return error;
210 Bad_Format:
211 error = TT_Err_Unknown_File_Format;
212 goto Exit;
213 }
216 /*************************************************************************/
217 /* */
218 /* <Function> */
219 /* TT_Done_Face */
220 /* */
221 /* <Description> */
222 /* Finalizes a given face object. */
223 /* */
224 /* <Input> */
225 /* face :: A pointer to the face object to destroy. */
226 /* */
227 FT_LOCAL_DEF void
228 TT_Done_Face( TT_Face face )
229 {
230 FT_Memory memory = face->root.memory;
231 FT_Stream stream = face->root.stream;
233 SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt;
236 /* for `extended TrueType formats' (i.e. compressed versions) */
237 if ( face->extra.finalizer )
238 face->extra.finalizer( face->extra.data );
240 if ( sfnt )
241 sfnt->done_face( face );
243 /* freeing the locations table */
244 FREE( face->glyph_locations );
245 face->num_locations = 0;
247 /* freeing the CVT */
248 FREE( face->cvt );
249 face->cvt_size = 0;
251 /* freeing the programs */
252 RELEASE_Frame( face->font_program );
253 RELEASE_Frame( face->cvt_program );
254 face->font_program_size = 0;
255 face->cvt_program_size = 0;
256 }
259 /*************************************************************************/
260 /* */
261 /* SIZE FUNCTIONS */
262 /* */
263 /*************************************************************************/
266 /*************************************************************************/
267 /* */
268 /* <Function> */
269 /* TT_Init_Size */
270 /* */
271 /* <Description> */
272 /* Initializes a new TrueType size object. */
273 /* */
274 /* <InOut> */
275 /* size :: A handle to the size object. */
276 /* */
277 /* <Return> */
278 /* FreeType error code. 0 means success. */
279 /* */
280 FT_LOCAL_DEF FT_Error
281 TT_Init_Size( TT_Size size )
282 {
283 FT_Error error = TT_Err_Ok;
286 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
288 TT_Face face = (TT_Face)size->root.face;
289 FT_Memory memory = face->root.memory;
290 FT_Int i;
292 TT_ExecContext exec;
293 FT_UShort n_twilight;
294 TT_MaxProfile* maxp = &face->max_profile;
297 size->ttmetrics.valid = FALSE;
299 size->max_function_defs = maxp->maxFunctionDefs;
300 size->max_instruction_defs = maxp->maxInstructionDefs;
302 size->num_function_defs = 0;
303 size->num_instruction_defs = 0;
305 size->max_func = 0;
306 size->max_ins = 0;
308 size->cvt_size = face->cvt_size;
309 size->storage_size = maxp->maxStorage;
311 /* Set default metrics */
312 {
313 FT_Size_Metrics* metrics = &size->root.metrics;
314 TT_Size_Metrics* metrics2 = &size->ttmetrics;
317 metrics->x_ppem = 0;
318 metrics->y_ppem = 0;
320 metrics2->rotated = FALSE;
321 metrics2->stretched = FALSE;
323 /* set default compensation (all 0) */
324 for ( i = 0; i < 4; i++ )
325 metrics2->compensations[i] = 0;
326 }
328 /* allocate function defs, instruction defs, cvt, and storage area */
329 if ( ALLOC_ARRAY( size->function_defs,
330 size->max_function_defs,
331 TT_DefRecord ) ||
333 ALLOC_ARRAY( size->instruction_defs,
334 size->max_instruction_defs,
335 TT_DefRecord ) ||
337 ALLOC_ARRAY( size->cvt,
338 size->cvt_size, FT_Long ) ||
340 ALLOC_ARRAY( size->storage,
341 size->storage_size, FT_Long ) )
343 goto Fail_Memory;
345 /* reserve twilight zone */
346 n_twilight = maxp->maxTwilightPoints;
347 error = TT_New_GlyphZone( memory, n_twilight, 0, &size->twilight );
348 if ( error )
349 goto Fail_Memory;
351 size->twilight.n_points = n_twilight;
353 /* set `face->interpreter' according to the debug hook present */
354 {
355 FT_Library library = face->root.driver->root.library;
358 face->interpreter = (TT_Interpreter)
359 library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE];
360 if ( !face->interpreter )
361 face->interpreter = (TT_Interpreter)TT_RunIns;
362 }
364 /* Fine, now execute the font program! */
365 exec = size->context;
366 /* size objects used during debugging have their own context */
367 if ( !size->debug )
368 exec = TT_New_Context( face );
370 if ( !exec )
371 {
372 error = TT_Err_Could_Not_Find_Context;
373 goto Fail_Memory;
374 }
376 size->GS = tt_default_graphics_state;
377 TT_Load_Context( exec, face, size );
379 exec->callTop = 0;
380 exec->top = 0;
382 exec->period = 64;
383 exec->phase = 0;
384 exec->threshold = 0;
386 {
387 FT_Size_Metrics* metrics = &exec->metrics;
388 TT_Size_Metrics* tt_metrics = &exec->tt_metrics;
391 metrics->x_ppem = 0;
392 metrics->y_ppem = 0;
393 metrics->x_scale = 0;
394 metrics->y_scale = 0;
396 tt_metrics->ppem = 0;
397 tt_metrics->scale = 0;
398 tt_metrics->ratio = 0x10000L;
399 }
401 exec->instruction_trap = FALSE;
403 exec->cvtSize = size->cvt_size;
404 exec->cvt = size->cvt;
406 exec->F_dot_P = 0x10000L;
408 /* allow font program execution */
409 TT_Set_CodeRange( exec,
410 tt_coderange_font,
411 face->font_program,
412 face->font_program_size );
414 /* disable CVT and glyph programs coderange */
415 TT_Clear_CodeRange( exec, tt_coderange_cvt );
416 TT_Clear_CodeRange( exec, tt_coderange_glyph );
418 if ( face->font_program_size > 0 )
419 {
420 error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
421 if ( !error )
422 error = face->interpreter( exec );
424 if ( error )
425 goto Fail_Exec;
426 }
427 else
428 error = TT_Err_Ok;
430 TT_Save_Context( exec, size );
432 if ( !size->debug )
433 TT_Done_Context( exec );
435 #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
437 size->ttmetrics.valid = FALSE;
438 return error;
440 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
442 Fail_Exec:
443 if ( !size->debug )
444 TT_Done_Context( exec );
446 Fail_Memory:
448 TT_Done_Size( size );
449 return error;
451 #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
453 }
456 /*************************************************************************/
457 /* */
458 /* <Function> */
459 /* TT_Done_Size */
460 /* */
461 /* <Description> */
462 /* The TrueType size object finalizer. */
463 /* */
464 /* <Input> */
465 /* size :: A handle to the target size object. */
466 /* */
467 FT_LOCAL_DEF void
468 TT_Done_Size( TT_Size size )
469 {
471 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
473 FT_Memory memory = size->root.face->memory;
476 if ( size->debug )
477 {
478 /* the debug context must be deleted by the debugger itself */
479 size->context = NULL;
480 size->debug = FALSE;
481 }
483 FREE( size->cvt );
484 size->cvt_size = 0;
486 /* free storage area */
487 FREE( size->storage );
488 size->storage_size = 0;
490 /* twilight zone */
491 TT_Done_GlyphZone( &size->twilight );
493 FREE( size->function_defs );
494 FREE( size->instruction_defs );
496 size->num_function_defs = 0;
497 size->max_function_defs = 0;
498 size->num_instruction_defs = 0;
499 size->max_instruction_defs = 0;
501 size->max_func = 0;
502 size->max_ins = 0;
504 #endif
506 size->ttmetrics.valid = FALSE;
507 }
510 /*************************************************************************/
511 /* */
512 /* <Function> */
513 /* Reset_Outline_Size */
514 /* */
515 /* <Description> */
516 /* Resets a TrueType outline size when resolutions and character */
517 /* dimensions have been changed. */
518 /* */
519 /* <Input> */
520 /* size :: A handle to the target size object. */
521 /* */
522 static FT_Error
523 Reset_Outline_Size( TT_Size size )
524 {
525 TT_Face face;
526 FT_Error error = TT_Err_Ok;
528 FT_Size_Metrics* metrics;
531 if ( size->ttmetrics.valid )
532 return TT_Err_Ok;
534 face = (TT_Face)size->root.face;
536 metrics = &size->root.metrics;
538 if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
539 return TT_Err_Invalid_PPem;
541 /* compute new transformation */
542 if ( metrics->x_ppem >= metrics->y_ppem )
543 {
544 size->ttmetrics.scale = metrics->x_scale;
545 size->ttmetrics.ppem = metrics->x_ppem;
546 size->ttmetrics.x_ratio = 0x10000L;
547 size->ttmetrics.y_ratio = FT_MulDiv( metrics->y_ppem,
548 0x10000L,
549 metrics->x_ppem );
550 }
551 else
552 {
553 size->ttmetrics.scale = metrics->y_scale;
554 size->ttmetrics.ppem = metrics->y_ppem;
555 size->ttmetrics.x_ratio = FT_MulDiv( metrics->x_ppem,
556 0x10000L,
557 metrics->y_ppem );
558 size->ttmetrics.y_ratio = 0x10000L;
559 }
561 /* Compute root ascender, descender, test height, and max_advance */
562 metrics->ascender = ( FT_MulFix( face->root.ascender,
563 metrics->y_scale ) + 32 ) & -64;
564 metrics->descender = ( FT_MulFix( face->root.descender,
565 metrics->y_scale ) + 32 ) & -64;
566 metrics->height = ( FT_MulFix( face->root.height,
567 metrics->y_scale ) + 32 ) & -64;
568 metrics->max_advance = ( FT_MulFix( face->root.max_advance_width,
569 metrics->x_scale ) + 32 ) & -64;
571 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
572 /* set to `invalid' by default */
573 size->strike_index = 0xFFFF;
574 #endif
576 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
578 {
579 TT_ExecContext exec;
580 FT_UInt i, j;
583 /* Scale the cvt values to the new ppem. */
584 /* We use by default the y ppem to scale the CVT. */
585 for ( i = 0; i < size->cvt_size; i++ )
586 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
588 /* All twilight points are originally zero */
589 for ( j = 0; j < (FT_UInt)size->twilight.n_points; j++ )
590 {
591 size->twilight.org[j].x = 0;
592 size->twilight.org[j].y = 0;
593 size->twilight.cur[j].x = 0;
594 size->twilight.cur[j].y = 0;
595 }
597 /* clear storage area */
598 for ( i = 0; i < (FT_UInt)size->storage_size; i++ )
599 size->storage[i] = 0;
601 size->GS = tt_default_graphics_state;
603 /* get execution context and run prep program */
604 if ( size->debug )
605 exec = size->context;
606 else
607 exec = TT_New_Context( face );
608 /* debugging instances have their own context */
610 if ( !exec )
611 return TT_Err_Could_Not_Find_Context;
613 TT_Load_Context( exec, face, size );
615 TT_Set_CodeRange( exec,
616 tt_coderange_cvt,
617 face->cvt_program,
618 face->cvt_program_size );
620 TT_Clear_CodeRange( exec, tt_coderange_glyph );
622 exec->instruction_trap = FALSE;
624 exec->top = 0;
625 exec->callTop = 0;
627 if ( face->cvt_program_size > 0 )
628 {
629 error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
630 if ( error )
631 goto End;
633 if ( !size->debug )
634 error = face->interpreter( exec );
635 }
636 else
637 error = TT_Err_Ok;
639 size->GS = exec->GS;
640 /* save default graphics state */
642 End:
643 TT_Save_Context( exec, size );
645 if ( !size->debug )
646 TT_Done_Context( exec );
647 /* debugging instances keep their context */
648 }
650 #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
652 if ( !error )
653 size->ttmetrics.valid = TRUE;
655 return error;
656 }
659 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
661 /*************************************************************************/
662 /* */
663 /* <Function> */
664 /* Reset_SBit_Size */
665 /* */
666 /* <Description> */
667 /* Resets a TrueType sbit size when resolutions and character */
668 /* dimensions have been changed. */
669 /* */
670 /* <Input> */
671 /* size :: A handle to the target size object. */
672 /* */
673 static FT_Error
674 Reset_SBit_Size( TT_Size size )
675 {
676 TT_Face face;
677 FT_Error error = TT_Err_Ok;
679 FT_ULong strike_index;
680 FT_Size_Metrics* metrics;
681 FT_Size_Metrics* sbit_metrics;
682 SFNT_Interface* sfnt;
685 metrics = &size->root.metrics;
687 if ( size->strike_index != 0xFFFF )
688 return TT_Err_Ok;
690 face = (TT_Face)size->root.face;
691 sfnt = (SFNT_Interface*)face->sfnt;
693 sbit_metrics = &size->strike_metrics;
695 error = sfnt->set_sbit_strike(face,
696 metrics->x_ppem, metrics->y_ppem,
697 &strike_index);
699 if ( !error )
700 {
701 TT_SBit_Strike* strike = face->sbit_strikes + strike_index;
704 sbit_metrics->x_ppem = metrics->x_ppem;
705 sbit_metrics->y_ppem = metrics->y_ppem;
706 #if 0
707 /*
708 * sbit_metrics->?_scale
709 * are not used now.
710 */
711 sbit_metrics->x_scale = 1 << 16;
712 sbit_metrics->y_scale = 1 << 16;
713 #endif
715 sbit_metrics->ascender = strike->hori.ascender << 6;
716 sbit_metrics->descender = strike->hori.descender << 6;
718 /* XXX: Is this correct? */
719 sbit_metrics->height = sbit_metrics->ascender -
720 sbit_metrics->descender;
722 /* XXX: Is this correct? */
723 sbit_metrics->max_advance = ( strike->hori.min_origin_SB +
724 strike->hori.max_width +
725 strike->hori.min_advance_SB ) << 6;
727 size->strike_index = strike_index;
728 }
729 else
730 {
731 size->strike_index = 0xFFFF;
733 sbit_metrics->x_ppem = 0;
734 sbit_metrics->y_ppem = 0;
735 sbit_metrics->ascender = 0;
736 sbit_metrics->descender = 0;
737 sbit_metrics->height = 0;
738 sbit_metrics->max_advance = 0;
739 }
741 return error;
742 }
744 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
747 /*************************************************************************/
748 /* */
749 /* <Function> */
750 /* TT_Reset_Size */
751 /* */
752 /* <Description> */
753 /* Resets a TrueType size when resolutions and character dimensions */
754 /* have been changed. */
755 /* */
756 /* <Input> */
757 /* size :: A handle to the target size object. */
758 /* */
759 FT_LOCAL_DEF FT_Error
760 TT_Reset_Size( TT_Size size )
761 {
762 FT_Face face;
763 FT_Error error = TT_Err_Ok;
766 face = size->root.face;
768 if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
769 {
770 if ( !size->ttmetrics.valid )
771 error = Reset_Outline_Size( size );
773 if ( error )
774 return error;
775 }
777 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
779 if ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES )
780 {
781 if ( size->strike_index == 0xFFFF )
782 error = Reset_SBit_Size( size );
784 if ( !error && !( face->face_flags & FT_FACE_FLAG_SCALABLE ) )
785 size->root.metrics = size->strike_metrics;
786 }
788 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
790 if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
791 return TT_Err_Ok;
792 else
793 return error;
794 }
797 /*************************************************************************/
798 /* */
799 /* <Function> */
800 /* TT_Init_Driver */
801 /* */
802 /* <Description> */
803 /* Initializes a given TrueType driver object. */
804 /* */
805 /* <Input> */
806 /* driver :: A handle to the target driver object. */
807 /* */
808 /* <Return> */
809 /* FreeType error code. 0 means success. */
810 /* */
811 FT_LOCAL_DEF FT_Error
812 TT_Init_Driver( TT_Driver driver )
813 {
814 FT_Error error;
817 /* set `extra' in glyph loader */
818 error = FT_GlyphLoader_Create_Extra( FT_DRIVER( driver )->glyph_loader );
820 /* init extension registry if needed */
822 #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
823 if ( !error )
824 return TT_Init_Extensions( driver );
825 #endif
827 return error;
828 }
831 /*************************************************************************/
832 /* */
833 /* <Function> */
834 /* TT_Done_Driver */
835 /* */
836 /* <Description> */
837 /* Finalizes a given TrueType driver. */
838 /* */
839 /* <Input> */
840 /* driver :: A handle to the target TrueType driver. */
841 /* */
842 FT_LOCAL_DEF void
843 TT_Done_Driver( TT_Driver driver )
844 {
845 /* destroy extensions registry if needed */
847 #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
849 TT_Done_Extensions( driver );
851 #endif
853 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
855 /* destroy the execution context */
856 if ( driver->context )
857 {
858 TT_Destroy_Context( driver->context, driver->root.root.memory );
859 driver->context = NULL;
860 }
861 #else
862 FT_UNUSED( driver );
863 #endif
865 }
868 /* END */