An efficient way of decorating all parenthesis in a line

If someone is still interested, it turned out to be not too slow.

I mainly check only PointDecorations offsetheight and then adjust the scaling of brackets/parenthesis:

{  
  getBracketDecorations(view) {
    const { doc } = view.state;
    const decorations = [];
    const stack = [];
    const rangeSets = view.state.facet(EditorView.atomicRanges).map((f)=>f(view));
    let height = -1;

    for (let pos = 0; pos < doc.length; pos += 1) {
      const char = doc.sliceString(pos, pos + 1);
      if (char === '(' || char === '[' || char === '{') {
        stack.push({ type: char, from: pos });
      } else if (char === ')' || char === ']' || char === '}') {
        const open = stack.pop();
        if (open && open.type === this.getMatchingBracket(char)) {
            height = -1;
            rangeSets.forEach((rangeSet) => {
            if (rangeSet.size > 0) {
                const cursor = rangeSet.iter();
                let v;
                do {
                  v = cursor.value;
                  if (!v) break;
                  const start = v.widget.visibleValue.pos;
                  const end   = v.widget.visibleValue.pos + v.widget.visibleValue.length;
                  if (start > open.from && end < pos+1 && v.widget.DOMElement) {
                    height = Math.max(height, v.widget.DOMElement.offsetHeight)
                  }
                  cursor.next();
                } while(v);
              }
          });

          if (height > 14) {
            decorations.push(
              Decoration.mark({ attributes: {style: `transform: scaleY(${height/14}); display:inline-block`} }).range(open.from, open.from + 1),
              Decoration.mark({ attributes: {style: `transform: scaleY(${height/14}); display:inline-block`} }).range(pos, pos + 1),
            );
          }
        }
      }
    }

    decorations.sort((a, b) => a.from - b.from || a.startSide - b.startSide);

    return Decoration.set(decorations);
  }

  getMatchingBracket(closingBracket) {
    switch (closingBracket) {
      case ')': return '(';
      case ']': return '[';
      case '}': return '{';
      default: return null;
    }
  }

}

However now there is another issue: scaled glyphs are horrible.

Therefore, I believe I need to recreate them using SVG/CSS magic with ReplacingDecorations instead of MarkDecorations. But this is another story…