/* Shared by the browser (live preview) and the server (full-size export), so both draw identically. */ (function(root){ const eff=(L,it)=>{const o=it&&it.ov&&it.ov[L.id];return o?{...L,...o}:L}; function metrics(E,c,w,h){ const ww=E.size*w;let hh,fs=0; if(E.type==='image')hh=ww*E.cv.height/E.cv.width; else{c.font=`${E.weight} 100px "${E.font}",sans-serif`;fs=ww/Math.max(1,c.measureText(E.text||' ').width)*100;hh=fs*1.15} return{ww,hh,fs} } function place(E,m,w,h){ const mg=E.margin*w; if(E.anchor){const a=E.anchor;return{x:a[1]==='l'?mg+m.ww/2:a[1]==='r'?w-mg-m.ww/2:w/2,y:a[0]==='t'?mg+m.hh/2:a[0]==='b'?h-mg-m.hh/2:h/2}} return{x:E.x*w,y:E.y*h} } function drawLayer(c,L,item,w,h){ const E=eff(L,item),m=metrics(E,c,w,h),p=place(E,m,w,h); c.save();c.globalAlpha=E.opacity;c.translate(p.x,p.y);c.rotate(E.rot*Math.PI/180); if(E.shadow){c.shadowColor='rgba(0,0,0,.5)';c.shadowBlur=m.ww*.03;c.shadowOffsetY=m.ww*.008} const stamp=(x,y)=>{ if(E.type==='image')c.drawImage(E.cv,x-m.ww/2,y-m.hh/2,m.ww,m.hh); else{c.font=`${E.weight} ${m.fs}px "${E.font}",sans-serif`;c.fillStyle=E.color;c.textAlign='center';c.textBaseline='middle';c.fillText(E.text,x,y)}}; if(E.tile){const sx=m.ww*(1+E.gap),sy=m.hh*(1+E.gap),ext=Math.hypot(w,h),nx=Math.ceil(ext/sx)+1,ny=Math.ceil(ext/sy)+1; for(let j=-ny;j<=ny;j++)for(let i=-nx;i<=nx;i++)stamp(i*sx+(j&1?sx/2:0),j*sy)} else stamp(0,0); c.restore();return{...m,...p,E} } function drawAll(c,w,h,layers,item){for(const L of layers){if(L.vis)drawLayer(c,L,item,w,h)}} const api={eff,metrics,place,drawLayer,drawAll}; if(typeof module!=='undefined'&&module.exports)module.exports=api;else Object.assign(root,api); })(typeof window!=='undefined'?window:globalThis);