src/java.desktop/share/native/libfontmanager/harfbuzz/hb-debug.hh
changeset 48274 51772bf1fb0c
child 50352 25db2c8f3cf8
equal deleted inserted replaced
48273:e2065f7505eb 48274:51772bf1fb0c
       
     1 /*
       
     2  * Copyright © 2017  Google, Inc.
       
     3  *
       
     4  *  This is part of HarfBuzz, a text shaping library.
       
     5  *
       
     6  * Permission is hereby granted, without written agreement and without
       
     7  * license or royalty fees, to use, copy, modify, and distribute this
       
     8  * software and its documentation for any purpose, provided that the
       
     9  * above copyright notice and the following two paragraphs appear in
       
    10  * all copies of this software.
       
    11  *
       
    12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
       
    13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
       
    14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
       
    15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
       
    16  * DAMAGE.
       
    17  *
       
    18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
       
    19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
       
    20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
       
    21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
       
    22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
       
    23  *
       
    24  * Google Author(s): Behdad Esfahbod
       
    25  */
       
    26 
       
    27 #ifndef HB_DEBUG_HH
       
    28 #define HB_DEBUG_HH
       
    29 
       
    30 #include "hb-private.hh"
       
    31 
       
    32 
       
    33 #ifndef HB_DEBUG
       
    34 #define HB_DEBUG 0
       
    35 #endif
       
    36 
       
    37 static inline bool
       
    38 _hb_debug (unsigned int level,
       
    39            unsigned int max_level)
       
    40 {
       
    41   return level < max_level;
       
    42 }
       
    43 
       
    44 #define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
       
    45 #define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
       
    46 
       
    47 static inline void
       
    48 _hb_print_func (const char *func)
       
    49 {
       
    50   if (func)
       
    51   {
       
    52     unsigned int func_len = strlen (func);
       
    53     /* Skip "static" */
       
    54     if (0 == strncmp (func, "static ", 7))
       
    55       func += 7;
       
    56     /* Skip "typename" */
       
    57     if (0 == strncmp (func, "typename ", 9))
       
    58       func += 9;
       
    59     /* Skip return type */
       
    60     const char *space = strchr (func, ' ');
       
    61     if (space)
       
    62       func = space + 1;
       
    63     /* Skip parameter list */
       
    64     const char *paren = strchr (func, '(');
       
    65     if (paren)
       
    66       func_len = paren - func;
       
    67     fprintf (stderr, "%.*s", func_len, func);
       
    68   }
       
    69 }
       
    70 
       
    71 template <int max_level> static inline void
       
    72 _hb_debug_msg_va (const char *what,
       
    73                   const void *obj,
       
    74                   const char *func,
       
    75                   bool indented,
       
    76                   unsigned int level,
       
    77                   int level_dir,
       
    78                   const char *message,
       
    79                   va_list ap) HB_PRINTF_FUNC(7, 0);
       
    80 template <int max_level> static inline void
       
    81 _hb_debug_msg_va (const char *what,
       
    82                   const void *obj,
       
    83                   const char *func,
       
    84                   bool indented,
       
    85                   unsigned int level,
       
    86                   int level_dir,
       
    87                   const char *message,
       
    88                   va_list ap)
       
    89 {
       
    90   if (!_hb_debug (level, max_level))
       
    91     return;
       
    92 
       
    93   fprintf (stderr, "%-10s", what ? what : "");
       
    94 
       
    95   if (obj)
       
    96     fprintf (stderr, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned long) obj);
       
    97   else
       
    98     fprintf (stderr, " %*s  ", (unsigned int) (2 * sizeof (void *)), "");
       
    99 
       
   100   if (indented) {
       
   101 #define VBAR    "\342\224\202"  /* U+2502 BOX DRAWINGS LIGHT VERTICAL */
       
   102 #define VRBAR   "\342\224\234"  /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
       
   103 #define DLBAR   "\342\225\256"  /* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */
       
   104 #define ULBAR   "\342\225\257"  /* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */
       
   105 #define LBAR    "\342\225\264"  /* U+2574 BOX DRAWINGS LIGHT LEFT */
       
   106     static const char bars[] =
       
   107       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
       
   108       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
       
   109       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
       
   110       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
       
   111       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
       
   112     fprintf (stderr, "%2u %s" VRBAR "%s",
       
   113              level,
       
   114              bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
       
   115              level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
       
   116   } else
       
   117     fprintf (stderr, "   " VRBAR LBAR);
       
   118 
       
   119   _hb_print_func (func);
       
   120 
       
   121   if (message)
       
   122   {
       
   123     fprintf (stderr, ": ");
       
   124     vfprintf (stderr, message, ap);
       
   125   }
       
   126 
       
   127   fprintf (stderr, "\n");
       
   128 }
       
   129 template <> inline void
       
   130 _hb_debug_msg_va<0> (const char *what HB_UNUSED,
       
   131                      const void *obj HB_UNUSED,
       
   132                      const char *func HB_UNUSED,
       
   133                      bool indented HB_UNUSED,
       
   134                      unsigned int level HB_UNUSED,
       
   135                      int level_dir HB_UNUSED,
       
   136                      const char *message HB_UNUSED,
       
   137                      va_list ap HB_UNUSED) {}
       
   138 
       
   139 template <int max_level> static inline void
       
   140 _hb_debug_msg (const char *what,
       
   141                const void *obj,
       
   142                const char *func,
       
   143                bool indented,
       
   144                unsigned int level,
       
   145                int level_dir,
       
   146                const char *message,
       
   147                ...) HB_PRINTF_FUNC(7, 8);
       
   148 template <int max_level> static inline void
       
   149 _hb_debug_msg (const char *what,
       
   150                const void *obj,
       
   151                const char *func,
       
   152                bool indented,
       
   153                unsigned int level,
       
   154                int level_dir,
       
   155                const char *message,
       
   156                ...)
       
   157 {
       
   158   va_list ap;
       
   159   va_start (ap, message);
       
   160   _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap);
       
   161   va_end (ap);
       
   162 }
       
   163 template <> inline void
       
   164 _hb_debug_msg<0> (const char *what HB_UNUSED,
       
   165                   const void *obj HB_UNUSED,
       
   166                   const char *func HB_UNUSED,
       
   167                   bool indented HB_UNUSED,
       
   168                   unsigned int level HB_UNUSED,
       
   169                   int level_dir HB_UNUSED,
       
   170                   const char *message HB_UNUSED,
       
   171                   ...) HB_PRINTF_FUNC(7, 8);
       
   172 template <> inline void
       
   173 _hb_debug_msg<0> (const char *what HB_UNUSED,
       
   174                   const void *obj HB_UNUSED,
       
   175                   const char *func HB_UNUSED,
       
   176                   bool indented HB_UNUSED,
       
   177                   unsigned int level HB_UNUSED,
       
   178                   int level_dir HB_UNUSED,
       
   179                   const char *message HB_UNUSED,
       
   180                   ...) {}
       
   181 
       
   182 #define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...)       _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr,    true, (LEVEL), (LEVEL_DIR), __VA_ARGS__)
       
   183 #define DEBUG_MSG(WHAT, OBJ, ...)                               _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr,    false, 0, 0, __VA_ARGS__)
       
   184 #define DEBUG_MSG_FUNC(WHAT, OBJ, ...)                          _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__)
       
   185 
       
   186 
       
   187 /*
       
   188  * Printer
       
   189  */
       
   190 
       
   191 template <typename T>
       
   192 struct hb_printer_t {
       
   193   const char *print (const T&) { return "something"; }
       
   194 };
       
   195 
       
   196 template <>
       
   197 struct hb_printer_t<bool> {
       
   198   const char *print (bool v) { return v ? "true" : "false"; }
       
   199 };
       
   200 
       
   201 template <>
       
   202 struct hb_printer_t<hb_void_t> {
       
   203   const char *print (hb_void_t) { return ""; }
       
   204 };
       
   205 
       
   206 
       
   207 /*
       
   208  * Trace
       
   209  */
       
   210 
       
   211 template <typename T>
       
   212 static inline void _hb_warn_no_return (bool returned)
       
   213 {
       
   214   if (unlikely (!returned)) {
       
   215     fprintf (stderr, "OUCH, returned with no call to return_trace().  This is a bug, please report.\n");
       
   216   }
       
   217 }
       
   218 template <>
       
   219 /*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
       
   220 {}
       
   221 
       
   222 template <int max_level, typename ret_t>
       
   223 struct hb_auto_trace_t {
       
   224   explicit inline hb_auto_trace_t (unsigned int *plevel_,
       
   225                                    const char *what_,
       
   226                                    const void *obj_,
       
   227                                    const char *func,
       
   228                                    const char *message,
       
   229                                    ...) : plevel (plevel_), what (what_), obj (obj_), returned (false)
       
   230   {
       
   231     if (plevel) ++*plevel;
       
   232 
       
   233     va_list ap;
       
   234     va_start (ap, message);
       
   235     _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
       
   236     va_end (ap);
       
   237   }
       
   238   inline ~hb_auto_trace_t (void)
       
   239   {
       
   240     _hb_warn_no_return<ret_t> (returned);
       
   241     if (!returned) {
       
   242       _hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1, " ");
       
   243     }
       
   244     if (plevel) --*plevel;
       
   245   }
       
   246 
       
   247   inline ret_t ret (ret_t v, unsigned int line = 0)
       
   248   {
       
   249     if (unlikely (returned)) {
       
   250       fprintf (stderr, "OUCH, double calls to return_trace().  This is a bug, please report.\n");
       
   251       return v;
       
   252     }
       
   253 
       
   254     _hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1,
       
   255                               "return %s (line %d)",
       
   256                               hb_printer_t<ret_t>().print (v), line);
       
   257     if (plevel) --*plevel;
       
   258     plevel = nullptr;
       
   259     returned = true;
       
   260     return v;
       
   261   }
       
   262 
       
   263   private:
       
   264   unsigned int *plevel;
       
   265   const char *what;
       
   266   const void *obj;
       
   267   bool returned;
       
   268 };
       
   269 template <typename ret_t> /* Make sure we don't use hb_auto_trace_t when not tracing. */
       
   270 struct hb_auto_trace_t<0, ret_t>;
       
   271 
       
   272 /* For disabled tracing; optimize out everything.
       
   273  * https://github.com/behdad/harfbuzz/pull/605 */
       
   274 template <typename ret_t>
       
   275 struct hb_no_trace_t {
       
   276   inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
       
   277 };
       
   278 
       
   279 #define return_trace(RET) return trace.ret (RET, __LINE__)
       
   280 
       
   281 
       
   282 /*
       
   283  * Instances.
       
   284  */
       
   285 
       
   286 #ifndef HB_DEBUG_ARABIC
       
   287 #define HB_DEBUG_ARABIC (HB_DEBUG+0)
       
   288 #endif
       
   289 
       
   290 #ifndef HB_DEBUG_BLOB
       
   291 #define HB_DEBUG_BLOB (HB_DEBUG+0)
       
   292 #endif
       
   293 
       
   294 #ifndef HB_DEBUG_CORETEXT
       
   295 #define HB_DEBUG_CORETEXT (HB_DEBUG+0)
       
   296 #endif
       
   297 
       
   298 #ifndef HB_DEBUG_DIRECTWRITE
       
   299 #define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0)
       
   300 #endif
       
   301 
       
   302 #ifndef HB_DEBUG_FT
       
   303 #define HB_DEBUG_FT (HB_DEBUG+0)
       
   304 #endif
       
   305 
       
   306 #ifndef HB_DEBUG_GET_COVERAGE
       
   307 #define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0)
       
   308 #endif
       
   309 
       
   310 #ifndef HB_DEBUG_OBJECT
       
   311 #define HB_DEBUG_OBJECT (HB_DEBUG+0)
       
   312 #endif
       
   313 
       
   314 #ifndef HB_DEBUG_SHAPE_PLAN
       
   315 #define HB_DEBUG_SHAPE_PLAN (HB_DEBUG+0)
       
   316 #endif
       
   317 
       
   318 #ifndef HB_DEBUG_UNISCRIBE
       
   319 #define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
       
   320 #endif
       
   321 
       
   322 /*
       
   323  * With tracing.
       
   324  */
       
   325 
       
   326 #ifndef HB_DEBUG_APPLY
       
   327 #define HB_DEBUG_APPLY (HB_DEBUG+0)
       
   328 #endif
       
   329 #if HB_DEBUG_APPLY
       
   330 #define TRACE_APPLY(this) \
       
   331         hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
       
   332         (&c->debug_depth, c->get_name (), this, HB_FUNC, \
       
   333          "idx %d gid %u lookup %d", \
       
   334          c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index)
       
   335 #else
       
   336 #define TRACE_APPLY(this) hb_no_trace_t<bool> trace
       
   337 #endif
       
   338 
       
   339 #ifndef HB_DEBUG_CLOSURE
       
   340 #define HB_DEBUG_CLOSURE (HB_DEBUG+0)
       
   341 #endif
       
   342 #if HB_DEBUG_CLOSURE
       
   343 #define TRACE_CLOSURE(this) \
       
   344         hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
       
   345         (&c->debug_depth, c->get_name (), this, HB_FUNC, \
       
   346          "")
       
   347 #else
       
   348 #define TRACE_CLOSURE(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
       
   349 #endif
       
   350 
       
   351 #ifndef HB_DEBUG_COLLECT_GLYPHS
       
   352 #define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0)
       
   353 #endif
       
   354 #if HB_DEBUG_COLLECT_GLYPHS
       
   355 #define TRACE_COLLECT_GLYPHS(this) \
       
   356         hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \
       
   357         (&c->debug_depth, c->get_name (), this, HB_FUNC, \
       
   358          "")
       
   359 #else
       
   360 #define TRACE_COLLECT_GLYPHS(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
       
   361 #endif
       
   362 
       
   363 #ifndef HB_DEBUG_SANITIZE
       
   364 #define HB_DEBUG_SANITIZE (HB_DEBUG+0)
       
   365 #endif
       
   366 #if HB_DEBUG_SANITIZE
       
   367 #define TRACE_SANITIZE(this) \
       
   368         hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \
       
   369         (&c->debug_depth, c->get_name (), this, HB_FUNC, \
       
   370          "");
       
   371 #else
       
   372 #define TRACE_SANITIZE(this) hb_no_trace_t<bool> trace
       
   373 #endif
       
   374 
       
   375 #ifndef HB_DEBUG_SERIALIZE
       
   376 #define HB_DEBUG_SERIALIZE (HB_DEBUG+0)
       
   377 #endif
       
   378 #if HB_DEBUG_SERIALIZE
       
   379 #define TRACE_SERIALIZE(this) \
       
   380         hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \
       
   381         (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \
       
   382          "");
       
   383 #else
       
   384 #define TRACE_SERIALIZE(this) hb_no_trace_t<bool> trace
       
   385 #endif
       
   386 
       
   387 #ifndef HB_DEBUG_WOULD_APPLY
       
   388 #define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
       
   389 #endif
       
   390 #if HB_DEBUG_WOULD_APPLY
       
   391 #define TRACE_WOULD_APPLY(this) \
       
   392         hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \
       
   393         (&c->debug_depth, c->get_name (), this, HB_FUNC, \
       
   394          "%d glyphs", c->len);
       
   395 #else
       
   396 #define TRACE_WOULD_APPLY(this) hb_no_trace_t<bool> trace
       
   397 #endif
       
   398 
       
   399 #ifndef HB_DEBUG_DISPATCH
       
   400 #define HB_DEBUG_DISPATCH ( \
       
   401         HB_DEBUG_APPLY + \
       
   402         HB_DEBUG_CLOSURE + \
       
   403         HB_DEBUG_COLLECT_GLYPHS + \
       
   404         HB_DEBUG_SANITIZE + \
       
   405         HB_DEBUG_SERIALIZE + \
       
   406         HB_DEBUG_WOULD_APPLY + \
       
   407         0)
       
   408 #endif
       
   409 #if HB_DEBUG_DISPATCH
       
   410 #define TRACE_DISPATCH(this, format) \
       
   411         hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
       
   412         (&c->debug_depth, c->get_name (), this, HB_FUNC, \
       
   413          "format %d", (int) format);
       
   414 #else
       
   415 #define TRACE_DISPATCH(this, format) hb_no_trace_t<typename context_t::return_t> trace
       
   416 #endif
       
   417 
       
   418 
       
   419 #endif /* HB_DEBUG_HH */