three-text 0.2.4 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * three-text v0.2.4
2
+ * three-text v0.2.5
3
3
  * Copyright (C) 2025 Countertype LLC
4
4
  *
5
5
  * This program is free software: you can redistribute it and/or modify
@@ -11,4 +11,4 @@
11
11
  *
12
12
  * This software includes third-party code - see LICENSE_THIRD_PARTY for details.
13
13
  */
14
- !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).ThreeText={})}(this,function(e){const n=!("undefined"==typeof window||!window.THREE_TEXT_LOG)||"undefined"!=typeof globalThis&&"true"===globalThis.process?.env?.THREE_TEXT_LOG;const i=new class{warn(e,...n){console.warn(e,...n)}error(e,...n){console.error(e,...n)}log(e,...i){n&&console.log(e,...i)}};const s=new class{constructor(){this.metrics=[],this.activeTimers=new Map}start(e,i){if(!n)return;const s=performance.now();this.activeTimers.set(e,s),this.metrics.push({name:e,startTime:s,metadata:i})}end(e){if(!n)return null;const s=performance.now(),r=this.activeTimers.get(e);if(void 0===r)return i.warn(`Performance timer "${e}" was not started`),null;const o=s-r;this.activeTimers.delete(e);for(let n=this.metrics.length-1;n>=0;n--){const i=this.metrics[n];if(i.name===e&&!i.endTime){i.endTime=s,i.duration=o;break}}return console.log(`${e}: ${o.toFixed(2)}ms`),o}getSummary(){if(!n)return{};const e={};for(const n of this.metrics){if(!n.duration)continue;const i=e[n.name];i?(i.count++,i.totalDuration+=n.duration,i.avgDuration=i.totalDuration/i.count,i.lastDuration=n.duration):e[n.name]={count:1,avgDuration:n.duration,totalDuration:n.duration,lastDuration:n.duration}}return e}printSummary(){if(!n)return;const e=this.getSummary();console.table(e),console.log("Operations:",Object.keys(e).sort().join(", "))}printBaseline(){if(!n)return;const e=this.getSummary();Object.entries(e).forEach(([e,n])=>{console.log(`BASELINE ${e}: ${n.avgDuration.toFixed(2)}ms avg (${n.count} calls)`)})}clear(){n&&(this.metrics.length=0,this.activeTimers.clear())}time(e,i,s){if(!n)return i();this.start(e,s);try{return i()}finally{this.end(e)}}async timeAsync(e,i,s){if(!n)return i();this.start(e,s);try{return await i()}finally{this.end(e)}}},r=200,o=100,h=0,c=1/3;var l,d;!function(e){e[e.BOX=0]="BOX",e[e.GLUE=1]="GLUE",e[e.PENALTY=2]="PENALTY",e[e.DISCRETIONARY=3]="DISCRETIONARY"}(l||(l={})),function(e){e[e.TIGHT=0]="TIGHT",e[e.NORMAL=1]="NORMAL",e[e.LOOSE=2]="LOOSE",e[e.VERY_LOOSE=3]="VERY_LOOSE"}(d||(d={}));class ActiveNodeList{constructor(){this.nodesByKey=new Map,this.activeList=[],this.allNodes=new Set}getKey(e,n){return e<<2|n}insert(e){const n=this.getKey(e.position,e.fitness),i=this.nodesByKey.get(n);i&&e.totalDemerits<i.totalDemerits?(i.totalDemerits=e.totalDemerits,i.previous=e.previous,i.totalWidth=e.totalWidth):i||(this.nodesByKey.set(n,e),this.allNodes.add(e),e.activeListIndex=this.activeList.length,this.activeList.push(e))}findExisting(e,n){return this.nodesByKey.get(this.getKey(e,n))}getAllActive(){return this.activeList}deactivateNode(e){if(e.active&&void 0!==e.activeListIndex){e.active=!1;const n=e.activeListIndex,i=this.activeList.length-1;if(n!==i){const e=this.activeList[i];this.activeList[n]=e,e.activeListIndex=n}this.activeList.pop(),e.activeListIndex=void 0}}size(){return this.allNodes.size}}const f=50,p=50,g=1e4,y=10,b=1e4,m=-1/0,_=2,w=4,O=1e4;class LineBreak{static badness(e,n){if(0===e)return 0;if(n<=0)return O;let i;return i=e<=7230584?Math.floor(297*e/n):n>=1663497?Math.floor(e/Math.floor(n/297)):e,i>1290?O:Math.floor((i*i*i+131072)/262144)}static findHyphenationPoints(e,n="en-us",i,s=_,r=w){let o;if(!i||!i[n])return[];if(o=i[n],!o)return[];const h=`.${e.toLowerCase()}.`,c=new Array(h.length).fill(0);for(let e=0;e<h.length;e++){let n=o;for(let i=e;i<h.length;i++){const s=h[i];if(!n.children||!n.children[s])break;if(n=n.children[s],n.patterns)for(let i=0;i<n.patterns.length;i++){const s=e+i;s<c.length&&(c[s]=Math.max(c[s],n.patterns[i]))}}}const l=[];for(let e=2;e<h.length-2;e++)c[e]%2==1&&l.push(e-1);return l.filter(n=>n>=s&&e.length-n>=r)}static itemizeText(e,n,i=!1,s="en-us",r,o=_,h=w,c){const d=[];return d.push(...this.itemizeParagraph(e,n,i,s,r,o,h,c)),d.push({type:l.GLUE,width:0,stretch:1/0,shrink:0,text:"",originIndex:e.length}),d.push({type:l.PENALTY,width:0,penalty:-1/0,text:"",originIndex:e.length}),d}static itemizeParagraph(e,n,i,s,r,o,h,d){const g=[],y=e.match(/\S+|\s+/g)||[];let b=0;for(let e=0;e<y.length;e++){const m=y[e],_=b;if(/\s+/.test(m)){const e=n(m);g.push({type:l.GLUE,width:e,stretch:.5*e,shrink:e*c,text:m,originIndex:_}),b+=m.length}else{const e=m.split(/(-)/);let c=_;for(let y=0;y<e.length;y++){const b=e[y];if(b)if("-"===b)g.push({type:l.DISCRETIONARY,width:n("-"),preBreak:"-",postBreak:"",noBreak:"-",preBreakWidth:n("-"),penalty:d?.exHyphenPenalty??p,flagged:!0,text:"-",originIndex:c}),c+=1;else{if(b.includes("­")){const e=b.split("­");let i=0;for(let s=0;s<e.length;s++){const r=e[s];r.length>0&&(g.push({type:l.BOX,width:n(r),text:r,originIndex:c+i}),i+=r.length),s<e.length-1&&(g.push({type:l.DISCRETIONARY,width:0,preBreak:"-",postBreak:"",noBreak:"",preBreakWidth:n("-"),penalty:d?.hyphenPenalty??f,flagged:!0,text:"",originIndex:c+i}),i+=1)}}else if(i&&b.length>=o+h){const e=LineBreak.findHyphenationPoints(b,s,r,o,h);if(e.length>0){let i=0;for(const s of e){const e=b.substring(i,s);g.push({type:l.BOX,width:n(e),text:e,originIndex:c+i}),g.push({type:l.DISCRETIONARY,width:0,preBreak:"-",postBreak:"",noBreak:"",preBreakWidth:n("-"),penalty:d?.hyphenPenalty??f,flagged:!0,text:"",originIndex:c+s}),i=s}const s=b.substring(i);g.push({type:l.BOX,width:n(s),text:s,originIndex:c+i})}else g.push({type:l.BOX,width:n(b),text:b,originIndex:c})}else g.push({type:l.BOX,width:n(b),text:b,originIndex:c});c+=b.length}}b+=m.length}}return g}static hasSingleWordLines(e,n,i){let s=0;for(let r=0;r<n.length-1;r++){const o=n[r];let h=0,c=0;for(let n=s;n<o;n++)e[n].type===l.GLUE&&h++,e[n].type!==l.PENALTY&&(c+=e[n].width);if(0===h&&c>0){if(c/i<.5)return!0}s=o+1}return!1}static breakText(e){s.start("LineBreak.breakText",{textLength:e.text.length,width:e.width,align:e.align||"left",hyphenate:e.hyphenate||!1});const{text:n,width:c,align:d="left",direction:m="ltr",hyphenate:O=!1,language:k="en-us",respectExistingBreaks:j=!0,measureText:$,hyphenationPatterns:Y,unitsPerEm:q,tolerance:tt=r,pretolerance:et=o,emergencyStretch:nt=h,autoEmergencyStretch:it,lefthyphenmin:st=_,righthyphenmin:rt=w,linepenalty:at=y,adjdemerits:ot=b,hyphenpenalty:ht=f,exhyphenpenalty:ct=p,doublehyphendemerits:lt=g,looseness:ut=0,disableSingleWordDetection:dt=!1}=e;if(j&&n.includes("\n")){const i=n.split("\n"),r=[];let o=0;for(const n of i){if(0===n.length)r.push({text:"",originalStart:o,originalEnd:o,xOffset:0,isLastLine:!0,naturalWidth:0,endedWithHyphen:!1});else{const i=LineBreak.breakText({...e,text:n,respectExistingBreaks:!1});i.forEach(e=>{e.originalStart+=o,e.originalEnd+=o}),r.push(...i)}o+=n.length+1}return s.end("LineBreak.breakText"),r}let ft=O;!ft||Y&&Y[k]||(i.warn(`Hyphenation patterns for ${k} not available`),ft=!1);let pt=nt;void 0!==it&&c?pt=c*it:!ft&&nt===h&&c&&(pt=.1*c);const gt={linePenalty:at,adjDemerits:ot,doubleHyphenDemerits:lt,hyphenPenalty:ht,exHyphenPenalty:ct,currentAlign:d,unitsPerEm:q};if(!c||c===1/0){const e=$(n);return s.end("LineBreak.breakText"),[{text:n,originalStart:0,originalEnd:n.length-1,xOffset:0,isLastLine:!0,naturalWidth:e,endedWithHyphen:!1}]}const yt=LineBreak.itemizeText(n,$,ft,k,Y,st,rt,gt);if(0===yt.length)return[];let bt=0,mt=pt,_t=null;const xt=!dt;for(;bt<5;){let e=ft?yt.filter(e=>e.type!==l.DISCRETIONARY||e.penalty!==(gt?.hyphenPenalty??f)):yt,i=LineBreak.findBreakpoints(e,c,et,ut,!1,0,gt);if(0===i.length&&ft&&(e=yt,i=LineBreak.findBreakpoints(e,c,tt,ut,!1,0,gt)),0===i.length&&(e=yt,i=LineBreak.findBreakpoints(e,c,10001,ut,!0,mt,gt)),0===i.length&&(i=LineBreak.findBreakpoints(e,c,1/0,ut,!0,mt,gt)),i.length>0){const s=LineBreak.computeCumulativeWidths(e);if(_t=LineBreak.createLines(n,e,i,c,d,m,s,gt),xt&&i.length>1&&LineBreak.hasSingleWordLines(e,i,c)){mt+=.1*c,bt++;continue}break}break}if(s.end("LineBreak.breakText"),_t&&_t.length>0)return _t;const wt=$(n);return[{text:n,originalStart:0,originalEnd:n.length-1,xOffset:0,adjustmentRatio:0,isLastLine:!0,naturalWidth:wt,endedWithHyphen:!1}]}static findBreakpoints(e,n,i=1/0,s=0,r=!1,o=0,h){const c=LineBreak.computeCumulativeWidths(e),f=new ActiveNodeList;f.insert({position:0,line:0,fitness:d.NORMAL,totalDemerits:0,totalWidth:0,previous:null,active:!0});for(let s=0;s<e.length;s++){const r=e[s];r.type===l.PENALTY&&r.penalty<1/0&&LineBreak.considerBreak(e,f,s,n,i,o,c,h),r.type===l.DISCRETIONARY&&r.penalty<1/0&&LineBreak.considerBreak(e,f,s,n,i,o,c,h),r.type===l.GLUE&&s>0&&e[s-1].type===l.BOX&&LineBreak.considerBreak(e,f,s,n,i,o,c,h),LineBreak.deactivateNodes(f,s,n,c.minWidths)}const p=[];let g=null;if(0===s){const e=f.getAllActive();let n=1/0;for(const i of e)i.active&&i.totalDemerits<n&&(n=i.totalDemerits,g=i)}else{const e=f.getAllActive();let n=0,i=1/0;for(const s of e)s.active&&s.totalDemerits<i&&(i=s.totalDemerits,n=s.line);let o=0,h=1/0;for(const i of e){if(!i.active)continue;const e=i.line-n;e<o&&s<=e||e>o&&s>=e?(g=i,o=e,h=i.totalDemerits):e===o&&i.totalDemerits<h&&(g=i,h=i.totalDemerits)}if(!r&&o!==s&&g)return[]}if(!g)return[];for(;g&&g.position>0;)p.unshift(g.position),g=g.previous;return p}static considerBreak(e,n,i,s,r=1/0,o=0,h,c){const d=(e[i].type===l.PENALTY?e[i].penalty:0)<=-1/0,f=n.getAllActive();for(let p=0;p<f.length;p++){const g=f[p];if(!g.active)continue;const y=LineBreak.computeAdjustmentRatio(e,g.position,i,g.line,s,h,c),{ratio:b,adjustment:_,stretch:w,shrink:O,totalWidth:k}=y;let j;if(_>0){const e=w+o;j=e<=0?10001:LineBreak.badness(_,e)}else j=_<0?O<=0||-_>O?10001:LineBreak.badness(-_,O):0;if(!d&&b<-1)continue;const $=LineBreak.computeFitnessClass(j,_>0);if(!d&&j>r)continue;let Y=0,q=0;let tt=(c?.linePenalty??0)+j,et=Math.abs(tt)>=1e4?1e8:tt*tt;const nt=e[i].type===l.PENALTY||e[i].type===l.DISCRETIONARY?e[i].penalty:0;0!==nt&&(nt>0?et+=nt*nt:nt>m&&(et-=nt*nt));const it=e[i].type===l.PENALTY&&e[i].flagged||e[i].type===l.DISCRETIONARY&&e[i].flagged,st=g.position>0&&(e[g.position].type===l.PENALTY&&e[g.position].flagged||e[g.position].type===l.DISCRETIONARY&&e[g.position].flagged);it&&st&&(Y=c?.doubleHyphenDemerits??0,et+=Y),Math.abs($-g.fitness)>1&&(q=c?.adjDemerits??0,et+=q),d&&(et=0);const rt=g.totalDemerits+et;let at=n.findExisting(i,$);at?rt<at.totalDemerits&&(at.totalDemerits=rt,at.previous=g,at.totalWidth=k):n.insert({position:i,line:g.line+1,fitness:$,totalDemerits:rt,totalWidth:k,previous:g,active:!0})}}static computeAdjustmentRatio(e,n,i,s,r,o,h){let c=0,d=0,f=0;if(o){c=o.widths[i]-o.widths[n],d=o.stretches[i]-o.stretches[n],f=o.shrinks[i]-o.shrinks[n];for(let s=n;s<i;s++){const n=e[s];n.type===l.PENALTY&&(c-=n.width)}}else for(let s=n;s<i;s++){const n=e[s];n.type!==l.PENALTY&&(c+=n.width,n.type===l.GLUE&&(d+=n.stretch,f+=n.shrink))}i<e.length&&(e[i].type===l.PENALTY||e[i].type===l.DISCRETIONARY)&&(c+=e[i].type===l.PENALTY?e[i].width:e[i].preBreakWidth);const p=r-c;let g;return g=p>0&&d>0?p/d:p<0&&f>0?p/f:0===p?0:p>0?3:-1,{ratio:g,adjustment:p,stretch:d,shrink:f,totalWidth:c}}static computeFitnessClass(e,n){return n?e<=12?d.NORMAL:e<=99?d.LOOSE:d.VERY_LOOSE:e<=12?d.NORMAL:d.TIGHT}static computeCumulativeWidths(e){const n=e.length+1,i=new Array(n),s=new Array(n),r=new Array(n),o=new Array(n);i[0]=0,s[0]=0,r[0]=0,o[0]=0;for(let n=0;n<e.length;n++){const h=e[n];if(i[n+1]=i[n]+h.width,h.type===l.PENALTY)o[n+1]=o[n];else if(h.type===l.GLUE){const e=h;s[n+1]=s[n]+e.stretch,r[n+1]=r[n]+e.shrink,o[n+1]=o[n]+Math.max(0,e.width-e.shrink)}else s[n+1]=s[n],r[n+1]=r[n],o[n+1]=o[n]+h.width}return{widths:i,stretches:s,shrinks:r,minWidths:o}}static deactivateNodes(e,n,i,s){const r=e.getAllActive();for(let o=r.length-1;o>=0;o--){const h=r[o];if(!h.active)continue;s[n]-s[h.position]>i&&e.deactivateNode(h)}}static createLines(e,n,i,s,r,o,h,c){if(0===i.length)return[{text:e,originalStart:0,originalEnd:e.length-1,xOffset:0}];const d=[];let f=0;for(let e=0;e<i.length;e++){const p=i[e],g=!(i[i.length-1]+1<n.length-1)&&e===i.length-1,y=[];let b=-1,m=-1,_=0;for(let e=f;e<p;e++){const i=n[e];if((i.type!==l.PENALTY||i.text)&&(i.type!==l.DISCRETIONARY||i.noBreak)){if(void 0!==i.originIndex){(-1===b||i.originIndex<b)&&(b=i.originIndex);const e=i.text?i.text.length:0,n=i.originIndex+e-1;n>m&&(m=n)}if(i.text)y.push(i.text);else if(i.type===l.DISCRETIONARY){const e=i;e.noBreak&&y.push(e.noBreak)}_+=i.width}}const w=n[p];let O=!1;if(p<n.length)if(w.type===l.PENALTY&&w.flagged)y.push("-"),_+=w.width,O=!0,void 0!==w.originIndex&&(m=w.originIndex-1);else if(w.type===l.DISCRETIONARY){const e=w;e.preBreak&&(y.push(e.preBreak),_+=e.preBreakWidth,O=e.flagged||!1,void 0!==w.originIndex&&(m=w.originIndex-1))}const k=y.join("");let j=0,$=0,Y=r;if("justify"===r&&g&&(Y="rtl"===o?"right":"left"),"center"===Y)j=(s-_)/2;else if("right"===Y)j=s-_;else if("justify"===Y&&!g){$=LineBreak.computeAdjustmentRatio(n,f,p,e,s,h,c).ratio}d.push({text:k,originalStart:b,originalEnd:m,xOffset:j,adjustmentRatio:$,isLastLine:!1,naturalWidth:_,endedWithHyphen:O}),f=p+1}if(f<n.length-1){const e=[];let i=-1,h=-1,c=0;for(let s=f;s<n.length-1;s++){const r=n[s];r.type!==l.PENALTY&&(void 0!==r.originIndex&&((-1===i||r.originIndex<i)&&(i=r.originIndex),r.originIndex>h&&(h=r.originIndex)),r.text&&e.push(r.text),c+=r.width)}const p=e.join("");let g=0,y=r;"justify"===r&&(y="rtl"===o?"right":"left"),"center"===y?g=(s-c)/2:"right"===y&&(g=s-c),d.push({text:p,originalStart:i,originalEnd:h,xOffset:g,adjustmentRatio:0,isLastLine:!0,naturalWidth:c,endedWithHyphen:!1}),d.length>1&&(d[d.length-2].isLastLine=!1),d[d.length-1].isLastLine=!0}else d.length>0&&(d[d.length-1].isLastLine=!0);return d}}class TextMeasurer{static measureTextWidth(e,n,i=0){const s=e.hb.createBuffer();s.addText(n),s.guessSegmentProperties(),e.hb.shape(e.font,s);const r=s.json(e.font),o=i*e.upem;let h=0;return r.forEach((e,i)=>{h+=e.ax;const s=i===r.length-1,c=" "===n||" "===n||/^\s+$/.test(n);0===o||s&&!c||(h+=o)}),s.destroy(),h}}class TextLayout{constructor(e){this.loadedFont=e}computeLines(e){const{text:n,width:i,align:s,direction:r,hyphenate:o,language:h,respectExistingBreaks:c,tolerance:l,pretolerance:d,emergencyStretch:f,autoEmergencyStretch:p,hyphenationPatterns:g,lefthyphenmin:y,righthyphenmin:b,linepenalty:m,adjdemerits:_,hyphenpenalty:w,exhyphenpenalty:O,doublehyphendemerits:k,looseness:j,disableSingleWordDetection:$,letterSpacing:Y}=e;let q;if(i)q=LineBreak.breakText({text:n,width:i,align:s,direction:r,hyphenate:o,language:h,respectExistingBreaks:c,tolerance:l,pretolerance:d,emergencyStretch:f,autoEmergencyStretch:p,hyphenationPatterns:g,lefthyphenmin:y,righthyphenmin:b,linepenalty:m,adjdemerits:_,hyphenpenalty:w,exhyphenpenalty:O,doublehyphendemerits:k,looseness:j,disableSingleWordDetection:$,unitsPerEm:this.loadedFont.upem,measureText:e=>TextMeasurer.measureTextWidth(this.loadedFont,e,Y)});else{const e=n.split("\n");q=[];let i=0;for(const n of e)q.push({text:n,originalStart:i,originalEnd:i+n.length-1,xOffset:0}),i+=n.length+1}return{lines:q}}applyAlignment(e,n){const{width:i,align:s,planeBounds:r}=n;let o=0;const h={min:{...r.min},max:{...r.max}};if(i&&("center"===s||"right"===s)){const n=r.max.x-r.min.x;if("center"===s?o=(i-n)/2-r.min.x:"right"===s&&(o=i-r.max.x),0!==o){for(let n=0;n<e.length;n+=3)e[n]+=o;h.min.x+=o,h.max.x+=o}}return{offset:o,adjustedBounds:h}}}const k=1330926671,j=1953784678,$=2001684038;class FontMetadataExtractor{static extractMetadata(e){if(!e||e.byteLength<12)throw new Error("Invalid font buffer: too small to be a valid font file");const n=new DataView(e),i=n.getUint32(0);if(![65536,k,j].includes(i))throw new Error(`Invalid font format. Expected TrueType or OpenType, got signature: 0x${i.toString(16)}`);const s=new Uint8Array(e),r=n.getUint16(4);let o=!1,h=0,c=0,l=0,d=0,f=0,p=0;for(let e=0;e<r;e++){const i=(new TextDecoder).decode(s.slice(12+16*e,12+16*e+4));("CFF "===i||"CFF2"===i)&&(o=!0),"head"===i&&(h=n.getUint32(12+16*e+8)),"hhea"===i&&(c=n.getUint32(12+16*e+8)),"OS/2"===i&&(l=n.getUint32(12+16*e+8)),"fvar"===i&&(p=n.getUint32(12+16*e+8)),"STAT"===i&&(d=n.getUint32(12+16*e+8)),"name"===i&&(f=n.getUint32(12+16*e+8))}const g=h?n.getUint16(h+18):1e3;let y=null;c&&(y={ascender:n.getInt16(c+4),descender:n.getInt16(c+6),lineGap:n.getInt16(c+8)});let b=null;l&&(b={typoAscender:n.getInt16(l+68),typoDescender:n.getInt16(l+70),typoLineGap:n.getInt16(l+72),winAscent:n.getUint16(l+74),winDescent:n.getUint16(l+76)});let m=null;return p&&d&&f&&(m=this.extractAxisNames(n,d,f)),{isCFF:o,unitsPerEm:g,hheaAscender:y?.ascender||null,hheaDescender:y?.descender||null,hheaLineGap:y?.lineGap||null,typoAscender:b?.typoAscender||null,typoDescender:b?.typoDescender||null,typoLineGap:b?.typoLineGap||null,winAscent:b?.winAscent||null,winDescent:b?.winDescent||null,axisNames:m}}static extractAxisNames(e,n,i){try{if(e.getUint16(n)<1)return null;const s=e.getUint16(n+4),r=e.getUint16(n+6),o=e.getUint32(n+8),h={};for(let c=0;c<r;c++){const r=n+o+c*s,l=String.fromCharCode(e.getUint8(r),e.getUint8(r+1),e.getUint8(r+2),e.getUint8(r+3)),d=e.getUint16(r+4),f=this.getNameFromNameTable(e,i,d);f&&(h[l]=f)}return Object.keys(h).length>0?h:null}catch(e){return null}}static getNameFromNameTable(e,n,i){try{const s=e.getUint16(n+2),r=e.getUint16(n+4);for(let o=0;o<s;o++){const s=n+6+12*o,h=e.getUint16(s),c=e.getUint16(s+2),l=e.getUint16(s+4),d=e.getUint16(s+6),f=e.getUint16(s+8),p=e.getUint16(s+10);if(d===i&&(0===h||3===h&&1033===l)){const i=n+r+p,s=new Uint8Array(e.buffer,i,f);if(0===h||3===h&&1===c){let e="";for(let n=0;n<s.length;n+=2)e+=String.fromCharCode(s[n]<<8|s[n+1]);return e}return new TextDecoder("ascii").decode(s)}}return null}catch(e){return null}}static getVerticalMetrics(e){return null!==e.typoAscender&&null!==e.typoDescender?{ascender:e.typoAscender,descender:e.typoDescender,lineGap:0}:null!==e.hheaAscender&&null!==e.hheaDescender?{ascender:e.hheaAscender,descender:e.hheaDescender,lineGap:0}:null!==e.winAscent&&null!==e.winDescent?{ascender:e.winAscent,descender:-e.winDescent,lineGap:0}:{ascender:Math.round(.8*e.unitsPerEm),descender:-Math.round(.2*e.unitsPerEm),lineGap:0}}static getFontMetrics(e){const n=FontMetadataExtractor.getVerticalMetrics(e);return{ascender:n.ascender,descender:n.descender,lineGap:n.lineGap,unitsPerEm:e.unitsPerEm,naturalLineHeight:n.ascender-n.descender}}}class WoffConverter{static detectFormat(e){if(e.byteLength<4)return"ttf/otf";const n=new DataView(e).getUint32(0);return n===$?"woff":2001684018===n?"woff2":"ttf/otf"}static async decompressWoff(e){const n=new DataView(e),s=new Uint8Array(e);if(n.getUint32(0)!==$)throw new Error("Not a valid WOFF font");const r=n.getUint32(4),o=n.getUint16(12),h=n.getUint32(16);if("undefined"==typeof DecompressionStream)throw new Error("WOFF fonts require DecompressionStream API (Chrome 80+, Firefox 113+, Safari 16.4+). Please use TTF/OTF fonts or upgrade your browser.");const c=new Uint8Array(h),l=new DataView(c.buffer);l.setUint32(0,r),l.setUint16(4,o);const d=2**Math.floor(Math.log2(o))*16;l.setUint16(6,d),l.setUint16(8,Math.floor(Math.log2(o))),l.setUint16(10,16*o-d);let f=12+16*o;const p=[];for(let e=0;e<o;e++){const i=44+20*e;p.push({tag:n.getUint32(i),offset:n.getUint32(i+4),length:n.getUint32(i+8),origLength:n.getUint32(i+12),checksum:n.getUint32(i+16)})}p.sort((e,n)=>e.tag-n.tag);for(let e=0;e<o;e++){const n=p[e],i=12+16*e;if(l.setUint32(i,n.tag),l.setUint32(i+4,n.checksum),l.setUint32(i+8,f),l.setUint32(i+12,n.origLength),n.length===n.origLength)c.set(s.subarray(n.offset,n.offset+n.length),f);else{const e=s.subarray(n.offset,n.offset+n.length),i=await WoffConverter.decompressZlib(e);if(i.byteLength!==n.origLength)throw new Error(`Decompression failed: expected ${n.origLength} bytes, got ${i.byteLength}`);c.set(new Uint8Array(i),f)}f+=n.origLength;f+=(4-n.origLength%4)%4}return i.log("WOFF font decompressed successfully"),c.buffer.slice(0,f)}static async decompressZlib(e){const n=new ReadableStream({start(n){n.enqueue(e),n.close()}}).pipeThrough(new DecompressionStream("deflate"));return new Response(n).arrayBuffer()}}class FontLoader{constructor(e){this.getHarfBuzzInstance=e}async loadFont(e,n){if(s.start("FontLoader.loadFont",{bufferSize:e.byteLength}),!e||e.byteLength<12)throw new Error("Invalid font buffer: too small to be a valid font file");const r=WoffConverter.detectFormat(e);if("woff"===r)i.log("WOFF font detected, decompressing..."),e=await WoffConverter.decompressWoff(e);else if("woff2"===r)throw new Error("WOFF2 fonts are not yet supported. Please use WOFF or TTF/OTF format.");const o=new DataView(e).getUint32(0);if(![65536,k,j].includes(o))throw new Error(`Invalid font format. Expected TrueType or OpenType, got signature: 0x${o.toString(16)}`);const{hb:h,module:c}=await this.getHarfBuzzInstance();try{const i=h.createBlob(new Uint8Array(e)),s=h.createFace(i,0),r=h.createFont(s);n&&r.setVariations(n);const o=s.getAxisInfos(),l=Object.keys(o).length>0,d=FontMetadataExtractor.extractMetadata(e);let f;if(l&&o){f={};for(const[e,n]of Object.entries(o))f[e]={...n,name:d.axisNames?.[e]||null}}return{hb:h,fontBlob:i,face:s,font:r,module:c,upem:d.unitsPerEm,metrics:d,fontVariations:n,isVariable:l,variationAxes:f}}catch(e){throw i.error("Failed to load font:",e),e}finally{s.end("FontLoader.loadFont")}}static destroyFont(e){try{e.font&&"function"==typeof e.font.destroy&&e.font.destroy(),e.face&&"function"==typeof e.face.destroy&&e.face.destroy(),e.fontBlob&&"function"==typeof e.fontBlob.destroy&&e.fontBlob.destroy()}catch(e){i.error("Error destroying font resources:",e)}}}async function loadPattern(e,n){{const i=`ThreeTextPatterns_${e.replace(/-/g,"_")}`;if(window[i])return window[i];const s=n||"/patterns/";return new Promise((n,r)=>{const o=document.createElement("script");o.src=`${s}${e}.umd.js`,o.async=!0,o.onload=()=>{window[i]?n(window[i]):r(new Error(`Pattern script loaded, but global ${i} not found.`))},o.onerror=()=>{r(new Error(`Failed to load hyphenation pattern from ${o.src}. Did you copy the pattern files to your public directory?`))},document.head.appendChild(o)})}}class Vec2{constructor(e=0,n=0){this.x=e,this.y=n}set(e,n){return this.x=e,this.y=n,this}clone(){return new Vec2(this.x,this.y)}copy(e){return this.x=e.x,this.y=e.y,this}add(e){return this.x+=e.x,this.y+=e.y,this}sub(e){return this.x-=e.x,this.y-=e.y,this}multiply(e){return this.x*=e,this.y*=e,this}divide(e){return this.x/=e,this.y/=e,this}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}lengthSq(){return this.x*this.x+this.y*this.y}normalize(){const e=this.length();return e>0&&this.divide(e),this}dot(e){return this.x*e.x+this.y*e.y}distanceTo(e){const n=this.x-e.x,i=this.y-e.y;return Math.sqrt(n*n+i*i)}distanceToSquared(e){const n=this.x-e.x,i=this.y-e.y;return n*n+i*i}equals(e){return this.x===e.x&&this.y===e.y}angle(){return Math.atan2(this.y,this.x)}}class Vec3{constructor(e=0,n=0,i=0){this.x=e,this.y=n,this.z=i}set(e,n,i){return this.x=e,this.y=n,this.z=i,this}clone(){return new Vec3(this.x,this.y,this.z)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}multiply(e){return this.x*=e,this.y*=e,this.z*=e,this}divide(e){return this.x/=e,this.y/=e,this.z/=e,this}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}normalize(){const e=this.length();return e>0&&this.divide(e),this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.z}cross(e){const n=this.y*e.z-this.z*e.y,i=this.z*e.x-this.x*e.z,s=this.x*e.y-this.y*e.x;return this.x=n,this.y=i,this.z=s,this}distanceTo(e){const n=this.x-e.x,i=this.y-e.y,s=this.z-e.z;return Math.sqrt(n*n+i*i+s*s)}distanceToSquared(e){const n=this.x-e.x,i=this.y-e.y,s=this.z-e.z;return n*n+i*i+s*s}equals(e){return this.x===e.x&&this.y===e.y&&this.z===e.z}}class Box3{constructor(e=new Vec3(1/0,1/0,1/0),n=new Vec3(-1/0,-1/0,-1/0)){this.min=e,this.max=n}set(e,n){return this.min.copy(e),this.max.copy(n),this}setFromPoints(e){this.makeEmpty();for(let n=0;n<e.length;n++)this.expandByPoint(e[n]);return this}makeEmpty(){return this.min.x=this.min.y=this.min.z=1/0,this.max.x=this.max.y=this.max.z=-1/0,this}isEmpty(){return this.max.x<this.min.x||this.max.y<this.min.y||this.max.z<this.min.z}expandByPoint(e){return this.min.x=Math.min(this.min.x,e.x),this.min.y=Math.min(this.min.y,e.y),this.min.z=Math.min(this.min.z,e.z),this.max.x=Math.max(this.max.x,e.x),this.max.y=Math.max(this.max.y,e.y),this.max.z=Math.max(this.max.z,e.z),this}expandByScalar(e){return this.min.x-=e,this.min.y-=e,this.min.z-=e,this.max.x+=e,this.max.y+=e,this.max.z+=e,this}containsPoint(e){return e.x>=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y&&e.z>=this.min.z&&e.z<=this.max.z}containsBox(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z}intersectsBox(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y&&e.max.z>=this.min.z&&e.min.z<=this.max.z}getCenter(e=new Vec3){return this.isEmpty()?e.set(0,0,0):e.set(.5*(this.min.x+this.max.x),.5*(this.min.y+this.max.y),.5*(this.min.z+this.max.z))}getSize(e=new Vec3){return this.isEmpty()?e.set(0,0,0):e.set(this.max.x-this.min.x,this.max.y-this.min.y,this.max.z-this.min.z)}clone(){return new Box3(this.min.clone(),this.max.clone())}copy(e){return this.min.copy(e.min),this.max.copy(e.max),this}union(e){return this.min.x=Math.min(this.min.x,e.min.x),this.min.y=Math.min(this.min.y,e.min.y),this.min.z=Math.min(this.min.z,e.min.z),this.max.x=Math.max(this.max.x,e.max.x),this.max.y=Math.max(this.max.y,e.max.y),this.max.z=Math.max(this.max.z,e.max.z),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}var Y="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function getDefaultExportFromCjs(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function getAugmentedNamespace(e){if(e.__esModule)return e;var n=e.default;if("function"==typeof n){var i=function a(){return this instanceof a?Reflect.construct(n,arguments,this.constructor):n.apply(this,arguments)};i.prototype=n.prototype}else i={};return Object.defineProperty(i,"__esModule",{value:!0}),Object.keys(e).forEach(function(n){var s=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(i,n,s.get?s:{enumerable:!0,get:function(){return e[n]}})}),i}var q={exports:{}};!function(e){var n;function t(e,n){return e.b===n.b&&e.a===n.a}function u(e,n){return e.b<n.b||e.b===n.b&&e.a<=n.a}function v(e,n,i){var s=n.b-e.b,r=i.b-n.b;return 0<s+r?s<r?n.a-e.a+s/(s+r)*(e.a-i.a):n.a-i.a+r/(s+r)*(i.a-e.a):0}function x(e,n,i){var s=n.b-e.b,r=i.b-n.b;return 0<s+r?(n.a-i.a)*s+(n.a-e.a)*r:0}function z(e,n){return e.a<n.a||e.a===n.a&&e.b<=n.b}function aa(e,n,i){var s=n.a-e.a,r=i.a-n.a;return 0<s+r?s<r?n.b-e.b+s/(s+r)*(e.b-i.b):n.b-i.b+r/(s+r)*(i.b-e.b):0}function ba(e,n,i){var s=n.a-e.a,r=i.a-n.a;return 0<s+r?(n.b-i.b)*s+(n.b-e.b)*r:0}function ca(e){return u(e.b.a,e.a)}function da(e){return u(e.a,e.b.a)}function A(e,n,i,s){return(e=0>e?0:e)<=(i=0>i?0:i)?0===i?(n+s)/2:n+e/(e+i)*(s-n):s+i/(e+i)*(n-s)}function ea(e){var n=B(e.b);return C(n,e.c),C(n.b,e.c),D(n,e.a),n}function E(e,n){var i=!1,s=!1;e!==n&&(n.a!==e.a&&(s=!0,F(n.a,e.a)),n.d!==e.d&&(i=!0,G(n.d,e.d)),H(n,e),s||(C(n,e.a),e.a.c=e),i||(D(n,e.d),e.d.a=e))}function I(e){var n=e.b,i=!1;e.d!==e.b.d&&(i=!0,G(e.d,e.b.d)),e.c===e?F(e.a,null):(e.b.d.a=J(e),e.a.c=e.c,H(e,J(e)),i||D(e,e.d)),n.c===n?(F(n.a,null),G(n.d,null)):(e.d.a=J(n),n.a.c=n.c,H(n,J(n))),fa(e)}function K(e){var n=B(e),i=n.b;return H(n,e.e),n.a=e.b.a,C(i,n.a),n.d=i.d=e.d,n=n.b,H(e.b,J(e.b)),H(e.b,n),e.b.a=n.a,n.b.a.c=n.b,n.b.d=e.b.d,n.f=e.f,n.b.f=e.b.f,n}function L(e,n){var i=!1,s=B(e),r=s.b;return n.d!==e.d&&(i=!0,G(n.d,e.d)),H(s,e.e),H(r,n),s.a=e.b.a,r.a=n.a,s.d=r.d=e.d,e.d.a=r,i||D(s,e.d),s}function B(e){var n=new M,i=new M,s=e.b.h;return i.h=s,s.b.h=n,n.h=e,e.b.h=i,n.b=i,n.c=n,n.e=i,i.b=n,i.c=i,i.e=n}function H(e,n){var i=e.c,s=n.c;i.b.e=n,s.b.e=e,e.c=s,n.c=i}function C(e,n){var i=n.f,s=new N(n,i);i.e=s,n.f=s,i=s.c=e;do{i.a=s,i=i.c}while(i!==e)}function D(e,n){var i=n.d,s=new ga(n,i);i.b=s,n.d=s,s.a=e,s.c=n.c,i=e;do{i.d=s,i=i.e}while(i!==e)}function fa(e){var n=e.h;e=e.b.h,n.b.h=e,e.b.h=n}function F(e,n){var i=e.c,s=i;do{s.a=n,s=s.c}while(s!==i);i=e.f,(s=e.e).f=i,i.e=s}function G(e,n){var i=e.a,s=i;do{s.d=n,s=s.e}while(s!==i);i=e.d,(s=e.b).d=i,i.b=s}function ha(e){var n=0;return Math.abs(e[1])>Math.abs(e[0])&&(n=1),Math.abs(e[2])>Math.abs(e[n])&&(n=2),n}var i=4e150;function P(e,n){e.f+=n.f,e.b.f+=n.b.f}function ia(e,n,i){return e=e.a,n=n.a,i=i.a,n.b.a===e?i.b.a===e?u(n.a,i.a)?0>=x(i.b.a,n.a,i.a):0<=x(n.b.a,i.a,n.a):0>=x(i.b.a,e,i.a):i.b.a===e?0<=x(n.b.a,e,n.a):(n=v(n.b.a,e,n.a))>=(e=v(i.b.a,e,i.a))}function Q(e){e.a.i=null;var n=e.e;n.a.c=n.c,n.c.a=n.a,e.e=null}function ja(e,n){I(e.a),e.c=!1,e.a=n,n.i=e}function ka(e){var n=e.a.a;do{e=R(e)}while(e.a.a===n);return e.c&&(ja(e,n=L(S(e).a.b,e.a.e)),e=R(e)),e}function la(e,n,i){var s=new ma;return s.a=i,s.e=na(e.f,n.e,s),i.i=s}function oa(e,n){switch(e.s){case 100130:return!!(1&n);case 100131:return 0!==n;case 100132:return 0<n;case 100133:return 0>n;case 100134:return 2<=n||-2>=n}return!1}function pa(e){var n=e.a,i=n.d;i.c=e.d,i.a=n,Q(e)}function T(e,n,i){for(e=n,n=n.a;e!==i;){e.c=!1;var s=S(e),r=s.a;if(r.a!==n.a){if(!s.c){pa(e);break}ja(s,r=L(n.c.b,r.b))}n.c!==r&&(E(J(r),r),E(n,r)),pa(e),n=s.a,e=s}return n}function U(e,n,i,s,r,o){var h=!0;do{la(e,n,i.b),i=i.c}while(i!==s);for(null===r&&(r=S(n).a.b.c);(i=(s=S(n)).a.b).a===r.a;)i.c!==r&&(E(J(i),i),E(J(r),i)),s.f=n.f-i.f,s.d=oa(e,s.f),n.b=!0,!h&&qa(e,n)&&(P(i,r),Q(n),I(r)),h=!1,n=s,r=i;n.b=!0,o&&ra(e,n)}function sa(e,n,i,s,r){var o=[n.g[0],n.g[1],n.g[2]];n.d=null,n.d=e.o&&e.o(o,i,s,e.c)||null,null===n.d&&(r?e.n||(V(e,100156),e.n=!0):n.d=i[0])}function ta(e,n,i){var s=[null,null,null,null];s[0]=n.a.d,s[1]=i.a.d,sa(e,n.a,s,[.5,.5,0,0],!1),E(n,i)}function ua(e,n,i,s,r){var o=Math.abs(n.b-e.b)+Math.abs(n.a-e.a),h=Math.abs(i.b-e.b)+Math.abs(i.a-e.a),c=r+1;s[r]=.5*h/(o+h),s[c]=.5*o/(o+h),e.g[0]+=s[r]*n.g[0]+s[c]*i.g[0],e.g[1]+=s[r]*n.g[1]+s[c]*i.g[1],e.g[2]+=s[r]*n.g[2]+s[c]*i.g[2]}function qa(e,n){var i=S(n),s=n.a,r=i.a;if(u(s.a,r.a)){if(0<x(r.b.a,s.a,r.a))return!1;if(t(s.a,r.a)){if(s.a!==r.a){i=e.e;var o=s.a.h;if(0<=o){var h=(i=i.b).d,c=i.e,l=i.c,d=l[o];h[d]=h[i.a],l[h[d]]=d,d<=--i.a&&(1>=d||u(c[h[d>>1]],c[h[d]])?W(i,d):va(i,d)),c[o]=null,l[o]=i.b,i.b=o}else for(i.c[-(o+1)]=null;0<i.a&&null===i.c[i.d[i.a-1]];)--i.a;ta(e,J(r),s)}}else K(r.b),E(s,J(r)),n.b=i.b=!0}else{if(0>x(s.b.a,r.a,s.a))return!1;R(n).b=n.b=!0,K(s.b),E(J(r),s)}return!0}function wa(e,n){var i=S(n),s=n.a,r=i.a,o=s.a,h=r.a,c=s.b.a,l=r.b.a,d=new N;if(x(c,e.a,o),x(l,e.a,h),o===h||Math.min(o.a,c.a)>Math.max(h.a,l.a))return!1;if(u(o,h)){if(0<x(l,o,h))return!1}else if(0>x(c,h,o))return!1;var f,p,g=c,y=o,b=l,m=h;if(u(g,y)||(f=g,g=y,y=f),u(b,m)||(f=b,b=m,m=f),u(g,b)||(f=g,g=b,b=f,f=y,y=m,m=f),u(b,y)?u(y,m)?(0>(f=v(g,b,y))+(p=v(b,y,m))&&(f=-f,p=-p),d.b=A(f,b.b,p,y.b)):(0>(f=x(g,b,y))+(p=-x(g,m,y))&&(f=-f,p=-p),d.b=A(f,b.b,p,m.b)):d.b=(b.b+y.b)/2,z(g,y)||(f=g,g=y,y=f),z(b,m)||(f=b,b=m,m=f),z(g,b)||(f=g,g=b,b=f,f=y,y=m,m=f),z(b,y)?z(y,m)?(0>(f=aa(g,b,y))+(p=aa(b,y,m))&&(f=-f,p=-p),d.a=A(f,b.a,p,y.a)):(0>(f=ba(g,b,y))+(p=-ba(g,m,y))&&(f=-f,p=-p),d.a=A(f,b.a,p,m.a)):d.a=(b.a+y.a)/2,u(d,e.a)&&(d.b=e.a.b,d.a=e.a.a),g=u(o,h)?o:h,u(g,d)&&(d.b=g.b,d.a=g.a),t(d,o)||t(d,h))return qa(e,n),!1;if(!t(c,e.a)&&0<=x(c,e.a,d)||!t(l,e.a)&&0>=x(l,e.a,d)){if(l===e.a)return K(s.b),E(r.b,s),s=S(n=ka(n)).a,T(e,S(n),i),U(e,n,J(s),s,s,!0),!0;if(c===e.a){K(r.b),E(s.e,J(r)),h=(o=i=n).a.b.a;do{o=R(o)}while(o.a.b.a===h);return o=S(n=o).a.b.c,i.a=J(r),U(e,n,(r=T(e,i,null)).c,s.b.c,o,!0),!0}return 0<=x(c,e.a,d)&&(R(n).b=n.b=!0,K(s.b),s.a.b=e.a.b,s.a.a=e.a.a),0>=x(l,e.a,d)&&(n.b=i.b=!0,K(r.b),r.a.b=e.a.b,r.a.a=e.a.a),!1}return K(s.b),K(r.b),E(J(r),s),s.a.b=d.b,s.a.a=d.a,s.a.h=xa(e.e,s.a),s=s.a,r=[0,0,0,0],d=[o.d,c.d,h.d,l.d],s.g[0]=s.g[1]=s.g[2]=0,ua(s,o,c,r,0),ua(s,h,l,r,2),sa(e,s,d,r,!0),R(n).b=n.b=i.b=!0,!1}function ra(e,n){for(var i=S(n);;){for(;i.b;)n=i,i=S(i);if(!n.b&&(i=n,null===(n=R(n))||!n.b))break;n.b=!1;var s,r=n.a,o=i.a;if(s=r.b.a!==o.b.a)t:{var h=S(s=n),c=s.a,l=h.a,d=void 0;if(u(c.b.a,l.b.a)){if(0>x(c.b.a,l.b.a,c.a)){s=!1;break t}R(s).b=s.b=!0,d=K(c),E(l.b,d),d.d.c=s.d}else{if(0<x(l.b.a,c.b.a,l.a)){s=!1;break t}s.b=h.b=!0,d=K(l),E(c.e,l.b),d.b.d.c=s.d}s=!0}if(s&&(i.c?(Q(i),I(o),o=(i=S(n)).a):n.c&&(Q(n),I(r),r=(n=R(i)).a)),r.a!==o.a)if(r.b.a===o.b.a||n.c||i.c||r.b.a!==e.a&&o.b.a!==e.a)qa(e,n);else if(wa(e,n))break;r.a===o.a&&r.b.a===o.b.a&&(P(o,r),Q(n),I(r),n=R(i))}}function ya(e,n){e.a=n;for(var i=n.c;null===i.i;)if((i=i.c)===n.c){i=e;var s=n;(h=new ma).a=s.c.b;var r=(l=i.f).a;do{r=r.a}while(null!==r.b&&!l.c(l.b,h,r.b));var o=S(l=r.b),h=l.a;r=o.a;if(0===x(h.b.a,s,h.a))t((h=l.a).a,s)||t(h.b.a,s)||(K(h.b),l.c&&(I(h.c),l.c=!1),E(s.c,h),ya(i,s));else{var c=u(r.b.a,h.b.a)?l:o;o=void 0;l.d||c.c?(o=c===l?L(s.c.b,h.e):L(r.b.c.b,s.c).b,c.c?ja(c,o):(h=i,(l=la(i,l,o)).f=R(l).f+l.a.f,l.d=oa(h,l.f)),ya(i,s)):U(i,l,s.c,s.c,null,!0)}return}if(l=(h=S(i=ka(i.i))).a,(h=T(e,h,null)).c===l){h=(l=h).c,r=S(i),o=i.a,c=r.a;var l,d=!1;o.b.a!==c.b.a&&wa(e,i),t(o.a,e.a)&&(E(J(h),o),h=S(i=ka(i)).a,T(e,S(i),r),d=!0),t(c.a,e.a)&&(E(l,J(c)),l=T(e,r,null),d=!0),d?U(e,i,l.c,h,h,!0):(s=u(c.a,o.a)?J(c):o,U(e,i,s=L(l.c.b,s),s.c,s.c,!1),s.b.i.c=!0,ra(e,i))}else U(e,i,h.c,l,l,!0)}function za(e,n){var s=new ma,r=ea(e.b);r.a.b=i,r.a.a=n,r.b.a.b=-i,r.b.a.a=n,e.a=r.b.a,s.a=r,s.f=0,s.d=!1,s.c=!1,s.h=!0,s.b=!1,r=na(r=e.f,r.a,s),s.e=r}function Aa(e){this.a=new Ba,this.b=e,this.c=ia}function na(e,n,i){do{n=n.c}while(null!==n.b&&!e.c(e.b,n.b,i));return e=new Ba(i,n.a,n),n.a.c=e,n.a=e}function Ba(e,n,i){this.b=e||null,this.a=n||this,this.c=i||this}function X(){this.d=s,this.p=this.b=this.q=null,this.j=[0,0,0],this.s=100130,this.n=!1,this.o=this.a=this.e=this.f=null,this.m=!1,this.c=this.r=this.i=this.k=this.l=this.h=null}var s=0;function Z(e,n){if(e.d!==n)for(;e.d!==n;)if(e.d<n)switch(e.d){case s:V(e,100151),e.u(null);break;case 1:V(e,100152),e.t()}else switch(e.d){case 2:V(e,100154),e.v();break;case 1:V(e,100153),e.w()}}function V(e,n){e.p&&e.p(n,e.c)}function ga(e,n){this.b=e||this,this.d=n||this,this.a=null,this.c=!1}function M(){this.h=this,this.i=this.d=this.a=this.e=this.c=this.b=null,this.f=0}function J(e){return e.b.e}function Ca(){this.c=new N,this.a=new ga,this.b=new M,this.d=new M,this.b.b=this.d,this.d.b=this.b}function N(e,n){this.e=e||this,this.f=n||this,this.d=this.c=null,this.g=[0,0,0],this.h=this.a=this.b=0}function Da(){this.c=[],this.d=null,this.a=0,this.e=!1,this.b=new Ha}function xa(e,n){if(e.e){var i,s=e.b,r=++s.a;return 2*r>s.f&&(s.f*=2,s.c=Ja(s.c,s.f+1)),0===s.b?i=r:(i=s.b,s.b=s.c[s.b]),s.e[i]=n,s.c[i]=r,s.d[r]=i,s.h&&va(s,r),i}return s=e.a++,e.c[s]=n,-(s+1)}function Fa(e){if(0===e.a)return Ka(e.b);var n=e.c[e.d[e.a-1]];if(0!==e.b.a&&u(Ga(e.b),n))return Ka(e.b);do{--e.a}while(0<e.a&&null===e.c[e.d[e.a-1]]);return n}function Ha(){this.d=Ja([0],33),this.e=[null,null],this.c=[0,0],this.a=0,this.f=32,this.b=0,this.h=!1,this.d[1]=1}function Ja(e,n){for(var i=Array(n),s=0;s<e.length;s++)i[s]=e[s];for(;s<n;s++)i[s]=0;return i}function Ga(e){return e.e[e.d[1]]}function Ka(e){var n=e.d,i=e.e,s=e.c,r=n[1],o=i[r];return 0<e.a&&(n[1]=n[e.a],s[n[1]]=1,i[r]=null,s[r]=e.b,e.b=r,0<--e.a&&W(e,1)),o}function W(e,n){for(var i=e.d,s=e.e,r=e.c,o=n,h=i[o];;){var c=o<<1;c<e.a&&u(s[i[c+1]],s[i[c]])&&(c+=1);var l=i[c];if(c>e.a||u(s[h],s[l])){i[o]=h,r[h]=o;break}i[o]=l,r[l]=o,o=c}}function va(e,n){for(var i=e.d,s=e.e,r=e.c,o=n,h=i[o];;){var c=o>>1,l=i[c];if(0===c||u(s[l],s[h])){i[o]=h,r[h]=o;break}i[o]=l,r[l]=o,o=c}}function ma(){this.e=this.a=null,this.f=0,this.c=this.b=this.h=this.d=!1}function S(e){return e.e.c.b}function R(e){return e.e.a.b}(n=X.prototype).x=function(){Z(this,s)},n.B=function(e,n){switch(e){case 100142:return;case 100140:switch(n){case 100130:case 100131:case 100132:case 100133:case 100134:return void(this.s=n)}break;case 100141:return void(this.m=!!n);default:return void V(this,100900)}V(this,100901)},n.y=function(e){switch(e){case 100142:return 0;case 100140:return this.s;case 100141:return this.m;default:V(this,100900)}return!1},n.A=function(e,n,i){this.j[0]=e,this.j[1]=n,this.j[2]=i},n.z=function(e,n){var i=n||null;switch(e){case 100100:case 100106:this.h=i;break;case 100104:case 100110:this.l=i;break;case 100101:case 100107:this.k=i;break;case 100102:case 100108:this.i=i;break;case 100103:case 100109:this.p=i;break;case 100105:case 100111:this.o=i;break;case 100112:this.r=i;break;default:V(this,100900)}},n.C=function(e,n){var i=!1,s=[0,0,0];Z(this,2);for(var r=0;3>r;++r){var o=e[r];-1e150>o&&(o=-1e150,i=!0),1e150<o&&(o=1e150,i=!0),s[r]=o}i&&V(this,100155),null===(i=this.q)?E(i=ea(this.b),i.b):(K(i),i=i.e),i.a.d=n,i.a.g[0]=s[0],i.a.g[1]=s[1],i.a.g[2]=s[2],i.f=1,i.b.f=-1,this.q=i},n.u=function(e){Z(this,s),this.d=1,this.b=new Ca,this.c=e},n.t=function(){Z(this,1),this.d=2,this.q=null},n.v=function(){Z(this,2),this.d=1},n.w=function(){Z(this,1),this.d=s;var e=!1,n=[l=this.j[0],r=this.j[1],h=this.j[2]];if(0===l&&0===r&&0===h){for(var r=[-2e150,-2e150,-2e150],o=[2e150,2e150,2e150],h=[],c=[],l=(e=this.b.c).e;l!==e;l=l.e)for(var d=0;3>d;++d){var f=l.g[d];f<o[d]&&(o[d]=f,c[d]=l),f>r[d]&&(r[d]=f,h[d]=l)}if(l=0,r[1]-o[1]>r[0]-o[0]&&(l=1),r[2]-o[2]>r[l]-o[l]&&(l=2),o[l]>=r[l])n[0]=0,n[1]=0,n[2]=1;else{for(r=0,o=c[l],h=h[l],c=[0,0,0],o=[o.g[0]-h.g[0],o.g[1]-h.g[1],o.g[2]-h.g[2]],d=[0,0,0],l=e.e;l!==e;l=l.e)d[0]=l.g[0]-h.g[0],d[1]=l.g[1]-h.g[1],d[2]=l.g[2]-h.g[2],c[0]=o[1]*d[2]-o[2]*d[1],c[1]=o[2]*d[0]-o[0]*d[2],c[2]=o[0]*d[1]-o[1]*d[0],(f=c[0]*c[0]+c[1]*c[1]+c[2]*c[2])>r&&(r=f,n[0]=c[0],n[1]=c[1],n[2]=c[2]);0>=r&&(n[0]=n[1]=n[2]=0,n[ha(o)]=1)}e=!0}for(c=ha(n),l=this.b.c,r=(c+1)%3,h=(c+2)%3,c=0<n[c]?1:-1,n=l.e;n!==l;n=n.e)n.b=n.g[r],n.a=c*n.g[h];if(e){for(n=0,l=(e=this.b.a).b;l!==e;l=l.b)if(!(0>=(r=l.a).f))do{n+=(r.a.b-r.b.a.b)*(r.a.a+r.b.a.a),r=r.e}while(r!==l.a);if(0>n)for(e=(n=this.b.c).e;e!==n;e=e.e)e.a=-e.a}for(this.n=!1,l=(n=this.b.b).h;l!==n;l=e)e=l.h,r=l.e,t(l.a,l.b.a)&&l.e.e!==l&&(ta(this,r,l),I(l),r=(l=r).e),r.e===l&&(r!==l&&(r!==e&&r!==e.b||(e=e.h),I(r)),l!==e&&l!==e.b||(e=e.h),I(l));for(this.e=n=new Da,l=(e=this.b.c).e;l!==e;l=l.e)l.h=xa(n,l);for(function(e){e.d=[];for(var n=0;n<e.a;n++)e.d[n]=n;e.d.sort(function(e){return function(n,i){return u(e[n],e[i])?1:-1}}(e.c)),e.e=!0,function(e){for(var n=e.a;1<=n;--n)W(e,n);e.h=!0}(e.b)}(n),this.f=new Aa(this),za(this,-i),za(this,i);null!==(n=Fa(this.e));){for(;;){t:if(l=this.e,0===l.a)e=Ga(l.b);else if(e=l.c[l.d[l.a-1]],0!==l.b.a&&(l=Ga(l.b),u(l,e))){e=l;break t}if(null===e||!t(e,n))break;e=Fa(this.e),ta(this,n.c,e.c)}ya(this,n)}for(this.a=this.f.a.a.b.a.a,n=0;null!==(e=this.f.a.a.b);)e.h||++n,Q(e);for(this.f=null,(n=this.e).b=null,n.d=null,this.e=n.c=null,l=(n=this.b).a.b;l!==n.a;l=e)e=l.b,(l=l.a).e.e===l&&(P(l.c,l),I(l));if(!this.n){if(n=this.b,this.m)for(l=n.b.h;l!==n.b;l=e)e=l.h,l.b.d.c!==l.d.c?l.f=l.d.c?1:-1:I(l);else for(l=n.a.b;l!==n.a;l=e)if(e=l.b,l.c){for(l=l.a;u(l.b.a,l.a);l=l.c.b);for(;u(l.a,l.b.a);l=l.e);for(r=l.c.b,h=void 0;l.e!==r;)if(u(l.b.a,r.a)){for(;r.e!==l&&(ca(r.e)||0>=x(r.a,r.b.a,r.e.b.a));)r=(h=L(r.e,r)).b;r=r.c.b}else{for(;r.e!==l&&(da(l.c.b)||0<=x(l.b.a,l.a,l.c.b.a));)l=(h=L(l,l.c.b)).b;l=l.e}for(;r.e.e!==l;)r=(h=L(r.e,r)).b}if(this.h||this.i||this.k||this.l)if(this.m){for(e=(n=this.b).a.b;e!==n.a;e=e.b)if(e.c){this.h&&this.h(2,this.c),l=e.a;do{this.k&&this.k(l.a.d,this.c),l=l.e}while(l!==e.a);this.i&&this.i(this.c)}}else{for(n=this.b,e=!!this.l,l=!1,r=-1,h=n.a.d;h!==n.a;h=h.d)if(h.c){l||(this.h&&this.h(4,this.c),l=!0),c=h.a;do{e&&(r!==(o=c.b.d.c?0:1)&&(r=o,this.l&&this.l(!!r,this.c))),this.k&&this.k(c.a.d,this.c),c=c.e}while(c!==h.a)}l&&this.i&&this.i(this.c)}if(this.r){for(l=(n=this.b).a.b;l!==n.a;l=e)if(e=l.b,!l.c){h=(r=l.a).e,c=void 0;do{h=(c=h).e,c.d=null,null===c.b.d&&(c.c===c?F(c.a,null):(c.a.c=c.c,H(c,J(c))),(o=c.b).c===o?F(o.a,null):(o.a.c=o.c,H(o,J(o))),fa(c))}while(c!==r);r=l.d,(l=l.b).d=r,r.b=l}return this.r(this.b),void(this.c=this.b=null)}}this.b=this.c=null},Y.libtess={GluTesselator:X,windingRule:{GLU_TESS_WINDING_ODD:100130,GLU_TESS_WINDING_NONZERO:100131,GLU_TESS_WINDING_POSITIVE:100132,GLU_TESS_WINDING_NEGATIVE:100133,GLU_TESS_WINDING_ABS_GEQ_TWO:100134},primitiveType:{GL_LINE_LOOP:2,GL_TRIANGLES:4,GL_TRIANGLE_STRIP:5,GL_TRIANGLE_FAN:6},errorType:{GLU_TESS_MISSING_BEGIN_POLYGON:100151,GLU_TESS_MISSING_END_POLYGON:100153,GLU_TESS_MISSING_BEGIN_CONTOUR:100152,GLU_TESS_MISSING_END_CONTOUR:100154,GLU_TESS_COORD_TOO_LARGE:100155,GLU_TESS_NEED_COMBINE_CALLBACK:100156},gluEnum:{GLU_TESS_MESH:100112,GLU_TESS_TOLERANCE:100142,GLU_TESS_WINDING_RULE:100140,GLU_TESS_BOUNDARY_ONLY:100141,GLU_INVALID_ENUM:100900,GLU_INVALID_VALUE:100901,GLU_TESS_BEGIN:100100,GLU_TESS_VERTEX:100101,GLU_TESS_END:100102,GLU_TESS_ERROR:100103,GLU_TESS_EDGE_FLAG:100104,GLU_TESS_COMBINE:100105,GLU_TESS_BEGIN_DATA:100106,GLU_TESS_VERTEX_DATA:100107,GLU_TESS_END_DATA:100108,GLU_TESS_ERROR_DATA:100109,GLU_TESS_EDGE_FLAG_DATA:100110,GLU_TESS_COMBINE_DATA:100111}},X.prototype.gluDeleteTess=X.prototype.x,X.prototype.gluTessProperty=X.prototype.B,X.prototype.gluGetTessProperty=X.prototype.y,X.prototype.gluTessNormal=X.prototype.A,X.prototype.gluTessCallback=X.prototype.z,X.prototype.gluTessVertex=X.prototype.C,X.prototype.gluTessBeginPolygon=X.prototype.u,X.prototype.gluTessBeginContour=X.prototype.t,X.prototype.gluTessEndContour=X.prototype.v,X.prototype.gluTessEndPolygon=X.prototype.w,e.exports=Y.libtess}(q);var tt=q.exports;class Tessellator{process(e,n=!0,s=!1){if(0===e.length)return{triangles:{vertices:[],indices:[]},contours:[]};const r=e.filter(e=>e.points.length>=3);return 0===r.length?{triangles:{vertices:[],indices:[]},contours:[]}:(i.log(`Tessellator: removeOverlaps=${n}, processing ${r.length} paths`),this.tessellate(r,n,s))}tessellate(e,n,s){const r=s||n?e:e.map(e=>this.reverseWinding(e));let o=this.pathsToContours(r);if(n){i.log("Two-pass: boundary extraction then triangulation");const e=this.performTessellation(o,"boundary");if(!e)return i.warn("libtess returned empty result from boundary pass"),{triangles:{vertices:[],indices:[]},contours:[]};o=this.boundaryToContours(e),i.log(`Boundary pass created ${o.length} contours. Starting triangulation pass.`)}else i.log("Single-pass triangulation for "+(s?"CFF":"TTF"));const h=this.performTessellation(o,"triangles");if(!h){const e=n?"libtess returned empty result from triangulation pass":"libtess returned empty result from single-pass triangulation";return i.warn(e),{triangles:{vertices:[],indices:[]},contours:o}}return{triangles:{vertices:h.vertices,indices:h.indices||[]},contours:o}}pathsToContours(e){return e.map(e=>{const n=[];for(const i of e.points)n.push(i.x,i.y);return n})}performTessellation(e,n){const s=new tt.GluTesselator;s.gluTessProperty(tt.gluEnum.GLU_TESS_WINDING_RULE,tt.windingRule.GLU_TESS_WINDING_NONZERO);const r=[],o=[],h=[];let c=[];"boundary"===n&&s.gluTessProperty(tt.gluEnum.GLU_TESS_BOUNDARY_ONLY,!0),"triangles"===n?s.gluTessCallback(tt.gluEnum.GLU_TESS_VERTEX_DATA,e=>{o.push(e)}):(s.gluTessCallback(tt.gluEnum.GLU_TESS_BEGIN,()=>{c=[]}),s.gluTessCallback(tt.gluEnum.GLU_TESS_VERTEX_DATA,e=>{c.push(e)}),s.gluTessCallback(tt.gluEnum.GLU_TESS_END,()=>{c.length>0&&h.push([...c])})),s.gluTessCallback(tt.gluEnum.GLU_TESS_COMBINE,e=>{const n=r.length/2;return r.push(e[0],e[1]),n}),s.gluTessCallback(tt.gluEnum.GLU_TESS_ERROR,e=>{i.warn(`libtess error: ${e}`)}),s.gluTessNormal(0,0,1),s.gluTessBeginPolygon(null);for(const n of e){s.gluTessBeginContour();for(let e=0;e<n.length;e+=2){const i=r.length/2;r.push(n[e],n[e+1]),s.gluTessVertex([n[e],n[e+1],0],i)}s.gluTessEndContour()}return s.gluTessEndPolygon(),0===r.length?null:"triangles"===n?{vertices:r,indices:o}:{vertices:r,contourIndices:h}}boundaryToContours(e){if(!e.contourIndices)return[];const n=[];for(const i of e.contourIndices){const s=[];for(const n of i){const i=2*n;s.push(e.vertices[i],e.vertices[i+1])}s.length>2&&(s[0]===s[s.length-2]&&s[1]===s[s.length-1]||s.push(s[0],s[1])),n.push(s)}return n}reverseWinding(e){return{...e,points:[...e.points].reverse()}}}class Extruder{constructor(){}extrude(e,n=0,i){const s=[],r=[],o=[];if(0===n)this.addFlatFaces(e.triangles,s,r,o);else{this.addFrontAndBackFaces(e.triangles,s,r,o,n,i);for(const i of e.contours)this.addSideWalls(i,s,r,o,n)}return{vertices:s,normals:r,indices:o}}addFlatFaces(e,n,i,s){const r=n.length/3,o=e.vertices,h=e.indices;for(let e=0;e<o.length;e+=2)n.push(o[e],o[e+1],0),i.push(0,0,-1);for(let e=0;e<h.length;e++)s.push(r+h[e])}addFrontAndBackFaces(e,n,i,s,r,o){const h=n.length/3,c=e.vertices,l=e.indices;for(let e=0;e<c.length;e+=2)n.push(c[e],c[e+1],0),i.push(0,0,-1);const d=25e-6*o,f=r<=d?d:r;for(let e=0;e<c.length;e+=2)n.push(c[e],c[e+1],f),i.push(0,0,1);const p=c.length/2;for(let e=0;e<l.length;e++)s.push(h+l[e]);for(let e=l.length-1;e>=0;e--)s.push(h+l[e]+p)}addSideWalls(e,n,i,s,r){for(let o=0;o<e.length-2;o+=2){const h=e[o],c=e[o+1],l=e[o+2],d=e[o+3],f=new Vec2(l-h,d-c),p=new Vec2(f.y,-f.x).normalize(),g=n.length/3;n.push(h,c,0,l,d,0,h,c,r,l,d,r),i.push(p.x,p.y,0,p.x,p.y,0,p.x,p.y,0,p.x,p.y,0),s.push(g,g+1,g+2,g+1,g+3,g+2)}}}class BoundaryClusterer{constructor(){}cluster(e,n){return 0===e.length?[]:this.clusterSweepLine(e,n)}clusterSweepLine(e,n){const i=e.length;if(i<=1)return 0===i?[]:[[0]];const s=new Array(i),r=new Array(2*i);let o=0;for(let h=0;h<i;h++)s[h]=this.getWorldBounds(e[h],n[h]),r[o++]=[s[h].minX,0,h],r[o++]=[s[h].maxX,1,h];r.sort((e,n)=>e[0]-n[0]||e[1]-n[1]);const h=Array.from({length:i},(e,n)=>n),c=new Array(i).fill(0);function find(e){return h[e]===e?e:h[e]=find(h[e])}function union(e,n){const i=find(e),s=find(n);i!==s&&(c[i]<c[s]?h[i]=s:c[i]>c[s]?h[s]=i:(h[s]=i,c[i]++))}const l=new Set;for(const[,e,n]of r)if(0===e){const e=s[n];for(const i of l){const r=s[i];e.minY<r.maxY+.001&&e.maxY>r.minY-.001&&union(n,i)}l.add(n)}else l.delete(n);const d=new Map;for(let e=0;e<i;e++){const n=find(e);d.has(n)||d.set(n,[]),d.get(n).push(e)}return Array.from(d.values())}getWorldBounds(e,n){return{minX:e.bounds.min.x+n.x,minY:e.bounds.min.y+n.y,maxX:e.bounds.max.x+n.x,maxY:e.bounds.max.y+n.y}}}class MinHeap{constructor(e){this.heap=[],this.itemIndex=new Map,this.compare=e}insert(e){const n=this.itemIndex.get(e);if(void 0!==n)return this.siftUp(n),void this.siftDown(n);const i=this.heap.length;this.heap.push(e),this.itemIndex.set(e,i),this.siftUp(i)}extractMin(){const e=this.heap.length;if(!e)return;if(1===e){const e=this.heap.pop();return this.itemIndex.clear(),e}const n=this.heap[0],i=this.heap.pop();return this.heap[0]=i,this.itemIndex.delete(n),this.itemIndex.set(i,0),this.siftDown(0),n}update(e){const n=this.itemIndex.get(e);void 0!==n?(this.siftUp(n),this.siftDown(n)):this.insert(e)}isEmpty(){return!this.heap.length}swap(e,n){const i=this.heap[e],s=this.heap[n];this.heap[e]=s,this.heap[n]=i,this.itemIndex.set(i,n),this.itemIndex.set(s,e)}siftUp(e){const n=this.heap[e];for(;e>0;){const i=e-1>>1,s=this.heap[i];if(this.compare(n,s)>=0)break;this.heap[e]=s,this.itemIndex.set(s,e),e=i}this.heap[e]=n,this.itemIndex.set(n,e)}siftDown(e){const n=this.heap[e],i=this.heap.length,s=i>>1;for(;e<s;){const s=1+(e<<1),r=s+1;let o=e,h=n;const c=this.heap[s];if(this.compare(c,h)<0&&(o=s,h=c),r<i){const e=this.heap[r];this.compare(e,h)<0&&(o=r,h=e)}if(o===e)break;this.heap[e]=h,this.itemIndex.set(h,e),e=o}this.heap[e]=n,this.itemIndex.set(n,e)}}const et={enabled:!0,areaThreshold:1,colinearThreshold:.0087,minSegmentLength:10};class PathOptimizer{constructor(e){this.stats={pointsRemovedByVisvalingam:0,pointsRemovedByColinear:0,originalPointCount:0},this.config=e}setConfig(e){this.config=e}optimizePath(e){if(!this.config.enabled||e.points.length<=2)return e;this.stats.originalPointCount+=e.points.length;let n=[...e.points];return n.length<5?e:(n=this.simplifyPathVW(n,this.config.areaThreshold),n.length<3?e:(n=this.removeColinearPoints(n,this.config.colinearThreshold),n.length<3?e:{...e,points:n}))}simplifyPathVW(e,n){if(e.length<=3)return e;const i=e.length,s=e.map((e,n)=>({index:n,area:1/0,prev:null,next:null}));for(let e=0;e<s.length;e++)s[e].prev=s[e-1]||null,s[e].next=s[e+1]||null;const r=new MinHeap((e,n)=>e.area-n.area);for(let n=1;n<s.length-1;n++){const i=s[n];i.area=this.calculateTriangleArea(e[i.prev.index],e[i.index],e[i.next.index]),r.insert(i)}let o=i;for(;!r.isEmpty()&&o>3;){const i=r.extractMin();if(!i||i.area>n)break;if(this.config.minSegmentLength>0&&i.prev&&i.next){const n=e[i.prev.index],s=e[i.index],r=e[i.next.index],o=n.distanceTo(s),h=s.distanceTo(r);if(o<this.config.minSegmentLength||h<this.config.minSegmentLength)continue}i.prev&&(i.prev.next=i.next),i.next&&(i.next.prev=i.prev),o--,i.prev&&i.prev.prev&&(i.prev.area=this.calculateTriangleArea(e[i.prev.prev.index],e[i.prev.index],e[i.next.index]),r.update(i.prev)),i.next&&i.next.next&&(i.next.area=this.calculateTriangleArea(e[i.prev.index],e[i.next.index],e[i.next.next.index]),r.update(i.next))}const h=[];let c=s[0];for(;c;)h.push(e[c.index]),c=c.next;const l=i-h.length;return this.stats.pointsRemovedByVisvalingam+=l,h}removeColinearPoints(e,n){if(e.length<=2)return e;const i=[e[0]];for(let s=1;s<e.length-1;s++){const r=e[s-1],o=e[s],h=e[s+1],c=new Vec2(o.x-r.x,o.y-r.y),l=new Vec2(h.x-o.x,h.y-o.y),d=Math.abs(c.angle()-l.angle());Math.min(d,2*Math.PI-d)>n||c.length()<this.config.minSegmentLength||l.length()<this.config.minSegmentLength?i.push(o):this.stats.pointsRemovedByColinear++}return i.push(e[e.length-1]),i}calculateTriangleArea(e,n,i){return Math.abs((e.x*(n.y-i.y)+n.x*(i.y-e.y)+i.x*(e.y-n.y))/2)}getStats(){return{...this.stats}}resetStats(){this.stats={pointsRemovedByVisvalingam:0,pointsRemovedByColinear:0,originalPointCount:0}}}const nt={distanceTolerance:.5,angleTolerance:.2},it=1e-6;class Polygonizer{constructor(e){this.curveFidelityConfig={...nt,...e}}setCurveFidelityConfig(e){this.curveFidelityConfig={...nt,...e}}polygonizeQuadratic(e,n,i){const s=[];return this.recursiveQuadratic(e.x,e.y,n.x,n.y,i.x,i.y,s),this.addPoint(i.x,i.y,s),s}polygonizeCubic(e,n,i,s){const r=[];return this.recursiveCubic(e.x,e.y,n.x,n.y,i.x,i.y,s.x,s.y,r),this.addPoint(s.x,s.y,r),r}recursiveQuadratic(e,n,i,s,r,o,h,c=0){if(c>16)return;const l=(e+i)/2,d=(n+s)/2,f=(i+r)/2,p=(s+o)/2,g=(l+f)/2,y=(d+p)/2,b=r-e,m=o-n,_=Math.abs((i-r)*m-(s-o)*b),w=this.curveFidelityConfig.distanceTolerance??nt.distanceTolerance,O=w*w;if(_>it){if(_*_<=O*(b*b+m*m)){const c=this.curveFidelityConfig.angleTolerance??nt.angleTolerance;if(!(c>0))return void this.addPoint(i,s,h);{let l=Math.abs(Math.atan2(o-s,r-i)-Math.atan2(s-n,i-e));if(l>=Math.PI&&(l=2*Math.PI-l),l<c)return void this.addPoint(i,s,h)}}}else{const r=b*b+m*m;if(0===r){if((i-e)*(i-e)+(s-n)*(s-n)<=O)return void this.addPoint(i,s,h)}else{const o=((i-e)*b+(s-n)*m)/r;if(o>0&&o<1&&_*_<=O*r)return void this.addPoint(i,s,h)}}this.recursiveQuadratic(e,n,l,d,g,y,h,c+1),this.recursiveQuadratic(g,y,f,p,r,o,h,c+1)}recursiveCubic(e,n,i,s,r,o,h,c,l,d=0){if(d>16)return;const f=(e+i)/2,p=(n+s)/2,g=(i+r)/2,y=(s+o)/2,b=(r+h)/2,m=(o+c)/2,_=(f+g)/2,w=(p+y)/2,O=(g+b)/2,k=(y+m)/2,j=(_+O)/2,$=(w+k)/2,Y=h-e,q=c-n,tt=Math.abs((i-h)*q-(s-c)*Y),et=Math.abs((r-h)*q-(o-c)*Y),st=this.curveFidelityConfig.distanceTolerance??nt.distanceTolerance,rt=st*st;let at=0;switch(tt>it&&(at|=1),et>it&&(at|=2),at){case 0:const d=Y*Y+q*q;if(0===d){if((i-e)*(i-e)+(s-n)*(s-n)<=rt&&(r-e)*(r-e)+(o-n)*(o-n)<=rt)return this.addPoint(i,s,l),void this.addPoint(r,o,l)}else{const h=((i-e)*Y+(s-n)*q)/d,c=((r-e)*Y+(o-n)*q)/d;if(h>0&&h<1&&c>0&&c<1&&(tt+et)*(tt+et)<=rt*d)return this.addPoint(i,s,l),void this.addPoint(r,o,l)}break;case 1:if(et*et<=rt*(Y*Y+q*q)){const e=this.curveFidelityConfig.angleTolerance??nt.angleTolerance;if(!(e>0))return this.addPoint(i,s,l),void this.addPoint(r,o,l);{let n=Math.abs(Math.atan2(c-o,h-r)-Math.atan2(o-s,r-i));if(n>=Math.PI&&(n=2*Math.PI-n),n<e)return this.addPoint(i,s,l),void this.addPoint(r,o,l)}}break;case 2:if(tt*tt<=rt*(Y*Y+q*q)){const h=this.curveFidelityConfig.angleTolerance??nt.angleTolerance;if(!(h>0))return this.addPoint(i,s,l),void this.addPoint(r,o,l);{let c=Math.abs(Math.atan2(o-s,r-i)-Math.atan2(s-n,i-e));if(c>=Math.PI&&(c=2*Math.PI-c),c<h)return this.addPoint(i,s,l),void this.addPoint(r,o,l)}}break;case 3:if((tt+et)*(tt+et)<=rt*(Y*Y+q*q)){const d=this.curveFidelityConfig.angleTolerance??nt.angleTolerance;if(!(d>0))return this.addPoint(i,s,l),void this.addPoint(r,o,l);{let f=Math.abs(Math.atan2(o-s,r-i)-Math.atan2(s-n,i-e)),p=Math.abs(Math.atan2(c-o,h-r)-Math.atan2(o-s,r-i));if(f>=Math.PI&&(f=2*Math.PI-f),p>=Math.PI&&(p=2*Math.PI-p),f+p<d)return this.addPoint(i,s,l),void this.addPoint(r,o,l)}}}this.recursiveCubic(e,n,f,p,_,w,j,$,l,d+1),this.recursiveCubic(j,$,O,k,b,m,h,c,l,d+1)}addPoint(e,n,i){const s=new Vec2(e,n);if(0===i.length)return void i.push(s);const r=i[i.length-1],o=s.x-r.x,h=s.y-r.y;o*o+h*h>1e-12&&i.push(s)}}class GlyphContourCollector{constructor(e,n){this.currentGlyphId=0,this.currentTextIndex=0,this.currentGlyphPaths=[],this.currentPath=null,this.currentPoint=null,this.currentGlyphBounds={min:new Vec2(1/0,1/0),max:new Vec2(-1/0,-1/0)},this.collectedGlyphs=[],this.glyphPositions=[],this.glyphTextIndices=[],this.currentPosition=new Vec2(0,0),this.polygonizer=new Polygonizer(e),this.pathOptimizer=new PathOptimizer({...et,...n})}setPosition(e,n){this.currentPosition.set(e,n)}updatePosition(e,n){this.currentPosition.x+=e,this.currentPosition.y+=n}beginGlyph(e,n){this.currentGlyphPaths.length>0&&this.finishGlyph(),this.currentGlyphId=e,this.currentTextIndex=n,this.currentGlyphPaths=[],this.currentGlyphBounds.min.set(1/0,1/0),this.currentGlyphBounds.max.set(-1/0,-1/0),this.glyphPositions.push(this.currentPosition.clone())}finishGlyph(){this.currentPath&&this.finishPath(),this.currentGlyphPaths.length>0&&(this.collectedGlyphs.push({glyphId:this.currentGlyphId,paths:[...this.currentGlyphPaths],bounds:{min:{x:this.currentGlyphBounds.min.x,y:this.currentGlyphBounds.min.y},max:{x:this.currentGlyphBounds.max.x,y:this.currentGlyphBounds.max.y}}}),this.glyphTextIndices.push(this.currentTextIndex)),this.currentGlyphPaths=[]}onMoveTo(e,n){this.currentPath&&this.finishPath(),this.currentPoint=new Vec2(e,n),this.updateBounds(this.currentPoint),this.currentPath={points:[this.currentPoint],glyphIndex:this.currentGlyphId}}onLineTo(e,n){if(!this.currentPath||!this.currentPoint)return;const i=new Vec2(e,n);this.updateBounds(i),this.currentPath.points.push(i),this.currentPoint=i}onQuadTo(e,n,i,s){if(!this.currentPath||!this.currentPoint)return;const r=this.currentPoint,o=new Vec2(e,n),h=new Vec2(i,s),c=h.x-r.x,l=h.y-r.y;if(Math.abs((o.x-h.x)*l-(o.y-h.y)*c)<it)return void this.onLineTo(i,s);const d=this.polygonizer.polygonizeQuadratic(r,o,h);for(const e of d)this.updateBounds(e);for(let e=0;e<d.length;e++)this.currentPath.points.push(d[e]);this.currentPoint=h}onCubicTo(e,n,i,s,r,o){if(!this.currentPath||!this.currentPoint)return;const h=this.currentPoint,c=new Vec2(e,n),l=new Vec2(i,s),d=new Vec2(r,o),f=d.x-h.x,p=d.y-h.y,g=Math.abs((c.x-d.x)*p-(c.y-d.y)*f),y=Math.abs((l.x-d.x)*p-(l.y-d.y)*f);if(g<it&&y<it)return void this.onLineTo(r,o);const b=this.polygonizer.polygonizeCubic(h,c,l,d);for(const e of b)this.updateBounds(e);for(let e=0;e<b.length;e++)this.currentPath.points.push(b[e]);this.currentPoint=d}onClosePath(){if(!this.currentPath||!this.currentPoint)return;const e=this.currentPath.points[0];this.currentPoint.equals(e)||this.currentPath.points.push(e),this.finishPath()}finishPath(){if(this.currentPath){const e=this.pathOptimizer.optimizePath(this.currentPath);this.currentGlyphPaths.push(e),this.currentPath=null,this.currentPoint=null}}updateBounds(e){this.currentGlyphBounds.min.x=Math.min(this.currentGlyphBounds.min.x,e.x),this.currentGlyphBounds.min.y=Math.min(this.currentGlyphBounds.min.y,e.y),this.currentGlyphBounds.max.x=Math.max(this.currentGlyphBounds.max.x,e.x),this.currentGlyphBounds.max.y=Math.max(this.currentGlyphBounds.max.y,e.y)}getCollectedGlyphs(){return this.currentGlyphPaths.length>0&&this.finishGlyph(),this.collectedGlyphs}getGlyphPositions(){return this.glyphPositions}getTextIndices(){return this.glyphTextIndices}reset(){this.collectedGlyphs=[],this.glyphPositions=[],this.glyphTextIndices=[],this.currentGlyphPaths=[],this.currentPath=null,this.currentPoint=null,this.currentGlyphId=0,this.currentTextIndex=0,this.currentPosition.set(0,0),this.currentGlyphBounds={min:new Vec2(1/0,1/0),max:new Vec2(-1/0,-1/0)}}setCurveFidelityConfig(e){this.polygonizer.setCurveFidelityConfig(e)}setGeometryOptimization(e){this.pathOptimizer.setConfig({...et,...e})}getOptimizationStats(){return this.pathOptimizer.getStats()}}class DrawCallbackHandler{constructor(){this.moveTo_func=null,this.lineTo_func=null,this.quadTo_func=null,this.cubicTo_func=null,this.closePath_func=null,this.drawFuncsPtr=0,this.position={x:0,y:0}}setPosition(e,n){this.position.x=e,this.position.y=n,this.collector&&this.collector.setPosition(e,n)}updatePosition(e,n){this.position.x+=e,this.position.y+=n,this.collector&&this.collector.updatePosition(e,n)}createDrawFuncs(e,n){if(!e||!e.module||!e.hb)throw new Error("Invalid font object");if(this.collector=n,this.drawFuncsPtr)return;const i=e.module;this.moveTo_func=i.addFunction((e,n,i,s,r)=>{this.collector?.onMoveTo(s,r)},"viiiffi"),this.lineTo_func=i.addFunction((e,n,i,s,r)=>{this.collector?.onLineTo(s,r)},"viiiffi"),this.quadTo_func=i.addFunction((e,n,i,s,r,o,h)=>{this.collector?.onQuadTo(s,r,o,h)},"viiiffffi"),this.cubicTo_func=i.addFunction((e,n,i,s,r,o,h,c,l)=>{this.collector?.onCubicTo(s,r,o,h,c,l)},"viiiffffffi"),this.closePath_func=i.addFunction((e,n,i)=>{this.collector?.onClosePath()},"viiii"),this.drawFuncsPtr=i.exports.hb_draw_funcs_create(),i.exports.hb_draw_funcs_set_move_to_func(this.drawFuncsPtr,this.moveTo_func,0,0),i.exports.hb_draw_funcs_set_line_to_func(this.drawFuncsPtr,this.lineTo_func,0,0),i.exports.hb_draw_funcs_set_quadratic_to_func(this.drawFuncsPtr,this.quadTo_func,0,0),i.exports.hb_draw_funcs_set_cubic_to_func(this.drawFuncsPtr,this.cubicTo_func,0,0),i.exports.hb_draw_funcs_set_close_path_func(this.drawFuncsPtr,this.closePath_func,0,0)}getDrawFuncsPtr(){if(!this.drawFuncsPtr)throw new Error("Draw functions not initialized");return this.drawFuncsPtr}destroy(e){if(!e||!e.module||!e.hb)return;const n=e.module;try{this.drawFuncsPtr&&(n.exports.hb_draw_funcs_destroy(this.drawFuncsPtr),this.drawFuncsPtr=0),null!==this.moveTo_func&&(n.removeFunction(this.moveTo_func),this.moveTo_func=null),null!==this.lineTo_func&&(n.removeFunction(this.lineTo_func),this.lineTo_func=null),null!==this.quadTo_func&&(n.removeFunction(this.quadTo_func),this.quadTo_func=null),null!==this.cubicTo_func&&(n.removeFunction(this.cubicTo_func),this.cubicTo_func=null),null!==this.closePath_func&&(n.removeFunction(this.closePath_func),this.closePath_func=null)}catch(e){i.warn("Error destroying draw callbacks:",e)}this.collector=void 0}}class GlyphGeometryBuilder{constructor(e,n){this.fontId="default",this.wordCache=new Map,this.cache=e,this.loadedFont=n,this.tessellator=new Tessellator,this.extruder=new Extruder,this.clusterer=new BoundaryClusterer,this.collector=new GlyphContourCollector,this.drawCallbacks=new DrawCallbackHandler,this.drawCallbacks.createDrawFuncs(this.loadedFont,this.collector)}getOptimizationStats(){return this.collector.getOptimizationStats()}setCurveFidelityConfig(e){this.collector.setCurveFidelityConfig(e)}setGeometryOptimization(e){this.collector.setGeometryOptimization(e)}setFontId(e){this.fontId=e}buildInstancedGeometry(e,n,i,r,o=!1){s.start("GlyphGeometryBuilder.buildInstancedGeometry",{lineCount:e.length,wordCount:e.flat().length,depth:n,removeOverlaps:i});const h=[],c=[],l=[],d=[],f={min:{x:1/0,y:1/0,z:0},max:{x:-1/0,y:-1/0,z:n}};for(let s=0;s<e.length;s++){const p=e[s];for(const e of p){const s=[];for(const n of e.glyphs)s.push(this.getContoursForGlyph(n.g));const p=e.glyphs.map(e=>new Vec3(e.x,e.y,0)),g=this.clusterer.cluster(s,p);if(!o&&g.some(e=>e.length>1)){const o=`${this.fontId}_${e.text}_${n}_${i}`;let p=this.wordCache.get(o);if(!p){const i=[];for(let n=0;n<s.length;n++){const r=s[n],o=e.glyphs[n];for(const e of r.paths)i.push({...e,points:e.points.map(e=>new Vec2(e.x+(o.x??0),e.y+(o.y??0)))})}p=this.tessellateGlyphCluster(i,n,r),this.wordCache.set(o,p)}const g=h.length/3;this.appendGeometry(h,c,l,p,e.position,g);const y=p.vertices.length/3;for(let i=0;i<e.glyphs.length;i++){const r=e.glyphs[i],o=s[i],h=new Vec3(e.position.x+(r.x??0),e.position.y+(r.y??0),e.position.z),c=this.createGlyphInfo(r,g,y,h,o,n);d.push(c),this.updatePlaneBounds(c.bounds,f)}}else for(let o=0;o<e.glyphs.length;o++){const p=e.glyphs[o],g=s[o],y=new Vec3(e.position.x+(p.x??0),e.position.y+(p.y??0),e.position.z);if(0===g.paths.length){const e=this.createGlyphInfo(p,0,0,y,g,n);d.push(e);continue}let b=this.cache.get(this.fontId,p.g,n,i);b||(b=this.tessellateGlyph(g,n,i,r),this.cache.set(this.fontId,p.g,n,i,b));const m=h.length/3;this.appendGeometry(h,c,l,b,y,m);const _=this.createGlyphInfo(p,m,b.vertices.length/3,y,g,n);d.push(_),this.updatePlaneBounds(_.bounds,f)}}}const p=new Float32Array(h),g=new Float32Array(c),y=new Uint32Array(l);return s.end("GlyphGeometryBuilder.buildInstancedGeometry"),{vertices:p,normals:g,indices:y,glyphInfos:d,planeBounds:f}}appendGeometry(e,n,i,s,r,o){for(let n=0;n<s.vertices.length;n+=3)e.push(s.vertices[n]+r.x,s.vertices[n+1]+r.y,s.vertices[n+2]+r.z);for(let e=0;e<s.normals.length;e++)n.push(s.normals[e]);for(let e=0;e<s.indices.length;e++)i.push(s.indices[e]+o)}createGlyphInfo(e,n,i,s,r,o){return{textIndex:e.absoluteTextIndex,lineIndex:e.lineIndex,vertexStart:n,vertexCount:i,bounds:{min:{x:r.bounds.min.x+s.x,y:r.bounds.min.y+s.y,z:s.z},max:{x:r.bounds.max.x+s.x,y:r.bounds.max.y+s.y,z:s.z+o}}}}getContoursForGlyph(e){this.collector.reset(),this.collector.beginGlyph(e,0),this.loadedFont.module.exports.hb_font_draw_glyph(this.loadedFont.font.ptr,e,this.drawCallbacks.getDrawFuncsPtr(),0),this.collector.finishGlyph();const n=this.collector.getCollectedGlyphs()[0];return n||{glyphId:e,paths:[],bounds:{min:{x:0,y:0},max:{x:0,y:0}}}}tessellateGlyphCluster(e,n,i){const s=this.tessellator.process(e,!0,i);return this.extrudeAndPackage(s,n)}extrudeAndPackage(e,n){const i=this.extruder.extrude(e,n,this.loadedFont.upem),s=i.vertices;let r=1/0,o=1/0,h=1/0,c=-1/0,l=-1/0,d=-1/0;for(let e=0;e<s.length;e+=3){const n=s[e],i=s[e+1],f=s[e+2];n<r&&(r=n),n>c&&(c=n),i<o&&(o=i),i>l&&(l=i),f<h&&(h=f),f>d&&(d=f)}const f=new Vec3(r,o,h),p=new Vec3(c,l,d),g=i.vertices.length/3<65536?Uint16Array:Uint32Array;return{geometry:e,vertices:new Float32Array(i.vertices),normals:new Float32Array(i.normals),indices:new g(i.indices),bounds:{min:f,max:p},useCount:1}}tessellateGlyph(e,n,i,r){s.start("GlyphGeometryBuilder.tessellateGlyph",{glyphId:e.glyphId,pathCount:e.paths.length});const o=this.tessellator.process(e.paths,i,r);return this.extrudeAndPackage(o,n)}updatePlaneBounds(e,n){const i=new Box3(new Vec3(n.min.x,n.min.y,n.min.z),new Vec3(n.max.x,n.max.y,n.max.z)),s=new Box3(new Vec3(e.min.x,e.min.y,e.min.z),new Vec3(e.max.x,e.max.y,e.max.z));i.union(s),n.min.x=i.min.x,n.min.y=i.min.y,n.min.z=i.min.z,n.max.x=i.max.x,n.max.y=i.max.y,n.max.z=i.max.z}getCacheStats(){return this.cache.getStats()}clearCache(){this.cache.clear(),this.wordCache.clear()}}class TextShaper{constructor(e,n){this.cachedSpaceWidth=new Map,this.loadedFont=e,this.geometryBuilder=n}shapeLines(e,n,i,r,o,h,c){s.start("TextShaper.shapeLines",{lineCount:e.length});const l=new Set;if(h&&"object"==typeof h&&"byText"in h&&h.byText&&c)for(const e of Object.keys(h.byText)){let n=0;for(;-1!==(n=c.indexOf(e,n));)l.add(n),l.add(n+e.length),n+=e.length}const d=[];return e.forEach((e,s)=>{const h=this.shapeLineIntoClusters(e,s,n,i,r,o,l);d.push(h)}),d}shapeLineIntoClusters(e,n,i,s,r,o,h){const c=this.loadedFont.hb.createBuffer();"rtl"===o&&c.setDirection("rtl"),c.addText(e.text),c.guessSegmentProperties(),this.loadedFont.hb.shape(this.loadedFont.font,c);const l=c.json(this.loadedFont.font);c.destroy();const d=[];let f=[],p="",g=new Vec3,y=new Vec3(e.xOffset,-n*i,0);const b=s*this.loadedFont.upem,m=this.calculateSpaceAdjustment(e,r,s);for(let i=0;i<l.length;i++){const s=l[i],r=/\s/.test(e.text[s.cl]);e.endedWithHyphen&&s.cl===e.text.length-1&&"-"===e.text[s.cl]?s.absoluteTextIndex=e.originalEnd:s.absoluteTextIndex=e.originalStart+s.cl,s.lineIndex=n;const o=h.has(s.absoluteTextIndex);(r||o)&&f.length>0&&(d.push({text:p,glyphs:f,position:g.clone()}),f=[],p="");const c=y.clone().add(new Vec3(s.dx,s.dy,0));r||(0===f.length&&g.copy(c),s.x=c.x-g.x,s.y=c.y-g.y,f.push(s),p+=e.text[s.cl]),y.x+=s.ax,y.y+=s.ay,0!==b&&i<l.length-1&&(y.x+=b),r&&(y.x+=m)}return f.length>0&&d.push({text:p,glyphs:f,position:g.clone()}),d}calculateSpaceAdjustment(e,n,i){let s=0;if(void 0!==e.adjustmentRatio&&"justify"===n&&!e.isLastLine){let n=this.cachedSpaceWidth.get(i);void 0===n&&(n=TextMeasurer.measureTextWidth(this.loadedFont," ",i),this.cachedSpaceWidth.set(i,n));const r=.5,o=c;e.adjustmentRatio>0?s=e.adjustmentRatio*n*r:e.adjustmentRatio<0&&(s=e.adjustmentRatio*n*o)}return s}clearCache(){this.geometryBuilder.clearCache()}getCacheStats(){return this.geometryBuilder.getCacheStats()}}class GlyphCache{constructor(e){this.cache=new Map,this.head=null,this.tail=null,this.stats={hits:0,misses:0,totalGlyphs:0,uniqueGlyphs:0,cacheSize:0,saved:0,memoryUsage:0},e&&(this.maxCacheSize=1024*e*1024)}getCacheKey(e,n,i,s){return`${e}_${n}_${Math.round(1e3*i)/1e3}_${s}`}has(e,n,i,s){const r=this.getCacheKey(e,n,i,s);return this.cache.has(r)}get(e,n,i,s){const r=this.getCacheKey(e,n,i,s),o=this.cache.get(r);return o?(this.stats.hits++,this.stats.saved++,o.data.useCount++,this.moveToHead(o),this.stats.totalGlyphs++,o.data):(this.stats.misses++,void this.stats.totalGlyphs++)}set(e,n,i,s,r){const o=this.getCacheKey(e,n,i,s),h=this.calculateMemoryUsage(r);this.maxCacheSize&&this.stats.memoryUsage+h>this.maxCacheSize&&this.evictLRU(h);const c={key:o,data:r,prev:null,next:null};this.cache.set(o,c),this.addToHead(c),this.stats.uniqueGlyphs=this.cache.size,this.stats.cacheSize++,this.stats.memoryUsage+=h}calculateMemoryUsage(e){let n=0;return n+=4*e.vertices.length,n+=4*e.normals.length,n+=e.indices.length*e.indices.BYTES_PER_ELEMENT,n+=24,n+=256,n}evictLRU(e){let n=0;for(;this.tail&&n<e;){const e=this.calculateMemoryUsage(this.tail.data),i=this.tail;this.removeTail(),this.cache.delete(i.key),this.stats.memoryUsage-=e,this.stats.cacheSize--,n+=e}}addToHead(e){this.head?(e.next=this.head,this.head.prev=e,this.head=e):this.head=this.tail=e}removeNode(e){e.prev?e.prev.next=e.next:this.head=e.next,e.next?e.next.prev=e.prev:this.tail=e.prev}removeTail(){this.tail&&this.removeNode(this.tail)}moveToHead(e){e!==this.head&&(this.removeNode(e),this.addToHead(e))}clear(){this.cache.clear(),this.head=null,this.tail=null,this.stats={hits:0,misses:0,totalGlyphs:0,uniqueGlyphs:0,cacheSize:0,saved:0,memoryUsage:0}}getStats(){const e=this.stats.totalGlyphs>0?this.stats.hits/this.stats.totalGlyphs*100:0;return this.stats.uniqueGlyphs=this.cache.size,{...this.stats,hitRate:e,memoryUsageMB:this.stats.memoryUsage/1048576}}}const st=new GlyphCache(250);var rt={exports:{}};var at=getAugmentedNamespace({__proto__:null,default:{},readFileSync:()=>{throw new Error("fs not available in browser")}});!function(e){var n,i=(n="undefined"!=typeof document?document.currentScript?.src:void 0,async function(e={}){var i=e,s="object"==typeof window,r="undefined"!=typeof WorkerGlobalScope,o="object"==typeof process&&process.versions?.node&&"renderer"!=process.type,quit_=(e,n)=>{throw n};"undefined"!=typeof __filename?n=__filename:r&&(n=self.location.href);var h,c,l="";if(o){var d=at;l=__dirname+"/",c=e=>(e=isFileURI(e)?new URL(e):e,d.readFileSync(e)),h=async(e,n=!0)=>(e=isFileURI(e)?new URL(e):e,d.readFileSync(e,n?void 0:"utf8")),process.argv.length>1&&process.argv[1].replace(/\\/g,"/"),process.argv.slice(2),quit_=(e,n)=>{throw process.exitCode=e,n}}else if(s||r){try{l=new URL(".",n).href}catch{}r&&(c=e=>{var n=new XMLHttpRequest;return n.open("GET",e,!1),n.responseType="arraybuffer",n.send(null),new Uint8Array(n.response)}),h=async e=>{if(isFileURI(e))return new Promise((n,i)=>{var s=new XMLHttpRequest;s.open("GET",e,!0),s.responseType="arraybuffer",s.onload=()=>{200==s.status||0==s.status&&s.response?n(s.response):i(s.status)},s.onerror=i,s.send(null)});var n=await fetch(e,{credentials:"same-origin"});if(n.ok)return n.arrayBuffer();throw new Error(n.status+" : "+n.url)}}console.log.bind(console);var f,p,g,y,b,m,_=console.error.bind(console),w=!1,isFileURI=e=>e.startsWith("file://"),O=!1;function updateMemoryViews(){var e=b.buffer;i.HEAP8=new Int8Array(e),i.HEAPU8=m=new Uint8Array(e),i.HEAP32=new Int32Array(e),i.HEAPU32=new Uint32Array(e),i.HEAPF32=new Float32Array(e),new BigInt64Array(e),new BigUint64Array(e)}var k,j=0,$=null;function abort(e){i.onAbort?.(e),_(e="Aborted("+e+")"),w=!0,e+=". Build with -sASSERTIONS for more info.";var n=new WebAssembly.RuntimeError(e);throw y?.(n),n}function findWasmBinary(){return e="hb.wasm",i.locateFile?i.locateFile(e,l):l+e;var e}async function getWasmBinary(e){if(!f)try{var n=await h(e);return new Uint8Array(n)}catch{}return function(e){if(e==k&&f)return new Uint8Array(f);if(c)return c(e);throw"both async and sync fetching of the wasm failed"}(e)}async function instantiateAsync(e,n,i){if(!e&&!isFileURI(n)&&!o)try{var s=fetch(n,{credentials:"same-origin"});return await WebAssembly.instantiateStreaming(s,i)}catch(e){_(`wasm streaming compile failed: ${e}`),_("falling back to ArrayBuffer instantiation")}return async function(e,n){try{var i=await getWasmBinary(e);return await WebAssembly.instantiate(i,n)}catch(e){_(`failed to asynchronously prepare wasm: ${e}`),abort(e)}}(n,i)}class ExitStatus{name="ExitStatus";constructor(e){this.message=`Program terminated with exit(${e})`,this.status=e}}var Y,q,tt,callRuntimeCallbacks=e=>{for(;e.length>0;)e.shift()(i)},et=[],addOnPostRun=e=>et.push(e),nt=[],addOnPreRun=e=>nt.push(e),it=!0,st=0,rt={},handleException=e=>{if(e instanceof ExitStatus||"unwind"==e)return p;quit_(1,e)},keepRuntimeAlive=()=>it||st>0,_proc_exit=e=>{p=e,keepRuntimeAlive()||(i.onExit?.(e),w=!0),quit_(e,new ExitStatus(e))},_exit=(e,n)=>{p=e,_proc_exit(e)},callUserCallback=e=>{if(!w)try{e(),(()=>{if(!keepRuntimeAlive())try{_exit(p)}catch(e){handleException(e)}})()}catch(e){handleException(e)}},alignMemory=(e,n)=>Math.ceil(e/n)*n,growMemory=e=>{var n=(e-b.buffer.byteLength+65535)/65536|0;try{return b.grow(n),updateMemoryViews(),1}catch(e){}},uleb128EncodeWithLen=e=>{const n=e.length;return[n%128|128,n>>7,...e]},ot={i:127,p:127,j:126,f:125,d:124,e:111},generateTypePack=e=>uleb128EncodeWithLen(Array.from(e,e=>ot[e])),getWasmTableEntry=e=>Y.get(e),getFunctionAddress=e=>(q||(q=new WeakMap,((e,n)=>{if(q)for(var i=e;i<e+n;i++){var s=getWasmTableEntry(i);s&&q.set(s,i)}})(0,Y.length)),q.get(e)||0),ht=[],setWasmTableEntry=(e,n)=>Y.set(e,n);i.noExitRuntime&&(it=i.noExitRuntime),i.print&&i.print,i.printErr&&(_=i.printErr),i.wasmBinary&&(f=i.wasmBinary),i.arguments&&i.arguments,i.thisProgram&&i.thisProgram,i.wasmMemory=b,i.wasmExports=lt,i.addFunction=(e,n)=>{var i=getFunctionAddress(e);if(i)return i;var s=ht.length?ht.pop():Y.grow(1);try{setWasmTableEntry(s,e)}catch(i){if(!(i instanceof TypeError))throw i;var r=((e,n)=>{var i=Uint8Array.of(0,97,115,109,1,0,0,0,1,...uleb128EncodeWithLen([1,96,...generateTypePack(n.slice(1)),...generateTypePack("v"===n[0]?"":n[0])]),2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0),s=new WebAssembly.Module(i);return new WebAssembly.Instance(s,{e:{f:e}}).exports.f})(e,n);setWasmTableEntry(s,r)}return q.set(e,s),s},i.removeFunction=e=>{q.delete(getWasmTableEntry(e)),setWasmTableEntry(e,null),ht.push(e)};var ct={_abort_js:()=>abort(""),_emscripten_runtime_keepalive_clear:()=>{it=!1,st=0},_setitimer_js:(e,n)=>{if(rt[e]&&(clearTimeout(rt[e].id),delete rt[e]),!n)return 0;var i=setTimeout(()=>{delete rt[e],callUserCallback(()=>tt(e,performance.now()))},n);return rt[e]={id:i,timeout_ms:n},0},emscripten_resize_heap:e=>{var n=m.length,i=2147483648;if((e>>>=0)>i)return!1;for(var s=1;s<=4;s*=2){var r=n*(1+.2/s);r=Math.min(r,e+100663296);var o=Math.min(i,alignMemory(Math.max(e,r),65536));if(growMemory(o))return!0}return!1},proc_exit:_proc_exit},lt=await async function(){function receiveInstance(e,n){return lt=e.exports,i.wasmExports=lt,b=lt.memory,i.wasmMemory=b,updateMemoryViews(),Y=lt.__indirect_function_table,function(e){i._hb_blob_create=e.hb_blob_create,i._hb_blob_destroy=e.hb_blob_destroy,i._hb_blob_get_length=e.hb_blob_get_length,i._hb_blob_get_data=e.hb_blob_get_data,i._hb_buffer_serialize_glyphs=e.hb_buffer_serialize_glyphs,i._hb_buffer_create=e.hb_buffer_create,i._hb_buffer_destroy=e.hb_buffer_destroy,i._hb_buffer_get_content_type=e.hb_buffer_get_content_type,i._hb_buffer_set_direction=e.hb_buffer_set_direction,i._hb_buffer_set_script=e.hb_buffer_set_script,i._hb_buffer_set_language=e.hb_buffer_set_language,i._hb_buffer_set_flags=e.hb_buffer_set_flags,i._hb_buffer_set_cluster_level=e.hb_buffer_set_cluster_level,i._hb_buffer_get_length=e.hb_buffer_get_length,i._hb_buffer_get_glyph_infos=e.hb_buffer_get_glyph_infos,i._hb_buffer_get_glyph_positions=e.hb_buffer_get_glyph_positions,i._hb_glyph_info_get_glyph_flags=e.hb_glyph_info_get_glyph_flags,i._hb_buffer_guess_segment_properties=e.hb_buffer_guess_segment_properties,i._hb_buffer_add_utf8=e.hb_buffer_add_utf8,i._hb_buffer_add_utf16=e.hb_buffer_add_utf16,i._hb_buffer_set_message_func=e.hb_buffer_set_message_func,i._hb_language_from_string=e.hb_language_from_string,i._hb_script_from_string=e.hb_script_from_string,i._hb_version=e.hb_version,i._hb_version_string=e.hb_version_string,i._hb_feature_from_string=e.hb_feature_from_string,i._malloc=e.malloc,i._free=e.free,i._hb_draw_funcs_set_move_to_func=e.hb_draw_funcs_set_move_to_func,i._hb_draw_funcs_set_line_to_func=e.hb_draw_funcs_set_line_to_func,i._hb_draw_funcs_set_quadratic_to_func=e.hb_draw_funcs_set_quadratic_to_func,i._hb_draw_funcs_set_cubic_to_func=e.hb_draw_funcs_set_cubic_to_func,i._hb_draw_funcs_set_close_path_func=e.hb_draw_funcs_set_close_path_func,i._hb_draw_funcs_create=e.hb_draw_funcs_create,i._hb_draw_funcs_destroy=e.hb_draw_funcs_destroy,i._hb_face_create=e.hb_face_create,i._hb_face_destroy=e.hb_face_destroy,i._hb_face_reference_table=e.hb_face_reference_table,i._hb_face_get_upem=e.hb_face_get_upem,i._hb_face_collect_unicodes=e.hb_face_collect_unicodes,i._hb_font_draw_glyph=e.hb_font_draw_glyph,i._hb_font_glyph_to_string=e.hb_font_glyph_to_string,i._hb_font_create=e.hb_font_create,i._hb_font_set_variations=e.hb_font_set_variations,i._hb_font_destroy=e.hb_font_destroy,i._hb_font_set_scale=e.hb_font_set_scale,i._hb_set_create=e.hb_set_create,i._hb_set_destroy=e.hb_set_destroy,i._hb_ot_var_get_axis_infos=e.hb_ot_var_get_axis_infos,i._hb_set_get_population=e.hb_set_get_population,i._hb_set_next_many=e.hb_set_next_many,i._hb_shape=e.hb_shape,tt=e._emscripten_timeout}(lt),function(){if(j--,i.monitorRunDependencies?.(j),0==j&&$){var e=$;$=null,e()}}(),lt}j++,i.monitorRunDependencies?.(j);var e={env:ct,wasi_snapshot_preview1:ct};if(i.instantiateWasm)return new Promise((n,s)=>{i.instantiateWasm(e,(e,i)=>{n(receiveInstance(e))})});k??=findWasmBinary();var n=function(e){return receiveInstance(e.instance)}(await instantiateAsync(f,k,e));return n}();return function(){if(i.preInit)for("function"==typeof i.preInit&&(i.preInit=[i.preInit]);i.preInit.length>0;)i.preInit.shift()()}(),function run(){function doRun(){i.calledRun=!0,w||(O=!0,lt.__wasm_call_ctors(),g?.(i),i.onRuntimeInitialized?.(),function(){if(i.postRun)for("function"==typeof i.postRun&&(i.postRun=[i.postRun]);i.postRun.length;)addOnPostRun(i.postRun.shift());callRuntimeCallbacks(et)}())}j>0?$=run:(function(){if(i.preRun)for("function"==typeof i.preRun&&(i.preRun=[i.preRun]);i.preRun.length;)addOnPreRun(i.preRun.shift());callRuntimeCallbacks(nt)}(),j>0?$=run:i.setStatus?(i.setStatus("Running..."),setTimeout(()=>{setTimeout(()=>i.setStatus(""),1),doRun()},1)):doRun())}(),O?i:new Promise((e,n)=>{g=e,y=n})});e.exports=i,e.exports.default=i}(rt);var ot=getDefaultExportFromCjs(rt.exports),ht={exports:{}};try{ht.exports=function(e){var n=e.wasmExports,i=new TextDecoder("utf8");let s=e.addFunction,r=e.removeFunction;var o=s(function(e){n.free(e)},"vi");function hb_tag(e){return(255&e.charCodeAt(0))<<24|(255&e.charCodeAt(1))<<16|(255&e.charCodeAt(2))<<8|255&e.charCodeAt(3)}var h=hb_tag("JSON"),c="",l=n.malloc(256);function createAsciiString(i){var s=n.malloc(i.length+1);for(let n=0;n<i.length;++n){const r=i.charCodeAt(n);if(r>127)throw new Error("Expected ASCII text");e.HEAPU8[s+n]=r}return e.HEAPU8[s+i.length]=0,{ptr:s,length:i.length,free:function(){n.free(s)}}}function shape(e,i,s){var r=0,o=0;s&&(s=s.split(","),r=n.malloc(16*s.length),s.forEach(function(e,i){var s=createAsciiString(e);n.hb_feature_from_string(s.ptr,-1,r+16*o)&&o++,s.free()})),n.hb_shape(e.ptr,i.ptr,r,o),r&&n.free(r)}return{createBlob:function(i){var s=n.malloc(i.byteLength);e.HEAPU8.set(new Uint8Array(i),s);var r=n.hb_blob_create(s,i.byteLength,2,s,o);return{ptr:r,destroy:function(){n.hb_blob_destroy(r)}}},createFace:function(i,s){var r=n.hb_face_create(i.ptr,s);const o=n.hb_face_get_upem(r);return{ptr:r,upem:o,reference_table:function(i){var s=n.hb_face_reference_table(r,hb_tag(i)),o=n.hb_blob_get_length(s);if(o){var h=n.hb_blob_get_data(s,null);return e.HEAPU8.subarray(h,h+o)}},getAxisInfos:function(){var i=n.malloc(2048),s=n.malloc(4);e.HEAPU32[s/4]=64,n.hb_ot_var_get_axis_infos(r,0,s,i);var o={};return Array.from({length:e.HEAPU32[s/4]}).forEach(function(n,s){var r;o[(r=e.HEAPU32[i/4+8*s+1],[String.fromCharCode(r>>24&255),String.fromCharCode(r>>16&255),String.fromCharCode(r>>8&255),String.fromCharCode(255&r)].join(""))]={min:e.HEAPF32[i/4+8*s+4],default:e.HEAPF32[i/4+8*s+5],max:e.HEAPF32[i/4+8*s+6]}}),n.free(s),n.free(i),o},collectUnicodes:function(){var i=n.hb_set_create();n.hb_face_collect_unicodes(r,i);var s=function(i){const s=n.hb_set_get_population(i),r=n.malloc(s<<2),o=r>>2,h=e.HEAPU32.subarray(o,o+s);return e.HEAPU32.set(h,o),n.hb_set_next_many(i,-1,r,s),h}(i);return n.hb_set_destroy(i),s},destroy:function(){n.hb_face_destroy(r)}}},createFont:function(o){var h=n.hb_font_create(o.ptr),d=null,f=null,p=null,g=null,y=null,b=null;function glyphToPath(e){return d||(f=s(function(e,n,i,s,r,o){c+=`M${s},${r}`},"viiiffi"),p=s(function(e,n,i,s,r,o){c+=`L${s},${r}`},"viiiffi"),g=s(function(e,n,i,s,r,o,h,l,d,f){c+=`C${s},${r} ${o},${h} ${l},${d}`},"viiiffffffi"),y=s(function(e,n,i,s,r,o,h,l){c+=`Q${s},${r} ${o},${h}`},"viiiffffi"),b=s(function(e,n,i,s){c+="Z"},"viiii"),d=n.hb_draw_funcs_create(),n.hb_draw_funcs_set_move_to_func(d,f,0,0),n.hb_draw_funcs_set_line_to_func(d,p,0,0),n.hb_draw_funcs_set_cubic_to_func(d,g,0,0),n.hb_draw_funcs_set_quadratic_to_func(d,y,0,0),n.hb_draw_funcs_set_close_path_func(d,b,0,0)),c="",n.hb_font_draw_glyph(h,e,d,0),c}return{ptr:h,glyphName:function(s){n.hb_font_glyph_to_string(h,s,l,256);var r=e.HEAPU8.subarray(l,l+256);return i.decode(r.slice(0,r.indexOf(0)))},glyphToPath:glyphToPath,glyphToJson:function(e){return glyphToPath(e).replace(/([MLQCZ])/g,"|$1 ").split("|").filter(function(e){return e.length}).map(function(e){var n=e.split(/[ ,]/g);return{type:n[0],values:n.slice(1).filter(function(e){return e.length}).map(function(e){return+e})}})},setScale:function(e,i){n.hb_font_set_scale(h,e,i)},setVariations:function(i){var s=Object.entries(i),r=n.malloc(8*s.length);s.forEach(function(n,i){e.HEAPU32[r/4+2*i+0]=hb_tag(n[0]),e.HEAPF32[r/4+2*i+1]=n[1]}),n.hb_font_set_variations(h,r,s.length),n.free(r)},destroy:function(){n.hb_font_destroy(h),d&&(n.hb_draw_funcs_destroy(d),d=null,r(f),r(p),r(g),r(y),r(b))}}},createBuffer:function(){var i=n.hb_buffer_create();return{ptr:i,addText:function(s){const r=function(i){const s=n.malloc(2*i.length),r=new Uint16Array(e.wasmMemory.buffer,s,i.length);for(let e=0;e<r.length;++e)r[e]=i.charCodeAt(e);return{ptr:s,length:r.length,free:function(){n.free(s)}}}(s);n.hb_buffer_add_utf16(i,r.ptr,r.length,0,r.length),r.free()},guessSegmentProperties:function(){return n.hb_buffer_guess_segment_properties(i)},setDirection:function(e){n.hb_buffer_set_direction(i,{ltr:4,rtl:5,ttb:6,btt:7}[e]||0)},setFlags:function(e){var s=0;e.forEach(function(e){s|=function(e){return"BOT"==e?1:"EOT"==e?2:"PRESERVE_DEFAULT_IGNORABLES"==e?4:"REMOVE_DEFAULT_IGNORABLES"==e?8:"DO_NOT_INSERT_DOTTED_CIRCLE"==e?16:"PRODUCE_UNSAFE_TO_CONCAT"==e?64:0}(e)}),n.hb_buffer_set_flags(i,s)},setLanguage:function(e){var s=createAsciiString(e);n.hb_buffer_set_language(i,n.hb_language_from_string(s.ptr,-1)),s.free()},setScript:function(e){var s=createAsciiString(e);n.hb_buffer_set_script(i,n.hb_script_from_string(s.ptr,-1)),s.free()},setClusterLevel:function(e){n.hb_buffer_set_cluster_level(i,e)},json:function(){for(var s=n.hb_buffer_get_length(i),r=[],o=n.hb_buffer_get_glyph_infos(i,0),h=o/4,c=n.hb_buffer_get_glyph_positions(i,0)/4,l=e.HEAPU32.subarray(h,h+5*s),d=e.HEAP32.subarray(c,c+5*s),f=0;f<s;++f)r.push({g:l[5*f+0],cl:l[5*f+2],ax:d[5*f+0],ay:d[5*f+1],dx:d[5*f+2],dy:d[5*f+3],flags:n.hb_glyph_info_get_glyph_flags(o+20*f)});return r},destroy:function(){n.hb_buffer_destroy(i)}}},shape:shape,shapeWithTrace:function(o,c,l,d,f){var p=[],g=0,y=!1,b=1048576,m=n.malloc(b),_=s(function(s,r,o,c){var l=i.decode(e.HEAPU8.subarray(o,e.HEAPU8.indexOf(0,o)));return l.startsWith("start table GSUB")?g=1:l.startsWith("start table GPOS")&&(g=2),g!=f&&(y=!1),0!=f&&g==f&&l.startsWith("end lookup "+d)&&(y=!0),y?0:(n.hb_buffer_serialize_glyphs(s,0,n.hb_buffer_get_length(s),m,b,0,r,h,4),p.push({m:l,t:JSON.parse(i.decode(e.HEAPU8.subarray(m,e.HEAPU8.indexOf(0,m)))),glyphs:2==n.hb_buffer_get_content_type(s)}),1)},"iiiii");return n.hb_buffer_set_message_func(c.ptr,_,0,0),shape(o,c,l),n.free(m),r(_),p},version:function(){var i=n.malloc(12);n.hb_version(i,i+4,i+8);var s={major:e.HEAPU32[i/4],minor:e.HEAPU32[(i+4)/4],micro:e.HEAPU32[(i+8)/4]};return n.free(i),s},version_string:function(){var s=n.hb_version_string();return i.decode(e.HEAPU8.subarray(s,e.HEAPU8.indexOf(0,s)))}}}}catch(e){}var ct=getDefaultExportFromCjs(ht.exports);let lt=null,ut=null,dt=null;const ft={setWasmPath(e){ut=e,dt=null,lt=null},setWasmBuffer(e){dt=e,ut=null,lt=null},getHarfBuzz:async()=>lt||(lt=new Promise(async(e,n)=>{try{const n={};if(dt)n.wasmBinary=dt;else{if(!ut)throw new Error("HarfBuzz WASM path or buffer must be set before initialization.");n.locateFile=(e,n)=>e.endsWith(".wasm")?ut:n+e}const i=await ot(n),s=ct(i);e({hb:s,module:{addFunction:i.addFunction,exports:i.wasmExports,removeFunction:i.removeFunction}})}catch(e){n(new Error(`Failed to initialize HarfBuzz: ${e}`))}}),lt)};class TextRangeQuery{constructor(e,n){this.text=e,this.glyphsByTextIndex=new Map,n.forEach(e=>{const n=this.glyphsByTextIndex.get(e.textIndex)||[];n.push(e),this.glyphsByTextIndex.set(e.textIndex,n)})}execute(e){const n=[];return e.byText&&n.push(...this.findByText(e.byText)),e.byCharRange&&n.push(...this.findByCharRange(e.byCharRange)),n}findByText(e){const n=[];for(const i of e){let e=0;for(;-1!==(e=this.text.indexOf(i,e));)n.push(this.createTextRange(e,e+i.length,i)),e+=i.length}return n}findByCharRange(e){return e.map(e=>{const n=this.text.slice(e.start,e.end);return this.createTextRange(e.start,e.end,n)})}createTextRange(e,n,i){const s=[],r=new Map;for(let i=e;i<n;i++){const e=this.glyphsByTextIndex.get(i);if(e)for(const n of e){s.push(n);const e=r.get(n.lineIndex)||[];e.push(n),r.set(n.lineIndex,e)}}return{start:e,end:n,originalText:i,bounds:Array.from(r.values()).map(e=>this.calculateBounds(e)),glyphs:s,lineIndices:Array.from(r.keys()).sort((e,n)=>e-n)}}calculateBounds(e){if(0===e.length)return{min:{x:0,y:0,z:0},max:{x:0,y:0,z:0}};const n=new Box3;for(const i of e){const e=new Box3(new Vec3(i.bounds.min.x,i.bounds.min.y,i.bounds.min.z),new Vec3(i.bounds.max.x,i.bounds.max.y,i.bounds.max.z));n.union(e)}return{min:{x:n.min.x,y:n.min.y,z:n.min.z},max:{x:n.max.x,y:n.max.y,z:n.max.z}}}}class Text{static{this.patternCache=new Map}static{this.hbInitPromise=null}static{this.fontCache=new Map}static{this.fontIdCounter=0}constructor(e){this.currentFontId="",Text.hbInitPromise||(Text.hbInitPromise=ft.getHarfBuzz()),this.fontLoader=new FontLoader(()=>Text.hbInitPromise)}static setHarfBuzzPath(e){ft.setWasmPath(e),Text.hbInitPromise=null}static setHarfBuzzBuffer(e){ft.setWasmBuffer(e),Text.hbInitPromise=null}static init(){return Text.hbInitPromise||(Text.hbInitPromise=ft.getHarfBuzz()),Text.hbInitPromise}static async create(e){if(!e.font)throw new Error("Font is required. Specify options.font as a URL string or ArrayBuffer.");Text.hbInitPromise||(Text.hbInitPromise=ft.getHarfBuzz());const n="string"==typeof e.font?e.font:`buffer-${Text.generateFontContentHash(e.font)}`,i=e.fontVariations?`${n}_${JSON.stringify(e.fontVariations)}`:n;let s=Text.fontCache.get(i);s||(s=await Text.loadAndCacheFont(i,e.font,e.fontVariations));const r=new Text({maxCacheSizeMB:e.maxCacheSizeMB});r.setLoadedFont(s);const{font:o,maxCacheSizeMB:h,...c}=e;return{...await r.createGeometry(c),getLoadedFont:()=>r.getLoadedFont(),getCacheStatistics:()=>r.getCacheStatistics(),clearCache:()=>r.clearCache(),measureTextWidth:(e,n)=>r.measureTextWidth(e,n)}}static async loadAndCacheFont(e,n,i){const s=new Text;await s.loadFont(n,i);const r=s.getLoadedFont();return Text.fontCache.set(e,r),r}static generateFontContentHash(e){if(e){const n=new Uint8Array(e);return`${n[0]}_${n[Math.floor(n.length/2)]}_${n[n.length-1]}_${n.length}`}return""+ ++Text.fontIdCounter}setLoadedFont(e){this.loadedFont=e;const n=Text.generateFontContentHash(e._buffer);this.currentFontId=`font_${n}`,e.fontVariations&&(this.currentFontId+=`_${JSON.stringify(e.fontVariations)}`)}async loadFont(e,n){s.start("Text.loadFont",{fontSrc:"string"==typeof e?e:`buffer(${e.byteLength})`}),Text.hbInitPromise||(Text.hbInitPromise=ft.getHarfBuzz()),await Text.hbInitPromise;const r="string"==typeof e?await fetch(e).then(n=>{if(!n.ok)throw new Error(`Failed to load font from ${e}: HTTP ${n.status} ${n.statusText}`);return n.arrayBuffer()}):e;try{this.loadedFont&&this.destroy(),this.loadedFont=await this.fontLoader.loadFont(r,n);const e=Text.generateFontContentHash(r);this.currentFontId=`font_${e}`,n&&(this.currentFontId+=`_${JSON.stringify(n)}`)}catch(e){throw i.error("Failed to load font:",e),e}finally{s.end("Text.loadFont")}}async createGeometry(e){s.start("Text.createGeometry",{textLength:e.text.length,size:e.size||72,hasLayout:!!e.layout,mode:"cached"});try{if(!this.loadedFont)throw new Error("Font not loaded. Use Text.create() with a font option.");const n=await this.prepareHyphenation(e);if(this.validateOptions(n),e=n,this.updateFontVariations(e),!this.geometryBuilder){const n=e.maxCacheSizeMB?new GlyphCache(e.maxCacheSizeMB):st;this.geometryBuilder=new GlyphGeometryBuilder(n,this.loadedFont),this.geometryBuilder.setFontId(this.currentFontId)}this.geometryBuilder.setCurveFidelityConfig(e.curveFidelity),this.geometryBuilder.setGeometryOptimization(e.geometryOptimization),this.loadedFont.font.setScale(this.loadedFont.upem,this.loadedFont.upem),this.textShaper||(this.textShaper=new TextShaper(this.loadedFont,this.geometryBuilder));const i=this.prepareLayout(e),s=e.removeOverlaps??this.loadedFont.isVariable??!1,r=this.textShaper.shapeLines(i.lines,i.scaledLineHeight,i.letterSpacing,i.align,i.direction,e.color,e.text),o=this.geometryBuilder.buildInstancedGeometry(r,i.depth,s,this.loadedFont.metrics.isCFF,e.separateGlyphsWithAttributes||!1),h=this.geometryBuilder.getCacheStats(),c=this.finalizeGeometry(o.vertices,o.normals,o.indices,o.glyphInfos,o.planeBounds,e,h,e.text);if(e.separateGlyphsWithAttributes){const e=this.createGlyphAttributes(c.vertices.length/3,c.glyphs);c.glyphAttributes=e}return c}finally{s.end("Text.createGeometry")}}async prepareHyphenation(e){if(!1!==e.layout?.hyphenate&&e.layout?.width){const n=e.layout?.language||"en-us";if(!e.layout?.hyphenationPatterns?.[n])try{if(!Text.patternCache.has(n)){const i=await loadPattern(n,e.layout?.patternsPath);Text.patternCache.set(n,i)}return{...e,layout:{...e.layout,hyphenationPatterns:{...e.layout?.hyphenationPatterns,[n]:Text.patternCache.get(n)}}}}catch(s){return i.warn(`Failed to load patterns for ${n}: ${s}`),{...e,layout:{...e.layout,hyphenate:!1}}}}return e}validateOptions(e){if(!e.text)throw new Error("Text content is required");const n=e.maxTextLength??1e5;if(e.text.length>n)throw new Error(`Text exceeds ${n} character limit`)}updateFontVariations(e){e.fontVariations&&this.loadedFont&&JSON.stringify(e.fontVariations)!==JSON.stringify(this.loadedFont.fontVariations)&&(this.loadedFont.font.setVariations(e.fontVariations),this.loadedFont.fontVariations=e.fontVariations)}prepareLayout(e){if(!this.loadedFont)throw new Error("Font not loaded. Use Text.create() with a font option");const{text:n,size:i=72,depth:s=0,lineHeight:c=1,letterSpacing:l=0,layout:d={}}=e,{width:f,direction:p="ltr",align:g=("rtl"===p?"right":"left"),respectExistingBreaks:y=!0,hyphenate:b=!0,language:m="en-us",tolerance:_=r,pretolerance:w=o,emergencyStretch:O=h,autoEmergencyStretch:k,hyphenationPatterns:j,lefthyphenmin:$,righthyphenmin:Y,linepenalty:q,adjdemerits:tt,hyphenpenalty:et,exhyphenpenalty:nt,doublehyphendemerits:it,looseness:st,disableSingleWordDetection:rt}=d;let at;void 0!==f&&(at=f*(this.loadedFont.upem/i));const ot=s*(this.loadedFont.upem/i);this.textLayout||(this.textLayout=new TextLayout(this.loadedFont));const ht=this.textLayout.computeLines({text:n,width:at,align:g,direction:p,hyphenate:b,language:m,respectExistingBreaks:y,tolerance:_,pretolerance:w,emergencyStretch:O,autoEmergencyStretch:k,hyphenationPatterns:j,lefthyphenmin:$,righthyphenmin:Y,linepenalty:q,adjdemerits:tt,hyphenpenalty:et,exhyphenpenalty:nt,doublehyphendemerits:it,looseness:st,disableSingleWordDetection:rt,letterSpacing:l}),ct=FontMetadataExtractor.getVerticalMetrics(this.loadedFont.metrics),lt=(ct.ascender-ct.descender)*c;return{lines:ht.lines,scaledLineHeight:lt,letterSpacing:l,align:g,direction:p,depth:ot,size:i}}applyColorSystem(e,n,i,s){const r=e.length/3,o=new Float32Array(3*r),h=[];if(Array.isArray(i)){for(let e=0;e<r;e++){const n=3*e;o[n]=i[0],o[n+1]=i[1],o[n+2]=i[2]}h.push({start:0,end:s.length,originalText:s,color:i,bounds:[],glyphs:n,lineIndices:[...new Set(n.map(e=>e.lineIndex))]})}else{const e=i.default||[1,1,1];for(let n=0;n<o.length;n+=3)o[n]=e[0],o[n+1]=e[1],o[n+2]=e[2];if(i.byText){new TextRangeQuery(s,n).execute({byText:Object.keys(i.byText)}).forEach(e=>{const n=i.byText[e.originalText];n&&(e.glyphs.forEach(e=>{for(let i=0;i<e.vertexCount;i++){const s=3*(e.vertexStart+i);s>=0&&s<o.length&&(o[s]=n[0],o[s+1]=n[1],o[s+2]=n[2])}}),h.push({start:e.start,end:e.end,originalText:e.originalText,color:n,bounds:e.bounds,glyphs:e.glyphs,lineIndices:e.lineIndices}))})}i.byCharRange&&i.byCharRange.forEach(e=>{const i=[];for(const s of n)if(s.textIndex>=e.start&&s.textIndex<e.end){i.push(s);for(let n=0;n<s.vertexCount;n++){const i=3*(s.vertexStart+n);i>=0&&i<o.length&&(o[i]=e.color[0],o[i+1]=e.color[1],o[i+2]=e.color[2])}}h.push({start:e.start,end:e.end,originalText:s.slice(e.start,e.end),color:e.color,bounds:[],glyphs:i,lineIndices:[...new Set(i.map(e=>e.lineIndex))]})})}return{colors:o,coloredRanges:h}}finalizeGeometry(e,n,i,s,r,o,h,c){const{layout:l={},size:d=72}=o,{width:f,align:p=("rtl"===l.direction?"right":"left")}=l;this.textLayout||(this.textLayout=new TextLayout(this.loadedFont));const g=this.textLayout.applyAlignment(e,{width:f,align:p,planeBounds:r}),y=g.offset;r.min.x=g.adjustedBounds.min.x,r.max.x=g.adjustedBounds.max.x;const b=d/this.loadedFont.upem;for(let n=0;n<e.length;n++)e[n]*=b;r.min.x*=b,r.min.y*=b,r.min.z*=b,r.max.x*=b,r.max.y*=b,r.max.z*=b;for(let e=0;e<s.length;e++){const n=s[e];0!==y&&(n.bounds.min.x+=y,n.bounds.max.x+=y),n.bounds.min.x*=b,n.bounds.min.y*=b,n.bounds.min.z*=b,n.bounds.max.x*=b,n.bounds.max.y*=b,n.bounds.max.z*=b}let m,_;if(o.color){const n=this.applyColorSystem(e,s,o.color,o.text);m=n.colors,_=n.coloredRanges}const w=this.geometryBuilder.getOptimizationStats(),O=i.length/3,k=e.length/3;return{vertices:e,normals:n,indices:i,colors:m,glyphs:s,planeBounds:r,stats:{trianglesGenerated:O,verticesGenerated:k,pointsRemovedByVisvalingam:w.pointsRemovedByVisvalingam,pointsRemovedByColinear:w.pointsRemovedByColinear,originalPointCount:w.originalPointCount,...h||{}},query:e=>{if(!c)throw new Error("Original text not available for querying");return new TextRangeQuery(c,s).execute(e)},coloredRanges:_,glyphAttributes:void 0}}getFontMetrics(){if(!this.loadedFont)throw new Error("Font not loaded. Call loadFont() first");return FontMetadataExtractor.getFontMetrics(this.loadedFont.metrics)}static async preloadPatterns(e,n){await Promise.all(e.map(async e=>{if(!Text.patternCache.has(e))try{const i=await loadPattern(e,n);Text.patternCache.set(e,i)}catch(n){i.warn(`Failed to pre-load patterns for ${e}: ${n}`)}}))}static registerPattern(e,n){Text.patternCache.set(e,n)}getLoadedFont(){return this.loadedFont}measureTextWidth(e,n=0){if(!this.loadedFont)throw new Error("Font not loaded. Call loadFont() first");return TextMeasurer.measureTextWidth(this.loadedFont,e,n)}getCacheStatistics(){return this.geometryBuilder?this.geometryBuilder.getCacheStats():null}clearCache(){this.geometryBuilder&&this.geometryBuilder.clearCache()}createGlyphAttributes(e,n){const i=new Float32Array(3*e),s=new Float32Array(e),r=new Float32Array(e);return n.forEach((n,o)=>{const h=(n.bounds.min.x+n.bounds.max.x)/2,c=(n.bounds.min.y+n.bounds.max.y)/2,l=(n.bounds.min.z+n.bounds.max.z)/2;for(let d=0;d<n.vertexCount;d++){const f=n.vertexStart+d;f<e&&(i[3*f]=h,i[3*f+1]=c,i[3*f+2]=l,s[f]=o,r[f]=n.lineIndex)}}),{glyphCenter:i,glyphIndex:s,glyphLineIndex:r}}destroy(){if(!this.loadedFont)return;const e=this.loadedFont;try{FontLoader.destroyFont(e)}catch(e){i.warn("Error destroying HarfBuzz objects:",e)}finally{this.loadedFont=void 0,this.textLayout=void 0,this.textShaper=void 0}}}e.DEFAULT_CURVE_FIDELITY=nt,e.FontMetadataExtractor=FontMetadataExtractor,e.Text=Text,e.globalGlyphCache=st});
14
+ !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).ThreeText={})}(this,function(e){const n=!("undefined"==typeof window||!window.THREE_TEXT_LOG)||"undefined"!=typeof globalThis&&"true"===globalThis.process?.env?.THREE_TEXT_LOG;const i=new class{warn(e,...n){console.warn(e,...n)}error(e,...n){console.error(e,...n)}log(e,...i){n&&console.log(e,...i)}};const s=new class{constructor(){this.metrics=[],this.activeTimers=new Map}start(e,i){if(!n)return;const s=performance.now();this.activeTimers.set(e,s),this.metrics.push({name:e,startTime:s,metadata:i})}end(e){if(!n)return null;const s=performance.now(),r=this.activeTimers.get(e);if(void 0===r)return i.warn(`Performance timer "${e}" was not started`),null;const o=s-r;this.activeTimers.delete(e);for(let n=this.metrics.length-1;n>=0;n--){const i=this.metrics[n];if(i.name===e&&!i.endTime){i.endTime=s,i.duration=o;break}}return console.log(`${e}: ${o.toFixed(2)}ms`),o}getSummary(){if(!n)return{};const e={};for(const n of this.metrics){if(!n.duration)continue;const i=e[n.name];i?(i.count++,i.totalDuration+=n.duration,i.avgDuration=i.totalDuration/i.count,i.lastDuration=n.duration):e[n.name]={count:1,avgDuration:n.duration,totalDuration:n.duration,lastDuration:n.duration}}return e}printSummary(){if(!n)return;const e=this.getSummary();console.table(e),console.log("Operations:",Object.keys(e).sort().join(", "))}printBaseline(){if(!n)return;const e=this.getSummary();Object.entries(e).forEach(([e,n])=>{console.log(`BASELINE ${e}: ${n.avgDuration.toFixed(2)}ms avg (${n.count} calls)`)})}clear(){n&&(this.metrics.length=0,this.activeTimers.clear())}time(e,i,s){if(!n)return i();this.start(e,s);try{return i()}finally{this.end(e)}}async timeAsync(e,i,s){if(!n)return i();this.start(e,s);try{return await i()}finally{this.end(e)}}},r=200,o=100,h=0,c=1/3;var l,d;!function(e){e[e.BOX=0]="BOX",e[e.GLUE=1]="GLUE",e[e.PENALTY=2]="PENALTY",e[e.DISCRETIONARY=3]="DISCRETIONARY"}(l||(l={})),function(e){e[e.TIGHT=0]="TIGHT",e[e.NORMAL=1]="NORMAL",e[e.LOOSE=2]="LOOSE",e[e.VERY_LOOSE=3]="VERY_LOOSE"}(d||(d={}));class ActiveNodeList{constructor(){this.nodesByKey=new Map,this.activeList=[],this.allNodes=new Set}getKey(e,n){return e<<2|n}insert(e){const n=this.getKey(e.position,e.fitness),i=this.nodesByKey.get(n);i&&e.totalDemerits<i.totalDemerits?(i.totalDemerits=e.totalDemerits,i.previous=e.previous,i.totalWidth=e.totalWidth):i||(this.nodesByKey.set(n,e),this.allNodes.add(e),e.activeListIndex=this.activeList.length,this.activeList.push(e))}findExisting(e,n){return this.nodesByKey.get(this.getKey(e,n))}getAllActive(){return this.activeList}deactivateNode(e){if(e.active&&void 0!==e.activeListIndex){e.active=!1;const n=e.activeListIndex,i=this.activeList.length-1;if(n!==i){const e=this.activeList[i];this.activeList[n]=e,e.activeListIndex=n}this.activeList.pop(),e.activeListIndex=void 0}}size(){return this.allNodes.size}}const f=50,p=50,g=1e4,y=10,b=1e4,m=-1/0,_=2,w=4,O=1e4;class LineBreak{static badness(e,n){if(0===e)return 0;if(n<=0)return O;let i;return i=e<=7230584?Math.floor(297*e/n):n>=1663497?Math.floor(e/Math.floor(n/297)):e,i>1290?O:Math.floor((i*i*i+131072)/262144)}static findHyphenationPoints(e,n="en-us",i,s=_,r=w){let o;if(!i||!i[n])return[];if(o=i[n],!o)return[];const h=`.${e.toLowerCase()}.`,c=new Array(h.length).fill(0);for(let e=0;e<h.length;e++){let n=o;for(let i=e;i<h.length;i++){const s=h[i];if(!n.children||!n.children[s])break;if(n=n.children[s],n.patterns)for(let i=0;i<n.patterns.length;i++){const s=e+i;s<c.length&&(c[s]=Math.max(c[s],n.patterns[i]))}}}const l=[];for(let e=2;e<h.length-2;e++)c[e]%2==1&&l.push(e-1);return l.filter(n=>n>=s&&e.length-n>=r)}static itemizeText(e,n,i=!1,s="en-us",r,o=_,h=w,c){const d=[];return d.push(...this.itemizeParagraph(e,n,i,s,r,o,h,c)),d.push({type:l.GLUE,width:0,stretch:1/0,shrink:0,text:"",originIndex:e.length}),d.push({type:l.PENALTY,width:0,penalty:-1/0,text:"",originIndex:e.length}),d}static itemizeParagraph(e,n,i,s,r,o,h,d){const g=[],y=e.match(/\S+|\s+/g)||[];let b=0;for(let e=0;e<y.length;e++){const m=y[e],_=b;if(/\s+/.test(m)){const e=n(m);g.push({type:l.GLUE,width:e,stretch:.5*e,shrink:e*c,text:m,originIndex:_}),b+=m.length}else{const e=m.split(/(-)/);let c=_;for(let y=0;y<e.length;y++){const b=e[y];if(b)if("-"===b)g.push({type:l.DISCRETIONARY,width:n("-"),preBreak:"-",postBreak:"",noBreak:"-",preBreakWidth:n("-"),penalty:d?.exHyphenPenalty??p,flagged:!0,text:"-",originIndex:c}),c+=1;else{if(b.includes("­")){const e=b.split("­");let i=0;for(let s=0;s<e.length;s++){const r=e[s];r.length>0&&(g.push({type:l.BOX,width:n(r),text:r,originIndex:c+i}),i+=r.length),s<e.length-1&&(g.push({type:l.DISCRETIONARY,width:0,preBreak:"-",postBreak:"",noBreak:"",preBreakWidth:n("-"),penalty:d?.hyphenPenalty??f,flagged:!0,text:"",originIndex:c+i}),i+=1)}}else if(i&&b.length>=o+h){const e=LineBreak.findHyphenationPoints(b,s,r,o,h);if(e.length>0){let i=0;for(const s of e){const e=b.substring(i,s);g.push({type:l.BOX,width:n(e),text:e,originIndex:c+i}),g.push({type:l.DISCRETIONARY,width:0,preBreak:"-",postBreak:"",noBreak:"",preBreakWidth:n("-"),penalty:d?.hyphenPenalty??f,flagged:!0,text:"",originIndex:c+s}),i=s}const s=b.substring(i);g.push({type:l.BOX,width:n(s),text:s,originIndex:c+i})}else g.push({type:l.BOX,width:n(b),text:b,originIndex:c})}else g.push({type:l.BOX,width:n(b),text:b,originIndex:c});c+=b.length}}b+=m.length}}return g}static hasSingleWordLines(e,n,i){let s=0;for(let r=0;r<n.length-1;r++){const o=n[r];let h=0,c=0;for(let n=s;n<o;n++)e[n].type===l.GLUE&&h++,e[n].type!==l.PENALTY&&(c+=e[n].width);if(0===h&&c>0){if(c/i<.5)return!0}s=o+1}return!1}static breakText(e){s.start("LineBreak.breakText",{textLength:e.text.length,width:e.width,align:e.align||"left",hyphenate:e.hyphenate||!1});const{text:n,width:c,align:d="left",direction:m="ltr",hyphenate:O=!1,language:k="en-us",respectExistingBreaks:j=!0,measureText:$,hyphenationPatterns:Y,unitsPerEm:q,tolerance:tt=r,pretolerance:et=o,emergencyStretch:nt=h,autoEmergencyStretch:it,lefthyphenmin:st=_,righthyphenmin:rt=w,linepenalty:at=y,adjdemerits:ot=b,hyphenpenalty:ht=f,exhyphenpenalty:ct=p,doublehyphendemerits:lt=g,looseness:ut=0,disableSingleWordDetection:dt=!1}=e;if(j&&n.includes("\n")){const i=n.split("\n"),r=[];let o=0;for(const n of i){if(0===n.length)r.push({text:"",originalStart:o,originalEnd:o,xOffset:0,isLastLine:!0,naturalWidth:0,endedWithHyphen:!1});else{const i=LineBreak.breakText({...e,text:n,respectExistingBreaks:!1});i.forEach(e=>{e.originalStart+=o,e.originalEnd+=o}),r.push(...i)}o+=n.length+1}return s.end("LineBreak.breakText"),r}let ft=O;!ft||Y&&Y[k]||(i.warn(`Hyphenation patterns for ${k} not available`),ft=!1);let pt=nt;void 0!==it&&c?pt=c*it:!ft&&nt===h&&c&&(pt=.1*c);const gt={linePenalty:at,adjDemerits:ot,doubleHyphenDemerits:lt,hyphenPenalty:ht,exHyphenPenalty:ct,currentAlign:d,unitsPerEm:q};if(!c||c===1/0){const e=$(n);return s.end("LineBreak.breakText"),[{text:n,originalStart:0,originalEnd:n.length-1,xOffset:0,isLastLine:!0,naturalWidth:e,endedWithHyphen:!1}]}const yt=LineBreak.itemizeText(n,$,ft,k,Y,st,rt,gt);if(0===yt.length)return[];let bt=0,mt=pt,_t=null;const xt=!dt;for(;bt<5;){let e=ft?yt.filter(e=>e.type!==l.DISCRETIONARY||e.penalty!==(gt?.hyphenPenalty??f)):yt,i=LineBreak.findBreakpoints(e,c,et,ut,!1,0,gt);if(0===i.length&&ft&&(e=yt,i=LineBreak.findBreakpoints(e,c,tt,ut,!1,0,gt)),0===i.length&&(e=yt,i=LineBreak.findBreakpoints(e,c,10001,ut,!0,mt,gt)),0===i.length&&(i=LineBreak.findBreakpoints(e,c,1/0,ut,!0,mt,gt)),i.length>0){const s=LineBreak.computeCumulativeWidths(e);if(_t=LineBreak.createLines(n,e,i,c,d,m,s,gt),xt&&i.length>1&&LineBreak.hasSingleWordLines(e,i,c)){mt+=.1*c,bt++;continue}break}break}if(s.end("LineBreak.breakText"),_t&&_t.length>0)return _t;const wt=$(n);return[{text:n,originalStart:0,originalEnd:n.length-1,xOffset:0,adjustmentRatio:0,isLastLine:!0,naturalWidth:wt,endedWithHyphen:!1}]}static findBreakpoints(e,n,i=1/0,s=0,r=!1,o=0,h){const c=LineBreak.computeCumulativeWidths(e),f=new ActiveNodeList;f.insert({position:0,line:0,fitness:d.NORMAL,totalDemerits:0,totalWidth:0,previous:null,active:!0});for(let s=0;s<e.length;s++){const r=e[s];r.type===l.PENALTY&&r.penalty<1/0&&LineBreak.considerBreak(e,f,s,n,i,o,c,h),r.type===l.DISCRETIONARY&&r.penalty<1/0&&LineBreak.considerBreak(e,f,s,n,i,o,c,h),r.type===l.GLUE&&s>0&&e[s-1].type===l.BOX&&LineBreak.considerBreak(e,f,s,n,i,o,c,h),LineBreak.deactivateNodes(f,s,n,c.minWidths)}const p=[];let g=null;if(0===s){const e=f.getAllActive();let n=1/0;for(const i of e)i.active&&i.totalDemerits<n&&(n=i.totalDemerits,g=i)}else{const e=f.getAllActive();let n=0,i=1/0;for(const s of e)s.active&&s.totalDemerits<i&&(i=s.totalDemerits,n=s.line);let o=0,h=1/0;for(const i of e){if(!i.active)continue;const e=i.line-n;e<o&&s<=e||e>o&&s>=e?(g=i,o=e,h=i.totalDemerits):e===o&&i.totalDemerits<h&&(g=i,h=i.totalDemerits)}if(!r&&o!==s&&g)return[]}if(!g)return[];for(;g&&g.position>0;)p.unshift(g.position),g=g.previous;return p}static considerBreak(e,n,i,s,r=1/0,o=0,h,c){const d=(e[i].type===l.PENALTY?e[i].penalty:0)<=-1/0,f=n.getAllActive();for(let p=0;p<f.length;p++){const g=f[p];if(!g.active)continue;const y=LineBreak.computeAdjustmentRatio(e,g.position,i,g.line,s,h,c),{ratio:b,adjustment:_,stretch:w,shrink:O,totalWidth:k}=y;let j;if(_>0){const e=w+o;j=e<=0?10001:LineBreak.badness(_,e)}else j=_<0?O<=0||-_>O?10001:LineBreak.badness(-_,O):0;if(!d&&b<-1)continue;const $=LineBreak.computeFitnessClass(j,_>0);if(!d&&j>r)continue;let Y=0,q=0;let tt=(c?.linePenalty??0)+j,et=Math.abs(tt)>=1e4?1e8:tt*tt;const nt=e[i].type===l.PENALTY||e[i].type===l.DISCRETIONARY?e[i].penalty:0;0!==nt&&(nt>0?et+=nt*nt:nt>m&&(et-=nt*nt));const it=e[i].type===l.PENALTY&&e[i].flagged||e[i].type===l.DISCRETIONARY&&e[i].flagged,st=g.position>0&&(e[g.position].type===l.PENALTY&&e[g.position].flagged||e[g.position].type===l.DISCRETIONARY&&e[g.position].flagged);it&&st&&(Y=c?.doubleHyphenDemerits??0,et+=Y),Math.abs($-g.fitness)>1&&(q=c?.adjDemerits??0,et+=q),d&&(et=0);const rt=g.totalDemerits+et;let at=n.findExisting(i,$);at?rt<at.totalDemerits&&(at.totalDemerits=rt,at.previous=g,at.totalWidth=k):n.insert({position:i,line:g.line+1,fitness:$,totalDemerits:rt,totalWidth:k,previous:g,active:!0})}}static computeAdjustmentRatio(e,n,i,s,r,o,h){let c=0,d=0,f=0;if(o){c=o.widths[i]-o.widths[n],d=o.stretches[i]-o.stretches[n],f=o.shrinks[i]-o.shrinks[n];for(let s=n;s<i;s++){const n=e[s];n.type===l.PENALTY&&(c-=n.width)}}else for(let s=n;s<i;s++){const n=e[s];n.type!==l.PENALTY&&(c+=n.width,n.type===l.GLUE&&(d+=n.stretch,f+=n.shrink))}i<e.length&&(e[i].type===l.PENALTY||e[i].type===l.DISCRETIONARY)&&(c+=e[i].type===l.PENALTY?e[i].width:e[i].preBreakWidth);const p=r-c;let g;return g=p>0&&d>0?p/d:p<0&&f>0?p/f:0===p?0:p>0?3:-1,{ratio:g,adjustment:p,stretch:d,shrink:f,totalWidth:c}}static computeFitnessClass(e,n){return n?e<=12?d.NORMAL:e<=99?d.LOOSE:d.VERY_LOOSE:e<=12?d.NORMAL:d.TIGHT}static computeCumulativeWidths(e){const n=e.length+1,i=new Array(n),s=new Array(n),r=new Array(n),o=new Array(n);i[0]=0,s[0]=0,r[0]=0,o[0]=0;for(let n=0;n<e.length;n++){const h=e[n];if(i[n+1]=i[n]+h.width,h.type===l.PENALTY)o[n+1]=o[n];else if(h.type===l.GLUE){const e=h;s[n+1]=s[n]+e.stretch,r[n+1]=r[n]+e.shrink,o[n+1]=o[n]+Math.max(0,e.width-e.shrink)}else s[n+1]=s[n],r[n+1]=r[n],o[n+1]=o[n]+h.width}return{widths:i,stretches:s,shrinks:r,minWidths:o}}static deactivateNodes(e,n,i,s){const r=e.getAllActive();for(let o=r.length-1;o>=0;o--){const h=r[o];if(!h.active)continue;s[n]-s[h.position]>i&&e.deactivateNode(h)}}static createLines(e,n,i,s,r,o,h,c){if(0===i.length)return[{text:e,originalStart:0,originalEnd:e.length-1,xOffset:0}];const d=[];let f=0;for(let e=0;e<i.length;e++){const p=i[e],g=!(i[i.length-1]+1<n.length-1)&&e===i.length-1,y=[];let b=-1,m=-1,_=0;for(let e=f;e<p;e++){const i=n[e];if((i.type!==l.PENALTY||i.text)&&(i.type!==l.DISCRETIONARY||i.noBreak)){if(void 0!==i.originIndex){(-1===b||i.originIndex<b)&&(b=i.originIndex);const e=i.text?i.text.length:0,n=i.originIndex+e-1;n>m&&(m=n)}if(i.text)y.push(i.text);else if(i.type===l.DISCRETIONARY){const e=i;e.noBreak&&y.push(e.noBreak)}_+=i.width}}const w=n[p];let O=!1;if(p<n.length)if(w.type===l.PENALTY&&w.flagged)y.push("-"),_+=w.width,O=!0,void 0!==w.originIndex&&(m=w.originIndex-1);else if(w.type===l.DISCRETIONARY){const e=w;e.preBreak&&(y.push(e.preBreak),_+=e.preBreakWidth,O=e.flagged||!1,void 0!==w.originIndex&&(m=w.originIndex-1))}const k=y.join("");let j=0,$=0,Y=r;if("justify"===r&&g&&(Y="rtl"===o?"right":"left"),"center"===Y)j=(s-_)/2;else if("right"===Y)j=s-_;else if("justify"===Y&&!g){$=LineBreak.computeAdjustmentRatio(n,f,p,e,s,h,c).ratio}d.push({text:k,originalStart:b,originalEnd:m,xOffset:j,adjustmentRatio:$,isLastLine:!1,naturalWidth:_,endedWithHyphen:O}),f=p+1}if(f<n.length-1){const e=[];let i=-1,h=-1,c=0;for(let s=f;s<n.length-1;s++){const r=n[s];r.type!==l.PENALTY&&(void 0!==r.originIndex&&((-1===i||r.originIndex<i)&&(i=r.originIndex),r.originIndex>h&&(h=r.originIndex)),r.text&&e.push(r.text),c+=r.width)}const p=e.join("");let g=0,y=r;"justify"===r&&(y="rtl"===o?"right":"left"),"center"===y?g=(s-c)/2:"right"===y&&(g=s-c),d.push({text:p,originalStart:i,originalEnd:h,xOffset:g,adjustmentRatio:0,isLastLine:!0,naturalWidth:c,endedWithHyphen:!1}),d.length>1&&(d[d.length-2].isLastLine=!1),d[d.length-1].isLastLine=!0}else d.length>0&&(d[d.length-1].isLastLine=!0);return d}}class TextMeasurer{static measureTextWidth(e,n,i=0){const s=e.hb.createBuffer();s.addText(n),s.guessSegmentProperties(),e.hb.shape(e.font,s);const r=s.json(e.font),o=i*e.upem;let h=0;return r.forEach(e=>{h+=e.ax,0!==o&&(h+=o)}),s.destroy(),h}}class TextLayout{constructor(e){this.loadedFont=e}computeLines(e){const{text:n,width:i,align:s,direction:r,hyphenate:o,language:h,respectExistingBreaks:c,tolerance:l,pretolerance:d,emergencyStretch:f,autoEmergencyStretch:p,hyphenationPatterns:g,lefthyphenmin:y,righthyphenmin:b,linepenalty:m,adjdemerits:_,hyphenpenalty:w,exhyphenpenalty:O,doublehyphendemerits:k,looseness:j,disableSingleWordDetection:$,letterSpacing:Y}=e;let q;if(i)q=LineBreak.breakText({text:n,width:i,align:s,direction:r,hyphenate:o,language:h,respectExistingBreaks:c,tolerance:l,pretolerance:d,emergencyStretch:f,autoEmergencyStretch:p,hyphenationPatterns:g,lefthyphenmin:y,righthyphenmin:b,linepenalty:m,adjdemerits:_,hyphenpenalty:w,exhyphenpenalty:O,doublehyphendemerits:k,looseness:j,disableSingleWordDetection:$,unitsPerEm:this.loadedFont.upem,measureText:e=>TextMeasurer.measureTextWidth(this.loadedFont,e,Y)});else{const e=n.split("\n");q=[];let i=0;for(const n of e)q.push({text:n,originalStart:i,originalEnd:i+n.length-1,xOffset:0}),i+=n.length+1}return{lines:q}}applyAlignment(e,n){const{width:i,align:s,planeBounds:r}=n;let o=0;const h={min:{...r.min},max:{...r.max}};if(i&&("center"===s||"right"===s)){const n=r.max.x-r.min.x;if("center"===s?o=(i-n)/2-r.min.x:"right"===s&&(o=i-r.max.x),0!==o){for(let n=0;n<e.length;n+=3)e[n]+=o;h.min.x+=o,h.max.x+=o}}return{offset:o,adjustedBounds:h}}}const k=1330926671,j=1953784678,$=2001684038;class FontMetadataExtractor{static extractMetadata(e){if(!e||e.byteLength<12)throw new Error("Invalid font buffer: too small to be a valid font file");const n=new DataView(e),i=n.getUint32(0);if(![65536,k,j].includes(i))throw new Error(`Invalid font format. Expected TrueType or OpenType, got signature: 0x${i.toString(16)}`);const s=new Uint8Array(e),r=n.getUint16(4);let o=!1,h=0,c=0,l=0,d=0,f=0,p=0;for(let e=0;e<r;e++){const i=(new TextDecoder).decode(s.slice(12+16*e,12+16*e+4));("CFF "===i||"CFF2"===i)&&(o=!0),"head"===i&&(h=n.getUint32(12+16*e+8)),"hhea"===i&&(c=n.getUint32(12+16*e+8)),"OS/2"===i&&(l=n.getUint32(12+16*e+8)),"fvar"===i&&(p=n.getUint32(12+16*e+8)),"STAT"===i&&(d=n.getUint32(12+16*e+8)),"name"===i&&(f=n.getUint32(12+16*e+8))}const g=h?n.getUint16(h+18):1e3;let y=null;c&&(y={ascender:n.getInt16(c+4),descender:n.getInt16(c+6),lineGap:n.getInt16(c+8)});let b=null;l&&(b={typoAscender:n.getInt16(l+68),typoDescender:n.getInt16(l+70),typoLineGap:n.getInt16(l+72),winAscent:n.getUint16(l+74),winDescent:n.getUint16(l+76)});let m=null;return p&&d&&f&&(m=this.extractAxisNames(n,d,f)),{isCFF:o,unitsPerEm:g,hheaAscender:y?.ascender||null,hheaDescender:y?.descender||null,hheaLineGap:y?.lineGap||null,typoAscender:b?.typoAscender||null,typoDescender:b?.typoDescender||null,typoLineGap:b?.typoLineGap||null,winAscent:b?.winAscent||null,winDescent:b?.winDescent||null,axisNames:m}}static extractAxisNames(e,n,i){try{if(e.getUint16(n)<1)return null;const s=e.getUint16(n+4),r=e.getUint16(n+6),o=e.getUint32(n+8),h={};for(let c=0;c<r;c++){const r=n+o+c*s,l=String.fromCharCode(e.getUint8(r),e.getUint8(r+1),e.getUint8(r+2),e.getUint8(r+3)),d=e.getUint16(r+4),f=this.getNameFromNameTable(e,i,d);f&&(h[l]=f)}return Object.keys(h).length>0?h:null}catch(e){return null}}static getNameFromNameTable(e,n,i){try{const s=e.getUint16(n+2),r=e.getUint16(n+4);for(let o=0;o<s;o++){const s=n+6+12*o,h=e.getUint16(s),c=e.getUint16(s+2),l=e.getUint16(s+4),d=e.getUint16(s+6),f=e.getUint16(s+8),p=e.getUint16(s+10);if(d===i&&(0===h||3===h&&1033===l)){const i=n+r+p,s=new Uint8Array(e.buffer,i,f);if(0===h||3===h&&1===c){let e="";for(let n=0;n<s.length;n+=2)e+=String.fromCharCode(s[n]<<8|s[n+1]);return e}return new TextDecoder("ascii").decode(s)}}return null}catch(e){return null}}static getVerticalMetrics(e){return null!==e.typoAscender&&null!==e.typoDescender?{ascender:e.typoAscender,descender:e.typoDescender,lineGap:0}:null!==e.hheaAscender&&null!==e.hheaDescender?{ascender:e.hheaAscender,descender:e.hheaDescender,lineGap:0}:null!==e.winAscent&&null!==e.winDescent?{ascender:e.winAscent,descender:-e.winDescent,lineGap:0}:{ascender:Math.round(.8*e.unitsPerEm),descender:-Math.round(.2*e.unitsPerEm),lineGap:0}}static getFontMetrics(e){const n=FontMetadataExtractor.getVerticalMetrics(e);return{ascender:n.ascender,descender:n.descender,lineGap:n.lineGap,unitsPerEm:e.unitsPerEm,naturalLineHeight:n.ascender-n.descender}}}class WoffConverter{static detectFormat(e){if(e.byteLength<4)return"ttf/otf";const n=new DataView(e).getUint32(0);return n===$?"woff":2001684018===n?"woff2":"ttf/otf"}static async decompressWoff(e){const n=new DataView(e),s=new Uint8Array(e);if(n.getUint32(0)!==$)throw new Error("Not a valid WOFF font");const r=n.getUint32(4),o=n.getUint16(12),h=n.getUint32(16);if("undefined"==typeof DecompressionStream)throw new Error("WOFF fonts require DecompressionStream API (Chrome 80+, Firefox 113+, Safari 16.4+). Please use TTF/OTF fonts or upgrade your browser.");const c=new Uint8Array(h),l=new DataView(c.buffer);l.setUint32(0,r),l.setUint16(4,o);const d=2**Math.floor(Math.log2(o))*16;l.setUint16(6,d),l.setUint16(8,Math.floor(Math.log2(o))),l.setUint16(10,16*o-d);let f=12+16*o;const p=[];for(let e=0;e<o;e++){const i=44+20*e;p.push({tag:n.getUint32(i),offset:n.getUint32(i+4),length:n.getUint32(i+8),origLength:n.getUint32(i+12),checksum:n.getUint32(i+16)})}p.sort((e,n)=>e.tag-n.tag);for(let e=0;e<o;e++){const n=p[e],i=12+16*e;if(l.setUint32(i,n.tag),l.setUint32(i+4,n.checksum),l.setUint32(i+8,f),l.setUint32(i+12,n.origLength),n.length===n.origLength)c.set(s.subarray(n.offset,n.offset+n.length),f);else{const e=s.subarray(n.offset,n.offset+n.length),i=await WoffConverter.decompressZlib(e);if(i.byteLength!==n.origLength)throw new Error(`Decompression failed: expected ${n.origLength} bytes, got ${i.byteLength}`);c.set(new Uint8Array(i),f)}f+=n.origLength;f+=(4-n.origLength%4)%4}return i.log("WOFF font decompressed successfully"),c.buffer.slice(0,f)}static async decompressZlib(e){const n=new ReadableStream({start(n){n.enqueue(e),n.close()}}).pipeThrough(new DecompressionStream("deflate"));return new Response(n).arrayBuffer()}}class FontLoader{constructor(e){this.getHarfBuzzInstance=e}async loadFont(e,n){if(s.start("FontLoader.loadFont",{bufferSize:e.byteLength}),!e||e.byteLength<12)throw new Error("Invalid font buffer: too small to be a valid font file");const r=WoffConverter.detectFormat(e);if("woff"===r)i.log("WOFF font detected, decompressing..."),e=await WoffConverter.decompressWoff(e);else if("woff2"===r)throw new Error("WOFF2 fonts are not yet supported. Please use WOFF or TTF/OTF format.");const o=new DataView(e).getUint32(0);if(![65536,k,j].includes(o))throw new Error(`Invalid font format. Expected TrueType or OpenType, got signature: 0x${o.toString(16)}`);const{hb:h,module:c}=await this.getHarfBuzzInstance();try{const i=h.createBlob(new Uint8Array(e)),s=h.createFace(i,0),r=h.createFont(s);n&&r.setVariations(n);const o=s.getAxisInfos(),l=Object.keys(o).length>0,d=FontMetadataExtractor.extractMetadata(e);let f;if(l&&o){f={};for(const[e,n]of Object.entries(o))f[e]={...n,name:d.axisNames?.[e]||null}}return{hb:h,fontBlob:i,face:s,font:r,module:c,upem:d.unitsPerEm,metrics:d,fontVariations:n,isVariable:l,variationAxes:f}}catch(e){throw i.error("Failed to load font:",e),e}finally{s.end("FontLoader.loadFont")}}static destroyFont(e){try{e.font&&"function"==typeof e.font.destroy&&e.font.destroy(),e.face&&"function"==typeof e.face.destroy&&e.face.destroy(),e.fontBlob&&"function"==typeof e.fontBlob.destroy&&e.fontBlob.destroy()}catch(e){i.error("Error destroying font resources:",e)}}}async function loadPattern(e,n){{const i=`ThreeTextPatterns_${e.replace(/-/g,"_")}`;if(window[i])return window[i];const s=n||"/patterns/";return new Promise((n,r)=>{const o=document.createElement("script");o.src=`${s}${e}.umd.js`,o.async=!0,o.onload=()=>{window[i]?n(window[i]):r(new Error(`Pattern script loaded, but global ${i} not found.`))},o.onerror=()=>{r(new Error(`Failed to load hyphenation pattern from ${o.src}. Did you copy the pattern files to your public directory?`))},document.head.appendChild(o)})}}class Vec2{constructor(e=0,n=0){this.x=e,this.y=n}set(e,n){return this.x=e,this.y=n,this}clone(){return new Vec2(this.x,this.y)}copy(e){return this.x=e.x,this.y=e.y,this}add(e){return this.x+=e.x,this.y+=e.y,this}sub(e){return this.x-=e.x,this.y-=e.y,this}multiply(e){return this.x*=e,this.y*=e,this}divide(e){return this.x/=e,this.y/=e,this}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}lengthSq(){return this.x*this.x+this.y*this.y}normalize(){const e=this.length();return e>0&&this.divide(e),this}dot(e){return this.x*e.x+this.y*e.y}distanceTo(e){const n=this.x-e.x,i=this.y-e.y;return Math.sqrt(n*n+i*i)}distanceToSquared(e){const n=this.x-e.x,i=this.y-e.y;return n*n+i*i}equals(e){return this.x===e.x&&this.y===e.y}angle(){return Math.atan2(this.y,this.x)}}class Vec3{constructor(e=0,n=0,i=0){this.x=e,this.y=n,this.z=i}set(e,n,i){return this.x=e,this.y=n,this.z=i,this}clone(){return new Vec3(this.x,this.y,this.z)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}multiply(e){return this.x*=e,this.y*=e,this.z*=e,this}divide(e){return this.x/=e,this.y/=e,this.z/=e,this}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}normalize(){const e=this.length();return e>0&&this.divide(e),this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.z}cross(e){const n=this.y*e.z-this.z*e.y,i=this.z*e.x-this.x*e.z,s=this.x*e.y-this.y*e.x;return this.x=n,this.y=i,this.z=s,this}distanceTo(e){const n=this.x-e.x,i=this.y-e.y,s=this.z-e.z;return Math.sqrt(n*n+i*i+s*s)}distanceToSquared(e){const n=this.x-e.x,i=this.y-e.y,s=this.z-e.z;return n*n+i*i+s*s}equals(e){return this.x===e.x&&this.y===e.y&&this.z===e.z}}class Box3{constructor(e=new Vec3(1/0,1/0,1/0),n=new Vec3(-1/0,-1/0,-1/0)){this.min=e,this.max=n}set(e,n){return this.min.copy(e),this.max.copy(n),this}setFromPoints(e){this.makeEmpty();for(let n=0;n<e.length;n++)this.expandByPoint(e[n]);return this}makeEmpty(){return this.min.x=this.min.y=this.min.z=1/0,this.max.x=this.max.y=this.max.z=-1/0,this}isEmpty(){return this.max.x<this.min.x||this.max.y<this.min.y||this.max.z<this.min.z}expandByPoint(e){return this.min.x=Math.min(this.min.x,e.x),this.min.y=Math.min(this.min.y,e.y),this.min.z=Math.min(this.min.z,e.z),this.max.x=Math.max(this.max.x,e.x),this.max.y=Math.max(this.max.y,e.y),this.max.z=Math.max(this.max.z,e.z),this}expandByScalar(e){return this.min.x-=e,this.min.y-=e,this.min.z-=e,this.max.x+=e,this.max.y+=e,this.max.z+=e,this}containsPoint(e){return e.x>=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y&&e.z>=this.min.z&&e.z<=this.max.z}containsBox(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z}intersectsBox(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y&&e.max.z>=this.min.z&&e.min.z<=this.max.z}getCenter(e=new Vec3){return this.isEmpty()?e.set(0,0,0):e.set(.5*(this.min.x+this.max.x),.5*(this.min.y+this.max.y),.5*(this.min.z+this.max.z))}getSize(e=new Vec3){return this.isEmpty()?e.set(0,0,0):e.set(this.max.x-this.min.x,this.max.y-this.min.y,this.max.z-this.min.z)}clone(){return new Box3(this.min.clone(),this.max.clone())}copy(e){return this.min.copy(e.min),this.max.copy(e.max),this}union(e){return this.min.x=Math.min(this.min.x,e.min.x),this.min.y=Math.min(this.min.y,e.min.y),this.min.z=Math.min(this.min.z,e.min.z),this.max.x=Math.max(this.max.x,e.max.x),this.max.y=Math.max(this.max.y,e.max.y),this.max.z=Math.max(this.max.z,e.max.z),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}var Y="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function getDefaultExportFromCjs(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function getAugmentedNamespace(e){if(e.__esModule)return e;var n=e.default;if("function"==typeof n){var i=function a(){return this instanceof a?Reflect.construct(n,arguments,this.constructor):n.apply(this,arguments)};i.prototype=n.prototype}else i={};return Object.defineProperty(i,"__esModule",{value:!0}),Object.keys(e).forEach(function(n){var s=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(i,n,s.get?s:{enumerable:!0,get:function(){return e[n]}})}),i}var q={exports:{}};!function(e){var n;function t(e,n){return e.b===n.b&&e.a===n.a}function u(e,n){return e.b<n.b||e.b===n.b&&e.a<=n.a}function v(e,n,i){var s=n.b-e.b,r=i.b-n.b;return 0<s+r?s<r?n.a-e.a+s/(s+r)*(e.a-i.a):n.a-i.a+r/(s+r)*(i.a-e.a):0}function x(e,n,i){var s=n.b-e.b,r=i.b-n.b;return 0<s+r?(n.a-i.a)*s+(n.a-e.a)*r:0}function z(e,n){return e.a<n.a||e.a===n.a&&e.b<=n.b}function aa(e,n,i){var s=n.a-e.a,r=i.a-n.a;return 0<s+r?s<r?n.b-e.b+s/(s+r)*(e.b-i.b):n.b-i.b+r/(s+r)*(i.b-e.b):0}function ba(e,n,i){var s=n.a-e.a,r=i.a-n.a;return 0<s+r?(n.b-i.b)*s+(n.b-e.b)*r:0}function ca(e){return u(e.b.a,e.a)}function da(e){return u(e.a,e.b.a)}function A(e,n,i,s){return(e=0>e?0:e)<=(i=0>i?0:i)?0===i?(n+s)/2:n+e/(e+i)*(s-n):s+i/(e+i)*(n-s)}function ea(e){var n=B(e.b);return C(n,e.c),C(n.b,e.c),D(n,e.a),n}function E(e,n){var i=!1,s=!1;e!==n&&(n.a!==e.a&&(s=!0,F(n.a,e.a)),n.d!==e.d&&(i=!0,G(n.d,e.d)),H(n,e),s||(C(n,e.a),e.a.c=e),i||(D(n,e.d),e.d.a=e))}function I(e){var n=e.b,i=!1;e.d!==e.b.d&&(i=!0,G(e.d,e.b.d)),e.c===e?F(e.a,null):(e.b.d.a=J(e),e.a.c=e.c,H(e,J(e)),i||D(e,e.d)),n.c===n?(F(n.a,null),G(n.d,null)):(e.d.a=J(n),n.a.c=n.c,H(n,J(n))),fa(e)}function K(e){var n=B(e),i=n.b;return H(n,e.e),n.a=e.b.a,C(i,n.a),n.d=i.d=e.d,n=n.b,H(e.b,J(e.b)),H(e.b,n),e.b.a=n.a,n.b.a.c=n.b,n.b.d=e.b.d,n.f=e.f,n.b.f=e.b.f,n}function L(e,n){var i=!1,s=B(e),r=s.b;return n.d!==e.d&&(i=!0,G(n.d,e.d)),H(s,e.e),H(r,n),s.a=e.b.a,r.a=n.a,s.d=r.d=e.d,e.d.a=r,i||D(s,e.d),s}function B(e){var n=new M,i=new M,s=e.b.h;return i.h=s,s.b.h=n,n.h=e,e.b.h=i,n.b=i,n.c=n,n.e=i,i.b=n,i.c=i,i.e=n}function H(e,n){var i=e.c,s=n.c;i.b.e=n,s.b.e=e,e.c=s,n.c=i}function C(e,n){var i=n.f,s=new N(n,i);i.e=s,n.f=s,i=s.c=e;do{i.a=s,i=i.c}while(i!==e)}function D(e,n){var i=n.d,s=new ga(n,i);i.b=s,n.d=s,s.a=e,s.c=n.c,i=e;do{i.d=s,i=i.e}while(i!==e)}function fa(e){var n=e.h;e=e.b.h,n.b.h=e,e.b.h=n}function F(e,n){var i=e.c,s=i;do{s.a=n,s=s.c}while(s!==i);i=e.f,(s=e.e).f=i,i.e=s}function G(e,n){var i=e.a,s=i;do{s.d=n,s=s.e}while(s!==i);i=e.d,(s=e.b).d=i,i.b=s}function ha(e){var n=0;return Math.abs(e[1])>Math.abs(e[0])&&(n=1),Math.abs(e[2])>Math.abs(e[n])&&(n=2),n}var i=4e150;function P(e,n){e.f+=n.f,e.b.f+=n.b.f}function ia(e,n,i){return e=e.a,n=n.a,i=i.a,n.b.a===e?i.b.a===e?u(n.a,i.a)?0>=x(i.b.a,n.a,i.a):0<=x(n.b.a,i.a,n.a):0>=x(i.b.a,e,i.a):i.b.a===e?0<=x(n.b.a,e,n.a):(n=v(n.b.a,e,n.a))>=(e=v(i.b.a,e,i.a))}function Q(e){e.a.i=null;var n=e.e;n.a.c=n.c,n.c.a=n.a,e.e=null}function ja(e,n){I(e.a),e.c=!1,e.a=n,n.i=e}function ka(e){var n=e.a.a;do{e=R(e)}while(e.a.a===n);return e.c&&(ja(e,n=L(S(e).a.b,e.a.e)),e=R(e)),e}function la(e,n,i){var s=new ma;return s.a=i,s.e=na(e.f,n.e,s),i.i=s}function oa(e,n){switch(e.s){case 100130:return!!(1&n);case 100131:return 0!==n;case 100132:return 0<n;case 100133:return 0>n;case 100134:return 2<=n||-2>=n}return!1}function pa(e){var n=e.a,i=n.d;i.c=e.d,i.a=n,Q(e)}function T(e,n,i){for(e=n,n=n.a;e!==i;){e.c=!1;var s=S(e),r=s.a;if(r.a!==n.a){if(!s.c){pa(e);break}ja(s,r=L(n.c.b,r.b))}n.c!==r&&(E(J(r),r),E(n,r)),pa(e),n=s.a,e=s}return n}function U(e,n,i,s,r,o){var h=!0;do{la(e,n,i.b),i=i.c}while(i!==s);for(null===r&&(r=S(n).a.b.c);(i=(s=S(n)).a.b).a===r.a;)i.c!==r&&(E(J(i),i),E(J(r),i)),s.f=n.f-i.f,s.d=oa(e,s.f),n.b=!0,!h&&qa(e,n)&&(P(i,r),Q(n),I(r)),h=!1,n=s,r=i;n.b=!0,o&&ra(e,n)}function sa(e,n,i,s,r){var o=[n.g[0],n.g[1],n.g[2]];n.d=null,n.d=e.o&&e.o(o,i,s,e.c)||null,null===n.d&&(r?e.n||(V(e,100156),e.n=!0):n.d=i[0])}function ta(e,n,i){var s=[null,null,null,null];s[0]=n.a.d,s[1]=i.a.d,sa(e,n.a,s,[.5,.5,0,0],!1),E(n,i)}function ua(e,n,i,s,r){var o=Math.abs(n.b-e.b)+Math.abs(n.a-e.a),h=Math.abs(i.b-e.b)+Math.abs(i.a-e.a),c=r+1;s[r]=.5*h/(o+h),s[c]=.5*o/(o+h),e.g[0]+=s[r]*n.g[0]+s[c]*i.g[0],e.g[1]+=s[r]*n.g[1]+s[c]*i.g[1],e.g[2]+=s[r]*n.g[2]+s[c]*i.g[2]}function qa(e,n){var i=S(n),s=n.a,r=i.a;if(u(s.a,r.a)){if(0<x(r.b.a,s.a,r.a))return!1;if(t(s.a,r.a)){if(s.a!==r.a){i=e.e;var o=s.a.h;if(0<=o){var h=(i=i.b).d,c=i.e,l=i.c,d=l[o];h[d]=h[i.a],l[h[d]]=d,d<=--i.a&&(1>=d||u(c[h[d>>1]],c[h[d]])?W(i,d):va(i,d)),c[o]=null,l[o]=i.b,i.b=o}else for(i.c[-(o+1)]=null;0<i.a&&null===i.c[i.d[i.a-1]];)--i.a;ta(e,J(r),s)}}else K(r.b),E(s,J(r)),n.b=i.b=!0}else{if(0>x(s.b.a,r.a,s.a))return!1;R(n).b=n.b=!0,K(s.b),E(J(r),s)}return!0}function wa(e,n){var i=S(n),s=n.a,r=i.a,o=s.a,h=r.a,c=s.b.a,l=r.b.a,d=new N;if(x(c,e.a,o),x(l,e.a,h),o===h||Math.min(o.a,c.a)>Math.max(h.a,l.a))return!1;if(u(o,h)){if(0<x(l,o,h))return!1}else if(0>x(c,h,o))return!1;var f,p,g=c,y=o,b=l,m=h;if(u(g,y)||(f=g,g=y,y=f),u(b,m)||(f=b,b=m,m=f),u(g,b)||(f=g,g=b,b=f,f=y,y=m,m=f),u(b,y)?u(y,m)?(0>(f=v(g,b,y))+(p=v(b,y,m))&&(f=-f,p=-p),d.b=A(f,b.b,p,y.b)):(0>(f=x(g,b,y))+(p=-x(g,m,y))&&(f=-f,p=-p),d.b=A(f,b.b,p,m.b)):d.b=(b.b+y.b)/2,z(g,y)||(f=g,g=y,y=f),z(b,m)||(f=b,b=m,m=f),z(g,b)||(f=g,g=b,b=f,f=y,y=m,m=f),z(b,y)?z(y,m)?(0>(f=aa(g,b,y))+(p=aa(b,y,m))&&(f=-f,p=-p),d.a=A(f,b.a,p,y.a)):(0>(f=ba(g,b,y))+(p=-ba(g,m,y))&&(f=-f,p=-p),d.a=A(f,b.a,p,m.a)):d.a=(b.a+y.a)/2,u(d,e.a)&&(d.b=e.a.b,d.a=e.a.a),g=u(o,h)?o:h,u(g,d)&&(d.b=g.b,d.a=g.a),t(d,o)||t(d,h))return qa(e,n),!1;if(!t(c,e.a)&&0<=x(c,e.a,d)||!t(l,e.a)&&0>=x(l,e.a,d)){if(l===e.a)return K(s.b),E(r.b,s),s=S(n=ka(n)).a,T(e,S(n),i),U(e,n,J(s),s,s,!0),!0;if(c===e.a){K(r.b),E(s.e,J(r)),h=(o=i=n).a.b.a;do{o=R(o)}while(o.a.b.a===h);return o=S(n=o).a.b.c,i.a=J(r),U(e,n,(r=T(e,i,null)).c,s.b.c,o,!0),!0}return 0<=x(c,e.a,d)&&(R(n).b=n.b=!0,K(s.b),s.a.b=e.a.b,s.a.a=e.a.a),0>=x(l,e.a,d)&&(n.b=i.b=!0,K(r.b),r.a.b=e.a.b,r.a.a=e.a.a),!1}return K(s.b),K(r.b),E(J(r),s),s.a.b=d.b,s.a.a=d.a,s.a.h=xa(e.e,s.a),s=s.a,r=[0,0,0,0],d=[o.d,c.d,h.d,l.d],s.g[0]=s.g[1]=s.g[2]=0,ua(s,o,c,r,0),ua(s,h,l,r,2),sa(e,s,d,r,!0),R(n).b=n.b=i.b=!0,!1}function ra(e,n){for(var i=S(n);;){for(;i.b;)n=i,i=S(i);if(!n.b&&(i=n,null===(n=R(n))||!n.b))break;n.b=!1;var s,r=n.a,o=i.a;if(s=r.b.a!==o.b.a)t:{var h=S(s=n),c=s.a,l=h.a,d=void 0;if(u(c.b.a,l.b.a)){if(0>x(c.b.a,l.b.a,c.a)){s=!1;break t}R(s).b=s.b=!0,d=K(c),E(l.b,d),d.d.c=s.d}else{if(0<x(l.b.a,c.b.a,l.a)){s=!1;break t}s.b=h.b=!0,d=K(l),E(c.e,l.b),d.b.d.c=s.d}s=!0}if(s&&(i.c?(Q(i),I(o),o=(i=S(n)).a):n.c&&(Q(n),I(r),r=(n=R(i)).a)),r.a!==o.a)if(r.b.a===o.b.a||n.c||i.c||r.b.a!==e.a&&o.b.a!==e.a)qa(e,n);else if(wa(e,n))break;r.a===o.a&&r.b.a===o.b.a&&(P(o,r),Q(n),I(r),n=R(i))}}function ya(e,n){e.a=n;for(var i=n.c;null===i.i;)if((i=i.c)===n.c){i=e;var s=n;(h=new ma).a=s.c.b;var r=(l=i.f).a;do{r=r.a}while(null!==r.b&&!l.c(l.b,h,r.b));var o=S(l=r.b),h=l.a;r=o.a;if(0===x(h.b.a,s,h.a))t((h=l.a).a,s)||t(h.b.a,s)||(K(h.b),l.c&&(I(h.c),l.c=!1),E(s.c,h),ya(i,s));else{var c=u(r.b.a,h.b.a)?l:o;o=void 0;l.d||c.c?(o=c===l?L(s.c.b,h.e):L(r.b.c.b,s.c).b,c.c?ja(c,o):(h=i,(l=la(i,l,o)).f=R(l).f+l.a.f,l.d=oa(h,l.f)),ya(i,s)):U(i,l,s.c,s.c,null,!0)}return}if(l=(h=S(i=ka(i.i))).a,(h=T(e,h,null)).c===l){h=(l=h).c,r=S(i),o=i.a,c=r.a;var l,d=!1;o.b.a!==c.b.a&&wa(e,i),t(o.a,e.a)&&(E(J(h),o),h=S(i=ka(i)).a,T(e,S(i),r),d=!0),t(c.a,e.a)&&(E(l,J(c)),l=T(e,r,null),d=!0),d?U(e,i,l.c,h,h,!0):(s=u(c.a,o.a)?J(c):o,U(e,i,s=L(l.c.b,s),s.c,s.c,!1),s.b.i.c=!0,ra(e,i))}else U(e,i,h.c,l,l,!0)}function za(e,n){var s=new ma,r=ea(e.b);r.a.b=i,r.a.a=n,r.b.a.b=-i,r.b.a.a=n,e.a=r.b.a,s.a=r,s.f=0,s.d=!1,s.c=!1,s.h=!0,s.b=!1,r=na(r=e.f,r.a,s),s.e=r}function Aa(e){this.a=new Ba,this.b=e,this.c=ia}function na(e,n,i){do{n=n.c}while(null!==n.b&&!e.c(e.b,n.b,i));return e=new Ba(i,n.a,n),n.a.c=e,n.a=e}function Ba(e,n,i){this.b=e||null,this.a=n||this,this.c=i||this}function X(){this.d=s,this.p=this.b=this.q=null,this.j=[0,0,0],this.s=100130,this.n=!1,this.o=this.a=this.e=this.f=null,this.m=!1,this.c=this.r=this.i=this.k=this.l=this.h=null}var s=0;function Z(e,n){if(e.d!==n)for(;e.d!==n;)if(e.d<n)switch(e.d){case s:V(e,100151),e.u(null);break;case 1:V(e,100152),e.t()}else switch(e.d){case 2:V(e,100154),e.v();break;case 1:V(e,100153),e.w()}}function V(e,n){e.p&&e.p(n,e.c)}function ga(e,n){this.b=e||this,this.d=n||this,this.a=null,this.c=!1}function M(){this.h=this,this.i=this.d=this.a=this.e=this.c=this.b=null,this.f=0}function J(e){return e.b.e}function Ca(){this.c=new N,this.a=new ga,this.b=new M,this.d=new M,this.b.b=this.d,this.d.b=this.b}function N(e,n){this.e=e||this,this.f=n||this,this.d=this.c=null,this.g=[0,0,0],this.h=this.a=this.b=0}function Da(){this.c=[],this.d=null,this.a=0,this.e=!1,this.b=new Ha}function xa(e,n){if(e.e){var i,s=e.b,r=++s.a;return 2*r>s.f&&(s.f*=2,s.c=Ja(s.c,s.f+1)),0===s.b?i=r:(i=s.b,s.b=s.c[s.b]),s.e[i]=n,s.c[i]=r,s.d[r]=i,s.h&&va(s,r),i}return s=e.a++,e.c[s]=n,-(s+1)}function Fa(e){if(0===e.a)return Ka(e.b);var n=e.c[e.d[e.a-1]];if(0!==e.b.a&&u(Ga(e.b),n))return Ka(e.b);do{--e.a}while(0<e.a&&null===e.c[e.d[e.a-1]]);return n}function Ha(){this.d=Ja([0],33),this.e=[null,null],this.c=[0,0],this.a=0,this.f=32,this.b=0,this.h=!1,this.d[1]=1}function Ja(e,n){for(var i=Array(n),s=0;s<e.length;s++)i[s]=e[s];for(;s<n;s++)i[s]=0;return i}function Ga(e){return e.e[e.d[1]]}function Ka(e){var n=e.d,i=e.e,s=e.c,r=n[1],o=i[r];return 0<e.a&&(n[1]=n[e.a],s[n[1]]=1,i[r]=null,s[r]=e.b,e.b=r,0<--e.a&&W(e,1)),o}function W(e,n){for(var i=e.d,s=e.e,r=e.c,o=n,h=i[o];;){var c=o<<1;c<e.a&&u(s[i[c+1]],s[i[c]])&&(c+=1);var l=i[c];if(c>e.a||u(s[h],s[l])){i[o]=h,r[h]=o;break}i[o]=l,r[l]=o,o=c}}function va(e,n){for(var i=e.d,s=e.e,r=e.c,o=n,h=i[o];;){var c=o>>1,l=i[c];if(0===c||u(s[l],s[h])){i[o]=h,r[h]=o;break}i[o]=l,r[l]=o,o=c}}function ma(){this.e=this.a=null,this.f=0,this.c=this.b=this.h=this.d=!1}function S(e){return e.e.c.b}function R(e){return e.e.a.b}(n=X.prototype).x=function(){Z(this,s)},n.B=function(e,n){switch(e){case 100142:return;case 100140:switch(n){case 100130:case 100131:case 100132:case 100133:case 100134:return void(this.s=n)}break;case 100141:return void(this.m=!!n);default:return void V(this,100900)}V(this,100901)},n.y=function(e){switch(e){case 100142:return 0;case 100140:return this.s;case 100141:return this.m;default:V(this,100900)}return!1},n.A=function(e,n,i){this.j[0]=e,this.j[1]=n,this.j[2]=i},n.z=function(e,n){var i=n||null;switch(e){case 100100:case 100106:this.h=i;break;case 100104:case 100110:this.l=i;break;case 100101:case 100107:this.k=i;break;case 100102:case 100108:this.i=i;break;case 100103:case 100109:this.p=i;break;case 100105:case 100111:this.o=i;break;case 100112:this.r=i;break;default:V(this,100900)}},n.C=function(e,n){var i=!1,s=[0,0,0];Z(this,2);for(var r=0;3>r;++r){var o=e[r];-1e150>o&&(o=-1e150,i=!0),1e150<o&&(o=1e150,i=!0),s[r]=o}i&&V(this,100155),null===(i=this.q)?E(i=ea(this.b),i.b):(K(i),i=i.e),i.a.d=n,i.a.g[0]=s[0],i.a.g[1]=s[1],i.a.g[2]=s[2],i.f=1,i.b.f=-1,this.q=i},n.u=function(e){Z(this,s),this.d=1,this.b=new Ca,this.c=e},n.t=function(){Z(this,1),this.d=2,this.q=null},n.v=function(){Z(this,2),this.d=1},n.w=function(){Z(this,1),this.d=s;var e=!1,n=[l=this.j[0],r=this.j[1],h=this.j[2]];if(0===l&&0===r&&0===h){for(var r=[-2e150,-2e150,-2e150],o=[2e150,2e150,2e150],h=[],c=[],l=(e=this.b.c).e;l!==e;l=l.e)for(var d=0;3>d;++d){var f=l.g[d];f<o[d]&&(o[d]=f,c[d]=l),f>r[d]&&(r[d]=f,h[d]=l)}if(l=0,r[1]-o[1]>r[0]-o[0]&&(l=1),r[2]-o[2]>r[l]-o[l]&&(l=2),o[l]>=r[l])n[0]=0,n[1]=0,n[2]=1;else{for(r=0,o=c[l],h=h[l],c=[0,0,0],o=[o.g[0]-h.g[0],o.g[1]-h.g[1],o.g[2]-h.g[2]],d=[0,0,0],l=e.e;l!==e;l=l.e)d[0]=l.g[0]-h.g[0],d[1]=l.g[1]-h.g[1],d[2]=l.g[2]-h.g[2],c[0]=o[1]*d[2]-o[2]*d[1],c[1]=o[2]*d[0]-o[0]*d[2],c[2]=o[0]*d[1]-o[1]*d[0],(f=c[0]*c[0]+c[1]*c[1]+c[2]*c[2])>r&&(r=f,n[0]=c[0],n[1]=c[1],n[2]=c[2]);0>=r&&(n[0]=n[1]=n[2]=0,n[ha(o)]=1)}e=!0}for(c=ha(n),l=this.b.c,r=(c+1)%3,h=(c+2)%3,c=0<n[c]?1:-1,n=l.e;n!==l;n=n.e)n.b=n.g[r],n.a=c*n.g[h];if(e){for(n=0,l=(e=this.b.a).b;l!==e;l=l.b)if(!(0>=(r=l.a).f))do{n+=(r.a.b-r.b.a.b)*(r.a.a+r.b.a.a),r=r.e}while(r!==l.a);if(0>n)for(e=(n=this.b.c).e;e!==n;e=e.e)e.a=-e.a}for(this.n=!1,l=(n=this.b.b).h;l!==n;l=e)e=l.h,r=l.e,t(l.a,l.b.a)&&l.e.e!==l&&(ta(this,r,l),I(l),r=(l=r).e),r.e===l&&(r!==l&&(r!==e&&r!==e.b||(e=e.h),I(r)),l!==e&&l!==e.b||(e=e.h),I(l));for(this.e=n=new Da,l=(e=this.b.c).e;l!==e;l=l.e)l.h=xa(n,l);for(function(e){e.d=[];for(var n=0;n<e.a;n++)e.d[n]=n;e.d.sort(function(e){return function(n,i){return u(e[n],e[i])?1:-1}}(e.c)),e.e=!0,function(e){for(var n=e.a;1<=n;--n)W(e,n);e.h=!0}(e.b)}(n),this.f=new Aa(this),za(this,-i),za(this,i);null!==(n=Fa(this.e));){for(;;){t:if(l=this.e,0===l.a)e=Ga(l.b);else if(e=l.c[l.d[l.a-1]],0!==l.b.a&&(l=Ga(l.b),u(l,e))){e=l;break t}if(null===e||!t(e,n))break;e=Fa(this.e),ta(this,n.c,e.c)}ya(this,n)}for(this.a=this.f.a.a.b.a.a,n=0;null!==(e=this.f.a.a.b);)e.h||++n,Q(e);for(this.f=null,(n=this.e).b=null,n.d=null,this.e=n.c=null,l=(n=this.b).a.b;l!==n.a;l=e)e=l.b,(l=l.a).e.e===l&&(P(l.c,l),I(l));if(!this.n){if(n=this.b,this.m)for(l=n.b.h;l!==n.b;l=e)e=l.h,l.b.d.c!==l.d.c?l.f=l.d.c?1:-1:I(l);else for(l=n.a.b;l!==n.a;l=e)if(e=l.b,l.c){for(l=l.a;u(l.b.a,l.a);l=l.c.b);for(;u(l.a,l.b.a);l=l.e);for(r=l.c.b,h=void 0;l.e!==r;)if(u(l.b.a,r.a)){for(;r.e!==l&&(ca(r.e)||0>=x(r.a,r.b.a,r.e.b.a));)r=(h=L(r.e,r)).b;r=r.c.b}else{for(;r.e!==l&&(da(l.c.b)||0<=x(l.b.a,l.a,l.c.b.a));)l=(h=L(l,l.c.b)).b;l=l.e}for(;r.e.e!==l;)r=(h=L(r.e,r)).b}if(this.h||this.i||this.k||this.l)if(this.m){for(e=(n=this.b).a.b;e!==n.a;e=e.b)if(e.c){this.h&&this.h(2,this.c),l=e.a;do{this.k&&this.k(l.a.d,this.c),l=l.e}while(l!==e.a);this.i&&this.i(this.c)}}else{for(n=this.b,e=!!this.l,l=!1,r=-1,h=n.a.d;h!==n.a;h=h.d)if(h.c){l||(this.h&&this.h(4,this.c),l=!0),c=h.a;do{e&&(r!==(o=c.b.d.c?0:1)&&(r=o,this.l&&this.l(!!r,this.c))),this.k&&this.k(c.a.d,this.c),c=c.e}while(c!==h.a)}l&&this.i&&this.i(this.c)}if(this.r){for(l=(n=this.b).a.b;l!==n.a;l=e)if(e=l.b,!l.c){h=(r=l.a).e,c=void 0;do{h=(c=h).e,c.d=null,null===c.b.d&&(c.c===c?F(c.a,null):(c.a.c=c.c,H(c,J(c))),(o=c.b).c===o?F(o.a,null):(o.a.c=o.c,H(o,J(o))),fa(c))}while(c!==r);r=l.d,(l=l.b).d=r,r.b=l}return this.r(this.b),void(this.c=this.b=null)}}this.b=this.c=null},Y.libtess={GluTesselator:X,windingRule:{GLU_TESS_WINDING_ODD:100130,GLU_TESS_WINDING_NONZERO:100131,GLU_TESS_WINDING_POSITIVE:100132,GLU_TESS_WINDING_NEGATIVE:100133,GLU_TESS_WINDING_ABS_GEQ_TWO:100134},primitiveType:{GL_LINE_LOOP:2,GL_TRIANGLES:4,GL_TRIANGLE_STRIP:5,GL_TRIANGLE_FAN:6},errorType:{GLU_TESS_MISSING_BEGIN_POLYGON:100151,GLU_TESS_MISSING_END_POLYGON:100153,GLU_TESS_MISSING_BEGIN_CONTOUR:100152,GLU_TESS_MISSING_END_CONTOUR:100154,GLU_TESS_COORD_TOO_LARGE:100155,GLU_TESS_NEED_COMBINE_CALLBACK:100156},gluEnum:{GLU_TESS_MESH:100112,GLU_TESS_TOLERANCE:100142,GLU_TESS_WINDING_RULE:100140,GLU_TESS_BOUNDARY_ONLY:100141,GLU_INVALID_ENUM:100900,GLU_INVALID_VALUE:100901,GLU_TESS_BEGIN:100100,GLU_TESS_VERTEX:100101,GLU_TESS_END:100102,GLU_TESS_ERROR:100103,GLU_TESS_EDGE_FLAG:100104,GLU_TESS_COMBINE:100105,GLU_TESS_BEGIN_DATA:100106,GLU_TESS_VERTEX_DATA:100107,GLU_TESS_END_DATA:100108,GLU_TESS_ERROR_DATA:100109,GLU_TESS_EDGE_FLAG_DATA:100110,GLU_TESS_COMBINE_DATA:100111}},X.prototype.gluDeleteTess=X.prototype.x,X.prototype.gluTessProperty=X.prototype.B,X.prototype.gluGetTessProperty=X.prototype.y,X.prototype.gluTessNormal=X.prototype.A,X.prototype.gluTessCallback=X.prototype.z,X.prototype.gluTessVertex=X.prototype.C,X.prototype.gluTessBeginPolygon=X.prototype.u,X.prototype.gluTessBeginContour=X.prototype.t,X.prototype.gluTessEndContour=X.prototype.v,X.prototype.gluTessEndPolygon=X.prototype.w,e.exports=Y.libtess}(q);var tt=q.exports;class Tessellator{process(e,n=!0,s=!1){if(0===e.length)return{triangles:{vertices:[],indices:[]},contours:[]};const r=e.filter(e=>e.points.length>=3);return 0===r.length?{triangles:{vertices:[],indices:[]},contours:[]}:(i.log(`Tessellator: removeOverlaps=${n}, processing ${r.length} paths`),this.tessellate(r,n,s))}tessellate(e,n,s){const r=s||n?e:e.map(e=>this.reverseWinding(e));let o=this.pathsToContours(r);if(n){i.log("Two-pass: boundary extraction then triangulation");const e=this.performTessellation(o,"boundary");if(!e)return i.warn("libtess returned empty result from boundary pass"),{triangles:{vertices:[],indices:[]},contours:[]};o=this.boundaryToContours(e),i.log(`Boundary pass created ${o.length} contours. Starting triangulation pass.`)}else i.log("Single-pass triangulation for "+(s?"CFF":"TTF"));const h=this.performTessellation(o,"triangles");if(!h){const e=n?"libtess returned empty result from triangulation pass":"libtess returned empty result from single-pass triangulation";return i.warn(e),{triangles:{vertices:[],indices:[]},contours:o}}return{triangles:{vertices:h.vertices,indices:h.indices||[]},contours:o}}pathsToContours(e){return e.map(e=>{const n=[];for(const i of e.points)n.push(i.x,i.y);return n})}performTessellation(e,n){const s=new tt.GluTesselator;s.gluTessProperty(tt.gluEnum.GLU_TESS_WINDING_RULE,tt.windingRule.GLU_TESS_WINDING_NONZERO);const r=[],o=[],h=[];let c=[];"boundary"===n&&s.gluTessProperty(tt.gluEnum.GLU_TESS_BOUNDARY_ONLY,!0),"triangles"===n?s.gluTessCallback(tt.gluEnum.GLU_TESS_VERTEX_DATA,e=>{o.push(e)}):(s.gluTessCallback(tt.gluEnum.GLU_TESS_BEGIN,()=>{c=[]}),s.gluTessCallback(tt.gluEnum.GLU_TESS_VERTEX_DATA,e=>{c.push(e)}),s.gluTessCallback(tt.gluEnum.GLU_TESS_END,()=>{c.length>0&&h.push([...c])})),s.gluTessCallback(tt.gluEnum.GLU_TESS_COMBINE,e=>{const n=r.length/2;return r.push(e[0],e[1]),n}),s.gluTessCallback(tt.gluEnum.GLU_TESS_ERROR,e=>{i.warn(`libtess error: ${e}`)}),s.gluTessNormal(0,0,1),s.gluTessBeginPolygon(null);for(const n of e){s.gluTessBeginContour();for(let e=0;e<n.length;e+=2){const i=r.length/2;r.push(n[e],n[e+1]),s.gluTessVertex([n[e],n[e+1],0],i)}s.gluTessEndContour()}return s.gluTessEndPolygon(),0===r.length?null:"triangles"===n?{vertices:r,indices:o}:{vertices:r,contourIndices:h}}boundaryToContours(e){if(!e.contourIndices)return[];const n=[];for(const i of e.contourIndices){const s=[];for(const n of i){const i=2*n;s.push(e.vertices[i],e.vertices[i+1])}s.length>2&&(s[0]===s[s.length-2]&&s[1]===s[s.length-1]||s.push(s[0],s[1])),n.push(s)}return n}reverseWinding(e){return{...e,points:[...e.points].reverse()}}}class Extruder{constructor(){}extrude(e,n=0,i){const s=[],r=[],o=[];if(0===n)this.addFlatFaces(e.triangles,s,r,o);else{this.addFrontAndBackFaces(e.triangles,s,r,o,n,i);for(const i of e.contours)this.addSideWalls(i,s,r,o,n)}return{vertices:s,normals:r,indices:o}}addFlatFaces(e,n,i,s){const r=n.length/3,o=e.vertices,h=e.indices;for(let e=0;e<o.length;e+=2)n.push(o[e],o[e+1],0),i.push(0,0,-1);for(let e=0;e<h.length;e++)s.push(r+h[e])}addFrontAndBackFaces(e,n,i,s,r,o){const h=n.length/3,c=e.vertices,l=e.indices;for(let e=0;e<c.length;e+=2)n.push(c[e],c[e+1],0),i.push(0,0,-1);const d=25e-6*o,f=r<=d?d:r;for(let e=0;e<c.length;e+=2)n.push(c[e],c[e+1],f),i.push(0,0,1);const p=c.length/2;for(let e=0;e<l.length;e++)s.push(h+l[e]);for(let e=l.length-1;e>=0;e--)s.push(h+l[e]+p)}addSideWalls(e,n,i,s,r){for(let o=0;o<e.length-2;o+=2){const h=e[o],c=e[o+1],l=e[o+2],d=e[o+3],f=new Vec2(l-h,d-c),p=new Vec2(f.y,-f.x).normalize(),g=n.length/3;n.push(h,c,0,l,d,0,h,c,r,l,d,r),i.push(p.x,p.y,0,p.x,p.y,0,p.x,p.y,0,p.x,p.y,0),s.push(g,g+1,g+2,g+1,g+3,g+2)}}}class BoundaryClusterer{constructor(){}cluster(e,n){return 0===e.length?[]:this.clusterSweepLine(e,n)}clusterSweepLine(e,n){const i=e.length;if(i<=1)return 0===i?[]:[[0]];const s=new Array(i),r=new Array(2*i);let o=0;for(let h=0;h<i;h++)s[h]=this.getWorldBounds(e[h],n[h]),r[o++]=[s[h].minX,0,h],r[o++]=[s[h].maxX,1,h];r.sort((e,n)=>e[0]-n[0]||e[1]-n[1]);const h=Array.from({length:i},(e,n)=>n),c=new Array(i).fill(0);function find(e){return h[e]===e?e:h[e]=find(h[e])}function union(e,n){const i=find(e),s=find(n);i!==s&&(c[i]<c[s]?h[i]=s:c[i]>c[s]?h[s]=i:(h[s]=i,c[i]++))}const l=new Set;for(const[,e,n]of r)if(0===e){const e=s[n];for(const i of l){const r=s[i];e.minY<r.maxY+.001&&e.maxY>r.minY-.001&&union(n,i)}l.add(n)}else l.delete(n);const d=new Map;for(let e=0;e<i;e++){const n=find(e);d.has(n)||d.set(n,[]),d.get(n).push(e)}return Array.from(d.values())}getWorldBounds(e,n){return{minX:e.bounds.min.x+n.x,minY:e.bounds.min.y+n.y,maxX:e.bounds.max.x+n.x,maxY:e.bounds.max.y+n.y}}}class MinHeap{constructor(e){this.heap=[],this.itemIndex=new Map,this.compare=e}insert(e){const n=this.itemIndex.get(e);if(void 0!==n)return this.siftUp(n),void this.siftDown(n);const i=this.heap.length;this.heap.push(e),this.itemIndex.set(e,i),this.siftUp(i)}extractMin(){const e=this.heap.length;if(!e)return;if(1===e){const e=this.heap.pop();return this.itemIndex.clear(),e}const n=this.heap[0],i=this.heap.pop();return this.heap[0]=i,this.itemIndex.delete(n),this.itemIndex.set(i,0),this.siftDown(0),n}update(e){const n=this.itemIndex.get(e);void 0!==n?(this.siftUp(n),this.siftDown(n)):this.insert(e)}isEmpty(){return!this.heap.length}swap(e,n){const i=this.heap[e],s=this.heap[n];this.heap[e]=s,this.heap[n]=i,this.itemIndex.set(i,n),this.itemIndex.set(s,e)}siftUp(e){const n=this.heap[e];for(;e>0;){const i=e-1>>1,s=this.heap[i];if(this.compare(n,s)>=0)break;this.heap[e]=s,this.itemIndex.set(s,e),e=i}this.heap[e]=n,this.itemIndex.set(n,e)}siftDown(e){const n=this.heap[e],i=this.heap.length,s=i>>1;for(;e<s;){const s=1+(e<<1),r=s+1;let o=e,h=n;const c=this.heap[s];if(this.compare(c,h)<0&&(o=s,h=c),r<i){const e=this.heap[r];this.compare(e,h)<0&&(o=r,h=e)}if(o===e)break;this.heap[e]=h,this.itemIndex.set(h,e),e=o}this.heap[e]=n,this.itemIndex.set(n,e)}}const et={enabled:!0,areaThreshold:1,colinearThreshold:.0087,minSegmentLength:10};class PathOptimizer{constructor(e){this.stats={pointsRemovedByVisvalingam:0,pointsRemovedByColinear:0,originalPointCount:0},this.config=e}setConfig(e){this.config=e}optimizePath(e){if(!this.config.enabled||e.points.length<=2)return e;this.stats.originalPointCount+=e.points.length;let n=[...e.points];return n.length<5?e:(n=this.simplifyPathVW(n,this.config.areaThreshold),n.length<3?e:(n=this.removeColinearPoints(n,this.config.colinearThreshold),n.length<3?e:{...e,points:n}))}simplifyPathVW(e,n){if(e.length<=3)return e;const i=e.length,s=e.map((e,n)=>({index:n,area:1/0,prev:null,next:null}));for(let e=0;e<s.length;e++)s[e].prev=s[e-1]||null,s[e].next=s[e+1]||null;const r=new MinHeap((e,n)=>e.area-n.area);for(let n=1;n<s.length-1;n++){const i=s[n];i.area=this.calculateTriangleArea(e[i.prev.index],e[i.index],e[i.next.index]),r.insert(i)}let o=i;for(;!r.isEmpty()&&o>3;){const i=r.extractMin();if(!i||i.area>n)break;if(this.config.minSegmentLength>0&&i.prev&&i.next){const n=e[i.prev.index],s=e[i.index],r=e[i.next.index],o=n.distanceTo(s),h=s.distanceTo(r);if(o<this.config.minSegmentLength||h<this.config.minSegmentLength)continue}i.prev&&(i.prev.next=i.next),i.next&&(i.next.prev=i.prev),o--,i.prev&&i.prev.prev&&(i.prev.area=this.calculateTriangleArea(e[i.prev.prev.index],e[i.prev.index],e[i.next.index]),r.update(i.prev)),i.next&&i.next.next&&(i.next.area=this.calculateTriangleArea(e[i.prev.index],e[i.next.index],e[i.next.next.index]),r.update(i.next))}const h=[];let c=s[0];for(;c;)h.push(e[c.index]),c=c.next;const l=i-h.length;return this.stats.pointsRemovedByVisvalingam+=l,h}removeColinearPoints(e,n){if(e.length<=2)return e;const i=[e[0]];for(let s=1;s<e.length-1;s++){const r=e[s-1],o=e[s],h=e[s+1],c=new Vec2(o.x-r.x,o.y-r.y),l=new Vec2(h.x-o.x,h.y-o.y),d=Math.abs(c.angle()-l.angle());Math.min(d,2*Math.PI-d)>n||c.length()<this.config.minSegmentLength||l.length()<this.config.minSegmentLength?i.push(o):this.stats.pointsRemovedByColinear++}return i.push(e[e.length-1]),i}calculateTriangleArea(e,n,i){return Math.abs((e.x*(n.y-i.y)+n.x*(i.y-e.y)+i.x*(e.y-n.y))/2)}getStats(){return{...this.stats}}resetStats(){this.stats={pointsRemovedByVisvalingam:0,pointsRemovedByColinear:0,originalPointCount:0}}}const nt={distanceTolerance:.5,angleTolerance:.2},it=1e-6;class Polygonizer{constructor(e){this.curveFidelityConfig={...nt,...e}}setCurveFidelityConfig(e){this.curveFidelityConfig={...nt,...e}}polygonizeQuadratic(e,n,i){const s=[];return this.recursiveQuadratic(e.x,e.y,n.x,n.y,i.x,i.y,s),this.addPoint(i.x,i.y,s),s}polygonizeCubic(e,n,i,s){const r=[];return this.recursiveCubic(e.x,e.y,n.x,n.y,i.x,i.y,s.x,s.y,r),this.addPoint(s.x,s.y,r),r}recursiveQuadratic(e,n,i,s,r,o,h,c=0){if(c>16)return;const l=(e+i)/2,d=(n+s)/2,f=(i+r)/2,p=(s+o)/2,g=(l+f)/2,y=(d+p)/2,b=r-e,m=o-n,_=Math.abs((i-r)*m-(s-o)*b),w=this.curveFidelityConfig.distanceTolerance??nt.distanceTolerance,O=w*w;if(_>it){if(_*_<=O*(b*b+m*m)){const c=this.curveFidelityConfig.angleTolerance??nt.angleTolerance;if(!(c>0))return void this.addPoint(i,s,h);{let l=Math.abs(Math.atan2(o-s,r-i)-Math.atan2(s-n,i-e));if(l>=Math.PI&&(l=2*Math.PI-l),l<c)return void this.addPoint(i,s,h)}}}else{const r=b*b+m*m;if(0===r){if((i-e)*(i-e)+(s-n)*(s-n)<=O)return void this.addPoint(i,s,h)}else{const o=((i-e)*b+(s-n)*m)/r;if(o>0&&o<1&&_*_<=O*r)return void this.addPoint(i,s,h)}}this.recursiveQuadratic(e,n,l,d,g,y,h,c+1),this.recursiveQuadratic(g,y,f,p,r,o,h,c+1)}recursiveCubic(e,n,i,s,r,o,h,c,l,d=0){if(d>16)return;const f=(e+i)/2,p=(n+s)/2,g=(i+r)/2,y=(s+o)/2,b=(r+h)/2,m=(o+c)/2,_=(f+g)/2,w=(p+y)/2,O=(g+b)/2,k=(y+m)/2,j=(_+O)/2,$=(w+k)/2,Y=h-e,q=c-n,tt=Math.abs((i-h)*q-(s-c)*Y),et=Math.abs((r-h)*q-(o-c)*Y),st=this.curveFidelityConfig.distanceTolerance??nt.distanceTolerance,rt=st*st;let at=0;switch(tt>it&&(at|=1),et>it&&(at|=2),at){case 0:const d=Y*Y+q*q;if(0===d){if((i-e)*(i-e)+(s-n)*(s-n)<=rt&&(r-e)*(r-e)+(o-n)*(o-n)<=rt)return this.addPoint(i,s,l),void this.addPoint(r,o,l)}else{const h=((i-e)*Y+(s-n)*q)/d,c=((r-e)*Y+(o-n)*q)/d;if(h>0&&h<1&&c>0&&c<1&&(tt+et)*(tt+et)<=rt*d)return this.addPoint(i,s,l),void this.addPoint(r,o,l)}break;case 1:if(et*et<=rt*(Y*Y+q*q)){const e=this.curveFidelityConfig.angleTolerance??nt.angleTolerance;if(!(e>0))return this.addPoint(i,s,l),void this.addPoint(r,o,l);{let n=Math.abs(Math.atan2(c-o,h-r)-Math.atan2(o-s,r-i));if(n>=Math.PI&&(n=2*Math.PI-n),n<e)return this.addPoint(i,s,l),void this.addPoint(r,o,l)}}break;case 2:if(tt*tt<=rt*(Y*Y+q*q)){const h=this.curveFidelityConfig.angleTolerance??nt.angleTolerance;if(!(h>0))return this.addPoint(i,s,l),void this.addPoint(r,o,l);{let c=Math.abs(Math.atan2(o-s,r-i)-Math.atan2(s-n,i-e));if(c>=Math.PI&&(c=2*Math.PI-c),c<h)return this.addPoint(i,s,l),void this.addPoint(r,o,l)}}break;case 3:if((tt+et)*(tt+et)<=rt*(Y*Y+q*q)){const d=this.curveFidelityConfig.angleTolerance??nt.angleTolerance;if(!(d>0))return this.addPoint(i,s,l),void this.addPoint(r,o,l);{let f=Math.abs(Math.atan2(o-s,r-i)-Math.atan2(s-n,i-e)),p=Math.abs(Math.atan2(c-o,h-r)-Math.atan2(o-s,r-i));if(f>=Math.PI&&(f=2*Math.PI-f),p>=Math.PI&&(p=2*Math.PI-p),f+p<d)return this.addPoint(i,s,l),void this.addPoint(r,o,l)}}}this.recursiveCubic(e,n,f,p,_,w,j,$,l,d+1),this.recursiveCubic(j,$,O,k,b,m,h,c,l,d+1)}addPoint(e,n,i){const s=new Vec2(e,n);if(0===i.length)return void i.push(s);const r=i[i.length-1],o=s.x-r.x,h=s.y-r.y;o*o+h*h>1e-12&&i.push(s)}}class GlyphContourCollector{constructor(e,n){this.currentGlyphId=0,this.currentTextIndex=0,this.currentGlyphPaths=[],this.currentPath=null,this.currentPoint=null,this.currentGlyphBounds={min:new Vec2(1/0,1/0),max:new Vec2(-1/0,-1/0)},this.collectedGlyphs=[],this.glyphPositions=[],this.glyphTextIndices=[],this.currentPosition=new Vec2(0,0),this.polygonizer=new Polygonizer(e),this.pathOptimizer=new PathOptimizer({...et,...n})}setPosition(e,n){this.currentPosition.set(e,n)}updatePosition(e,n){this.currentPosition.x+=e,this.currentPosition.y+=n}beginGlyph(e,n){this.currentGlyphPaths.length>0&&this.finishGlyph(),this.currentGlyphId=e,this.currentTextIndex=n,this.currentGlyphPaths=[],this.currentGlyphBounds.min.set(1/0,1/0),this.currentGlyphBounds.max.set(-1/0,-1/0),this.glyphPositions.push(this.currentPosition.clone())}finishGlyph(){this.currentPath&&this.finishPath(),this.currentGlyphPaths.length>0&&(this.collectedGlyphs.push({glyphId:this.currentGlyphId,paths:[...this.currentGlyphPaths],bounds:{min:{x:this.currentGlyphBounds.min.x,y:this.currentGlyphBounds.min.y},max:{x:this.currentGlyphBounds.max.x,y:this.currentGlyphBounds.max.y}}}),this.glyphTextIndices.push(this.currentTextIndex)),this.currentGlyphPaths=[]}onMoveTo(e,n){this.currentPath&&this.finishPath(),this.currentPoint=new Vec2(e,n),this.updateBounds(this.currentPoint),this.currentPath={points:[this.currentPoint],glyphIndex:this.currentGlyphId}}onLineTo(e,n){if(!this.currentPath||!this.currentPoint)return;const i=new Vec2(e,n);this.updateBounds(i),this.currentPath.points.push(i),this.currentPoint=i}onQuadTo(e,n,i,s){if(!this.currentPath||!this.currentPoint)return;const r=this.currentPoint,o=new Vec2(e,n),h=new Vec2(i,s),c=h.x-r.x,l=h.y-r.y;if(Math.abs((o.x-h.x)*l-(o.y-h.y)*c)<it)return void this.onLineTo(i,s);const d=this.polygonizer.polygonizeQuadratic(r,o,h);for(const e of d)this.updateBounds(e);for(let e=0;e<d.length;e++)this.currentPath.points.push(d[e]);this.currentPoint=h}onCubicTo(e,n,i,s,r,o){if(!this.currentPath||!this.currentPoint)return;const h=this.currentPoint,c=new Vec2(e,n),l=new Vec2(i,s),d=new Vec2(r,o),f=d.x-h.x,p=d.y-h.y,g=Math.abs((c.x-d.x)*p-(c.y-d.y)*f),y=Math.abs((l.x-d.x)*p-(l.y-d.y)*f);if(g<it&&y<it)return void this.onLineTo(r,o);const b=this.polygonizer.polygonizeCubic(h,c,l,d);for(const e of b)this.updateBounds(e);for(let e=0;e<b.length;e++)this.currentPath.points.push(b[e]);this.currentPoint=d}onClosePath(){if(!this.currentPath||!this.currentPoint)return;const e=this.currentPath.points[0];this.currentPoint.equals(e)||this.currentPath.points.push(e),this.finishPath()}finishPath(){if(this.currentPath){const e=this.pathOptimizer.optimizePath(this.currentPath);this.currentGlyphPaths.push(e),this.currentPath=null,this.currentPoint=null}}updateBounds(e){this.currentGlyphBounds.min.x=Math.min(this.currentGlyphBounds.min.x,e.x),this.currentGlyphBounds.min.y=Math.min(this.currentGlyphBounds.min.y,e.y),this.currentGlyphBounds.max.x=Math.max(this.currentGlyphBounds.max.x,e.x),this.currentGlyphBounds.max.y=Math.max(this.currentGlyphBounds.max.y,e.y)}getCollectedGlyphs(){return this.currentGlyphPaths.length>0&&this.finishGlyph(),this.collectedGlyphs}getGlyphPositions(){return this.glyphPositions}getTextIndices(){return this.glyphTextIndices}reset(){this.collectedGlyphs=[],this.glyphPositions=[],this.glyphTextIndices=[],this.currentGlyphPaths=[],this.currentPath=null,this.currentPoint=null,this.currentGlyphId=0,this.currentTextIndex=0,this.currentPosition.set(0,0),this.currentGlyphBounds={min:new Vec2(1/0,1/0),max:new Vec2(-1/0,-1/0)}}setCurveFidelityConfig(e){this.polygonizer.setCurveFidelityConfig(e)}setGeometryOptimization(e){this.pathOptimizer.setConfig({...et,...e})}getOptimizationStats(){return this.pathOptimizer.getStats()}}class DrawCallbackHandler{constructor(){this.moveTo_func=null,this.lineTo_func=null,this.quadTo_func=null,this.cubicTo_func=null,this.closePath_func=null,this.drawFuncsPtr=0,this.position={x:0,y:0}}setPosition(e,n){this.position.x=e,this.position.y=n,this.collector&&this.collector.setPosition(e,n)}updatePosition(e,n){this.position.x+=e,this.position.y+=n,this.collector&&this.collector.updatePosition(e,n)}createDrawFuncs(e,n){if(!e||!e.module||!e.hb)throw new Error("Invalid font object");if(this.collector=n,this.drawFuncsPtr)return;const i=e.module;this.moveTo_func=i.addFunction((e,n,i,s,r)=>{this.collector?.onMoveTo(s,r)},"viiiffi"),this.lineTo_func=i.addFunction((e,n,i,s,r)=>{this.collector?.onLineTo(s,r)},"viiiffi"),this.quadTo_func=i.addFunction((e,n,i,s,r,o,h)=>{this.collector?.onQuadTo(s,r,o,h)},"viiiffffi"),this.cubicTo_func=i.addFunction((e,n,i,s,r,o,h,c,l)=>{this.collector?.onCubicTo(s,r,o,h,c,l)},"viiiffffffi"),this.closePath_func=i.addFunction((e,n,i)=>{this.collector?.onClosePath()},"viiii"),this.drawFuncsPtr=i.exports.hb_draw_funcs_create(),i.exports.hb_draw_funcs_set_move_to_func(this.drawFuncsPtr,this.moveTo_func,0,0),i.exports.hb_draw_funcs_set_line_to_func(this.drawFuncsPtr,this.lineTo_func,0,0),i.exports.hb_draw_funcs_set_quadratic_to_func(this.drawFuncsPtr,this.quadTo_func,0,0),i.exports.hb_draw_funcs_set_cubic_to_func(this.drawFuncsPtr,this.cubicTo_func,0,0),i.exports.hb_draw_funcs_set_close_path_func(this.drawFuncsPtr,this.closePath_func,0,0)}getDrawFuncsPtr(){if(!this.drawFuncsPtr)throw new Error("Draw functions not initialized");return this.drawFuncsPtr}destroy(e){if(!e||!e.module||!e.hb)return;const n=e.module;try{this.drawFuncsPtr&&(n.exports.hb_draw_funcs_destroy(this.drawFuncsPtr),this.drawFuncsPtr=0),null!==this.moveTo_func&&(n.removeFunction(this.moveTo_func),this.moveTo_func=null),null!==this.lineTo_func&&(n.removeFunction(this.lineTo_func),this.lineTo_func=null),null!==this.quadTo_func&&(n.removeFunction(this.quadTo_func),this.quadTo_func=null),null!==this.cubicTo_func&&(n.removeFunction(this.cubicTo_func),this.cubicTo_func=null),null!==this.closePath_func&&(n.removeFunction(this.closePath_func),this.closePath_func=null)}catch(e){i.warn("Error destroying draw callbacks:",e)}this.collector=void 0}}class GlyphGeometryBuilder{constructor(e,n){this.fontId="default",this.wordCache=new Map,this.cache=e,this.loadedFont=n,this.tessellator=new Tessellator,this.extruder=new Extruder,this.clusterer=new BoundaryClusterer,this.collector=new GlyphContourCollector,this.drawCallbacks=new DrawCallbackHandler,this.drawCallbacks.createDrawFuncs(this.loadedFont,this.collector)}getOptimizationStats(){return this.collector.getOptimizationStats()}setCurveFidelityConfig(e){this.collector.setCurveFidelityConfig(e)}setGeometryOptimization(e){this.collector.setGeometryOptimization(e)}setFontId(e){this.fontId=e}buildInstancedGeometry(e,n,i,r,o=!1){s.start("GlyphGeometryBuilder.buildInstancedGeometry",{lineCount:e.length,wordCount:e.flat().length,depth:n,removeOverlaps:i});const h=[],c=[],l=[],d=[],f={min:{x:1/0,y:1/0,z:0},max:{x:-1/0,y:-1/0,z:n}};for(let s=0;s<e.length;s++){const p=e[s];for(const e of p){const s=[];for(const n of e.glyphs)s.push(this.getContoursForGlyph(n.g));const p=e.glyphs.map(e=>new Vec3(e.x,e.y,0)),g=this.clusterer.cluster(s,p);if(!o&&g.some(e=>e.length>1)){const o=`${this.fontId}_${e.text}_${n}_${i}`;let p=this.wordCache.get(o);if(!p){const i=[];for(let n=0;n<s.length;n++){const r=s[n],o=e.glyphs[n];for(const e of r.paths)i.push({...e,points:e.points.map(e=>new Vec2(e.x+(o.x??0),e.y+(o.y??0)))})}p=this.tessellateGlyphCluster(i,n,r),this.wordCache.set(o,p)}const g=h.length/3;this.appendGeometry(h,c,l,p,e.position,g);const y=p.vertices.length/3;for(let i=0;i<e.glyphs.length;i++){const r=e.glyphs[i],o=s[i],h=new Vec3(e.position.x+(r.x??0),e.position.y+(r.y??0),e.position.z),c=this.createGlyphInfo(r,g,y,h,o,n);d.push(c),this.updatePlaneBounds(c.bounds,f)}}else for(let o=0;o<e.glyphs.length;o++){const p=e.glyphs[o],g=s[o],y=new Vec3(e.position.x+(p.x??0),e.position.y+(p.y??0),e.position.z);if(0===g.paths.length){const e=this.createGlyphInfo(p,0,0,y,g,n);d.push(e);continue}let b=this.cache.get(this.fontId,p.g,n,i);b||(b=this.tessellateGlyph(g,n,i,r),this.cache.set(this.fontId,p.g,n,i,b));const m=h.length/3;this.appendGeometry(h,c,l,b,y,m);const _=this.createGlyphInfo(p,m,b.vertices.length/3,y,g,n);d.push(_),this.updatePlaneBounds(_.bounds,f)}}}const p=new Float32Array(h),g=new Float32Array(c),y=new Uint32Array(l);return s.end("GlyphGeometryBuilder.buildInstancedGeometry"),{vertices:p,normals:g,indices:y,glyphInfos:d,planeBounds:f}}appendGeometry(e,n,i,s,r,o){for(let n=0;n<s.vertices.length;n+=3)e.push(s.vertices[n]+r.x,s.vertices[n+1]+r.y,s.vertices[n+2]+r.z);for(let e=0;e<s.normals.length;e++)n.push(s.normals[e]);for(let e=0;e<s.indices.length;e++)i.push(s.indices[e]+o)}createGlyphInfo(e,n,i,s,r,o){return{textIndex:e.absoluteTextIndex,lineIndex:e.lineIndex,vertexStart:n,vertexCount:i,bounds:{min:{x:r.bounds.min.x+s.x,y:r.bounds.min.y+s.y,z:s.z},max:{x:r.bounds.max.x+s.x,y:r.bounds.max.y+s.y,z:s.z+o}}}}getContoursForGlyph(e){this.collector.reset(),this.collector.beginGlyph(e,0),this.loadedFont.module.exports.hb_font_draw_glyph(this.loadedFont.font.ptr,e,this.drawCallbacks.getDrawFuncsPtr(),0),this.collector.finishGlyph();const n=this.collector.getCollectedGlyphs()[0];return n||{glyphId:e,paths:[],bounds:{min:{x:0,y:0},max:{x:0,y:0}}}}tessellateGlyphCluster(e,n,i){const s=this.tessellator.process(e,!0,i);return this.extrudeAndPackage(s,n)}extrudeAndPackage(e,n){const i=this.extruder.extrude(e,n,this.loadedFont.upem),s=i.vertices;let r=1/0,o=1/0,h=1/0,c=-1/0,l=-1/0,d=-1/0;for(let e=0;e<s.length;e+=3){const n=s[e],i=s[e+1],f=s[e+2];n<r&&(r=n),n>c&&(c=n),i<o&&(o=i),i>l&&(l=i),f<h&&(h=f),f>d&&(d=f)}const f=new Vec3(r,o,h),p=new Vec3(c,l,d),g=i.vertices.length/3<65536?Uint16Array:Uint32Array;return{geometry:e,vertices:new Float32Array(i.vertices),normals:new Float32Array(i.normals),indices:new g(i.indices),bounds:{min:f,max:p},useCount:1}}tessellateGlyph(e,n,i,r){s.start("GlyphGeometryBuilder.tessellateGlyph",{glyphId:e.glyphId,pathCount:e.paths.length});const o=this.tessellator.process(e.paths,i,r);return this.extrudeAndPackage(o,n)}updatePlaneBounds(e,n){const i=new Box3(new Vec3(n.min.x,n.min.y,n.min.z),new Vec3(n.max.x,n.max.y,n.max.z)),s=new Box3(new Vec3(e.min.x,e.min.y,e.min.z),new Vec3(e.max.x,e.max.y,e.max.z));i.union(s),n.min.x=i.min.x,n.min.y=i.min.y,n.min.z=i.min.z,n.max.x=i.max.x,n.max.y=i.max.y,n.max.z=i.max.z}getCacheStats(){return this.cache.getStats()}clearCache(){this.cache.clear(),this.wordCache.clear()}}class TextShaper{constructor(e,n){this.cachedSpaceWidth=new Map,this.loadedFont=e,this.geometryBuilder=n}shapeLines(e,n,i,r,o,h,c){s.start("TextShaper.shapeLines",{lineCount:e.length});const l=new Set;if(h&&"object"==typeof h&&"byText"in h&&h.byText&&c)for(const e of Object.keys(h.byText)){let n=0;for(;-1!==(n=c.indexOf(e,n));)l.add(n),l.add(n+e.length),n+=e.length}const d=[];return e.forEach((e,s)=>{const h=this.shapeLineIntoClusters(e,s,n,i,r,o,l);d.push(h)}),d}shapeLineIntoClusters(e,n,i,s,r,o,h){const c=this.loadedFont.hb.createBuffer();"rtl"===o&&c.setDirection("rtl"),c.addText(e.text),c.guessSegmentProperties(),this.loadedFont.hb.shape(this.loadedFont.font,c);const l=c.json(this.loadedFont.font);c.destroy();const d=[];let f=[],p="",g=new Vec3,y=new Vec3(e.xOffset,-n*i,0);const b=s*this.loadedFont.upem,m=this.calculateSpaceAdjustment(e,r,s);for(let i=0;i<l.length;i++){const s=l[i],r=/\s/.test(e.text[s.cl]);e.endedWithHyphen&&s.cl===e.text.length-1&&"-"===e.text[s.cl]?s.absoluteTextIndex=e.originalEnd:s.absoluteTextIndex=e.originalStart+s.cl,s.lineIndex=n;const o=h.has(s.absoluteTextIndex);(r||o)&&f.length>0&&(d.push({text:p,glyphs:f,position:g.clone()}),f=[],p="");const c=y.clone().add(new Vec3(s.dx,s.dy,0));r||(0===f.length&&g.copy(c),s.x=c.x-g.x,s.y=c.y-g.y,f.push(s),p+=e.text[s.cl]),y.x+=s.ax,y.y+=s.ay,0!==b&&i<l.length-1&&(y.x+=b),r&&(y.x+=m)}return f.length>0&&d.push({text:p,glyphs:f,position:g.clone()}),d}calculateSpaceAdjustment(e,n,i){let s=0;if(void 0!==e.adjustmentRatio&&"justify"===n&&!e.isLastLine){let n=this.cachedSpaceWidth.get(i);void 0===n&&(n=TextMeasurer.measureTextWidth(this.loadedFont," ",i),this.cachedSpaceWidth.set(i,n));const r=n,o=.5,h=c;e.adjustmentRatio>0?s=e.adjustmentRatio*r*o:e.adjustmentRatio<0&&(s=e.adjustmentRatio*r*h)}return s}clearCache(){this.geometryBuilder.clearCache()}getCacheStats(){return this.geometryBuilder.getCacheStats()}}class GlyphCache{constructor(e){this.cache=new Map,this.head=null,this.tail=null,this.stats={hits:0,misses:0,totalGlyphs:0,uniqueGlyphs:0,cacheSize:0,saved:0,memoryUsage:0},e&&(this.maxCacheSize=1024*e*1024)}getCacheKey(e,n,i,s){return`${e}_${n}_${Math.round(1e3*i)/1e3}_${s}`}has(e,n,i,s){const r=this.getCacheKey(e,n,i,s);return this.cache.has(r)}get(e,n,i,s){const r=this.getCacheKey(e,n,i,s),o=this.cache.get(r);return o?(this.stats.hits++,this.stats.saved++,o.data.useCount++,this.moveToHead(o),this.stats.totalGlyphs++,o.data):(this.stats.misses++,void this.stats.totalGlyphs++)}set(e,n,i,s,r){const o=this.getCacheKey(e,n,i,s),h=this.calculateMemoryUsage(r);this.maxCacheSize&&this.stats.memoryUsage+h>this.maxCacheSize&&this.evictLRU(h);const c={key:o,data:r,prev:null,next:null};this.cache.set(o,c),this.addToHead(c),this.stats.uniqueGlyphs=this.cache.size,this.stats.cacheSize++,this.stats.memoryUsage+=h}calculateMemoryUsage(e){let n=0;return n+=4*e.vertices.length,n+=4*e.normals.length,n+=e.indices.length*e.indices.BYTES_PER_ELEMENT,n+=24,n+=256,n}evictLRU(e){let n=0;for(;this.tail&&n<e;){const e=this.calculateMemoryUsage(this.tail.data),i=this.tail;this.removeTail(),this.cache.delete(i.key),this.stats.memoryUsage-=e,this.stats.cacheSize--,n+=e}}addToHead(e){this.head?(e.next=this.head,this.head.prev=e,this.head=e):this.head=this.tail=e}removeNode(e){e.prev?e.prev.next=e.next:this.head=e.next,e.next?e.next.prev=e.prev:this.tail=e.prev}removeTail(){this.tail&&this.removeNode(this.tail)}moveToHead(e){e!==this.head&&(this.removeNode(e),this.addToHead(e))}clear(){this.cache.clear(),this.head=null,this.tail=null,this.stats={hits:0,misses:0,totalGlyphs:0,uniqueGlyphs:0,cacheSize:0,saved:0,memoryUsage:0}}getStats(){const e=this.stats.totalGlyphs>0?this.stats.hits/this.stats.totalGlyphs*100:0;return this.stats.uniqueGlyphs=this.cache.size,{...this.stats,hitRate:e,memoryUsageMB:this.stats.memoryUsage/1048576}}}const st=new GlyphCache(250);var rt={exports:{}};var at=getAugmentedNamespace({__proto__:null,default:{},readFileSync:()=>{throw new Error("fs not available in browser")}});!function(e){var n,i=(n="undefined"!=typeof document?document.currentScript?.src:void 0,async function(e={}){var i=e,s="object"==typeof window,r="undefined"!=typeof WorkerGlobalScope,o="object"==typeof process&&process.versions?.node&&"renderer"!=process.type,quit_=(e,n)=>{throw n};"undefined"!=typeof __filename?n=__filename:r&&(n=self.location.href);var h,c,l="";if(o){var d=at;l=__dirname+"/",c=e=>(e=isFileURI(e)?new URL(e):e,d.readFileSync(e)),h=async(e,n=!0)=>(e=isFileURI(e)?new URL(e):e,d.readFileSync(e,n?void 0:"utf8")),process.argv.length>1&&process.argv[1].replace(/\\/g,"/"),process.argv.slice(2),quit_=(e,n)=>{throw process.exitCode=e,n}}else if(s||r){try{l=new URL(".",n).href}catch{}r&&(c=e=>{var n=new XMLHttpRequest;return n.open("GET",e,!1),n.responseType="arraybuffer",n.send(null),new Uint8Array(n.response)}),h=async e=>{if(isFileURI(e))return new Promise((n,i)=>{var s=new XMLHttpRequest;s.open("GET",e,!0),s.responseType="arraybuffer",s.onload=()=>{200==s.status||0==s.status&&s.response?n(s.response):i(s.status)},s.onerror=i,s.send(null)});var n=await fetch(e,{credentials:"same-origin"});if(n.ok)return n.arrayBuffer();throw new Error(n.status+" : "+n.url)}}console.log.bind(console);var f,p,g,y,b,m,_=console.error.bind(console),w=!1,isFileURI=e=>e.startsWith("file://"),O=!1;function updateMemoryViews(){var e=b.buffer;i.HEAP8=new Int8Array(e),i.HEAPU8=m=new Uint8Array(e),i.HEAP32=new Int32Array(e),i.HEAPU32=new Uint32Array(e),i.HEAPF32=new Float32Array(e),new BigInt64Array(e),new BigUint64Array(e)}var k,j=0,$=null;function abort(e){i.onAbort?.(e),_(e="Aborted("+e+")"),w=!0,e+=". Build with -sASSERTIONS for more info.";var n=new WebAssembly.RuntimeError(e);throw y?.(n),n}function findWasmBinary(){return e="hb.wasm",i.locateFile?i.locateFile(e,l):l+e;var e}async function getWasmBinary(e){if(!f)try{var n=await h(e);return new Uint8Array(n)}catch{}return function(e){if(e==k&&f)return new Uint8Array(f);if(c)return c(e);throw"both async and sync fetching of the wasm failed"}(e)}async function instantiateAsync(e,n,i){if(!e&&!isFileURI(n)&&!o)try{var s=fetch(n,{credentials:"same-origin"});return await WebAssembly.instantiateStreaming(s,i)}catch(e){_(`wasm streaming compile failed: ${e}`),_("falling back to ArrayBuffer instantiation")}return async function(e,n){try{var i=await getWasmBinary(e);return await WebAssembly.instantiate(i,n)}catch(e){_(`failed to asynchronously prepare wasm: ${e}`),abort(e)}}(n,i)}class ExitStatus{name="ExitStatus";constructor(e){this.message=`Program terminated with exit(${e})`,this.status=e}}var Y,q,tt,callRuntimeCallbacks=e=>{for(;e.length>0;)e.shift()(i)},et=[],addOnPostRun=e=>et.push(e),nt=[],addOnPreRun=e=>nt.push(e),it=!0,st=0,rt={},handleException=e=>{if(e instanceof ExitStatus||"unwind"==e)return p;quit_(1,e)},keepRuntimeAlive=()=>it||st>0,_proc_exit=e=>{p=e,keepRuntimeAlive()||(i.onExit?.(e),w=!0),quit_(e,new ExitStatus(e))},_exit=(e,n)=>{p=e,_proc_exit(e)},callUserCallback=e=>{if(!w)try{e(),(()=>{if(!keepRuntimeAlive())try{_exit(p)}catch(e){handleException(e)}})()}catch(e){handleException(e)}},alignMemory=(e,n)=>Math.ceil(e/n)*n,growMemory=e=>{var n=(e-b.buffer.byteLength+65535)/65536|0;try{return b.grow(n),updateMemoryViews(),1}catch(e){}},uleb128EncodeWithLen=e=>{const n=e.length;return[n%128|128,n>>7,...e]},ot={i:127,p:127,j:126,f:125,d:124,e:111},generateTypePack=e=>uleb128EncodeWithLen(Array.from(e,e=>ot[e])),getWasmTableEntry=e=>Y.get(e),getFunctionAddress=e=>(q||(q=new WeakMap,((e,n)=>{if(q)for(var i=e;i<e+n;i++){var s=getWasmTableEntry(i);s&&q.set(s,i)}})(0,Y.length)),q.get(e)||0),ht=[],setWasmTableEntry=(e,n)=>Y.set(e,n);i.noExitRuntime&&(it=i.noExitRuntime),i.print&&i.print,i.printErr&&(_=i.printErr),i.wasmBinary&&(f=i.wasmBinary),i.arguments&&i.arguments,i.thisProgram&&i.thisProgram,i.wasmMemory=b,i.wasmExports=lt,i.addFunction=(e,n)=>{var i=getFunctionAddress(e);if(i)return i;var s=ht.length?ht.pop():Y.grow(1);try{setWasmTableEntry(s,e)}catch(i){if(!(i instanceof TypeError))throw i;var r=((e,n)=>{var i=Uint8Array.of(0,97,115,109,1,0,0,0,1,...uleb128EncodeWithLen([1,96,...generateTypePack(n.slice(1)),...generateTypePack("v"===n[0]?"":n[0])]),2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0),s=new WebAssembly.Module(i);return new WebAssembly.Instance(s,{e:{f:e}}).exports.f})(e,n);setWasmTableEntry(s,r)}return q.set(e,s),s},i.removeFunction=e=>{q.delete(getWasmTableEntry(e)),setWasmTableEntry(e,null),ht.push(e)};var ct={_abort_js:()=>abort(""),_emscripten_runtime_keepalive_clear:()=>{it=!1,st=0},_setitimer_js:(e,n)=>{if(rt[e]&&(clearTimeout(rt[e].id),delete rt[e]),!n)return 0;var i=setTimeout(()=>{delete rt[e],callUserCallback(()=>tt(e,performance.now()))},n);return rt[e]={id:i,timeout_ms:n},0},emscripten_resize_heap:e=>{var n=m.length,i=2147483648;if((e>>>=0)>i)return!1;for(var s=1;s<=4;s*=2){var r=n*(1+.2/s);r=Math.min(r,e+100663296);var o=Math.min(i,alignMemory(Math.max(e,r),65536));if(growMemory(o))return!0}return!1},proc_exit:_proc_exit},lt=await async function(){function receiveInstance(e,n){return lt=e.exports,i.wasmExports=lt,b=lt.memory,i.wasmMemory=b,updateMemoryViews(),Y=lt.__indirect_function_table,function(e){i._hb_blob_create=e.hb_blob_create,i._hb_blob_destroy=e.hb_blob_destroy,i._hb_blob_get_length=e.hb_blob_get_length,i._hb_blob_get_data=e.hb_blob_get_data,i._hb_buffer_serialize_glyphs=e.hb_buffer_serialize_glyphs,i._hb_buffer_create=e.hb_buffer_create,i._hb_buffer_destroy=e.hb_buffer_destroy,i._hb_buffer_get_content_type=e.hb_buffer_get_content_type,i._hb_buffer_set_direction=e.hb_buffer_set_direction,i._hb_buffer_set_script=e.hb_buffer_set_script,i._hb_buffer_set_language=e.hb_buffer_set_language,i._hb_buffer_set_flags=e.hb_buffer_set_flags,i._hb_buffer_set_cluster_level=e.hb_buffer_set_cluster_level,i._hb_buffer_get_length=e.hb_buffer_get_length,i._hb_buffer_get_glyph_infos=e.hb_buffer_get_glyph_infos,i._hb_buffer_get_glyph_positions=e.hb_buffer_get_glyph_positions,i._hb_glyph_info_get_glyph_flags=e.hb_glyph_info_get_glyph_flags,i._hb_buffer_guess_segment_properties=e.hb_buffer_guess_segment_properties,i._hb_buffer_add_utf8=e.hb_buffer_add_utf8,i._hb_buffer_add_utf16=e.hb_buffer_add_utf16,i._hb_buffer_set_message_func=e.hb_buffer_set_message_func,i._hb_language_from_string=e.hb_language_from_string,i._hb_script_from_string=e.hb_script_from_string,i._hb_version=e.hb_version,i._hb_version_string=e.hb_version_string,i._hb_feature_from_string=e.hb_feature_from_string,i._malloc=e.malloc,i._free=e.free,i._hb_draw_funcs_set_move_to_func=e.hb_draw_funcs_set_move_to_func,i._hb_draw_funcs_set_line_to_func=e.hb_draw_funcs_set_line_to_func,i._hb_draw_funcs_set_quadratic_to_func=e.hb_draw_funcs_set_quadratic_to_func,i._hb_draw_funcs_set_cubic_to_func=e.hb_draw_funcs_set_cubic_to_func,i._hb_draw_funcs_set_close_path_func=e.hb_draw_funcs_set_close_path_func,i._hb_draw_funcs_create=e.hb_draw_funcs_create,i._hb_draw_funcs_destroy=e.hb_draw_funcs_destroy,i._hb_face_create=e.hb_face_create,i._hb_face_destroy=e.hb_face_destroy,i._hb_face_reference_table=e.hb_face_reference_table,i._hb_face_get_upem=e.hb_face_get_upem,i._hb_face_collect_unicodes=e.hb_face_collect_unicodes,i._hb_font_draw_glyph=e.hb_font_draw_glyph,i._hb_font_glyph_to_string=e.hb_font_glyph_to_string,i._hb_font_create=e.hb_font_create,i._hb_font_set_variations=e.hb_font_set_variations,i._hb_font_destroy=e.hb_font_destroy,i._hb_font_set_scale=e.hb_font_set_scale,i._hb_set_create=e.hb_set_create,i._hb_set_destroy=e.hb_set_destroy,i._hb_ot_var_get_axis_infos=e.hb_ot_var_get_axis_infos,i._hb_set_get_population=e.hb_set_get_population,i._hb_set_next_many=e.hb_set_next_many,i._hb_shape=e.hb_shape,tt=e._emscripten_timeout}(lt),function(){if(j--,i.monitorRunDependencies?.(j),0==j&&$){var e=$;$=null,e()}}(),lt}j++,i.monitorRunDependencies?.(j);var e={env:ct,wasi_snapshot_preview1:ct};if(i.instantiateWasm)return new Promise((n,s)=>{i.instantiateWasm(e,(e,i)=>{n(receiveInstance(e))})});k??=findWasmBinary();var n=function(e){return receiveInstance(e.instance)}(await instantiateAsync(f,k,e));return n}();return function(){if(i.preInit)for("function"==typeof i.preInit&&(i.preInit=[i.preInit]);i.preInit.length>0;)i.preInit.shift()()}(),function run(){function doRun(){i.calledRun=!0,w||(O=!0,lt.__wasm_call_ctors(),g?.(i),i.onRuntimeInitialized?.(),function(){if(i.postRun)for("function"==typeof i.postRun&&(i.postRun=[i.postRun]);i.postRun.length;)addOnPostRun(i.postRun.shift());callRuntimeCallbacks(et)}())}j>0?$=run:(function(){if(i.preRun)for("function"==typeof i.preRun&&(i.preRun=[i.preRun]);i.preRun.length;)addOnPreRun(i.preRun.shift());callRuntimeCallbacks(nt)}(),j>0?$=run:i.setStatus?(i.setStatus("Running..."),setTimeout(()=>{setTimeout(()=>i.setStatus(""),1),doRun()},1)):doRun())}(),O?i:new Promise((e,n)=>{g=e,y=n})});e.exports=i,e.exports.default=i}(rt);var ot=getDefaultExportFromCjs(rt.exports),ht={exports:{}};try{ht.exports=function(e){var n=e.wasmExports,i=new TextDecoder("utf8");let s=e.addFunction,r=e.removeFunction;var o=s(function(e){n.free(e)},"vi");function hb_tag(e){return(255&e.charCodeAt(0))<<24|(255&e.charCodeAt(1))<<16|(255&e.charCodeAt(2))<<8|255&e.charCodeAt(3)}var h=hb_tag("JSON"),c="",l=n.malloc(256);function createAsciiString(i){var s=n.malloc(i.length+1);for(let n=0;n<i.length;++n){const r=i.charCodeAt(n);if(r>127)throw new Error("Expected ASCII text");e.HEAPU8[s+n]=r}return e.HEAPU8[s+i.length]=0,{ptr:s,length:i.length,free:function(){n.free(s)}}}function shape(e,i,s){var r=0,o=0;s&&(s=s.split(","),r=n.malloc(16*s.length),s.forEach(function(e,i){var s=createAsciiString(e);n.hb_feature_from_string(s.ptr,-1,r+16*o)&&o++,s.free()})),n.hb_shape(e.ptr,i.ptr,r,o),r&&n.free(r)}return{createBlob:function(i){var s=n.malloc(i.byteLength);e.HEAPU8.set(new Uint8Array(i),s);var r=n.hb_blob_create(s,i.byteLength,2,s,o);return{ptr:r,destroy:function(){n.hb_blob_destroy(r)}}},createFace:function(i,s){var r=n.hb_face_create(i.ptr,s);const o=n.hb_face_get_upem(r);return{ptr:r,upem:o,reference_table:function(i){var s=n.hb_face_reference_table(r,hb_tag(i)),o=n.hb_blob_get_length(s);if(o){var h=n.hb_blob_get_data(s,null);return e.HEAPU8.subarray(h,h+o)}},getAxisInfos:function(){var i=n.malloc(2048),s=n.malloc(4);e.HEAPU32[s/4]=64,n.hb_ot_var_get_axis_infos(r,0,s,i);var o={};return Array.from({length:e.HEAPU32[s/4]}).forEach(function(n,s){var r;o[(r=e.HEAPU32[i/4+8*s+1],[String.fromCharCode(r>>24&255),String.fromCharCode(r>>16&255),String.fromCharCode(r>>8&255),String.fromCharCode(255&r)].join(""))]={min:e.HEAPF32[i/4+8*s+4],default:e.HEAPF32[i/4+8*s+5],max:e.HEAPF32[i/4+8*s+6]}}),n.free(s),n.free(i),o},collectUnicodes:function(){var i=n.hb_set_create();n.hb_face_collect_unicodes(r,i);var s=function(i){const s=n.hb_set_get_population(i),r=n.malloc(s<<2),o=r>>2,h=e.HEAPU32.subarray(o,o+s);return e.HEAPU32.set(h,o),n.hb_set_next_many(i,-1,r,s),h}(i);return n.hb_set_destroy(i),s},destroy:function(){n.hb_face_destroy(r)}}},createFont:function(o){var h=n.hb_font_create(o.ptr),d=null,f=null,p=null,g=null,y=null,b=null;function glyphToPath(e){return d||(f=s(function(e,n,i,s,r,o){c+=`M${s},${r}`},"viiiffi"),p=s(function(e,n,i,s,r,o){c+=`L${s},${r}`},"viiiffi"),g=s(function(e,n,i,s,r,o,h,l,d,f){c+=`C${s},${r} ${o},${h} ${l},${d}`},"viiiffffffi"),y=s(function(e,n,i,s,r,o,h,l){c+=`Q${s},${r} ${o},${h}`},"viiiffffi"),b=s(function(e,n,i,s){c+="Z"},"viiii"),d=n.hb_draw_funcs_create(),n.hb_draw_funcs_set_move_to_func(d,f,0,0),n.hb_draw_funcs_set_line_to_func(d,p,0,0),n.hb_draw_funcs_set_cubic_to_func(d,g,0,0),n.hb_draw_funcs_set_quadratic_to_func(d,y,0,0),n.hb_draw_funcs_set_close_path_func(d,b,0,0)),c="",n.hb_font_draw_glyph(h,e,d,0),c}return{ptr:h,glyphName:function(s){n.hb_font_glyph_to_string(h,s,l,256);var r=e.HEAPU8.subarray(l,l+256);return i.decode(r.slice(0,r.indexOf(0)))},glyphToPath:glyphToPath,glyphToJson:function(e){return glyphToPath(e).replace(/([MLQCZ])/g,"|$1 ").split("|").filter(function(e){return e.length}).map(function(e){var n=e.split(/[ ,]/g);return{type:n[0],values:n.slice(1).filter(function(e){return e.length}).map(function(e){return+e})}})},setScale:function(e,i){n.hb_font_set_scale(h,e,i)},setVariations:function(i){var s=Object.entries(i),r=n.malloc(8*s.length);s.forEach(function(n,i){e.HEAPU32[r/4+2*i+0]=hb_tag(n[0]),e.HEAPF32[r/4+2*i+1]=n[1]}),n.hb_font_set_variations(h,r,s.length),n.free(r)},destroy:function(){n.hb_font_destroy(h),d&&(n.hb_draw_funcs_destroy(d),d=null,r(f),r(p),r(g),r(y),r(b))}}},createBuffer:function(){var i=n.hb_buffer_create();return{ptr:i,addText:function(s){const r=function(i){const s=n.malloc(2*i.length),r=new Uint16Array(e.wasmMemory.buffer,s,i.length);for(let e=0;e<r.length;++e)r[e]=i.charCodeAt(e);return{ptr:s,length:r.length,free:function(){n.free(s)}}}(s);n.hb_buffer_add_utf16(i,r.ptr,r.length,0,r.length),r.free()},guessSegmentProperties:function(){return n.hb_buffer_guess_segment_properties(i)},setDirection:function(e){n.hb_buffer_set_direction(i,{ltr:4,rtl:5,ttb:6,btt:7}[e]||0)},setFlags:function(e){var s=0;e.forEach(function(e){s|=function(e){return"BOT"==e?1:"EOT"==e?2:"PRESERVE_DEFAULT_IGNORABLES"==e?4:"REMOVE_DEFAULT_IGNORABLES"==e?8:"DO_NOT_INSERT_DOTTED_CIRCLE"==e?16:"PRODUCE_UNSAFE_TO_CONCAT"==e?64:0}(e)}),n.hb_buffer_set_flags(i,s)},setLanguage:function(e){var s=createAsciiString(e);n.hb_buffer_set_language(i,n.hb_language_from_string(s.ptr,-1)),s.free()},setScript:function(e){var s=createAsciiString(e);n.hb_buffer_set_script(i,n.hb_script_from_string(s.ptr,-1)),s.free()},setClusterLevel:function(e){n.hb_buffer_set_cluster_level(i,e)},json:function(){for(var s=n.hb_buffer_get_length(i),r=[],o=n.hb_buffer_get_glyph_infos(i,0),h=o/4,c=n.hb_buffer_get_glyph_positions(i,0)/4,l=e.HEAPU32.subarray(h,h+5*s),d=e.HEAP32.subarray(c,c+5*s),f=0;f<s;++f)r.push({g:l[5*f+0],cl:l[5*f+2],ax:d[5*f+0],ay:d[5*f+1],dx:d[5*f+2],dy:d[5*f+3],flags:n.hb_glyph_info_get_glyph_flags(o+20*f)});return r},destroy:function(){n.hb_buffer_destroy(i)}}},shape:shape,shapeWithTrace:function(o,c,l,d,f){var p=[],g=0,y=!1,b=1048576,m=n.malloc(b),_=s(function(s,r,o,c){var l=i.decode(e.HEAPU8.subarray(o,e.HEAPU8.indexOf(0,o)));return l.startsWith("start table GSUB")?g=1:l.startsWith("start table GPOS")&&(g=2),g!=f&&(y=!1),0!=f&&g==f&&l.startsWith("end lookup "+d)&&(y=!0),y?0:(n.hb_buffer_serialize_glyphs(s,0,n.hb_buffer_get_length(s),m,b,0,r,h,4),p.push({m:l,t:JSON.parse(i.decode(e.HEAPU8.subarray(m,e.HEAPU8.indexOf(0,m)))),glyphs:2==n.hb_buffer_get_content_type(s)}),1)},"iiiii");return n.hb_buffer_set_message_func(c.ptr,_,0,0),shape(o,c,l),n.free(m),r(_),p},version:function(){var i=n.malloc(12);n.hb_version(i,i+4,i+8);var s={major:e.HEAPU32[i/4],minor:e.HEAPU32[(i+4)/4],micro:e.HEAPU32[(i+8)/4]};return n.free(i),s},version_string:function(){var s=n.hb_version_string();return i.decode(e.HEAPU8.subarray(s,e.HEAPU8.indexOf(0,s)))}}}}catch(e){}var ct=getDefaultExportFromCjs(ht.exports);let lt=null,ut=null,dt=null;const ft={setWasmPath(e){ut=e,dt=null,lt=null},setWasmBuffer(e){dt=e,ut=null,lt=null},getHarfBuzz:async()=>lt||(lt=new Promise(async(e,n)=>{try{const n={};if(dt)n.wasmBinary=dt;else{if(!ut)throw new Error("HarfBuzz WASM path or buffer must be set before initialization.");n.locateFile=(e,n)=>e.endsWith(".wasm")?ut:n+e}const i=await ot(n),s=ct(i);e({hb:s,module:{addFunction:i.addFunction,exports:i.wasmExports,removeFunction:i.removeFunction}})}catch(e){n(new Error(`Failed to initialize HarfBuzz: ${e}`))}}),lt)};class TextRangeQuery{constructor(e,n){this.text=e,this.glyphsByTextIndex=new Map,n.forEach(e=>{const n=this.glyphsByTextIndex.get(e.textIndex)||[];n.push(e),this.glyphsByTextIndex.set(e.textIndex,n)})}execute(e){const n=[];return e.byText&&n.push(...this.findByText(e.byText)),e.byCharRange&&n.push(...this.findByCharRange(e.byCharRange)),n}findByText(e){const n=[];for(const i of e){let e=0;for(;-1!==(e=this.text.indexOf(i,e));)n.push(this.createTextRange(e,e+i.length,i)),e+=i.length}return n}findByCharRange(e){return e.map(e=>{const n=this.text.slice(e.start,e.end);return this.createTextRange(e.start,e.end,n)})}createTextRange(e,n,i){const s=[],r=new Map;for(let i=e;i<n;i++){const e=this.glyphsByTextIndex.get(i);if(e)for(const n of e){s.push(n);const e=r.get(n.lineIndex)||[];e.push(n),r.set(n.lineIndex,e)}}return{start:e,end:n,originalText:i,bounds:Array.from(r.values()).map(e=>this.calculateBounds(e)),glyphs:s,lineIndices:Array.from(r.keys()).sort((e,n)=>e-n)}}calculateBounds(e){if(0===e.length)return{min:{x:0,y:0,z:0},max:{x:0,y:0,z:0}};const n=new Box3;for(const i of e){const e=new Box3(new Vec3(i.bounds.min.x,i.bounds.min.y,i.bounds.min.z),new Vec3(i.bounds.max.x,i.bounds.max.y,i.bounds.max.z));n.union(e)}return{min:{x:n.min.x,y:n.min.y,z:n.min.z},max:{x:n.max.x,y:n.max.y,z:n.max.z}}}}class Text{static{this.patternCache=new Map}static{this.hbInitPromise=null}static{this.fontCache=new Map}static{this.fontIdCounter=0}constructor(e){this.currentFontId="",Text.hbInitPromise||(Text.hbInitPromise=ft.getHarfBuzz()),this.fontLoader=new FontLoader(()=>Text.hbInitPromise)}static setHarfBuzzPath(e){ft.setWasmPath(e),Text.hbInitPromise=null}static setHarfBuzzBuffer(e){ft.setWasmBuffer(e),Text.hbInitPromise=null}static init(){return Text.hbInitPromise||(Text.hbInitPromise=ft.getHarfBuzz()),Text.hbInitPromise}static async create(e){if(!e.font)throw new Error("Font is required. Specify options.font as a URL string or ArrayBuffer.");Text.hbInitPromise||(Text.hbInitPromise=ft.getHarfBuzz());const n="string"==typeof e.font?e.font:`buffer-${Text.generateFontContentHash(e.font)}`,i=e.fontVariations?`${n}_${JSON.stringify(e.fontVariations)}`:n;let s=Text.fontCache.get(i);s||(s=await Text.loadAndCacheFont(i,e.font,e.fontVariations));const r=new Text({maxCacheSizeMB:e.maxCacheSizeMB});r.setLoadedFont(s);const{font:o,maxCacheSizeMB:h,...c}=e;return{...await r.createGeometry(c),getLoadedFont:()=>r.getLoadedFont(),getCacheStatistics:()=>r.getCacheStatistics(),clearCache:()=>r.clearCache(),measureTextWidth:(e,n)=>r.measureTextWidth(e,n)}}static async loadAndCacheFont(e,n,i){const s=new Text;await s.loadFont(n,i);const r=s.getLoadedFont();return Text.fontCache.set(e,r),r}static generateFontContentHash(e){if(e){const n=new Uint8Array(e);return`${n[0]}_${n[Math.floor(n.length/2)]}_${n[n.length-1]}_${n.length}`}return""+ ++Text.fontIdCounter}setLoadedFont(e){this.loadedFont=e;const n=Text.generateFontContentHash(e._buffer);this.currentFontId=`font_${n}`,e.fontVariations&&(this.currentFontId+=`_${JSON.stringify(e.fontVariations)}`)}async loadFont(e,n){s.start("Text.loadFont",{fontSrc:"string"==typeof e?e:`buffer(${e.byteLength})`}),Text.hbInitPromise||(Text.hbInitPromise=ft.getHarfBuzz()),await Text.hbInitPromise;const r="string"==typeof e?await fetch(e).then(n=>{if(!n.ok)throw new Error(`Failed to load font from ${e}: HTTP ${n.status} ${n.statusText}`);return n.arrayBuffer()}):e;try{this.loadedFont&&this.destroy(),this.loadedFont=await this.fontLoader.loadFont(r,n);const e=Text.generateFontContentHash(r);this.currentFontId=`font_${e}`,n&&(this.currentFontId+=`_${JSON.stringify(n)}`)}catch(e){throw i.error("Failed to load font:",e),e}finally{s.end("Text.loadFont")}}async createGeometry(e){s.start("Text.createGeometry",{textLength:e.text.length,size:e.size||72,hasLayout:!!e.layout,mode:"cached"});try{if(!this.loadedFont)throw new Error("Font not loaded. Use Text.create() with a font option.");const n=await this.prepareHyphenation(e);if(this.validateOptions(n),e=n,this.updateFontVariations(e),!this.geometryBuilder){const n=e.maxCacheSizeMB?new GlyphCache(e.maxCacheSizeMB):st;this.geometryBuilder=new GlyphGeometryBuilder(n,this.loadedFont),this.geometryBuilder.setFontId(this.currentFontId)}this.geometryBuilder.setCurveFidelityConfig(e.curveFidelity),this.geometryBuilder.setGeometryOptimization(e.geometryOptimization),this.loadedFont.font.setScale(this.loadedFont.upem,this.loadedFont.upem),this.textShaper||(this.textShaper=new TextShaper(this.loadedFont,this.geometryBuilder));const i=this.prepareLayout(e),s=e.removeOverlaps??this.loadedFont.isVariable??!1,r=this.textShaper.shapeLines(i.lines,i.scaledLineHeight,i.letterSpacing,i.align,i.direction,e.color,e.text),o=this.geometryBuilder.buildInstancedGeometry(r,i.depth,s,this.loadedFont.metrics.isCFF,e.separateGlyphsWithAttributes||!1),h=this.geometryBuilder.getCacheStats(),c=this.finalizeGeometry(o.vertices,o.normals,o.indices,o.glyphInfos,o.planeBounds,e,h,e.text);if(e.separateGlyphsWithAttributes){const e=this.createGlyphAttributes(c.vertices.length/3,c.glyphs);c.glyphAttributes=e}return c}finally{s.end("Text.createGeometry")}}async prepareHyphenation(e){if(!1!==e.layout?.hyphenate&&e.layout?.width){const n=e.layout?.language||"en-us";if(!e.layout?.hyphenationPatterns?.[n])try{if(!Text.patternCache.has(n)){const i=await loadPattern(n,e.layout?.patternsPath);Text.patternCache.set(n,i)}return{...e,layout:{...e.layout,hyphenationPatterns:{...e.layout?.hyphenationPatterns,[n]:Text.patternCache.get(n)}}}}catch(s){return i.warn(`Failed to load patterns for ${n}: ${s}`),{...e,layout:{...e.layout,hyphenate:!1}}}}return e}validateOptions(e){if(!e.text)throw new Error("Text content is required");const n=e.maxTextLength??1e5;if(e.text.length>n)throw new Error(`Text exceeds ${n} character limit`)}updateFontVariations(e){e.fontVariations&&this.loadedFont&&JSON.stringify(e.fontVariations)!==JSON.stringify(this.loadedFont.fontVariations)&&(this.loadedFont.font.setVariations(e.fontVariations),this.loadedFont.fontVariations=e.fontVariations)}prepareLayout(e){if(!this.loadedFont)throw new Error("Font not loaded. Use Text.create() with a font option");const{text:n,size:i=72,depth:s=0,lineHeight:c=1,letterSpacing:l=0,layout:d={}}=e,{width:f,direction:p="ltr",align:g=("rtl"===p?"right":"left"),respectExistingBreaks:y=!0,hyphenate:b=!0,language:m="en-us",tolerance:_=r,pretolerance:w=o,emergencyStretch:O=h,autoEmergencyStretch:k,hyphenationPatterns:j,lefthyphenmin:$,righthyphenmin:Y,linepenalty:q,adjdemerits:tt,hyphenpenalty:et,exhyphenpenalty:nt,doublehyphendemerits:it,looseness:st,disableSingleWordDetection:rt}=d;let at;void 0!==f&&(at=f*(this.loadedFont.upem/i));const ot=s*(this.loadedFont.upem/i);this.textLayout||(this.textLayout=new TextLayout(this.loadedFont));const ht=this.textLayout.computeLines({text:n,width:at,align:g,direction:p,hyphenate:b,language:m,respectExistingBreaks:y,tolerance:_,pretolerance:w,emergencyStretch:O,autoEmergencyStretch:k,hyphenationPatterns:j,lefthyphenmin:$,righthyphenmin:Y,linepenalty:q,adjdemerits:tt,hyphenpenalty:et,exhyphenpenalty:nt,doublehyphendemerits:it,looseness:st,disableSingleWordDetection:rt,letterSpacing:l}),ct=FontMetadataExtractor.getVerticalMetrics(this.loadedFont.metrics),lt=(ct.ascender-ct.descender)*c;return{lines:ht.lines,scaledLineHeight:lt,letterSpacing:l,align:g,direction:p,depth:ot,size:i}}applyColorSystem(e,n,i,s){const r=e.length/3,o=new Float32Array(3*r),h=[];if(Array.isArray(i)){for(let e=0;e<r;e++){const n=3*e;o[n]=i[0],o[n+1]=i[1],o[n+2]=i[2]}h.push({start:0,end:s.length,originalText:s,color:i,bounds:[],glyphs:n,lineIndices:[...new Set(n.map(e=>e.lineIndex))]})}else{const e=i.default||[1,1,1];for(let n=0;n<o.length;n+=3)o[n]=e[0],o[n+1]=e[1],o[n+2]=e[2];if(i.byText){new TextRangeQuery(s,n).execute({byText:Object.keys(i.byText)}).forEach(e=>{const n=i.byText[e.originalText];n&&(e.glyphs.forEach(e=>{for(let i=0;i<e.vertexCount;i++){const s=3*(e.vertexStart+i);s>=0&&s<o.length&&(o[s]=n[0],o[s+1]=n[1],o[s+2]=n[2])}}),h.push({start:e.start,end:e.end,originalText:e.originalText,color:n,bounds:e.bounds,glyphs:e.glyphs,lineIndices:e.lineIndices}))})}i.byCharRange&&i.byCharRange.forEach(e=>{const i=[];for(const s of n)if(s.textIndex>=e.start&&s.textIndex<e.end){i.push(s);for(let n=0;n<s.vertexCount;n++){const i=3*(s.vertexStart+n);i>=0&&i<o.length&&(o[i]=e.color[0],o[i+1]=e.color[1],o[i+2]=e.color[2])}}h.push({start:e.start,end:e.end,originalText:s.slice(e.start,e.end),color:e.color,bounds:[],glyphs:i,lineIndices:[...new Set(i.map(e=>e.lineIndex))]})})}return{colors:o,coloredRanges:h}}finalizeGeometry(e,n,i,s,r,o,h,c){const{layout:l={},size:d=72}=o,{width:f,align:p=("rtl"===l.direction?"right":"left")}=l;this.textLayout||(this.textLayout=new TextLayout(this.loadedFont));const g=this.textLayout.applyAlignment(e,{width:f,align:p,planeBounds:r}),y=g.offset;r.min.x=g.adjustedBounds.min.x,r.max.x=g.adjustedBounds.max.x;const b=d/this.loadedFont.upem;for(let n=0;n<e.length;n++)e[n]*=b;r.min.x*=b,r.min.y*=b,r.min.z*=b,r.max.x*=b,r.max.y*=b,r.max.z*=b;for(let e=0;e<s.length;e++){const n=s[e];0!==y&&(n.bounds.min.x+=y,n.bounds.max.x+=y),n.bounds.min.x*=b,n.bounds.min.y*=b,n.bounds.min.z*=b,n.bounds.max.x*=b,n.bounds.max.y*=b,n.bounds.max.z*=b}let m,_;if(o.color){const n=this.applyColorSystem(e,s,o.color,o.text);m=n.colors,_=n.coloredRanges}const w=this.geometryBuilder.getOptimizationStats(),O=i.length/3,k=e.length/3;return{vertices:e,normals:n,indices:i,colors:m,glyphs:s,planeBounds:r,stats:{trianglesGenerated:O,verticesGenerated:k,pointsRemovedByVisvalingam:w.pointsRemovedByVisvalingam,pointsRemovedByColinear:w.pointsRemovedByColinear,originalPointCount:w.originalPointCount,...h||{}},query:e=>{if(!c)throw new Error("Original text not available for querying");return new TextRangeQuery(c,s).execute(e)},coloredRanges:_,glyphAttributes:void 0}}getFontMetrics(){if(!this.loadedFont)throw new Error("Font not loaded. Call loadFont() first");return FontMetadataExtractor.getFontMetrics(this.loadedFont.metrics)}static async preloadPatterns(e,n){await Promise.all(e.map(async e=>{if(!Text.patternCache.has(e))try{const i=await loadPattern(e,n);Text.patternCache.set(e,i)}catch(n){i.warn(`Failed to pre-load patterns for ${e}: ${n}`)}}))}static registerPattern(e,n){Text.patternCache.set(e,n)}getLoadedFont(){return this.loadedFont}measureTextWidth(e,n=0){if(!this.loadedFont)throw new Error("Font not loaded. Call loadFont() first");return TextMeasurer.measureTextWidth(this.loadedFont,e,n)}getCacheStatistics(){return this.geometryBuilder?this.geometryBuilder.getCacheStats():null}clearCache(){this.geometryBuilder&&this.geometryBuilder.clearCache()}createGlyphAttributes(e,n){const i=new Float32Array(3*e),s=new Float32Array(e),r=new Float32Array(e);return n.forEach((n,o)=>{const h=(n.bounds.min.x+n.bounds.max.x)/2,c=(n.bounds.min.y+n.bounds.max.y)/2,l=(n.bounds.min.z+n.bounds.max.z)/2;for(let d=0;d<n.vertexCount;d++){const f=n.vertexStart+d;f<e&&(i[3*f]=h,i[3*f+1]=c,i[3*f+2]=l,s[f]=o,r[f]=n.lineIndex)}}),{glyphCenter:i,glyphIndex:s,glyphLineIndex:r}}destroy(){if(!this.loadedFont)return;const e=this.loadedFont;try{FontLoader.destroyFont(e)}catch(e){i.warn("Error destroying HarfBuzz objects:",e)}finally{this.loadedFont=void 0,this.textLayout=void 0,this.textShaper=void 0}}}e.DEFAULT_CURVE_FIDELITY=nt,e.FontMetadataExtractor=FontMetadataExtractor,e.Text=Text,e.globalGlyphCache=st});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "three-text",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "3D font rendering and text layout engine for the web",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",