{"version":3,"sources":["jsdelivr-header.js","/npm/canvas-editor-pdf@0.2.12/src/dataset/constant/Regular.ts","/npm/canvas-editor-pdf@0.2.12/src/utils/index.ts","/npm/canvas-editor-pdf@0.2.12/src/dataset/enum/Control.ts","/npm/canvas-editor-pdf@0.2.12/src/core/draw/particle/ImageParticle.ts","/npm/canvas-editor-pdf@0.2.12/src/core/draw/particle/latex/utils/LaTexUtils.ts","/npm/canvas-editor-pdf@0.2.12/src/utils/element.ts","/npm/canvas-editor-pdf@0.2.12/src/dataset/enum/VerticalAlign.ts","/npm/canvas-editor-pdf@0.2.12/src/core/position/Position.ts","/npm/canvas-editor-pdf@0.2.12/src/core/draw/particle/TextParticle.ts","/npm/canvas-editor-pdf@0.2.12/src/dataset/constant/PageNumber.ts","/npm/canvas-editor-pdf@0.2.12/src/core/draw/frame/PageNumber.ts","/npm/canvas-editor-pdf@0.2.12/src/core/draw/particle/table/TableParticle.ts","/npm/canvas-editor-pdf@0.2.12/src/core/draw/particle/HyperlinkParticle.ts","/npm/canvas-editor-pdf@0.2.12/src/core/draw/frame/Header.ts","/npm/canvas-editor-pdf@0.2.12/src/core/draw/particle/Superscript.ts","/npm/canvas-editor-pdf@0.2.12/src/core/draw/particle/Subscript.ts","/npm/canvas-editor-pdf@0.2.12/src/core/draw/particle/Separator.ts","/npm/canvas-editor-pdf@0.2.12/src/dataset/enum/Watermark.ts","/npm/canvas-editor-pdf@0.2.12/src/core/draw/frame/Watermark.ts","/npm/canvas-editor-pdf@0.2.12/src/core/draw/particle/CheckboxParticle.ts"],"names":[],"mappings":"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","file":"/npm/canvas-editor-pdf@0.2.12/dist/canvas-editor-pdf.umd.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/canvas-editor-pdf@0.2.12/dist/canvas-editor-pdf.umd.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","import { ZERO } from './Common'\r\n\r\nexport const NUMBER_REG = /[0-9]/\r\nexport const NUMBER_LIKE_REG = /[0-9.]/\r\nexport const CHINESE_REG = /[\\u4e00-\\u9fa5]/\r\nexport const SURROGATE_PAIR_REG = /[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/ // unicode代理对（surrogate pair）\r\n// https://github.com/mathiasbynens/emoji-test-regex-pattern\r\nexport const EMOJI_REG =\r\n  /[#*0-9]\\uFE0F?\\u20E3|[\\xA9\\xAE\\u203C\\u2049\\u2122\\u2139\\u2194-\\u2199\\u21A9\\u21AA\\u231A\\u231B\\u2328\\u23CF\\u23ED-\\u23EF\\u23F1\\u23F2\\u23F8-\\u23FA\\u24C2\\u25AA\\u25AB\\u25B6\\u25C0\\u25FB\\u25FC\\u25FE\\u2600-\\u2604\\u260E\\u2611\\u2614\\u2615\\u2618\\u2620\\u2622\\u2623\\u2626\\u262A\\u262E\\u262F\\u2638-\\u263A\\u2640\\u2642\\u2648-\\u2653\\u265F\\u2660\\u2663\\u2665\\u2666\\u2668\\u267B\\u267E\\u267F\\u2692\\u2694-\\u2697\\u2699\\u269B\\u269C\\u26A0\\u26A7\\u26AA\\u26B0\\u26B1\\u26BD\\u26BE\\u26C4\\u26C8\\u26CF\\u26D1\\u26E9\\u26F0-\\u26F5\\u26F7\\u26F8\\u26FA\\u2702\\u2708\\u2709\\u270F\\u2712\\u2714\\u2716\\u271D\\u2721\\u2733\\u2734\\u2744\\u2747\\u2757\\u2763\\u27A1\\u2934\\u2935\\u2B05-\\u2B07\\u2B1B\\u2B1C\\u2B55\\u3030\\u303D\\u3297\\u3299]\\uFE0F?|[\\u261D\\u270C\\u270D](?:\\uFE0F|\\uD83C[\\uDFFB-\\uDFFF])?|[\\u270A\\u270B](?:\\uD83C[\\uDFFB-\\uDFFF])?|[\\u23E9-\\u23EC\\u23F0\\u23F3\\u25FD\\u2693\\u26A1\\u26AB\\u26C5\\u26CE\\u26D4\\u26EA\\u26FD\\u2705\\u2728\\u274C\\u274E\\u2753-\\u2755\\u2795-\\u2797\\u27B0\\u27BF\\u2B50]|\\u26D3\\uFE0F?(?:\\u200D\\uD83D\\uDCA5)?|\\u26F9(?:\\uFE0F|\\uD83C[\\uDFFB-\\uDFFF])?(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|\\u2764\\uFE0F?(?:\\u200D(?:\\uD83D\\uDD25|\\uD83E\\uDE79))?|\\uD83C(?:[\\uDC04\\uDD70\\uDD71\\uDD7E\\uDD7F\\uDE02\\uDE37\\uDF21\\uDF24-\\uDF2C\\uDF36\\uDF7D\\uDF96\\uDF97\\uDF99-\\uDF9B\\uDF9E\\uDF9F\\uDFCD\\uDFCE\\uDFD4-\\uDFDF\\uDFF5\\uDFF7]\\uFE0F?|[\\uDF85\\uDFC2\\uDFC7](?:\\uD83C[\\uDFFB-\\uDFFF])?|[\\uDFC4\\uDFCA](?:\\uD83C[\\uDFFB-\\uDFFF])?(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|[\\uDFCB\\uDFCC](?:\\uFE0F|\\uD83C[\\uDFFB-\\uDFFF])?(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|[\\uDCCF\\uDD8E\\uDD91-\\uDD9A\\uDE01\\uDE1A\\uDE2F\\uDE32-\\uDE36\\uDE38-\\uDE3A\\uDE50\\uDE51\\uDF00-\\uDF20\\uDF2D-\\uDF35\\uDF37-\\uDF43\\uDF45-\\uDF4A\\uDF4C-\\uDF7C\\uDF7E-\\uDF84\\uDF86-\\uDF93\\uDFA0-\\uDFC1\\uDFC5\\uDFC6\\uDFC8\\uDFC9\\uDFCF-\\uDFD3\\uDFE0-\\uDFF0\\uDFF8-\\uDFFF]|\\uDDE6\\uD83C[\\uDDE8-\\uDDEC\\uDDEE\\uDDF1\\uDDF2\\uDDF4\\uDDF6-\\uDDFA\\uDDFC\\uDDFD\\uDDFF]|\\uDDE7\\uD83C[\\uDDE6\\uDDE7\\uDDE9-\\uDDEF\\uDDF1-\\uDDF4\\uDDF6-\\uDDF9\\uDDFB\\uDDFC\\uDDFE\\uDDFF]|\\uDDE8\\uD83C[\\uDDE6\\uDDE8\\uDDE9\\uDDEB-\\uDDEE\\uDDF0-\\uDDF5\\uDDF7\\uDDFA-\\uDDFF]|\\uDDE9\\uD83C[\\uDDEA\\uDDEC\\uDDEF\\uDDF0\\uDDF2\\uDDF4\\uDDFF]|\\uDDEA\\uD83C[\\uDDE6\\uDDE8\\uDDEA\\uDDEC\\uDDED\\uDDF7-\\uDDFA]|\\uDDEB\\uD83C[\\uDDEE-\\uDDF0\\uDDF2\\uDDF4\\uDDF7]|\\uDDEC\\uD83C[\\uDDE6\\uDDE7\\uDDE9-\\uDDEE\\uDDF1-\\uDDF3\\uDDF5-\\uDDFA\\uDDFC\\uDDFE]|\\uDDED\\uD83C[\\uDDF0\\uDDF2\\uDDF3\\uDDF7\\uDDF9\\uDDFA]|\\uDDEE\\uD83C[\\uDDE8-\\uDDEA\\uDDF1-\\uDDF4\\uDDF6-\\uDDF9]|\\uDDEF\\uD83C[\\uDDEA\\uDDF2\\uDDF4\\uDDF5]|\\uDDF0\\uD83C[\\uDDEA\\uDDEC-\\uDDEE\\uDDF2\\uDDF3\\uDDF5\\uDDF7\\uDDFC\\uDDFE\\uDDFF]|\\uDDF1\\uD83C[\\uDDE6-\\uDDE8\\uDDEE\\uDDF0\\uDDF7-\\uDDFB\\uDDFE]|\\uDDF2\\uD83C[\\uDDE6\\uDDE8-\\uDDED\\uDDF0-\\uDDFF]|\\uDDF3\\uD83C[\\uDDE6\\uDDE8\\uDDEA-\\uDDEC\\uDDEE\\uDDF1\\uDDF4\\uDDF5\\uDDF7\\uDDFA\\uDDFF]|\\uDDF4\\uD83C\\uDDF2|\\uDDF5\\uD83C[\\uDDE6\\uDDEA-\\uDDED\\uDDF0-\\uDDF3\\uDDF7-\\uDDF9\\uDDFC\\uDDFE]|\\uDDF6\\uD83C\\uDDE6|\\uDDF7\\uD83C[\\uDDEA\\uDDF4\\uDDF8\\uDDFA\\uDDFC]|\\uDDF8\\uD83C[\\uDDE6-\\uDDEA\\uDDEC-\\uDDF4\\uDDF7-\\uDDF9\\uDDFB\\uDDFD-\\uDDFF]|\\uDDF9\\uD83C[\\uDDE6\\uDDE8\\uDDE9\\uDDEB-\\uDDED\\uDDEF-\\uDDF4\\uDDF7\\uDDF9\\uDDFB\\uDDFC\\uDDFF]|\\uDDFA\\uD83C[\\uDDE6\\uDDEC\\uDDF2\\uDDF3\\uDDF8\\uDDFE\\uDDFF]|\\uDDFB\\uD83C[\\uDDE6\\uDDE8\\uDDEA\\uDDEC\\uDDEE\\uDDF3\\uDDFA]|\\uDDFC\\uD83C[\\uDDEB\\uDDF8]|\\uDDFD\\uD83C\\uDDF0|\\uDDFE\\uD83C[\\uDDEA\\uDDF9]|\\uDDFF\\uD83C[\\uDDE6\\uDDF2\\uDDFC]|\\uDF44(?:\\u200D\\uD83D\\uDFEB)?|\\uDF4B(?:\\u200D\\uD83D\\uDFE9)?|\\uDFC3(?:\\uD83C[\\uDFFB-\\uDFFF])?(?:\\u200D(?:[\\u2640\\u2642]\\uFE0F?(?:\\u200D\\u27A1\\uFE0F?)?|\\u27A1\\uFE0F?))?|\\uDFF3\\uFE0F?(?:\\u200D(?:\\u26A7\\uFE0F?|\\uD83C\\uDF08))?|\\uDFF4(?:\\u200D\\u2620\\uFE0F?|\\uDB40\\uDC67\\uDB40\\uDC62\\uDB40(?:\\uDC65\\uDB40\\uDC6E\\uDB40\\uDC67|\\uDC73\\uDB40\\uDC63\\uDB40\\uDC74|\\uDC77\\uDB40\\uDC6C\\uDB40\\uDC73)\\uDB40\\uDC7F)?)|\\uD83D(?:[\\uDC3F\\uDCFD\\uDD49\\uDD4A\\uDD6F\\uDD70\\uDD73\\uDD76-\\uDD79\\uDD87\\uDD8A-\\uDD8D\\uDDA5\\uDDA8\\uDDB1\\uDDB2\\uDDBC\\uDDC2-\\uDDC4\\uDDD1-\\uDDD3\\uDDDC-\\uDDDE\\uDDE1\\uDDE3\\uDDE8\\uDDEF\\uDDF3\\uDDFA\\uDECB\\uDECD-\\uDECF\\uDEE0-\\uDEE5\\uDEE9\\uDEF0\\uDEF3]\\uFE0F?|[\\uDC42\\uDC43\\uDC46-\\uDC50\\uDC66\\uDC67\\uDC6B-\\uDC6D\\uDC72\\uDC74-\\uDC76\\uDC78\\uDC7C\\uDC83\\uDC85\\uDC8F\\uDC91\\uDCAA\\uDD7A\\uDD95\\uDD96\\uDE4C\\uDE4F\\uDEC0\\uDECC](?:\\uD83C[\\uDFFB-\\uDFFF])?|[\\uDC6E\\uDC70\\uDC71\\uDC73\\uDC77\\uDC81\\uDC82\\uDC86\\uDC87\\uDE45-\\uDE47\\uDE4B\\uDE4D\\uDE4E\\uDEA3\\uDEB4\\uDEB5](?:\\uD83C[\\uDFFB-\\uDFFF])?(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|[\\uDD74\\uDD90](?:\\uFE0F|\\uD83C[\\uDFFB-\\uDFFF])?|[\\uDC00-\\uDC07\\uDC09-\\uDC14\\uDC16-\\uDC25\\uDC27-\\uDC3A\\uDC3C-\\uDC3E\\uDC40\\uDC44\\uDC45\\uDC51-\\uDC65\\uDC6A\\uDC79-\\uDC7B\\uDC7D-\\uDC80\\uDC84\\uDC88-\\uDC8E\\uDC90\\uDC92-\\uDCA9\\uDCAB-\\uDCFC\\uDCFF-\\uDD3D\\uDD4B-\\uDD4E\\uDD50-\\uDD67\\uDDA4\\uDDFB-\\uDE2D\\uDE2F-\\uDE34\\uDE37-\\uDE41\\uDE43\\uDE44\\uDE48-\\uDE4A\\uDE80-\\uDEA2\\uDEA4-\\uDEB3\\uDEB7-\\uDEBF\\uDEC1-\\uDEC5\\uDED0-\\uDED2\\uDED5-\\uDED7\\uDEDC-\\uDEDF\\uDEEB\\uDEEC\\uDEF4-\\uDEFC\\uDFE0-\\uDFEB\\uDFF0]|\\uDC08(?:\\u200D\\u2B1B)?|\\uDC15(?:\\u200D\\uD83E\\uDDBA)?|\\uDC26(?:\\u200D(?:\\u2B1B|\\uD83D\\uDD25))?|\\uDC3B(?:\\u200D\\u2744\\uFE0F?)?|\\uDC41\\uFE0F?(?:\\u200D\\uD83D\\uDDE8\\uFE0F?)?|\\uDC68(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:\\uDC8B\\u200D\\uD83D)?\\uDC68|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D(?:[\\uDC68\\uDC69]\\u200D\\uD83D(?:\\uDC66(?:\\u200D\\uD83D\\uDC66)?|\\uDC67(?:\\u200D\\uD83D[\\uDC66\\uDC67])?)|[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uDC66(?:\\u200D\\uD83D\\uDC66)?|\\uDC67(?:\\u200D\\uD83D[\\uDC66\\uDC67])?)|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]))|\\uD83C(?:\\uDFFB(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:\\uDC8B\\u200D\\uD83D)?\\uDC68\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D\\uDC68\\uD83C[\\uDFFC-\\uDFFF])))?|\\uDFFC(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:\\uDC8B\\u200D\\uD83D)?\\uDC68\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D\\uDC68\\uD83C[\\uDFFB\\uDFFD-\\uDFFF])))?|\\uDFFD(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:\\uDC8B\\u200D\\uD83D)?\\uDC68\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D\\uDC68\\uD83C[\\uDFFB\\uDFFC\\uDFFE\\uDFFF])))?|\\uDFFE(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:\\uDC8B\\u200D\\uD83D)?\\uDC68\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D\\uDC68\\uD83C[\\uDFFB-\\uDFFD\\uDFFF])))?|\\uDFFF(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:\\uDC8B\\u200D\\uD83D)?\\uDC68\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D\\uDC68\\uD83C[\\uDFFB-\\uDFFE])))?))?|\\uDC69(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:\\uDC8B\\u200D\\uD83D)?[\\uDC68\\uDC69]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D(?:[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uDC66(?:\\u200D\\uD83D\\uDC66)?|\\uDC67(?:\\u200D\\uD83D[\\uDC66\\uDC67])?|\\uDC69\\u200D\\uD83D(?:\\uDC66(?:\\u200D\\uD83D\\uDC66)?|\\uDC67(?:\\u200D\\uD83D[\\uDC66\\uDC67])?))|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]))|\\uD83C(?:\\uDFFB(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:[\\uDC68\\uDC69]|\\uDC8B\\u200D\\uD83D[\\uDC68\\uDC69])\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D[\\uDC68\\uDC69]\\uD83C[\\uDFFC-\\uDFFF])))?|\\uDFFC(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:[\\uDC68\\uDC69]|\\uDC8B\\u200D\\uD83D[\\uDC68\\uDC69])\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D[\\uDC68\\uDC69]\\uD83C[\\uDFFB\\uDFFD-\\uDFFF])))?|\\uDFFD(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:[\\uDC68\\uDC69]|\\uDC8B\\u200D\\uD83D[\\uDC68\\uDC69])\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D[\\uDC68\\uDC69]\\uD83C[\\uDFFB\\uDFFC\\uDFFE\\uDFFF])))?|\\uDFFE(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:[\\uDC68\\uDC69]|\\uDC8B\\u200D\\uD83D[\\uDC68\\uDC69])\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D[\\uDC68\\uDC69]\\uD83C[\\uDFFB-\\uDFFD\\uDFFF])))?|\\uDFFF(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:[\\uDC68\\uDC69]|\\uDC8B\\u200D\\uD83D[\\uDC68\\uDC69])\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D[\\uDC68\\uDC69]\\uD83C[\\uDFFB-\\uDFFE])))?))?|\\uDC6F(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|\\uDD75(?:\\uFE0F|\\uD83C[\\uDFFB-\\uDFFF])?(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|\\uDE2E(?:\\u200D\\uD83D\\uDCA8)?|\\uDE35(?:\\u200D\\uD83D\\uDCAB)?|\\uDE36(?:\\u200D\\uD83C\\uDF2B\\uFE0F?)?|\\uDE42(?:\\u200D[\\u2194\\u2195]\\uFE0F?)?|\\uDEB6(?:\\uD83C[\\uDFFB-\\uDFFF])?(?:\\u200D(?:[\\u2640\\u2642]\\uFE0F?(?:\\u200D\\u27A1\\uFE0F?)?|\\u27A1\\uFE0F?))?)|\\uD83E(?:[\\uDD0C\\uDD0F\\uDD18-\\uDD1F\\uDD30-\\uDD34\\uDD36\\uDD77\\uDDB5\\uDDB6\\uDDBB\\uDDD2\\uDDD3\\uDDD5\\uDEC3-\\uDEC5\\uDEF0\\uDEF2-\\uDEF8](?:\\uD83C[\\uDFFB-\\uDFFF])?|[\\uDD26\\uDD35\\uDD37-\\uDD39\\uDD3D\\uDD3E\\uDDB8\\uDDB9\\uDDCD\\uDDCF\\uDDD4\\uDDD6-\\uDDDD](?:\\uD83C[\\uDFFB-\\uDFFF])?(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|[\\uDDDE\\uDDDF](?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|[\\uDD0D\\uDD0E\\uDD10-\\uDD17\\uDD20-\\uDD25\\uDD27-\\uDD2F\\uDD3A\\uDD3F-\\uDD45\\uDD47-\\uDD76\\uDD78-\\uDDB4\\uDDB7\\uDDBA\\uDDBC-\\uDDCC\\uDDD0\\uDDE0-\\uDDFF\\uDE70-\\uDE7C\\uDE80-\\uDE88\\uDE90-\\uDEBD\\uDEBF-\\uDEC2\\uDECE-\\uDEDB\\uDEE0-\\uDEE8]|\\uDD3C(?:\\u200D[\\u2640\\u2642]\\uFE0F?|\\uD83C[\\uDFFB-\\uDFFF])?|\\uDDCE(?:\\uD83C[\\uDFFB-\\uDFFF])?(?:\\u200D(?:[\\u2640\\u2642]\\uFE0F?(?:\\u200D\\u27A1\\uFE0F?)?|\\u27A1\\uFE0F?))?|\\uDDD1(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF84\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83E\\uDDD1|\\uDDD1\\u200D\\uD83E\\uDDD2(?:\\u200D\\uD83E\\uDDD2)?|\\uDDD2(?:\\u200D\\uD83E\\uDDD2)?))|\\uD83C(?:\\uDFFB(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D(?:\\uD83D\\uDC8B\\u200D)?\\uD83E\\uDDD1\\uD83C[\\uDFFC-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF84\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83E\\uDDD1\\uD83C[\\uDFFB-\\uDFFF])))?|\\uDFFC(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D(?:\\uD83D\\uDC8B\\u200D)?\\uD83E\\uDDD1\\uD83C[\\uDFFB\\uDFFD-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF84\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83E\\uDDD1\\uD83C[\\uDFFB-\\uDFFF])))?|\\uDFFD(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D(?:\\uD83D\\uDC8B\\u200D)?\\uD83E\\uDDD1\\uD83C[\\uDFFB\\uDFFC\\uDFFE\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF84\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83E\\uDDD1\\uD83C[\\uDFFB-\\uDFFF])))?|\\uDFFE(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D(?:\\uD83D\\uDC8B\\u200D)?\\uD83E\\uDDD1\\uD83C[\\uDFFB-\\uDFFD\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF84\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83E\\uDDD1\\uD83C[\\uDFFB-\\uDFFF])))?|\\uDFFF(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D(?:\\uD83D\\uDC8B\\u200D)?\\uD83E\\uDDD1\\uD83C[\\uDFFB-\\uDFFE]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF84\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83E\\uDDD1\\uD83C[\\uDFFB-\\uDFFF])))?))?|\\uDEF1(?:\\uD83C(?:\\uDFFB(?:\\u200D\\uD83E\\uDEF2\\uD83C[\\uDFFC-\\uDFFF])?|\\uDFFC(?:\\u200D\\uD83E\\uDEF2\\uD83C[\\uDFFB\\uDFFD-\\uDFFF])?|\\uDFFD(?:\\u200D\\uD83E\\uDEF2\\uD83C[\\uDFFB\\uDFFC\\uDFFE\\uDFFF])?|\\uDFFE(?:\\u200D\\uD83E\\uDEF2\\uD83C[\\uDFFB-\\uDFFD\\uDFFF])?|\\uDFFF(?:\\u200D\\uD83E\\uDEF2\\uD83C[\\uDFFB-\\uDFFE])?))?)/g\r\n\r\nexport const UNICODE_SYMBOL_REG = new RegExp(\r\n  `${EMOJI_REG.source}|${SURROGATE_PAIR_REG.source}`,\r\n  'g'\r\n)\r\n\r\nexport const PUNCTUATION_REG =\r\n  /[、，。？！；：……「」“”‘’*（）【】〔〕〖〗〘〙〚〛《》———﹝﹞–—\\\\/·.,!?;:`~<>()[\\]{}'\"|]/\r\n\r\nexport const START_LINE_BREAK_REG = new RegExp(`^[${ZERO}\\n]`)\r\n","import { UNICODE_SYMBOL_REG } from '../dataset/constant/Regular'\r\nimport { IElementFillRect } from '../interface/Element'\r\n\r\nexport function debounce<T extends unknown[]>(\r\n  func: (...arg: T) => unknown,\r\n  delay: number\r\n) {\r\n  let timer: number\r\n  return function (this: unknown, ...args: T) {\r\n    if (timer) {\r\n      window.clearTimeout(timer)\r\n    }\r\n    timer = window.setTimeout(() => {\r\n      func.apply(this, args)\r\n    }, delay)\r\n  }\r\n}\r\n\r\nexport function throttle<T extends unknown[]>(\r\n  func: (...arg: T) => unknown,\r\n  delay: number\r\n) {\r\n  let lastExecTime = 0\r\n  let timer: number\r\n  return function (this: unknown, ...args: T) {\r\n    const currentTime = Date.now()\r\n    if (currentTime - lastExecTime >= delay) {\r\n      window.clearTimeout(timer)\r\n      func.apply(this, args)\r\n      lastExecTime = currentTime\r\n    } else {\r\n      window.clearTimeout(timer)\r\n      timer = window.setTimeout(() => {\r\n        func.apply(this, args)\r\n        lastExecTime = currentTime\r\n      }, delay)\r\n    }\r\n  }\r\n}\r\n\r\nexport function deepCloneOmitKeys<T, K>(obj: T, omitKeys: (keyof K)[]): T {\r\n  if (!obj || typeof obj !== 'object') {\r\n    return obj\r\n  }\r\n  let newObj: any = {}\r\n  if (Array.isArray(obj)) {\r\n    newObj = obj.map(item => deepCloneOmitKeys(item, omitKeys))\r\n  } else {\r\n    // prettier-ignore\r\n    (Object.keys(obj) as (keyof K)[]).forEach(key => {\r\n      if (omitKeys.includes(key)) return\r\n      return (newObj[key] = deepCloneOmitKeys((obj[key as unknown as keyof T] ), omitKeys))\r\n    })\r\n  }\r\n  return newObj\r\n}\r\n\r\nexport function deepClone<T>(obj: T): T {\r\n  if (!obj || typeof obj !== 'object') {\r\n    return obj\r\n  }\r\n  let newObj: any = {}\r\n  if (Array.isArray(obj)) {\r\n    newObj = obj.map(item => deepClone(item))\r\n  } else {\r\n    // prettier-ignore\r\n    (Object.keys(obj) as (keyof T)[]).forEach(key => {\r\n      return (newObj[key] = deepClone(obj[key]))\r\n    })\r\n  }\r\n  return newObj\r\n}\r\n\r\nexport function isBody(node: Element): boolean {\r\n  return node && node.nodeType === 1 && node.tagName.toLowerCase() === 'body'\r\n}\r\n\r\nexport function findParent(\r\n  node: Element,\r\n  filterFn: Function,\r\n  includeSelf: boolean\r\n) {\r\n  if (node && !isBody(node)) {\r\n    node = includeSelf ? node : (node.parentNode as Element)\r\n    while (node) {\r\n      if (!filterFn || filterFn(node) || isBody(node)) {\r\n        return filterFn && !filterFn(node) && isBody(node) ? null : node\r\n      }\r\n      node = node.parentNode as Element\r\n    }\r\n  }\r\n  return null\r\n}\r\n\r\nexport function getUUID(): string {\r\n  function S4(): string {\r\n    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)\r\n  }\r\n  return (\r\n    S4() +\r\n    S4() +\r\n    '-' +\r\n    S4() +\r\n    '-' +\r\n    S4() +\r\n    '-' +\r\n    S4() +\r\n    '-' +\r\n    S4() +\r\n    S4() +\r\n    S4()\r\n  )\r\n}\r\n\r\nexport function splitText(text: string): string[] {\r\n  const data: string[] = []\r\n  if (Intl.Segmenter) {\r\n    const segmenter = new Intl.Segmenter()\r\n    const segments = segmenter.segment(text)\r\n    for (const { segment } of segments) {\r\n      data.push(segment)\r\n    }\r\n  } else {\r\n    const symbolMap = new Map<number, string>()\r\n    for (const match of text.matchAll(UNICODE_SYMBOL_REG)) {\r\n      symbolMap.set(match.index!, match[0])\r\n    }\r\n    let t = 0\r\n    while (t < text.length) {\r\n      const symbol = symbolMap.get(t)\r\n      if (symbol) {\r\n        data.push(symbol)\r\n        t += symbol.length\r\n      } else {\r\n        data.push(text[t])\r\n        t++\r\n      }\r\n    }\r\n  }\r\n  return data\r\n}\r\n\r\nexport function downloadFile(href: string, fileName: string) {\r\n  const a = document.createElement('a')\r\n  a.href = href\r\n  a.download = fileName\r\n  a.click()\r\n}\r\n\r\nexport function threeClick(dom: HTMLElement, fn: (evt: MouseEvent) => any) {\r\n  nClickEvent(3, dom, fn)\r\n}\r\n\r\nfunction nClickEvent(\r\n  n: number,\r\n  dom: HTMLElement,\r\n  fn: (evt: MouseEvent) => any\r\n) {\r\n  let count = 0\r\n  let lastTime = 0\r\n\r\n  const handler = function (evt: MouseEvent) {\r\n    const currentTime = new Date().getTime()\r\n    count = currentTime - lastTime < 300 ? count + 1 : 0\r\n    lastTime = new Date().getTime()\r\n    if (count >= n - 1) {\r\n      fn(evt)\r\n      count = 0\r\n    }\r\n  }\r\n\r\n  dom.addEventListener('click', handler)\r\n}\r\n\r\nexport function isObject(type: unknown): type is Record<string, unknown> {\r\n  return Object.prototype.toString.call(type) === '[object Object]'\r\n}\r\n\r\nexport function isArray(type: unknown): type is Array<unknown> {\r\n  return Array.isArray(type)\r\n}\r\n\r\nexport function mergeObject<T>(source: T, target: T): T {\r\n  if (isObject(source) && isObject(target)) {\r\n    const objectTarget = <Record<string, unknown>>target\r\n    for (const [key, val] of Object.entries(source)) {\r\n      if (!objectTarget[key]) {\r\n        objectTarget[key] = val\r\n      } else {\r\n        objectTarget[key] = mergeObject(val, objectTarget[key])\r\n      }\r\n    }\r\n  } else if (isArray(source) && isArray(target)) {\r\n    target.push(...source)\r\n  }\r\n  return target\r\n}\r\n\r\nexport function nextTick(fn: Function) {\r\n  setTimeout(() => {\r\n    fn()\r\n  }, 0)\r\n}\r\n\r\nexport function convertNumberToChinese(num: number) {\r\n  const chineseNum = [\r\n    '零',\r\n    '一',\r\n    '二',\r\n    '三',\r\n    '四',\r\n    '五',\r\n    '六',\r\n    '七',\r\n    '八',\r\n    '九'\r\n  ]\r\n  const chineseUnit = [\r\n    '',\r\n    '十',\r\n    '百',\r\n    '千',\r\n    '万',\r\n    '十',\r\n    '百',\r\n    '千',\r\n    '亿',\r\n    '十',\r\n    '百',\r\n    '千',\r\n    '万',\r\n    '十',\r\n    '百',\r\n    '千',\r\n    '亿'\r\n  ]\r\n  if (!num || isNaN(num)) return '零'\r\n  const numStr = num.toString().split('')\r\n  let result = ''\r\n  for (let i = 0; i < numStr.length; i++) {\r\n    const desIndex = numStr.length - 1 - i\r\n    result = `${chineseUnit[i]}${result}`\r\n    result = `${chineseNum[Number(numStr[desIndex])]}${result}`\r\n  }\r\n  result = result.replace(/零(千|百|十)/g, '零').replace(/十零/g, '十')\r\n  result = result.replace(/零+/g, '零')\r\n  result = result.replace(/零亿/g, '亿').replace(/零万/g, '万')\r\n  result = result.replace(/亿万/g, '亿')\r\n  result = result.replace(/零+$/, '')\r\n  result = result.replace(/^一十/g, '十')\r\n  return result\r\n}\r\n\r\nexport function cloneProperty<T>(\r\n  properties: (keyof T)[],\r\n  sourceElement: T,\r\n  targetElement: T\r\n) {\r\n  for (let i = 0; i < properties.length; i++) {\r\n    const property = properties[i]\r\n    const value = sourceElement[property]\r\n    if (value !== undefined) {\r\n      targetElement[property] = value\r\n    } else {\r\n      delete targetElement[property]\r\n    }\r\n  }\r\n}\r\n\r\nexport function pickObject<T>(object: T, pickKeys: (keyof T)[]): T {\r\n  const newObject: T = <T>{}\r\n  for (const key in object) {\r\n    if (pickKeys.includes(key)) {\r\n      newObject[key] = object[key]\r\n    }\r\n  }\r\n  return newObject\r\n}\r\n\r\nexport function omitObject<T>(object: T, omitKeys: (keyof T)[]): T {\r\n  const newObject: T = <T>{}\r\n  for (const key in object) {\r\n    if (!omitKeys.includes(key)) {\r\n      newObject[key] = object[key]\r\n    }\r\n  }\r\n  return newObject\r\n}\r\n\r\nexport function convertStringToBase64(input: string) {\r\n  const encoder = new TextEncoder()\r\n  const data = encoder.encode(input)\r\n  const charArray = Array.from(data, byte => String.fromCharCode(byte))\r\n  const base64 = window.btoa(charArray.join(''))\r\n  return base64\r\n}\r\n\r\nexport function findScrollContainer(element: HTMLElement) {\r\n  let parent = element.parentElement\r\n  while (parent) {\r\n    const style = window.getComputedStyle(parent)\r\n    const overflowY = style.getPropertyValue('overflow-y')\r\n    if (\r\n      parent.scrollHeight > parent.clientHeight &&\r\n      (overflowY === 'auto' || overflowY === 'scroll')\r\n    ) {\r\n      return parent\r\n    }\r\n    parent = parent.parentElement\r\n  }\r\n  return document.documentElement\r\n}\r\n\r\nexport function isArrayEqual(arr1: unknown[], arr2: unknown[]): boolean {\r\n  if (arr1.length !== arr2.length) {\r\n    return false\r\n  }\r\n  return !arr1.some(item => !arr2.includes(item))\r\n}\r\n\r\nexport function isObjectEqual(obj1: unknown, obj2: unknown): boolean {\r\n  if (!isObject(obj1) || !isObject(obj2)) return false\r\n  const obj1Keys = Object.keys(obj1)\r\n  const obj2Keys = Object.keys(obj2)\r\n  if (obj1Keys.length !== obj2Keys.length) {\r\n    return false\r\n  }\r\n  return !obj1Keys.some(key => obj2[key] !== obj1[key])\r\n}\r\n\r\nexport function isRectIntersect(\r\n  rect1: IElementFillRect,\r\n  rect2: IElementFillRect\r\n): boolean {\r\n  const rect1Left = rect1.x\r\n  const rect1Right = rect1.x + rect1.width\r\n  const rect1Top = rect1.y\r\n  const rect1Bottom = rect1.y + rect1.height\r\n  const rect2Left = rect2.x\r\n  const rect2Right = rect2.x + rect2.width\r\n  const rect2Top = rect2.y\r\n  const rect2Bottom = rect2.y + rect2.height\r\n  if (\r\n    rect1Left > rect2Right ||\r\n    rect1Right < rect2Left ||\r\n    rect1Top > rect2Bottom ||\r\n    rect1Bottom < rect2Top\r\n  ) {\r\n    return false\r\n  }\r\n  return true\r\n}\r\n","export enum ControlType {\r\n  TEXT = 'text',\r\n  SELECT = 'select',\r\n  CHECKBOX = 'checkbox',\r\n  RADIO = 'radio',\r\n  DATE = 'date'\r\n}\r\n\r\nexport enum ControlComponent {\r\n  PREFIX = 'prefix',\r\n  POSTFIX = 'postfix',\r\n  PLACEHOLDER = 'placeholder',\r\n  VALUE = 'value',\r\n  CHECKBOX = 'checkbox',\r\n  RADIO = 'radio'\r\n}\r\n\r\n// 控件内容缩进方式\r\nexport enum ControlIndentation {\r\n  ROW_START = 'rowStart', // 从行起始位置缩进\r\n  VALUE_START = 'valueStart' // 从值起始位置缩进\r\n}\r\n","import { Context2d } from 'jspdf'\r\nimport { EDITOR_PREFIX } from '../../../dataset/constant/Editor'\r\nimport { ImageDisplay } from '../../../dataset/enum/Common'\r\nimport { IEditorOption } from '../../../interface/Editor'\r\nimport { IElement } from '../../../interface/Element'\r\nimport { convertStringToBase64 } from '../../../utils'\r\nimport { DrawPdf } from '../DrawPdf'\r\n\r\nexport class ImageParticle {\r\n  protected draw: DrawPdf\r\n  protected options: Required<IEditorOption>\r\n  protected imageCache: Map<string, HTMLImageElement>\r\n  // private container: HTMLDivElement\r\n  private floatImageContainer: HTMLDivElement | null\r\n  private floatImage: HTMLImageElement | null\r\n\r\n  constructor(draw: DrawPdf) {\r\n    this.draw = draw\r\n    this.options = draw.getOptions()\r\n    // this.container = draw.getContainer()\r\n    this.imageCache = new Map()\r\n    this.floatImageContainer = null\r\n    this.floatImage = null\r\n  }\r\n\r\n  public createFloatImage(element: IElement) {\r\n    const { scale } = this.options\r\n    // 复用浮动元素\r\n    let floatImageContainer = this.floatImageContainer\r\n    let floatImage = this.floatImage\r\n    if (!floatImageContainer) {\r\n      floatImageContainer = document.createElement('div')\r\n      floatImageContainer.classList.add(`${EDITOR_PREFIX}-float-image`)\r\n      // this.container.append(floatImageContainer)\r\n      this.floatImageContainer = floatImageContainer\r\n    }\r\n    if (!floatImage) {\r\n      floatImage = document.createElement('img')\r\n      floatImageContainer.append(floatImage)\r\n      this.floatImage = floatImage\r\n    }\r\n    floatImageContainer.style.display = 'none'\r\n    floatImage.style.width = `${element.width! * scale}px`\r\n    floatImage.style.height = `${element.height! * scale}px`\r\n    // 浮动图片初始信息\r\n    const height = this.draw.getHeight()\r\n    const pageGap = this.draw.getPageGap()\r\n    const preY = this.draw.getPageNo() * (height + pageGap)\r\n    const imgFloatPosition = element.imgFloatPosition!\r\n    floatImageContainer.style.left = `${imgFloatPosition.x}px`\r\n    floatImageContainer.style.top = `${preY + imgFloatPosition.y}px`\r\n    floatImage.src = element.value\r\n  }\r\n\r\n  public dragFloatImage(movementX: number, movementY: number) {\r\n    if (!this.floatImageContainer) return\r\n    this.floatImageContainer.style.display = 'block'\r\n    // 之前的坐标加移动长度\r\n    const x = parseFloat(this.floatImageContainer.style.left) + movementX\r\n    const y = parseFloat(this.floatImageContainer.style.top) + movementY\r\n    this.floatImageContainer.style.left = `${x}px`\r\n    this.floatImageContainer.style.top = `${y}px`\r\n  }\r\n\r\n  public destroyFloatImage() {\r\n    if (this.floatImageContainer) {\r\n      this.floatImageContainer.style.display = 'none'\r\n    }\r\n  }\r\n\r\n  protected addImageObserver(promise: Promise<unknown>) {\r\n    this.draw.getImageObserver().add(promise)\r\n  }\r\n\r\n  protected getFallbackImage(width: number, height: number): HTMLImageElement {\r\n    const tileSize = 8\r\n    const x = (width - Math.ceil(width / tileSize) * tileSize) / 2\r\n    const y = (height - Math.ceil(height / tileSize) * tileSize) / 2\r\n    const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"0 0 ${width} ${height}\">\r\n                  <rect width=\"${width}\" height=\"${height}\" fill=\"url(#mosaic)\" />\r\n                  <defs>\r\n                    <pattern id=\"mosaic\" x=\"${x}\" y=\"${y}\" width=\"${tileSize * 2\r\n      }\" height=\"${tileSize * 2}\" patternUnits=\"userSpaceOnUse\">\r\n                      <rect width=\"${tileSize}\" height=\"${tileSize}\" fill=\"#cccccc\" />\r\n                      <rect width=\"${tileSize}\" height=\"${tileSize}\" fill=\"#cccccc\" transform=\"translate(${tileSize}, ${tileSize})\" />\r\n                    </pattern>\r\n                  </defs>\r\n                </svg>`\r\n    const fallbackImage = new Image()\r\n    fallbackImage.src = `data:image/svg+xml;base64,${convertStringToBase64(\r\n      svg\r\n    )}`\r\n    return fallbackImage\r\n  }\r\n\r\n  public render(\r\n    ctx2d: Context2d,\r\n    element: IElement,\r\n    x: number,\r\n    y: number\r\n  ) {\r\n    // 衬于文字下方图片需要重新首先绘制\r\n    if (element.imgDisplay === ImageDisplay.FLOAT_BOTTOM) {\r\n      this.draw.render({\r\n        isCompute: false,\r\n        isSetCursor: false,\r\n        isSubmitHistory: false\r\n      })\r\n    } else {\r\n      const { scale } = this.options\r\n      const width = element.width! * scale\r\n      const height = element.height! * scale\r\n      ctx2d.drawImage(element.value, x, y, width, height)\r\n    }\r\n  }\r\n}\r\n\r\nexport function svgString2Image(svgString: string, width: number, height: number, format: string, callback: { (pngData: any): void; (arg0: string): void }) {\r\n  return new Promise((resolve) => {\r\n    // set default for format parameter\r\n    format = format ? format : 'png'\r\n    // SVG data URL from SVG string\r\n    const svgData = svgString//'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svgString)))\r\n    // create canvas in memory(not in DOM)\r\n    const canvas = document.createElement('canvas')\r\n    // get canvas context for drawing on canvas\r\n    const context = canvas.getContext('2d')\r\n    // set canvas size\r\n    canvas.width = width\r\n    canvas.height = height\r\n    // create image in memory(not in DOM)\r\n    const image = new Image()\r\n    // later when image loads run this\r\n    image.onload = function () { // async (happens later)\r\n      if (context) {\r\n        // clear canvas\r\n        context.clearRect(0, 0, width, height)\r\n        // draw image with SVG data to canvas\r\n        context.drawImage(image, 0, 0, width, height)\r\n        // snapshot canvas as png\r\n        const pngData = canvas.toDataURL('image/' + format)\r\n        // pass png data URL to callback\r\n        resolve(pngData)\r\n        callback(pngData)\r\n      }\r\n    } // end async\r\n    // start loading SVG data into in memory image\r\n    image.src = svgData\r\n  })\r\n}","import { HERSHEY } from './hershey'\r\nimport { SYMB, Symb, asciiMap } from './symbols'\r\n\r\nconst CONFIG: Record<string, number> = {\r\n  SUB_SUP_SCALE: 0.5,\r\n  SQRT_MAG_SCALE: 0.5,\r\n  FRAC_SCALE: 0.85,\r\n  LINE_SPACING: 0.5,\r\n  FRAC_SPACING: 0.4\r\n}\r\n\r\nfunction tokenize(str: string): string[] {\r\n  str = str.replace(/\\n/g, ' ')\r\n  let i = 0\r\n  const tokens: string[] = []\r\n  let curr = ''\r\n  while (i < str.length) {\r\n    if (str[i] == ' ') {\r\n      if (curr.length) {\r\n        tokens.push(curr)\r\n        curr = ''\r\n      }\r\n    } else if (str[i] == '\\\\') {\r\n      if (curr.length == 1 && curr[0] == '\\\\') {\r\n        curr += str[i]\r\n        tokens.push(curr)\r\n        curr = ''\r\n      } else {\r\n        if (curr.length) {\r\n          tokens.push(curr)\r\n        }\r\n        curr = str[i]\r\n      }\r\n    } else if (/[A-Za-z0-9\\.]/.test(str[i])) {\r\n      curr += str[i]\r\n    } else {\r\n      if (curr.length && curr != '\\\\') {\r\n        tokens.push(curr)\r\n        curr = ''\r\n      }\r\n      curr += str[i]\r\n      tokens.push(curr)\r\n      curr = ''\r\n    }\r\n    i++\r\n  }\r\n  if (curr.length) tokens.push(curr)\r\n  return tokens\r\n}\r\n\r\ninterface Bbox {\r\n  x: number\r\n  y: number\r\n  w: number\r\n  h: number\r\n}\r\n\r\ninterface Expr {\r\n  type: string\r\n  text: string\r\n  mode: string\r\n  chld: Expr[]\r\n  bbox: Bbox\r\n}\r\n\r\nfunction parseAtom(x: string): Expr {\r\n  return {\r\n    type: SYMB[x] ? 'symb' : 'char',\r\n    mode: 'math',\r\n    text: x,\r\n    chld: [],\r\n    // @ts-ignore\r\n    bbox: null\r\n  }\r\n}\r\n\r\nfunction parse(tokens: string[]): Expr {\r\n  let i = 0\r\n  let expr: Expr = {\r\n    type: 'node',\r\n    text: '',\r\n    mode: 'math',\r\n    chld: [],\r\n    // @ts-ignore\r\n    bbox: null\r\n  }\r\n\r\n  function takeOpt(): Expr | null {\r\n    if (tokens[i] != '[') {\r\n      return null\r\n    }\r\n    let lvl = 0\r\n    let j = i\r\n    while (j < tokens.length) {\r\n      if (tokens[j] == '[') {\r\n        lvl++\r\n      } else if (tokens[j] == ']') {\r\n        lvl--\r\n        if (!lvl) {\r\n          break\r\n        }\r\n      }\r\n      j++\r\n    }\r\n    const ret: Expr = parse(tokens.slice(i + 1, j))\r\n    i = j\r\n    return ret\r\n  }\r\n\r\n  function takeN(n: number): Expr[] {\r\n    let j: number = i\r\n    let j0: number = j\r\n    let lvl = 0\r\n    let cnt = 0\r\n    const ret: Expr[] = []\r\n    while (j < tokens.length) {\r\n      if (tokens[j] == '{') {\r\n        if (!lvl) {\r\n          j0 = j\r\n        }\r\n        lvl++\r\n      } else if (tokens[j] == '}') {\r\n        lvl--\r\n        if (!lvl) {\r\n          ret.push(parse(tokens.slice(j0 + 1, j)))\r\n          cnt++\r\n          if (cnt == n) {\r\n            break\r\n          }\r\n        }\r\n      } else {\r\n        if (lvl == 0) {\r\n          ret.push(parseAtom(tokens[j]))\r\n          cnt++\r\n          if (cnt == n) {\r\n            break\r\n          }\r\n        }\r\n      }\r\n      j++\r\n    }\r\n    i = j\r\n    return ret\r\n  }\r\n\r\n  for (i = 0; i < tokens.length; i++) {\r\n    const s: Symb = SYMB[tokens[i]]\r\n    const e: Expr = {\r\n      type: '',\r\n      text: tokens[i],\r\n      mode: 'math',\r\n      chld: [],\r\n      // @ts-ignore\r\n      bbox: null\r\n    }\r\n    if (s) {\r\n      if (s.arity) {\r\n        i++\r\n        e.type = 'func'\r\n        let opt: Expr | null = null\r\n        if (s.flags.opt) {\r\n          opt = takeOpt()\r\n          if (opt) i++\r\n        }\r\n        const chld: Expr[] = takeN(s.arity)\r\n        e.chld = chld\r\n        if (opt) {\r\n          e.chld.push(opt)\r\n        }\r\n      } else {\r\n        e.type = 'symb'\r\n      }\r\n    } else {\r\n      if (tokens[i] == '{') {\r\n        e.type = 'node'\r\n        e.text = ''\r\n        e.chld = takeN(1)\r\n      } else {\r\n        e.type = 'char'\r\n      }\r\n    }\r\n    expr.chld.push(e)\r\n  }\r\n  if (expr.chld.length == 1) {\r\n    expr = expr.chld[0]\r\n  }\r\n  return expr\r\n}\r\n\r\nfunction environments(exprs: Expr[]) {\r\n  let i = 0\r\n  while (i < exprs.length) {\r\n    if (exprs[i].text == '\\\\begin') {\r\n      let j: number\r\n      for (j = i; j < exprs.length; j++) {\r\n        if (exprs[j].text == '\\\\end') {\r\n          break\r\n        }\r\n      }\r\n      const es: Expr[] = exprs.splice(i + 1, j - (i + 1))\r\n      environments(es)\r\n      exprs[i].text = exprs[i].chld[0].text\r\n      exprs[i].chld = es\r\n      exprs.splice(i + 1, 1)\r\n    }\r\n    i++\r\n  }\r\n}\r\n\r\nfunction transform(\r\n  expr: Expr,\r\n  sclx: number,\r\n  scly: number,\r\n  x: number,\r\n  y: number,\r\n  notFirst?: boolean\r\n) {\r\n  if (scly == null) {\r\n    scly = sclx\r\n  }\r\n  if (!expr.bbox) return\r\n  if (notFirst) {\r\n    expr.bbox.x *= sclx\r\n    expr.bbox.y *= scly\r\n  }\r\n  expr.bbox.w *= sclx\r\n  expr.bbox.h *= scly\r\n  for (let i = 0; i < expr.chld.length; i++) {\r\n    transform(expr.chld[i], sclx, scly, 0, 0, true)\r\n  }\r\n  expr.bbox.x += x\r\n  expr.bbox.y += y\r\n}\r\n\r\nfunction computeBbox(exprs: Expr[]): Bbox {\r\n  let xmin = Infinity\r\n  let xmax = -Infinity\r\n  let ymin = Infinity\r\n  let ymax = -Infinity\r\n  for (let i = 0; i < exprs.length; i++) {\r\n    if (!exprs[i].bbox) {\r\n      continue\r\n    }\r\n    xmin = Math.min(xmin, exprs[i].bbox.x)\r\n    ymin = Math.min(ymin, exprs[i].bbox.y)\r\n    xmax = Math.max(xmax, exprs[i].bbox.x + exprs[i].bbox.w)\r\n    ymax = Math.max(ymax, exprs[i].bbox.y + exprs[i].bbox.h)\r\n  }\r\n  return { x: xmin, y: ymin, w: xmax - xmin, h: ymax - ymin }\r\n}\r\n\r\nfunction group(exprs: Expr[]): Expr {\r\n  if (!exprs.length) {\r\n    // @ts-ignore\r\n    return null\r\n  }\r\n  const bbox: Bbox = computeBbox(exprs)\r\n  // console.log(exprs,bbox);\r\n  for (let i = 0; i < exprs.length; i++) {\r\n    if (!exprs[i].bbox) {\r\n      continue\r\n    }\r\n    exprs[i].bbox.x -= bbox.x\r\n    exprs[i].bbox.y -= bbox.y\r\n  }\r\n  const expr: Expr = {\r\n    type: 'node',\r\n    text: '',\r\n    mode: 'math',\r\n    chld: exprs,\r\n    bbox\r\n  }\r\n  return expr\r\n}\r\n\r\nfunction align(exprs: Expr[], alignment = 'center'): void {\r\n  for (let i = 0; i < exprs.length; i++) {\r\n    if (exprs[i].text == '^' || exprs[i].text == '\\'') {\r\n      let h = 0\r\n      let j = i\r\n      while (\r\n        j > 0 &&\r\n        (exprs[j].text == '^' || exprs[j].text == '_' || exprs[j].text == '\\'')\r\n      ) {\r\n        j--\r\n      }\r\n      h = exprs[j].bbox.y\r\n      if (exprs[i].text == '\\'') {\r\n        exprs[i].bbox.y = h\r\n      } else {\r\n        // @ts-ignore\r\n        transform(exprs[i], CONFIG.SUB_SUP_SCALE, null, 0, 0)\r\n        if (SYMB[exprs[j].text] && SYMB[exprs[j].text].flags.big) {\r\n          exprs[i].bbox.y = h - exprs[i].bbox.h\r\n        } else if (exprs[j].text == '\\\\int') {\r\n          exprs[i].bbox.y = h\r\n        } else {\r\n          exprs[i].bbox.y = h - exprs[i].bbox.h / 2\r\n        }\r\n      }\r\n    } else if (exprs[i].text == '_') {\r\n      let h = 1\r\n      let j = i\r\n      while (\r\n        j > 0 &&\r\n        (exprs[j].text == '^' || exprs[j].text == '_' || exprs[j].text == '\\'')\r\n      ) {\r\n        j--\r\n      }\r\n      h = exprs[j].bbox.y + exprs[j].bbox.h\r\n      // @ts-ignore\r\n      transform(exprs[i], CONFIG.SUB_SUP_SCALE, null, 0, 0)\r\n      if (SYMB[exprs[j].text] && SYMB[exprs[j].text].flags.big) {\r\n        exprs[i].bbox.y = h\r\n      } else if (exprs[j].text == '\\\\int') {\r\n        exprs[i].bbox.y = h - exprs[i].bbox.h\r\n      } else {\r\n        exprs[i].bbox.y = h - exprs[i].bbox.h / 2\r\n      }\r\n    }\r\n  }\r\n  function searchHigh(\r\n    i: number,\r\n    l: string,\r\n    r: string,\r\n    dir: number,\r\n    lvl0: number\r\n  ): number[] {\r\n    let j = i\r\n    let lvl = lvl0\r\n    let ymin = Infinity\r\n    let ymax = -Infinity\r\n    while (dir > 0 ? j < exprs.length : j >= 0) {\r\n      if (exprs[j].text == l) {\r\n        lvl++\r\n      } else if (exprs[j].text == r) {\r\n        lvl--\r\n        if (lvl == 0) {\r\n          break\r\n        }\r\n      } else if (exprs[j].text == '^' || exprs[j].text == '_') {\r\n        //skip\r\n      } else if (exprs[j].bbox) {\r\n        ymin = Math.min(ymin, exprs[j].bbox.y)\r\n        ymax = Math.max(ymax, exprs[j].bbox.y + exprs[j].bbox.h)\r\n      }\r\n      j += dir\r\n    }\r\n    return [ymin, ymax]\r\n  }\r\n  for (let i = 0; i < exprs.length; i++) {\r\n    if (exprs[i].text == '\\\\left') {\r\n      const [ymin, ymax] = searchHigh(i, '\\\\left', '\\\\right', 1, 0)\r\n      if (ymin != Infinity && ymax != -Infinity) {\r\n        exprs[i].bbox.y = ymin\r\n        transform(exprs[i], 1, (ymax - ymin) / exprs[i].bbox.h, 0, 0)\r\n      }\r\n    } else if (exprs[i].text == '\\\\right') {\r\n      const [ymin, ymax] = searchHigh(i, '\\\\right', '\\\\left', -1, 0)\r\n      if (ymin != Infinity && ymax != -Infinity) {\r\n        exprs[i].bbox.y = ymin\r\n        transform(exprs[i], 1, (ymax - ymin) / exprs[i].bbox.h, 0, 0)\r\n      }\r\n    } else if (exprs[i].text == '\\\\middle') {\r\n      const [lmin, lmax] = searchHigh(i, '\\\\right', '\\\\left', -1, 1)\r\n      const [rmin, rmax] = searchHigh(i, '\\\\left', '\\\\right', 1, 1)\r\n      const ymin = Math.min(lmin, rmin)\r\n      const ymax = Math.max(lmax, rmax)\r\n      if (ymin != Infinity && ymax != -Infinity) {\r\n        exprs[i].bbox.y = ymin\r\n        transform(exprs[i], 1, (ymax - ymin) / exprs[i].bbox.h, 0, 0)\r\n      }\r\n    }\r\n  }\r\n\r\n  if (!exprs.some(x => x.text == '&' || x.text == '\\\\\\\\')) {\r\n    return\r\n  }\r\n\r\n  const rows: Expr[][][] = []\r\n  let row: Expr[][] = []\r\n  let cell: Expr[] = []\r\n\r\n  for (let i = 0; i < exprs.length; i++) {\r\n    if (exprs[i].text == '&') {\r\n      row.push(cell)\r\n      cell = []\r\n    } else if (exprs[i].text == '\\\\\\\\') {\r\n      if (cell.length) {\r\n        row.push(cell)\r\n        cell = []\r\n      }\r\n      rows.push(row)\r\n      row = []\r\n    } else {\r\n      cell.push(exprs[i])\r\n    }\r\n  }\r\n  if (cell.length) {\r\n    row.push(cell)\r\n  }\r\n  if (row.length) {\r\n    rows.push(row)\r\n  }\r\n  const colws: number[] = []\r\n  const erows: Expr[][] = []\r\n  for (let i = 0; i < rows.length; i++) {\r\n    const erow: Expr[] = []\r\n    for (let j = 0; j < rows[i].length; j++) {\r\n      const e: Expr = group(rows[i][j])\r\n      if (e) {\r\n        colws[j] = colws[j] || 0\r\n        colws[j] = Math.max(e.bbox.w + 1, colws[j])\r\n      }\r\n      erow[j] = e\r\n    }\r\n    erows.push(erow)\r\n  }\r\n\r\n  const ybds: number[][] = []\r\n  for (let i = 0; i < erows.length; i++) {\r\n    let ymin = Infinity\r\n    let ymax = -Infinity\r\n    for (let j = 0; j < erows[i].length; j++) {\r\n      if (!erows[i][j]) {\r\n        continue\r\n      }\r\n      ymin = Math.min(ymin, erows[i][j].bbox.y)\r\n      ymax = Math.max(ymax, erows[i][j].bbox.y + erows[i][j].bbox.h)\r\n    }\r\n    ybds.push([ymin, ymax])\r\n  }\r\n\r\n  for (let i = 0; i < ybds.length; i++) {\r\n    if (ybds[i][0] == Infinity || ybds[i][1] == Infinity) {\r\n      ybds[i][0] = i == 0 ? 0 : ybds[i - 1][1]\r\n      ybds[i][1] = ybds[i][0] + 2\r\n    }\r\n  }\r\n\r\n  for (let i = 1; i < erows.length; i++) {\r\n    const shft = ybds[i - 1][1] - ybds[i][0] + CONFIG.LINE_SPACING\r\n    for (let j = 0; j < erows[i].length; j++) {\r\n      if (erows[i][j]) {\r\n        erows[i][j].bbox.y += shft\r\n      }\r\n    }\r\n    ybds[i][0] += shft\r\n    ybds[i][1] += shft\r\n  }\r\n\r\n  exprs.splice(0, exprs.length)\r\n  for (let i = 0; i < erows.length; i++) {\r\n    let dx = 0\r\n    for (let j = 0; j < erows[i].length; j++) {\r\n      const e: Expr = erows[i][j]\r\n      if (!e) {\r\n        dx += colws[j]\r\n        continue\r\n      }\r\n      e.bbox.x += dx\r\n      dx += colws[j] - e.bbox.w\r\n      // e.bbox.w = colws[j];\r\n      if (alignment == 'center') {\r\n        e.bbox.x += (colws[j] - e.bbox.w) / 2\r\n      } else if (alignment == 'left') {\r\n        //ok\r\n      } else if (alignment == 'right') {\r\n        e.bbox.x += colws[j] - e.bbox.w\r\n      } else if (alignment == 'equation') {\r\n        if (j != erows[i].length - 1) {\r\n          e.bbox.x += colws[j] - e.bbox.w\r\n        }\r\n      }\r\n      exprs.push(e)\r\n    }\r\n  }\r\n}\r\n\r\nfunction plan(expr: Expr, mode = 'math'): void {\r\n  const tmd: string =\r\n    {\r\n      '\\\\text': 'text',\r\n      '\\\\mathnormal': 'math',\r\n      '\\\\mathrm': 'rm',\r\n      '\\\\mathit': 'it',\r\n      '\\\\mathbf': 'bf',\r\n      '\\\\mathsf': 'sf',\r\n      '\\\\mathtt': 'tt',\r\n      '\\\\mathfrak': 'frak',\r\n      '\\\\mathcal': 'cal',\r\n      '\\\\mathbb': 'bb',\r\n      '\\\\mathscr': 'scr',\r\n      '\\\\rm': 'rm',\r\n      '\\\\it': 'it',\r\n      '\\\\bf': 'bf',\r\n      '\\\\sf': 'tt',\r\n      '\\\\tt': 'tt',\r\n      '\\\\frak': 'frak',\r\n      '\\\\cal': 'cal',\r\n      '\\\\bb': 'bb',\r\n      '\\\\scr': 'scr'\r\n    }[expr.text] ?? mode\r\n  if (!expr.chld.length) {\r\n    if (SYMB[expr.text]) {\r\n      if (SYMB[expr.text].flags.big) {\r\n        if (expr.text == '\\\\lim') {\r\n          expr.bbox = { x: 0, y: 0, w: 3.5, h: 2 }\r\n        } else {\r\n          expr.bbox = { x: 0, y: -0.5, w: 3, h: 3 }\r\n        }\r\n      } else if (SYMB[expr.text].flags.txt) {\r\n        let w = 0\r\n        for (let i = 1; i < expr.text.length; i++) {\r\n          w += HERSHEY(asciiMap(expr.text[i], 'text')).w\r\n        }\r\n        w /= 16\r\n        expr.bbox = { x: 0, y: 0, w: w, h: 2 }\r\n      } else if (SYMB[expr.text].glyph) {\r\n        let w = HERSHEY(SYMB[expr.text].glyph).w\r\n        w /= 16\r\n        if (expr.text == '\\\\int' || expr.text == '\\\\oint') {\r\n          expr.bbox = { x: 0, y: -1.5, w: w, h: 5 }\r\n        } else {\r\n          expr.bbox = { x: 0, y: 0, w: w, h: 2 }\r\n        }\r\n      } else {\r\n        expr.bbox = { x: 0, y: 0, w: 1, h: 2 }\r\n      }\r\n    } else {\r\n      let w = 0\r\n      for (let i = 0; i < expr.text.length; i++) {\r\n        if (!HERSHEY(asciiMap(expr.text[i], tmd))) {\r\n          continue\r\n        }\r\n        if (tmd == 'tt') {\r\n          w += 16\r\n        } else {\r\n          w += HERSHEY(asciiMap(expr.text[i], tmd)).w\r\n        }\r\n      }\r\n      w /= 16\r\n      expr.bbox = { x: 0, y: 0, w: w, h: 2 }\r\n    }\r\n    expr.mode = tmd\r\n    return\r\n  }\r\n  if (expr.text == '\\\\frac') {\r\n    const a: Expr = expr.chld[0]\r\n    const b: Expr = expr.chld[1]\r\n    const s: number = CONFIG.FRAC_SCALE\r\n    plan(a)\r\n    plan(b)\r\n    a.bbox.x = 0\r\n    a.bbox.y = 0\r\n    b.bbox.x = 0\r\n    b.bbox.y = 0\r\n    const mw: number = Math.max(a.bbox.w, b.bbox.w) * s\r\n    // @ts-ignore\r\n    transform(a, s, null, (mw - a.bbox.w * s) / 2, 0)\r\n    transform(\r\n      b,\r\n      s,\r\n      // @ts-ignore\r\n      null,\r\n      (mw - b.bbox.w * s) / 2,\r\n      a.bbox.h + CONFIG.FRAC_SPACING\r\n    )\r\n    expr.bbox = {\r\n      x: 0,\r\n      y: -a.bbox.h + 1 - CONFIG.FRAC_SPACING / 2,\r\n      w: mw,\r\n      h: a.bbox.h + b.bbox.h + CONFIG.FRAC_SPACING\r\n    }\r\n  } else if (expr.text == '\\\\binom') {\r\n    const a: Expr = expr.chld[0]\r\n    const b: Expr = expr.chld[1]\r\n    plan(a)\r\n    plan(b)\r\n    a.bbox.x = 0\r\n    a.bbox.y = 0\r\n    b.bbox.x = 0\r\n    b.bbox.y = 0\r\n    const mw: number = Math.max(a.bbox.w, b.bbox.w)\r\n    // @ts-ignore\r\n    transform(a, 1, null, (mw - a.bbox.w) / 2 + 1, 0)\r\n    // @ts-ignore\r\n    transform(b, 1, null, (mw - b.bbox.w) / 2 + 1, a.bbox.h)\r\n    expr.bbox = { x: 0, y: -a.bbox.h + 1, w: mw + 2, h: a.bbox.h + b.bbox.h }\r\n  } else if (expr.text == '\\\\sqrt') {\r\n    const e: Expr = expr.chld[0]\r\n    plan(e)\r\n    const f: Expr = expr.chld[1]\r\n    let pl = 0\r\n    if (f) {\r\n      plan(f)\r\n      pl = Math.max(f.bbox.w * CONFIG.SQRT_MAG_SCALE - 0.5, 0)\r\n      // @ts-ignore\r\n      transform(f, CONFIG.SQRT_MAG_SCALE, null, 0, 0.5)\r\n    }\r\n    // @ts-ignore\r\n    transform(e, 1, null, 1 + pl, 0.5)\r\n    expr.bbox = {\r\n      x: 0,\r\n      y: 2 - e.bbox.h - 0.5,\r\n      w: e.bbox.w + 1 + pl,\r\n      h: e.bbox.h + 0.5\r\n    }\r\n  } else if (SYMB[expr.text] && SYMB[expr.text].flags.hat) {\r\n    const e: Expr = expr.chld[0]\r\n    plan(e)\r\n    const y0 = e.bbox.y - 0.5\r\n    e.bbox.y = 0.5\r\n    expr.bbox = { x: 0, y: y0, w: e.bbox.w, h: e.bbox.h + 0.5 }\r\n  } else if (SYMB[expr.text] && SYMB[expr.text].flags.mat) {\r\n    const e: Expr = expr.chld[0]\r\n    plan(e)\r\n    expr.bbox = { x: 0, y: 0, w: e.bbox.w, h: e.bbox.h + 0.5 }\r\n  } else {\r\n    let dx = 0\r\n    let dy = 0\r\n    let mh = 1\r\n    for (let i = 0; i < expr.chld.length; i++) {\r\n      const c: Expr = expr.chld[i]\r\n      // @ts-ignore\r\n      const spac: number =\r\n        {\r\n          '\\\\quad': 2,\r\n          '\\\\,': (2 * 3) / 18,\r\n          '\\\\:': (2 * 4) / 18,\r\n          '\\\\;': (2 * 5) / 18,\r\n          '\\\\!': (2 * -3) / 18\r\n        }[c.text] ?? null\r\n\r\n      if (c.text == '\\\\\\\\') {\r\n        dy += mh\r\n        dx = 0\r\n        mh = 1\r\n        continue\r\n      } else if (c.text == '&') {\r\n        continue\r\n      } else if (spac != null) {\r\n        dx += spac\r\n        continue\r\n      } else {\r\n        plan(c, tmd)\r\n        // @ts-ignore\r\n        transform(c, 1, null, dx, dy)\r\n        if (c.text == '^' || c.text == '_' || c.text == '\\'') {\r\n          let j: number = i\r\n          while (\r\n            j > 0 &&\r\n            (expr.chld[j].text == '^' ||\r\n              expr.chld[j].text == '_' ||\r\n              expr.chld[j].text == '\\'')\r\n          ) {\r\n            j--\r\n          }\r\n          const wasBig =\r\n            SYMB[expr.chld[j].text] && SYMB[expr.chld[j].text].flags.big\r\n          if (c.text == '\\'') {\r\n            let k = j + 1\r\n            let nth = 0\r\n            while (k < i) {\r\n              if (expr.chld[k].text == '\\'') {\r\n                nth++\r\n              }\r\n              k++\r\n            }\r\n            c.bbox.x =\r\n              expr.chld[j].bbox.x + expr.chld[j].bbox.w + c.bbox.w * nth\r\n            dx = Math.max(dx, c.bbox.x + c.bbox.w)\r\n          } else {\r\n            if (wasBig) {\r\n              const ex =\r\n                expr.chld[j].bbox.x +\r\n                (expr.chld[j].bbox.w - c.bbox.w * CONFIG.SUB_SUP_SCALE) / 2\r\n              c.bbox.x = ex\r\n              dx = Math.max(\r\n                dx,\r\n                expr.chld[j].bbox.x +\r\n                  expr.chld[j].bbox.w +\r\n                  (c.bbox.w * CONFIG.SUB_SUP_SCALE - expr.chld[j].bbox.w) / 2\r\n              )\r\n            } else {\r\n              c.bbox.x = expr.chld[j].bbox.x + expr.chld[j].bbox.w\r\n              dx = Math.max(dx, c.bbox.x + c.bbox.w * CONFIG.SUB_SUP_SCALE)\r\n            }\r\n          }\r\n        } else {\r\n          dx += c.bbox.w\r\n        }\r\n        if (mode == 'text') {\r\n          dx += 1\r\n        }\r\n        mh = Math.max(c.bbox.y + c.bbox.h - dy, mh)\r\n      }\r\n    }\r\n    dy += mh\r\n    const m2s: Record<string, string[]> = {\r\n      bmatrix: ['[', ']'],\r\n      pmatrix: ['(', ')'],\r\n      Bmatrix: ['\\\\{', '\\\\}'],\r\n      cases: ['\\\\{']\r\n    }\r\n    const alt: string =\r\n      {\r\n        bmatrix: 'center',\r\n        pmatrix: 'center',\r\n        Bmatrix: 'center',\r\n        cases: 'left',\r\n        matrix: 'center',\r\n        aligned: 'equation'\r\n      }[expr.text] ?? 'left'\r\n\r\n    const hasLp = !!m2s[expr.text]\r\n    const hasRp = !!m2s[expr.text] && m2s[expr.text].length > 1\r\n\r\n    align(expr.chld, alt)\r\n    const bb = computeBbox(expr.chld)\r\n    if (expr.text == '\\\\text') {\r\n      bb.x -= 1\r\n      bb.w += 2\r\n    }\r\n\r\n    for (let i = 0; i < expr.chld.length; i++) {\r\n      // @ts-ignore\r\n      transform(expr.chld[i], 1, null, -bb.x + (hasLp ? 1.5 : 0), -bb.y)\r\n    }\r\n    expr.bbox = {\r\n      x: 0,\r\n      y: 0,\r\n      w: bb.w + 1.5 * Number(hasLp) + 1.5 * Number(hasRp),\r\n      h: bb.h\r\n    }\r\n\r\n    if (hasLp) {\r\n      expr.chld.unshift({\r\n        type: 'symb',\r\n        text: m2s[expr.text][0],\r\n        mode: expr.mode,\r\n        chld: [],\r\n        bbox: { x: 0, y: 0, w: 1, h: bb.h }\r\n      })\r\n    }\r\n    if (hasRp) {\r\n      expr.chld.push({\r\n        type: 'symb',\r\n        text: m2s[expr.text][1],\r\n        mode: expr.mode,\r\n        chld: [],\r\n        bbox: { x: bb.w + 2, y: 0, w: 1, h: bb.h }\r\n      })\r\n    }\r\n    if (hasLp || hasRp || expr.text == 'matrix') {\r\n      expr.type = 'node'\r\n      expr.text = ''\r\n      expr.bbox.y -= (expr.bbox.h - 2) / 2\r\n    }\r\n  }\r\n}\r\n\r\nfunction flatten(expr: Expr) {\r\n  function flat(expr: Expr, dx: number, dy: number): Expr[] {\r\n    const ff: Expr[] = []\r\n    if (expr.bbox) {\r\n      dx += expr.bbox.x\r\n      dy += expr.bbox.y\r\n      if (expr.text == '\\\\frac') {\r\n        const h: number =\r\n          expr.chld[1].bbox.y - (expr.chld[0].bbox.y + expr.chld[0].bbox.h)\r\n        const e: Expr = {\r\n          type: 'symb',\r\n          mode: expr.mode,\r\n          text: '\\\\bar',\r\n          bbox: {\r\n            x: dx,\r\n            y: dy + (expr.chld[1].bbox.y - h / 2) - h / 2,\r\n            w: expr.bbox.w,\r\n            h: h\r\n          },\r\n          chld: []\r\n        }\r\n        ff.push(e)\r\n      } else if (expr.text == '\\\\sqrt') {\r\n        const h: number = expr.chld[0].bbox.y\r\n        const xx: number = Math.max(\r\n          0,\r\n          expr.chld[0].bbox.x - expr.chld[0].bbox.h / 2\r\n        )\r\n        const e: Expr = {\r\n          type: 'symb',\r\n          mode: expr.mode,\r\n          text: '\\\\sqrt',\r\n          bbox: {\r\n            x: dx + xx,\r\n            y: dy + h / 2,\r\n            w: expr.chld[0].bbox.x - xx,\r\n            h: expr.bbox.h - h / 2\r\n          },\r\n          chld: []\r\n        }\r\n        ff.push(e)\r\n        ff.push({\r\n          type: 'symb',\r\n          text: '\\\\bar',\r\n          mode: expr.mode,\r\n          bbox: {\r\n            x: dx + expr.chld[0].bbox.x,\r\n            y: dy,\r\n            w: expr.bbox.w - expr.chld[0].bbox.x,\r\n            h: h\r\n          },\r\n          chld: []\r\n        })\r\n      } else if (expr.text == '\\\\binom') {\r\n        const w = Math.min(expr.chld[0].bbox.x, expr.chld[1].bbox.x)\r\n        const e: Expr = {\r\n          type: 'symb',\r\n          mode: expr.mode,\r\n          text: '(',\r\n          bbox: {\r\n            x: dx,\r\n            y: dy,\r\n            w: w,\r\n            h: expr.bbox.h\r\n          },\r\n          chld: []\r\n        }\r\n        ff.push(e)\r\n        ff.push({\r\n          type: 'symb',\r\n          text: ')',\r\n          mode: expr.mode,\r\n          bbox: {\r\n            x: dx + expr.bbox.w - w,\r\n            y: dy,\r\n            w: w,\r\n            h: expr.bbox.h\r\n          },\r\n          chld: []\r\n        })\r\n      } else if (SYMB[expr.text] && SYMB[expr.text].flags.hat) {\r\n        const h: number = expr.chld[0].bbox.y\r\n        const e: Expr = {\r\n          type: 'symb',\r\n          mode: expr.mode,\r\n          text: expr.text,\r\n          bbox: {\r\n            x: dx,\r\n            y: dy,\r\n            w: expr.bbox.w,\r\n            h: h\r\n          },\r\n          chld: []\r\n        }\r\n        ff.push(e)\r\n      } else if (SYMB[expr.text] && SYMB[expr.text].flags.mat) {\r\n        const h: number = expr.chld[0].bbox.h\r\n        const e: Expr = {\r\n          type: 'symb',\r\n          text: expr.text,\r\n          mode: expr.mode,\r\n          bbox: {\r\n            x: dx,\r\n            y: dy + h,\r\n            w: expr.bbox.w,\r\n            h: expr.bbox.h - h\r\n          },\r\n          chld: []\r\n        }\r\n        ff.push(e)\r\n      } else if (expr.type != 'node' && expr.text != '^' && expr.text != '_') {\r\n        const e: Expr = {\r\n          type: expr.type == 'func' ? 'symb' : expr.type,\r\n          text: expr.text,\r\n          mode: expr.mode,\r\n          bbox: {\r\n            x: dx,\r\n            y: dy,\r\n            w: expr.bbox.w,\r\n            h: expr.bbox.h\r\n          },\r\n          chld: []\r\n        }\r\n        ff.push(e)\r\n      }\r\n    }\r\n    for (let i = 0; i < expr.chld.length; i++) {\r\n      const f = flat(expr.chld[i], dx, dy)\r\n      ff.push(...f)\r\n    }\r\n    return ff\r\n  }\r\n  const f = flat(expr, -expr.bbox.x, -expr.bbox.y)\r\n  expr.type = 'node'\r\n  expr.text = ''\r\n  expr.chld = f\r\n}\r\n\r\nfunction render(expr: Expr): number[][][] {\r\n  const o: number[][][] = []\r\n  for (let i = 0; i < expr.chld.length; i++) {\r\n    const e: Expr = expr.chld[i]\r\n    let s = e.bbox.h / 2\r\n    let isSmallHat = false\r\n    if (\r\n      SYMB[e.text] &&\r\n      SYMB[e.text].flags.hat &&\r\n      !SYMB[e.text].flags.xfl &&\r\n      !SYMB[e.text].flags.yfl\r\n    ) {\r\n      s *= 4\r\n      isSmallHat = true\r\n    }\r\n    if (SYMB[e.text] && SYMB[e.text].glyph) {\r\n      const d = HERSHEY(SYMB[e.text].glyph)\r\n      for (let j = 0; j < d.polylines.length; j++) {\r\n        const l: number[][] = []\r\n\r\n        for (let k = 0; k < d.polylines[j].length; k++) {\r\n          let x = d.polylines[j][k][0]\r\n          let y = d.polylines[j][k][1]\r\n\r\n          if (SYMB[e.text].flags.xfl) {\r\n            x = ((x - d.xmin) / Math.max(d.xmax - d.xmin, 1)) * e.bbox.w\r\n            x += e.bbox.x\r\n          } else if ((d.w / 16) * s > e.bbox.w) {\r\n            x = (x / Math.max(d.w, 1)) * e.bbox.w\r\n            x += e.bbox.x\r\n          } else {\r\n            x = (x / 16) * s\r\n            const p = (e.bbox.w - (d.w / 16) * s) / 2\r\n            x += e.bbox.x + p\r\n          }\r\n          if (SYMB[e.text].flags.yfl) {\r\n            y = ((y - d.ymin) / Math.max(d.ymax - d.ymin, 1)) * e.bbox.h\r\n            y += e.bbox.y\r\n          } else {\r\n            y = (y / 16) * s\r\n            if (isSmallHat) {\r\n              const p = (d.ymax + d.ymin) / 2\r\n              y -= (p / 16) * s\r\n            }\r\n            y += e.bbox.y + e.bbox.h / 2\r\n          }\r\n          l.push([x, y])\r\n        }\r\n        o.push(l)\r\n      }\r\n    } else if ((SYMB[e.text] && SYMB[e.text].flags.txt) || e.type == 'char') {\r\n      let x0 = e.bbox.x\r\n      const isVerb = !!(SYMB[e.text] && SYMB[e.text].flags.txt)\r\n      for (let n = Number(isVerb); n < e.text.length; n++) {\r\n        const d = HERSHEY(asciiMap(e.text[n], isVerb ? 'text' : e.mode))\r\n        if (!d) {\r\n          console.warn('unmapped character: ' + e.text[n])\r\n          continue\r\n        }\r\n        for (let j = 0; j < d.polylines.length; j++) {\r\n          const l: number[][] = []\r\n          for (let k = 0; k < d.polylines[j].length; k++) {\r\n            let x = d.polylines[j][k][0]\r\n            let y = d.polylines[j][k][1]\r\n            x /= 16\r\n            y /= 16\r\n            x *= s\r\n            y *= s\r\n            if (e.mode == 'tt') {\r\n              if (d.w > 16) {\r\n                x *= 16 / d.w\r\n              } else {\r\n                x += (16 - d.w) / 2 / 16\r\n              }\r\n            }\r\n            x += x0\r\n            y += e.bbox.y + e.bbox.h / 2\r\n            l.push([x, y])\r\n          }\r\n          o.push(l)\r\n        }\r\n        if (e.mode == 'tt') {\r\n          x0 += s\r\n        } else {\r\n          x0 += (d.w / 16) * s\r\n        }\r\n      }\r\n    }\r\n  }\r\n  return o\r\n}\r\n\r\ninterface ExportOpt {\r\n  MIN_CHAR_H?: number\r\n  MAX_W?: number\r\n  MAX_H?: number\r\n  MARGIN_X?: number\r\n  MARGIN_Y?: number\r\n  SCALE_X?: number\r\n  SCALE_Y?: number\r\n  STROKE_W?: number\r\n  FG_COLOR?: string\r\n  BG_COLOR?: string\r\n}\r\n\r\nfunction nf(x: number): number {\r\n  return Math.round(x * 100) / 100\r\n}\r\n\r\nexport interface LaTexSVG {\r\n  svg: string\r\n  width: number\r\n  height: number\r\n}\r\n\r\nexport class LaTexUtils {\r\n  _latex: string\r\n  _tree: Expr\r\n  _tokens: string[]\r\n  _polylines: number[][][]\r\n\r\n  constructor(latex: string) {\r\n    this._latex = latex\r\n    this._tokens = tokenize(latex)\r\n    this._tree = parse(this._tokens)\r\n    environments(this._tree.chld)\r\n    plan(this._tree)\r\n    flatten(this._tree)\r\n    this._polylines = render(this._tree)\r\n  }\r\n\r\n  private resolveScale(opt?: ExportOpt): number[] {\r\n    if (opt == undefined) {\r\n      return [16, 16, 16, 16]\r\n    }\r\n    let sclx: number = opt.SCALE_X ?? 16\r\n    let scly: number = opt.SCALE_Y ?? 16\r\n\r\n    if (opt.MIN_CHAR_H != undefined) {\r\n      let mh = 0\r\n      for (let i = 0; i < this._tree.chld.length; i++) {\r\n        const c: Expr = this._tree.chld[i]\r\n        if (\r\n          c.type == 'char' ||\r\n          (SYMB[c.text] &&\r\n            (SYMB[c.text].flags.txt || !Object.keys(SYMB[c.text].flags).length))\r\n        ) {\r\n          mh = Math.min(c.bbox.h, mh)\r\n        }\r\n      }\r\n      const s: number = Math.max(1, opt.MIN_CHAR_H / mh)\r\n      sclx *= s\r\n      scly *= s\r\n    }\r\n    if (opt.MAX_W != undefined) {\r\n      const s0 = sclx\r\n      sclx = Math.min(sclx, opt.MAX_W / this._tree.bbox.w)\r\n      scly *= sclx / s0\r\n    }\r\n    if (opt.MAX_H != undefined) {\r\n      const s0 = scly\r\n      scly = Math.min(scly, opt.MAX_H / this._tree.bbox.h)\r\n      sclx *= scly / s0\r\n    }\r\n    const px: number = opt.MARGIN_X ?? sclx\r\n    const py: number = opt.MARGIN_Y ?? scly\r\n    return [px, py, sclx, scly]\r\n  }\r\n\r\n  polylines(opt?: ExportOpt): number[][][] {\r\n    if (!opt) opt = {}\r\n    const polylines: number[][][] = []\r\n    const [px, py, sclx, scly] = this.resolveScale(opt)\r\n    for (let i = 0; i < this._polylines.length; i++) {\r\n      polylines.push([])\r\n      for (let j = 0; j < this._polylines[i].length; j++) {\r\n        const [x, y] = this._polylines[i][j]\r\n        polylines[polylines.length - 1].push([px + x * sclx, py + y * scly])\r\n      }\r\n    }\r\n    return polylines\r\n  }\r\n\r\n  pathd(opt?: ExportOpt): string {\r\n    if (!opt) opt = {}\r\n    let d = ''\r\n    const [px, py, sclx, scly] = this.resolveScale(opt)\r\n    for (let i = 0; i < this._polylines.length; i++) {\r\n      for (let j = 0; j < this._polylines[i].length; j++) {\r\n        const [x, y] = this._polylines[i][j]\r\n        d += !j ? 'M' : 'L'\r\n        d += `${nf(px + x * sclx)} ${nf(py + y * scly)}`\r\n      }\r\n    }\r\n    return d\r\n  }\r\n\r\n  svg(opt: ExportOpt): LaTexSVG {\r\n    if (!opt) opt = {}\r\n    const [px, py, sclx, scly] = this.resolveScale(opt)\r\n    const w = nf(this._tree.bbox.w * sclx + px * 2)\r\n    const h = nf(this._tree.bbox.h * scly + py * 2)\r\n    let o = `<svg\r\n      xmlns=\"http://www.w3.org/2000/svg\"\r\n      width=\"${w}\" height=\"${h}\"\r\n      fill=\"none\" stroke=\"${opt.FG_COLOR ?? 'black'}\" stroke-width=\"${\r\n      opt.STROKE_W ?? 1\r\n    }\"\r\n      stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n    >`\r\n    if (opt.BG_COLOR) {\r\n      o += `<rect x=\"${0}\" y=\"${0}\" width=\"${w}\" height=\"${h}\" fill=\"${\r\n        opt.BG_COLOR\r\n      }\" stroke=\"none\"></rect>`\r\n    }\r\n    o += `<path d=\"`\r\n    for (let i = 0; i < this._polylines.length; i++) {\r\n      o += 'M'\r\n      for (let j = 0; j < this._polylines[i].length; j++) {\r\n        const [x, y] = this._polylines[i][j]\r\n        o += nf(px + x * sclx) + ' ' + nf(py + y * scly) + ' '\r\n      }\r\n    }\r\n    o += `\"/>`\r\n    o += `</svg>`\r\n    return {\r\n      svg: `data:image/svg+xml;base64,${window.btoa(o)}`,\r\n      width: Math.ceil(w),\r\n      height: Math.ceil(h)\r\n    }\r\n  }\r\n\r\n  pdf(opt: ExportOpt): string {\r\n    if (!opt) opt = {}\r\n    const [px, py, sclx, scly] = this.resolveScale(opt)\r\n\r\n    const width = nf(this._tree.bbox.w * sclx + px * 2)\r\n    const height = nf(this._tree.bbox.h * scly + py * 2)\r\n    let head = `%PDF-1.1\\n%%¥±ë\\n1 0 obj\\n<< /Type /Catalog\\n/Pages 2 0 R\\n>>endobj\r\n    2 0 obj\\n<< /Type /Pages\\n/Kids [3 0 R]\\n/Count 1\\n/MediaBox [0 0 ${width} ${height}]\\n>>\\nendobj\r\n    3 0 obj\\n<< /Type /Page\\n/Parent 2 0 R\\n/Resources\\n<< /Font\\n<< /F1\\n<< /Type /Font\r\n    /Subtype /Type1\\n/BaseFont /Times-Roman\\n>>\\n>>\\n>>\\n/Contents [`\r\n    let pdf = ''\r\n    let count = 4\r\n    for (let i = 0; i < this._polylines.length; i++) {\r\n      pdf += `${count} 0 obj \\n<< /Length 0 >>\\n stream\\n 1 j 1 J ${\r\n        opt.STROKE_W ?? 1\r\n      } w\\n`\r\n      for (let j = 0; j < this._polylines[i].length; j++) {\r\n        const [x, y] = this._polylines[i][j]\r\n        pdf += `${nf(px + x * sclx)} ${nf(height - (py + y * scly))} ${\r\n          j ? 'l' : 'm'\r\n        } `\r\n      }\r\n      pdf += '\\nS\\nendstream\\nendobj\\n'\r\n      head += `${count} 0 R `\r\n      count++\r\n    }\r\n    head += ']\\n>>\\nendobj\\n'\r\n    pdf += '\\ntrailer\\n<< /Root 1 0 R \\n /Size 0\\n >>startxref\\n\\n%%EOF\\n'\r\n    return head + pdf\r\n  }\r\n\r\n  boxes(opt: ExportOpt): Bbox[] {\r\n    if (!opt) opt = {}\r\n    const [px, py, sclx, scly] = this.resolveScale(opt)\r\n    const bs: Bbox[] = []\r\n    for (let i = 0; i < this._tree.chld.length; i++) {\r\n      const { x, y, w, h } = this._tree.chld[i].bbox\r\n      bs.push({ x: px + x * sclx, y: py + y * scly, w: w * sclx, h: h * scly })\r\n    }\r\n    return bs\r\n  }\r\n\r\n  box(opt: ExportOpt): Bbox {\r\n    if (!opt) opt = {}\r\n    const [px, py, sclx, scly] = this.resolveScale(opt)\r\n    return {\r\n      x: px + this._tree.bbox.x * sclx,\r\n      y: py + this._tree.bbox.y * scly,\r\n      w: this._tree.bbox.w * sclx,\r\n      h: this._tree.bbox.h * scly\r\n    }\r\n  }\r\n}\r\n\r\nconst _impl: Record<string, Function> = {\r\n  tokenize,\r\n  parse,\r\n  environments,\r\n  plan,\r\n  flatten,\r\n  render\r\n}\r\n\r\nexport { CONFIG, _impl }\r\n","import {\r\n  cloneProperty,\r\n  deepClone,\r\n  deepCloneOmitKeys,\r\n  getUUID,\r\n  isArrayEqual,\r\n  omitObject,\r\n  pickObject,\r\n  splitText\r\n} from '.'\r\n// import {\r\n//   EditorMode,\r\n//   ElementType,\r\n//   IElement,\r\n//   ImageDisplay,\r\n//   ListStyle,\r\n//   ListType,\r\n//   RowFlex,\r\n//   TableBorder,\r\n//   TdBorder\r\n// } from '@hufe921/canvas-editor'\r\nimport { LaTexParticle } from '../core/draw/particle/latex/LaTexParticle'\r\nimport { NON_BREAKING_SPACE, ZERO } from '../dataset/constant/Common'\r\nimport {\r\n  BLOCK_ELEMENT_TYPE,\r\n  CONTROL_STYLE_ATTR,\r\n  EDITOR_ELEMENT_CONTEXT_ATTR,\r\n  EDITOR_ELEMENT_ZIP_ATTR,\r\n  EDITOR_ROW_ATTR,\r\n  INLINE_NODE_NAME,\r\n  TABLE_CONTEXT_ATTR,\r\n  TABLE_TD_ZIP_ATTR,\r\n  TEXTLIKE_ELEMENT_TYPE,\r\n  TITLE_CONTEXT_ATTR\r\n} from '../dataset/constant/Element'\r\nimport {\r\n  listStyleCSSMapping,\r\n  listTypeElementMapping,\r\n  ulStyleMapping\r\n} from '../dataset/constant/List'\r\nimport { START_LINE_BREAK_REG } from '../dataset/constant/Regular'\r\nimport {\r\n  titleNodeNameMapping,\r\n  titleOrderNumberMapping,\r\n  titleSizeMapping\r\n} from '../dataset/constant/Title'\r\nimport { ControlComponent, ControlType } from '../dataset/enum/Control'\r\nimport { ListStyle, ListType, UlStyle } from '../dataset/enum/List'\r\nimport { DeepRequired } from '../interface/Common'\r\nimport { IControlSelect } from '../interface/Control'\r\nimport { IRowElement } from '../interface/Row'\r\nimport { ITd } from '../interface/table/Td'\r\nimport { ITr } from '../interface/table/Tr'\r\nimport { IEditorOption } from '../interface/Editor'\r\nimport { svgString2Image } from '..'\r\nimport { IElement } from '../interface/Element'\r\nimport { ElementType } from '../dataset/enum/Element'\r\nimport { RowFlex } from '../dataset/enum/Row'\r\nimport { EditorMode } from '../dataset/enum/Editor'\r\nimport { TableBorder, TdBorder } from '../dataset/enum/table/Table'\r\nimport { ImageDisplay } from '../dataset/enum/Common'\r\n// import { mergeOption } from './option'\r\n\r\nexport function unzipElementList(elementList: IElement[]): IElement[] {\r\n  const result: IElement[] = []\r\n  for (let v = 0; v < elementList.length; v++) {\r\n    const valueItem = elementList[v]\r\n    const textList = splitText(valueItem.value)\r\n    for (let d = 0; d < textList.length; d++) {\r\n      result.push({ ...valueItem, value: textList[d] })\r\n    }\r\n  }\r\n  return result\r\n}\r\n\r\ninterface IFormatElementListOption {\r\n  isHandleFirstElement?: boolean // 根据上下文确定首字符处理逻辑（处理首字符补偿）\r\n  isForceCompensation?: boolean // 强制补偿字符\r\n  editorOptions: DeepRequired<IEditorOption>\r\n}\r\n\r\nexport async function formatElementList(\r\n  elementList: IElement[],\r\n  options: IFormatElementListOption\r\n) {\r\n  const {\r\n    isHandleFirstElement = true,\r\n    isForceCompensation = false,\r\n    editorOptions\r\n  } = options\r\n  const startElement = elementList[0]\r\n  // 非首字符零宽节点文本元素则补偿-列表元素内部会补偿此处忽略\r\n  if (\r\n    isForceCompensation ||\r\n    (isHandleFirstElement &&\r\n      startElement?.type !== ElementType.LIST &&\r\n      ((startElement?.type && startElement.type !== ElementType.TEXT) ||\r\n        !START_LINE_BREAK_REG.test(startElement?.value)))\r\n  ) {\r\n    elementList.unshift({\r\n      value: ZERO\r\n    })\r\n  }\r\n  let i = 0\r\n  while (i < elementList.length) {\r\n    let el = elementList[i]\r\n    // 优先处理虚拟元素\r\n    if (el.type === ElementType.TITLE) {\r\n      // 移除父节点\r\n      elementList.splice(i, 1)\r\n      // 格式化元素\r\n      const valueList = el.valueList || []\r\n      formatElementList(valueList, {\r\n        ...options,\r\n        isHandleFirstElement: false,\r\n        isForceCompensation: false\r\n      })\r\n      // 追加节点\r\n      if (valueList.length) {\r\n        const titleId = getUUID()\r\n        const titleOptions = editorOptions.title\r\n        for (let v = 0; v < valueList.length; v++) {\r\n          const value = valueList[v]\r\n          value.title = el.title\r\n          if (el.level) {\r\n            value.titleId = titleId\r\n            value.level = el.level\r\n          }\r\n          // 文本型元素设置字体及加粗\r\n          if (isTextLikeElement(value)) {\r\n            if (!value.size) {\r\n              value.size = titleOptions[titleSizeMapping[value.level!]]\r\n            }\r\n            if (value.bold === undefined) {\r\n              value.bold = true\r\n            }\r\n          }\r\n          elementList.splice(i, 0, value)\r\n          i++\r\n        }\r\n      }\r\n      i--\r\n    } else if (el.type === ElementType.LIST) {\r\n      // 移除父节点\r\n      elementList.splice(i, 1)\r\n      // 格式化元素\r\n      const valueList = el.valueList || []\r\n      formatElementList(valueList, {\r\n        ...options,\r\n        isHandleFirstElement: true,\r\n        isForceCompensation: false\r\n      })\r\n      // 追加节点\r\n      if (valueList.length) {\r\n        const listId = getUUID()\r\n        for (let v = 0; v < valueList.length; v++) {\r\n          const value = valueList[v]\r\n          value.listId = listId\r\n          value.listType = el.listType\r\n          value.listStyle = el.listStyle\r\n          elementList.splice(i, 0, value)\r\n          i++\r\n        }\r\n      }\r\n      i--\r\n    } else if (el.type === ElementType.TABLE) {\r\n      const tableId = getUUID()\r\n      el.id = tableId\r\n      if (el.trList) {\r\n        const { defaultTrMinHeight } = editorOptions.table\r\n        for (let t = 0; t < el.trList.length; t++) {\r\n          const tr = el.trList[t]\r\n          const trId = getUUID()\r\n          tr.id = trId\r\n          if (!tr.minHeight || tr.minHeight < defaultTrMinHeight) {\r\n            tr.minHeight = defaultTrMinHeight\r\n          }\r\n          if (tr.height < tr.minHeight) {\r\n            tr.height = tr.minHeight\r\n          }\r\n          for (let d = 0; d < tr.tdList.length; d++) {\r\n            const td = tr.tdList[d]\r\n            const tdId = getUUID()\r\n            td.id = tdId\r\n            formatElementList(td.value, {\r\n              ...options,\r\n              isHandleFirstElement: true,\r\n              isForceCompensation: true\r\n            })\r\n            for (let v = 0; v < td.value.length; v++) {\r\n              const value = td.value[v]\r\n              value.tdId = tdId\r\n              value.trId = trId\r\n              value.tableId = tableId\r\n            }\r\n          }\r\n        }\r\n      }\r\n    } else if (el.type === ElementType.HYPERLINK) {\r\n      // 移除父节点\r\n      elementList.splice(i, 1)\r\n      // 元素展开\r\n      const valueList = unzipElementList(el.valueList || [])\r\n      // 追加节点\r\n      if (valueList.length) {\r\n        const hyperlinkId = getUUID()\r\n        for (let v = 0; v < valueList.length; v++) {\r\n          const value = valueList[v]\r\n          value.type = el.type\r\n          value.url = el.url\r\n          value.hyperlinkId = hyperlinkId\r\n          elementList.splice(i, 0, value)\r\n          i++\r\n        }\r\n      }\r\n      i--\r\n    } else if (el.type === ElementType.DATE) {\r\n      // 移除父节点\r\n      elementList.splice(i, 1)\r\n      // 元素展开\r\n      const valueList = unzipElementList(el.valueList || [])\r\n      // 追加节点\r\n      if (valueList.length) {\r\n        const dateId = getUUID()\r\n        for (let v = 0; v < valueList.length; v++) {\r\n          const value = valueList[v]\r\n          value.type = el.type\r\n          value.dateFormat = el.dateFormat\r\n          value.dateId = dateId\r\n          elementList.splice(i, 0, value)\r\n          i++\r\n        }\r\n      }\r\n      i--\r\n    } else if (el.type === ElementType.CONTROL) {\r\n      // 兼容控件内容类型错误\r\n      if (!el.control) {\r\n        i++\r\n        continue\r\n      }\r\n      const { prefix, postfix, value, placeholder, code, type, valueSets } =\r\n        el.control\r\n      const {\r\n        editorOptions: {\r\n          control: controlOption,\r\n          checkbox: checkboxOption,\r\n          radio: radioOption\r\n        }\r\n      } = options\r\n      const controlId = getUUID()\r\n      // 移除父节点\r\n      elementList.splice(i, 1)\r\n      // 控件上下文提取（压缩后的控件上下文无法提取）\r\n      const controlContext = pickObject(el, [\r\n        ...EDITOR_ELEMENT_CONTEXT_ATTR,\r\n        ...EDITOR_ROW_ATTR\r\n      ])\r\n      // 控件设置的默认样式（以前缀为基准）\r\n      const controlDefaultStyle = pickObject(\r\n        <IElement>(<unknown>el.control),\r\n        CONTROL_STYLE_ATTR\r\n      )\r\n      // 前后缀个性化设置\r\n      const thePrePostfixArg: Omit<IElement, 'value'> = {\r\n        ...controlDefaultStyle,\r\n        color: editorOptions.control.bracketColor\r\n      }\r\n      // 前缀\r\n      const prefixStrList = splitText(prefix || controlOption.prefix)\r\n      for (let p = 0; p < prefixStrList.length; p++) {\r\n        const value = prefixStrList[p]\r\n        elementList.splice(i, 0, {\r\n          ...controlContext,\r\n          ...thePrePostfixArg,\r\n          controlId,\r\n          value,\r\n          type: el.type,\r\n          control: el.control,\r\n          controlComponent: ControlComponent.PREFIX\r\n        })\r\n        i++\r\n      }\r\n      // 值\r\n      if (\r\n        (value && value.length) ||\r\n        type === ControlType.CHECKBOX ||\r\n        type === ControlType.RADIO ||\r\n        (type === ControlType.SELECT && code && (!value || !value.length))\r\n      ) {\r\n        let valueList: IElement[] = value || []\r\n        if (type === ControlType.CHECKBOX) {\r\n          const codeList = code ? code.split(',') : []\r\n          if (Array.isArray(valueSets) && valueSets.length) {\r\n            // 拆分valueList优先使用其属性\r\n            const valueStyleList = valueList.reduce(\r\n              (pre, cur) =>\r\n                pre.concat(\r\n                  cur.value.split('').map(v => ({ ...cur, value: v }))\r\n                ),\r\n              [] as IElement[]\r\n            )\r\n            let valueStyleIndex = 0\r\n            for (let v = 0; v < valueSets.length; v++) {\r\n              const valueSet = valueSets[v]\r\n              // checkbox组件\r\n              elementList.splice(i, 0, {\r\n                ...controlContext,\r\n                ...controlDefaultStyle,\r\n                controlId,\r\n                value: '',\r\n                type: el.type,\r\n                control: el.control,\r\n                controlComponent: ControlComponent.CHECKBOX,\r\n                checkbox: {\r\n                  code: valueSet.code,\r\n                  value: codeList.includes(valueSet.code)\r\n                }\r\n              })\r\n              i++\r\n              // 文本\r\n              const valueStrList = splitText(valueSet.value)\r\n              for (let e = 0; e < valueStrList.length; e++) {\r\n                const value = valueStrList[e]\r\n                const isLastLetter = e === valueStrList.length - 1\r\n                elementList.splice(i, 0, {\r\n                  ...controlContext,\r\n                  ...controlDefaultStyle,\r\n                  ...valueStyleList[valueStyleIndex],\r\n                  controlId,\r\n                  value: value === '\\n' ? ZERO : value,\r\n                  letterSpacing: isLastLetter ? checkboxOption.gap : 0,\r\n                  control: el.control,\r\n                  controlComponent: ControlComponent.VALUE\r\n                })\r\n                valueStyleIndex++\r\n                i++\r\n              }\r\n            }\r\n          }\r\n        } else if (type === ControlType.RADIO) {\r\n          if (Array.isArray(valueSets) && valueSets.length) {\r\n            // 拆分valueList优先使用其属性\r\n            const valueStyleList = valueList.reduce(\r\n              (pre, cur) =>\r\n                pre.concat(\r\n                  cur.value.split('').map(v => ({ ...cur, value: v }))\r\n                ),\r\n              [] as IElement[]\r\n            )\r\n            let valueStyleIndex = 0\r\n            for (let v = 0; v < valueSets.length; v++) {\r\n              const valueSet = valueSets[v]\r\n              // radio组件\r\n              elementList.splice(i, 0, {\r\n                ...controlContext,\r\n                ...controlDefaultStyle,\r\n                controlId,\r\n                value: '',\r\n                type: el.type,\r\n                control: el.control,\r\n                controlComponent: ControlComponent.RADIO,\r\n                radio: {\r\n                  code: valueSet.code,\r\n                  value: code === valueSet.code\r\n                }\r\n              })\r\n              i++\r\n              // 文本\r\n              const valueStrList = splitText(valueSet.value)\r\n              for (let e = 0; e < valueStrList.length; e++) {\r\n                const value = valueStrList[e]\r\n                const isLastLetter = e === valueStrList.length - 1\r\n                elementList.splice(i, 0, {\r\n                  ...controlContext,\r\n                  ...controlDefaultStyle,\r\n                  ...valueStyleList[valueStyleIndex],\r\n                  controlId,\r\n                  value: value === '\\n' ? ZERO : value,\r\n                  letterSpacing: isLastLetter ? radioOption.gap : 0,\r\n                  control: el.control,\r\n                  controlComponent: ControlComponent.VALUE\r\n                })\r\n                valueStyleIndex++\r\n                i++\r\n              }\r\n            }\r\n          }\r\n        } else {\r\n          if (!value || !value.length) {\r\n            if (Array.isArray(valueSets) && valueSets.length) {\r\n              const valueSet = valueSets.find(v => v.code === code)\r\n              if (valueSet) {\r\n                valueList = [\r\n                  {\r\n                    value: valueSet.value\r\n                  }\r\n                ]\r\n              }\r\n            }\r\n          }\r\n          formatElementList(valueList, {\r\n            ...options,\r\n            isHandleFirstElement: false,\r\n            isForceCompensation: false\r\n          })\r\n          for (let v = 0; v < valueList.length; v++) {\r\n            const element = valueList[v]\r\n            const value = element.value\r\n            elementList.splice(i, 0, {\r\n              ...controlContext,\r\n              ...controlDefaultStyle,\r\n              ...element,\r\n              controlId,\r\n              value: value === '\\n' ? ZERO : value,\r\n              type: element.type || ElementType.TEXT,\r\n              control: el.control,\r\n              controlComponent: ControlComponent.VALUE\r\n            })\r\n            i++\r\n          }\r\n        }\r\n      } else if (placeholder) {\r\n        // placeholder\r\n        const thePlaceholderArgs: Omit<IElement, 'value'> = {\r\n          ...controlDefaultStyle,\r\n          color: editorOptions.control.placeholderColor\r\n        }\r\n        const placeholderStrList = splitText(placeholder)\r\n        for (let p = 0; p < placeholderStrList.length; p++) {\r\n          const value = placeholderStrList[p]\r\n          elementList.splice(i, 0, {\r\n            ...controlContext,\r\n            ...thePlaceholderArgs,\r\n            controlId,\r\n            value: value === '\\n' ? ZERO : value,\r\n            type: el.type,\r\n            control: el.control,\r\n            controlComponent: ControlComponent.PLACEHOLDER\r\n          })\r\n          i++\r\n        }\r\n      }\r\n      // 后缀\r\n      const postfixStrList = splitText(postfix || controlOption.postfix)\r\n      for (let p = 0; p < postfixStrList.length; p++) {\r\n        const value = postfixStrList[p]\r\n        elementList.splice(i, 0, {\r\n          ...controlContext,\r\n          ...thePrePostfixArg,\r\n          controlId,\r\n          value,\r\n          type: el.type,\r\n          control: el.control,\r\n          controlComponent: ControlComponent.POSTFIX\r\n        })\r\n        i++\r\n      }\r\n      i--\r\n    } else if (\r\n      (!el.type || TEXTLIKE_ELEMENT_TYPE.includes(el.type)) &&\r\n      el.value.length > 1\r\n    ) {\r\n      elementList.splice(i, 1)\r\n      const valueList = splitText(el.value)\r\n      for (let v = 0; v < valueList.length; v++) {\r\n        elementList.splice(i + v, 0, { ...el, value: valueList[v] })\r\n      }\r\n      el = elementList[i]\r\n    }\r\n    if (el.value === '\\n' || el.value == '\\r\\n') {\r\n      el.value = ZERO\r\n    }\r\n    if (el.type === ElementType.IMAGE || el.type === ElementType.BLOCK) {\r\n      el.id = getUUID()\r\n    }\r\n    if (el.type === ElementType.LATEX) {\r\n      const { svg, width, height } = LaTexParticle.convertLaTextToSVG(el.value)\r\n      el.width = el.width || width\r\n      el.height = el.height || height\r\n      el.laTexSVG = svg\r\n      el.id = getUUID()\r\n      await svgString2Image(el.laTexSVG, width, height, 'png', (pngData: any) => {\r\n        // pngData is base64 png string\r\n        el.laTexSVG = pngData\r\n      })\r\n    }\r\n    i++\r\n  }\r\n}\r\n\r\nexport function isSameElementExceptValue(\r\n  source: IElement,\r\n  target: IElement\r\n): boolean {\r\n  const sourceKeys = Object.keys(source)\r\n  const targetKeys = Object.keys(target)\r\n  if (sourceKeys.length !== targetKeys.length) return false\r\n  for (let s = 0; s < sourceKeys.length; s++) {\r\n    const key = sourceKeys[s] as never\r\n    // 值不需要校验\r\n    if (key === 'value') continue\r\n    // groupIds数组需特殊校验数组是否相等\r\n    if (\r\n      key === 'groupIds' &&\r\n      Array.isArray(source[key]) &&\r\n      Array.isArray(target[key]) &&\r\n      isArrayEqual(source[key], target[key])\r\n    ) {\r\n      continue\r\n    }\r\n    if (source[key] !== target[key]) {\r\n      return false\r\n    }\r\n  }\r\n  return true\r\n}\r\ninterface IPickElementOption {\r\n  extraPickAttrs?: Array<keyof IElement>\r\n}\r\nexport function pickElementAttr(\r\n  payload: IElement,\r\n  option: IPickElementOption = {}\r\n): IElement {\r\n  const { extraPickAttrs } = option\r\n  const zipAttrs = EDITOR_ELEMENT_ZIP_ATTR\r\n  if (extraPickAttrs) {\r\n    zipAttrs.push(...extraPickAttrs)\r\n  }\r\n  const element: IElement = {\r\n    value: payload.value === ZERO ? `\\n` : payload.value\r\n  }\r\n  zipAttrs.forEach(attr => {\r\n    const value = payload[attr] as never\r\n    if (value !== undefined) {\r\n      element[attr] = value\r\n    }\r\n  })\r\n  return element\r\n}\r\n\r\ninterface IZipElementListOption {\r\n  extraPickAttrs?: Array<keyof IElement>\r\n}\r\nexport function zipElementList(\r\n  payload: IElement[],\r\n  options: IZipElementListOption = {}\r\n): IElement[] {\r\n  const { extraPickAttrs } = options\r\n  const elementList = deepClone(payload)\r\n  const zipElementListData: IElement[] = []\r\n  let e = 0\r\n  while (e < elementList.length) {\r\n    let element = elementList[e]\r\n    // 上下文首字符（占位符）-列表首字符要保留避免是复选框\r\n    if (\r\n      e === 0 &&\r\n      element.value === ZERO &&\r\n      !element.listId &&\r\n      (!element.type || element.type === ElementType.TEXT)\r\n    ) {\r\n      e++\r\n      continue\r\n    }\r\n    // 优先处理虚拟元素，后表格、超链接、日期、控件特殊处理\r\n    if (element.titleId && element.level) {\r\n      // 标题处理\r\n      const titleId = element.titleId\r\n      if (titleId) {\r\n        const level = element.level\r\n        const titleElement: IElement = {\r\n          type: ElementType.TITLE,\r\n          title: element.title,\r\n          value: '',\r\n          level\r\n        }\r\n        const valueList: IElement[] = []\r\n        while (e < elementList.length) {\r\n          const titleE = elementList[e]\r\n          if (titleId !== titleE.titleId) {\r\n            e--\r\n            break\r\n          }\r\n          delete titleE.level\r\n          delete titleE.title\r\n          valueList.push(titleE)\r\n          e++\r\n        }\r\n        titleElement.valueList = zipElementList(valueList, options)\r\n        element = titleElement\r\n      }\r\n    } else if (element.listId && element.listType) {\r\n      // 列表处理\r\n      const listId = element.listId\r\n      if (listId) {\r\n        const listType = element.listType\r\n        const listStyle = element.listStyle\r\n        const listElement: IElement = {\r\n          type: ElementType.LIST,\r\n          value: '',\r\n          listId,\r\n          listType,\r\n          listStyle\r\n        }\r\n        const valueList: IElement[] = []\r\n        while (e < elementList.length) {\r\n          const listE = elementList[e]\r\n          if (listId !== listE.listId) {\r\n            e--\r\n            break\r\n          }\r\n          delete listE.listType\r\n          delete listE.listStyle\r\n          valueList.push(listE)\r\n          e++\r\n        }\r\n        listElement.valueList = zipElementList(valueList, options)\r\n        element = listElement\r\n      }\r\n    } else if (element.type === ElementType.TABLE) {\r\n      // 分页表格先进行合并\r\n      if (element.pagingId) {\r\n        let tableIndex = e + 1\r\n        let combineCount = 0\r\n        while (tableIndex < elementList.length) {\r\n          const nextElement = elementList[tableIndex]\r\n          if (nextElement.pagingId === element.pagingId) {\r\n            element.height! += nextElement.height!\r\n            element.trList!.push(...nextElement.trList!)\r\n            tableIndex++\r\n            combineCount++\r\n          } else {\r\n            break\r\n          }\r\n        }\r\n        e += combineCount\r\n      }\r\n      if (element.trList) {\r\n        for (let t = 0; t < element.trList.length; t++) {\r\n          const tr = element.trList[t]\r\n          delete tr.id\r\n          for (let d = 0; d < tr.tdList.length; d++) {\r\n            const td = tr.tdList[d]\r\n            const zipTd: ITd = {\r\n              colspan: td.colspan,\r\n              rowspan: td.rowspan,\r\n              value: zipElementList(td.value, options)\r\n            }\r\n            // 压缩单元格属性\r\n            TABLE_TD_ZIP_ATTR.forEach(attr => {\r\n              const value = td[attr] as never\r\n              if (value !== undefined) {\r\n                zipTd[attr] = value\r\n              }\r\n            })\r\n            tr.tdList[d] = zipTd\r\n          }\r\n        }\r\n      }\r\n    } else if (element.type === ElementType.HYPERLINK) {\r\n      // 超链接处理\r\n      const hyperlinkId = element.hyperlinkId\r\n      if (hyperlinkId) {\r\n        const hyperlinkElement: IElement = {\r\n          type: ElementType.HYPERLINK,\r\n          value: '',\r\n          url: element.url\r\n        }\r\n        const valueList: IElement[] = []\r\n        while (e < elementList.length) {\r\n          const hyperlinkE = elementList[e]\r\n          if (hyperlinkId !== hyperlinkE.hyperlinkId) {\r\n            e--\r\n            break\r\n          }\r\n          delete hyperlinkE.type\r\n          delete hyperlinkE.url\r\n          valueList.push(hyperlinkE)\r\n          e++\r\n        }\r\n        hyperlinkElement.valueList = zipElementList(valueList, options)\r\n        element = hyperlinkElement\r\n      }\r\n    } else if (element.type === ElementType.DATE) {\r\n      const dateId = element.dateId\r\n      if (dateId) {\r\n        const dateElement: IElement = {\r\n          type: ElementType.DATE,\r\n          value: '',\r\n          dateFormat: element.dateFormat\r\n        }\r\n        const valueList: IElement[] = []\r\n        while (e < elementList.length) {\r\n          const dateE = elementList[e]\r\n          if (dateId !== dateE.dateId) {\r\n            e--\r\n            break\r\n          }\r\n          delete dateE.type\r\n          delete dateE.dateFormat\r\n          valueList.push(dateE)\r\n          e++\r\n        }\r\n        dateElement.valueList = zipElementList(valueList, options)\r\n        element = dateElement\r\n      }\r\n    } else if (element.controlId) {\r\n      // 控件处理\r\n      const controlId = element.controlId\r\n      if (controlId) {\r\n        // 以前缀为基准更新控件默认样式\r\n        const controlDefaultStyle = <IControlSelect>(\r\n          (<unknown>pickObject(element, CONTROL_STYLE_ATTR))\r\n        )\r\n        const control = {\r\n          ...element.control!,\r\n          ...controlDefaultStyle\r\n        }\r\n        const controlElement: IElement = {\r\n          ...pickObject(element, EDITOR_ROW_ATTR),\r\n          type: ElementType.CONTROL,\r\n          value: '',\r\n          control,\r\n          controlId\r\n        }\r\n        const valueList: IElement[] = []\r\n        while (e < elementList.length) {\r\n          const controlE = elementList[e]\r\n          if (controlId !== controlE.controlId) {\r\n            e--\r\n            break\r\n          }\r\n          if (controlE.controlComponent === ControlComponent.VALUE) {\r\n            delete controlE.control\r\n            delete controlE.controlId\r\n            valueList.push(controlE)\r\n          }\r\n          e++\r\n        }\r\n        controlElement.control!.value = zipElementList(valueList, options)\r\n        element = pickElementAttr(controlElement, { extraPickAttrs })\r\n      }\r\n    }\r\n    // 组合元素\r\n    const pickElement = pickElementAttr(element, { extraPickAttrs })\r\n    if (\r\n      !element.type ||\r\n      element.type === ElementType.TEXT ||\r\n      element.type === ElementType.SUBSCRIPT ||\r\n      element.type === ElementType.SUPERSCRIPT\r\n    ) {\r\n      while (e < elementList.length) {\r\n        const nextElement = elementList[e + 1]\r\n        e++\r\n        if (\r\n          nextElement &&\r\n          isSameElementExceptValue(\r\n            pickElement,\r\n            pickElementAttr(nextElement, { extraPickAttrs })\r\n          )\r\n        ) {\r\n          const nextValue =\r\n            nextElement.value === ZERO ? '\\n' : nextElement.value\r\n          pickElement.value += nextValue\r\n        } else {\r\n          break\r\n        }\r\n      }\r\n    } else {\r\n      e++\r\n    }\r\n    zipElementListData.push(pickElement)\r\n  }\r\n  return zipElementListData\r\n}\r\n\r\nexport function convertTextAlignToRowFlex(node: HTMLElement) {\r\n  const textAlign = window.getComputedStyle(node).textAlign\r\n  switch (textAlign) {\r\n    case 'left':\r\n    case 'start':\r\n      return RowFlex.LEFT\r\n    case 'center':\r\n      return RowFlex.CENTER\r\n    case 'right':\r\n    case 'end':\r\n      return RowFlex.RIGHT\r\n    case 'justify':\r\n      return RowFlex.ALIGNMENT\r\n    case 'justify-all':\r\n      return RowFlex.JUSTIFY\r\n    default:\r\n      return RowFlex.LEFT\r\n  }\r\n}\r\n\r\nexport function convertRowFlexToTextAlign(rowFlex: RowFlex) {\r\n  return rowFlex === RowFlex.ALIGNMENT ? 'justify' : rowFlex\r\n}\r\n\r\nexport function convertRowFlexToJustifyContent(rowFlex: RowFlex) {\r\n  switch (rowFlex) {\r\n    case RowFlex.LEFT:\r\n      return 'flex-start'\r\n    case RowFlex.CENTER:\r\n      return 'center'\r\n    case RowFlex.RIGHT:\r\n      return 'flex-end'\r\n    case RowFlex.ALIGNMENT:\r\n    case RowFlex.JUSTIFY:\r\n      return 'space-between'\r\n    default:\r\n      return 'flex-start'\r\n  }\r\n}\r\n\r\nexport function isTextLikeElement(element: IElement): boolean {\r\n  return !element.type || TEXTLIKE_ELEMENT_TYPE.includes(element.type)\r\n}\r\n\r\nexport function getAnchorElement(\r\n  elementList: IElement[],\r\n  anchorIndex: number\r\n): IElement | null {\r\n  const anchorElement = elementList[anchorIndex]\r\n  if (!anchorElement) return null\r\n  const anchorNextElement = elementList[anchorIndex + 1]\r\n  // 非列表元素 && 当前元素是换行符 && 下一个元素不是换行符 则以下一个元素作为参考元素\r\n  return !anchorElement.listId &&\r\n    anchorElement.value === ZERO &&\r\n    anchorNextElement &&\r\n    anchorNextElement.value !== ZERO\r\n    ? anchorNextElement\r\n    : anchorElement\r\n}\r\n\r\nexport interface IFormatElementContextOption {\r\n  isBreakWhenWrap?: boolean\r\n  editorOptions?: DeepRequired<IEditorOption>\r\n}\r\n\r\nexport function formatElementContext(\r\n  sourceElementList: IElement[],\r\n  formatElementList: IElement[],\r\n  anchorIndex: number,\r\n  options?: IFormatElementContextOption\r\n) {\r\n  let copyElement = getAnchorElement(sourceElementList, anchorIndex)\r\n  if (!copyElement) return\r\n  const { isBreakWhenWrap = false, editorOptions } = options || {}\r\n  const { mode } = editorOptions || {}\r\n  // 非设计模式时：标题元素禁用时不复制标题属性\r\n  if (mode !== EditorMode.DESIGN && copyElement.title?.disabled) {\r\n    copyElement = omitObject(copyElement, TITLE_CONTEXT_ATTR)\r\n  }\r\n  // 是否已经换行\r\n  let isBreakWarped = false\r\n  for (let e = 0; e < formatElementList.length; e++) {\r\n    const targetElement = formatElementList[e]\r\n    if (\r\n      isBreakWhenWrap &&\r\n      !copyElement.listId &&\r\n      START_LINE_BREAK_REG.test(targetElement.value)\r\n    ) {\r\n      isBreakWarped = true\r\n    }\r\n    // 1. 即使换行停止也要处理表格上下文信息\r\n    // 2. 定位元素非列表，无需处理粘贴列表的上下文，仅处理表格及行上下文信息\r\n    if (\r\n      isBreakWarped ||\r\n      (!copyElement.listId && targetElement.type === ElementType.LIST)\r\n    ) {\r\n      const cloneAttr = [...TABLE_CONTEXT_ATTR, ...EDITOR_ROW_ATTR]\r\n      cloneProperty<IElement>(cloneAttr, copyElement!, targetElement)\r\n      targetElement.valueList?.forEach(valueItem => {\r\n        cloneProperty<IElement>(cloneAttr, copyElement!, valueItem)\r\n      })\r\n      continue\r\n    }\r\n    if (targetElement.valueList?.length) {\r\n      formatElementContext(\r\n        sourceElementList,\r\n        targetElement.valueList,\r\n        anchorIndex,\r\n        options\r\n      )\r\n    }\r\n    // 非块类元素，需处理行属性\r\n    const cloneAttr = [...EDITOR_ELEMENT_CONTEXT_ATTR]\r\n    if (!getIsBlockElement(targetElement)) {\r\n      cloneAttr.push(...EDITOR_ROW_ATTR)\r\n    }\r\n    cloneProperty<IElement>(cloneAttr, copyElement, targetElement)\r\n  }\r\n}\r\n\r\nexport function convertElementToDom(\r\n  element: IElement,\r\n  options: DeepRequired<IEditorOption>\r\n): HTMLElement {\r\n  let tagName: keyof HTMLElementTagNameMap = 'span'\r\n  if (element.type === ElementType.SUPERSCRIPT) {\r\n    tagName = 'sup'\r\n  } else if (element.type === ElementType.SUBSCRIPT) {\r\n    tagName = 'sub'\r\n  }\r\n  const dom = document.createElement(tagName)\r\n  dom.style.fontFamily = element.font || options.defaultFont\r\n  if (element.rowFlex) {\r\n    dom.style.textAlign = convertRowFlexToTextAlign(element.rowFlex)\r\n  }\r\n  if (element.color) {\r\n    dom.style.color = element.color\r\n  }\r\n  if (element.bold) {\r\n    dom.style.fontWeight = '600'\r\n  }\r\n  if (element.italic) {\r\n    dom.style.fontStyle = 'italic'\r\n  }\r\n  dom.style.fontSize = `${element.size || options.defaultSize}px`\r\n  if (element.highlight) {\r\n    dom.style.backgroundColor = element.highlight\r\n  }\r\n  if (element.underline) {\r\n    dom.style.textDecoration = 'underline'\r\n  }\r\n  if (element.strikeout) {\r\n    dom.style.textDecoration += ' line-through'\r\n  }\r\n  dom.innerText = element.value.replace(new RegExp(`${ZERO}`, 'g'), '\\n')\r\n  return dom\r\n}\r\n\r\nexport function splitListElement(\r\n  elementList: IElement[]\r\n): Map<number, IElement[]> {\r\n  let curListIndex = 0\r\n  const listElementListMap: Map<number, IElement[]> = new Map()\r\n  for (let e = 0; e < elementList.length; e++) {\r\n    const element = elementList[e]\r\n    // 移除列表首行换行字符-如果是复选框直接忽略\r\n    if (e === 0) {\r\n      if (element.checkbox) continue\r\n      element.value = element.value.replace(START_LINE_BREAK_REG, '')\r\n    }\r\n    if (element.listWrap) {\r\n      const listElementList = listElementListMap.get(curListIndex) || []\r\n      listElementList.push(element)\r\n      listElementListMap.set(curListIndex, listElementList)\r\n    } else {\r\n      const valueList = element.value.split('\\n')\r\n      for (let c = 0; c < valueList.length; c++) {\r\n        if (c > 0) {\r\n          curListIndex += 1\r\n        }\r\n        const value = valueList[c]\r\n        const listElementList = listElementListMap.get(curListIndex) || []\r\n        listElementList.push({\r\n          ...element,\r\n          value\r\n        })\r\n        listElementListMap.set(curListIndex, listElementList)\r\n      }\r\n    }\r\n  }\r\n  return listElementListMap\r\n}\r\n\r\nexport interface IElementListGroupRowFlex {\r\n  rowFlex: RowFlex | null\r\n  data: IElement[]\r\n}\r\n\r\nexport function groupElementListByRowFlex(\r\n  elementList: IElement[]\r\n): IElementListGroupRowFlex[] {\r\n  const elementListGroupList: IElementListGroupRowFlex[] = []\r\n  if (!elementList.length) return elementListGroupList\r\n  let currentRowFlex: RowFlex | null = elementList[0]?.rowFlex || null\r\n  elementListGroupList.push({\r\n    rowFlex: currentRowFlex,\r\n    data: [elementList[0]]\r\n  })\r\n  for (let e = 1; e < elementList.length; e++) {\r\n    const element = elementList[e]\r\n    const rowFlex = element.rowFlex || null\r\n    // 行布局相同&非块元素时追加数据，否则新增分组\r\n    if (\r\n      currentRowFlex === rowFlex &&\r\n      !getIsBlockElement(element) &&\r\n      !getIsBlockElement(elementList[e - 1])\r\n    ) {\r\n      const lastElementListGroup =\r\n        elementListGroupList[elementListGroupList.length - 1]\r\n      lastElementListGroup.data.push(element)\r\n    } else {\r\n      elementListGroupList.push({\r\n        rowFlex,\r\n        data: [element]\r\n      })\r\n      currentRowFlex = rowFlex\r\n    }\r\n  }\r\n  // 压缩数据\r\n  for (let g = 0; g < elementListGroupList.length; g++) {\r\n    const elementListGroup = elementListGroupList[g]\r\n    elementListGroup.data = zipElementList(elementListGroup.data)\r\n  }\r\n  return elementListGroupList\r\n}\r\n\r\nexport function createDomFromElementList(\r\n  elementList: IElement[],\r\n  options?: IEditorOption\r\n) {\r\n  // const editorOptions = mergeOption(options)\r\n  function buildDom(payload: IElement[]): HTMLDivElement {\r\n    const clipboardDom = document.createElement('div')\r\n    for (let e = 0; e < payload.length; e++) {\r\n      const element = payload[e]\r\n      // 构造表格\r\n      if (element.type === ElementType.TABLE) {\r\n        const tableDom: HTMLTableElement = document.createElement('table')\r\n        tableDom.setAttribute('cellSpacing', '0')\r\n        tableDom.setAttribute('cellpadding', '0')\r\n        tableDom.setAttribute('border', '0')\r\n        const borderStyle = '1px solid #000000'\r\n        // 表格边框\r\n        if (!element.borderType || element.borderType === TableBorder.ALL) {\r\n          tableDom.style.borderTop = borderStyle\r\n          tableDom.style.borderLeft = borderStyle\r\n        } else if (element.borderType === TableBorder.EXTERNAL) {\r\n          tableDom.style.border = borderStyle\r\n        }\r\n        tableDom.style.width = `${element.width}px`\r\n        // colgroup\r\n        const colgroupDom = document.createElement('colgroup')\r\n        for (let c = 0; c < element.colgroup!.length; c++) {\r\n          const colgroup = element.colgroup![c]\r\n          const colDom = document.createElement('col')\r\n          colDom.setAttribute('width', `${colgroup.width}`)\r\n          colgroupDom.append(colDom)\r\n        }\r\n        tableDom.append(colgroupDom)\r\n        // tr\r\n        const trList = element.trList!\r\n        for (let t = 0; t < trList.length; t++) {\r\n          const trDom = document.createElement('tr')\r\n          const tr = trList[t]\r\n          trDom.style.height = `${tr.height}px`\r\n          for (let d = 0; d < tr.tdList.length; d++) {\r\n            const tdDom = document.createElement('td')\r\n            if (!element.borderType || element.borderType === TableBorder.ALL) {\r\n              tdDom.style.borderBottom = tdDom.style.borderRight = '1px solid'\r\n            }\r\n            const td = tr.tdList[d]\r\n            tdDom.colSpan = td.colspan\r\n            tdDom.rowSpan = td.rowspan\r\n            tdDom.style.verticalAlign = td.verticalAlign || 'top'\r\n            // 单元格边框\r\n            if (td.borderTypes?.includes(TdBorder.TOP)) {\r\n              tdDom.style.borderTop = borderStyle\r\n            }\r\n            if (td.borderTypes?.includes(TdBorder.RIGHT)) {\r\n              tdDom.style.borderRight = borderStyle\r\n            }\r\n            if (td.borderTypes?.includes(TdBorder.BOTTOM)) {\r\n              tdDom.style.borderBottom = borderStyle\r\n            }\r\n            if (td.borderTypes?.includes(TdBorder.LEFT)) {\r\n              tdDom.style.borderLeft = borderStyle\r\n            }\r\n            const childDom = createDomFromElementList(td.value!, options)\r\n            tdDom.innerHTML = childDom.innerHTML\r\n            if (td.backgroundColor) {\r\n              tdDom.style.backgroundColor = td.backgroundColor\r\n            }\r\n            trDom.append(tdDom)\r\n          }\r\n          tableDom.append(trDom)\r\n        }\r\n        clipboardDom.append(tableDom)\r\n      } else if (element.type === ElementType.HYPERLINK) {\r\n        const a = document.createElement('a')\r\n        a.innerText = element.valueList!.map(v => v.value).join('')\r\n        if (element.url) {\r\n          a.href = element.url\r\n        }\r\n        clipboardDom.append(a)\r\n      } else if (element.type === ElementType.TITLE) {\r\n        const h = document.createElement(\r\n          `h${titleOrderNumberMapping[element.level!]}`\r\n        )\r\n        const childDom = buildDom(element.valueList!)\r\n        h.innerHTML = childDom.innerHTML\r\n        clipboardDom.append(h)\r\n      } else if (element.type === ElementType.LIST) {\r\n        const list = document.createElement(\r\n          listTypeElementMapping[element.listType!]\r\n        )\r\n        if (element.listStyle) {\r\n          list.style.listStyleType = listStyleCSSMapping[element.listStyle]\r\n        }\r\n        // 按照换行符拆分\r\n        const zipList = zipElementList(element.valueList!)\r\n        const listElementListMap = splitListElement(zipList)\r\n        listElementListMap.forEach(listElementList => {\r\n          const li = document.createElement('li')\r\n          const childDom = buildDom(listElementList)\r\n          li.innerHTML = childDom.innerHTML\r\n          list.append(li)\r\n        })\r\n        clipboardDom.append(list)\r\n      } else if (element.type === ElementType.IMAGE) {\r\n        const img = document.createElement('img')\r\n        if (element.value) {\r\n          img.src = element.value\r\n          img.width = element.width!\r\n          img.height = element.height!\r\n        }\r\n        clipboardDom.append(img)\r\n      } else if (element.type === ElementType.SEPARATOR) {\r\n        const hr = document.createElement('hr')\r\n        clipboardDom.append(hr)\r\n      } else if (element.type === ElementType.CHECKBOX) {\r\n        const checkbox = document.createElement('input')\r\n        checkbox.type = 'checkbox'\r\n        if (element.checkbox?.value) {\r\n          checkbox.setAttribute('checked', 'true')\r\n        }\r\n        clipboardDom.append(checkbox)\r\n      } else if (element.type === ElementType.RADIO) {\r\n        const radio = document.createElement('input')\r\n        radio.type = 'radio'\r\n        if (element.radio?.value) {\r\n          radio.setAttribute('checked', 'true')\r\n        }\r\n        clipboardDom.append(radio)\r\n      } else if (element.type === ElementType.TAB) {\r\n        const tab = document.createElement('span')\r\n        tab.innerHTML = `${NON_BREAKING_SPACE}${NON_BREAKING_SPACE}`\r\n        clipboardDom.append(tab)\r\n      } else if (element.type === ElementType.CONTROL) {\r\n        const controlElement = document.createElement('span')\r\n        const childDom = buildDom(element.control?.value || [])\r\n        controlElement.innerHTML = childDom.innerHTML\r\n        clipboardDom.append(controlElement)\r\n      } else if (\r\n        !element.type ||\r\n        element.type === ElementType.LATEX ||\r\n        TEXTLIKE_ELEMENT_TYPE.includes(element.type)\r\n      ) {\r\n        let text = ''\r\n        if (element.type === ElementType.DATE) {\r\n          text = element.valueList?.map(v => v.value).join('') || ''\r\n        } else {\r\n          text = element.value\r\n        }\r\n        if (!text) continue\r\n        // const dom = convertElementToDom(element, editorOptions)\r\n        // 前一个元素是标题，移除首行换行符\r\n        if (payload[e - 1]?.type === ElementType.TITLE) {\r\n          text = text.replace(/^\\n/, '')\r\n        }\r\n        // dom.innerText = text.replace(new RegExp(`${ZERO}`, 'g'), '\\n')\r\n        // clipboardDom.append(dom)\r\n      }\r\n    }\r\n    return clipboardDom\r\n  }\r\n  // 按行布局分类创建dom\r\n  const clipboardDom = document.createElement('div')\r\n  const groupElementList = groupElementListByRowFlex(elementList)\r\n  for (let g = 0; g < groupElementList.length; g++) {\r\n    const elementGroupRowFlex = groupElementList[g]\r\n    // 行布局样式设置\r\n    const isDefaultRowFlex =\r\n      !elementGroupRowFlex.rowFlex ||\r\n      elementGroupRowFlex.rowFlex === RowFlex.LEFT\r\n    // 块元素使用flex否则使用text-align\r\n    const rowFlexDom = document.createElement('div')\r\n    if (!isDefaultRowFlex) {\r\n      const firstElement = elementGroupRowFlex.data[0]\r\n      if (getIsBlockElement(firstElement)) {\r\n        rowFlexDom.style.display = 'flex'\r\n        rowFlexDom.style.justifyContent = convertRowFlexToJustifyContent(\r\n          firstElement.rowFlex!\r\n        )\r\n      } else {\r\n        rowFlexDom.style.textAlign = convertRowFlexToTextAlign(\r\n          elementGroupRowFlex.rowFlex!\r\n        )\r\n      }\r\n    }\r\n    // 布局内容\r\n    rowFlexDom.innerHTML = buildDom(elementGroupRowFlex.data).innerHTML\r\n    // 未设置行布局时无需行布局容器\r\n    if (!isDefaultRowFlex) {\r\n      clipboardDom.append(rowFlexDom)\r\n    } else {\r\n      rowFlexDom.childNodes.forEach(child => {\r\n        clipboardDom.append(child.cloneNode(true))\r\n      })\r\n    }\r\n  }\r\n  return clipboardDom\r\n}\r\n\r\nexport function convertTextNodeToElement(\r\n  textNode: Element | Node\r\n): IElement | null {\r\n  if (!textNode || textNode.nodeType !== 3) return null\r\n  const parentNode = <HTMLElement>textNode.parentNode\r\n  const anchorNode =\r\n    parentNode.nodeName === 'FONT'\r\n      ? <HTMLElement>parentNode.parentNode\r\n      : parentNode\r\n  const rowFlex = convertTextAlignToRowFlex(anchorNode)\r\n  const value = textNode.textContent\r\n  const style = window.getComputedStyle(anchorNode)\r\n  if (!value || anchorNode.nodeName === 'STYLE') return null\r\n  const element: IElement = {\r\n    value,\r\n    color: style.color,\r\n    bold: Number(style.fontWeight) > 500,\r\n    italic: style.fontStyle.includes('italic'),\r\n    size: Math.floor(parseFloat(style.fontSize))\r\n  }\r\n  // 元素类型-默认文本\r\n  if (anchorNode.nodeName === 'SUB' || style.verticalAlign === 'sub') {\r\n    element.type = ElementType.SUBSCRIPT\r\n  } else if (anchorNode.nodeName === 'SUP' || style.verticalAlign === 'super') {\r\n    element.type = ElementType.SUPERSCRIPT\r\n  }\r\n  // 行对齐\r\n  if (rowFlex !== RowFlex.LEFT) {\r\n    element.rowFlex = rowFlex\r\n  }\r\n  // 高亮色\r\n  if (style.backgroundColor !== 'rgba(0, 0, 0, 0)') {\r\n    element.highlight = style.backgroundColor\r\n  }\r\n  // 下划线\r\n  if (style.textDecorationLine.includes('underline')) {\r\n    element.underline = true\r\n  }\r\n  // 删除线\r\n  if (style.textDecorationLine.includes('line-through')) {\r\n    element.strikeout = true\r\n  }\r\n  return element\r\n}\r\n\r\ninterface IGetElementListByHTMLOption {\r\n  innerWidth: number\r\n}\r\n\r\nexport function getElementListByHTML(\r\n  htmlText: string,\r\n  options: IGetElementListByHTMLOption\r\n): IElement[] {\r\n  const elementList: IElement[] = []\r\n  function findTextNode(dom: Element | Node) {\r\n    if (dom.nodeType === 3) {\r\n      const element = convertTextNodeToElement(dom)\r\n      if (element) {\r\n        elementList.push(element)\r\n      }\r\n    } else if (dom.nodeType === 1) {\r\n      const childNodes = dom.childNodes\r\n      for (let n = 0; n < childNodes.length; n++) {\r\n        const node = childNodes[n]\r\n        // br元素与display:block元素需换行\r\n        if (node.nodeName === 'BR') {\r\n          elementList.push({\r\n            value: '\\n'\r\n          })\r\n        } else if (node.nodeName === 'A') {\r\n          const aElement = node as HTMLLinkElement\r\n          const value = aElement.innerText\r\n          if (value) {\r\n            elementList.push({\r\n              type: ElementType.HYPERLINK,\r\n              value: '',\r\n              valueList: [\r\n                {\r\n                  value\r\n                }\r\n              ],\r\n              url: aElement.href\r\n            })\r\n          }\r\n        } else if (/H[1-6]/.test(node.nodeName)) {\r\n          const hElement = node as HTMLTitleElement\r\n          const valueList = getElementListByHTML(\r\n            replaceHTMLElementTag(hElement, 'div').outerHTML,\r\n            options\r\n          )\r\n          elementList.push({\r\n            value: '',\r\n            type: ElementType.TITLE,\r\n            level: titleNodeNameMapping[node.nodeName],\r\n            valueList\r\n          })\r\n          if (\r\n            node.nextSibling &&\r\n            !INLINE_NODE_NAME.includes(node.nextSibling.nodeName)\r\n          ) {\r\n            elementList.push({\r\n              value: '\\n'\r\n            })\r\n          }\r\n        } else if (node.nodeName === 'UL' || node.nodeName === 'OL') {\r\n          const listNode = node as HTMLOListElement | HTMLUListElement\r\n          const listElement: IElement = {\r\n            value: '',\r\n            type: ElementType.LIST,\r\n            valueList: []\r\n          }\r\n          if (node.nodeName === 'OL') {\r\n            listElement.listType = ListType.OL\r\n          } else {\r\n            listElement.listType = ListType.UL\r\n            listElement.listStyle = <ListStyle>(\r\n              (<unknown>listNode.style.listStyleType)\r\n            )\r\n          }\r\n          listNode.querySelectorAll('li').forEach(li => {\r\n            const liValueList = getElementListByHTML(li.innerHTML, options)\r\n            liValueList.forEach(list => {\r\n              if (list.value === '\\n') {\r\n                list.listWrap = true\r\n              }\r\n            })\r\n            liValueList.unshift({\r\n              value: '\\n'\r\n            })\r\n            listElement.valueList!.push(...liValueList)\r\n          })\r\n          elementList.push(listElement)\r\n        } else if (node.nodeName === 'HR') {\r\n          elementList.push({\r\n            value: '\\n',\r\n            type: ElementType.SEPARATOR\r\n          })\r\n        } else if (node.nodeName === 'IMG') {\r\n          const { src, width, height } = node as HTMLImageElement\r\n          if (src && width && height) {\r\n            elementList.push({\r\n              width,\r\n              height,\r\n              value: src,\r\n              type: ElementType.IMAGE\r\n            })\r\n          }\r\n        } else if (node.nodeName === 'TABLE') {\r\n          const tableElement = node as HTMLTableElement\r\n          const element: IElement = {\r\n            type: ElementType.TABLE,\r\n            value: '\\n',\r\n            colgroup: [],\r\n            trList: []\r\n          }\r\n          // 基础数据\r\n          tableElement.querySelectorAll('tr').forEach(trElement => {\r\n            const trHeightStr = window\r\n              .getComputedStyle(trElement)\r\n              .height.replace('px', '')\r\n            const tr: ITr = {\r\n              height: Number(trHeightStr),\r\n              tdList: []\r\n            }\r\n            trElement.querySelectorAll('th,td').forEach(tdElement => {\r\n              const tableCell = <HTMLTableCellElement>tdElement\r\n              const valueList = getElementListByHTML(\r\n                tableCell.innerHTML,\r\n                options\r\n              )\r\n              const td: ITd = {\r\n                colspan: tableCell.colSpan,\r\n                rowspan: tableCell.rowSpan,\r\n                value: valueList\r\n              }\r\n              if (tableCell.style.backgroundColor) {\r\n                td.backgroundColor = tableCell.style.backgroundColor\r\n              }\r\n              tr.tdList.push(td)\r\n            })\r\n            element.trList!.push(tr)\r\n          })\r\n          if (element.trList!.length) {\r\n            // 列选项数据\r\n            const tdCount = element.trList![0].tdList.reduce(\r\n              (pre, cur) => pre + cur.colspan,\r\n              0\r\n            )\r\n            const width = Math.ceil(options.innerWidth / tdCount)\r\n            for (let i = 0; i < tdCount; i++) {\r\n              element.colgroup!.push({\r\n                width\r\n              })\r\n            }\r\n            elementList.push(element)\r\n          }\r\n        } else if (\r\n          node.nodeName === 'INPUT' &&\r\n          (<HTMLInputElement>node).type === ControlComponent.CHECKBOX\r\n        ) {\r\n          elementList.push({\r\n            type: ElementType.CHECKBOX,\r\n            value: '',\r\n            checkbox: {\r\n              value: (<HTMLInputElement>node).checked\r\n            }\r\n          })\r\n        } else if (\r\n          node.nodeName === 'INPUT' &&\r\n          (<HTMLInputElement>node).type === ControlComponent.RADIO\r\n        ) {\r\n          elementList.push({\r\n            type: ElementType.RADIO,\r\n            value: '',\r\n            radio: {\r\n              value: (<HTMLInputElement>node).checked\r\n            }\r\n          })\r\n        } else {\r\n          findTextNode(node)\r\n          if (node.nodeType === 1 && n !== childNodes.length - 1) {\r\n            const display = window.getComputedStyle(node as Element).display\r\n            if (display === 'block') {\r\n              elementList.push({\r\n                value: '\\n'\r\n              })\r\n            }\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n  // 追加dom\r\n  const clipboardDom = document.createElement('div')\r\n  clipboardDom.innerHTML = htmlText\r\n  document.body.appendChild(clipboardDom)\r\n  const deleteNodes: ChildNode[] = []\r\n  clipboardDom.childNodes.forEach(child => {\r\n    if (child.nodeType !== 1 && !child.textContent?.trim()) {\r\n      deleteNodes.push(child)\r\n    }\r\n  })\r\n  deleteNodes.forEach(node => node.remove())\r\n  // 搜索文本节点\r\n  findTextNode(clipboardDom)\r\n  // 移除dom\r\n  clipboardDom.remove()\r\n  return elementList\r\n}\r\n\r\nexport function getTextFromElementList(elementList: IElement[]) {\r\n  function buildText(payload: IElement[]): string {\r\n    let text = ''\r\n    for (let e = 0; e < payload.length; e++) {\r\n      const element = payload[e]\r\n      // 构造表格\r\n      if (element.type === ElementType.TABLE) {\r\n        text += `\\n`\r\n        const trList = element.trList!\r\n        for (let t = 0; t < trList.length; t++) {\r\n          const tr = trList[t]\r\n          for (let d = 0; d < tr.tdList.length; d++) {\r\n            const td = tr.tdList[d]\r\n            const tdText = buildText(zipElementList(td.value!))\r\n            const isFirst = d === 0\r\n            const isLast = tr.tdList.length - 1 === d\r\n            text += `${!isFirst ? `  ` : ``}${tdText}${isLast ? `\\n` : ``}`\r\n          }\r\n        }\r\n      } else if (element.type === ElementType.TAB) {\r\n        text += `\\t`\r\n      } else if (element.type === ElementType.HYPERLINK) {\r\n        text += element.valueList!.map(v => v.value).join('')\r\n      } else if (element.type === ElementType.TITLE) {\r\n        text += `${buildText(zipElementList(element.valueList!))}`\r\n      } else if (element.type === ElementType.LIST) {\r\n        // 按照换行符拆分\r\n        const zipList = zipElementList(element.valueList!)\r\n        const listElementListMap = splitListElement(zipList)\r\n        // 无序列表前缀\r\n        let ulListStyleText = ''\r\n        if (element.listType === ListType.UL) {\r\n          ulListStyleText =\r\n            ulStyleMapping[<UlStyle>(<unknown>element.listStyle)]\r\n        }\r\n        listElementListMap.forEach((listElementList, listIndex) => {\r\n          const isLast = listElementListMap.size - 1 === listIndex\r\n          text += `\\n${ulListStyleText || `${listIndex + 1}.`}${buildText(\r\n            listElementList\r\n          )}${isLast ? `\\n` : ``}`\r\n        })\r\n      } else if (element.type === ElementType.CHECKBOX) {\r\n        text += element.checkbox?.value ? `☑` : `□`\r\n      } else if (element.type === ElementType.RADIO) {\r\n        text += element.radio?.value ? `☉` : `○`\r\n      } else if (\r\n        !element.type ||\r\n        element.type === ElementType.LATEX ||\r\n        TEXTLIKE_ELEMENT_TYPE.includes(element.type)\r\n      ) {\r\n        let textLike = ''\r\n        if (element.type === ElementType.CONTROL) {\r\n          textLike = element.control!.value?.[0]?.value || ''\r\n        } else if (element.type === ElementType.DATE) {\r\n          textLike = element.valueList?.map(v => v.value).join('') || ''\r\n        } else {\r\n          textLike = element.value\r\n        }\r\n        text += textLike.replace(new RegExp(`${ZERO}`, 'g'), '\\n')\r\n      }\r\n    }\r\n    return text\r\n  }\r\n  return buildText(zipElementList(elementList))\r\n}\r\n\r\nexport function getSlimCloneElementList(elementList: IElement[]) {\r\n  return deepCloneOmitKeys<IElement[], IRowElement>(elementList, [\r\n    'metrics',\r\n    'style'\r\n  ])\r\n}\r\n\r\nexport function getIsBlockElement(element?: IElement) {\r\n  return (\r\n    !!element?.type &&\r\n    (BLOCK_ELEMENT_TYPE.includes(element.type) ||\r\n      element.imgDisplay === ImageDisplay.INLINE)\r\n  )\r\n}\r\n\r\nexport function replaceHTMLElementTag(\r\n  oldDom: HTMLElement,\r\n  tagName: keyof HTMLElementTagNameMap\r\n): HTMLElement {\r\n  const newDom = document.createElement(tagName)\r\n  for (let i = 0; i < oldDom.attributes.length; i++) {\r\n    const attr = oldDom.attributes[i]\r\n    newDom.setAttribute(attr.name, attr.value)\r\n  }\r\n  newDom.innerHTML = oldDom.innerHTML\r\n  return newDom\r\n}\r\n\r\nexport function pickSurroundElementList(elementList: IElement[]) {\r\n  const surroundElementList: IElement[] = []\r\n  for (let e = 0; e < elementList.length; e++) {\r\n    const element = elementList[e]\r\n    if (element.imgDisplay === ImageDisplay.SURROUND) {\r\n      surroundElementList.push(element)\r\n    }\r\n  }\r\n  return surroundElementList\r\n}\r\n\r\nexport function deleteSurroundElementList(\r\n  elementList: IElement[],\r\n  pageNo: number\r\n) {\r\n  for (let s = elementList.length - 1; s >= 0; s--) {\r\n    const surroundElement = elementList[s]\r\n    if (surroundElement.imgFloatPosition?.pageNo === pageNo) {\r\n      elementList.splice(s, 1)\r\n    }\r\n  }\r\n}\r\n","export enum VerticalAlign {\r\n  TOP = 'top',\r\n  MIDDLE = 'middle',\r\n  BOTTOM = 'bottom'\r\n}\r\n","// import { ElementType, ListStyle, RowFlex, VerticalAlign } from '@hufe921/canvas-editor'\r\nimport { ZERO } from '../../dataset/constant/Common'\r\nimport { ControlComponent } from '../../dataset/enum/Control'\r\nimport {\r\n  IComputePageRowPositionPayload,\r\n  IComputePageRowPositionResult,\r\n  IComputeRowPositionPayload,\r\n  IFloatPosition,\r\n  IGetFloatPositionByXYPayload,\r\n  ISetSurroundPositionPayload\r\n} from '../../interface/Position'\r\nimport { IEditorOption } from '../../interface/Editor'\r\nimport { IElement, IElementPosition } from '../../interface/Element'\r\nimport {\r\n  ICurrentPosition,\r\n  IGetPositionByXYPayload,\r\n  IPositionContext\r\n} from '../../interface/Position'\r\nimport { DrawPdf } from '../draw/DrawPdf'\r\nimport { EditorZone } from '../../dataset/enum/Editor'\r\nimport { deepClone, isRectIntersect } from '../../utils'\r\nimport { ImageDisplay } from '../../dataset/enum/Common'\r\nimport { DeepRequired } from '../../interface/Common'\r\n// import { EventBus } from '../event/eventbus/EventBus'\r\n// import { EventBusMap } from '../../interface/EventBus'\r\nimport { getIsBlockElement } from '../../utils/element'\r\nimport { RowFlex } from '../../dataset/enum/Row'\r\nimport { ElementType } from '../../dataset/enum/Element'\r\nimport { VerticalAlign } from '../../dataset/enum/VerticalAlign'\r\nimport { ListStyle } from '../../dataset/enum/List'\r\n\r\nexport class Position {\r\n  private cursorPosition: IElementPosition | null\r\n  private positionContext: IPositionContext\r\n  private positionList: IElementPosition[]\r\n  private floatPositionList: IFloatPosition[]\r\n\r\n  private draw: DrawPdf\r\n  // private eventBus: EventBus<EventBusMap>\r\n  private options: DeepRequired<IEditorOption>\r\n\r\n  constructor(draw: DrawPdf) {\r\n    this.positionList = []\r\n    this.floatPositionList = []\r\n    this.cursorPosition = null\r\n    this.positionContext = {\r\n      isTable: false,\r\n      isControl: false\r\n    }\r\n\r\n    this.draw = draw\r\n    // this.eventBus = draw.getEventBus()\r\n    this.options = draw.getOptions()\r\n  }\r\n\r\n  public getFloatPositionList(): IFloatPosition[] {\r\n    return this.floatPositionList\r\n  }\r\n\r\n  public getTablePositionList(\r\n    sourceElementList: IElement[]\r\n  ): IElementPosition[] {\r\n    const { index, trIndex, tdIndex } = this.positionContext\r\n    return (\r\n      sourceElementList[index!].trList![trIndex!].tdList[tdIndex!]\r\n        .positionList || []\r\n    )\r\n  }\r\n\r\n  public getPositionList(): IElementPosition[] {\r\n    return this.positionContext.isTable\r\n      ? this.getTablePositionList(this.draw.getOriginalElementList())\r\n      : this.getOriginalPositionList()\r\n  }\r\n\r\n  public getMainPositionList(): IElementPosition[] {\r\n    return this.positionContext.isTable\r\n      ? this.getTablePositionList(this.draw.getOriginalMainElementList())\r\n      : this.positionList\r\n  }\r\n\r\n  public getOriginalPositionList(): IElementPosition[] {\r\n    // const zoneManager = this.draw.getZone()\r\n    // if (zoneManager.isHeaderActive()) {\r\n    //   const header = this.draw.getHeader()\r\n    //   return header.getPositionList()\r\n    // }\r\n    // if (zoneManager.isFooterActive()) {\r\n    //   const footer = this.draw.getFooter()\r\n    //   return footer.getPositionList()\r\n    // }\r\n    return this.positionList\r\n  }\r\n\r\n  public getOriginalMainPositionList(): IElementPosition[] {\r\n    return this.positionList\r\n  }\r\n\r\n  // public getSelectionPositionList(): IElementPosition[] | null {\r\n  //   const { startIndex, endIndex } = this.draw.getRange().getRange()\r\n  //   if (startIndex === endIndex) return null\r\n  //   const positionList = this.getPositionList()\r\n  //   return positionList.slice(startIndex + 1, endIndex + 1)\r\n  // }\r\n\r\n  public setPositionList(payload: IElementPosition[]) {\r\n    this.positionList = payload\r\n  }\r\n\r\n  public setFloatPositionList(payload: IFloatPosition[]) {\r\n    this.floatPositionList = payload\r\n  }\r\n\r\n  public computePageRowPosition(\r\n    payload: IComputePageRowPositionPayload\r\n  ): IComputePageRowPositionResult {\r\n    const {\r\n      positionList,\r\n      rowList,\r\n      pageNo,\r\n      startX,\r\n      startY,\r\n      startRowIndex,\r\n      startIndex,\r\n      innerWidth,\r\n      zone\r\n    } = payload\r\n    const {\r\n      scale,\r\n      table: { tdPadding }\r\n    } = this.options\r\n    let x = startX\r\n    let y = startY\r\n    let index = startIndex\r\n    for (let i = 0; i < rowList.length; i++) {\r\n      const curRow = rowList[i]\r\n      // 行存在环绕的可能性均不设置行布局\r\n      if (!curRow.isSurround) {\r\n        // 计算行偏移量（行居中、居右）\r\n        const curRowWidth = curRow.width + (curRow.offsetX || 0)\r\n        if (curRow.rowFlex === RowFlex.CENTER) {\r\n          // console.log('curRow')\r\n          // console.log(curRow)\r\n          // console.log('innerWidth, curRowWidth')\r\n          // console.log(innerWidth, curRowWidth)\r\n          // console.log('x', x)\r\n          x += (innerWidth - curRowWidth) / 2\r\n          // console.log('x', x)\r\n        } else if (curRow.rowFlex === RowFlex.RIGHT) {\r\n          x += innerWidth - curRowWidth\r\n        }\r\n      }\r\n      // 当前行X轴偏移量\r\n      x += curRow.offsetX || 0\r\n      // 当前td所在位置\r\n      const tablePreX = x\r\n      const tablePreY = y\r\n      for (let j = 0; j < curRow.elementList.length; j++) {\r\n        const element = curRow.elementList[j]\r\n        const metrics = element.metrics\r\n        const offsetY =\r\n          (element.imgDisplay !== ImageDisplay.INLINE &&\r\n            element.type === ElementType.IMAGE) ||\r\n            element.type === ElementType.LATEX\r\n            ? curRow.ascent - metrics.height\r\n            : curRow.ascent\r\n        // 偏移量\r\n        if (element.left) {\r\n          x += element.left\r\n        }\r\n        const positionItem: IElementPosition = {\r\n          pageNo,\r\n          index,\r\n          value: element.value,\r\n          rowIndex: startRowIndex + i,\r\n          rowNo: i,\r\n          metrics,\r\n          left: element.left || 0,\r\n          ascent: offsetY,\r\n          lineHeight: curRow.height,\r\n          isFirstLetter: j === 0,\r\n          isLastLetter: j === curRow.elementList.length - 1,\r\n          coordinate: {\r\n            leftTop: [x, y],\r\n            leftBottom: [x, y + curRow.height],\r\n            rightTop: [x + metrics.width, y],\r\n            rightBottom: [x + metrics.width, y + curRow.height]\r\n          }\r\n        }\r\n        // 缓存浮动元素信息\r\n        if (\r\n          element.imgDisplay === ImageDisplay.SURROUND ||\r\n          element.imgDisplay === ImageDisplay.FLOAT_TOP ||\r\n          element.imgDisplay === ImageDisplay.FLOAT_BOTTOM\r\n        ) {\r\n          // 浮动元素使用上一位置信息\r\n          const prePosition = positionList[positionList.length - 1]\r\n          if (prePosition) {\r\n            positionItem.metrics = prePosition.metrics\r\n            positionItem.coordinate = prePosition.coordinate\r\n          }\r\n          // 兼容浮动元素初始坐标为空的情况-默认使用左上坐标\r\n          if (!element.imgFloatPosition) {\r\n            element.imgFloatPosition = {\r\n              x,\r\n              y,\r\n              pageNo\r\n            }\r\n          }\r\n          this.floatPositionList.push({\r\n            pageNo,\r\n            element,\r\n            position: positionItem,\r\n            isTable: payload.isTable,\r\n            index: payload.index,\r\n            tdIndex: payload.tdIndex,\r\n            trIndex: payload.trIndex,\r\n            tdValueIndex: index,\r\n            zone\r\n          })\r\n        }\r\n        positionList.push(positionItem)\r\n        index++\r\n        x += metrics.width\r\n        // 计算表格内元素位置\r\n        if (element.type === ElementType.TABLE) {\r\n          const tdPaddingWidth = tdPadding[1] + tdPadding[3]\r\n          const tdPaddingHeight = tdPadding[0] + tdPadding[2]\r\n          for (let t = 0; t < element.trList!.length; t++) {\r\n            const tr = element.trList![t]\r\n            for (let d = 0; d < tr.tdList!.length; d++) {\r\n              const td = tr.tdList[d]\r\n              td.positionList = []\r\n              const rowList = td.rowList!\r\n              const drawRowResult = this.computePageRowPosition({\r\n                positionList: td.positionList,\r\n                rowList,\r\n                pageNo,\r\n                startRowIndex: 0,\r\n                startIndex: 0,\r\n                startX: (td.x! + tdPadding[3]) * scale + tablePreX,\r\n                startY: (td.y! + tdPadding[0]) * scale + tablePreY,\r\n                innerWidth: (td.width! - tdPaddingWidth) * scale,\r\n                isTable: true,\r\n                index: index - 1,\r\n                tdIndex: d,\r\n                trIndex: t,\r\n                zone\r\n              })\r\n              // 垂直对齐方式\r\n              if (\r\n                td.verticalAlign === VerticalAlign.MIDDLE ||\r\n                td.verticalAlign === VerticalAlign.BOTTOM\r\n              ) {\r\n                const rowsHeight = rowList.reduce(\r\n                  (pre, cur) => pre + cur.height,\r\n                  0\r\n                )\r\n                const blankHeight =\r\n                  (td.height! - tdPaddingHeight) * scale - rowsHeight\r\n                const offsetHeight =\r\n                  td.verticalAlign === VerticalAlign.MIDDLE\r\n                    ? blankHeight / 2\r\n                    : blankHeight\r\n                if (Math.floor(offsetHeight) > 0) {\r\n                  td.positionList.forEach(tdPosition => {\r\n                    const {\r\n                      coordinate: { leftTop, leftBottom, rightBottom, rightTop }\r\n                    } = tdPosition\r\n                    leftTop[1] += offsetHeight\r\n                    leftBottom[1] += offsetHeight\r\n                    rightBottom[1] += offsetHeight\r\n                    rightTop[1] += offsetHeight\r\n                  })\r\n                }\r\n              }\r\n              x = drawRowResult.x\r\n              y = drawRowResult.y\r\n            }\r\n          }\r\n          // 恢复初始x、y\r\n          x = tablePreX\r\n          y = tablePreY\r\n        }\r\n      }\r\n      x = startX\r\n      y += curRow.height\r\n    }\r\n    return { x, y, index }\r\n  }\r\n\r\n  public computePositionList() {\r\n    // 置空原位置信息\r\n    this.positionList = []\r\n    // 按每页行计算\r\n    const innerWidth = this.draw.getInnerWidth()\r\n    const pageRowList = this.draw.getPageRowList()\r\n    const margins = this.draw.getMargins()\r\n    const startX = margins[3]\r\n    // 起始位置受页眉影响\r\n    const header = this.draw.getHeader()\r\n    const extraHeight = header.getExtraHeight()\r\n    const startY = margins[0] + extraHeight\r\n    let startRowIndex = 0\r\n    for (let i = 0; i < pageRowList.length; i++) {\r\n      const rowList = pageRowList[i]\r\n      const startIndex = rowList[0]?.startIndex\r\n      this.computePageRowPosition({\r\n        positionList: this.positionList,\r\n        rowList,\r\n        pageNo: i,\r\n        startRowIndex,\r\n        startIndex,\r\n        startX,\r\n        startY,\r\n        innerWidth\r\n      })\r\n      startRowIndex += rowList.length\r\n    }\r\n  }\r\n\r\n  public computeRowPosition(\r\n    payload: IComputeRowPositionPayload\r\n  ): IElementPosition[] {\r\n    const { row, innerWidth } = payload\r\n    const positionList: IElementPosition[] = []\r\n    this.computePageRowPosition({\r\n      positionList,\r\n      innerWidth,\r\n      rowList: [deepClone(row)],\r\n      pageNo: 0,\r\n      startX: 0,\r\n      startY: 0,\r\n      startIndex: 0,\r\n      startRowIndex: 0\r\n    })\r\n    return positionList\r\n  }\r\n\r\n  public setCursorPosition(position: IElementPosition | null) {\r\n    this.cursorPosition = position\r\n  }\r\n\r\n  public getCursorPosition(): IElementPosition | null {\r\n    return this.cursorPosition\r\n  }\r\n\r\n  public getPositionContext(): IPositionContext {\r\n    return this.positionContext\r\n  }\r\n\r\n  public setPositionContext(payload: IPositionContext) {\r\n    // this.eventBus.emit('positionContextChange', {\r\n    //   value: payload,\r\n    //   oldValue: this.positionContext\r\n    // })\r\n    this.positionContext = payload\r\n  }\r\n\r\n  public getPositionByXY(payload: IGetPositionByXYPayload): ICurrentPosition {\r\n    const { x, y, isTable } = payload\r\n    let { elementList, positionList } = payload\r\n    if (!elementList) {\r\n      elementList = this.draw.getOriginalElementList()\r\n    }\r\n    if (!positionList) {\r\n      positionList = this.getOriginalPositionList()\r\n    }\r\n    // const zoneManager = this.draw.getZone()\r\n    const curPageNo = payload.pageNo ?? this.draw.getPageNo()\r\n    // const isMainActive = zoneManager.isMainActive()\r\n    const positionNo = curPageNo//isMainActive ? curPageNo : 0\r\n    // 验证浮于文字上方元素\r\n    if (!isTable) {\r\n      const floatTopPosition = this.getFloatPositionByXY({\r\n        ...payload,\r\n        imgDisplays: [ImageDisplay.FLOAT_TOP, ImageDisplay.SURROUND]\r\n      })\r\n      if (floatTopPosition) return floatTopPosition\r\n    }\r\n    // 普通元素\r\n    for (let j = 0; j < positionList.length; j++) {\r\n      const {\r\n        index,\r\n        pageNo,\r\n        left,\r\n        isFirstLetter,\r\n        coordinate: { leftTop, rightTop, leftBottom }\r\n      } = positionList[j]\r\n      if (positionNo !== pageNo) continue\r\n      if (pageNo > positionNo) break\r\n      // 命中元素\r\n      if (\r\n        leftTop[0] - left <= x &&\r\n        rightTop[0] >= x &&\r\n        leftTop[1] <= y &&\r\n        leftBottom[1] >= y\r\n      ) {\r\n        let curPositionIndex = j\r\n        const element = elementList[j]\r\n        // 表格被命中\r\n        if (element.type === ElementType.TABLE) {\r\n          for (let t = 0; t < element.trList!.length; t++) {\r\n            const tr = element.trList![t]\r\n            for (let d = 0; d < tr.tdList.length; d++) {\r\n              const td = tr.tdList[d]\r\n              const tablePosition = this.getPositionByXY({\r\n                x,\r\n                y,\r\n                td,\r\n                pageNo: curPageNo,\r\n                tablePosition: positionList[j],\r\n                isTable: true,\r\n                elementList: td.value,\r\n                positionList: td.positionList\r\n              })\r\n              if (~tablePosition.index) {\r\n                const { index: tdValueIndex, hitLineStartIndex } = tablePosition\r\n                const tdValueElement = td.value[tdValueIndex]\r\n                return {\r\n                  index,\r\n                  isCheckbox:\r\n                    tablePosition.isCheckbox ||\r\n                    tdValueElement.type === ElementType.CHECKBOX ||\r\n                    tdValueElement.controlComponent ===\r\n                    ControlComponent.CHECKBOX,\r\n                  isRadio:\r\n                    tdValueElement.type === ElementType.RADIO ||\r\n                    tdValueElement.controlComponent === ControlComponent.RADIO,\r\n                  isControl: !!tdValueElement.controlId,\r\n                  isImage: tablePosition.isImage,\r\n                  isDirectHit: tablePosition.isDirectHit,\r\n                  isTable: true,\r\n                  tdIndex: d,\r\n                  trIndex: t,\r\n                  tdValueIndex,\r\n                  tdId: td.id,\r\n                  trId: tr.id,\r\n                  tableId: element.id,\r\n                  hitLineStartIndex\r\n                }\r\n              }\r\n            }\r\n          }\r\n        }\r\n        // 图片区域均为命中\r\n        if (\r\n          element.type === ElementType.IMAGE ||\r\n          element.type === ElementType.LATEX\r\n        ) {\r\n          return {\r\n            index: curPositionIndex,\r\n            isDirectHit: true,\r\n            isImage: true\r\n          }\r\n        }\r\n        if (\r\n          element.type === ElementType.CHECKBOX ||\r\n          element.controlComponent === ControlComponent.CHECKBOX\r\n        ) {\r\n          return {\r\n            index: curPositionIndex,\r\n            isDirectHit: true,\r\n            isCheckbox: true\r\n          }\r\n        }\r\n        if (\r\n          element.type === ElementType.RADIO ||\r\n          element.controlComponent === ControlComponent.RADIO\r\n        ) {\r\n          return {\r\n            index: curPositionIndex,\r\n            isDirectHit: true,\r\n            isRadio: true\r\n          }\r\n        }\r\n        let hitLineStartIndex: number | undefined\r\n        // 判断是否在文字中间前后\r\n        if (elementList[index].value !== ZERO) {\r\n          const valueWidth = rightTop[0] - leftTop[0]\r\n          if (x < leftTop[0] + valueWidth / 2) {\r\n            curPositionIndex = j - 1\r\n            if (isFirstLetter) {\r\n              hitLineStartIndex = j\r\n            }\r\n          }\r\n        }\r\n        return {\r\n          isDirectHit: true,\r\n          hitLineStartIndex,\r\n          index: curPositionIndex,\r\n          isControl: !!element.controlId\r\n        }\r\n      }\r\n    }\r\n    // 验证衬于文字下方元素\r\n    if (!isTable) {\r\n      const floatBottomPosition = this.getFloatPositionByXY({\r\n        ...payload,\r\n        imgDisplays: [ImageDisplay.FLOAT_BOTTOM]\r\n      })\r\n      if (floatBottomPosition) return floatBottomPosition\r\n    }\r\n    // 非命中区域\r\n    let isLastArea = false\r\n    let curPositionIndex = -1\r\n    let hitLineStartIndex: number | undefined\r\n    // 判断是否在表格内\r\n    if (isTable) {\r\n      const { scale } = this.options\r\n      const { td, tablePosition } = payload\r\n      if (td && tablePosition) {\r\n        const { leftTop } = tablePosition.coordinate\r\n        const tdX = td.x! * scale + leftTop[0]\r\n        const tdY = td.y! * scale + leftTop[1]\r\n        const tdWidth = td.width! * scale\r\n        const tdHeight = td.height! * scale\r\n        if (!(tdX < x && x < tdX + tdWidth && tdY < y && y < tdY + tdHeight)) {\r\n          return {\r\n            index: curPositionIndex\r\n          }\r\n        }\r\n      }\r\n    }\r\n    // 判断所属行是否存在元素\r\n    const lastLetterList = positionList.filter(\r\n      p => p.isLastLetter && p.pageNo === positionNo\r\n    )\r\n    for (let j = 0; j < lastLetterList.length; j++) {\r\n      const {\r\n        index,\r\n        rowNo,\r\n        coordinate: { leftTop, leftBottom }\r\n      } = lastLetterList[j]\r\n      if (y > leftTop[1] && y <= leftBottom[1]) {\r\n        const headIndex = positionList.findIndex(\r\n          p => p.pageNo === positionNo && p.rowNo === rowNo\r\n        )\r\n        const headElement = elementList[headIndex]\r\n        const headPosition = positionList[headIndex]\r\n        // 是否在头部\r\n        const headStartX =\r\n          headElement.listStyle === ListStyle.CHECKBOX\r\n            ? this.options.margins[3]\r\n            : headPosition.coordinate.leftTop[0]\r\n        if (x < headStartX) {\r\n          // 头部元素为空元素时无需选中\r\n          if (~headIndex) {\r\n            if (headPosition.value === ZERO) {\r\n              curPositionIndex = headIndex\r\n            } else {\r\n              curPositionIndex = headIndex - 1\r\n              hitLineStartIndex = headIndex\r\n            }\r\n          } else {\r\n            curPositionIndex = index\r\n          }\r\n        } else {\r\n          // 是否是复选框列表\r\n          if (headElement.listStyle === ListStyle.CHECKBOX && x < leftTop[0]) {\r\n            return {\r\n              index: headIndex,\r\n              isDirectHit: true,\r\n              isCheckbox: true\r\n            }\r\n          }\r\n          curPositionIndex = index\r\n        }\r\n        isLastArea = true\r\n        break\r\n      }\r\n    }\r\n    if (!isLastArea) {\r\n      // 页眉底部距离页面顶部距离\r\n      const header = this.draw.getHeader()\r\n      const headerHeight = header.getHeight()\r\n      const headerBottomY = header.getHeaderTop() + headerHeight\r\n      // 页脚上部距离页面顶部距离\r\n      const footer = this.draw.getFooter()\r\n      const pageHeight = this.draw.getHeight()\r\n      const footerTopY =\r\n        pageHeight - (footer.getFooterBottom() + footer.getHeight())\r\n      // 判断所属位置是否属于页眉页脚区域\r\n      // if (isMainActive) {\r\n      // 页眉：当前位置小于页眉底部位置\r\n      if (y < headerBottomY) {\r\n        return {\r\n          index: -1,\r\n          zone: EditorZone.HEADER\r\n        }\r\n      }\r\n      // 页脚：当前位置大于页脚顶部位置\r\n      if (y > footerTopY) {\r\n        return {\r\n          index: -1,\r\n          zone: EditorZone.FOOTER\r\n        }\r\n      }\r\n      // } else {\r\n      //   // main区域：当前位置小于页眉底部位置 && 大于页脚顶部位置\r\n      //   if (y <= footerTopY && y >= headerBottomY) {\r\n      //     return {\r\n      //       index: -1,\r\n      //       zone: EditorZone.MAIN\r\n      //     }\r\n      //   }\r\n      // }\r\n      // 正文上-循环首行\r\n      const margins = this.draw.getMargins()\r\n      if (y <= margins[1]) {\r\n        for (let p = 0; p < positionList.length; p++) {\r\n          const position = positionList[p]\r\n          if (position.pageNo !== positionNo || position.rowNo !== 0) continue\r\n          const { leftTop, rightTop } = position.coordinate\r\n          // 小于左页边距 || 命中文字 || 首行最后元素\r\n          if (\r\n            x <= margins[3] ||\r\n            (x >= leftTop[0] && x <= rightTop[0]) ||\r\n            positionList[p + 1]?.rowNo !== 0\r\n          ) {\r\n            return {\r\n              index: position.index\r\n            }\r\n          }\r\n        }\r\n      } else {\r\n        // 正文下-循环尾行\r\n        const lastLetter = lastLetterList[lastLetterList.length - 1]\r\n        if (lastLetter) {\r\n          const lastRowNo = lastLetter.rowNo\r\n          for (let p = 0; p < positionList.length; p++) {\r\n            const position = positionList[p]\r\n            if (\r\n              position.pageNo !== positionNo ||\r\n              position.rowNo !== lastRowNo\r\n            ) {\r\n              continue\r\n            }\r\n            const { leftTop, rightTop } = position.coordinate\r\n            // 小于左页边距 || 命中文字 || 尾行最后元素\r\n            if (\r\n              x <= margins[3] ||\r\n              (x >= leftTop[0] && x <= rightTop[0]) ||\r\n              positionList[p + 1]?.rowNo !== lastRowNo\r\n            ) {\r\n              return {\r\n                index: position.index\r\n              }\r\n            }\r\n          }\r\n        }\r\n      }\r\n      // 当前页最后一行\r\n      return {\r\n        index:\r\n          lastLetterList[lastLetterList.length - 1]?.index ||\r\n          positionList.length - 1\r\n      }\r\n    }\r\n    return {\r\n      hitLineStartIndex,\r\n      index: curPositionIndex,\r\n      isControl: !!elementList[curPositionIndex]?.controlId\r\n    }\r\n  }\r\n\r\n  public getFloatPositionByXY(\r\n    payload: IGetFloatPositionByXYPayload\r\n  ): ICurrentPosition | void {\r\n    const { x, y } = payload\r\n    const currentPageNo = payload.pageNo ?? this.draw.getPageNo()\r\n    // const currentZone = this.draw.getZone().getZone()\r\n    for (let f = 0; f < this.floatPositionList.length; f++) {\r\n      const {\r\n        position,\r\n        element,\r\n        isTable,\r\n        index,\r\n        trIndex,\r\n        tdIndex,\r\n        tdValueIndex,\r\n        // zone: floatElementZone,\r\n        pageNo\r\n      } = this.floatPositionList[f]\r\n      if (\r\n        currentPageNo === pageNo &&\r\n        element.type === ElementType.IMAGE &&\r\n        element.imgDisplay &&\r\n        payload.imgDisplays.includes(element.imgDisplay)// &&\r\n        // (!floatElementZone || floatElementZone === currentZone)\r\n      ) {\r\n        const imgFloatPosition = element.imgFloatPosition!\r\n        if (\r\n          x >= imgFloatPosition.x &&\r\n          x <= imgFloatPosition.x + element.width! &&\r\n          y >= imgFloatPosition.y &&\r\n          y <= imgFloatPosition.y + element.height!\r\n        ) {\r\n          if (isTable) {\r\n            return {\r\n              index: index!,\r\n              isDirectHit: true,\r\n              isImage: true,\r\n              isTable,\r\n              trIndex,\r\n              tdIndex,\r\n              tdValueIndex,\r\n              tdId: element.tdId,\r\n              trId: element.trId,\r\n              tableId: element.tableId\r\n            }\r\n          }\r\n          return {\r\n            index: position.index,\r\n            isDirectHit: true,\r\n            isImage: true\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  public adjustPositionContext(\r\n    payload: IGetPositionByXYPayload\r\n  ): ICurrentPosition | null {\r\n    const positionResult = this.getPositionByXY(payload)\r\n    if (!~positionResult.index) return null\r\n    // // 移动控件内光标\r\n    // if (\r\n    //   positionResult.isControl &&\r\n    //   this.draw.getMode() !== EditorMode.READONLY\r\n    // ) {\r\n    //   const { index, isTable, trIndex, tdIndex, tdValueIndex } = positionResult\r\n    //   const control = this.draw.getControl()\r\n    //   const { newIndex } = control.moveCursor({\r\n    //     index,\r\n    //     isTable,\r\n    //     trIndex,\r\n    //     tdIndex,\r\n    //     tdValueIndex\r\n    //   })\r\n    //   if (isTable) {\r\n    //     positionResult.tdValueIndex = newIndex\r\n    //   } else {\r\n    //     positionResult.index = newIndex\r\n    //   }\r\n    // }\r\n    const {\r\n      index,\r\n      isCheckbox,\r\n      isRadio,\r\n      isControl,\r\n      isImage,\r\n      isDirectHit,\r\n      isTable,\r\n      trIndex,\r\n      tdIndex,\r\n      tdId,\r\n      trId,\r\n      tableId\r\n    } = positionResult\r\n    // 设置位置上下文\r\n    this.setPositionContext({\r\n      isTable: isTable || false,\r\n      isCheckbox: isCheckbox || false,\r\n      isRadio: isRadio || false,\r\n      isControl: isControl || false,\r\n      isImage: isImage || false,\r\n      isDirectHit: isDirectHit || false,\r\n      index,\r\n      trIndex,\r\n      tdIndex,\r\n      tdId,\r\n      trId,\r\n      tableId\r\n    })\r\n    return positionResult\r\n  }\r\n\r\n  public setSurroundPosition(payload: ISetSurroundPositionPayload) {\r\n    const {\r\n      pageNo,\r\n      row,\r\n      rowElement,\r\n      rowElementRect,\r\n      surroundElementList,\r\n      availableWidth\r\n    } = payload\r\n    let x = rowElementRect.x\r\n    let rowIncreaseWidth = 0\r\n    if (\r\n      surroundElementList.length &&\r\n      !getIsBlockElement(rowElement) &&\r\n      !rowElement.control?.minWidth\r\n    ) {\r\n      for (let s = 0; s < surroundElementList.length; s++) {\r\n        const surroundElement = surroundElementList[s]\r\n        const floatPosition = surroundElement.imgFloatPosition!\r\n        if (floatPosition.pageNo !== pageNo) continue\r\n        const surroundRect = {\r\n          ...floatPosition,\r\n          width: surroundElement.width!,\r\n          height: surroundElement.height!\r\n        }\r\n        if (isRectIntersect(rowElementRect, surroundRect)) {\r\n          row.isSurround = true\r\n          // 需向左移动距离：浮动元素宽度 + 浮动元素左上坐标 - 元素左上坐标\r\n          const translateX =\r\n            surroundRect.width + surroundRect.x - rowElementRect.x\r\n          rowElement.left = translateX\r\n          // 增加行宽\r\n          row.width += translateX\r\n          rowIncreaseWidth += translateX\r\n          // 下个元素起始位置：浮动元素右坐标 - 元素宽度\r\n          x = surroundRect.x + surroundRect.width\r\n          // 检测宽度是否足够，不够则移动到下一行，并还原状态\r\n          console.log('availableWidth')\r\n          console.log(availableWidth)\r\n          console.log(row)\r\n          console.log(rowElement)\r\n          if (row.width + rowElement.metrics.width > availableWidth) {\r\n            rowElement.left = 0\r\n            row.width -= rowIncreaseWidth\r\n            break\r\n          }\r\n        }\r\n      }\r\n    }\r\n    return { x, rowIncreaseWidth }\r\n  }\r\n}\r\n","import { Context2d } from 'jspdf'\r\nimport {\r\n  PUNCTUATION_LIST,\r\n  METRICS_BASIS_TEXT\r\n} from '../../../dataset/constant/Common'\r\nimport { IRowElement } from '../../../interface/Row'\r\nimport { ITextMetrics } from '../../../interface/Text'\r\nimport { DrawPdf } from '../DrawPdf'\r\nimport { DeepRequired } from '../../../interface/Common'\r\nimport { IElement } from '../../../interface/Element'\r\nimport { IEditorOption } from '../../../interface/Editor'\r\nimport { ElementType } from '../../../dataset/enum/Element'\r\nimport { RenderMode } from '../../../dataset/enum/Editor'\r\n\r\nexport interface IMeasureWordResult {\r\n  width: number\r\n  endElement: IElement\r\n}\r\n\r\nexport class TextParticle {\r\n  private draw: DrawPdf\r\n  private options: DeepRequired<IEditorOption>\r\n\r\n  private ctx2d: Context2d\r\n  private curX: number\r\n  private curY: number\r\n  private text: string\r\n  private bold?: boolean\r\n  private italic?: boolean\r\n  private curStyle: string\r\n  private curColor?: string\r\n  public cacheMeasureText: Map<string, TextMetrics>\r\n\r\n  constructor(draw: DrawPdf) {\r\n    this.draw = draw\r\n    this.options = draw.getOptions()\r\n    this.ctx2d = draw.getCtx2d()\r\n    this.curX = -1\r\n    this.curY = -1\r\n    this.text = ''\r\n    this.bold = false\r\n    this.italic = false\r\n    this.curStyle = ''\r\n    this.cacheMeasureText = new Map()\r\n  }\r\n\r\n  public measureBasisWord(\r\n    ctx2d: Context2d,\r\n    font: string\r\n  ): ITextMetrics {\r\n    ctx2d.save()\r\n    ctx2d.font = font\r\n    const textMetrics = this.measureText(ctx2d, {\r\n      value: METRICS_BASIS_TEXT\r\n    })\r\n    ctx2d.restore()\r\n    return textMetrics\r\n  }\r\n\r\n  public measureWord(\r\n    ctx2d: Context2d,\r\n    elementList: IElement[],\r\n    curIndex: number\r\n  ): IMeasureWordResult {\r\n    const LETTER_REG = this.draw.getLetterReg()\r\n    let width = 0\r\n    let endElement: IElement = elementList[curIndex]\r\n    let i = curIndex\r\n    while (i < elementList.length) {\r\n      const element = elementList[i]\r\n      if (\r\n        (element.type && element.type !== ElementType.TEXT) ||\r\n        !LETTER_REG.test(element.value)\r\n      ) {\r\n        endElement = element\r\n        break\r\n      }\r\n      width += this.measureText(ctx2d, element).width\r\n      i++\r\n    }\r\n    return {\r\n      width,\r\n      endElement\r\n    }\r\n  }\r\n\r\n  public measurePunctuationWidth(\r\n    ctx2d: Context2d,\r\n    element: IElement\r\n  ): number {\r\n    if (!element || !PUNCTUATION_LIST.includes(element.value)) return 0\r\n    return this.measureText(ctx2d, element).width\r\n  }\r\n\r\n  public measureText(\r\n    ctx2d: Context2d,\r\n    element: IElement\r\n  ): ITextMetrics {\r\n    // 优先使用自定义字宽设置\r\n    const font = this.draw.getFont(element)\r\n    const value = element.value === `\\n` ? '' : element.value\r\n    if (element.width) {\r\n      const textMetrics = this.draw.measureText(font, element.value)\r\n      // TextMetrics是类无法解构\r\n      return {\r\n        width: element.width,\r\n        actualBoundingBoxAscent: textMetrics.actualBoundingBoxAscent,\r\n        actualBoundingBoxDescent: textMetrics.actualBoundingBoxDescent,\r\n        actualBoundingBoxLeft: textMetrics.actualBoundingBoxLeft,\r\n        actualBoundingBoxRight: textMetrics.actualBoundingBoxRight,\r\n        fontBoundingBoxAscent: textMetrics.fontBoundingBoxAscent,\r\n        fontBoundingBoxDescent: textMetrics.fontBoundingBoxDescent\r\n      }\r\n    }\r\n    const id = `${element.value}${ctx2d.font}`\r\n    const cacheTextMetrics = this.cacheMeasureText.get(id)\r\n    if (cacheTextMetrics) {\r\n      return cacheTextMetrics\r\n    }\r\n    const textMetrics = this.draw.measureText(font, value)\r\n    this.cacheMeasureText.set(id, textMetrics)\r\n    return textMetrics\r\n  }\r\n\r\n  public complete() {\r\n    this._render()\r\n    this.text = ''\r\n  }\r\n\r\n  public record(\r\n    ctx2d: Context2d,\r\n    element: IRowElement,\r\n    x: number,\r\n    y: number\r\n  ) {\r\n    this.ctx2d = ctx2d\r\n    // 兼容模式立即绘制\r\n    if (this.options.renderMode === RenderMode.COMPATIBILITY) {\r\n      this._setCurXY(x, y)\r\n      this.text = element.value\r\n      this.curStyle = element.style\r\n      this.curColor = element.color\r\n      this.bold = element.bold\r\n      this.italic = element.italic\r\n      this.complete()\r\n      return\r\n    }\r\n    // 主动完成的重设起始点\r\n    if (!this.text) {\r\n      this._setCurXY(x, y)\r\n    }\r\n    // 样式发生改变\r\n    if (\r\n      (this.curStyle && element.style !== this.curStyle) ||\r\n      element.color !== this.curColor\r\n    ) {\r\n      this.complete()\r\n      this._setCurXY(x, y)\r\n    }\r\n    this.text += element.value\r\n    this.curStyle = element.style.toLocaleLowerCase()\r\n    this.curColor = element.color\r\n    this.bold = element.bold\r\n    this.italic = element.italic\r\n  }\r\n\r\n  private _setCurXY(x: number, y: number) {\r\n    this.curX = x\r\n    this.curY = y\r\n  }\r\n\r\n  private _render() {\r\n    if (!this.text || !~this.curX || !~this.curX) return\r\n    this.ctx2d.save()\r\n    // if (this.curStyle.includes('Microsoft YaHei')) {\r\n    //   this.curStyle = this.curStyle.replace('Microsoft YaHei', 'Yahei')\r\n    // }\r\n    this.ctx2d.font = this.curStyle.toLowerCase()\r\n    const fontWeight = this.bold ? 'bold' : 'normal'\r\n    const fontItalic = this.italic ? 'italic' : ''\r\n    this.draw.getPdf().setFont(this.curStyle.split('px ')[1], fontItalic, fontWeight)\r\n    this.draw.getPdf().setCharSpace(0.1) // https://jsfiddle.net/pg7byu80/5/\r\n    // this.draw.getPdf().internal.write(0, \"Tw\")\r\n    // this.draw.getPdf().text(this.text, this.curX, this.curY) // attempt to apply the font globally every time you add some text - currently unsuccessful\r\n    this.ctx2d.save()\r\n    this.ctx2d.fillStyle = this.curColor || this.options.defaultColor\r\n    this.ctx2d.fillText(this.text, this.curX, this.curY)\r\n    this.ctx2d.restore()\r\n  }\r\n}\r\n","import { IPageNumber } from '../../interface/PageNumber'\r\nimport { NumberType } from '../enum/Common'\r\nimport { RowFlex } from '../enum/Row'\r\n\r\nexport const FORMAT_PLACEHOLDER = {\r\n  PAGE_NO: '{pageNo}',\r\n  PAGE_COUNT: '{pageCount}'\r\n}\r\n\r\nexport const defaultPageNumberOption: Readonly<Required<IPageNumber>> = {\r\n  bottom: 60,\r\n  size: 12,\r\n  font: 'Microsoft YaHei',\r\n  color: '#000000',\r\n  rowFlex: RowFlex.CENTER,\r\n  format: FORMAT_PLACEHOLDER.PAGE_NO,\r\n  numberType: NumberType.ARABIC,\r\n  disabled: false,\r\n  startPageNo: 1,\r\n  fromPageNo: 0,\r\n  maxPageNo: null\r\n}\r\n","import { Context2d } from 'jspdf'\r\nimport { FORMAT_PLACEHOLDER } from '../../../dataset/constant/PageNumber'\r\nimport { NumberType } from '../../../dataset/enum/Common'\r\nimport { PageMode } from '../../../dataset/enum/Editor'\r\nimport { RowFlex } from '../../../dataset/enum/Row'\r\nimport { DeepRequired } from '../../../interface/Common'\r\nimport { IEditorOption } from '../../../interface/Editor'\r\nimport { convertNumberToChinese } from '../../../utils'\r\nimport { DrawPdf } from '../DrawPdf'\r\n\r\nexport class PageNumber {\r\n  private draw: DrawPdf\r\n  private options: DeepRequired<IEditorOption>\r\n\r\n  constructor(draw: DrawPdf) {\r\n    this.draw = draw\r\n    this.options = draw.getOptions()\r\n  }\r\n\r\n  static formatNumberPlaceholder(\r\n    text: string,\r\n    pageNo: number,\r\n    replaceReg: RegExp,\r\n    numberType: NumberType\r\n  ) {\r\n    const pageNoText =\r\n      numberType === NumberType.CHINESE\r\n        ? convertNumberToChinese(pageNo)\r\n        : `${pageNo}`\r\n    return text.replace(replaceReg, pageNoText)\r\n  }\r\n\r\n  public render(ctx2d: Context2d, pageNo: number) {\r\n    const {\r\n      scale,\r\n      pageMode,\r\n      pageNumber: {\r\n        size,\r\n        font,\r\n        color,\r\n        rowFlex,\r\n        numberType,\r\n        format,\r\n        startPageNo,\r\n        fromPageNo\r\n      }\r\n    } = this.options\r\n    if (pageNo < fromPageNo) return\r\n    // 处理页码格式\r\n    let text = format\r\n    const pageNoReg = new RegExp(FORMAT_PLACEHOLDER.PAGE_NO)\r\n    if (pageNoReg.test(text)) {\r\n      const realPageNo = pageNo + startPageNo - fromPageNo\r\n      const pageNoText =\r\n        numberType === NumberType.CHINESE\r\n          ? convertNumberToChinese(realPageNo)\r\n          : `${realPageNo}`\r\n      text = text.replace(pageNoReg, pageNoText)\r\n    }\r\n    const pageCountReg = new RegExp(FORMAT_PLACEHOLDER.PAGE_COUNT)\r\n    if (pageCountReg.test(text)) {\r\n      const pageCount = this.draw.getPageCount() - fromPageNo\r\n      const pageCountText =\r\n        numberType === NumberType.CHINESE\r\n          ? convertNumberToChinese(pageCount)\r\n          : `${pageCount}`\r\n      text = text.replace(pageCountReg, pageCountText)\r\n    }\r\n    const width = this.draw.getWidth()\r\n    // 计算y位置\r\n    const height =\r\n      pageMode === PageMode.CONTINUITY\r\n        ? this.draw.getCanvasHeight(pageNo)\r\n        : this.draw.getHeight()\r\n    const pageNumberBottom = this.draw.getPageNumberBottom()\r\n    const y = height - pageNumberBottom\r\n    ctx2d.save()\r\n    ctx2d.fillStyle = color\r\n    let newFont = font\r\n    if (newFont.includes('Microsoft YaHei')) {\r\n      newFont = newFont.replace('Microsoft YaHei', 'Yahei')\r\n    }\r\n    ctx2d.font = `${size * scale}px ${newFont}`\r\n    // 计算x位置-居左、居中、居右\r\n    let x = 0\r\n    const margins = this.draw.getMargins()\r\n    const { width: textWidth } = this.draw.getFakeCtx().measureText(text)\r\n    if (rowFlex === RowFlex.CENTER) {\r\n      x = (width - textWidth) / 2\r\n    } else if (rowFlex === RowFlex.RIGHT) {\r\n      x = width - textWidth - margins[1]\r\n    } else {\r\n      x = margins[3]\r\n    }\r\n    ctx2d.fillText(text, x, y)\r\n    ctx2d.restore()\r\n  }\r\n}\r\n","import { Context2d } from 'jspdf'\r\n// import { /*ElementType,*/ IElement, TableBorder } from '@hufe921/canvas-editor'\r\nimport { TableBorder, TdBorder, TdSlash } from '../../../../dataset/enum/table/Table'\r\nimport { DeepRequired } from '../../../../interface/Common'\r\nimport { IEditorOption } from '../../../../interface/Editor'\r\nimport { ITd } from '../../../../interface/table/Td'\r\nimport { deepClone } from '../../../../utils'\r\n// import { RangeManager } from '../../../range/RangeManager'\r\nimport { DrawPdf } from '../../DrawPdf'\r\nimport { ITr } from '../../../../interface/table/Tr'\r\nimport { IRowElement } from '../../../../interface/Row'\r\nimport { IElement } from '../../../../interface/Element'\r\n// import { ITr } from '@hufe921/canvas-editor/dist/src/editor/interface/table/Tr'\r\n// import { IRowElement } from '@hufe921/canvas-editor/dist/src/editor/interface/Row'\r\n\r\ninterface IDrawTableBorderOption {\r\n  ctx2d: Context2d\r\n  startX: number\r\n  startY: number\r\n  width: number\r\n  height: number\r\n  borderExternalWidth?: number\r\n  isDrawFullBorder?: boolean\r\n}\r\n\r\nexport class TableParticle {\r\n  // private draw: DrawPdf\r\n  // private range: RangeManager\r\n  private options: DeepRequired<IEditorOption>\r\n\r\n  constructor(draw: DrawPdf) {\r\n    // this.draw = draw\r\n    // this.range = draw.getRange()\r\n    this.options = draw.getOptions()\r\n  }\r\n\r\n  public getTrListGroupByCol(payload: ITr[]): ITr[] {\r\n    const trList = deepClone(payload)\r\n    for (let t = 0; t < payload.length; t++) {\r\n      const tr = trList[t]\r\n      for (let d = tr.tdList.length - 1; d >= 0; d--) {\r\n        const td = tr.tdList[d]\r\n        const { rowspan, rowIndex, colIndex } = td\r\n        const curRowIndex = rowIndex! + rowspan - 1\r\n        if (curRowIndex !== d) {\r\n          const changeTd = tr.tdList.splice(d, 1)[0]\r\n          trList[curRowIndex]?.tdList.splice(colIndex!, 0, changeTd)\r\n        }\r\n      }\r\n    }\r\n    return trList\r\n  }\r\n\r\n  // public getRangeRowCol(): ITd[][] | null {\r\n  //   const { isTable, index, trIndex, tdIndex } = this.draw\r\n  //     .getPosition()\r\n  //     .getPositionContext()\r\n  //   if (!isTable) return null\r\n  //   const {\r\n  //     isCrossRowCol,\r\n  //     startTdIndex,\r\n  //     endTdIndex,\r\n  //     startTrIndex,\r\n  //     endTrIndex\r\n  //   } = this.range.getRange()\r\n  //   const originalElementList = this.draw.getOriginalElementList()\r\n  //   const element = originalElementList[index!]\r\n  //   const curTrList = element.trList!\r\n  //   // 非跨列直接返回光标所在单元格\r\n  //   if (!isCrossRowCol) {\r\n  //     return [[curTrList[trIndex!].tdList[tdIndex!]]]\r\n  //   }\r\n  //   let startTd = curTrList[startTrIndex!].tdList[startTdIndex!]\r\n  //   let endTd = curTrList[endTrIndex!].tdList[endTdIndex!]\r\n  //   // 交换起始位置\r\n  //   if (startTd.x! > endTd.x! || startTd.y! > endTd.y!) {\r\n  //     // prettier-ignore\r\n  //     [startTd, endTd] = [endTd, startTd]\r\n  //   }\r\n  //   const startColIndex = startTd.colIndex!\r\n  //   const endColIndex = endTd.colIndex! + (endTd.colspan - 1)\r\n  //   const startRowIndex = startTd.rowIndex!\r\n  //   const endRowIndex = endTd.rowIndex! + (endTd.rowspan - 1)\r\n  //   // 选区行列\r\n  //   const rowCol: ITd[][] = []\r\n  //   for (let t = 0; t < curTrList.length; t++) {\r\n  //     const tr = curTrList[t]\r\n  //     const tdList: ITd[] = []\r\n  //     for (let d = 0; d < tr.tdList.length; d++) {\r\n  //       const td = tr.tdList[d]\r\n  //       const tdColIndex = td.colIndex!\r\n  //       const tdRowIndex = td.rowIndex!\r\n  //       if (\r\n  //         tdColIndex >= startColIndex &&\r\n  //         tdColIndex <= endColIndex &&\r\n  //         tdRowIndex >= startRowIndex &&\r\n  //         tdRowIndex <= endRowIndex\r\n  //       ) {\r\n  //         tdList.push(td)\r\n  //       }\r\n  //     }\r\n  //     if (tdList.length) {\r\n  //       rowCol.push(tdList)\r\n  //     }\r\n  //   }\r\n  //   return rowCol.length ? rowCol : null\r\n  // }\r\n\r\n  private _drawOuterBorder(payload: IDrawTableBorderOption) {\r\n    const {\r\n      ctx2d,\r\n      startX,\r\n      startY,\r\n      width,\r\n      height,\r\n      isDrawFullBorder,\r\n      borderExternalWidth\r\n    } = payload\r\n    const { scale } = this.options\r\n    // 外部边框单独设置\r\n    const lineWidth = ctx2d.lineWidth\r\n    if (borderExternalWidth) {\r\n      ctx2d.lineWidth = borderExternalWidth * scale\r\n    }\r\n    ctx2d.beginPath()\r\n    const x = Math.round(startX)\r\n    const y = Math.round(startY)\r\n    ctx2d.translate(0.5, 0.5)\r\n    if (isDrawFullBorder) {\r\n      ctx2d.rect(x, y, width, height)\r\n    } else {\r\n      ctx2d.moveTo(x, y + height)\r\n      ctx2d.lineTo(x, y)\r\n      ctx2d.lineTo(x + width, y)\r\n    }\r\n    ctx2d.stroke()\r\n    // 还原边框设置\r\n    if (borderExternalWidth) {\r\n      ctx2d.lineWidth = lineWidth\r\n    }\r\n    ctx2d.translate(-0.5, -0.5)\r\n  }\r\n\r\n  private _drawSlash(\r\n    ctx2d: Context2d,\r\n    td: ITd,\r\n    startX: number,\r\n    startY: number\r\n  ) {\r\n    const { scale } = this.options\r\n    ctx2d.save()\r\n    const width = td.width! * scale\r\n    const height = td.height! * scale\r\n    const x = Math.round(td.x! * scale + startX)\r\n    const y = Math.round(td.y! * scale + startY)\r\n    // 正斜线 /\r\n    if (td.slashTypes?.includes(TdSlash.FORWARD)) {\r\n      ctx2d.moveTo(x + width, y)\r\n      ctx2d.lineTo(x, y + height)\r\n    }\r\n    // 反斜线 \\\r\n    if (td.slashTypes?.includes(TdSlash.BACK)) {\r\n      ctx2d.moveTo(x, y)\r\n      ctx2d.lineTo(x + width, y + height)\r\n    }\r\n    ctx2d.stroke()\r\n    ctx2d.restore()\r\n  }\r\n\r\n  private _drawBorder(\r\n    ctx2d: Context2d,\r\n    element: IElement,\r\n    startX: number,\r\n    startY: number\r\n  ) {\r\n    const {\r\n      colgroup,\r\n      trList,\r\n      borderType,\r\n      borderColor,\r\n      borderWidth = 1,\r\n      borderExternalWidth\r\n    } = element\r\n    if (!colgroup || !trList) return\r\n    const {\r\n      scale,\r\n      table: { defaultBorderColor }\r\n    } = this.options\r\n    const tableWidth = element.width! * scale\r\n    const tableHeight = element.height! * scale\r\n    // 无边框\r\n    const isEmptyBorderType = borderType === TableBorder.EMPTY\r\n    // 仅外边框\r\n    const isExternalBorderType = borderType === TableBorder.EXTERNAL\r\n    // 内边框\r\n    const isInternalBorderType = borderType === TableBorder.INTERNAL\r\n    ctx2d.save()\r\n    // 虚线\r\n    if (borderType === TableBorder.DASH) {\r\n      // ctx2d.setLineDash([3, 3])\r\n    }\r\n    ctx2d.lineWidth = borderWidth * scale\r\n    ctx2d.strokeStyle = borderColor || defaultBorderColor\r\n    // 渲染边框\r\n    if (!isEmptyBorderType && !isInternalBorderType) {\r\n      this._drawOuterBorder({\r\n        ctx2d,\r\n        startX,\r\n        startY,\r\n        width: tableWidth,\r\n        height: tableHeight,\r\n        borderExternalWidth,\r\n        isDrawFullBorder: isExternalBorderType\r\n      })\r\n    }\r\n    // 渲染单元格\r\n    for (let t = 0; t < trList.length; t++) {\r\n      const tr = trList[t]\r\n      for (let d = 0; d < tr.tdList.length; d++) {\r\n        const td = tr.tdList[d]\r\n        // 单元格内斜线\r\n        if (td.slashTypes?.length) {\r\n          this._drawSlash(ctx2d, td, startX, startY)\r\n        }\r\n        // 没有设置单元格边框 && 没有设置表格边框则忽略\r\n        if (\r\n          !td.borderTypes?.length &&\r\n          (isEmptyBorderType || isExternalBorderType)\r\n        ) {\r\n          continue\r\n        }\r\n        const width = td.width! * scale\r\n        const height = td.height! * scale\r\n        const x = Math.round(td.x! * scale + startX + width)\r\n        const y = Math.round(td.y! * scale + startY)\r\n        ctx2d.translate(0.5, 0.5)\r\n        // 绘制线条\r\n        ctx2d.beginPath()\r\n        // 单元格边框\r\n        if (td.borderTypes?.includes(TdBorder.TOP)) {\r\n          ctx2d.moveTo(x - width, y)\r\n          ctx2d.lineTo(x, y)\r\n          ctx2d.stroke()\r\n        }\r\n        if (td.borderTypes?.includes(TdBorder.RIGHT)) {\r\n          ctx2d.moveTo(x, y)\r\n          ctx2d.lineTo(x, y + height)\r\n          ctx2d.stroke()\r\n        }\r\n        if (td.borderTypes?.includes(TdBorder.BOTTOM)) {\r\n          ctx2d.moveTo(x, y + height)\r\n          ctx2d.lineTo(x - width, y + height)\r\n          ctx2d.stroke()\r\n        }\r\n        if (td.borderTypes?.includes(TdBorder.LEFT)) {\r\n          ctx2d.moveTo(x - width, y)\r\n          ctx2d.lineTo(x - width, y + height)\r\n          ctx2d.stroke()\r\n        }\r\n        // 表格线\r\n        if (!isEmptyBorderType && !isExternalBorderType) {\r\n          // 右边框\r\n          if (\r\n            !isInternalBorderType ||\r\n            td.colIndex! + td.colspan < colgroup.length\r\n          ) {\r\n            ctx2d.moveTo(x, y)\r\n            ctx2d.lineTo(x, y + height)\r\n            // 外部边框宽度设置时 => 最右边框宽度单独设置\r\n            if (\r\n              borderExternalWidth &&\r\n              borderExternalWidth !== borderWidth &&\r\n              td.colIndex! + td.colspan === colgroup.length\r\n            ) {\r\n              const lineWidth = ctx2d.lineWidth\r\n              ctx2d.lineWidth = borderExternalWidth * scale\r\n              ctx2d.stroke()\r\n              // 清空path\r\n              ctx2d.beginPath()\r\n              ctx2d.lineWidth = lineWidth\r\n            }\r\n          }\r\n          // 下边框\r\n          if (\r\n            !isInternalBorderType ||\r\n            td.rowIndex! + td.rowspan < trList.length\r\n          ) {\r\n            // 外部边框宽度设置时 => 立即绘制竖线\r\n            const isSetExternalBottomBorder =\r\n              borderExternalWidth &&\r\n              borderExternalWidth !== borderWidth &&\r\n              td.rowIndex! + td.rowspan === trList.length\r\n            if (isSetExternalBottomBorder) {\r\n              ctx2d.stroke()\r\n              // 清空path\r\n              ctx2d.beginPath()\r\n            }\r\n            ctx2d.moveTo(x, y + height)\r\n            ctx2d.lineTo(x - width, y + height)\r\n            // 外部边框宽度设置时 => 最下边框宽度单独设置\r\n            if (isSetExternalBottomBorder) {\r\n              const lineWidth = ctx2d.lineWidth\r\n              ctx2d.lineWidth = borderExternalWidth * scale\r\n              ctx2d.stroke()\r\n              // 清空path\r\n              ctx2d.beginPath()\r\n              ctx2d.lineWidth = lineWidth\r\n            }\r\n          }\r\n          ctx2d.stroke()\r\n        }\r\n        ctx2d.translate(-0.5, -0.5)\r\n      }\r\n    }\r\n    ctx2d.restore()\r\n  }\r\n\r\n  private _drawBackgroundColor(\r\n    ctx2d: Context2d,\r\n    element: IRowElement,\r\n    startX: number,\r\n    startY: number\r\n  ) {\r\n    const { trList } = element\r\n    if (!trList) return\r\n    const { scale } = this.options\r\n    for (let t = 0; t < trList.length; t++) {\r\n      const tr = trList[t]\r\n      for (let d = 0; d < tr.tdList.length; d++) {\r\n        const td = tr.tdList[d]\r\n        if (!td.backgroundColor) continue\r\n        ctx2d.save()\r\n        const width = td.width! * scale\r\n        const height = td.height! * scale\r\n        const x = Math.round(td.x! * scale + startX)\r\n        const y = Math.round(td.y! * scale + startY)\r\n        ctx2d.fillStyle = td.backgroundColor\r\n        ctx2d.fillRect(x, y, width, height)\r\n        ctx2d.restore()\r\n      }\r\n    }\r\n  }\r\n\r\n  public getTableWidth(element: IElement): number {\r\n    return element.colgroup!.reduce((pre, cur) => pre + cur.width, 0)\r\n  }\r\n\r\n  public getTableHeight(element: IElement): number {\r\n    const trList = element.trList\r\n    if (!trList?.length) return 0\r\n    return this.getTdListByColIndex(trList, 0).reduce(\r\n      (pre, cur) => pre + cur.height!,\r\n      0\r\n    )\r\n  }\r\n\r\n  public getRowCountByColIndex(trList: ITr[], colIndex: number): number {\r\n    return this.getTdListByColIndex(trList, colIndex).reduce(\r\n      (pre, cur) => pre + cur.rowspan,\r\n      0\r\n    )\r\n  }\r\n\r\n  public getTdListByColIndex(trList: ITr[], colIndex: number): ITd[] {\r\n    const data: ITd[] = []\r\n    for (let r = 0; r < trList.length; r++) {\r\n      const tdList = trList[r].tdList\r\n      for (let d = 0; d < tdList.length; d++) {\r\n        const td = tdList[d]\r\n        const min = td.colIndex!\r\n        const max = min + td.colspan - 1\r\n        if (colIndex >= min && colIndex <= max) {\r\n          data.push(td)\r\n        }\r\n      }\r\n    }\r\n    return data\r\n  }\r\n\r\n  public computeRowColInfo(element: IElement) {\r\n    const { colgroup, trList } = element\r\n    if (!colgroup || !trList) return\r\n    let preX = 0\r\n    for (let t = 0; t < trList.length; t++) {\r\n      const tr = trList[t]\r\n      // 表格最后一行\r\n      const isLastTr = trList.length - 1 === t\r\n      // 当前行最小高度\r\n      let rowMinHeight = 0\r\n      for (let d = 0; d < tr.tdList.length; d++) {\r\n        const td = tr.tdList[d]\r\n        // 计算当前td所属列索引\r\n        let colIndex = 0\r\n        // 第一行td位置为当前列索引+上一个单元格colspan，否则从第一行开始计算列偏移量\r\n        if (trList.length > 1 && t !== 0) {\r\n          // 当前列起始索引：以之前单元格为起始点\r\n          const preTd = tr.tdList[d - 1]\r\n          const start = preTd ? preTd.colIndex! + preTd.colspan : d\r\n          for (let c = start; c < colgroup.length; c++) {\r\n            // 查找相同索引列之前行数，相加判断是否位置被挤占\r\n            const rowCount = this.getRowCountByColIndex(trList.slice(0, t), c)\r\n            // 不存在挤占则默认当前单元格可以存在该位置\r\n            if (rowCount === t) {\r\n              colIndex = c\r\n              // 重置单元格起始位置坐标\r\n              let preColWidth = 0\r\n              for (let preC = 0; preC < c; preC++) {\r\n                preColWidth += colgroup[preC].width\r\n              }\r\n              preX = preColWidth\r\n              break\r\n            }\r\n          }\r\n        } else {\r\n          const preTd = tr.tdList[d - 1]\r\n          if (preTd) {\r\n            colIndex = preTd.colIndex! + preTd.colspan\r\n          }\r\n        }\r\n        // 计算格宽高\r\n        let width = 0\r\n        for (let col = 0; col < td.colspan; col++) {\r\n          width += colgroup[col + colIndex].width\r\n        }\r\n        let height = 0\r\n        for (let row = 0; row < td.rowspan; row++) {\r\n          const curTr = trList[row + t] || trList[t]\r\n          height += curTr.height\r\n        }\r\n        // y偏移量\r\n        if (rowMinHeight === 0 || rowMinHeight > height) {\r\n          rowMinHeight = height\r\n        }\r\n        // 当前行最后一个td\r\n        const isLastRowTd = tr.tdList.length - 1 === d\r\n        // 当前列最后一个td\r\n        let isLastColTd = isLastTr\r\n        if (!isLastColTd) {\r\n          if (td.rowspan > 1) {\r\n            const nextTrLength = trList.length - 1 - t\r\n            isLastColTd = td.rowspan - 1 === nextTrLength\r\n          }\r\n        }\r\n        // 当前表格最后一个td\r\n        const isLastTd = isLastTr && isLastRowTd\r\n        td.isLastRowTd = isLastRowTd\r\n        td.isLastColTd = isLastColTd\r\n        td.isLastTd = isLastTd\r\n        // 修改当前格clientBox\r\n        td.x = preX\r\n        // 之前行相同列的高度\r\n        let preY = 0\r\n        for (let preR = 0; preR < t; preR++) {\r\n          const preTdList = trList[preR].tdList\r\n          for (let preD = 0; preD < preTdList.length; preD++) {\r\n            const td = preTdList[preD]\r\n            if (\r\n              colIndex >= td.colIndex! &&\r\n              colIndex < td.colIndex! + td.colspan\r\n            ) {\r\n              preY += td.height!\r\n              break\r\n            }\r\n          }\r\n        }\r\n        td.y = preY\r\n        td.width = width\r\n        td.height = height\r\n        td.rowIndex = t\r\n        td.colIndex = colIndex\r\n        td.trIndex = t\r\n        td.tdIndex = d\r\n        // 当前列x轴累加\r\n        preX += width\r\n        // 一行中的最后td\r\n        if (isLastRowTd && !isLastTd) {\r\n          preX = 0\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  // public drawRange(\r\n  //   ctx: CanvasRenderingContext2D,\r\n  //   element: IElement,\r\n  //   startX: number,\r\n  //   startY: number\r\n  // ) {\r\n  //   const { scale, rangeAlpha, rangeColor } = this.options\r\n  //   const { type, trList } = element\r\n  //   if (!trList || type !== ElementType.TABLE) return\r\n  //   const {\r\n  //     isCrossRowCol,\r\n  //     startTdIndex,\r\n  //     endTdIndex,\r\n  //     startTrIndex,\r\n  //     endTrIndex\r\n  //   } = this.range.getRange()\r\n  //   // 存在跨行/列\r\n  //   if (!isCrossRowCol) return\r\n  //   let startTd = trList[startTrIndex!].tdList[startTdIndex!]\r\n  //   let endTd = trList[endTrIndex!].tdList[endTdIndex!]\r\n  //   // 交换起始位置\r\n  //   if (startTd.x! > endTd.x! || startTd.y! > endTd.y!) {\r\n  //     // prettier-ignore\r\n  //     [startTd, endTd] = [endTd, startTd]\r\n  //   }\r\n  //   const startColIndex = startTd.colIndex!\r\n  //   const endColIndex = endTd.colIndex! + (endTd.colspan - 1)\r\n  //   const startRowIndex = startTd.rowIndex!\r\n  //   const endRowIndex = endTd.rowIndex! + (endTd.rowspan - 1)\r\n  //   ctx.save()\r\n  //   for (let t = 0; t < trList.length; t++) {\r\n  //     const tr = trList[t]\r\n  //     for (let d = 0; d < tr.tdList.length; d++) {\r\n  //       const td = tr.tdList[d]\r\n  //       const tdColIndex = td.colIndex!\r\n  //       const tdRowIndex = td.rowIndex!\r\n  //       if (\r\n  //         tdColIndex >= startColIndex &&\r\n  //         tdColIndex <= endColIndex &&\r\n  //         tdRowIndex >= startRowIndex &&\r\n  //         tdRowIndex <= endRowIndex\r\n  //       ) {\r\n  //         const x = td.x! * scale\r\n  //         const y = td.y! * scale\r\n  //         const width = td.width! * scale\r\n  //         const height = td.height! * scale\r\n  //         ctx.globalAlpha = rangeAlpha\r\n  //         ctx.fillStyle = rangeColor\r\n  //         ctx.fillRect(x + startX, y + startY, width, height)\r\n  //       }\r\n  //     }\r\n  //   }\r\n  //   ctx.restore()\r\n  // }\r\n\r\n  public render(\r\n    ctx2d: Context2d,\r\n    element: IRowElement,\r\n    startX: number,\r\n    startY: number\r\n  ) {\r\n    this._drawBackgroundColor(ctx2d, element, startX, startY)\r\n    this._drawBorder(ctx2d, element, startX, startY)\r\n  }\r\n}\r\n","import { Context2d } from 'jspdf'\r\n// import { IElement } from '@hufe921/canvas-editor'\r\nimport { EDITOR_PREFIX } from '../../../dataset/constant/Editor'\r\nimport { IEditorOption } from '../../../interface/Editor'\r\nimport { IElement, IElementPosition } from '../../../interface/Element'\r\nimport { IRowElement } from '../../../interface/Row'\r\nimport { DrawPdf } from '../DrawPdf'\r\n\r\nexport class HyperlinkParticle {\r\n  private draw: DrawPdf\r\n  private options: Required<IEditorOption>\r\n  // private container: HTMLDivElement\r\n  private hyperlinkPopupContainer: HTMLDivElement\r\n  private hyperlinkDom: HTMLAnchorElement\r\n\r\n  constructor(draw: DrawPdf) {\r\n    this.draw = draw\r\n    this.options = draw.getOptions()\r\n    // this.container = draw.getContainer()\r\n    const { hyperlinkPopupContainer, hyperlinkDom } =\r\n      this._createHyperlinkPopupDom()\r\n    this.hyperlinkDom = hyperlinkDom\r\n    this.hyperlinkPopupContainer = hyperlinkPopupContainer\r\n  }\r\n\r\n  private _createHyperlinkPopupDom() {\r\n    const hyperlinkPopupContainer = document.createElement('div')\r\n    hyperlinkPopupContainer.classList.add(`${EDITOR_PREFIX}-hyperlink-popup`)\r\n    const hyperlinkDom = document.createElement('a')\r\n    hyperlinkDom.target = '_blank'\r\n    hyperlinkDom.rel = 'noopener'\r\n    hyperlinkPopupContainer.append(hyperlinkDom)\r\n    // this.container.append(hyperlinkPopupContainer)\r\n    return { hyperlinkPopupContainer, hyperlinkDom }\r\n  }\r\n\r\n  public drawHyperlinkPopup(element: IElement, position: IElementPosition) {\r\n    const {\r\n      coordinate: {\r\n        leftTop: [left, top]\r\n      },\r\n      lineHeight\r\n    } = position\r\n    const height = this.draw.getHeight()\r\n    const pageGap = this.draw.getPageGap()\r\n    const preY = this.draw.getPageNo() * (height + pageGap)\r\n    // 位置\r\n    this.hyperlinkPopupContainer.style.display = 'block'\r\n    this.hyperlinkPopupContainer.style.left = `${left}px`\r\n    this.hyperlinkPopupContainer.style.top = `${top + preY + lineHeight}px`\r\n    // 标签\r\n    const url = element.url || '#'\r\n    this.hyperlinkDom.href = url\r\n    this.hyperlinkDom.title = url\r\n    this.hyperlinkDom.innerText = url\r\n  }\r\n\r\n  public clearHyperlinkPopup() {\r\n    this.hyperlinkPopupContainer.style.display = 'none'\r\n  }\r\n\r\n  public openHyperlink(element: IElement) {\r\n    const newTab = window.open(element.url, '_blank')\r\n    if (newTab) {\r\n      newTab.opener = null\r\n    }\r\n  }\r\n\r\n  public render(\r\n    ctx2d: Context2d,\r\n    element: IRowElement,\r\n    x: number,\r\n    y: number\r\n  ) {\r\n    ctx2d.save()\r\n    ctx2d.font = element.style.toLowerCase()\r\n    // if (ctx2d.font.includes('Microsoft YaHei')) {\r\n    //   ctx2d.font = ctx2d.font.replace('Microsoft YaHei', 'Yahei')\r\n    // }\r\n    if (!element.color) {\r\n      element.color = this.options.defaultHyperlinkColor\r\n    }\r\n    ctx2d.fillStyle = element.color\r\n    if (element.underline === undefined) {\r\n      element.underline = true\r\n    }\r\n    ctx2d.fillText(element.value, x, y)\r\n    ctx2d.restore()\r\n  }\r\n}\r\n","import { Context2d } from 'jspdf'\r\nimport { maxHeightRadioMapping } from '../../../dataset/constant/Common'\r\nimport { EditorZone } from '../../../dataset/enum/Editor'\r\nimport { DeepRequired } from '../../../interface/Common'\r\nimport { IEditorOption } from '../../../interface/Editor'\r\nimport { pickSurroundElementList } from '../../../utils/element'\r\nimport { Position } from '../../position/Position'\r\nimport { DrawPdf } from '../DrawPdf'\r\nimport { IElement, IElementPosition } from '../../../interface/Element'\r\nimport { IRow } from '../../../interface/Row'\r\n// import { IElement } from '@hufe921/canvas-editor'\r\n// import { IElementPosition } from '@hufe921/canvas-editor/dist/src/editor/interface/Element'\r\n// import { IRow } from '@hufe921/canvas-editor/dist/src/editor/interface/Row'\r\n\r\nexport class Header {\r\n  private draw: DrawPdf\r\n  private position: Position\r\n  private options: DeepRequired<IEditorOption>\r\n\r\n  private elementList: IElement[]\r\n  private rowList: IRow[]\r\n  private positionList: IElementPosition[]\r\n\r\n  constructor(draw: DrawPdf, data?: IElement[]) {\r\n    this.draw = draw\r\n    this.position = draw.getPosition()\r\n    this.options = draw.getOptions()\r\n\r\n    this.elementList = data || []\r\n    this.rowList = []\r\n    this.positionList = []\r\n  }\r\n\r\n  public getRowList(): IRow[] {\r\n    return this.rowList\r\n  }\r\n\r\n  public setElementList(elementList: IElement[]) {\r\n    this.elementList = elementList\r\n  }\r\n\r\n  public getElementList(): IElement[] {\r\n    return this.elementList\r\n  }\r\n\r\n  public getPositionList(): IElementPosition[] {\r\n    return this.positionList\r\n  }\r\n\r\n  public compute() {\r\n    this.recovery()\r\n    this._computeRowList()\r\n    this._computePositionList()\r\n  }\r\n\r\n  public recovery() {\r\n    this.rowList = []\r\n    this.positionList = []\r\n  }\r\n\r\n  private _computeRowList() {\r\n    const innerWidth = this.draw.getInnerWidth()\r\n    const margins = this.draw.getMargins()\r\n    const surroundElementList = pickSurroundElementList(this.elementList)\r\n    this.rowList = this.draw.computeRowList({\r\n      startX: margins[3],\r\n      startY: this.getHeaderTop(),\r\n      innerWidth,\r\n      elementList: this.elementList,\r\n      surroundElementList\r\n    })\r\n  }\r\n\r\n  private _computePositionList() {\r\n    const headerTop = this.getHeaderTop()\r\n    const innerWidth = this.draw.getInnerWidth()\r\n    const margins = this.draw.getMargins()\r\n    const startX = margins[3]\r\n    const startY = headerTop\r\n    this.position.computePageRowPosition({\r\n      positionList: this.positionList,\r\n      rowList: this.rowList,\r\n      pageNo: 0,\r\n      startRowIndex: 0,\r\n      startIndex: 0,\r\n      startX,\r\n      startY,\r\n      innerWidth,\r\n      zone: EditorZone.HEADER\r\n    })\r\n  }\r\n\r\n  public getHeaderTop(): number {\r\n    const {\r\n      header: { top, disabled },\r\n      scale\r\n    } = this.options\r\n    if (disabled) return 0\r\n    return Math.floor(top * scale)\r\n  }\r\n\r\n  public getMaxHeight(): number {\r\n    const {\r\n      header: { maxHeightRadio }\r\n    } = this.options\r\n    const height = this.draw.getHeight()\r\n    return Math.floor(height * maxHeightRadioMapping[maxHeightRadio])\r\n  }\r\n\r\n  public getHeight(): number {\r\n    const maxHeight = this.getMaxHeight()\r\n    const rowHeight = this.getRowHeight()\r\n    return rowHeight > maxHeight ? maxHeight : rowHeight\r\n  }\r\n\r\n  public getRowHeight(): number {\r\n    return this.rowList.reduce((pre, cur) => pre + cur.height, 0)\r\n  }\r\n\r\n  public getExtraHeight(): number {\r\n    // 页眉上边距 + 实际高 - 页面上边距\r\n    const margins = this.draw.getMargins()\r\n    const headerHeight = this.getHeight()\r\n    const headerTop = this.getHeaderTop()\r\n    const extraHeight = headerTop + headerHeight - margins[0]\r\n    return extraHeight <= 0 ? 0 : extraHeight\r\n  }\r\n\r\n  public render(ctx2d: Context2d, pageNo: number) {\r\n    ctx2d.globalAlpha = 1\r\n    const innerWidth = this.draw.getInnerWidth()\r\n    const maxHeight = this.getMaxHeight()\r\n    // 超出最大高度不渲染\r\n    const rowList: IRow[] = []\r\n    let curRowHeight = 0\r\n    for (let r = 0; r < this.rowList.length; r++) {\r\n      const row = this.rowList[r]\r\n      if (curRowHeight + row.height > maxHeight) {\r\n        break\r\n      }\r\n      rowList.push(row)\r\n      curRowHeight += row.height\r\n    }\r\n    this.draw.drawRow(ctx2d, {\r\n      elementList: this.elementList,\r\n      positionList: this.draw.getHeader().getPositionList(),\r\n      rowList,\r\n      pageNo,\r\n      startIndex: 0,\r\n      innerWidth,\r\n      zone: EditorZone.HEADER\r\n    })\r\n  }\r\n}\r\n","import { Context2d } from 'jspdf'\r\nimport { IRowElement } from '../../../interface/Row'\r\n\r\nexport class SuperscriptParticle {\r\n  // 向上偏移字高的一半\r\n  public getOffsetY(element: IRowElement): number {\r\n    return -element.metrics.height / 2\r\n  }\r\n\r\n  public render(\r\n    ctx2d: Context2d,\r\n    element: IRowElement,\r\n    x: number,\r\n    y: number\r\n  ) {\r\n    ctx2d.save()\r\n    ctx2d.font = element.style\r\n    if (element.color) {\r\n      ctx2d.fillStyle = element.color\r\n    }\r\n    ctx2d.fillText(element.value, x, y + this.getOffsetY(element))\r\n    ctx2d.restore()\r\n  }\r\n}\r\n","import { Context2d } from 'jspdf'\r\nimport { IRowElement } from '../../../interface/Row'\r\n\r\nexport class SubscriptParticle {\r\n  // 向下偏移字高的一半\r\n  public getOffsetY(element: IRowElement): number {\r\n    return element.metrics.height / 2\r\n  }\r\n\r\n  public render(\r\n    ctx2d: Context2d,\r\n    element: IRowElement,\r\n    x: number,\r\n    y: number\r\n  ) {\r\n    ctx2d.save()\r\n    ctx2d.font = element.style\r\n    if (element.color) {\r\n      ctx2d.fillStyle = element.color\r\n    }\r\n    ctx2d.fillText(element.value, x, y + this.getOffsetY(element))\r\n    ctx2d.restore()\r\n  }\r\n}\r\n","import { Context2d } from 'jspdf'\r\nimport { DeepRequired } from '../../../interface/Common'\r\nimport { IEditorOption } from '../../../interface/Editor'\r\nimport { IRowElement } from '../../../interface/Row'\r\nimport { DrawPdf } from '../DrawPdf'\r\nexport class SeparatorParticle {\r\n  private options: DeepRequired<IEditorOption>\r\n\r\n  constructor(draw: DrawPdf) {\r\n    this.options = draw.getOptions()\r\n  }\r\n\r\n  public render(\r\n    ctx2d: Context2d,\r\n    element: IRowElement,\r\n    x: number,\r\n    y: number\r\n  ) {\r\n    ctx2d.save()\r\n    const {\r\n      scale,\r\n      separator: { lineWidth, strokeStyle }\r\n    } = this.options\r\n    ctx2d.lineWidth = lineWidth * scale\r\n    ctx2d.strokeStyle = element.color || strokeStyle\r\n    if (element.dashArray?.length) {\r\n      // ctx2d.setLineDash(element.dashArray)\r\n    }\r\n    const offsetY = Math.round(y) // 四舍五入避免绘制模糊\r\n    ctx2d.translate(0, ctx2d.lineWidth / 2)\r\n    ctx2d.beginPath()\r\n    ctx2d.moveTo(x, offsetY)\r\n    // console.log(\"element\")\r\n    // console.log(element)\r\n    // console.log(\"offsetY, y\")\r\n    // console.log(offsetY, y)\r\n    ctx2d.lineTo(x + element.width! * scale, offsetY)\r\n    ctx2d.stroke()\r\n    ctx2d.restore()\r\n  }\r\n}\r\n","export enum WatermarkType {\r\n  TEXT = 'text',\r\n  IMAGE = 'image'\r\n}\r\n","import { Context2d, GState } from 'jspdf'\r\n// import { IEditorOption } from '@hufe921/canvas-editor'\r\nimport { DeepRequired } from '../../../interface/Common'\r\nimport { DrawPdf } from '../DrawPdf'\r\nimport { IEditorOption } from '../../../interface/Editor'\r\nimport { FORMAT_PLACEHOLDER } from '../../../dataset/constant/PageNumber'\r\nimport { PageNumber } from './PageNumber'\r\nimport { WatermarkType } from '../../../dataset/enum/Watermark'\r\n\r\nexport class Watermark {\r\n  private draw: DrawPdf\r\n  private options: DeepRequired<IEditorOption>\r\n  private imageCache: Map<string, HTMLImageElement>\r\n\r\n  constructor(draw: DrawPdf) {\r\n    this.draw = draw\r\n    this.options = <DeepRequired<IEditorOption>>draw.getOptions()\r\n    this.imageCache = new Map()\r\n  }\r\n\r\n  public renderText(ctx2d: Context2d, pageNo: number) {\r\n    const {\r\n      watermark: { data, opacity, font, size, color, repeat, gap, numberType },\r\n      scale\r\n    } = this.options\r\n    const width = this.draw.getWidth()\r\n    const height = this.draw.getHeight()\r\n    // 开始绘制\r\n    ctx2d.save()\r\n    this.draw.getPdf().setGState(new GState({\r\n      opacity\r\n    }))\r\n    ctx2d.globalAlpha = opacity\r\n    ctx2d.font = `${size * scale}px ${font}`\r\n    // 格式化文本\r\n    let text = data\r\n    const pageNoReg = new RegExp(FORMAT_PLACEHOLDER.PAGE_NO)\r\n    if (pageNoReg.test(text)) {\r\n      text = PageNumber.formatNumberPlaceholder(\r\n        text,\r\n        pageNo + 1,\r\n        pageNoReg,\r\n        numberType\r\n      )\r\n    }\r\n    const pageCountReg = new RegExp(FORMAT_PLACEHOLDER.PAGE_COUNT)\r\n    if (pageCountReg.test(text)) {\r\n      text = PageNumber.formatNumberPlaceholder(\r\n        text,\r\n        this.draw.getPageCount(),\r\n        pageCountReg,\r\n        numberType\r\n      )\r\n    }\r\n    const measureText = this.draw.getFakeCtx().measureText(data)\r\n    if (repeat) {\r\n      const dpr = this.draw.getPagePixelRatio()\r\n      const temporaryCanvas = document.createElement('canvas')\r\n      const temporaryCtx = temporaryCanvas.getContext('2d')!\r\n      // 勾股定理计算旋转后的宽高对角线尺寸 a^2 + b^2 = c^2\r\n      const textWidth = measureText.width\r\n      const textHeight =\r\n        measureText.actualBoundingBoxAscent +\r\n        measureText.actualBoundingBoxDescent\r\n      const diagonalLength = Math.sqrt(\r\n        Math.pow(textWidth, 2) + Math.pow(textHeight, 2)\r\n      )\r\n      // 加上 gap 间距\r\n      const patternWidth = diagonalLength + 2 * gap[0] * scale\r\n      const patternHeight = diagonalLength + 2 * gap[1] * scale\r\n      // 宽高设置\r\n      temporaryCanvas.width = patternWidth\r\n      temporaryCanvas.height = patternHeight\r\n      temporaryCanvas.style.width = `${patternWidth * dpr}px`\r\n      temporaryCanvas.style.height = `${patternHeight * dpr}px`\r\n      // 旋转45度\r\n      temporaryCtx.translate(patternWidth / 2, patternHeight / 2)\r\n      temporaryCtx.rotate((-45 * Math.PI) / 180)\r\n      temporaryCtx.translate(-patternWidth / 2, -patternHeight / 2)\r\n      // 绘制文本\r\n      temporaryCtx.font = `${size * scale}px ${font}`\r\n      temporaryCtx.fillStyle = color\r\n      temporaryCtx.fillText(\r\n        data,\r\n        (patternWidth - textWidth) / 2,\r\n        (patternHeight - textHeight) / 2 + measureText.actualBoundingBoxAscent\r\n      )\r\n      // 创建平铺模式\r\n      // const pattern = this.draw.getDraw().getCtx().createPattern(temporaryCanvas, 'repeat')\r\n      // if (pattern) {\r\n      ctx2d.createPattern()\r\n      // ctx2d.fillStyle = pattern\r\n      ctx2d.fillRect(0, 0, width, height)\r\n      // }\r\n    } else {\r\n      const x = width / 2.8\r\n      const y = height\r\n      ctx2d.globalAlpha = opacity\r\n      ctx2d.font = `${size * scale}px ${font}`\r\n      ctx2d.fillStyle = color\r\n      // 移动到中心位置再旋转\r\n      ctx2d.translate(x, y)\r\n      ctx2d.rotate((-45 * Math.PI) / 180)\r\n      // console.log(size, y)\r\n      ctx2d.fillText(\r\n        data,\r\n        -measureText.width / 2,\r\n        measureText.actualBoundingBoxAscent - (size * 2)\r\n      )\r\n    }\r\n    this.draw.getPdf().setGState(new GState({\r\n      opacity: 1\r\n    }))\r\n    ctx2d.restore()\r\n  }\r\n\r\n  public renderImage(ctx2d: Context2d) {\r\n    const {\r\n      watermark: { width, height, data, opacity, repeat, gap },\r\n      scale\r\n    } = this.options\r\n    if (!this.imageCache.has(data)) {\r\n      // const img = new Image()\r\n      // img.setAttribute('crossOrigin', 'Anonymous')\r\n      // img.src = data\r\n      // img.onload = () => {\r\n      //   this.imageCache.set(data, img)\r\n      //   // 避免层级上浮，触发编辑器二次渲染\r\n      //   this.draw.render({\r\n      //     isCompute: false,\r\n      //     isSubmitHistory: false\r\n      //   })\r\n      // }\r\n      // return\r\n    }\r\n    const docWidth = this.draw.getWidth()\r\n    const docHeight = this.draw.getHeight()\r\n    const imageWidth = width * scale\r\n    const imageHeight = height * scale\r\n    // 开始绘制\r\n    ctx2d.save()\r\n    ctx2d.globalAlpha = opacity\r\n    if (repeat) {\r\n      const dpr = this.draw.getPagePixelRatio()\r\n      const temporaryCanvas = document.createElement('canvas')\r\n      const temporaryCtx = temporaryCanvas.getContext('2d')!\r\n      // 勾股定理计算旋转后的宽高对角线尺寸 a^2 + b^2 = c^2\r\n      const diagonalLength = Math.sqrt(\r\n        Math.pow(imageWidth, 2) + Math.pow(imageHeight, 2)\r\n      )\r\n      // 加上 gap 间距\r\n      const patternWidth = diagonalLength + 2 * gap[0] * scale\r\n      const patternHeight = diagonalLength + 2 * gap[1] * scale\r\n      // 宽高设置\r\n      temporaryCanvas.width = patternWidth\r\n      temporaryCanvas.height = patternHeight\r\n      temporaryCanvas.style.width = `${patternWidth * dpr}px`\r\n      temporaryCanvas.style.height = `${patternHeight * dpr}px`\r\n      // 旋转45度\r\n      temporaryCtx.translate(patternWidth / 2, patternHeight / 2)\r\n      temporaryCtx.rotate((-45 * Math.PI) / 180)\r\n      temporaryCtx.translate(-patternWidth / 2, -patternHeight / 2)\r\n      // 绘制图片\r\n      temporaryCtx.drawImage(\r\n        this.imageCache.get(data)!,\r\n        (patternWidth - imageWidth) / 2,\r\n        (patternHeight - imageHeight) / 2,\r\n        imageWidth,\r\n        imageHeight\r\n      )\r\n      // 创建平铺模式\r\n      // const pattern = ctx2d.createPattern(temporaryCanvas, 'repeat')\r\n      ctx2d.createPattern()\r\n      // if (pattern) {\r\n      //   ctx2d.fillStyle = pattern\r\n      ctx2d.fillRect(0, 0, docWidth, docHeight)\r\n      // }\r\n    } else {\r\n      // const x = docWidth / 2\r\n      // const y = docHeight / 2\r\n      // ctx2d.translate(x, y)\r\n      // ctx2d.rotate((-45 * Math.PI) / 180)\r\n      // const angle = 45 * Math.PI / 180 // em radianos\r\n      // const centerX = imageWidth / 2\r\n      // const centerY = imageHeight / 2\r\n\r\n      // Para rotacionar pelo centro, ajuste x e y:\r\n      // const x = centerX + (imageWidth / 2)\r\n      // console.log('x, centerX, docWidth, imageWidth')\r\n      // console.log(x, centerX, docWidth, imageWidth)\r\n      // const y = centerY + (imageHeight / 2)\r\n      // console.log('y, centerY, docHeight, imageHeight')\r\n      // console.log(y, centerY, docHeight, imageHeight)\r\n      // console.log('(docWidth - (docWidth * 45) / 100)')\r\n      // console.log((docWidth - (docWidth * 45) / 100))\r\n      // console.log((docHeight - (docHeight * 35) / 100))\r\n      this.draw.getPdf().addImage(\r\n        data,\r\n        'PNG', // ou outro formato\r\n        ((docWidth * 45) / 100),\r\n        ((docHeight * 35) / 100),\r\n        imageWidth,\r\n        imageHeight,\r\n        undefined,\r\n        'FAST',\r\n        45\r\n      )\r\n    }\r\n    ctx2d.restore()\r\n  }\r\n\r\n  public render(ctx2d: Context2d, pageNo: number) {\r\n    if (this.options.watermark.type === WatermarkType.IMAGE) {\r\n      this.renderImage(ctx2d)\r\n    } else {\r\n      this.renderText(ctx2d, pageNo)\r\n    }\r\n  }\r\n}","import { Context2d } from 'jspdf'\r\nimport { NBSP, ZERO } from '../../../dataset/constant/Common'\r\nimport { VerticalAlign } from '../../../dataset/enum/VerticalAlign'\r\nimport { DeepRequired } from '../../../interface/Common'\r\nimport { IEditorOption } from '../../../interface/Editor'\r\nimport { IElement } from '../../../interface/Element'\r\nimport { IRow, IRowElement } from '../../../interface/Row'\r\nimport { DrawPdf } from '../DrawPdf'\r\n\r\ninterface ICheckboxRenderOption {\r\n  ctx2d: Context2d\r\n  x: number\r\n  y: number\r\n  row: IRow\r\n  index: number\r\n}\r\n\r\nexport class CheckboxParticle {\r\n  private draw: DrawPdf\r\n  private options: DeepRequired<IEditorOption>\r\n\r\n  constructor(draw: DrawPdf) {\r\n    this.draw = draw\r\n    this.options = draw.getOptions()\r\n  }\r\n\r\n  public setSelect(element: IElement) {\r\n    const { checkbox } = element\r\n    if (checkbox) {\r\n      checkbox.value = !checkbox.value\r\n    } else {\r\n      element.checkbox = {\r\n        value: true\r\n      }\r\n    }\r\n    this.draw.render({\r\n      isCompute: false,\r\n      isSetCursor: false\r\n    })\r\n  }\r\n\r\n  public render(payload: ICheckboxRenderOption) {\r\n    const { ctx2d, x, index, row } = payload\r\n    let { y } = payload\r\n    const {\r\n      checkbox: { gap, lineWidth, fillStyle, strokeStyle, verticalAlign },\r\n      scale\r\n    } = this.options\r\n    const { metrics, checkbox } = row.elementList[index]\r\n    // 垂直布局设置\r\n    if (\r\n      verticalAlign === VerticalAlign.TOP ||\r\n      verticalAlign === VerticalAlign.MIDDLE\r\n    ) {\r\n      let nextIndex = index + 1\r\n      let nextElement: IRowElement | null = null\r\n      while (nextIndex < row.elementList.length) {\r\n        nextElement = row.elementList[nextIndex]\r\n        if (nextElement.value !== ZERO && nextElement.value !== NBSP) break\r\n        nextIndex++\r\n      }\r\n      // 以后一个非空格元素为基准\r\n      if (nextElement) {\r\n        const {\r\n          metrics: { boundingBoxAscent, boundingBoxDescent }\r\n        } = nextElement\r\n        const textHeight = boundingBoxAscent + boundingBoxDescent\r\n        if (textHeight > metrics.height) {\r\n          if (verticalAlign === VerticalAlign.TOP) {\r\n            y -= boundingBoxAscent - metrics.height\r\n          } else if (verticalAlign === VerticalAlign.MIDDLE) {\r\n            y -= (textHeight - metrics.height) / 2\r\n          }\r\n        }\r\n      }\r\n    }\r\n    // left top 四舍五入避免1像素问题\r\n    const left = Math.round(x + gap * scale)\r\n    const top = Math.round(y - metrics.height + lineWidth)\r\n    const width = metrics.width - gap * 2 * scale\r\n    const height = metrics.height\r\n    ctx2d.save()\r\n    ctx2d.beginPath()\r\n    ctx2d.translate(0.5, 0.5)\r\n    // 绘制勾选状态\r\n    if (checkbox?.value) {\r\n      // 边框\r\n      ctx2d.lineWidth = lineWidth\r\n      ctx2d.strokeStyle = fillStyle\r\n      ctx2d.rect(left, top, width, height)\r\n      ctx2d.stroke()\r\n      // 背景色\r\n      ctx2d.beginPath()\r\n      ctx2d.fillStyle = fillStyle\r\n      ctx2d.fillRect(left, top, width, height)\r\n      // 勾选对号\r\n      ctx2d.beginPath()\r\n      ctx2d.strokeStyle = strokeStyle\r\n      ctx2d.lineWidth = lineWidth * 2 * scale\r\n      ctx2d.moveTo(left + 2 * scale, top + height / 2)\r\n      ctx2d.lineTo(left + width / 2, top + height - 3 * scale)\r\n      ctx2d.lineTo(left + width - 2 * scale, top + 3 * scale)\r\n      ctx2d.stroke()\r\n    } else {\r\n      ctx2d.lineWidth = lineWidth\r\n      ctx2d.rect(left, top, width, height)\r\n      ctx2d.stroke()\r\n    }\r\n    ctx2d.closePath()\r\n    ctx2d.restore()\r\n  }\r\n}\r\n"]}