# This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details class Node: def __init__(self): self.name = "" self.children = {} # computed self.depth = 0 self.width = 0 self.offset = 0 def child(self, name): node = self.children.get(name) if not node: node = self.__class__() node.name = name self.children[name] = node return node def subtree(self): result = [self] offset = 0 while offset < len(result): p = result[offset] offset += 1 for c in p.children.values(): result.append(c) return result def escape(s): return s.replace("&", "&").replace("<", "<").replace(">", ">") def layout(root, widthcb): for n in reversed(root.subtree()): # propagate width to the parent n.width = widthcb(n) for c in n.children.values(): n.width += c.width # compute offset from parent for every child in width order (layout order) offset = 0 for c in sorted(n.children.values(), key = lambda x: x.width, reverse = True): c.offset = offset offset += c.width for n in root.subtree(): for c in n.children.values(): c.depth = n.depth + 1 c.offset += n.offset # svg template (stolen from framegraph.pl) template = r""" $title Reset Zoom Search ic """ def namehash(s): # FNV-1a hval = 0x811c9dc5 for ch in s: hval = hval ^ ord(ch) hval = hval * 0x01000193 hval = hval % (2 ** 32) return (hval % 31337) / 31337.0 def display(root, title, colors, flip = False): if colors == "cold": gradient_start = "#eef2ee" gradient_end = "#e0ffe0" else: gradient_start = "#eeeeee" gradient_end = "#eeeeb0" maxdepth = 0 for n in root.subtree(): maxdepth = max(maxdepth, n.depth) svgheight = maxdepth * 16 + 3 * 16 + 2 * 16 print(template .replace("$title", title) .replace("$gradient-start", gradient_start) .replace("$gradient-end", gradient_end) .replace("$height", str(svgheight)) .replace("$status", str((svgheight - 16 + 3 if flip else 3 * 16 - 3))) .replace("$flip", str(int(flip))) ) framewidth = 1200 - 20 def pixels(x): return float(x) / root.width * framewidth if root.width > 0 else 0 for n in root.subtree(): if pixels(n.width) < 0.1: continue x = 10 + pixels(n.offset) y = (maxdepth - 1 - n.depth if flip else n.depth) * 16 + 3 * 16 width = pixels(n.width) height = 15 if colors == "cold": fillr = 0 fillg = int(190 + 50 * namehash(n.name)) fillb = int(210 * namehash(n.name[::-1])) else: fillr = int(205 + 50 * namehash(n.name)) fillg = int(230 * namehash(n.name[::-1])) fillb = int(55 * namehash(n.name[::-2])) fill = "rgb({},{},{})".format(fillr, fillg, fillb) chars = width / (12 * 0.59) text = n.text() if chars >= 3: if chars < len(text): text = text[:int(chars-2)] + ".." else: text = "" print("") print("{}".format(escape(n.title()))) print("
{}
".format(escape(n.details(root)))) print("".format(x, y, width, height, fill)) print("{}".format(x + 3, y + 10.5, escape(text))) print("{}".format(escape(n.text()))) print("
") print("
\n
\n")