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