function draw_stroke(stroke) { const points = stroke.points; if (points.length === 0) { return; } // if (config.debug_print) console.debug(points) storage.ctx0.beginPath(); storage.ctx0.moveTo(points[0].x, points[0].y); storage.ctx0.strokeStyle = color_from_u32(stroke.color); storage.ctx0.lineWidth = stroke.width; for (let i = 1; i < points.length; ++i) { const p = points[i]; storage.ctx0.lineTo(p.x, p.y); } storage.ctx0.stroke(); } function redraw_predraw() { storage.ctx1.clearRect(0, 0, storage.ctx1.canvas.width, storage.ctx1.canvas.height); } function predraw_user(user_id, event) { if (!(user_id in storage.predraw)) { storage.predraw[user_id] = []; } storage.ctx1.beginPath(); if (storage.predraw[user_id].length > 0) { const last = storage.predraw[user_id][storage.predraw[user_id].length - 1]; storage.ctx1.moveTo(last.x, last.y); storage.ctx1.lineTo(event.x, event.y); } else { storage.ctx1.moveTo(event.x, event.y); } storage.ctx1.stroke(); storage.predraw[user_id].push({ 'x': event.x, 'y': event.y }); } function redraw_region(bbox) { // const start = performance.now(); if (bbox.xmin === bbox.xmax || bbox.ymin === bbox.ymax) { return; } storage.ctx0.save(); storage.ctx0.clearRect(bbox.xmin, bbox.ymin, bbox.xmax - bbox.xmin, bbox.ymax - bbox.ymin); storage.ctx0.beginPath(); storage.ctx0.rect(bbox.xmin, bbox.ymin, bbox.xmax - bbox.xmin, bbox.ymax - bbox.ymin); storage.ctx0.clip(); for (const event of storage.events) { if (event.type === EVENT.STROKE && !event.deleted) { if (stroke_intersects_region(event.points, bbox)) { draw_stroke(event); } } } storage.ctx0.restore(); // const end = performance.now(); // if (config.debug_print) console.debug(`Redraw took ${end - start}ms`); }