Beautify debug output
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 06b7300..25475c5 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -171,17 +171,17 @@
     this->edit_count = 0;
     this->debug_depth = 0;
 
-    DEBUG_MSG (SANITIZE, this->blob,
-	       "init [%p..%p] (%lu bytes)",
-	       this->start, this->end,
-	       (unsigned long) (this->end - this->start));
+    DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, +1,
+		     "init [%p..%p] (%lu bytes)",
+		     this->start, this->end,
+		     (unsigned long) (this->end - this->start));
   }
 
   inline void finish (void)
   {
-    DEBUG_MSG (SANITIZE, this->blob,
-	       "fini [%p..%p] %u edit requests",
-	       this->start, this->end, this->edit_count);
+    DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, -1,
+		     "fini [%p..%p] %u edit requests",
+		     this->start, this->end, this->edit_count);
 
     hb_blob_destroy (this->blob);
     this->blob = NULL;
@@ -195,7 +195,7 @@
 	       p <= this->end &&
 	       (unsigned int) (this->end - p) >= len;
 
-    DEBUG_MSG_LEVEL (SANITIZE, this->blob, this->debug_depth + 1,
+    DEBUG_MSG_LEVEL (SANITIZE, this->blob, this->debug_depth + 1, 0,
 		     "range [%p..%p] (%d bytes) in [%p..%p] -> %s",
 		     p, p + len, len,
 		     this->start, this->end,
@@ -209,7 +209,7 @@
     const char *p = (const char *) base;
     bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
 
-    DEBUG_MSG_LEVEL (SANITIZE, this->blob, this->debug_depth + 1,
+    DEBUG_MSG_LEVEL (SANITIZE, this->blob, this->debug_depth + 1, 0,
 		     "array [%p..%p] (%d*%d=%ld bytes) in [%p..%p] -> %s",
 		     p, p + (record_size * len), record_size, len, (unsigned long) record_size * len,
 		     this->start, this->end,
@@ -229,7 +229,7 @@
     const char *p = (const char *) base;
     this->edit_count++;
 
-    DEBUG_MSG_LEVEL (SANITIZE, this->blob, this->debug_depth + 1,
+    DEBUG_MSG_LEVEL (SANITIZE, this->blob, this->debug_depth + 1, 0,
 		     "edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
 		     this->edit_count,
 		     p, p + len, len,
diff --git a/src/hb-private.hh b/src/hb-private.hh
index 07445c3..5511e39 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -503,18 +503,24 @@
 
 template <int max_level> inline bool /* always returns TRUE */
 _hb_debug_msg_va (const char *what,
-	       const void *obj,
-	       const char *func,
-	       bool indented,
-	       int level,
-	       const char *message,
-	       va_list ap)
+		  const void *obj,
+		  const char *func,
+		  bool indented,
+		  unsigned int level,
+		  int level_dir,
+		  const char *message,
+		  va_list ap)
 {
+  static const char bars[] = "││││││││││││││││││││││││││││││││││││││││";
+
   (void) (_hb_debug (level, max_level) &&
-	  fprintf (stderr, "%s", what) &&
-	  (obj && fprintf (stderr, "(%p)", obj), TRUE) &&
-	  fprintf (stderr, ": ") &&
-	  (indented && fprintf (stderr, "%-*d-> ", level + 1, level), TRUE) &&
+	  (fprintf (stderr, "%-10s", what ? what : ""), TRUE) &&
+	  ((obj && fprintf (stderr, "(%p) ", obj), TRUE) || fprintf (stderr, " %*s  ", (unsigned int) (2 * sizeof (void *)), ""), TRUE) &&
+	  (indented && fprintf (stderr, "%2d %s├%s",
+				level,
+				bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars), 3 * level),
+				level_dir ? (level_dir > 0 ? "╮" : "╯") : "╴"), TRUE) &&
+	  (!indented && fprintf (stderr, "   ├╴"), TRUE) &&
 	  (func && fprintf (stderr, "%s: ", func), TRUE) &&
 	  (vfprintf (stderr, message, ap), TRUE) &&
 	  fprintf (stderr, "\n"));
@@ -523,12 +529,13 @@
 }
 template <> inline bool /* always returns TRUE */
 _hb_debug_msg_va<0> (const char *what,
-		  const void *obj,
-		  const char *func,
-		  bool indented,
-		  int level,
-		  const char *message,
-		  va_list ap)
+		     const void *obj,
+		     const char *func,
+		     bool indented,
+		     unsigned int level,
+		     int level_dir,
+		     const char *message,
+		     va_list ap)
 {
   return TRUE;
 }
@@ -538,22 +545,24 @@
 	       const void *obj,
 	       const char *func,
 	       bool indented,
-	       int level,
+	       unsigned int level,
+	       int level_dir,
 	       const char *message,
-	       ...) HB_PRINTF_FUNC(6, 7);
+	       ...) HB_PRINTF_FUNC(7, 8);
 template <int max_level> inline bool /* always returns TRUE */
 _hb_debug_msg (const char *what,
 	       const void *obj,
 	       const char *func,
 	       bool indented,
-	       int level,
+	       unsigned int level,
+	       int level_dir,
 	       const char *message,
 	       ...)
 {
   va_list ap;
   va_start (ap, message);
 
-  bool ret = _hb_debug_msg_va<max_level> (what, obj, func, indented, level, message, ap);
+  bool ret = _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap);
 
   va_end (ap);
 
@@ -564,24 +573,26 @@
 		  const void *obj,
 		  const char *func,
 		  bool indented,
-		  int level,
+		  unsigned int level,
+		  int level_dir,
 		  const char *message,
-		  ...) HB_PRINTF_FUNC(6, 7);
+		  ...) HB_PRINTF_FUNC(7, 8);
 template <> inline bool /* always returns TRUE */
 _hb_debug_msg<0> (const char *what,
 		  const void *obj,
 		  const char *func,
 		  bool indented,
-		  int level,
+		  unsigned int level,
+		  int level_dir,
 		  const char *message,
 		  ...)
 {
   return TRUE;
 }
 
-#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL, TRUE, (LEVEL), __VA_ARGS__)
-#define DEBUG_MSG(WHAT, OBJ, ...) DEBUG_MSG_LEVEL (WHAT, OBJ, 0, __VA_ARGS__)
-#define DEBUG_MSG_FUNC(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, FALSE, 0, __VA_ARGS__)
+#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...)	_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL,    TRUE, (LEVEL), (LEVEL_DIR), __VA_ARGS__)
+#define DEBUG_MSG(WHAT, OBJ, ...) 				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL,    FALSE, 0, 0, __VA_ARGS__)
+#define DEBUG_MSG_FUNC(WHAT, OBJ, ...)				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, FALSE, 0, 0, __VA_ARGS__)
 
 
 /*
@@ -597,14 +608,19 @@
 				   const char *message,
 				   ...) : plevel(plevel_)
   {
-    if (max_level) ++*plevel;
+    if (plevel) ++*plevel;
 
     va_list ap;
     va_start (ap, message);
-    _hb_debug_msg_va<max_level> (what, obj, func, TRUE, *plevel, message, ap);
+    _hb_debug_msg_va<max_level> (what, obj, func, TRUE, plevel ? *plevel : 0, +1, message, ap);
     va_end (ap);
   }
-  ~hb_auto_trace_t (void) { if (max_level) --*plevel; }
+  ~hb_auto_trace_t (void)
+  {
+    _hb_debug_msg<max_level> (NULL, NULL, NULL, TRUE, plevel ? *plevel : 1, -1, " ");
+
+    if (plevel) --*plevel;
+  }
 
   private:
   unsigned int *plevel;