chromium/third_party/blink/web_tests/http/tests/csspaint/border-color.html

<!DOCTYPE html>
<html>
<script src="resources/test-runner-paint-worklet.js"></script>

<style>
#example {
  max-width: 100px;
  --border-top-width: 10;
  --border-right-width: 20;
  --border-bottom-width: 30;
  --border-left-width: 40;
  --border-top-color: red;
  --border-right-color: green;
  --border-bottom-color: cyan;
  --border-left-color: blue;
}
.multi-border {
  border-style: solid;
  border-image: paint(border-colors);
  border-image-slice:
    var(--border-top-width)
    var(--border-right-width)
    var(--border-bottom-width)
    var(--border-left-width);
  border-width:
    calc(var(--border-top-width) * 1px)
    calc(var(--border-right-width) * 1px)
    calc(var(--border-bottom-width) * 1px)
    calc(var(--border-left-width) * 1px);
}
</style>

<body>
<div id=example class=multi-border></div>
<script>
[
  '--border-top-color',
  '--border-right-color',
  '--border-bottom-color',
  '--border-left-color',
].map((name) => {
  CSS.registerProperty({
    name: name,
    syntax: '<color>+',
    inherits: false,
    initialValue: 'currentcolor',
  });
});
[
  '--border-top-width',
  '--border-right-width',
  '--border-bottom-width',
  '--border-left-width',
].map((name) => {
  CSS.registerProperty({
    name: name,
    syntax: '<number>',
    inherits: false,
    initialValue: '0',
  });
});
</script>

<script id="code" type="text/worklet">
registerPaint('border-colors', class {
  static get inputProperties() {
    return [
      '--border-top-width',
      '--border-right-width',
      '--border-bottom-width',
      '--border-left-width',
      '--border-top-color',
      '--border-right-color',
      '--border-bottom-color',
      '--border-left-color',
    ];
  }

  paint(ctx, size, styleMap) {
    const t = 0;
    const r = size.width;
    const b = size.height;
    const l = 0;

    const tw = parseFloat(styleMap.get('--border-top-width'));
    const rw = parseFloat(styleMap.get('--border-right-width'));
    const bw = parseFloat(styleMap.get('--border-bottom-width'));
    const lw = parseFloat(styleMap.get('--border-left-width'));

    const ti = tw;
    const ri = size.width - rw;
    const bi = size.height - bw;
    const li = lw;

    let tp, rp, bp, lp, colors;
    const updateProgression = function() {
      tp = tw / colors.length;
      rp = rw / colors.length;
      bp = bw / colors.length;
      lp = lw / colors.length;
    }

    colors = styleMap.getAll('--border-top-color');
    updateProgression();
    for (let i = 0; i < colors.length; i++) {
      ctx.fillStyle = colors[i];
      this.fillQuad(ctx,
          li - lp * i, ti - tp * i,
          li - lp * (i+1), ti - tp * (i+1),
          ri + lp * (i+1), ti - tp * (i+1),
          ri + lp * i, ti - tp * i);
    }

    colors = styleMap.getAll('--border-right-color');
    updateProgression();
    for (let i = 0; i < colors.length; i++) {
      ctx.fillStyle = colors[i];
      this.fillQuad(ctx,
          ri + rp * i, ti - tp * i,
          ri + rp * (i+1), ti - tp * (i+1),
          ri + rp * (i+1), bi + bp * (i+1),
          ri + rp * i, bi + bp * i);
    }

    colors = styleMap.getAll('--border-bottom-color');
    updateProgression();
    for (let i = 0; i < colors.length; i++) {
      ctx.fillStyle = colors[i];
      this.fillQuad(ctx,
          ri + rp * i, bi + bp * i,
          ri + rp * (i+1), bi + bp * (i+1),
          li - lp * (i+1), bi + bp * (i+1),
          li - lp * i, bi + bp * i);
    }

    colors = styleMap.getAll('--border-left-color');
    updateProgression();
    for (let i = 0; i < colors.length; i++) {
      ctx.fillStyle = colors[i];
      this.fillQuad(ctx,
          li - lp * i, bi + bp * i,
          li - lp * (i+1), bi + bp * (i+1),
          li - lp * (i+1), ti - tp * (i+1),
          li - lp * i, ti - tp * i);
    }
  }

  fillQuad(ctx, x1, y1, x2, y2, x3, y3, x4, y4) {
    ctx.beginPath();
    ctx.moveTo(x1, y1);
    ctx.lineTo(x2, y2);
    ctx.lineTo(x3, y3);
    ctx.lineTo(x4, y4);
    ctx.lineTo(x1, y1);
    ctx.fill();
  }
});
</script>

<script>
    importPaintWorkletThenEndTest(document.getElementById('code').textContent);
</script>
</body>
</html>