{"version":3,"file":"FontLoader.cjs","sources":["../../src/loaders/FontLoader.ts"],"sourcesContent":["import { Loader, FileLoader, ShapePath } from 'three'\n\nimport type { LoadingManager, Shape } from 'three'\n\ntype Options = {\n  lineHeight: number\n  letterSpacing: number\n}\n\nexport class FontLoader extends Loader {\n  constructor(manager?: LoadingManager) {\n    super(manager)\n  }\n\n  public load(\n    url: string,\n    onLoad?: (responseFont: Font) => void,\n    onProgress?: (event: ProgressEvent) => void,\n    onError?: (event: ErrorEvent) => void,\n  ): void {\n    const loader = new FileLoader(this.manager)\n\n    loader.setPath(this.path)\n    loader.setRequestHeader(this.requestHeader)\n    loader.setWithCredentials(this.withCredentials)\n\n    loader.load(\n      url,\n      (response) => {\n        if (typeof response !== 'string') throw new Error('unsupported data type')\n\n        const json = JSON.parse(response)\n\n        const font = this.parse(json)\n\n        if (onLoad) onLoad(font)\n      },\n      onProgress,\n      onError as (event: unknown) => void,\n    )\n  }\n\n  loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<Font> {\n    // @ts-ignore\n    return super.loadAsync(url, onProgress)\n  }\n\n  public parse(json: FontData): Font {\n    return new Font(json)\n  }\n}\n\ntype Glyph = {\n  _cachedOutline: string[]\n  ha: number\n  o: string\n}\n\ntype FontData = {\n  boundingBox: { yMax: number; yMin: number }\n  familyName: string\n  glyphs: { [k: string]: Glyph }\n  resolution: number\n  underlineThickness: number\n}\n\nexport class Font {\n  public data: FontData\n  public isFont = true\n  public type = 'Font'\n\n  constructor(data: FontData) {\n    this.data = data\n  }\n\n  public generateShapes(text: string, size = 100, _options?: Partial<Options>): Shape[] {\n    const shapes: Shape[] = []\n    const options = { letterSpacing: 0, lineHeight: 1, ..._options }\n    const paths = createPaths(text, size, this.data, options)\n    for (let p = 0, pl = paths.length; p < pl; p++) {\n      Array.prototype.push.apply(shapes, paths[p].toShapes(false))\n    }\n    return shapes\n  }\n}\n\nfunction createPaths(text: string, size: number, data: FontData, options: Options): ShapePath[] {\n  const chars = Array.from(text)\n  const scale = size / data.resolution\n  const line_height = (data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness) * scale\n\n  const paths: ShapePath[] = []\n\n  let offsetX = 0,\n    offsetY = 0\n\n  for (let i = 0; i < chars.length; i++) {\n    const char = chars[i]\n\n    if (char === '\\n') {\n      offsetX = 0\n      offsetY -= line_height * options.lineHeight\n    } else {\n      const ret = createPath(char, scale, offsetX, offsetY, data)\n      if (ret) {\n        offsetX += ret.offsetX + options.letterSpacing\n        paths.push(ret.path)\n      }\n    }\n  }\n\n  return paths\n}\n\nfunction createPath(\n  char: string,\n  scale: number,\n  offsetX: number,\n  offsetY: number,\n  data: FontData,\n): { offsetX: number; path: ShapePath } | undefined {\n  const glyph = data.glyphs[char] || data.glyphs['?']\n\n  if (!glyph) {\n    console.error('THREE.Font: character \"' + char + '\" does not exists in font family ' + data.familyName + '.')\n    return\n  }\n\n  const path = new ShapePath()\n\n  let x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2\n\n  if (glyph.o) {\n    const outline = glyph._cachedOutline || (glyph._cachedOutline = glyph.o.split(' '))\n\n    for (let i = 0, l = outline.length; i < l; ) {\n      const action = outline[i++]\n\n      switch (action) {\n        case 'm': // moveTo\n          x = parseInt(outline[i++]) * scale + offsetX\n          y = parseInt(outline[i++]) * scale + offsetY\n\n          path.moveTo(x, y)\n\n          break\n\n        case 'l': // lineTo\n          x = parseInt(outline[i++]) * scale + offsetX\n          y = parseInt(outline[i++]) * scale + offsetY\n\n          path.lineTo(x, y)\n\n          break\n\n        case 'q': // quadraticCurveTo\n          cpx = parseInt(outline[i++]) * scale + offsetX\n          cpy = parseInt(outline[i++]) * scale + offsetY\n          cpx1 = parseInt(outline[i++]) * scale + offsetX\n          cpy1 = parseInt(outline[i++]) * scale + offsetY\n\n          path.quadraticCurveTo(cpx1, cpy1, cpx, cpy)\n\n          break\n\n        case 'b': // bezierCurveTo\n          cpx = parseInt(outline[i++]) * scale + offsetX\n          cpy = parseInt(outline[i++]) * scale + offsetY\n          cpx1 = parseInt(outline[i++]) * scale + offsetX\n          cpy1 = parseInt(outline[i++]) * scale + offsetY\n          cpx2 = parseInt(outline[i++]) * scale + offsetX\n          cpy2 = parseInt(outline[i++]) * scale + offsetY\n\n          path.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, cpx, cpy)\n\n          break\n      }\n    }\n  }\n\n  return { offsetX: glyph.ha * scale, path }\n}\n"],"names":["Loader","FileLoader","ShapePath"],"mappings":"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"}