• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  *
3  * ftdebug.h
4  *
5  *   Debugging and logging component (specification).
6  *
7  * Copyright (C) 1996-2023 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  * IMPORTANT: A description of FreeType's debugging support can be
18  *             found in 'docs/DEBUG.TXT'.  Read it if you need to use or
19  *             understand this code.
20  *
21  */
22 
23 
24 #ifndef FTDEBUG_H_
25 #define FTDEBUG_H_
26 
27 
28 #include <ft2build.h>
29 #include FT_CONFIG_CONFIG_H
30 #include <freetype/freetype.h>
31 
32 #include "compiler-macros.h"
33 
34 #ifdef FT_DEBUG_LOGGING
35 #define DLG_STATIC
36 #include <dlg/output.h>
37 #include <dlg/dlg.h>
38 
39 #include <freetype/ftlogging.h>
40 #endif /* FT_DEBUG_LOGGING */
41 
42 
43 FT_BEGIN_HEADER
44 
45   /* force the definition of FT_DEBUG_LEVEL_TRACE if FT_DEBUG_LOGGING is */
46   /* already defined.                                                    */
47   /*                                                                     */
48 #ifdef FT_DEBUG_LOGGING
49 #undef  FT_DEBUG_LEVEL_TRACE
50 #define FT_DEBUG_LEVEL_TRACE
51 #endif
52 
53   /* force the definition of FT_DEBUG_LEVEL_ERROR if FT_DEBUG_LEVEL_TRACE */
54   /* is already defined; this simplifies the following #ifdefs            */
55   /*                                                                      */
56 #ifdef FT_DEBUG_LEVEL_TRACE
57 #undef  FT_DEBUG_LEVEL_ERROR
58 #define FT_DEBUG_LEVEL_ERROR
59 #endif
60 
61 
62   /**************************************************************************
63    *
64    * Define the trace enums as well as the trace levels array when they are
65    * needed.
66    *
67    */
68 
69 #ifdef FT_DEBUG_LEVEL_TRACE
70 
71 #define FT_TRACE_DEF( x )  trace_ ## x ,
72 
73   /* defining the enumeration */
74   typedef enum  FT_Trace_
75   {
76 #include <freetype/internal/fttrace.h>
77     trace_count
78 
79   } FT_Trace;
80 
81 
82   /* a pointer to the array of trace levels, */
83   /* provided by `src/base/ftdebug.c'        */
84   extern int*  ft_trace_levels;
85 
86 #undef FT_TRACE_DEF
87 
88 #endif /* FT_DEBUG_LEVEL_TRACE */
89 
90 
91   /**************************************************************************
92    *
93    * Define the FT_TRACE macro
94    *
95    * IMPORTANT!
96    *
97    * Each component must define the macro FT_COMPONENT to a valid FT_Trace
98    * value before using any TRACE macro.
99    *
100    * To get consistent logging output, there should be no newline character
101    * (i.e., '\n') or a single trailing one in the message string of
102    * `FT_TRACEx` and `FT_ERROR`.
103    */
104 
105 
106   /*************************************************************************
107    *
108    * If FT_DEBUG_LOGGING is enabled, tracing messages are sent to dlg's API.
109    * If FT_DEBUG_LOGGING is disabled, tracing messages are sent to
110    * `FT_Message` (defined in ftdebug.c).
111    */
112 #ifdef FT_DEBUG_LOGGING
113 
114   /* we need two macros to convert the names of `FT_COMPONENT` to a string */
115 #define FT_LOGGING_TAG( x )   FT_LOGGING_TAG_( x )
116 #define FT_LOGGING_TAG_( x )  #x
117 
118   /* we need two macros to convert the component and the trace level */
119   /* to a string that combines them                                  */
120 #define FT_LOGGING_TAGX( x, y )   FT_LOGGING_TAGX_( x, y )
121 #define FT_LOGGING_TAGX_( x, y )  #x ":" #y
122 
123 
124 #define FT_LOG( level, varformat )                                         \
125           do                                                               \
126           {                                                                \
127             const char*  dlg_tag = FT_LOGGING_TAGX( FT_COMPONENT, level ); \
128                                                                            \
129                                                                            \
130             ft_add_tag( dlg_tag );                                         \
131             if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] >= level ) \
132             {                                                              \
133               if ( custom_output_handler != NULL )                         \
134                 FT_Logging_Callback varformat;                             \
135               else                                                         \
136                 dlg_trace varformat;                                       \
137             }                                                              \
138             ft_remove_tag( dlg_tag );                                      \
139           } while( 0 )
140 
141 #else /* !FT_DEBUG_LOGGING */
142 
143 #define FT_LOG( level, varformat )                                         \
144           do                                                               \
145           {                                                                \
146             if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] >= level ) \
147               FT_Message varformat;                                        \
148           } while ( 0 )
149 
150 #endif /* !FT_DEBUG_LOGGING */
151 
152 
153 #ifdef FT_DEBUG_LEVEL_TRACE
154 
155   /* we need two macros here to make cpp expand `FT_COMPONENT' */
156 #define FT_TRACE_COMP( x )   FT_TRACE_COMP_( x )
157 #define FT_TRACE_COMP_( x )  trace_ ## x
158 
159 #define FT_TRACE( level, varformat )  FT_LOG( level, varformat )
160 
161 #else /* !FT_DEBUG_LEVEL_TRACE */
162 
163 #define FT_TRACE( level, varformat )  do { } while ( 0 )      /* nothing */
164 
165 #endif /* !FT_DEBUG_LEVEL_TRACE */
166 
167 
168   /**************************************************************************
169    *
170    * @function:
171    *   FT_Trace_Get_Count
172    *
173    * @description:
174    *   Return the number of available trace components.
175    *
176    * @return:
177    *   The number of trace components.  0 if FreeType 2 is not built with
178    *   FT_DEBUG_LEVEL_TRACE definition.
179    *
180    * @note:
181    *   This function may be useful if you want to access elements of the
182    *   internal trace levels array by an index.
183    */
184   FT_BASE( FT_Int )
185   FT_Trace_Get_Count( void );
186 
187 
188   /**************************************************************************
189    *
190    * @function:
191    *   FT_Trace_Get_Name
192    *
193    * @description:
194    *   Return the name of a trace component.
195    *
196    * @input:
197    *   The index of the trace component.
198    *
199    * @return:
200    *   The name of the trace component.  This is a statically allocated
201    *   C~string, so do not free it after use.  `NULL` if FreeType is not
202    *   built with FT_DEBUG_LEVEL_TRACE definition.
203    *
204    * @note:
205    *   Use @FT_Trace_Get_Count to get the number of available trace
206    *   components.
207    */
208   FT_BASE( const char* )
209   FT_Trace_Get_Name( FT_Int  idx );
210 
211 
212   /**************************************************************************
213    *
214    * @function:
215    *   FT_Trace_Disable
216    *
217    * @description:
218    *   Switch off tracing temporarily.  It can be activated again with
219    *   @FT_Trace_Enable.
220    */
221   FT_BASE( void )
222   FT_Trace_Disable( void );
223 
224 
225   /**************************************************************************
226    *
227    * @function:
228    *   FT_Trace_Enable
229    *
230    * @description:
231    *   Activate tracing.  Use it after tracing has been switched off with
232    *   @FT_Trace_Disable.
233    */
234   FT_BASE( void )
235   FT_Trace_Enable( void );
236 
237 
238   /**************************************************************************
239    *
240    * You need two opening and closing parentheses!
241    *
242    * Example: FT_TRACE0(( "Value is %i", foo ))
243    *
244    * Output of the FT_TRACEX macros is sent to stderr.
245    *
246    */
247 
248 #define FT_TRACE0( varformat )  FT_TRACE( 0, varformat )
249 #define FT_TRACE1( varformat )  FT_TRACE( 1, varformat )
250 #define FT_TRACE2( varformat )  FT_TRACE( 2, varformat )
251 #define FT_TRACE3( varformat )  FT_TRACE( 3, varformat )
252 #define FT_TRACE4( varformat )  FT_TRACE( 4, varformat )
253 #define FT_TRACE5( varformat )  FT_TRACE( 5, varformat )
254 #define FT_TRACE6( varformat )  FT_TRACE( 6, varformat )
255 #define FT_TRACE7( varformat )  FT_TRACE( 7, varformat )
256 
257 
258   /**************************************************************************
259    *
260    * Define the FT_ERROR macro.
261    *
262    * Output of this macro is sent to stderr.
263    *
264    */
265 
266 #ifdef FT_DEBUG_LEVEL_ERROR
267 
268   /**************************************************************************
269    *
270    * If FT_DEBUG_LOGGING is enabled, error messages are sent to dlg's API.
271    * If FT_DEBUG_LOGGING is disabled, error messages are sent to `FT_Message`
272    * (defined in ftdebug.c).
273    *
274    */
275 #ifdef FT_DEBUG_LOGGING
276 
277 #define FT_ERROR( varformat )                                      \
278           do                                                       \
279           {                                                        \
280             const char*  dlg_tag = FT_LOGGING_TAG( FT_COMPONENT ); \
281                                                                    \
282                                                                    \
283             ft_add_tag( dlg_tag );                                 \
284             dlg_trace varformat;                                   \
285             ft_remove_tag( dlg_tag );                              \
286           } while ( 0 )
287 
288 #else /* !FT_DEBUG_LOGGING */
289 
290 #define FT_ERROR( varformat )  FT_Message varformat
291 
292 #endif /* !FT_DEBUG_LOGGING */
293 
294 
295 #else  /* !FT_DEBUG_LEVEL_ERROR */
296 
297 #define FT_ERROR( varformat )  do { } while ( 0 )      /* nothing */
298 
299 #endif /* !FT_DEBUG_LEVEL_ERROR */
300 
301 
302   /**************************************************************************
303    *
304    * Define the FT_ASSERT and FT_THROW macros.  The call to `FT_Throw` makes
305    * it possible to easily set a breakpoint at this function.
306    *
307    */
308 
309 #ifdef FT_DEBUG_LEVEL_ERROR
310 
311 #define FT_ASSERT( condition )                                      \
312           do                                                        \
313           {                                                         \
314             if ( !( condition ) )                                   \
315               FT_Panic( "assertion failed on line %d of file %s\n", \
316                         __LINE__, __FILE__ );                       \
317           } while ( 0 )
318 
319 #define FT_THROW( e )                                   \
320           ( FT_Throw( FT_ERR_CAT( FT_ERR_PREFIX, e ),   \
321                       __LINE__,                         \
322                       __FILE__ )                      | \
323             FT_ERR_CAT( FT_ERR_PREFIX, e )            )
324 
325 #else /* !FT_DEBUG_LEVEL_ERROR */
326 
327 #define FT_ASSERT( condition )  do { } while ( 0 )
328 
329 #define FT_THROW( e )  FT_ERR_CAT( FT_ERR_PREFIX, e )
330 
331 #endif /* !FT_DEBUG_LEVEL_ERROR */
332 
333 
334   /**************************************************************************
335    *
336    * Define `FT_Message` and `FT_Panic` when needed.
337    *
338    */
339 
340 #ifdef FT_DEBUG_LEVEL_ERROR
341 
342 #include "stdio.h"  /* for vfprintf() */
343 
344   /* print a message */
345   FT_BASE( void )
346   FT_Message( const char*  fmt,
347               ... );
348 
349   /* print a message and exit */
350   FT_BASE( void )
351   FT_Panic( const char*  fmt,
352             ... );
353 
354   /* report file name and line number of an error */
355   FT_BASE( int )
356   FT_Throw( FT_Error     error,
357             int          line,
358             const char*  file );
359 
360 #endif /* FT_DEBUG_LEVEL_ERROR */
361 
362 
363   FT_BASE( void )
364   ft_debug_init( void );
365 
366 
367 #ifdef FT_DEBUG_LOGGING
368 
369   /**************************************************************************
370    *
371    * 'dlg' uses output handlers to control how and where log messages are
372    * printed.  Therefore we need to define a default output handler for
373    * FreeType.
374    */
375   FT_BASE( void )
376   ft_log_handler( const struct dlg_origin*  origin,
377                   const char*               string,
378                   void*                     data );
379 
380 
381   /**************************************************************************
382    *
383    * 1. `ft_default_log_handler` stores the function pointer that is used
384    *    internally by FreeType to print logs to a file.
385    *
386    * 2. `custom_output_handler` stores the function pointer to the callback
387    *    function provided by the user.
388    *
389    * It is defined in `ftdebug.c`.
390    */
391   extern dlg_handler            ft_default_log_handler;
392   extern FT_Custom_Log_Handler  custom_output_handler;
393 
394 
395   /**************************************************************************
396    *
397    * If FT_DEBUG_LOGGING macro is enabled, FreeType needs to initialize and
398    * un-initialize `FILE*`.
399    *
400    * These functions are defined in `ftdebug.c`.
401    */
402   FT_BASE( void )
403   ft_logging_init( void );
404 
405   FT_BASE( void )
406   ft_logging_deinit( void );
407 
408 
409   /**************************************************************************
410    *
411    * For printing the name of `FT_COMPONENT` along with the actual log we
412    * need to add a tag with the name of `FT_COMPONENT`.
413    *
414    * These functions are defined in `ftdebug.c`.
415    */
416   FT_BASE( void )
417   ft_add_tag( const char*  tag );
418 
419   FT_BASE( void )
420   ft_remove_tag( const char*  tag );
421 
422 
423   /**************************************************************************
424    *
425    * A function to print log data using a custom callback logging function
426    * (which is set using `FT_Set_Log_Handler`).
427    *
428    * This function is defined in `ftdebug.c`.
429    */
430   FT_BASE( void )
431   FT_Logging_Callback( const char*  fmt,
432                        ... );
433 
434 #endif /* FT_DEBUG_LOGGING */
435 
436 
437 FT_END_HEADER
438 
439 #endif /* FTDEBUG_H_ */
440 
441 
442 /* END */
443