var parser = new DOMParser(), doc = parser.parseFromString('', 'text/xml'), deltas = parser.parseFromString('', 'text/xml'), canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'), points = []; doc.childNodes.forEach((glyph) => { if (glyph.nodeName.toLowerCase() == 'ttglyph') { glyph.childNodes.forEach((contour) => { if (contour.nodeName.toLowerCase() == 'contour') { ctx.save(); ctx.transform(1, 0, 0, -1, 200, 800); ctx.beginPath(); contour.childNodes.forEach((pt, k) => { if (pt.nodeName.toLowerCase() == 'pt') { var x = parseInt(pt.attributes.x.value), y = parseInt(pt.attributes.y.value); if (k > 0) { ctx.lineTo(x, y); } else { ctx.moveTo(x, y); } points.push([x, y]); } }); ctx.closePath(); ctx.stroke(); ctx.restore(); } }); } }); console.log(deltas) deltas.querySelectorAll('glyphVariations').forEach((glyphVariations) => { glyphVariations.querySelectorAll('tuple').forEach((tuple) => { tuple.querySelectorAll('delta').forEach((delta) => { var pt = delta.attributes.pt.value, x = parseInt(delta.attributes.x.value), y = parseInt(delta.attributes.y.value); ctx.save(); ctx.transform(1, 0, 0, -1, 200, 800); ctx.beginPath(); ctx.moveTo(points[pt][0], points[pt][1]); ctx.lineTo(points[pt][0] + x, points[pt][1] + y); ctx.stroke(); ctx.beginPath(); ctx.arc(points[pt][0] + x, points[pt][1] + y, 2, 0, 2 * Math.PI, false); ctx.fill(); ctx.restore(); }); }); });