xref: /inferno-os/libfreetype/ftobject.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth #include <ft2build.h>
2*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECT_H
3*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
4*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H
5*37da2899SCharles.Forsyth 
6*37da2899SCharles.Forsyth #define  FT_MAGIC_DEATH   0xDEADdead
7*37da2899SCharles.Forsyth #define  FT_MAGIC_CLASS   0x12345678
8*37da2899SCharles.Forsyth 
9*37da2899SCharles.Forsyth #define  FT_TYPE_HASH(x)  (( (FT_UInt32)(x) >> 2 )^( (FT_UInt32)(x) >> 10 ))
10*37da2899SCharles.Forsyth 
11*37da2899SCharles.Forsyth #define  FT_OBJECT_CHECK(o)                                  \
12*37da2899SCharles.Forsyth            ( FT_OBJECT(o)               != NULL           && \
13*37da2899SCharles.Forsyth              FT_OBJECT(o)->clazz        != NULL           && \
14*37da2899SCharles.Forsyth              FT_OBJECT(o)->ref_count    >= 1              && \
15*37da2899SCharles.Forsyth              FT_OBJECT(o)->clazz->magic == FT_MAGIC_CLASS )
16*37da2899SCharles.Forsyth 
17*37da2899SCharles.Forsyth #define  FT_CLASS_CHECK(c)  \
18*37da2899SCharles.Forsyth            ( FT_CLASS(c) != NULL && FT_CLASS(c)->magic == FT_MAGIC_CLASS )
19*37da2899SCharles.Forsyth 
20*37da2899SCharles.Forsyth #define  FT_ASSERT_IS_CLASS(c)  FT_ASSERT( FT_CLASS_CHECK(c) )
21*37da2899SCharles.Forsyth 
22*37da2899SCharles.Forsyth  /*******************************************************************/
23*37da2899SCharles.Forsyth  /*******************************************************************/
24*37da2899SCharles.Forsyth  /*****                                                         *****/
25*37da2899SCharles.Forsyth  /*****                                                         *****/
26*37da2899SCharles.Forsyth  /*****                  M E T A - C L A S S                    *****/
27*37da2899SCharles.Forsyth  /*****                                                         *****/
28*37da2899SCharles.Forsyth  /*****                                                         *****/
29*37da2899SCharles.Forsyth  /*******************************************************************/
30*37da2899SCharles.Forsyth  /*******************************************************************/
31*37da2899SCharles.Forsyth 
32*37da2899SCharles.Forsyth  /* forward declaration */
33*37da2899SCharles.Forsyth   FT_BASE_DEF( FT_Error )
34*37da2899SCharles.Forsyth   ft_metaclass_init( FT_MetaClass  meta,
35*37da2899SCharles.Forsyth                      FT_Library    library );
36*37da2899SCharles.Forsyth 
37*37da2899SCharles.Forsyth   /* forward declaration */
38*37da2899SCharles.Forsyth   FT_BASE_DEF( void )
39*37da2899SCharles.Forsyth   ft_metaclass_done( FT_MetaClass  meta );
40*37da2899SCharles.Forsyth 
41*37da2899SCharles.Forsyth 
42*37da2899SCharles.Forsyth   /* class type for the meta-class itself */
43*37da2899SCharles.Forsyth   static const FT_TypeRec  ft_meta_class_type =
44*37da2899SCharles.Forsyth   {
45*37da2899SCharles.Forsyth     "FT2.MetaClass",
46*37da2899SCharles.Forsyth     NULL,
47*37da2899SCharles.Forsyth 
48*37da2899SCharles.Forsyth     sizeof( FT_MetaClassRec ),
49*37da2899SCharles.Forsyth     (FT_Object_InitFunc)  ft_metaclass_init,
50*37da2899SCharles.Forsyth     (FT_Object_DoneFunc)  ft_metaclass_done,
51*37da2899SCharles.Forsyth 
52*37da2899SCharles.Forsyth     sizeof( FT_ClassRec ),
53*37da2899SCharles.Forsyth     (FT_Object_InitFunc)  NULL,
54*37da2899SCharles.Forsyth     (FT_Object_DoneFunc)  NULL
55*37da2899SCharles.Forsyth   };
56*37da2899SCharles.Forsyth 
57*37da2899SCharles.Forsyth 
58*37da2899SCharles.Forsyth 
59*37da2899SCharles.Forsyth 
60*37da2899SCharles.Forsyth  /* destroy a given class */
61*37da2899SCharles.Forsyth   static void
ft_class_hnode_destroy(FT_ClassHNode node)62*37da2899SCharles.Forsyth   ft_class_hnode_destroy( FT_ClassHNode  node )
63*37da2899SCharles.Forsyth   {
64*37da2899SCharles.Forsyth     FT_Class   clazz  = node->clazz;
65*37da2899SCharles.Forsyth     FT_Memory  memory = clazz->memory;
66*37da2899SCharles.Forsyth 
67*37da2899SCharles.Forsyth     if ( clazz->class_done )
68*37da2899SCharles.Forsyth       clazz->class_done( (FT_Object) clazz );
69*37da2899SCharles.Forsyth 
70*37da2899SCharles.Forsyth     FT_FREE( clazz );
71*37da2899SCharles.Forsyth 
72*37da2899SCharles.Forsyth     node->clazz = NULL;
73*37da2899SCharles.Forsyth     node->type  = NULL;
74*37da2899SCharles.Forsyth 
75*37da2899SCharles.Forsyth     FT_FREE( node );
76*37da2899SCharles.Forsyth   }
77*37da2899SCharles.Forsyth 
78*37da2899SCharles.Forsyth 
79*37da2899SCharles.Forsyth   static FT_Int
ft_type_equal(FT_Type type1,FT_Type type2)80*37da2899SCharles.Forsyth   ft_type_equal( FT_Type  type1,
81*37da2899SCharles.Forsyth                  FT_Type  type2 )
82*37da2899SCharles.Forsyth   {
83*37da2899SCharles.Forsyth     if ( type1 == type2 )
84*37da2899SCharles.Forsyth       goto Ok;
85*37da2899SCharles.Forsyth 
86*37da2899SCharles.Forsyth     if ( type1 == NULL || type2 == NULL )
87*37da2899SCharles.Forsyth       goto Fail;
88*37da2899SCharles.Forsyth 
89*37da2899SCharles.Forsyth     /* compare parent types */
90*37da2899SCharles.Forsyth     if ( type1->super != type2->super )
91*37da2899SCharles.Forsyth     {
92*37da2899SCharles.Forsyth       if ( type1->super == NULL           ||
93*37da2899SCharles.Forsyth            type2->super == NULL           ||
94*37da2899SCharles.Forsyth            !ft_type_equal( type1, type2 ) )
95*37da2899SCharles.Forsyth         goto Fail;
96*37da2899SCharles.Forsyth     }
97*37da2899SCharles.Forsyth 
98*37da2899SCharles.Forsyth     /* compare type names */
99*37da2899SCharles.Forsyth     if ( type1->name != type2->name )
100*37da2899SCharles.Forsyth     {
101*37da2899SCharles.Forsyth       if ( type1->name == NULL                        ||
102*37da2899SCharles.Forsyth            type2->name == NULL                        ||
103*37da2899SCharles.Forsyth            ft_strcmp( type1->name, type2->name ) != 0 )
104*37da2899SCharles.Forsyth         goto Fail;
105*37da2899SCharles.Forsyth     }
106*37da2899SCharles.Forsyth 
107*37da2899SCharles.Forsyth     /* compare the other type fields */
108*37da2899SCharles.Forsyth     if ( type1->class_size != type2->class_size ||
109*37da2899SCharles.Forsyth          type1->class_init != type2->class_init ||
110*37da2899SCharles.Forsyth          type1->class_done != type2->class_done ||
111*37da2899SCharles.Forsyth          type1->obj_size   != type2->obj_size   ||
112*37da2899SCharles.Forsyth          type1->obj_init   != type2->obj_init   ||
113*37da2899SCharles.Forsyth          type1->obj_done   != type2->obj_done   )
114*37da2899SCharles.Forsyth       goto Fail;
115*37da2899SCharles.Forsyth 
116*37da2899SCharles.Forsyth   Ok:
117*37da2899SCharles.Forsyth     return 1;
118*37da2899SCharles.Forsyth 
119*37da2899SCharles.Forsyth   Fail:
120*37da2899SCharles.Forsyth     return 0;
121*37da2899SCharles.Forsyth   }
122*37da2899SCharles.Forsyth 
123*37da2899SCharles.Forsyth 
124*37da2899SCharles.Forsyth   static FT_Int
ft_class_hnode_equal(const FT_ClassHNode node1,const FT_ClassHNode node2)125*37da2899SCharles.Forsyth   ft_class_hnode_equal( const FT_ClassHNode  node1,
126*37da2899SCharles.Forsyth                         const FT_ClassHNode  node2 )
127*37da2899SCharles.Forsyth   {
128*37da2899SCharles.Forsyth     FT_Type  type1 = node1->type;
129*37da2899SCharles.Forsyth     FT_Type  type2 = node2->type;
130*37da2899SCharles.Forsyth 
131*37da2899SCharles.Forsyth     /* comparing the pointers should work in 99% of cases */
132*37da2899SCharles.Forsyth     return ( type1 == type2 ) ? 1 : ft_type_equal( type1, type2 );
133*37da2899SCharles.Forsyth   }
134*37da2899SCharles.Forsyth 
135*37da2899SCharles.Forsyth 
136*37da2899SCharles.Forsyth   FT_BASE_DEF( void )
ft_metaclass_done(FT_MetaClass meta)137*37da2899SCharles.Forsyth   ft_metaclass_done( FT_MetaClass  meta )
138*37da2899SCharles.Forsyth   {
139*37da2899SCharles.Forsyth     /* clear all classes */
140*37da2899SCharles.Forsyth     ft_hash_done( &meta->type_to_class,
141*37da2899SCharles.Forsyth                   (FT_Hash_ForeachFunc) ft_class_hnode_destroy,
142*37da2899SCharles.Forsyth                    NULL );
143*37da2899SCharles.Forsyth 
144*37da2899SCharles.Forsyth     meta->clazz.object.clazz     = NULL;
145*37da2899SCharles.Forsyth     meta->clazz.object.ref_count = 0;
146*37da2899SCharles.Forsyth     meta->clazz.magic            = FT_MAGIC_DEATH;
147*37da2899SCharles.Forsyth   }
148*37da2899SCharles.Forsyth 
149*37da2899SCharles.Forsyth 
150*37da2899SCharles.Forsyth   FT_BASE_DEF( FT_Error )
ft_metaclass_init(FT_MetaClass meta,FT_Library library)151*37da2899SCharles.Forsyth   ft_metaclass_init( FT_MetaClass  meta,
152*37da2899SCharles.Forsyth                      FT_Library    library )
153*37da2899SCharles.Forsyth   {
154*37da2899SCharles.Forsyth     FT_ClassRec*  clazz = (FT_ClassRec*) &meta->clazz;
155*37da2899SCharles.Forsyth 
156*37da2899SCharles.Forsyth     /* the meta-class is its OWN class !! */
157*37da2899SCharles.Forsyth     clazz->object.clazz     = (FT_Class) clazz;
158*37da2899SCharles.Forsyth     clazz->object.ref_count = 1;
159*37da2899SCharles.Forsyth     clazz->magic            = FT_MAGIC_CLASS;
160*37da2899SCharles.Forsyth     clazz->library          = library;
161*37da2899SCharles.Forsyth     clazz->memory           = library->memory;
162*37da2899SCharles.Forsyth     clazz->type             = &ft_meta_class_type;
163*37da2899SCharles.Forsyth     clazz->info             = NULL;
164*37da2899SCharles.Forsyth 
165*37da2899SCharles.Forsyth     clazz->class_done       = (FT_Object_DoneFunc) ft_metaclass_done;
166*37da2899SCharles.Forsyth 
167*37da2899SCharles.Forsyth     clazz->obj_size         = sizeof( FT_ClassRec );
168*37da2899SCharles.Forsyth     clazz->obj_init         = NULL;
169*37da2899SCharles.Forsyth     clazz->obj_done         = NULL;
170*37da2899SCharles.Forsyth 
171*37da2899SCharles.Forsyth     return ft_hash_init( &meta->type_to_class,
172*37da2899SCharles.Forsyth                         (FT_Hash_EqualFunc) ft_class_hnode_equal,
173*37da2899SCharles.Forsyth                         library->memory );
174*37da2899SCharles.Forsyth   }
175*37da2899SCharles.Forsyth 
176*37da2899SCharles.Forsyth 
177*37da2899SCharles.Forsyth  /* find or create the class corresponding to a given type */
178*37da2899SCharles.Forsyth  /* note that this function will retunr NULL in case of    */
179*37da2899SCharles.Forsyth  /* memory overflow                                        */
180*37da2899SCharles.Forsyth  /*                                                        */
181*37da2899SCharles.Forsyth   static FT_Class
ft_metaclass_get_class(FT_MetaClass meta,FT_Type ctype)182*37da2899SCharles.Forsyth   ft_metaclass_get_class( FT_MetaClass  meta,
183*37da2899SCharles.Forsyth                           FT_Type       ctype )
184*37da2899SCharles.Forsyth   {
185*37da2899SCharles.Forsyth     FT_ClassHNodeRec   keynode, *node, **pnode;
186*37da2899SCharles.Forsyth     FT_Memory          memory;
187*37da2899SCharles.Forsyth     FT_ClassRec*       clazz;
188*37da2899SCharles.Forsyth     FT_Class           parent;
189*37da2899SCharles.Forsyth     FT_Error           error;
190*37da2899SCharles.Forsyth 
191*37da2899SCharles.Forsyth     keynode.hnode.hash = FT_TYPE_HASH( ctype );
192*37da2899SCharles.Forsyth     keynode.type       = ctype;
193*37da2899SCharles.Forsyth 
194*37da2899SCharles.Forsyth     pnode = (FT_ClassHNode*) ft_hash_lookup( &meta->type_to_class,
195*37da2899SCharles.Forsyth                                              (FT_HashNode) &keynode );
196*37da2899SCharles.Forsyth     node  = *pnode;
197*37da2899SCharles.Forsyth     if ( node != NULL )
198*37da2899SCharles.Forsyth     {
199*37da2899SCharles.Forsyth       clazz = (FT_ClassRec*) node->clazz;
200*37da2899SCharles.Forsyth       goto Exit;
201*37da2899SCharles.Forsyth     }
202*37da2899SCharles.Forsyth 
203*37da2899SCharles.Forsyth     memory = FT_CLASS__MEMORY(meta);
204*37da2899SCharles.Forsyth     clazz  = NULL;
205*37da2899SCharles.Forsyth     parent = NULL;
206*37da2899SCharles.Forsyth     if ( ctype->super != NULL )
207*37da2899SCharles.Forsyth     {
208*37da2899SCharles.Forsyth       FT_ASSERT( ctype->super->class_size <= ctype->class_size );
209*37da2899SCharles.Forsyth       FT_ASSERT( ctype->super->obj_size   <= ctype->obj_size   );
210*37da2899SCharles.Forsyth 
211*37da2899SCharles.Forsyth       parent = ft_metaclass_get_class( meta, ctype->super );
212*37da2899SCharles.Forsyth     }
213*37da2899SCharles.Forsyth 
214*37da2899SCharles.Forsyth     if ( !FT_NEW( node ) )
215*37da2899SCharles.Forsyth     {
216*37da2899SCharles.Forsyth       if ( !FT_ALLOC( clazz, ctype->class_size ) )
217*37da2899SCharles.Forsyth       {
218*37da2899SCharles.Forsyth         if ( parent )
219*37da2899SCharles.Forsyth           FT_MEM_COPY( (FT_ClassRec*)clazz, parent, parent->type->class_size );
220*37da2899SCharles.Forsyth 
221*37da2899SCharles.Forsyth         clazz->object.clazz     = (FT_Class) meta;
222*37da2899SCharles.Forsyth         clazz->object.ref_count = 1;
223*37da2899SCharles.Forsyth 
224*37da2899SCharles.Forsyth         clazz->memory  = memory;
225*37da2899SCharles.Forsyth         clazz->library = FT_CLASS__LIBRARY(meta);
226*37da2899SCharles.Forsyth         clazz->super   = parent;
227*37da2899SCharles.Forsyth         clazz->type    = ctype;
228*37da2899SCharles.Forsyth         clazz->info    = NULL;
229*37da2899SCharles.Forsyth         clazz->magic   = FT_MAGIC_CLASS;
230*37da2899SCharles.Forsyth 
231*37da2899SCharles.Forsyth         clazz->class_done = ctype->class_done;
232*37da2899SCharles.Forsyth         clazz->obj_size   = ctype->obj_size;
233*37da2899SCharles.Forsyth         clazz->obj_init   = ctype->obj_init;
234*37da2899SCharles.Forsyth         clazz->obj_done   = ctype->obj_done;
235*37da2899SCharles.Forsyth 
236*37da2899SCharles.Forsyth         if ( parent )
237*37da2899SCharles.Forsyth         {
238*37da2899SCharles.Forsyth           if ( clazz->class_done == NULL )
239*37da2899SCharles.Forsyth             clazz->class_done = parent->class_done;
240*37da2899SCharles.Forsyth 
241*37da2899SCharles.Forsyth           if ( clazz->obj_init == NULL )
242*37da2899SCharles.Forsyth             clazz->obj_init = parent->obj_init;
243*37da2899SCharles.Forsyth 
244*37da2899SCharles.Forsyth           if ( clazz->obj_done == NULL )
245*37da2899SCharles.Forsyth             clazz->obj_done = parent->obj_done;
246*37da2899SCharles.Forsyth         }
247*37da2899SCharles.Forsyth 
248*37da2899SCharles.Forsyth         /* find class initializer, if any */
249*37da2899SCharles.Forsyth         {
250*37da2899SCharles.Forsyth           FT_Type             ztype = ctype;
251*37da2899SCharles.Forsyth           FT_Object_InitFunc  cinit = NULL;
252*37da2899SCharles.Forsyth 
253*37da2899SCharles.Forsyth           do
254*37da2899SCharles.Forsyth           {
255*37da2899SCharles.Forsyth             cinit = ztype->class_init;
256*37da2899SCharles.Forsyth             if ( cinit != NULL )
257*37da2899SCharles.Forsyth               break;
258*37da2899SCharles.Forsyth 
259*37da2899SCharles.Forsyth             ztype = ztype->super;
260*37da2899SCharles.Forsyth           }
261*37da2899SCharles.Forsyth           while ( ztype != NULL );
262*37da2899SCharles.Forsyth 
263*37da2899SCharles.Forsyth           /* then call it when needed */
264*37da2899SCharles.Forsyth           if ( cinit != NULL )
265*37da2899SCharles.Forsyth             error = cinit( (FT_Object) clazz, NULL );
266*37da2899SCharles.Forsyth         }
267*37da2899SCharles.Forsyth       }
268*37da2899SCharles.Forsyth 
269*37da2899SCharles.Forsyth       if (error)
270*37da2899SCharles.Forsyth       {
271*37da2899SCharles.Forsyth         if ( clazz )
272*37da2899SCharles.Forsyth         {
273*37da2899SCharles.Forsyth           /* we always call the class destructor when    */
274*37da2899SCharles.Forsyth           /* an error was detected in the constructor !! */
275*37da2899SCharles.Forsyth           if ( clazz->class_done )
276*37da2899SCharles.Forsyth             clazz->class_done( (FT_Object) clazz );
277*37da2899SCharles.Forsyth 
278*37da2899SCharles.Forsyth           FT_FREE( clazz );
279*37da2899SCharles.Forsyth         }
280*37da2899SCharles.Forsyth         FT_FREE( node );
281*37da2899SCharles.Forsyth       }
282*37da2899SCharles.Forsyth     }
283*37da2899SCharles.Forsyth 
284*37da2899SCharles.Forsyth   Exit:
285*37da2899SCharles.Forsyth     return  (FT_Class) clazz;
286*37da2899SCharles.Forsyth   }
287*37da2899SCharles.Forsyth 
288*37da2899SCharles.Forsyth 
289*37da2899SCharles.Forsyth 
290*37da2899SCharles.Forsyth 
291*37da2899SCharles.Forsyth 
292*37da2899SCharles.Forsyth 
293*37da2899SCharles.Forsyth 
294*37da2899SCharles.Forsyth 
295*37da2899SCharles.Forsyth 
296*37da2899SCharles.Forsyth 
297*37da2899SCharles.Forsyth 
298*37da2899SCharles.Forsyth 
299*37da2899SCharles.Forsyth 
300*37da2899SCharles.Forsyth 
301*37da2899SCharles.Forsyth   FT_BASE_DEF( FT_Int )
ft_object_check(FT_Pointer obj)302*37da2899SCharles.Forsyth   ft_object_check( FT_Pointer  obj )
303*37da2899SCharles.Forsyth   {
304*37da2899SCharles.Forsyth     return FT_OBJECT_CHECK(obj);
305*37da2899SCharles.Forsyth   }
306*37da2899SCharles.Forsyth 
307*37da2899SCharles.Forsyth 
308*37da2899SCharles.Forsyth   FT_BASE_DEF( FT_Int )
ft_object_is_a(FT_Pointer obj,FT_Class clazz)309*37da2899SCharles.Forsyth   ft_object_is_a( FT_Pointer  obj,
310*37da2899SCharles.Forsyth                   FT_Class    clazz )
311*37da2899SCharles.Forsyth   {
312*37da2899SCharles.Forsyth     if ( FT_OBJECT_CHECK(obj) )
313*37da2899SCharles.Forsyth     {
314*37da2899SCharles.Forsyth       FT_Class   c = FT_OBJECT__CLASS(obj);
315*37da2899SCharles.Forsyth 
316*37da2899SCharles.Forsyth       do
317*37da2899SCharles.Forsyth       {
318*37da2899SCharles.Forsyth         if ( c == clazz )
319*37da2899SCharles.Forsyth           return 1;
320*37da2899SCharles.Forsyth 
321*37da2899SCharles.Forsyth         c = c->super;
322*37da2899SCharles.Forsyth       }
323*37da2899SCharles.Forsyth       while ( c == NULL );
324*37da2899SCharles.Forsyth 
325*37da2899SCharles.Forsyth       return (clazz == NULL);
326*37da2899SCharles.Forsyth     }
327*37da2899SCharles.Forsyth     return 0;
328*37da2899SCharles.Forsyth   }
329*37da2899SCharles.Forsyth 
330*37da2899SCharles.Forsyth 
331*37da2899SCharles.Forsyth   FT_BASE_DEF( FT_Error )
ft_object_create(FT_Object * pobject,FT_Class clazz,FT_Pointer init_data)332*37da2899SCharles.Forsyth   ft_object_create( FT_Object  *pobject,
333*37da2899SCharles.Forsyth                     FT_Class    clazz,
334*37da2899SCharles.Forsyth                     FT_Pointer  init_data )
335*37da2899SCharles.Forsyth   {
336*37da2899SCharles.Forsyth     FT_Memory  memory;
337*37da2899SCharles.Forsyth     FT_Error   error;
338*37da2899SCharles.Forsyth     FT_Object  obj;
339*37da2899SCharles.Forsyth 
340*37da2899SCharles.Forsyth     FT_ASSERT_IS_CLASS(clazz);
341*37da2899SCharles.Forsyth 
342*37da2899SCharles.Forsyth     memory = FT_CLASS__MEMORY(clazz);
343*37da2899SCharles.Forsyth     if ( !FT_ALLOC( obj, clazz->obj_size ) )
344*37da2899SCharles.Forsyth     {
345*37da2899SCharles.Forsyth       obj->clazz     = clazz;
346*37da2899SCharles.Forsyth       obj->ref_count = 1;
347*37da2899SCharles.Forsyth 
348*37da2899SCharles.Forsyth       if ( clazz->obj_init )
349*37da2899SCharles.Forsyth       {
350*37da2899SCharles.Forsyth         error = clazz->obj_init( obj, init_data );
351*37da2899SCharles.Forsyth         if ( error )
352*37da2899SCharles.Forsyth         {
353*37da2899SCharles.Forsyth           /* IMPORTANT: call the destructor when an error  */
354*37da2899SCharles.Forsyth           /*            was detected in the constructor !! */
355*37da2899SCharles.Forsyth           if ( clazz->obj_done )
356*37da2899SCharles.Forsyth             clazz->obj_done( obj );
357*37da2899SCharles.Forsyth 
358*37da2899SCharles.Forsyth           FT_FREE( obj );
359*37da2899SCharles.Forsyth         }
360*37da2899SCharles.Forsyth       }
361*37da2899SCharles.Forsyth     }
362*37da2899SCharles.Forsyth     *pobject = obj;
363*37da2899SCharles.Forsyth     return error;
364*37da2899SCharles.Forsyth   }
365*37da2899SCharles.Forsyth 
366*37da2899SCharles.Forsyth 
367*37da2899SCharles.Forsyth   FT_BASE_DEF( FT_Class )
ft_class_find_by_type(FT_Type type,FT_Library library)368*37da2899SCharles.Forsyth   ft_class_find_by_type( FT_Type     type,
369*37da2899SCharles.Forsyth                          FT_Library  library )
370*37da2899SCharles.Forsyth   {
371*37da2899SCharles.Forsyth     FT_MetaClass  meta = &library->meta_class;
372*37da2899SCharles.Forsyth 
373*37da2899SCharles.Forsyth     return ft_metaclass_get_class( meta, type );
374*37da2899SCharles.Forsyth   }
375*37da2899SCharles.Forsyth 
376*37da2899SCharles.Forsyth 
377*37da2899SCharles.Forsyth   FT_BASE_DEF( FT_Error )
ft_object_create_from_type(FT_Object * pobject,FT_Type type,FT_Pointer init_data,FT_Library library)378*37da2899SCharles.Forsyth   ft_object_create_from_type( FT_Object  *pobject,
379*37da2899SCharles.Forsyth                               FT_Type     type,
380*37da2899SCharles.Forsyth                               FT_Pointer  init_data,
381*37da2899SCharles.Forsyth                               FT_Library  library )
382*37da2899SCharles.Forsyth   {
383*37da2899SCharles.Forsyth     FT_Class  clazz;
384*37da2899SCharles.Forsyth     FT_Error  error;
385*37da2899SCharles.Forsyth 
386*37da2899SCharles.Forsyth     clazz = ft_class_find_by_type( type, library );
387*37da2899SCharles.Forsyth     if ( clazz )
388*37da2899SCharles.Forsyth       error = ft_object_create( pobject, clazz, init_data );
389*37da2899SCharles.Forsyth     else
390*37da2899SCharles.Forsyth     {
391*37da2899SCharles.Forsyth       *pobject = NULL;
392*37da2899SCharles.Forsyth       error    = FT_Err_Out_Of_Memory;
393*37da2899SCharles.Forsyth     }
394*37da2899SCharles.Forsyth 
395*37da2899SCharles.Forsyth     return error;
396*37da2899SCharles.Forsyth   }
397