1package theme23import "src.rest/cat/012/internal/sheet"45// Cell borders are drawn with box-drawing characters, so lines of6// different weights meet in the joints a terminal font draws for them.78// Junction returns the character drawn where cell edges meet, given the9// line of each arm: up, down, left and right (LineNone for no arm). A10// lone arm draws the whole line through, and no arm a space. Unicode11// joins double lines only to single ones: a single arm on the same axis12// as a double draws double, and where a double line meets a thick one13// the joint is drawn thick, the heavier look, as Unicode has no joint of14// the two (╠ between ┃ lines reads as a stray mark). The double line15// then starts beside the joint with a thick stub (see Bridges).16func Junction(up, down, left, right sheet.Line) string {17 arms := joinable([4]sheet.Line{up, down, left, right})18 n := 019 for _, a := range arms {20 if a != sheet.LineNone {21 n++22 }23 }24 switch {25 case n == 0:26 return " "27 case n == 1 && (arms[0] != sheet.LineNone || arms[1] != sheet.LineNone):28 arms[0], arms[1] = max(arms[0], arms[1]), max(arms[0], arms[1])29 case n == 1:30 arms[2], arms[3] = max(arms[2], arms[3]), max(arms[2], arms[3])31 }32 if g, ok := junctions[arms]; ok {33 return g34 }35 for i, a := range arms { // not in Unicode: draw it light36 arms[i] = min(a, sheet.LineThin)37 }38 return junctions[arms]39}4041// Bridges reports which of a junction's horizontal arms are double lines42// it draws thick, meeting a thick line: the line beside the joint on43// that side starts with a thick stub (━═══), so the joint's arm runs on44// into it rather than stopping at a gap.45func Bridges(up, down, left, right sheet.Line) (onLeft, onRight bool) {46 if !mixed([4]sheet.Line{up, down, left, right}) {47 return false, false48 }49 return left == sheet.LineDouble, right == sheet.LineDouble50}5152// Mixed reports whether a junction of these arms joins double and thick53// lines, which it draws thick.54func Mixed(up, down, left, right sheet.Line) bool {55 return mixed([4]sheet.Line{up, down, left, right})56}5758// mixed reports whether a junction joins double and thick lines.59func mixed(arms [4]sheet.Line) bool {60 double, thick := false, false61 for _, a := range arms {62 double = double || a == sheet.LineDouble63 thick = thick || a == sheet.LineThick64 }65 return double && thick66}6768// joinable turns the arms of a junction with a double line into ones69// Unicode has a character for.70func joinable(arms [4]sheet.Line) [4]sheet.Line {71 if mixed(arms) {72 for i, a := range arms {73 if a == sheet.LineDouble {74 arms[i] = sheet.LineThick75 }76 }77 return arms78 }79 double := false80 for _, a := range arms {81 double = double || a == sheet.LineDouble82 }83 if !double {84 return arms85 }86 for _, axis := range [2][2]int{{0, 1}, {2, 3}} {87 x, y := &arms[axis[0]], &arms[axis[1]]88 if *x != sheet.LineNone && *y != sheet.LineNone && *x != *y {89 *x, *y = sheet.LineDouble, sheet.LineDouble90 }91 }92 return arms93}9495// junctions are Unicode's box-drawing characters by the line of their96// arms: up, down, left, right.97var junctions = map[[4]sheet.Line]string{98 {0, 0, 1, 1}: "─",99 {0, 0, 1, 2}: "╼",100 {0, 0, 2, 1}: "╾",101 {0, 0, 2, 2}: "━",102 {0, 0, 3, 3}: "═",103 {0, 1, 0, 1}: "┌",104 {0, 1, 0, 2}: "┍",105 {0, 1, 0, 3}: "╒",106 {0, 1, 1, 0}: "┐",107 {0, 1, 1, 1}: "┬",108 {0, 1, 1, 2}: "┮",109 {0, 1, 2, 0}: "┑",110 {0, 1, 2, 1}: "┭",111 {0, 1, 2, 2}: "┯",112 {0, 1, 3, 0}: "╕",113 {0, 1, 3, 3}: "╤",114 {0, 2, 0, 1}: "┎",115 {0, 2, 0, 2}: "┏",116 {0, 2, 1, 0}: "┒",117 {0, 2, 1, 1}: "┰",118 {0, 2, 1, 2}: "┲",119 {0, 2, 2, 0}: "┓",120 {0, 2, 2, 1}: "┱",121 {0, 2, 2, 2}: "┳",122 {0, 3, 0, 1}: "╓",123 {0, 3, 0, 3}: "╔",124 {0, 3, 1, 0}: "╖",125 {0, 3, 1, 1}: "╥",126 {0, 3, 3, 0}: "╗",127 {0, 3, 3, 3}: "╦",128 {1, 0, 0, 1}: "└",129 {1, 0, 0, 2}: "┕",130 {1, 0, 0, 3}: "╘",131 {1, 0, 1, 0}: "┘",132 {1, 0, 1, 1}: "┴",133 {1, 0, 1, 2}: "┶",134 {1, 0, 2, 0}: "┙",135 {1, 0, 2, 1}: "┵",136 {1, 0, 2, 2}: "┷",137 {1, 0, 3, 0}: "╛",138 {1, 0, 3, 3}: "╧",139 {1, 1, 0, 0}: "│",140 {1, 1, 0, 1}: "├",141 {1, 1, 0, 2}: "┝",142 {1, 1, 0, 3}: "╞",143 {1, 1, 1, 0}: "┤",144 {1, 1, 1, 1}: "┼",145 {1, 1, 1, 2}: "┾",146 {1, 1, 2, 0}: "┥",147 {1, 1, 2, 1}: "┽",148 {1, 1, 2, 2}: "┿",149 {1, 1, 3, 0}: "╡",150 {1, 1, 3, 3}: "╪",151 {1, 2, 0, 0}: "╽",152 {1, 2, 0, 1}: "┟",153 {1, 2, 0, 2}: "┢",154 {1, 2, 1, 0}: "┧",155 {1, 2, 1, 1}: "╁",156 {1, 2, 1, 2}: "╆",157 {1, 2, 2, 0}: "┪",158 {1, 2, 2, 1}: "╅",159 {1, 2, 2, 2}: "╈",160 {2, 0, 0, 1}: "┖",161 {2, 0, 0, 2}: "┗",162 {2, 0, 1, 0}: "┚",163 {2, 0, 1, 1}: "┸",164 {2, 0, 1, 2}: "┺",165 {2, 0, 2, 0}: "┛",166 {2, 0, 2, 1}: "┹",167 {2, 0, 2, 2}: "┻",168 {2, 1, 0, 0}: "╿",169 {2, 1, 0, 1}: "┞",170 {2, 1, 0, 2}: "┡",171 {2, 1, 1, 0}: "┦",172 {2, 1, 1, 1}: "╀",173 {2, 1, 1, 2}: "╄",174 {2, 1, 2, 0}: "┩",175 {2, 1, 2, 1}: "╃",176 {2, 1, 2, 2}: "╇",177 {2, 2, 0, 0}: "┃",178 {2, 2, 0, 1}: "┠",179 {2, 2, 0, 2}: "┣",180 {2, 2, 1, 0}: "┨",181 {2, 2, 1, 1}: "╂",182 {2, 2, 1, 2}: "╊",183 {2, 2, 2, 0}: "┫",184 {2, 2, 2, 1}: "╉",185 {2, 2, 2, 2}: "╋",186 {3, 0, 0, 1}: "╙",187 {3, 0, 0, 3}: "╚",188 {3, 0, 1, 0}: "╜",189 {3, 0, 1, 1}: "╨",190 {3, 0, 3, 0}: "╝",191 {3, 0, 3, 3}: "╩",192 {3, 3, 0, 0}: "║",193 {3, 3, 0, 1}: "╟",194 {3, 3, 0, 3}: "╠",195 {3, 3, 1, 0}: "╢",196 {3, 3, 1, 1}: "╫",197 {3, 3, 3, 0}: "╣",198 {3, 3, 3, 3}: "╬",199}