{"version":3,"file":"textStyles.min.mjs","names":[],"sources":["../../../../src/util/misc/textStyles.ts"],"sourcesContent":["import { reNewline } from '../../constants';\nimport type {\n  TextStyle,\n  TextStyleDeclaration,\n} from '../../shapes/Text/StyledText';\nimport { cloneStyles } from '../internals/cloneStyles';\nimport { graphemeSplit } from '../lang_string';\n\nexport type TextStyleArray = {\n  start: number;\n  end: number;\n  style: TextStyleDeclaration;\n}[];\n\n/**\n * @param {Object} prevStyle first style to compare\n * @param {Object} thisStyle second style to compare\n * @param {boolean} forTextSpans whether to check overline, underline, and line-through properties\n * @return {boolean} true if the style changed\n */\nexport const hasStyleChanged = (\n  prevStyle: TextStyleDeclaration,\n  thisStyle: TextStyleDeclaration,\n  forTextSpans = false,\n) =>\n  prevStyle.fill !== thisStyle.fill ||\n  prevStyle.stroke !== thisStyle.stroke ||\n  prevStyle.strokeWidth !== thisStyle.strokeWidth ||\n  prevStyle.fontSize !== thisStyle.fontSize ||\n  prevStyle.fontFamily !== thisStyle.fontFamily ||\n  prevStyle.fontWeight !== thisStyle.fontWeight ||\n  prevStyle.fontStyle !== thisStyle.fontStyle ||\n  prevStyle.textDecorationThickness !== thisStyle.textDecorationThickness ||\n  prevStyle.textDecorationColor !== thisStyle.textDecorationColor ||\n  prevStyle.textBackgroundColor !== thisStyle.textBackgroundColor ||\n  prevStyle.deltaY !== thisStyle.deltaY ||\n  (forTextSpans &&\n    (prevStyle.overline !== thisStyle.overline ||\n      prevStyle.underline !== thisStyle.underline ||\n      prevStyle.linethrough !== thisStyle.linethrough));\n\n/**\n * Returns the array form of a text object's inline styles property with styles grouped in ranges\n * rather than per character. This format is less verbose, and is better suited for storage\n * so it is used in serialization (not during runtime).\n * @param {object} styles per character styles for a text object\n * @param {String} text the text string that the styles are applied to\n * @return {{start: number, end: number, style: object}[]}\n */\nexport const stylesToArray = (\n  styles: TextStyle,\n  text: string,\n): TextStyleArray => {\n  const textLines = text.split('\\n'),\n    stylesArray = [];\n  let charIndex = -1,\n    prevStyle = {};\n  // clone style structure to prevent mutation\n  styles = cloneStyles(styles);\n\n  //loop through each textLine\n  for (let i = 0; i < textLines.length; i++) {\n    const chars = graphemeSplit(textLines[i]);\n    if (!styles[i]) {\n      //no styles exist for this line, so add the line's length to the charIndex total and reset prevStyle\n      charIndex += chars.length;\n      prevStyle = {};\n      continue;\n    }\n    //loop through each character of the current line\n    for (let c = 0; c < chars.length; c++) {\n      charIndex++;\n      const thisStyle = styles[i][c];\n      //check if style exists for this character\n      if (thisStyle && Object.keys(thisStyle).length > 0) {\n        if (hasStyleChanged(prevStyle, thisStyle, true)) {\n          stylesArray.push({\n            start: charIndex,\n            end: charIndex + 1,\n            style: thisStyle,\n          });\n        } else {\n          //if style is the same as previous character, increase end index\n          stylesArray[stylesArray.length - 1].end++;\n        }\n      }\n      prevStyle = thisStyle || {};\n    }\n  }\n  return stylesArray;\n};\n\n/**\n * Returns the object form of the styles property with styles that are assigned per\n * character rather than grouped by range. This format is more verbose, and is\n * only used during runtime (not for serialization/storage)\n * @param {Array} styles the serialized form of a text object's styles\n * @param {String} text the text string that the styles are applied to\n * @return {Object}\n */\nexport const stylesFromArray = (\n  styles: TextStyleArray | TextStyle,\n  text: string,\n): TextStyle => {\n  if (!Array.isArray(styles)) {\n    // clone to prevent mutation\n    return cloneStyles(styles);\n  }\n  const textLines = text.split(reNewline),\n    stylesObject: TextStyle = {};\n  let charIndex = -1,\n    styleIndex = 0;\n  //loop through each textLine\n  for (let i = 0; i < textLines.length; i++) {\n    const chars = graphemeSplit(textLines[i]);\n\n    //loop through each character of the current line\n    for (let c = 0; c < chars.length; c++) {\n      charIndex++;\n      //check if there's a style collection that includes the current character\n      if (\n        styles[styleIndex] &&\n        styles[styleIndex].start <= charIndex &&\n        charIndex < styles[styleIndex].end\n      ) {\n        //create object for line index if it doesn't exist\n        stylesObject[i] = stylesObject[i] || {};\n        //assign a style at this character's index\n        stylesObject[i][c] = { ...styles[styleIndex].style };\n        //if character is at the end of the current style collection, move to the next\n        if (charIndex === styles[styleIndex].end - 1) {\n          styleIndex++;\n        }\n      }\n    }\n  }\n  return stylesObject;\n};\n"],"mappings":"0KAoBA,MAAa,GACX,EACA,EACA,EAAA,CAAe,IAEf,EAAU,OAAS,EAAU,MAC7B,EAAU,SAAW,EAAU,QAC/B,EAAU,cAAgB,EAAU,aACpC,EAAU,WAAa,EAAU,UACjC,EAAU,aAAe,EAAU,YACnC,EAAU,aAAe,EAAU,YACnC,EAAU,YAAc,EAAU,WAClC,EAAU,0BAA4B,EAAU,yBAChD,EAAU,sBAAwB,EAAU,qBAC5C,EAAU,sBAAwB,EAAU,qBAC5C,EAAU,SAAW,EAAU,QAC9B,IACE,EAAU,WAAa,EAAU,UAChC,EAAU,YAAc,EAAU,WAClC,EAAU,cAAgB,EAAU,aAU7B,GACX,EACA,IAAA,CAEA,IAAM,EAAY,EAAK,MAAM;EAAA,CAC3B,EAAc,EAAA,CACZ,EAAA,GACF,EAAY,EAAA,CAEd,EAAS,EAAY,EAAA,CAGrB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAU,OAAQ,IAAK,CACzC,IAAM,EAAQ,EAAc,EAAU,GAAA,CACtC,GAAK,EAAO,GAOZ,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,OAAQ,IAAK,CACrC,IACA,IAAM,EAAY,EAAO,GAAG,GAExB,GAAa,OAAO,KAAK,EAAA,CAAW,OAAS,IAC3C,EAAgB,EAAW,EAAA,CAAW,EAAA,CACxC,EAAY,KAAK,CACf,MAAO,EACP,IAAK,EAAY,EACjB,MAAO,EAAA,CAAA,CAIT,EAAY,EAAY,OAAS,GAAG,OAGxC,EAAY,GAAa,EAAA,MArBzB,GAAa,EAAM,OACnB,EAAY,EAAA,CAuBhB,OAAO,GAWI,GACX,EACA,IAAA,CAEA,GAAA,CAAK,MAAM,QAAQ,EAAA,CAEjB,OAAO,EAAY,EAAA,CAErB,IAAM,EAAY,EAAK,MAAM,EAAA,CAC3B,EAA0B,EAAA,CACxB,EAAA,GACF,EAAa,EAEf,IAAK,IAAI,EAAI,EAAG,EAAI,EAAU,OAAQ,IAAK,CACzC,IAAM,EAAQ,EAAc,EAAU,GAAA,CAGtC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,OAAQ,IAChC,IAGE,EAAO,IACP,EAAO,GAAY,OAAS,GAC5B,EAAY,EAAO,GAAY,MAG/B,EAAa,GAAK,EAAa,IAAM,EAAA,CAErC,EAAa,GAAG,GAAK,CAAA,GAAK,EAAO,GAAY,MAAA,CAEzC,IAAc,EAAO,GAAY,IAAM,GACzC,KAKR,OAAO,GAAA,OAAA,KAAA,gBAAA,KAAA,gBAAA,KAAA"}