]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - QRScanner/mobile/jni/thirdparty/freetype/src/cache/ftcmanag.c
Add MuPDF native source codes
[hornmich/skoda-qr-demo.git] / QRScanner / mobile / jni / thirdparty / freetype / src / cache / ftcmanag.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  ftcmanag.c                                                             */
4 /*                                                                         */
5 /*    FreeType Cache Manager (body).                                       */
6 /*                                                                         */
7 /*  Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010 by */
8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9 /*                                                                         */
10 /*  This file is part of the FreeType project, and may only be used,       */
11 /*  modified, and distributed under the terms of the FreeType project      */
12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13 /*  this file you indicate that you have read the license and              */
14 /*  understand and accept it fully.                                        */
15 /*                                                                         */
16 /***************************************************************************/
17
18
19 #include <ft2build.h>
20 #include FT_CACHE_H
21 #include "ftcmanag.h"
22 #include FT_INTERNAL_OBJECTS_H
23 #include FT_INTERNAL_DEBUG_H
24 #include FT_SIZES_H
25
26 #include "ftccback.h"
27 #include "ftcerror.h"
28
29 #ifdef FT_CONFIG_OPTION_PIC
30 #error "cache system does not support PIC yet"
31 #endif
32
33
34 #undef  FT_COMPONENT
35 #define FT_COMPONENT  trace_cache
36
37 #define FTC_LRU_GET_MANAGER( lru )  ( (FTC_Manager)(lru)->user_data )
38
39
40   static FT_Error
41   ftc_scaler_lookup_size( FTC_Manager  manager,
42                           FTC_Scaler   scaler,
43                           FT_Size     *asize )
44   {
45     FT_Face   face;
46     FT_Size   size = NULL;
47     FT_Error  error;
48
49
50     error = FTC_Manager_LookupFace( manager, scaler->face_id, &face );
51     if ( error )
52       goto Exit;
53
54     error = FT_New_Size( face, &size );
55     if ( error )
56       goto Exit;
57
58     FT_Activate_Size( size );
59
60     if ( scaler->pixel )
61       error = FT_Set_Pixel_Sizes( face, scaler->width, scaler->height );
62     else
63       error = FT_Set_Char_Size( face, scaler->width, scaler->height,
64                                 scaler->x_res, scaler->y_res );
65     if ( error )
66     {
67       FT_Done_Size( size );
68       size = NULL;
69     }
70
71   Exit:
72     *asize = size;
73     return error;
74   }
75
76
77   typedef struct  FTC_SizeNodeRec_
78   {
79     FTC_MruNodeRec  node;
80     FT_Size         size;
81     FTC_ScalerRec   scaler;
82
83   } FTC_SizeNodeRec, *FTC_SizeNode;
84
85 #define FTC_SIZE_NODE( x ) ( (FTC_SizeNode)( x ) )
86
87
88   FT_CALLBACK_DEF( void )
89   ftc_size_node_done( FTC_MruNode  ftcnode,
90                       FT_Pointer   data )
91   {
92     FTC_SizeNode  node = (FTC_SizeNode)ftcnode;
93     FT_Size       size = node->size;
94     FT_UNUSED( data );
95
96
97     if ( size )
98       FT_Done_Size( size );
99   }
100
101
102   FT_CALLBACK_DEF( FT_Bool )
103   ftc_size_node_compare( FTC_MruNode  ftcnode,
104                          FT_Pointer   ftcscaler )
105   {
106     FTC_SizeNode  node    = (FTC_SizeNode)ftcnode;
107     FTC_Scaler    scaler  = (FTC_Scaler)ftcscaler;
108     FTC_Scaler    scaler0 = &node->scaler;
109
110
111     if ( FTC_SCALER_COMPARE( scaler0, scaler ) )
112     {
113       FT_Activate_Size( node->size );
114       return 1;
115     }
116     return 0;
117   }
118
119
120   FT_CALLBACK_DEF( FT_Error )
121   ftc_size_node_init( FTC_MruNode  ftcnode,
122                       FT_Pointer   ftcscaler,
123                       FT_Pointer   ftcmanager )
124   {
125     FTC_SizeNode  node    = (FTC_SizeNode)ftcnode;
126     FTC_Scaler    scaler  = (FTC_Scaler)ftcscaler;
127     FTC_Manager   manager = (FTC_Manager)ftcmanager;
128
129
130     node->scaler = scaler[0];
131
132     return ftc_scaler_lookup_size( manager, scaler, &node->size );
133   }
134
135
136   FT_CALLBACK_DEF( FT_Error )
137   ftc_size_node_reset( FTC_MruNode  ftcnode,
138                        FT_Pointer   ftcscaler,
139                        FT_Pointer   ftcmanager )
140   {
141     FTC_SizeNode  node    = (FTC_SizeNode)ftcnode;
142     FTC_Scaler    scaler  = (FTC_Scaler)ftcscaler;
143     FTC_Manager   manager = (FTC_Manager)ftcmanager;
144
145
146     FT_Done_Size( node->size );
147
148     node->scaler = scaler[0];
149
150     return ftc_scaler_lookup_size( manager, scaler, &node->size );
151   }
152
153
154   FT_CALLBACK_TABLE_DEF
155   const FTC_MruListClassRec  ftc_size_list_class =
156   {
157     sizeof ( FTC_SizeNodeRec ),
158     ftc_size_node_compare,
159     ftc_size_node_init,
160     ftc_size_node_reset,
161     ftc_size_node_done
162   };
163
164
165   /* helper function used by ftc_face_node_done */
166   static FT_Bool
167   ftc_size_node_compare_faceid( FTC_MruNode  ftcnode,
168                                 FT_Pointer   ftcface_id )
169   {
170     FTC_SizeNode  node    = (FTC_SizeNode)ftcnode;
171     FTC_FaceID    face_id = (FTC_FaceID)ftcface_id;
172
173
174     return FT_BOOL( node->scaler.face_id == face_id );
175   }
176
177
178   /* documentation is in ftcache.h */
179
180   FT_EXPORT_DEF( FT_Error )
181   FTC_Manager_LookupSize( FTC_Manager  manager,
182                           FTC_Scaler   scaler,
183                           FT_Size     *asize )
184   {
185     FT_Error     error;
186     FTC_MruNode  mrunode;
187
188
189     if ( asize == NULL )
190       return FTC_Err_Invalid_Argument;
191
192     *asize = NULL;
193
194     if ( !manager )
195       return FTC_Err_Invalid_Cache_Handle;
196
197 #ifdef FTC_INLINE
198
199     FTC_MRULIST_LOOKUP_CMP( &manager->sizes, scaler, ftc_size_node_compare,
200                             mrunode, error );
201
202 #else
203     error = FTC_MruList_Lookup( &manager->sizes, scaler, &mrunode );
204 #endif
205
206     if ( !error )
207       *asize = FTC_SIZE_NODE( mrunode )->size;
208
209     return error;
210   }
211
212
213   /*************************************************************************/
214   /*************************************************************************/
215   /*****                                                               *****/
216   /*****                    FACE MRU IMPLEMENTATION                    *****/
217   /*****                                                               *****/
218   /*************************************************************************/
219   /*************************************************************************/
220
221   typedef struct  FTC_FaceNodeRec_
222   {
223     FTC_MruNodeRec  node;
224     FTC_FaceID      face_id;
225     FT_Face         face;
226
227   } FTC_FaceNodeRec, *FTC_FaceNode;
228
229 #define FTC_FACE_NODE( x ) ( ( FTC_FaceNode )( x ) )
230
231
232   FT_CALLBACK_DEF( FT_Error )
233   ftc_face_node_init( FTC_MruNode  ftcnode,
234                       FT_Pointer   ftcface_id,
235                       FT_Pointer   ftcmanager )
236   {
237     FTC_FaceNode  node    = (FTC_FaceNode)ftcnode;
238     FTC_FaceID    face_id = (FTC_FaceID)ftcface_id;
239     FTC_Manager   manager = (FTC_Manager)ftcmanager;
240     FT_Error      error;
241
242
243     node->face_id = face_id;
244
245     error = manager->request_face( face_id,
246                                    manager->library,
247                                    manager->request_data,
248                                    &node->face );
249     if ( !error )
250     {
251       /* destroy initial size object; it will be re-created later */
252       if ( node->face->size )
253         FT_Done_Size( node->face->size );
254     }
255
256     return error;
257   }
258
259
260   FT_CALLBACK_DEF( void )
261   ftc_face_node_done( FTC_MruNode  ftcnode,
262                       FT_Pointer   ftcmanager )
263   {
264     FTC_FaceNode  node    = (FTC_FaceNode)ftcnode;
265     FTC_Manager   manager = (FTC_Manager)ftcmanager;
266
267
268     /* we must begin by removing all scalers for the target face */
269     /* from the manager's list                                   */
270     FTC_MruList_RemoveSelection( &manager->sizes,
271                                  ftc_size_node_compare_faceid,
272                                  node->face_id );
273
274     /* all right, we can discard the face now */
275     FT_Done_Face( node->face );
276     node->face    = NULL;
277     node->face_id = NULL;
278   }
279
280
281   FT_CALLBACK_DEF( FT_Bool )
282   ftc_face_node_compare( FTC_MruNode  ftcnode,
283                          FT_Pointer   ftcface_id )
284   {
285     FTC_FaceNode  node    = (FTC_FaceNode)ftcnode;
286     FTC_FaceID    face_id = (FTC_FaceID)ftcface_id;
287
288
289     return FT_BOOL( node->face_id == face_id );
290   }
291
292
293   FT_CALLBACK_TABLE_DEF
294   const FTC_MruListClassRec  ftc_face_list_class =
295   {
296     sizeof ( FTC_FaceNodeRec),
297
298     ftc_face_node_compare,
299     ftc_face_node_init,
300     0,                          /* FTC_MruNode_ResetFunc */
301     ftc_face_node_done
302   };
303
304
305   /* documentation is in ftcache.h */
306
307   FT_EXPORT_DEF( FT_Error )
308   FTC_Manager_LookupFace( FTC_Manager  manager,
309                           FTC_FaceID   face_id,
310                           FT_Face     *aface )
311   {
312     FT_Error     error;
313     FTC_MruNode  mrunode;
314
315
316     if ( aface == NULL )
317       return FTC_Err_Invalid_Argument;
318
319     *aface = NULL;
320
321     if ( !manager )
322       return FTC_Err_Invalid_Cache_Handle;
323
324     /* we break encapsulation for the sake of speed */
325 #ifdef FTC_INLINE
326
327     FTC_MRULIST_LOOKUP_CMP( &manager->faces, face_id, ftc_face_node_compare,
328                             mrunode, error );
329
330 #else
331     error = FTC_MruList_Lookup( &manager->faces, face_id, &mrunode );
332 #endif
333
334     if ( !error )
335       *aface = FTC_FACE_NODE( mrunode )->face;
336
337     return error;
338   }
339
340
341   /*************************************************************************/
342   /*************************************************************************/
343   /*****                                                               *****/
344   /*****                    CACHE MANAGER ROUTINES                     *****/
345   /*****                                                               *****/
346   /*************************************************************************/
347   /*************************************************************************/
348
349
350   /* documentation is in ftcache.h */
351
352   FT_EXPORT_DEF( FT_Error )
353   FTC_Manager_New( FT_Library          library,
354                    FT_UInt             max_faces,
355                    FT_UInt             max_sizes,
356                    FT_ULong            max_bytes,
357                    FTC_Face_Requester  requester,
358                    FT_Pointer          req_data,
359                    FTC_Manager        *amanager )
360   {
361     FT_Error     error;
362     FT_Memory    memory;
363     FTC_Manager  manager = 0;
364
365
366     if ( !library )
367       return FTC_Err_Invalid_Library_Handle;
368
369     memory = library->memory;
370
371     if ( FT_NEW( manager ) )
372       goto Exit;
373
374     if ( max_faces == 0 )
375       max_faces = FTC_MAX_FACES_DEFAULT;
376
377     if ( max_sizes == 0 )
378       max_sizes = FTC_MAX_SIZES_DEFAULT;
379
380     if ( max_bytes == 0 )
381       max_bytes = FTC_MAX_BYTES_DEFAULT;
382
383     manager->library      = library;
384     manager->memory       = memory;
385     manager->max_weight   = max_bytes;
386
387     manager->request_face = requester;
388     manager->request_data = req_data;
389
390     FTC_MruList_Init( &manager->faces,
391                       &ftc_face_list_class,
392                       max_faces,
393                       manager,
394                       memory );
395
396     FTC_MruList_Init( &manager->sizes,
397                       &ftc_size_list_class,
398                       max_sizes,
399                       manager,
400                       memory );
401
402     *amanager = manager;
403
404   Exit:
405     return error;
406   }
407
408
409   /* documentation is in ftcache.h */
410
411   FT_EXPORT_DEF( void )
412   FTC_Manager_Done( FTC_Manager  manager )
413   {
414     FT_Memory  memory;
415     FT_UInt    idx;
416
417
418     if ( !manager || !manager->library )
419       return;
420
421     memory = manager->memory;
422
423     /* now discard all caches */
424     for (idx = manager->num_caches; idx-- > 0; )
425     {
426       FTC_Cache  cache = manager->caches[idx];
427
428
429       if ( cache )
430       {
431         cache->clazz.cache_done( cache );
432         FT_FREE( cache );
433         manager->caches[idx] = NULL;
434       }
435     }
436     manager->num_caches = 0;
437
438     /* discard faces and sizes */
439     FTC_MruList_Done( &manager->sizes );
440     FTC_MruList_Done( &manager->faces );
441
442     manager->library = NULL;
443     manager->memory  = NULL;
444
445     FT_FREE( manager );
446   }
447
448
449   /* documentation is in ftcache.h */
450
451   FT_EXPORT_DEF( void )
452   FTC_Manager_Reset( FTC_Manager  manager )
453   {
454     if ( manager )
455     {
456       FTC_MruList_Reset( &manager->sizes );
457       FTC_MruList_Reset( &manager->faces );
458     }
459     /* XXX: FIXME: flush the caches? */
460   }
461
462
463 #ifdef FT_DEBUG_ERROR
464
465   static void
466   FTC_Manager_Check( FTC_Manager  manager )
467   {
468     FTC_Node  node, first;
469
470
471     first = manager->nodes_list;
472
473     /* check node weights */
474     if ( first )
475     {
476       FT_ULong  weight = 0;
477
478
479       node = first;
480
481       do
482       {
483         FTC_Cache  cache = manager->caches[node->cache_index];
484
485
486         if ( (FT_UInt)node->cache_index >= manager->num_caches )
487           FT_TRACE0(( "FTC_Manager_Check: invalid node (cache index = %ld\n",
488                       node->cache_index ));
489         else
490           weight += cache->clazz.node_weight( node, cache );
491
492         node = FTC_NODE__NEXT( node );
493
494       } while ( node != first );
495
496       if ( weight != manager->cur_weight )
497         FT_TRACE0(( "FTC_Manager_Check: invalid weight %ld instead of %ld\n",
498                     manager->cur_weight, weight ));
499     }
500
501     /* check circular list */
502     if ( first )
503     {
504       FT_UFast  count = 0;
505
506
507       node = first;
508       do
509       {
510         count++;
511         node = FTC_NODE__NEXT( node );
512
513       } while ( node != first );
514
515       if ( count != manager->num_nodes )
516         FT_TRACE0(( "FTC_Manager_Check:"
517                     " invalid cache node count %d instead of %d\n",
518                     manager->num_nodes, count ));
519     }
520   }
521
522 #endif /* FT_DEBUG_ERROR */
523
524
525   /* `Compress' the manager's data, i.e., get rid of old cache nodes */
526   /* that are not referenced anymore in order to limit the total     */
527   /* memory used by the cache.                                       */
528
529   /* documentation is in ftcmanag.h */
530
531   FT_LOCAL_DEF( void )
532   FTC_Manager_Compress( FTC_Manager  manager )
533   {
534     FTC_Node   node, first;
535
536
537     if ( !manager )
538       return;
539
540     first = manager->nodes_list;
541
542 #ifdef FT_DEBUG_ERROR
543     FTC_Manager_Check( manager );
544
545     FT_TRACE0(( "compressing, weight = %ld, max = %ld, nodes = %d\n",
546                 manager->cur_weight, manager->max_weight,
547                 manager->num_nodes ));
548 #endif
549
550     if ( manager->cur_weight < manager->max_weight || first == NULL )
551       return;
552
553     /* go to last node -- it's a circular list */
554     node = FTC_NODE__PREV( first );
555     do
556     {
557       FTC_Node  prev;
558
559
560       prev = ( node == first ) ? NULL : FTC_NODE__PREV( node );
561
562       if ( node->ref_count <= 0 )
563         ftc_node_destroy( node, manager );
564
565       node = prev;
566
567     } while ( node && manager->cur_weight > manager->max_weight );
568   }
569
570
571   /* documentation is in ftcmanag.h */
572
573   FT_LOCAL_DEF( FT_Error )
574   FTC_Manager_RegisterCache( FTC_Manager      manager,
575                              FTC_CacheClass   clazz,
576                              FTC_Cache       *acache )
577   {
578     FT_Error   error = FTC_Err_Invalid_Argument;
579     FTC_Cache  cache = NULL;
580
581
582     if ( manager && clazz && acache )
583     {
584       FT_Memory  memory = manager->memory;
585
586
587       if ( manager->num_caches >= FTC_MAX_CACHES )
588       {
589         error = FTC_Err_Too_Many_Caches;
590         FT_ERROR(( "FTC_Manager_RegisterCache:"
591                    " too many registered caches\n" ));
592         goto Exit;
593       }
594
595       if ( !FT_ALLOC( cache, clazz->cache_size ) )
596       {
597         cache->manager   = manager;
598         cache->memory    = memory;
599         cache->clazz     = clazz[0];
600         cache->org_class = clazz;
601
602         /* THIS IS VERY IMPORTANT!  IT WILL WRETCH THE MANAGER */
603         /* IF IT IS NOT SET CORRECTLY                          */
604         cache->index = manager->num_caches;
605
606         error = clazz->cache_init( cache );
607         if ( error )
608         {
609           clazz->cache_done( cache );
610           FT_FREE( cache );
611           goto Exit;
612         }
613
614         manager->caches[manager->num_caches++] = cache;
615       }
616     }
617
618   Exit:
619     if ( acache )
620       *acache = cache;
621     return error;
622   }
623
624
625   FT_LOCAL_DEF( FT_UInt )
626   FTC_Manager_FlushN( FTC_Manager  manager,
627                       FT_UInt      count )
628   {
629     FTC_Node  first = manager->nodes_list;
630     FTC_Node  node;
631     FT_UInt   result;
632
633
634     /* try to remove `count' nodes from the list */
635     if ( first == NULL )  /* empty list! */
636       return 0;
637
638     /* go to last node - it's a circular list */
639     node = FTC_NODE__PREV(first);
640     for ( result = 0; result < count; )
641     {
642       FTC_Node  prev = FTC_NODE__PREV( node );
643
644
645       /* don't touch locked nodes */
646       if ( node->ref_count <= 0 )
647       {
648         ftc_node_destroy( node, manager );
649         result++;
650       }
651
652       if ( node == first )
653         break;
654
655       node = prev;
656     }
657     return  result;
658   }
659
660
661   /* documentation is in ftcache.h */
662
663   FT_EXPORT_DEF( void )
664   FTC_Manager_RemoveFaceID( FTC_Manager  manager,
665                             FTC_FaceID   face_id )
666   {
667     FT_UInt  nn;
668
669     /* this will remove all FTC_SizeNode that correspond to
670      * the face_id as well
671      */
672     FTC_MruList_RemoveSelection( &manager->faces,
673                                  ftc_face_node_compare,
674                                  face_id );
675
676     for ( nn = 0; nn < manager->num_caches; nn++ )
677       FTC_Cache_RemoveFaceID( manager->caches[nn], face_id );
678   }
679
680
681   /* documentation is in ftcache.h */
682
683   FT_EXPORT_DEF( void )
684   FTC_Node_Unref( FTC_Node     node,
685                   FTC_Manager  manager )
686   {
687     if ( node && (FT_UInt)node->cache_index < manager->num_caches )
688       node->ref_count--;
689   }
690
691
692 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
693
694   FT_EXPORT_DEF( FT_Error )
695   FTC_Manager_Lookup_Face( FTC_Manager  manager,
696                            FTC_FaceID   face_id,
697                            FT_Face     *aface )
698   {
699     return FTC_Manager_LookupFace( manager, face_id, aface );
700   }
701
702
703   FT_EXPORT( FT_Error )
704   FTC_Manager_Lookup_Size( FTC_Manager  manager,
705                            FTC_Font     font,
706                            FT_Face     *aface,
707                            FT_Size     *asize )
708   {
709     FTC_ScalerRec  scaler;
710     FT_Error       error;
711     FT_Size        size;
712     FT_Face        face;
713
714
715     scaler.face_id = font->face_id;
716     scaler.width   = font->pix_width;
717     scaler.height  = font->pix_height;
718     scaler.pixel   = TRUE;
719     scaler.x_res   = 0;
720     scaler.y_res   = 0;
721
722     error = FTC_Manager_LookupSize( manager, &scaler, &size );
723     if ( error )
724     {
725       face = NULL;
726       size = NULL;
727     }
728     else
729       face = size->face;
730
731     if ( aface )
732       *aface = face;
733
734     if ( asize )
735       *asize = size;
736
737     return error;
738   }
739
740 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
741
742
743 /* END */