Imported Upstream version 2.13.2
[platform/upstream/freetype2.git] / include / freetype / internal / ftdebug.h
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 */