{"version":3,"file":"XCircleNotes.min.mjs","sources":["../../../../src/shapes/canvasx/XCircleNotes.ts"],"sourcesContent":["import { TClassProperties } from '../../typedefs';\nimport { classRegistry } from '../../ClassRegistry';\nimport { XTextbase } from './XTextbase';\nimport { createRectNotesDefaultControls } from '../../controls/X_commonControls';\n\nimport { EntityKeys, WidgetCircleNotesInterface } from './type/widget.entity.circlenote';\nimport { WidgetType } from './type/widget.type';\n\n// @TODO: Many things here are configuration related and shouldn't be on the class nor prototype\n// regexes, list of properties that are not suppose to change by instances, magic consts.\n// this will be a separated effort\nexport const circleNotesDefaultValues: Partial<TClassProperties<XCircleNotes>> =\n{\n  minWidth: 20,\n  dynamicMinWidth: 2,\n  verticalAlign: 'middle',\n  lockScalingFlip: true,\n  noScaleCache: false,\n  _wordJoiners: /[ \\t\\r]/,\n  splitByGrapheme: true,\n  objType: 'XCircleNotes',\n  height: 138,\n  maxHeight: 138,\n  width: 138,\n  noteType: 'circle',\n  radius: 138,\n  cornerStrokeColor: 'gray',\n  cornerStyle: 'circle',\n  cornerColor: 'white',\n  transparentCorners: false,\n};\n\nexport interface CircleNotesProps {\n  id: string;\n  originX: string;\n  originY: string;\n  top: number;\n  left: number;\n  textAlign: string;\n  width: number;\n  height: number;\n  backgroundColor: string;\n}\n\n/**\n * Textbox class, based on IText, allows the user to resize the text rectangle\n * and wraps lines automatically. Textboxes have their Y scaling locked, the\n * user can only change width. Height is adjusted automatically based on the\n * wrapping of lines.\n */\nexport class XCircleNotes extends XTextbase implements WidgetCircleNotesInterface {\n  /**selectable\n   * Minimum width of textbox, in pixels.\n   * @type Number\n   * @default\n   */\n  declare minWidth: number;\n  declare maxHeight: number;\n  declare noteType: string;\n  declare radius: number;\n\n  static type: WidgetType = 'XCircleNotes';\n  static objType: WidgetType = 'XCircleNotes';\n\n  /* boardx cusotm function */\n  declare id: string;\n\n  declare locked: boolean;\n\n  declare boardId: string;\n\n  declare userId: string;\n\n  declare timestamp: Date;\n\n  declare verticalAlign: string;\n\n  declare zIndex: number;\n\n  declare lines: object[];\n\n  declare relationship: object[];\n\n  declare emoj: object[];\n\n  declare userEmoji: object[];\n\n  /**\n   * Minimum calculated width of a textbox, in pixels.\n   * fixed to 2 so that an empty textbox cannot go to 0\n   * and is still selectable without text.\n   * @type Number\n   * @default\n   */\n  declare dynamicMinWidth: number;\n\n  /**\n   * Use this boolean property in order to split strings that have no white space concept.\n   * this is a cheap way to help with chinese/japanese\n   * @type Boolean\n   * @since 2.6.0\n   */\n  declare splitByGrapheme: boolean;\n\n  static textLayoutProperties = [...XTextbase.textLayoutProperties, 'width'];\n\n  static ownDefaults: Record<string, any> = circleNotesDefaultValues;\n\n  static getDefaults() {\n    return {\n      ...super.getDefaults(),\n\n      ...XCircleNotes.ownDefaults,\n    };\n  }\n\n  constructor(text: string, options: any) {\n\n    super(text, options);\n    Object.assign(this, options);\n    Object.assign(this, {\n      controls: { ...createRectNotesDefaultControls(this) },\n    });\n    this.objType = 'XCircleNotes';\n  }\n\n\n  getObject() {\n    const entityKeys: string[] = EntityKeys;\n    const result: Record<string, any> = {};\n\n    entityKeys.forEach((key) => {\n      if (key in this) {\n        result[key] = (this as any)[key];\n      }\n    });\n\n    return result;\n  }\n\n\n\n  /**\n   * Unlike superclass's version of this function, Textbox does not update\n   * its width.\n   * @private\n   * @override\n   */\n  initDimensions() {\n    if (!this.initialized) {\n      return;\n    }\n    this.isEditing && this.initDelayedCursor();\n    this._clearCache();\n    // clear dynamicMinWidth as it will be different after we re-wrap line\n    this.dynamicMinWidth = 0;\n    // wrap lines\n    this._styleMap = this._generateStyleMap(this._splitText());\n    // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\n    if (this.dynamicMinWidth > this.width) {\n      this.set('fontSize', this.fontSize - 2);\n      this._splitTextIntoLines(this.text);\n      return;\n    }\n    if (this.textAlign.indexOf('justify') !== -1) {\n      // once text is measured we need to make space fatter to make justified text.\n      this.enlargeSpaces();\n    }\n    // clear cache and re-calculate height\n    const height = this.calcTextHeight();\n    if (height > 76 && this.fontSize > 2) {\n      this.set('fontSize', this.fontSize - 2);\n      this._splitTextIntoLines(this.text);\n      return;\n    }\n\n    this.height = this.maxHeight;\n    return this.height;\n  }\n\n  /**\n   * Generate an object that translates the style object so that it is\n   * broken up by visual lines (new lines and automatic wrapping).\n   * The original text styles object is broken up by actual lines (new lines only),\n   * which is only sufficient for Text / IText\n   * @private\n   */\n  _generateStyleMap(textInfo: any) {\n    let realLineCount = 0,\n      realLineCharCount = 0,\n      charCount = 0;\n    const map: any = {};\n\n    for (let i = 0; i < textInfo.graphemeLines.length; i++) {\n      if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\n        realLineCharCount = 0;\n        charCount++;\n        realLineCount++;\n      } else if (\n        !this.splitByGrapheme &&\n        this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) &&\n        i > 0\n      ) {\n        // this case deals with space's that are removed from end of lines when wrapping\n        realLineCharCount++;\n        charCount++;\n      }\n\n      map[i] = { line: realLineCount, offset: realLineCharCount };\n\n      charCount += textInfo.graphemeLines[i].length;\n      realLineCharCount += textInfo.graphemeLines[i].length;\n    }\n\n    return map;\n  }\n\n  // /**\n  //  * Returns true if object has a style property or has it on a specified line\n  //  * @param {Number} lineIndex\n  //  * @return {Boolean}\n  //  */\n  // styleHas(property, lineIndex: number): boolean {\n  //   if (this._styleMap && !this.isWrapping) {\n  //     const map = this._styleMap[lineIndex];\n  //     if (map) {\n  //       lineIndex = map.line;\n  //     }\n  //   }\n  //   return super.styleHas(property, lineIndex);\n  // }\n\n  // /**\n  //  * Returns true if object has no styling or no styling in a line\n  //  * @param {Number} lineIndex , lineIndex is on wrapped lines.\n  //  * @return {Boolean}\n  //  */\n  // isEmptyStyles(lineIndex: number): boolean {\n  //   if (!this.styles) {\n  //     return true;\n  //   }\n  //   let offset = 0,\n  //     nextLineIndex = lineIndex + 1,\n  //     nextOffset,\n  //     shouldLimit = false;\n  //   const map = this._styleMap[lineIndex],\n  //     mapNextLine = this._styleMap[lineIndex + 1];\n  //   if (map) {\n  //     lineIndex = map.line;\n  //     offset = map.offset;\n  //   }\n  //   if (mapNextLine) {\n  //     nextLineIndex = mapNextLine.line;\n  //     shouldLimit = nextLineIndex === lineIndex;\n  //     nextOffset = mapNextLine.offset;\n  //   }\n  //   const obj =\n  //     typeof lineIndex === 'undefined'\n  //       ? this.styles\n  //       : { line: this.styles[lineIndex] };\n  //   for (const p1 in obj) {\n  //     for (const p2 in obj[p1]) {\n  //       if (p2 >= offset && (!shouldLimit || p2 < nextOffset)) {\n  //         // eslint-disable-next-line no-unused-vars\n  //         for (const p3 in obj[p1][p2]) {\n  //           return false;\n  //         }\n  //       }\n  //     }\n  //   }\n  //   return true;\n  // }\n\n  // /**\n  //  * @param {Number} lineIndex\n  //  * @param {Number} charIndex\n  //  * @private\n  //  */\n  // _getStyleDeclaration(lineIndex: number, charIndex: number) {\n  //   if (this._styleMap && !this.isWrapping) {\n  //     const map = this._styleMap[lineIndex];\n  //     if (!map) {\n  //       return null;\n  //     }\n  //     lineIndex = map.line;\n  //     charIndex = map.offset + charIndex;\n  //   }\n  //   return super._getStyleDeclaration(lineIndex, charIndex);\n  // }\n\n  /**\n   * @param {Number} lineIndex\n   * @param {Number} charIndex\n   * @param {Object} style\n   * @private\n   */\n  _setStyleDeclaration(lineIndex: number, charIndex: number, style: object) {\n    const map = this._styleMap[lineIndex];\n    lineIndex = map.line;\n    charIndex = map.offset + charIndex;\n\n    this.styles[lineIndex][charIndex] = style;\n  }\n\n  /**\n   * @param {Number} lineIndex\n   * @param {Number} charIndex\n   * @private\n   */\n  _deleteStyleDeclaration(lineIndex: number, charIndex: number) {\n    const map = this._styleMap[lineIndex];\n    lineIndex = map.line;\n    charIndex = map.offset + charIndex;\n    delete this.styles[lineIndex][charIndex];\n  }\n\n  /**\n   * probably broken need a fix\n   * Returns the real style line that correspond to the wrapped lineIndex line\n   * Used just to verify if the line does exist or not.\n   * @param {Number} lineIndex\n   * @returns {Boolean} if the line exists or not\n   * @private\n   */\n  _getLineStyle(lineIndex: number): boolean {\n    const map = this._styleMap[lineIndex];\n    return !!this.styles[map.line];\n  }\n\n  /**\n   * Set the line style to an empty object so that is initialized\n   * @param {Number} lineIndex\n   * @param {Object} style\n   * @private\n   */\n  _setLineStyle(lineIndex: number) {\n    const map = this._styleMap[lineIndex];\n    this.styles[map.line] = {};\n  }\n\n  // /**\n  //  * Wraps text using the 'width' property of Textbox. First this function\n  //  * splits text on newlines, so we preserve newlines entered by the user.\n  //  * Then it wraps each line using the width of the Textbox by calling\n  //  * _wrapLine().\n  //  * @param {Array} lines The string array of text that is split into lines\n  //  * @param {Number} desiredWidth width you want to wrap to\n  //  * @returns {Array} Array of lines\n  //  */\n  // _wrapText(lines: Array<any>, desiredWidth: number): Array<any> {\n  //   const wrapped = [];\n  //   this.isWrapping = true;\n  //   for (let i = 0; i < lines.length; i++) {\n  //     wrapped.push(...this._wrapLine(lines[i], i, desiredWidth));\n  //   }\n  //   this.isWrapping = false;\n  //   return wrapped;\n  // }\n\n  /**\n   * Helper function to measure a string of text, given its lineIndex and charIndex offset\n   * It gets called when charBounds are not available yet.\n   * Override if necessary\n   * Use with {@link Textbox#wordSplit}\n   *\n   * @param {CanvasRenderingContext2D} ctx\n   * @param {String} text\n   * @param {number} lineIndex\n   * @param {number} charOffset\n   * @returns {number}\n   */\n  _measureWord(word: any, lineIndex: number, charOffset = 0): number {\n    let width = 0,\n      prevGrapheme;\n    const skipLeft = true;\n    for (let i = 0, len = word.length; i < len; i++) {\n      const box = this._getGraphemeBox(\n        word[i],\n        lineIndex,\n        i + charOffset,\n        prevGrapheme,\n        skipLeft\n      );\n      width += box.kernedWidth;\n      prevGrapheme = word[i];\n    }\n    return width;\n  }\n\n  /**\n   * Override this method to customize word splitting\n   * Use with {@link Textbox#_measureWord}\n   * @param {string} value\n   * @returns {string[]} array of words\n   */\n  wordSplit(value: string): string[] {\n    return value.split(this._wordJoiners);\n  }\n\n  /**\n   * Wraps a line of text using the width of the Textbox and a context.\n   * @param {Array} line The grapheme array that represent the line\n   * @param {Number} lineIndex\n   * @param {Number} desiredWidth width you want to wrap the line to\n   * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\n   * @returns {Array} Array of line(s) into which the given text is wrapped\n   * to.\n   */\n  graphemeSplitForRectNotes(textstring: string): string[] {\n    const graphemes = [];\n    const words = textstring.split(/\\b/);\n    for (let i = 0; i < words.length; i++) {\n      // 检查单词是否全为拉丁字母，长度不大于13，且没有四个或更多的连续相同的字母\n      if (\n        /^[a-zA-Z]+$/.test(words[i]) &&\n        words[i].length <= 13 &&\n        !/(\\w)\\1{3,}/.test(words[i])\n      ) {\n        graphemes.push(words[i]);\n      } else {\n        for (let j = 0; j < words[i].length; j++) {\n          graphemes.push(words[i][j]);\n        }\n      }\n    }\n    return graphemes;\n  }\n\n  // _wrapLine(\n  //   _line: any,\n  //   lineIndex: number,\n  //   desiredWidth: number,\n  //   reservedSpace = 0\n  // ): Array<any> {\n  //   const additionalSpace = this._getWidthOfCharSpacing(),\n  //     splitByGrapheme = this.splitByGrapheme,\n  //     graphemeLines = [],\n  //     words = splitByGrapheme\n  //       ? this.graphemeSplitForRectNotes(_line)\n  //       : this.wordSplit(_line),\n  //     infix = splitByGrapheme ? '' : ' ';\n\n  //   let lineWidth = 0,\n  //     line = [],\n  //     // spaces in different languages?\n  //     offset = 0,\n  //     infixWidth = 0,\n  //     largestWordWidth = 0,\n  //     lineJustStarted = true;\n  //   // fix a difference between split and graphemeSplit\n  //   if (words.length === 0) {\n  //     words.push([]);\n  //   }\n  //   desiredWidth -= reservedSpace;\n  //   // measure words\n  //   const data = words.map((word) => {\n  //     // if using splitByGrapheme words are already in graphemes.\n  //     word = splitByGrapheme ? word : this.graphemeSplitForRectNotes(word);\n  //     const width = this._measureWord(word, lineIndex, offset);\n  //     largestWordWidth = Math.max(width, largestWordWidth);\n  //     offset += word.length + 1;\n  //     return { word: word, width: width };\n  //   });\n  //   const maxWidth = Math.max(\n  //     desiredWidth,\n  //     largestWordWidth,\n  //     this.dynamicMinWidth\n  //   );\n  //   // layout words\n  //   offset = 0;\n  //   let i;\n  //   for (i = 0; i < words.length; i++) {\n  //     const word = data[i].word;\n  //     const wordWidth = data[i].width;\n  //     offset += word.length;\n\n  //     lineWidth += infixWidth + wordWidth - additionalSpace;\n  //     if (lineWidth > maxWidth && !lineJustStarted) {\n  //       graphemeLines.push(line);\n  //       line = [];\n  //       lineWidth = wordWidth;\n  //       lineJustStarted = true;\n  //     } else {\n  //       lineWidth += additionalSpace;\n  //     }\n\n  //     if (!lineJustStarted && !splitByGrapheme) {\n  //       line.push(infix);\n  //     }\n  //     if (word.length > 1) {\n  //       line = line.concat(word.split(''));\n  //     } else {\n  //       line = line.concat(word);\n  //     }\n\n  //     infixWidth = splitByGrapheme\n  //       ? 0\n  //       : this._measureWord([infix], lineIndex, offset);\n  //     offset++;\n  //     lineJustStarted = false;\n  //   }\n\n  //   i && graphemeLines.push(line);\n\n  //   if (largestWordWidth + reservedSpace > this.dynamicMinWidth) {\n  //     this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\n  //   }\n  //   return graphemeLines;\n  // }\n\n  /**\n   * Detect if the text line is ended with an hard break\n   * text and itext do not have wrapping, return false\n   * @param {Number} lineIndex text to split\n   * @return {Boolean}\n   */\n  isEndOfWrapping(lineIndex: number): boolean {\n    if (!this._styleMap[lineIndex + 1]) {\n      // is last line, return true;\n      return true;\n    }\n    if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\n      // this is last line before a line break, return true;\n      return true;\n    }\n    return false;\n  }\n\n  // /**\n  //  * Detect if a line has a linebreak and so we need to account for it when moving\n  //  * and counting style.\n  //  * @return Number\n  //  */\n  // missingNewlineOffset(lineIndex) {\n  //   if (this.splitByGrapheme) {\n  //     return this.isEndOfWrapping(lineIndex) ? 1 : 0;\n  //   }\n  //   return 1;\n  // }\n\n  /**\n   * Gets lines of text to render in the Textbox. This function calculates\n   * text wrapping on the fly every time it is called.\n   * @param {String} text text to split\n   * @returns {Array} Array of lines in the Textbox.\n   * @override\n   */\n  _splitTextIntoLines(text: string) {\n    const newText = super._splitTextIntoLines(text),\n      graphemeLines = this._wrapText(newText.lines, this.width),\n      lines = new Array(graphemeLines.length);\n    for (let i = 0; i < graphemeLines.length; i++) {\n      lines[i] = graphemeLines[i].join('');\n    }\n    newText.lines = lines;\n    newText.graphemeLines = graphemeLines;\n    return newText;\n  }\n\n  getMinWidth() {\n    return Math.max(this.minWidth, this.dynamicMinWidth);\n  }\n\n\n\n  /* caculate cusor positon in the middle of the textbox */\n  getCenteredTop(rectHeight: any) {\n    const textHeight = this.height;\n    return (rectHeight - textHeight) / 2;\n  }\n\n  _getTopOffset() {\n    switch (this.verticalAlign) {\n      case 'middle':\n        return -this._getTotalLineHeights() / 2;\n      case 'bottom':\n        return this.height / 2 - this._getTotalLineHeights();\n      default:\n        return -this.height / 2;\n    }\n  }\n\n  _getTotalLineHeight() {\n    return this._textLines.reduce(\n      (total, _line, index) => total + this.getHeightOfLine(index),\n      0\n    );\n  }\n\n  _getTotalLineHeights() {\n    return this._textLines.reduce(\n      (total, line, index) => total + this.getHeightOfLine(index),\n      0\n    );\n  }\n\n  _render(ctx: any) {\n    const path: any = this.path;\n\n    path && !path.isNotVisible() && path._render(ctx);\n    this._setTextStyles(ctx);\n    this._renderTextLinesBackground(ctx);\n    this._renderTextDecoration(ctx, 'underline');\n    this._renderText(ctx);\n    this._renderTextDecoration(ctx, 'overline');\n    this._renderTextDecoration(ctx, 'linethrough');\n\n    // const isEmojiExist = !(\n    //   this.emoji === undefined || this.emoji.join() === '0,0,0,0,0'\n    // );\n    // if (isEmojiExist) {\n    //   this.renderEmoji(ctx);\n    // }\n  }\n\n  // renderEmoji(ctx) {\n  //   if (this.emoji === undefined) {\n  //     return;\n  //   }\n\n  //   let width = 0;\n  //   const imageList = [\n  //     this.canvas.emoji_thumb,\n  //     this.canvas.emoji_love,\n  //     this.canvas.emoji_smile,\n  //     this.canvas.emoji_shock,\n  //     this.canvas.emoji_question,\n  //   ];\n  //   const imageListArray = [];\n  //   const emojiList = [];\n  //   for (let i = 0; i < 5; i++) {\n  //     if (this.emoji[i] !== 0) {\n  //       imageListArray.push(imageList[i]);\n  //       emojiList.push(this.emoji[i]);\n  //       width += 26.6;\n  //     }\n  //   }\n\n  //   if (emojiList.length === 0) return;\n\n  //   const x = this.width / 2 - width + this.padding / 2;\n  //   const y = this.height / 2 - 18 + this.padding / 2;\n  //   ctx.font = '10px Inter ';\n  //   ctx.lineJoin = 'round';\n  //   ctx.save();\n  //   ctx.translate(x - 10, y);\n  //   this.drawRoundRectPath(ctx, width, 15, 2);\n  //   ctx.fillStyle = 'rgba(255, 255, 255, 1)';\n  //   ctx.fill();\n  //   ctx.restore();\n\n  //   //ctx.strokeRect(x - 10, y, width, 16);\n  //   //ctx.fillRect(x - 10 + 10 / 2, y + 10 / 2, width - 10, 16 - 10);\n  //   ctx.fillStyle = '#000';\n  //   const isEmojiThumbExist = !(this.canvas.emoji_thumb === undefined);\n  //   if (isEmojiThumbExist) {\n  //     let modifier = 0;\n  //     for (let i = 0; i < imageListArray.length; i++) {\n  //       const imageX = this.width / 2 - 33.6 + modifier + 2 + this.padding / 2;\n  //       const imageY = this.height / 2 - 15 + this.padding / 2;\n  //       const imageW = 10;\n  //       const imageH = 10;\n  //       ctx.drawImage(imageListArray[i], imageX, imageY, imageW, imageH);\n  //       ctx.fillText(\n  //         emojiList[i].toString(),\n  //         this.width / 2 - 20.6 + modifier + 1 + this.padding / 2,\n  //         y + 12\n  //       );\n  //       modifier -= 23.6;\n  //     }\n  //   }\n  // }\n  _renderBackground(ctx: any) {\n    if (!this.backgroundColor) {\n      return;\n    }\n    const dim = this._getNonTransformedDimensions();\n    ctx.fillStyle = this.backgroundColor;\n    ctx.beginPath(); // start new path\n    const radius =\n      dim.x / 2 + this.padding / this.scaleX / (this.canvas?.getZoom() ?? 1);\n    ctx.arc(0, 0, radius, 0, 2 * Math.PI); // draw circle path\n    ctx.closePath(); // close path\n    ctx.strokeStyle = this.backgroundColor;\n    ctx.fillStyle = this.backgroundColor;\n    ctx.stroke();\n    ctx.fill();\n  }\n  _renderText(ctx: any) {\n    ctx.shadowOffsetX = ctx.shadowOffsetY = ctx.shadowBlur = 0;\n    ctx.shadowColor = '';\n\n    if (this.paintFirst === 'stroke') {\n      this._renderTextStroke(ctx);\n      this._renderTextFill(ctx);\n    } else {\n      this._renderTextFill(ctx);\n      this._renderTextStroke(ctx);\n    }\n  }\n  _renderTextCommon(ctx: any, method: any) {\n    ctx.save();\n    let lineHeights = 0;\n    const left = this._getLeftOffset();\n    const top = this._getTopOffset();\n\n    const offsets = this._applyPatternGradientTransform(\n      ctx,\n      //@ts-ignore\n      method === 'fillText' ? this.fill : this.stroke\n    );\n\n    for (let i = 0, len = this._textLines.length; i < len; i++) {\n      const heightOfLine = this.getHeightOfLine(i);\n      const maxHeight = heightOfLine / this.lineHeight;\n      const leftOffset = this._getLineLeftOffset(i);\n      this._renderTextLine(\n        method,\n        ctx,\n        this._textLines[i],\n        left + leftOffset - offsets.offsetX,\n        top + lineHeights + maxHeight - offsets.offsetY,\n        i\n      );\n      lineHeights += heightOfLine;\n    }\n    ctx.restore();\n  }\n\n  _getSVGLeftTopOffsets() {\n    return {\n      textLeft: -this.width / 2,\n      textTop: this._getTopOffset(),\n      lineTop: this.getHeightOfLine(0),\n    };\n  }\n\n  drawRoundRectPath(cxt: any, width: any, height: any, radius: any) {\n    cxt.beginPath(0);\n    //从右下角顺时针绘制，弧度从0到1/2PI\n    cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2);\n\n    //矩形下边线\n    cxt.lineTo(radius, height);\n\n    //左下角圆弧，弧度从1/2PI到PI\n    cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);\n\n    //矩形左边线\n    cxt.lineTo(0, radius);\n\n    //左上角圆弧，弧度从PI到3/2PI\n    cxt.arc(radius, radius, radius, Math.PI, (Math.PI * 3) / 2);\n\n    //上边线\n    cxt.lineTo(width - radius, 0);\n\n    //右上角圆弧\n    cxt.arc(width - radius, radius, radius, (Math.PI * 3) / 2, Math.PI * 2);\n\n    //右边线\n    cxt.lineTo(width, height - radius);\n    cxt.closePath();\n  }\n}\n\nclassRegistry.setClass(XCircleNotes);\nclassRegistry.setSVGClass(XCircleNotes, 'XCircleNotes');\n"],"names":["circleNotesDefaultValues","minWidth","dynamicMinWidth","verticalAlign","lockScalingFlip","noScaleCache","_wordJoiners","splitByGrapheme","objType","height","maxHeight","width","noteType","radius","cornerStrokeColor","cornerStyle","cornerColor","transparentCorners","XCircleNotes","XTextbase","getDefaults","_objectSpread","super","ownDefaults","constructor","text","options","Object","assign","this","controls","createRectNotesDefaultControls","getObject","result","EntityKeys","forEach","key","initDimensions","initialized","isEditing","initDelayedCursor","_clearCache","_styleMap","_generateStyleMap","_splitText","set","fontSize","_splitTextIntoLines","textAlign","indexOf","enlargeSpaces","calcTextHeight","textInfo","realLineCount","realLineCharCount","charCount","map","i","graphemeLines","length","graphemeText","_reSpaceAndTab","test","line","offset","_setStyleDeclaration","lineIndex","charIndex","style","styles","_deleteStyleDeclaration","_getLineStyle","_setLineStyle","_measureWord","word","prevGrapheme","charOffset","arguments","undefined","len","_getGraphemeBox","kernedWidth","wordSplit","value","split","graphemeSplitForRectNotes","textstring","graphemes","words","push","j","isEndOfWrapping","newText","_wrapText","lines","Array","join","getMinWidth","Math","max","getCenteredTop","rectHeight","_getTopOffset","_getTotalLineHeights","_getTotalLineHeight","_textLines","reduce","total","_line","index","getHeightOfLine","_render","ctx","path","isNotVisible","_setTextStyles","_renderTextLinesBackground","_renderTextDecoration","_renderText","_renderBackground","_this$canvas$getZoom","_this$canvas","backgroundColor","dim","_getNonTransformedDimensions","fillStyle","beginPath","x","padding","scaleX","canvas","getZoom","arc","PI","closePath","strokeStyle","stroke","fill","shadowOffsetX","shadowOffsetY","shadowBlur","shadowColor","paintFirst","_renderTextStroke","_renderTextFill","_renderTextCommon","method","save","lineHeights","left","_getLeftOffset","top","offsets","_applyPatternGradientTransform","heightOfLine","lineHeight","leftOffset","_getLineLeftOffset","_renderTextLine","offsetX","offsetY","restore","_getSVGLeftTopOffsets","textLeft","textTop","lineTop","drawRoundRectPath","cxt","lineTo","_defineProperty","textLayoutProperties","classRegistry","setClass","setSVGClass"],"mappings":"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"}