'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var core = require('pixijs/core');

const contextSettings = {
  willReadFrequently: true
};
class TextMetrics {
  constructor(text, style, width, height, lines, lineWidths, lineHeight, maxLineWidth, fontProperties) {
    this.text = text;
    this.style = style;
    this.width = width;
    this.height = height;
    this.lines = lines;
    this.lineWidths = lineWidths;
    this.lineHeight = lineHeight;
    this.maxLineWidth = maxLineWidth;
    this.fontProperties = fontProperties;
  }
  static measureText(text, style, wordWrap, canvas = TextMetrics._canvas) {
    wordWrap = wordWrap === void 0 || wordWrap === null ? style.wordWrap : wordWrap;
    const font = style.toFontString();
    const fontProperties = TextMetrics.measureFont(font);
    if (fontProperties.fontSize === 0) {
      fontProperties.fontSize = style.fontSize;
      fontProperties.ascent = style.fontSize;
    }
    const context = canvas.getContext("2d", contextSettings);
    context.font = font;
    const outputText = wordWrap ? TextMetrics.wordWrap(text, style, canvas) : text;
    const lines = outputText.split(/(?:\r\n|\r|\n)/);
    const lineWidths = new Array(lines.length);
    let maxLineWidth = 0;
    for (let i = 0; i < lines.length; i++) {
      const lineWidth = context.measureText(lines[i]).width + (lines[i].length - 1) * style.letterSpacing;
      lineWidths[i] = lineWidth;
      maxLineWidth = Math.max(maxLineWidth, lineWidth);
    }
    let width = maxLineWidth + style.strokeThickness;
    if (style.dropShadow) {
      width += style.dropShadowDistance;
    }
    const lineHeight = style.lineHeight || fontProperties.fontSize + style.strokeThickness;
    let height = Math.max(lineHeight, fontProperties.fontSize + style.strokeThickness * 2) + (lines.length - 1) * (lineHeight + style.leading);
    if (style.dropShadow) {
      height += style.dropShadowDistance;
    }
    return new TextMetrics(text, style, width, height, lines, lineWidths, lineHeight + style.leading, maxLineWidth, fontProperties);
  }
  static wordWrap(text, style, canvas = TextMetrics._canvas) {
    const context = canvas.getContext("2d", contextSettings);
    let width = 0;
    let line = "";
    let lines = "";
    const cache = /* @__PURE__ */ Object.create(null);
    const { letterSpacing, whiteSpace } = style;
    const collapseSpaces = TextMetrics.collapseSpaces(whiteSpace);
    const collapseNewlines = TextMetrics.collapseNewlines(whiteSpace);
    let canPrependSpaces = !collapseSpaces;
    const wordWrapWidth = style.wordWrapWidth + letterSpacing;
    const tokens = TextMetrics.tokenize(text);
    for (let i = 0; i < tokens.length; i++) {
      let token = tokens[i];
      if (TextMetrics.isNewline(token)) {
        if (!collapseNewlines) {
          lines += TextMetrics.addLine(line);
          canPrependSpaces = !collapseSpaces;
          line = "";
          width = 0;
          continue;
        }
        token = " ";
      }
      if (collapseSpaces) {
        const currIsBreakingSpace = TextMetrics.isBreakingSpace(token);
        const lastIsBreakingSpace = TextMetrics.isBreakingSpace(line[line.length - 1]);
        if (currIsBreakingSpace && lastIsBreakingSpace) {
          continue;
        }
      }
      const tokenWidth = TextMetrics.getFromCache(token, letterSpacing, cache, context);
      if (tokenWidth > wordWrapWidth) {
        if (line !== "") {
          lines += TextMetrics.addLine(line);
          line = "";
          width = 0;
        }
        if (TextMetrics.canBreakWords(token, style.breakWords)) {
          const characters = TextMetrics.wordWrapSplit(token);
          for (let j = 0; j < characters.length; j++) {
            let char = characters[j];
            let k = 1;
            while (characters[j + k]) {
              const nextChar = characters[j + k];
              const lastChar = char[char.length - 1];
              if (!TextMetrics.canBreakChars(lastChar, nextChar, token, j, style.breakWords)) {
                char += nextChar;
              } else {
                break;
              }
              k++;
            }
            j += char.length - 1;
            const characterWidth = TextMetrics.getFromCache(char, letterSpacing, cache, context);
            if (characterWidth + width > wordWrapWidth) {
              lines += TextMetrics.addLine(line);
              canPrependSpaces = false;
              line = "";
              width = 0;
            }
            line += char;
            width += characterWidth;
          }
        } else {
          if (line.length > 0) {
            lines += TextMetrics.addLine(line);
            line = "";
            width = 0;
          }
          const isLastToken = i === tokens.length - 1;
          lines += TextMetrics.addLine(token, !isLastToken);
          canPrependSpaces = false;
          line = "";
          width = 0;
        }
      } else {
        if (tokenWidth + width > wordWrapWidth) {
          canPrependSpaces = false;
          lines += TextMetrics.addLine(line);
          line = "";
          width = 0;
        }
        if (line.length > 0 || !TextMetrics.isBreakingSpace(token) || canPrependSpaces) {
          line += token;
          width += tokenWidth;
        }
      }
    }
    lines += TextMetrics.addLine(line, false);
    return lines;
  }
  static addLine(line, newLine = true) {
    line = TextMetrics.trimRight(line);
    line = newLine ? `${line}
` : line;
    return line;
  }
  static getFromCache(key, letterSpacing, cache, context) {
    let width = cache[key];
    if (typeof width !== "number") {
      const spacing = key.length * letterSpacing;
      width = context.measureText(key).width + spacing;
      cache[key] = width;
    }
    return width;
  }
  static collapseSpaces(whiteSpace) {
    return whiteSpace === "normal" || whiteSpace === "pre-line";
  }
  static collapseNewlines(whiteSpace) {
    return whiteSpace === "normal";
  }
  static trimRight(text) {
    if (typeof text !== "string") {
      return "";
    }
    for (let i = text.length - 1; i >= 0; i--) {
      const char = text[i];
      if (!TextMetrics.isBreakingSpace(char)) {
        break;
      }
      text = text.slice(0, -1);
    }
    return text;
  }
  static isNewline(char) {
    if (typeof char !== "string") {
      return false;
    }
    return TextMetrics._newlines.includes(char.charCodeAt(0));
  }
  static isBreakingSpace(char, _nextChar) {
    if (typeof char !== "string") {
      return false;
    }
    return TextMetrics._breakingSpaces.includes(char.charCodeAt(0));
  }
  static tokenize(text) {
    const tokens = [];
    let token = "";
    if (typeof text !== "string") {
      return tokens;
    }
    for (let i = 0; i < text.length; i++) {
      const char = text[i];
      const nextChar = text[i + 1];
      if (TextMetrics.isBreakingSpace(char, nextChar) || TextMetrics.isNewline(char)) {
        if (token !== "") {
          tokens.push(token);
          token = "";
        }
        tokens.push(char);
        continue;
      }
      token += char;
    }
    if (token !== "") {
      tokens.push(token);
    }
    return tokens;
  }
  static canBreakWords(_token, breakWords) {
    return breakWords;
  }
  static canBreakChars(_char, _nextChar, _token, _index, _breakWords) {
    return true;
  }
  static wordWrapSplit(token) {
    return token.split("");
  }
  static measureFont(font) {
    if (TextMetrics._fonts[font]) {
      return TextMetrics._fonts[font];
    }
    const properties = {
      ascent: 0,
      descent: 0,
      fontSize: 0
    };
    const canvas = TextMetrics._canvas;
    const context = TextMetrics._context;
    context.font = font;
    const metricsString = TextMetrics.METRICS_STRING + TextMetrics.BASELINE_SYMBOL;
    const width = Math.ceil(context.measureText(metricsString).width);
    let baseline = Math.ceil(context.measureText(TextMetrics.BASELINE_SYMBOL).width);
    const height = Math.ceil(TextMetrics.HEIGHT_MULTIPLIER * baseline);
    baseline = baseline * TextMetrics.BASELINE_MULTIPLIER | 0;
    canvas.width = width;
    canvas.height = height;
    context.fillStyle = "#f00";
    context.fillRect(0, 0, width, height);
    context.font = font;
    context.textBaseline = "alphabetic";
    context.fillStyle = "#000";
    context.fillText(metricsString, 0, baseline);
    const imagedata = context.getImageData(0, 0, width, height).data;
    const pixels = imagedata.length;
    const line = width * 4;
    let i = 0;
    let idx = 0;
    let stop = false;
    for (i = 0; i < baseline; ++i) {
      for (let j = 0; j < line; j += 4) {
        if (imagedata[idx + j] !== 255) {
          stop = true;
          break;
        }
      }
      if (!stop) {
        idx += line;
      } else {
        break;
      }
    }
    properties.ascent = baseline - i;
    idx = pixels - line;
    stop = false;
    for (i = height; i > baseline; --i) {
      for (let j = 0; j < line; j += 4) {
        if (imagedata[idx + j] !== 255) {
          stop = true;
          break;
        }
      }
      if (!stop) {
        idx -= line;
      } else {
        break;
      }
    }
    properties.descent = i - baseline;
    properties.fontSize = properties.ascent + properties.descent;
    TextMetrics._fonts[font] = properties;
    return properties;
  }
  static clearMetrics(font = "") {
    if (font) {
      delete TextMetrics._fonts[font];
    } else {
      TextMetrics._fonts = {};
    }
  }
  static get _canvas() {
    if (!TextMetrics.__canvas) {
      let canvas;
      try {
        const c = new OffscreenCanvas(0, 0);
        const context = c.getContext("2d", contextSettings);
        if (context?.measureText) {
          TextMetrics.__canvas = c;
          return c;
        }
        canvas = core.settings.ADAPTER.createCanvas();
      } catch (ex) {
        canvas = core.settings.ADAPTER.createCanvas();
      }
      canvas.width = canvas.height = 10;
      TextMetrics.__canvas = canvas;
    }
    return TextMetrics.__canvas;
  }
  static get _context() {
    if (!TextMetrics.__context) {
      TextMetrics.__context = TextMetrics._canvas.getContext("2d", contextSettings);
    }
    return TextMetrics.__context;
  }
}
TextMetrics._fonts = {};
TextMetrics.METRICS_STRING = "|\xC9q\xC5";
TextMetrics.BASELINE_SYMBOL = "M";
TextMetrics.BASELINE_MULTIPLIER = 1.4;
TextMetrics.HEIGHT_MULTIPLIER = 2;
TextMetrics._newlines = [
  10,
  13
];
TextMetrics._breakingSpaces = [
  9,
  32,
  8192,
  8193,
  8194,
  8195,
  8196,
  8197,
  8198,
  8200,
  8201,
  8202,
  8287,
  12288
];

exports.TextMetrics = TextMetrics;
//# sourceMappingURL=TextMetrics.js.map
