web-annotation-renderer 0.6.3 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/CHANGELOG.md +129 -0
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.js +62 -61
  5. package/dist/index.js.map +1 -1
  6. package/dist/index10.cjs +1 -1
  7. package/dist/index10.cjs.map +1 -1
  8. package/dist/index10.js +160 -13
  9. package/dist/index10.js.map +1 -1
  10. package/dist/index11.cjs +1 -1
  11. package/dist/index11.cjs.map +1 -1
  12. package/dist/index11.js +13 -50
  13. package/dist/index11.js.map +1 -1
  14. package/dist/index12.cjs +1 -1
  15. package/dist/index12.cjs.map +1 -1
  16. package/dist/index12.js +48 -155
  17. package/dist/index12.js.map +1 -1
  18. package/dist/index13.cjs +1 -1
  19. package/dist/index13.cjs.map +1 -1
  20. package/dist/index13.js +150 -34
  21. package/dist/index13.js.map +1 -1
  22. package/dist/index14.cjs +1 -1
  23. package/dist/index14.cjs.map +1 -1
  24. package/dist/index14.js +32 -65
  25. package/dist/index14.js.map +1 -1
  26. package/dist/index15.cjs +1 -1
  27. package/dist/index15.cjs.map +1 -1
  28. package/dist/index15.js +66 -33
  29. package/dist/index15.js.map +1 -1
  30. package/dist/index16.cjs +1 -1
  31. package/dist/index16.cjs.map +1 -1
  32. package/dist/index16.js +35 -77
  33. package/dist/index16.js.map +1 -1
  34. package/dist/index17.cjs +1 -1
  35. package/dist/index17.cjs.map +1 -1
  36. package/dist/index17.js +53 -28
  37. package/dist/index17.js.map +1 -1
  38. package/dist/index18.cjs +1 -1
  39. package/dist/index18.cjs.map +1 -1
  40. package/dist/index18.js +28 -22
  41. package/dist/index18.js.map +1 -1
  42. package/dist/index19.cjs +1 -1
  43. package/dist/index19.cjs.map +1 -1
  44. package/dist/index19.js +22 -117
  45. package/dist/index19.js.map +1 -1
  46. package/dist/index2.cjs +1 -1
  47. package/dist/index2.cjs.map +1 -1
  48. package/dist/index2.js +94 -98
  49. package/dist/index2.js.map +1 -1
  50. package/dist/index20.cjs +1 -1
  51. package/dist/index20.cjs.map +1 -1
  52. package/dist/index20.js +137 -100
  53. package/dist/index20.js.map +1 -1
  54. package/dist/index21.cjs +1 -1
  55. package/dist/index21.cjs.map +1 -1
  56. package/dist/index21.js +34 -76
  57. package/dist/index21.js.map +1 -1
  58. package/dist/index22.cjs +1 -1
  59. package/dist/index22.cjs.map +1 -1
  60. package/dist/index22.js +35 -139
  61. package/dist/index22.js.map +1 -1
  62. package/dist/index23.cjs +1 -1
  63. package/dist/index23.cjs.map +1 -1
  64. package/dist/index23.js +37 -37
  65. package/dist/index23.js.map +1 -1
  66. package/dist/index24.cjs +1 -1
  67. package/dist/index24.cjs.map +1 -1
  68. package/dist/index24.js +69 -37
  69. package/dist/index24.js.map +1 -1
  70. package/dist/index25.cjs +1 -1
  71. package/dist/index25.cjs.map +1 -1
  72. package/dist/index25.js +40 -38
  73. package/dist/index25.js.map +1 -1
  74. package/dist/index26.cjs +1 -1
  75. package/dist/index26.cjs.map +1 -1
  76. package/dist/index26.js +4 -39
  77. package/dist/index26.js.map +1 -1
  78. package/dist/index27.cjs +1 -1
  79. package/dist/index27.js +4 -4
  80. package/dist/index28.cjs +1 -1
  81. package/dist/index28.cjs.map +1 -1
  82. package/dist/index28.js +71 -5
  83. package/dist/index28.js.map +1 -1
  84. package/dist/index29.cjs +1 -1
  85. package/dist/index29.cjs.map +1 -1
  86. package/dist/index29.js +24 -69
  87. package/dist/index29.js.map +1 -1
  88. package/dist/index3.cjs +1 -1
  89. package/dist/index3.cjs.map +1 -1
  90. package/dist/index3.js +31 -31
  91. package/dist/index3.js.map +1 -1
  92. package/dist/index5.cjs +1 -1
  93. package/dist/index5.cjs.map +1 -1
  94. package/dist/index5.js +237 -190
  95. package/dist/index5.js.map +1 -1
  96. package/dist/index6.cjs +1 -1
  97. package/dist/index6.cjs.map +1 -1
  98. package/dist/index6.js +37 -19
  99. package/dist/index6.js.map +1 -1
  100. package/dist/index7.cjs +1 -1
  101. package/dist/index7.cjs.map +1 -1
  102. package/dist/index7.js +11 -17
  103. package/dist/index7.js.map +1 -1
  104. package/dist/index8.cjs +1 -1
  105. package/dist/index8.cjs.map +1 -1
  106. package/dist/index8.js +16 -125
  107. package/dist/index8.js.map +1 -1
  108. package/dist/index9.cjs +1 -1
  109. package/dist/index9.cjs.map +1 -1
  110. package/dist/index9.js +118 -201
  111. package/dist/index9.js.map +1 -1
  112. package/package.json +6 -3
@@ -1 +1 @@
1
- {"version":3,"file":"index15.cjs","sources":["../src/converters/underline.js"],"sourcesContent":["/**\n * Underline Converter - Converts underline annotations to stroke commands\n *\n * Transforms quads into horizontal stroke paths at the bottom edge\n * that can be rendered progressively on canvas with hand-drawn style.\n *\n * @module converters/underline\n */\n\nimport { roughLine, hashSeed } from '../rough/roughPathExtractor.js';\n\nconst SCALE = 1000;\n\n/**\n * Converts an underline annotation to stroke commands\n *\n * Each quad in the annotation becomes a horizontal stroke at the\n * bottom edge of the quad. Multiple quads are staggered in timing.\n * Uses RoughJS for hand-drawn style.\n *\n * @param {Object} annotation - Underline annotation object\n * @param {string} annotation.id - Unique identifier\n * @param {number} annotation.start - Start time in seconds\n * @param {number} annotation.end - End time in seconds\n * @param {Array<{x: number, y: number, w: number, h: number}>} annotation.quads - Array of quads\n * @param {Object} [annotation.style] - Optional style overrides\n * @param {Object} style - Resolved style configuration\n * @param {string} style.color - Stroke color\n * @param {number} style.width - Stroke width in pixels\n * @param {string} [style.lineCap='round'] - Line cap style\n * @param {number} [style.roughness=1.0] - Hand-drawn roughness\n * @param {number} [style.bowing=1.0] - Line curvature\n * @returns {Array<Object>} Array of stroke commands\n */\nexport function underlineToStrokes(annotation, style) {\n const { id, start, end, quads } = annotation;\n\n if (!quads || quads.length === 0) {\n return [];\n }\n\n const strokes = [];\n const totalDuration = end - start;\n const quadCount = quads.length;\n const quadDuration = totalDuration / quadCount;\n\n const roughness = style.roughness ?? 1.0;\n const bowing = style.bowing ?? 1.0;\n const curveFitting = style.curveFitting ?? 0.95;\n const curveStepCount = style.curveStepCount ?? 9;\n const maxRandomnessOffset = style.maxRandomnessOffset ?? 2;\n const disableMultiStroke = style.disableMultiStroke ?? false;\n\n for (let i = 0; i < quads.length; i++) {\n const quad = quads[i];\n const { x, y, w, h } = quad;\n\n const lineY = y + h;\n\n const roughPoints = roughLine(\n x * SCALE,\n lineY * SCALE,\n (x + w) * SCALE,\n lineY * SCALE,\n {\n roughness,\n bowing,\n seed: hashSeed(`${id}-${i}`),\n curveFitting,\n curveStepCount,\n maxRandomnessOffset,\n disableMultiStroke\n }\n );\n\n const points = roughPoints.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n const quadStart = start + i * quadDuration;\n const quadEnd = quadStart + quadDuration;\n\n strokes.push({\n id: `${id}-${i}`,\n points,\n start: quadStart,\n end: quadEnd,\n color: style.color || 'rgba(0, 0, 255, 0.8)',\n width: style.width || 2,\n lineCap: style.lineCap || 'round'\n });\n }\n\n return strokes;\n}\n\nexport default underlineToStrokes;\n"],"names":["SCALE","underlineToStrokes","annotation","style","id","start","end","quads","strokes","totalDuration","quadCount","quadDuration","roughness","bowing","curveFitting","curveStepCount","maxRandomnessOffset","disableMultiStroke","i","quad","x","y","w","h","lineY","points","roughLine","hashSeed","px","py","quadStart","quadEnd"],"mappings":"6IAWMA,EAAQ,IAuBP,SAASC,EAAmBC,EAAYC,EAAO,CACpD,KAAM,CAAE,GAAAC,EAAI,MAAAC,EAAO,IAAAC,EAAK,MAAAC,CAAK,EAAKL,EAElC,GAAI,CAACK,GAASA,EAAM,SAAW,EAC7B,MAAO,CAAA,EAGT,MAAMC,EAAU,CAAA,EACVC,EAAgBH,EAAMD,EACtBK,EAAYH,EAAM,OAClBI,EAAeF,EAAgBC,EAE/BE,EAAYT,EAAM,WAAa,EAC/BU,EAASV,EAAM,QAAU,EACzBW,EAAeX,EAAM,cAAgB,IACrCY,EAAiBZ,EAAM,gBAAkB,EACzCa,EAAsBb,EAAM,qBAAuB,EACnDc,EAAqBd,EAAM,oBAAsB,GAEvD,QAASe,EAAI,EAAGA,EAAIX,EAAM,OAAQW,IAAK,CACrC,MAAMC,EAAOZ,EAAMW,CAAC,EACd,CAAE,EAAAE,EAAG,EAAAC,EAAG,EAAAC,EAAG,EAAAC,CAAC,EAAKJ,EAEjBK,EAAQH,EAAIE,EAkBZE,EAhBcC,EAAAA,UAClBN,EAAIpB,EACJwB,EAAQxB,GACPoB,EAAIE,GAAKtB,EACVwB,EAAQxB,EACR,CACE,UAAAY,EACA,OAAAC,EACA,KAAMc,EAAAA,SAAS,GAAGvB,CAAE,IAAIc,CAAC,EAAE,EAC3B,aAAAJ,EACA,eAAAC,EACA,oBAAAC,EACA,mBAAAC,CACR,CACA,EAE+B,IAAI,CAAC,CAACW,EAAIC,CAAE,IAAM,CAACD,EAAK5B,EAAO6B,EAAK7B,CAAK,CAAC,EAE/D8B,EAAYzB,EAAQa,EAAIP,EACxBoB,EAAUD,EAAYnB,EAE5BH,EAAQ,KAAK,CACX,GAAI,GAAGJ,CAAE,IAAIc,CAAC,GACd,OAAAO,EACA,MAAOK,EACP,IAAKC,EACL,MAAO5B,EAAM,OAAS,uBACtB,MAAOA,EAAM,OAAS,EACtB,QAASA,EAAM,SAAW,OAChC,CAAK,CACH,CAEA,OAAOK,CACT"}
1
+ {"version":3,"file":"index15.cjs","sources":["../src/converters/text.js"],"sourcesContent":["/**\n * Text Converter - Converts text annotations to stroke commands\n *\n * Transforms text content into stroke paths for each character,\n * using single-stroke font glyphs for smooth writing animation\n * with hand-drawn style.\n *\n * @module converters/text\n */\n\nimport { resolveGlyph } from \"./glyphResolver.js\";\nimport { hashSeed } from \"../rough/roughPathExtractor.js\";\nimport { resolveColor } from \"./_shared.js\";\nimport { REFERENCE_HEIGHT } from \"../config/defaults.js\";\n\n/**\n * Simple seeded random number generator\n * Returns value between -1 and 1\n */\nfunction seededRandom(seed) {\n const x = Math.sin(seed) * 10000;\n return (x - Math.floor(x)) * 2 - 1;\n}\n\n/**\n * Apply hand-drawn jitter to points\n * Each point gets a random offset based on seed for reproducibility\n */\nfunction applyJitter(points, amplitude, seed) {\n return points.map(([x, y], i) => [\n x + seededRandom(seed + i * 2) * amplitude,\n y + seededRandom(seed + i * 2 + 1) * amplitude\n ]);\n}\n\n/**\n * Scales glyph points by fontSize scale factor\n *\n * Glyph points are in normalized space where:\n * - X is 0 to charWidth (already scaled within the glyph)\n * - Y is 0 to ~1.0 (baseline at 0.8, cap height at 0)\n *\n * This scales them to the target size, but does NOT add the base position.\n * The base position is stored separately to allow correct rendering with\n * mixed coordinate systems (position in page coords, offsets in uniform space).\n *\n * @param {Array<[number, number]>} points - Glyph points in normalized space\n * @param {number} offsetX - X offset from base position (character offset within text)\n * @param {number} scale - Scale factor based on fontSize\n * @returns {Array<[number, number]>} Scaled offset points (not absolute positions)\n */\nfunction scaleGlyphPoints(points, offsetX, scale) {\n // Scale points and add character offset (in uniform space)\n return points.map(([px, py]) => [(offsetX + px) * scale, py * scale]);\n}\n\n/**\n * Converts a text annotation to stroke commands\n *\n * Each character in the content becomes one or more strokes.\n * Characters are staggered in timing to create a writing effect.\n * Multi-path characters (like 'i', 'j', '!') use pathTiming to\n * control whether paths are drawn sequentially or in parallel.\n *\n * @param {Object} annotation - Text annotation object\n * @param {string} annotation.id - Unique identifier\n * @param {number} annotation.start - Start time in seconds\n * @param {number} annotation.end - End time in seconds\n * @param {string} annotation.content - Text content to render\n * @param {number} annotation.x - X position (normalized 0-1)\n * @param {number} annotation.y - Y position (normalized 0-1)\n * @param {number} [annotation.fontSize=16] - Font size in viewport-pixel units.\n * Internally converted via `fontScale = fontSize / REFERENCE_HEIGHT` and the\n * resulting glyphs are rendered using uniform scaling, so apparent screen\n * size scales with `viewport.height` (not absolute pixels). For predictable\n * results, choose `fontSize` relative to a 500px reference viewport\n * (`REFERENCE_HEIGHT` from `config/defaults.js`).\n *\n * v0.7.0 NOTE: prior versions divided by a hardcoded `1000` here, which\n * was inconsistent with the renderer's `REFERENCE_HEIGHT = 500` scale\n * factor and produced glyphs at half the documented size. This is now\n * fixed — at the same `fontSize` value, glyphs render approximately 2x\n * their pre-v0.7.0 size.\n * @param {Object} [annotation.style] - Optional style overrides\n * @param {Object} style - Resolved style configuration\n * @param {string} style.color - Stroke color\n * @param {number} style.width - Stroke width in pixels\n * @param {number} [style.fontSize=16] - Default font size (see annotation.fontSize)\n * @param {string} [style.lineCap='round'] - Line cap style\n * @param {number} [style.roughness=1.5] - Hand-drawn jitter amplitude\n * @returns {Array<Object>} Array of stroke commands\n */\nexport function textToStrokes(annotation, style) {\n const { id, start, end, content, x, y, fontSize: annotFontSize } = annotation;\n\n if (!content || content.length === 0) {\n return [];\n }\n\n const strokes = [];\n const totalDuration = end - start;\n const fontSize = annotFontSize || style.fontSize || 16;\n\n const roughness = style.roughness ?? 1.5;\n\n // Scale factor: convert fontSize (viewport-pixel units) to uniform-space\n // offsets. The renderer scales offsets by `viewport.height` when\n // `uniformScale=true`, so dividing by REFERENCE_HEIGHT here produces\n // glyphs that render at `fontSize` pixels tall on a 500px-tall viewport\n // (and scale proportionally on other sizes).\n const fontScale = fontSize / REFERENCE_HEIGHT;\n\n // Track character offset from base position (in glyph units, not page coords)\n let charOffsetX = 0;\n\n // Calculate timing per character\n const charCount = content.length;\n const charDuration = totalDuration / charCount;\n\n for (let charIndex = 0; charIndex < content.length; charIndex++) {\n const char = content[charIndex];\n const glyph = resolveGlyph(char);\n\n if (!glyph) {\n // Skip unknown characters, but advance position with default width\n charOffsetX += 0.5 + 0.18; // default width + spacing (in glyph units)\n continue;\n }\n\n const charWidth = glyph.width || 0.5;\n const charPaths = glyph.paths || [];\n const pathTiming = glyph.pathTiming || \"sequential\";\n\n // Skip if no paths (e.g., space character)\n if (charPaths.length === 0) {\n charOffsetX += charWidth + 0.18;\n continue;\n }\n\n // Calculate timing for this character's paths\n const charStart = start + charIndex * charDuration;\n const charEnd = charStart + charDuration;\n\n // Determine path timing based on pathTiming mode\n const pathCount = charPaths.length;\n\n for (let pathIndex = 0; pathIndex < charPaths.length; pathIndex++) {\n const pathData = charPaths[pathIndex];\n const rawPoints = pathData.points || [];\n\n if (rawPoints.length < 2) continue;\n\n // Scale glyph points to offset coordinates\n const scaledPoints = scaleGlyphPoints(rawPoints, charOffsetX, fontScale);\n\n // Apply hand-drawn jitter effect\n // Amplitude is in offset coordinates (scaled by viewport.height when rendered)\n // 0.0007 = ~0.4 pixels at 600px viewport, subtle hand-drawn effect\n const jitterAmplitude = roughness * 0.0007;\n const seed = hashSeed(`${id}-${charIndex}-${pathIndex}`);\n const points = applyJitter(scaledPoints, jitterAmplitude, seed);\n\n // Calculate path timing based on pathTiming mode\n let pathStart, pathEnd;\n\n if (pathTiming === \"parallel\") {\n // All paths drawn simultaneously during character duration\n pathStart = charStart;\n pathEnd = charEnd;\n } else {\n // Sequential: each path gets a portion of character duration\n const pathDuration = charDuration / pathCount;\n pathStart = charStart + pathIndex * pathDuration;\n pathEnd = pathStart + pathDuration;\n }\n\n strokes.push({\n id: `${id}-${charIndex}-${pathIndex}`,\n points, // Offset coordinates from baseX/baseY (uniform space)\n baseX: x, // Base X position (width-normalized page coords)\n baseY: y, // Base Y position (height-normalized page coords)\n start: pathStart,\n end: pathEnd,\n color: resolveColor(style, \"rgba(220, 20, 60, 1.0)\"),\n width: style.width || 2,\n lineCap: style.lineCap || \"round\",\n uniformScale: true, // Preserve aspect ratio when rendering\n });\n }\n\n // Advance offset for next character (in glyph units)\n charOffsetX += charWidth + 0.18; // Add small spacing\n }\n\n return strokes;\n}\n\nexport default textToStrokes;\n"],"names":["seededRandom","seed","x","applyJitter","points","amplitude","y","i","scaleGlyphPoints","offsetX","scale","px","py","textToStrokes","annotation","style","id","start","end","content","annotFontSize","strokes","totalDuration","fontSize","roughness","fontScale","REFERENCE_HEIGHT","charOffsetX","charCount","charDuration","charIndex","char","glyph","resolveGlyph","charWidth","charPaths","pathTiming","charStart","charEnd","pathCount","pathIndex","rawPoints","scaledPoints","jitterAmplitude","hashSeed","pathStart","pathEnd","pathDuration","resolveColor"],"mappings":"8NAmBA,SAASA,EAAaC,EAAM,CAC1B,MAAMC,EAAI,KAAK,IAAID,CAAI,EAAI,IAC3B,OAAQC,EAAI,KAAK,MAAMA,CAAC,GAAK,EAAI,CACnC,CAMA,SAASC,EAAYC,EAAQC,EAAWJ,EAAM,CAC5C,OAAOG,EAAO,IAAI,CAAC,CAACF,EAAGI,CAAC,EAAGC,IAAM,CAC/BL,EAAIF,EAAaC,EAAOM,EAAI,CAAC,EAAIF,EACjCC,EAAIN,EAAaC,EAAOM,EAAI,EAAI,CAAC,EAAIF,CACzC,CAAG,CACH,CAkBA,SAASG,EAAiBJ,EAAQK,EAASC,EAAO,CAEhD,OAAON,EAAO,IAAI,CAAC,CAACO,EAAIC,CAAE,IAAM,EAAEH,EAAUE,GAAMD,EAAOE,EAAKF,CAAK,CAAC,CACtE,CAsCO,SAASG,EAAcC,EAAYC,EAAO,CAC/C,KAAM,CAAE,GAAAC,EAAI,MAAAC,EAAO,IAAAC,EAAK,QAAAC,EAAS,EAAAjB,EAAG,EAAAI,EAAG,SAAUc,CAAa,EAAKN,EAEnE,GAAI,CAACK,GAAWA,EAAQ,SAAW,EACjC,MAAO,CAAA,EAGT,MAAME,EAAU,CAAA,EACVC,EAAgBJ,EAAMD,EACtBM,EAAWH,GAAiBL,EAAM,UAAY,GAE9CS,EAAYT,EAAM,WAAa,IAO/BU,EAAYF,EAAWG,EAAAA,iBAG7B,IAAIC,EAAc,EAGlB,MAAMC,EAAYT,EAAQ,OACpBU,EAAeP,EAAgBM,EAErC,QAASE,EAAY,EAAGA,EAAYX,EAAQ,OAAQW,IAAa,CAC/D,MAAMC,EAAOZ,EAAQW,CAAS,EACxBE,EAAQC,EAAAA,aAAaF,CAAI,EAE/B,GAAI,CAACC,EAAO,CAEVL,GAAe,GAAM,IACrB,QACF,CAEA,MAAMO,EAAYF,EAAM,OAAS,GAC3BG,EAAYH,EAAM,OAAS,CAAA,EAC3BI,EAAaJ,EAAM,YAAc,aAGvC,GAAIG,EAAU,SAAW,EAAG,CAC1BR,GAAeO,EAAY,IAC3B,QACF,CAGA,MAAMG,EAAYpB,EAAQa,EAAYD,EAChCS,EAAUD,EAAYR,EAGtBU,EAAYJ,EAAU,OAE5B,QAASK,EAAY,EAAGA,EAAYL,EAAU,OAAQK,IAAa,CAEjE,MAAMC,EADWN,EAAUK,CAAS,EACT,QAAU,CAAA,EAErC,GAAIC,EAAU,OAAS,EAAG,SAG1B,MAAMC,EAAelC,EAAiBiC,EAAWd,EAAaF,CAAS,EAKjEkB,EAAkBnB,EAAY,KAC9BvB,EAAO2C,WAAS,GAAG5B,CAAE,IAAIc,CAAS,IAAIU,CAAS,EAAE,EACjDpC,EAASD,EAAYuC,EAAcC,EAAiB1C,CAAI,EAG9D,IAAI4C,EAAWC,EAEf,GAAIV,IAAe,WAEjBS,EAAYR,EACZS,EAAUR,MACL,CAEL,MAAMS,EAAelB,EAAeU,EACpCM,EAAYR,EAAYG,EAAYO,EACpCD,EAAUD,EAAYE,CACxB,CAEA1B,EAAQ,KAAK,CACX,GAAI,GAAGL,CAAE,IAAIc,CAAS,IAAIU,CAAS,GACnC,OAAApC,EACA,MAAOF,EACP,MAAOI,EACP,MAAOuC,EACP,IAAKC,EACL,MAAOE,EAAAA,aAAajC,EAAO,wBAAwB,EACnD,MAAOA,EAAM,OAAS,EACtB,QAASA,EAAM,SAAW,QAC1B,aAAc,EACtB,CAAO,CACH,CAGAY,GAAeO,EAAY,GAC7B,CAEA,OAAOb,CACT"}
package/dist/index15.js CHANGED
@@ -1,40 +1,73 @@
1
- import { roughLine as L, hashSeed as M } from "./index29.js";
2
- const o = 1e3;
3
- function R(h, n) {
4
- const { id: e, start: r, end: g, quads: s } = h;
5
- if (!s || s.length === 0)
1
+ import { resolveGlyph as X } from "./index12.js";
2
+ import { hashSeed as j } from "./index28.js";
3
+ import { resolveColor as q } from "./index29.js";
4
+ import { REFERENCE_HEIGHT as y } from "./index24.js";
5
+ function x(e) {
6
+ const t = Math.sin(e) * 1e4;
7
+ return (t - Math.floor(t)) * 2 - 1;
8
+ }
9
+ function A(e, t, n) {
10
+ return e.map(([r, c], o) => [
11
+ r + x(n + o * 2) * t,
12
+ c + x(n + o * 2 + 1) * t
13
+ ]);
14
+ }
15
+ function J(e, t, n) {
16
+ return e.map(([r, c]) => [(t + r) * n, c * n]);
17
+ }
18
+ function B(e, t) {
19
+ const { id: n, start: r, end: c, content: o, x: C, y: $, fontSize: D } = e;
20
+ if (!o || o.length === 0)
6
21
  return [];
7
- const u = [], f = g - r, l = s.length, i = f / l, p = n.roughness ?? 1, S = n.bowing ?? 1, m = n.curveFitting ?? 0.95, q = n.curveStepCount ?? 9, C = n.maxRandomnessOffset ?? 2, b = n.disableMultiStroke ?? !1;
8
- for (let t = 0; t < s.length; t++) {
9
- const w = s[t], { x: a, y: k, w: v, h: x } = w, c = k + x, $ = L(
10
- a * o,
11
- c * o,
12
- (a + v) * o,
13
- c * o,
14
- {
15
- roughness: p,
16
- bowing: S,
17
- seed: M(`${e}-${t}`),
18
- curveFitting: m,
19
- curveStepCount: q,
20
- maxRandomnessOffset: C,
21
- disableMultiStroke: b
22
+ const m = [], w = c - r, z = D || t.fontSize || 16, P = t.roughness ?? 1.5, T = z / y;
23
+ let i = 0;
24
+ const b = o.length, u = w / b;
25
+ for (let a = 0; a < o.length; a++) {
26
+ const G = o[a], h = X(G);
27
+ if (!h) {
28
+ i += 0.5 + 0.18;
29
+ continue;
30
+ }
31
+ const g = h.width || 0.5, l = h.paths || [], I = h.pathTiming || "sequential";
32
+ if (l.length === 0) {
33
+ i += g + 0.18;
34
+ continue;
35
+ }
36
+ const f = r + a * u, R = f + u, k = l.length;
37
+ for (let s = 0; s < l.length; s++) {
38
+ const S = l[s].points || [];
39
+ if (S.length < 2) continue;
40
+ const v = J(S, i, T), F = P * 7e-4, H = j(`${n}-${a}-${s}`), M = A(v, F, H);
41
+ let p, d;
42
+ if (I === "parallel")
43
+ p = f, d = R;
44
+ else {
45
+ const E = u / k;
46
+ p = f + s * E, d = p + E;
22
47
  }
23
- ).map(([E, F]) => [E / o, F / o]), d = r + t * i, D = d + i;
24
- u.push({
25
- id: `${e}-${t}`,
26
- points: $,
27
- start: d,
28
- end: D,
29
- color: n.color || "rgba(0, 0, 255, 0.8)",
30
- width: n.width || 2,
31
- lineCap: n.lineCap || "round"
32
- });
48
+ m.push({
49
+ id: `${n}-${a}-${s}`,
50
+ points: M,
51
+ // Offset coordinates from baseX/baseY (uniform space)
52
+ baseX: C,
53
+ // Base X position (width-normalized page coords)
54
+ baseY: $,
55
+ // Base Y position (height-normalized page coords)
56
+ start: p,
57
+ end: d,
58
+ color: q(t, "rgba(220, 20, 60, 1.0)"),
59
+ width: t.width || 2,
60
+ lineCap: t.lineCap || "round",
61
+ uniformScale: !0
62
+ // Preserve aspect ratio when rendering
63
+ });
64
+ }
65
+ i += g + 0.18;
33
66
  }
34
- return u;
67
+ return m;
35
68
  }
36
69
  export {
37
- R as default,
38
- R as underlineToStrokes
70
+ B as default,
71
+ B as textToStrokes
39
72
  };
40
73
  //# sourceMappingURL=index15.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index15.js","sources":["../src/converters/underline.js"],"sourcesContent":["/**\n * Underline Converter - Converts underline annotations to stroke commands\n *\n * Transforms quads into horizontal stroke paths at the bottom edge\n * that can be rendered progressively on canvas with hand-drawn style.\n *\n * @module converters/underline\n */\n\nimport { roughLine, hashSeed } from '../rough/roughPathExtractor.js';\n\nconst SCALE = 1000;\n\n/**\n * Converts an underline annotation to stroke commands\n *\n * Each quad in the annotation becomes a horizontal stroke at the\n * bottom edge of the quad. Multiple quads are staggered in timing.\n * Uses RoughJS for hand-drawn style.\n *\n * @param {Object} annotation - Underline annotation object\n * @param {string} annotation.id - Unique identifier\n * @param {number} annotation.start - Start time in seconds\n * @param {number} annotation.end - End time in seconds\n * @param {Array<{x: number, y: number, w: number, h: number}>} annotation.quads - Array of quads\n * @param {Object} [annotation.style] - Optional style overrides\n * @param {Object} style - Resolved style configuration\n * @param {string} style.color - Stroke color\n * @param {number} style.width - Stroke width in pixels\n * @param {string} [style.lineCap='round'] - Line cap style\n * @param {number} [style.roughness=1.0] - Hand-drawn roughness\n * @param {number} [style.bowing=1.0] - Line curvature\n * @returns {Array<Object>} Array of stroke commands\n */\nexport function underlineToStrokes(annotation, style) {\n const { id, start, end, quads } = annotation;\n\n if (!quads || quads.length === 0) {\n return [];\n }\n\n const strokes = [];\n const totalDuration = end - start;\n const quadCount = quads.length;\n const quadDuration = totalDuration / quadCount;\n\n const roughness = style.roughness ?? 1.0;\n const bowing = style.bowing ?? 1.0;\n const curveFitting = style.curveFitting ?? 0.95;\n const curveStepCount = style.curveStepCount ?? 9;\n const maxRandomnessOffset = style.maxRandomnessOffset ?? 2;\n const disableMultiStroke = style.disableMultiStroke ?? false;\n\n for (let i = 0; i < quads.length; i++) {\n const quad = quads[i];\n const { x, y, w, h } = quad;\n\n const lineY = y + h;\n\n const roughPoints = roughLine(\n x * SCALE,\n lineY * SCALE,\n (x + w) * SCALE,\n lineY * SCALE,\n {\n roughness,\n bowing,\n seed: hashSeed(`${id}-${i}`),\n curveFitting,\n curveStepCount,\n maxRandomnessOffset,\n disableMultiStroke\n }\n );\n\n const points = roughPoints.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n const quadStart = start + i * quadDuration;\n const quadEnd = quadStart + quadDuration;\n\n strokes.push({\n id: `${id}-${i}`,\n points,\n start: quadStart,\n end: quadEnd,\n color: style.color || 'rgba(0, 0, 255, 0.8)',\n width: style.width || 2,\n lineCap: style.lineCap || 'round'\n });\n }\n\n return strokes;\n}\n\nexport default underlineToStrokes;\n"],"names":["SCALE","underlineToStrokes","annotation","style","id","start","end","quads","strokes","totalDuration","quadCount","quadDuration","roughness","bowing","curveFitting","curveStepCount","maxRandomnessOffset","disableMultiStroke","i","quad","x","y","w","h","lineY","points","roughLine","hashSeed","px","py","quadStart","quadEnd"],"mappings":";AAWA,MAAMA,IAAQ;AAuBP,SAASC,EAAmBC,GAAYC,GAAO;AACpD,QAAM,EAAE,IAAAC,GAAI,OAAAC,GAAO,KAAAC,GAAK,OAAAC,EAAK,IAAKL;AAElC,MAAI,CAACK,KAASA,EAAM,WAAW;AAC7B,WAAO,CAAA;AAGT,QAAMC,IAAU,CAAA,GACVC,IAAgBH,IAAMD,GACtBK,IAAYH,EAAM,QAClBI,IAAeF,IAAgBC,GAE/BE,IAAYT,EAAM,aAAa,GAC/BU,IAASV,EAAM,UAAU,GACzBW,IAAeX,EAAM,gBAAgB,MACrCY,IAAiBZ,EAAM,kBAAkB,GACzCa,IAAsBb,EAAM,uBAAuB,GACnDc,IAAqBd,EAAM,sBAAsB;AAEvD,WAASe,IAAI,GAAGA,IAAIX,EAAM,QAAQW,KAAK;AACrC,UAAMC,IAAOZ,EAAMW,CAAC,GACd,EAAE,GAAAE,GAAG,GAAAC,GAAG,GAAAC,GAAG,GAAAC,EAAC,IAAKJ,GAEjBK,IAAQH,IAAIE,GAkBZE,IAhBcC;AAAA,MAClBN,IAAIpB;AAAA,MACJwB,IAAQxB;AAAA,OACPoB,IAAIE,KAAKtB;AAAA,MACVwB,IAAQxB;AAAA,MACR;AAAA,QACE,WAAAY;AAAA,QACA,QAAAC;AAAA,QACA,MAAMc,EAAS,GAAGvB,CAAE,IAAIc,CAAC,EAAE;AAAA,QAC3B,cAAAJ;AAAA,QACA,gBAAAC;AAAA,QACA,qBAAAC;AAAA,QACA,oBAAAC;AAAA,MACR;AAAA,IACA,EAE+B,IAAI,CAAC,CAACW,GAAIC,CAAE,MAAM,CAACD,IAAK5B,GAAO6B,IAAK7B,CAAK,CAAC,GAE/D8B,IAAYzB,IAAQa,IAAIP,GACxBoB,IAAUD,IAAYnB;AAE5B,IAAAH,EAAQ,KAAK;AAAA,MACX,IAAI,GAAGJ,CAAE,IAAIc,CAAC;AAAA,MACd,QAAAO;AAAA,MACA,OAAOK;AAAA,MACP,KAAKC;AAAA,MACL,OAAO5B,EAAM,SAAS;AAAA,MACtB,OAAOA,EAAM,SAAS;AAAA,MACtB,SAASA,EAAM,WAAW;AAAA,IAChC,CAAK;AAAA,EACH;AAEA,SAAOK;AACT;"}
1
+ {"version":3,"file":"index15.js","sources":["../src/converters/text.js"],"sourcesContent":["/**\n * Text Converter - Converts text annotations to stroke commands\n *\n * Transforms text content into stroke paths for each character,\n * using single-stroke font glyphs for smooth writing animation\n * with hand-drawn style.\n *\n * @module converters/text\n */\n\nimport { resolveGlyph } from \"./glyphResolver.js\";\nimport { hashSeed } from \"../rough/roughPathExtractor.js\";\nimport { resolveColor } from \"./_shared.js\";\nimport { REFERENCE_HEIGHT } from \"../config/defaults.js\";\n\n/**\n * Simple seeded random number generator\n * Returns value between -1 and 1\n */\nfunction seededRandom(seed) {\n const x = Math.sin(seed) * 10000;\n return (x - Math.floor(x)) * 2 - 1;\n}\n\n/**\n * Apply hand-drawn jitter to points\n * Each point gets a random offset based on seed for reproducibility\n */\nfunction applyJitter(points, amplitude, seed) {\n return points.map(([x, y], i) => [\n x + seededRandom(seed + i * 2) * amplitude,\n y + seededRandom(seed + i * 2 + 1) * amplitude\n ]);\n}\n\n/**\n * Scales glyph points by fontSize scale factor\n *\n * Glyph points are in normalized space where:\n * - X is 0 to charWidth (already scaled within the glyph)\n * - Y is 0 to ~1.0 (baseline at 0.8, cap height at 0)\n *\n * This scales them to the target size, but does NOT add the base position.\n * The base position is stored separately to allow correct rendering with\n * mixed coordinate systems (position in page coords, offsets in uniform space).\n *\n * @param {Array<[number, number]>} points - Glyph points in normalized space\n * @param {number} offsetX - X offset from base position (character offset within text)\n * @param {number} scale - Scale factor based on fontSize\n * @returns {Array<[number, number]>} Scaled offset points (not absolute positions)\n */\nfunction scaleGlyphPoints(points, offsetX, scale) {\n // Scale points and add character offset (in uniform space)\n return points.map(([px, py]) => [(offsetX + px) * scale, py * scale]);\n}\n\n/**\n * Converts a text annotation to stroke commands\n *\n * Each character in the content becomes one or more strokes.\n * Characters are staggered in timing to create a writing effect.\n * Multi-path characters (like 'i', 'j', '!') use pathTiming to\n * control whether paths are drawn sequentially or in parallel.\n *\n * @param {Object} annotation - Text annotation object\n * @param {string} annotation.id - Unique identifier\n * @param {number} annotation.start - Start time in seconds\n * @param {number} annotation.end - End time in seconds\n * @param {string} annotation.content - Text content to render\n * @param {number} annotation.x - X position (normalized 0-1)\n * @param {number} annotation.y - Y position (normalized 0-1)\n * @param {number} [annotation.fontSize=16] - Font size in viewport-pixel units.\n * Internally converted via `fontScale = fontSize / REFERENCE_HEIGHT` and the\n * resulting glyphs are rendered using uniform scaling, so apparent screen\n * size scales with `viewport.height` (not absolute pixels). For predictable\n * results, choose `fontSize` relative to a 500px reference viewport\n * (`REFERENCE_HEIGHT` from `config/defaults.js`).\n *\n * v0.7.0 NOTE: prior versions divided by a hardcoded `1000` here, which\n * was inconsistent with the renderer's `REFERENCE_HEIGHT = 500` scale\n * factor and produced glyphs at half the documented size. This is now\n * fixed — at the same `fontSize` value, glyphs render approximately 2x\n * their pre-v0.7.0 size.\n * @param {Object} [annotation.style] - Optional style overrides\n * @param {Object} style - Resolved style configuration\n * @param {string} style.color - Stroke color\n * @param {number} style.width - Stroke width in pixels\n * @param {number} [style.fontSize=16] - Default font size (see annotation.fontSize)\n * @param {string} [style.lineCap='round'] - Line cap style\n * @param {number} [style.roughness=1.5] - Hand-drawn jitter amplitude\n * @returns {Array<Object>} Array of stroke commands\n */\nexport function textToStrokes(annotation, style) {\n const { id, start, end, content, x, y, fontSize: annotFontSize } = annotation;\n\n if (!content || content.length === 0) {\n return [];\n }\n\n const strokes = [];\n const totalDuration = end - start;\n const fontSize = annotFontSize || style.fontSize || 16;\n\n const roughness = style.roughness ?? 1.5;\n\n // Scale factor: convert fontSize (viewport-pixel units) to uniform-space\n // offsets. The renderer scales offsets by `viewport.height` when\n // `uniformScale=true`, so dividing by REFERENCE_HEIGHT here produces\n // glyphs that render at `fontSize` pixels tall on a 500px-tall viewport\n // (and scale proportionally on other sizes).\n const fontScale = fontSize / REFERENCE_HEIGHT;\n\n // Track character offset from base position (in glyph units, not page coords)\n let charOffsetX = 0;\n\n // Calculate timing per character\n const charCount = content.length;\n const charDuration = totalDuration / charCount;\n\n for (let charIndex = 0; charIndex < content.length; charIndex++) {\n const char = content[charIndex];\n const glyph = resolveGlyph(char);\n\n if (!glyph) {\n // Skip unknown characters, but advance position with default width\n charOffsetX += 0.5 + 0.18; // default width + spacing (in glyph units)\n continue;\n }\n\n const charWidth = glyph.width || 0.5;\n const charPaths = glyph.paths || [];\n const pathTiming = glyph.pathTiming || \"sequential\";\n\n // Skip if no paths (e.g., space character)\n if (charPaths.length === 0) {\n charOffsetX += charWidth + 0.18;\n continue;\n }\n\n // Calculate timing for this character's paths\n const charStart = start + charIndex * charDuration;\n const charEnd = charStart + charDuration;\n\n // Determine path timing based on pathTiming mode\n const pathCount = charPaths.length;\n\n for (let pathIndex = 0; pathIndex < charPaths.length; pathIndex++) {\n const pathData = charPaths[pathIndex];\n const rawPoints = pathData.points || [];\n\n if (rawPoints.length < 2) continue;\n\n // Scale glyph points to offset coordinates\n const scaledPoints = scaleGlyphPoints(rawPoints, charOffsetX, fontScale);\n\n // Apply hand-drawn jitter effect\n // Amplitude is in offset coordinates (scaled by viewport.height when rendered)\n // 0.0007 = ~0.4 pixels at 600px viewport, subtle hand-drawn effect\n const jitterAmplitude = roughness * 0.0007;\n const seed = hashSeed(`${id}-${charIndex}-${pathIndex}`);\n const points = applyJitter(scaledPoints, jitterAmplitude, seed);\n\n // Calculate path timing based on pathTiming mode\n let pathStart, pathEnd;\n\n if (pathTiming === \"parallel\") {\n // All paths drawn simultaneously during character duration\n pathStart = charStart;\n pathEnd = charEnd;\n } else {\n // Sequential: each path gets a portion of character duration\n const pathDuration = charDuration / pathCount;\n pathStart = charStart + pathIndex * pathDuration;\n pathEnd = pathStart + pathDuration;\n }\n\n strokes.push({\n id: `${id}-${charIndex}-${pathIndex}`,\n points, // Offset coordinates from baseX/baseY (uniform space)\n baseX: x, // Base X position (width-normalized page coords)\n baseY: y, // Base Y position (height-normalized page coords)\n start: pathStart,\n end: pathEnd,\n color: resolveColor(style, \"rgba(220, 20, 60, 1.0)\"),\n width: style.width || 2,\n lineCap: style.lineCap || \"round\",\n uniformScale: true, // Preserve aspect ratio when rendering\n });\n }\n\n // Advance offset for next character (in glyph units)\n charOffsetX += charWidth + 0.18; // Add small spacing\n }\n\n return strokes;\n}\n\nexport default textToStrokes;\n"],"names":["seededRandom","seed","x","applyJitter","points","amplitude","y","i","scaleGlyphPoints","offsetX","scale","px","py","textToStrokes","annotation","style","id","start","end","content","annotFontSize","strokes","totalDuration","fontSize","roughness","fontScale","REFERENCE_HEIGHT","charOffsetX","charCount","charDuration","charIndex","char","glyph","resolveGlyph","charWidth","charPaths","pathTiming","charStart","charEnd","pathCount","pathIndex","rawPoints","scaledPoints","jitterAmplitude","hashSeed","pathStart","pathEnd","pathDuration","resolveColor"],"mappings":";;;;AAmBA,SAASA,EAAaC,GAAM;AAC1B,QAAMC,IAAI,KAAK,IAAID,CAAI,IAAI;AAC3B,UAAQC,IAAI,KAAK,MAAMA,CAAC,KAAK,IAAI;AACnC;AAMA,SAASC,EAAYC,GAAQC,GAAWJ,GAAM;AAC5C,SAAOG,EAAO,IAAI,CAAC,CAACF,GAAGI,CAAC,GAAGC,MAAM;AAAA,IAC/BL,IAAIF,EAAaC,IAAOM,IAAI,CAAC,IAAIF;AAAA,IACjCC,IAAIN,EAAaC,IAAOM,IAAI,IAAI,CAAC,IAAIF;AAAA,EACzC,CAAG;AACH;AAkBA,SAASG,EAAiBJ,GAAQK,GAASC,GAAO;AAEhD,SAAON,EAAO,IAAI,CAAC,CAACO,GAAIC,CAAE,MAAM,EAAEH,IAAUE,KAAMD,GAAOE,IAAKF,CAAK,CAAC;AACtE;AAsCO,SAASG,EAAcC,GAAYC,GAAO;AAC/C,QAAM,EAAE,IAAAC,GAAI,OAAAC,GAAO,KAAAC,GAAK,SAAAC,GAAS,GAAAjB,GAAG,GAAAI,GAAG,UAAUc,EAAa,IAAKN;AAEnE,MAAI,CAACK,KAAWA,EAAQ,WAAW;AACjC,WAAO,CAAA;AAGT,QAAME,IAAU,CAAA,GACVC,IAAgBJ,IAAMD,GACtBM,IAAWH,KAAiBL,EAAM,YAAY,IAE9CS,IAAYT,EAAM,aAAa,KAO/BU,IAAYF,IAAWG;AAG7B,MAAIC,IAAc;AAGlB,QAAMC,IAAYT,EAAQ,QACpBU,IAAeP,IAAgBM;AAErC,WAASE,IAAY,GAAGA,IAAYX,EAAQ,QAAQW,KAAa;AAC/D,UAAMC,IAAOZ,EAAQW,CAAS,GACxBE,IAAQC,EAAaF,CAAI;AAE/B,QAAI,CAACC,GAAO;AAEV,MAAAL,KAAe,MAAM;AACrB;AAAA,IACF;AAEA,UAAMO,IAAYF,EAAM,SAAS,KAC3BG,IAAYH,EAAM,SAAS,CAAA,GAC3BI,IAAaJ,EAAM,cAAc;AAGvC,QAAIG,EAAU,WAAW,GAAG;AAC1B,MAAAR,KAAeO,IAAY;AAC3B;AAAA,IACF;AAGA,UAAMG,IAAYpB,IAAQa,IAAYD,GAChCS,IAAUD,IAAYR,GAGtBU,IAAYJ,EAAU;AAE5B,aAASK,IAAY,GAAGA,IAAYL,EAAU,QAAQK,KAAa;AAEjE,YAAMC,IADWN,EAAUK,CAAS,EACT,UAAU,CAAA;AAErC,UAAIC,EAAU,SAAS,EAAG;AAG1B,YAAMC,IAAelC,EAAiBiC,GAAWd,GAAaF,CAAS,GAKjEkB,IAAkBnB,IAAY,MAC9BvB,IAAO2C,EAAS,GAAG5B,CAAE,IAAIc,CAAS,IAAIU,CAAS,EAAE,GACjDpC,IAASD,EAAYuC,GAAcC,GAAiB1C,CAAI;AAG9D,UAAI4C,GAAWC;AAEf,UAAIV,MAAe;AAEjB,QAAAS,IAAYR,GACZS,IAAUR;AAAA,WACL;AAEL,cAAMS,IAAelB,IAAeU;AACpC,QAAAM,IAAYR,IAAYG,IAAYO,GACpCD,IAAUD,IAAYE;AAAA,MACxB;AAEA,MAAA1B,EAAQ,KAAK;AAAA,QACX,IAAI,GAAGL,CAAE,IAAIc,CAAS,IAAIU,CAAS;AAAA,QACnC,QAAApC;AAAA;AAAA,QACA,OAAOF;AAAA;AAAA,QACP,OAAOI;AAAA;AAAA,QACP,OAAOuC;AAAA,QACP,KAAKC;AAAA,QACL,OAAOE,EAAajC,GAAO,wBAAwB;AAAA,QACnD,OAAOA,EAAM,SAAS;AAAA,QACtB,SAASA,EAAM,WAAW;AAAA,QAC1B,cAAc;AAAA;AAAA,MACtB,CAAO;AAAA,IACH;AAGA,IAAAY,KAAeO,IAAY;AAAA,EAC7B;AAEA,SAAOb;AACT;"}
package/dist/index16.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const r=require("./index29.cjs"),t=1e3;function E(W,n){const{id:i,start:h,end:_,from_x:c,from_y:u,to_x:o,to_y:e}=W;if(typeof c!="number"||typeof u!="number"||typeof o!="number"||typeof e!="number")return[];const d=[],L=_-h,P=L*.7,$=L*.3,m=n.roughness??.8,S=n.bowing??.8,b=n.curveFitting??.95,M=n.curveStepCount??9,w=n.maxRandomnessOffset??2,C=n.disableMultiStroke??!1,k=r.roughLine(c*t,u*t,o*t,e*t,{roughness:m,bowing:S,seed:r.hashSeed(`${i}-line`),curveFitting:b,curveStepCount:M,maxRandomnessOffset:w,disableMultiStroke:C}).map(([s,a])=>[s/t,a/t]);d.push({id:`${i}-0`,points:k,start:h,end:h+P,color:n.color||"rgba(255, 0, 0, 0.8)",width:n.width||2,lineCap:n.lineCap||"round"});const x=Math.sqrt((o-c)**2+(e-u)**2),g=Math.min(x*.2,.03),p=Math.atan2(e-u,o-c),f=Math.PI/6,D=o-g*Math.cos(p-f),R=e-g*Math.sin(p-f),O=o-g*Math.cos(p+f),T=e-g*Math.sin(p+f),q=r.roughLine(o*t,e*t,D*t,R*t,{roughness:m,bowing:S,seed:r.hashSeed(`${i}-left`),curveFitting:b,curveStepCount:M,maxRandomnessOffset:w,disableMultiStroke:C}).map(([s,a])=>[s/t,a/t]),A=r.roughLine(o*t,e*t,O*t,T*t,{roughness:m,bowing:S,seed:r.hashSeed(`${i}-right`),curveFitting:b,curveStepCount:M,maxRandomnessOffset:w,disableMultiStroke:C}).map(([s,a])=>[s/t,a/t]),l=h+P,v=$/2;return d.push({id:`${i}-1`,points:q,start:l,end:l+v,color:n.color||"rgba(255, 0, 0, 0.8)",width:n.width||2,lineCap:n.lineCap||"round"}),d.push({id:`${i}-2`,points:A,start:l,end:l+v,color:n.color||"rgba(255, 0, 0, 0.8)",width:n.width||2,lineCap:n.lineCap||"round"}),d}exports.arrowToStrokes=E;exports.default=E;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const w=require("./index28.cjs"),l=require("./index29.cjs"),o=1e3,D={roughness:1.4,bowing:1.5,curveFitting:.85,curveStepCount:9,maxRandomnessOffset:2,disableMultiStroke:!1};function h(g,e){const{id:r,start:s,end:S,quads:n}=g;if(!n||n.length===0)return[];const u=[],f=S-s,p=n.length,i=f/p;for(let t=0;t<n.length;t++){const q=n[t],{x:a,y:b,w:C,h:E}=q,d=b+E,v=w.roughLine(a*o,d*o,(a+C)*o,d*o,l.buildRoughOptions(e,`${r}-${t}`,D)).map(([k,m])=>[k/o,m/o]),c=s+t*i,_=c+i;u.push({id:`${r}-${t}`,points:v,start:c,end:_,color:l.resolveColor(e,"rgba(0, 0, 255, 0.8)"),width:e.width||2,lineCap:e.lineCap||"round"})}return u}exports.default=h;exports.underlineToStrokes=h;
2
2
  //# sourceMappingURL=index16.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index16.cjs","sources":["../src/converters/arrow.js"],"sourcesContent":["/**\n * Arrow Converter - Converts arrow annotations to stroke commands\n *\n * Transforms arrow data into a line stroke with arrowhead strokes\n * that can be rendered progressively on canvas with hand-drawn style.\n *\n * @module converters/arrow\n */\n\nimport { roughLine, hashSeed } from '../rough/roughPathExtractor.js';\n\nconst SCALE = 1000;\n\n/**\n * Converts an arrow annotation to stroke commands\n *\n * Creates a main line stroke from source to target, followed by\n * two wing strokes forming the arrowhead. Line draws first (70%),\n * then arrowhead (30%).\n *\n * @param {Object} annotation - Arrow annotation object\n * @param {string} annotation.id - Unique identifier\n * @param {number} annotation.start - Start time in seconds\n * @param {number} annotation.end - End time in seconds\n * @param {number} annotation.from_x - Source x position (0-1 normalized)\n * @param {number} annotation.from_y - Source y position (0-1 normalized)\n * @param {number} annotation.to_x - Target x position (0-1 normalized)\n * @param {number} annotation.to_y - Target y position (0-1 normalized)\n * @param {Object} [annotation.style] - Optional style overrides\n * @param {Object} style - Resolved style configuration\n * @param {string} style.color - Stroke color\n * @param {number} style.width - Stroke width in pixels\n * @param {string} [style.lineCap='round'] - Line cap style\n * @returns {Array<Object>} Array of stroke commands\n */\nexport function arrowToStrokes(annotation, style) {\n const { id, start, end, from_x, from_y, to_x, to_y } = annotation;\n\n if (typeof from_x !== 'number' || typeof from_y !== 'number' ||\n typeof to_x !== 'number' || typeof to_y !== 'number') {\n return [];\n }\n\n const strokes = [];\n const totalDuration = end - start;\n const lineDuration = totalDuration * 0.7;\n const headDuration = totalDuration * 0.3;\n\n const roughness = style.roughness ?? 0.8;\n const bowing = style.bowing ?? 0.8;\n const curveFitting = style.curveFitting ?? 0.95;\n const curveStepCount = style.curveStepCount ?? 9;\n const maxRandomnessOffset = style.maxRandomnessOffset ?? 2;\n const disableMultiStroke = style.disableMultiStroke ?? false;\n\n // Main line stroke with RoughJS style\n const roughLinePoints = roughLine(\n from_x * SCALE,\n from_y * SCALE,\n to_x * SCALE,\n to_y * SCALE,\n {\n roughness,\n bowing,\n seed: hashSeed(`${id}-line`),\n curveFitting,\n curveStepCount,\n maxRandomnessOffset,\n disableMultiStroke\n }\n );\n\n const linePoints = roughLinePoints.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n strokes.push({\n id: `${id}-0`,\n points: linePoints,\n start: start,\n end: start + lineDuration,\n color: style.color || 'rgba(255, 0, 0, 0.8)',\n width: style.width || 2,\n lineCap: style.lineCap || 'round'\n });\n\n // Arrow head calculation\n const lineLength = Math.sqrt((to_x - from_x) ** 2 + (to_y - from_y) ** 2);\n const headSize = Math.min(lineLength * 0.2, 0.03);\n const angle = Math.atan2(to_y - from_y, to_x - from_x);\n const headAngle = Math.PI / 6; // 30 degrees\n\n // Left wing end point\n const leftEndX = to_x - headSize * Math.cos(angle - headAngle);\n const leftEndY = to_y - headSize * Math.sin(angle - headAngle);\n\n // Right wing end point\n const rightEndX = to_x - headSize * Math.cos(angle + headAngle);\n const rightEndY = to_y - headSize * Math.sin(angle + headAngle);\n\n // Left wing with RoughJS style\n const roughLeftWing = roughLine(\n to_x * SCALE,\n to_y * SCALE,\n leftEndX * SCALE,\n leftEndY * SCALE,\n {\n roughness,\n bowing,\n seed: hashSeed(`${id}-left`),\n curveFitting,\n curveStepCount,\n maxRandomnessOffset,\n disableMultiStroke\n }\n );\n\n const leftWingPoints = roughLeftWing.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n // Right wing with RoughJS style\n const roughRightWing = roughLine(\n to_x * SCALE,\n to_y * SCALE,\n rightEndX * SCALE,\n rightEndY * SCALE,\n {\n roughness,\n bowing,\n seed: hashSeed(`${id}-right`),\n curveFitting,\n curveStepCount,\n maxRandomnessOffset,\n disableMultiStroke\n }\n );\n\n const rightWingPoints = roughRightWing.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n const headStart = start + lineDuration;\n const wingDuration = headDuration / 2;\n\n strokes.push({\n id: `${id}-1`,\n points: leftWingPoints,\n start: headStart,\n end: headStart + wingDuration,\n color: style.color || 'rgba(255, 0, 0, 0.8)',\n width: style.width || 2,\n lineCap: style.lineCap || 'round'\n });\n\n strokes.push({\n id: `${id}-2`,\n points: rightWingPoints,\n start: headStart,\n end: headStart + wingDuration,\n color: style.color || 'rgba(255, 0, 0, 0.8)',\n width: style.width || 2,\n lineCap: style.lineCap || 'round'\n });\n\n return strokes;\n}\n\nexport default arrowToStrokes;\n"],"names":["SCALE","arrowToStrokes","annotation","style","id","start","end","from_x","from_y","to_x","to_y","strokes","totalDuration","lineDuration","headDuration","roughness","bowing","curveFitting","curveStepCount","maxRandomnessOffset","disableMultiStroke","linePoints","roughLine","hashSeed","px","py","lineLength","headSize","angle","headAngle","leftEndX","leftEndY","rightEndX","rightEndY","leftWingPoints","rightWingPoints","headStart","wingDuration"],"mappings":"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"}
1
+ {"version":3,"file":"index16.cjs","sources":["../src/converters/underline.js"],"sourcesContent":["/**\n * Underline Converter - Converts underline annotations to stroke commands\n *\n * Transforms quads into horizontal stroke paths at the bottom edge\n * that can be rendered progressively on canvas with hand-drawn style.\n *\n * @module converters/underline\n */\n\nimport { roughLine } from '../rough/roughPathExtractor.js';\nimport { buildRoughOptions, resolveColor } from './_shared.js';\n\nconst SCALE = 1000;\n\n// Per-converter RoughJS defaults — must match DEFAULT_CONFIG.underline\n// in config/defaults.js. Used for any field not provided by the caller's\n// resolved `style`.\nconst UNDERLINE_ROUGH_DEFAULTS = {\n roughness: 1.4,\n bowing: 1.5,\n curveFitting: 0.85,\n curveStepCount: 9,\n maxRandomnessOffset: 2,\n disableMultiStroke: false,\n};\n\n/**\n * Converts an underline annotation to stroke commands\n *\n * Each quad in the annotation becomes a horizontal stroke at the\n * bottom edge of the quad. Multiple quads are staggered in timing.\n * Uses RoughJS for hand-drawn style.\n *\n * @param {Object} annotation - Underline annotation object\n * @param {string} annotation.id - Unique identifier\n * @param {number} annotation.start - Start time in seconds\n * @param {number} annotation.end - End time in seconds\n * @param {Array<{x: number, y: number, w: number, h: number}>} annotation.quads - Array of quads\n * @param {Object} [annotation.style] - Optional style overrides\n * @param {Object} style - Resolved style configuration\n * @param {string} style.color - Stroke color\n * @param {number} style.width - Stroke width in pixels\n * @param {string} [style.lineCap='round'] - Line cap style\n * @param {number} [style.roughness=1.0] - Hand-drawn roughness\n * @param {number} [style.bowing=1.0] - Line curvature\n * @returns {Array<Object>} Array of stroke commands\n */\nexport function underlineToStrokes(annotation, style) {\n const { id, start, end, quads } = annotation;\n\n if (!quads || quads.length === 0) {\n return [];\n }\n\n const strokes = [];\n const totalDuration = end - start;\n const quadCount = quads.length;\n const quadDuration = totalDuration / quadCount;\n\n for (let i = 0; i < quads.length; i++) {\n const quad = quads[i];\n const { x, y, w, h } = quad;\n\n const lineY = y + h;\n\n const roughPoints = roughLine(\n x * SCALE,\n lineY * SCALE,\n (x + w) * SCALE,\n lineY * SCALE,\n buildRoughOptions(style, `${id}-${i}`, UNDERLINE_ROUGH_DEFAULTS)\n );\n\n const points = roughPoints.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n const quadStart = start + i * quadDuration;\n const quadEnd = quadStart + quadDuration;\n\n strokes.push({\n id: `${id}-${i}`,\n points,\n start: quadStart,\n end: quadEnd,\n color: resolveColor(style, 'rgba(0, 0, 255, 0.8)'),\n width: style.width || 2,\n lineCap: style.lineCap || 'round'\n });\n }\n\n return strokes;\n}\n\nexport default underlineToStrokes;\n"],"names":["SCALE","UNDERLINE_ROUGH_DEFAULTS","underlineToStrokes","annotation","style","id","start","end","quads","strokes","totalDuration","quadCount","quadDuration","i","quad","x","y","w","h","lineY","points","roughLine","buildRoughOptions","px","py","quadStart","quadEnd","resolveColor"],"mappings":"wKAYMA,EAAQ,IAKRC,EAA2B,CAC/B,UAAW,IACX,OAAQ,IACR,aAAc,IACd,eAAgB,EAChB,oBAAqB,EACrB,mBAAoB,EACtB,EAuBO,SAASC,EAAmBC,EAAYC,EAAO,CACpD,KAAM,CAAE,GAAAC,EAAI,MAAAC,EAAO,IAAAC,EAAK,MAAAC,CAAK,EAAKL,EAElC,GAAI,CAACK,GAASA,EAAM,SAAW,EAC7B,MAAO,CAAA,EAGT,MAAMC,EAAU,CAAA,EACVC,EAAgBH,EAAMD,EACtBK,EAAYH,EAAM,OAClBI,EAAeF,EAAgBC,EAErC,QAASE,EAAI,EAAGA,EAAIL,EAAM,OAAQK,IAAK,CACrC,MAAMC,EAAON,EAAMK,CAAC,EACd,CAAE,EAAAE,EAAG,EAAAC,EAAG,EAAAC,EAAG,EAAAC,CAAC,EAAKJ,EAEjBK,EAAQH,EAAIE,EAUZE,EARcC,EAAAA,UAClBN,EAAIf,EACJmB,EAAQnB,GACPe,EAAIE,GAAKjB,EACVmB,EAAQnB,EACRsB,EAAAA,kBAAkBlB,EAAO,GAAGC,CAAE,IAAIQ,CAAC,GAAIZ,CAAwB,CACrE,EAE+B,IAAI,CAAC,CAACsB,EAAIC,CAAE,IAAM,CAACD,EAAKvB,EAAOwB,EAAKxB,CAAK,CAAC,EAE/DyB,EAAYnB,EAAQO,EAAID,EACxBc,EAAUD,EAAYb,EAE5BH,EAAQ,KAAK,CACX,GAAI,GAAGJ,CAAE,IAAIQ,CAAC,GACd,OAAAO,EACA,MAAOK,EACP,IAAKC,EACL,MAAOC,EAAAA,aAAavB,EAAO,sBAAsB,EACjD,MAAOA,EAAM,OAAS,EACtB,QAASA,EAAM,SAAW,OAChC,CAAK,CACH,CAEA,OAAOK,CACT"}
package/dist/index16.js CHANGED
@@ -1,82 +1,40 @@
1
- import { roughLine as S, hashSeed as L } from "./index29.js";
2
- const n = 1e3;
3
- function T(x, t) {
4
- const { id: r, start: a, end: E, from_x: c, from_y: h, to_x: o, to_y: i } = x;
5
- if (typeof c != "number" || typeof h != "number" || typeof o != "number" || typeof i != "number")
1
+ import { roughLine as D } from "./index28.js";
2
+ import { buildRoughOptions as L, resolveColor as R } from "./index29.js";
3
+ const o = 1e3, $ = {
4
+ roughness: 1.4,
5
+ bowing: 1.5,
6
+ curveFitting: 0.85,
7
+ curveStepCount: 9,
8
+ maxRandomnessOffset: 2,
9
+ disableMultiStroke: !1
10
+ };
11
+ function O(l, s) {
12
+ const { id: r, start: e, end: h, quads: n } = l;
13
+ if (!n || n.length === 0)
6
14
  return [];
7
- const u = [], P = E - a, W = P * 0.7, k = P * 0.3, m = t.roughness ?? 0.8, l = t.bowing ?? 0.8, b = t.curveFitting ?? 0.95, w = t.curveStepCount ?? 9, M = t.maxRandomnessOffset ?? 2, C = t.disableMultiStroke ?? !1, v = S(
8
- c * n,
9
- h * n,
10
- o * n,
11
- i * n,
12
- {
13
- roughness: m,
14
- bowing: l,
15
- seed: L(`${r}-line`),
16
- curveFitting: b,
17
- curveStepCount: w,
18
- maxRandomnessOffset: M,
19
- disableMultiStroke: C
20
- }
21
- ).map(([e, s]) => [e / n, s / n]);
22
- u.push({
23
- id: `${r}-0`,
24
- points: v,
25
- start: a,
26
- end: a + W,
27
- color: t.color || "rgba(255, 0, 0, 0.8)",
28
- width: t.width || 2,
29
- lineCap: t.lineCap || "round"
30
- });
31
- const D = Math.sqrt((o - c) ** 2 + (i - h) ** 2), d = Math.min(D * 0.2, 0.03), g = Math.atan2(i - h, o - c), p = Math.PI / 6, R = o - d * Math.cos(g - p), _ = i - d * Math.sin(g - p), A = o - d * Math.cos(g + p), F = i - d * Math.sin(g + p), O = S(
32
- o * n,
33
- i * n,
34
- R * n,
35
- _ * n,
36
- {
37
- roughness: m,
38
- bowing: l,
39
- seed: L(`${r}-left`),
40
- curveFitting: b,
41
- curveStepCount: w,
42
- maxRandomnessOffset: M,
43
- disableMultiStroke: C
44
- }
45
- ).map(([e, s]) => [e / n, s / n]), X = S(
46
- o * n,
47
- i * n,
48
- A * n,
49
- F * n,
50
- {
51
- roughness: m,
52
- bowing: l,
53
- seed: L(`${r}-right`),
54
- curveFitting: b,
55
- curveStepCount: w,
56
- maxRandomnessOffset: M,
57
- disableMultiStroke: C
58
- }
59
- ).map(([e, s]) => [e / n, s / n]), f = a + W, $ = k / 2;
60
- return u.push({
61
- id: `${r}-1`,
62
- points: O,
63
- start: f,
64
- end: f + $,
65
- color: t.color || "rgba(255, 0, 0, 0.8)",
66
- width: t.width || 2,
67
- lineCap: t.lineCap || "round"
68
- }), u.push({
69
- id: `${r}-2`,
70
- points: X,
71
- start: f,
72
- end: f + $,
73
- color: t.color || "rgba(255, 0, 0, 0.8)",
74
- width: t.width || 2,
75
- lineCap: t.lineCap || "round"
76
- }), u;
15
+ const i = [], g = h - e, p = n.length, u = g / p;
16
+ for (let t = 0; t < n.length; t++) {
17
+ const f = n[t], { x: a, y: m, w: q, h: C } = f, d = m + C, S = D(
18
+ a * o,
19
+ d * o,
20
+ (a + q) * o,
21
+ d * o,
22
+ L(s, `${r}-${t}`, $)
23
+ ).map(([b, w]) => [b / o, w / o]), c = e + t * u, E = c + u;
24
+ i.push({
25
+ id: `${r}-${t}`,
26
+ points: S,
27
+ start: c,
28
+ end: E,
29
+ color: R(s, "rgba(0, 0, 255, 0.8)"),
30
+ width: s.width || 2,
31
+ lineCap: s.lineCap || "round"
32
+ });
33
+ }
34
+ return i;
77
35
  }
78
36
  export {
79
- T as arrowToStrokes,
80
- T as default
37
+ O as default,
38
+ O as underlineToStrokes
81
39
  };
82
40
  //# sourceMappingURL=index16.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index16.js","sources":["../src/converters/arrow.js"],"sourcesContent":["/**\n * Arrow Converter - Converts arrow annotations to stroke commands\n *\n * Transforms arrow data into a line stroke with arrowhead strokes\n * that can be rendered progressively on canvas with hand-drawn style.\n *\n * @module converters/arrow\n */\n\nimport { roughLine, hashSeed } from '../rough/roughPathExtractor.js';\n\nconst SCALE = 1000;\n\n/**\n * Converts an arrow annotation to stroke commands\n *\n * Creates a main line stroke from source to target, followed by\n * two wing strokes forming the arrowhead. Line draws first (70%),\n * then arrowhead (30%).\n *\n * @param {Object} annotation - Arrow annotation object\n * @param {string} annotation.id - Unique identifier\n * @param {number} annotation.start - Start time in seconds\n * @param {number} annotation.end - End time in seconds\n * @param {number} annotation.from_x - Source x position (0-1 normalized)\n * @param {number} annotation.from_y - Source y position (0-1 normalized)\n * @param {number} annotation.to_x - Target x position (0-1 normalized)\n * @param {number} annotation.to_y - Target y position (0-1 normalized)\n * @param {Object} [annotation.style] - Optional style overrides\n * @param {Object} style - Resolved style configuration\n * @param {string} style.color - Stroke color\n * @param {number} style.width - Stroke width in pixels\n * @param {string} [style.lineCap='round'] - Line cap style\n * @returns {Array<Object>} Array of stroke commands\n */\nexport function arrowToStrokes(annotation, style) {\n const { id, start, end, from_x, from_y, to_x, to_y } = annotation;\n\n if (typeof from_x !== 'number' || typeof from_y !== 'number' ||\n typeof to_x !== 'number' || typeof to_y !== 'number') {\n return [];\n }\n\n const strokes = [];\n const totalDuration = end - start;\n const lineDuration = totalDuration * 0.7;\n const headDuration = totalDuration * 0.3;\n\n const roughness = style.roughness ?? 0.8;\n const bowing = style.bowing ?? 0.8;\n const curveFitting = style.curveFitting ?? 0.95;\n const curveStepCount = style.curveStepCount ?? 9;\n const maxRandomnessOffset = style.maxRandomnessOffset ?? 2;\n const disableMultiStroke = style.disableMultiStroke ?? false;\n\n // Main line stroke with RoughJS style\n const roughLinePoints = roughLine(\n from_x * SCALE,\n from_y * SCALE,\n to_x * SCALE,\n to_y * SCALE,\n {\n roughness,\n bowing,\n seed: hashSeed(`${id}-line`),\n curveFitting,\n curveStepCount,\n maxRandomnessOffset,\n disableMultiStroke\n }\n );\n\n const linePoints = roughLinePoints.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n strokes.push({\n id: `${id}-0`,\n points: linePoints,\n start: start,\n end: start + lineDuration,\n color: style.color || 'rgba(255, 0, 0, 0.8)',\n width: style.width || 2,\n lineCap: style.lineCap || 'round'\n });\n\n // Arrow head calculation\n const lineLength = Math.sqrt((to_x - from_x) ** 2 + (to_y - from_y) ** 2);\n const headSize = Math.min(lineLength * 0.2, 0.03);\n const angle = Math.atan2(to_y - from_y, to_x - from_x);\n const headAngle = Math.PI / 6; // 30 degrees\n\n // Left wing end point\n const leftEndX = to_x - headSize * Math.cos(angle - headAngle);\n const leftEndY = to_y - headSize * Math.sin(angle - headAngle);\n\n // Right wing end point\n const rightEndX = to_x - headSize * Math.cos(angle + headAngle);\n const rightEndY = to_y - headSize * Math.sin(angle + headAngle);\n\n // Left wing with RoughJS style\n const roughLeftWing = roughLine(\n to_x * SCALE,\n to_y * SCALE,\n leftEndX * SCALE,\n leftEndY * SCALE,\n {\n roughness,\n bowing,\n seed: hashSeed(`${id}-left`),\n curveFitting,\n curveStepCount,\n maxRandomnessOffset,\n disableMultiStroke\n }\n );\n\n const leftWingPoints = roughLeftWing.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n // Right wing with RoughJS style\n const roughRightWing = roughLine(\n to_x * SCALE,\n to_y * SCALE,\n rightEndX * SCALE,\n rightEndY * SCALE,\n {\n roughness,\n bowing,\n seed: hashSeed(`${id}-right`),\n curveFitting,\n curveStepCount,\n maxRandomnessOffset,\n disableMultiStroke\n }\n );\n\n const rightWingPoints = roughRightWing.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n const headStart = start + lineDuration;\n const wingDuration = headDuration / 2;\n\n strokes.push({\n id: `${id}-1`,\n points: leftWingPoints,\n start: headStart,\n end: headStart + wingDuration,\n color: style.color || 'rgba(255, 0, 0, 0.8)',\n width: style.width || 2,\n lineCap: style.lineCap || 'round'\n });\n\n strokes.push({\n id: `${id}-2`,\n points: rightWingPoints,\n start: headStart,\n end: headStart + wingDuration,\n color: style.color || 'rgba(255, 0, 0, 0.8)',\n width: style.width || 2,\n lineCap: style.lineCap || 'round'\n });\n\n return strokes;\n}\n\nexport default arrowToStrokes;\n"],"names":["SCALE","arrowToStrokes","annotation","style","id","start","end","from_x","from_y","to_x","to_y","strokes","totalDuration","lineDuration","headDuration","roughness","bowing","curveFitting","curveStepCount","maxRandomnessOffset","disableMultiStroke","linePoints","roughLine","hashSeed","px","py","lineLength","headSize","angle","headAngle","leftEndX","leftEndY","rightEndX","rightEndY","leftWingPoints","rightWingPoints","headStart","wingDuration"],"mappings":"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"}
1
+ {"version":3,"file":"index16.js","sources":["../src/converters/underline.js"],"sourcesContent":["/**\n * Underline Converter - Converts underline annotations to stroke commands\n *\n * Transforms quads into horizontal stroke paths at the bottom edge\n * that can be rendered progressively on canvas with hand-drawn style.\n *\n * @module converters/underline\n */\n\nimport { roughLine } from '../rough/roughPathExtractor.js';\nimport { buildRoughOptions, resolveColor } from './_shared.js';\n\nconst SCALE = 1000;\n\n// Per-converter RoughJS defaults — must match DEFAULT_CONFIG.underline\n// in config/defaults.js. Used for any field not provided by the caller's\n// resolved `style`.\nconst UNDERLINE_ROUGH_DEFAULTS = {\n roughness: 1.4,\n bowing: 1.5,\n curveFitting: 0.85,\n curveStepCount: 9,\n maxRandomnessOffset: 2,\n disableMultiStroke: false,\n};\n\n/**\n * Converts an underline annotation to stroke commands\n *\n * Each quad in the annotation becomes a horizontal stroke at the\n * bottom edge of the quad. Multiple quads are staggered in timing.\n * Uses RoughJS for hand-drawn style.\n *\n * @param {Object} annotation - Underline annotation object\n * @param {string} annotation.id - Unique identifier\n * @param {number} annotation.start - Start time in seconds\n * @param {number} annotation.end - End time in seconds\n * @param {Array<{x: number, y: number, w: number, h: number}>} annotation.quads - Array of quads\n * @param {Object} [annotation.style] - Optional style overrides\n * @param {Object} style - Resolved style configuration\n * @param {string} style.color - Stroke color\n * @param {number} style.width - Stroke width in pixels\n * @param {string} [style.lineCap='round'] - Line cap style\n * @param {number} [style.roughness=1.0] - Hand-drawn roughness\n * @param {number} [style.bowing=1.0] - Line curvature\n * @returns {Array<Object>} Array of stroke commands\n */\nexport function underlineToStrokes(annotation, style) {\n const { id, start, end, quads } = annotation;\n\n if (!quads || quads.length === 0) {\n return [];\n }\n\n const strokes = [];\n const totalDuration = end - start;\n const quadCount = quads.length;\n const quadDuration = totalDuration / quadCount;\n\n for (let i = 0; i < quads.length; i++) {\n const quad = quads[i];\n const { x, y, w, h } = quad;\n\n const lineY = y + h;\n\n const roughPoints = roughLine(\n x * SCALE,\n lineY * SCALE,\n (x + w) * SCALE,\n lineY * SCALE,\n buildRoughOptions(style, `${id}-${i}`, UNDERLINE_ROUGH_DEFAULTS)\n );\n\n const points = roughPoints.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n const quadStart = start + i * quadDuration;\n const quadEnd = quadStart + quadDuration;\n\n strokes.push({\n id: `${id}-${i}`,\n points,\n start: quadStart,\n end: quadEnd,\n color: resolveColor(style, 'rgba(0, 0, 255, 0.8)'),\n width: style.width || 2,\n lineCap: style.lineCap || 'round'\n });\n }\n\n return strokes;\n}\n\nexport default underlineToStrokes;\n"],"names":["SCALE","UNDERLINE_ROUGH_DEFAULTS","underlineToStrokes","annotation","style","id","start","end","quads","strokes","totalDuration","quadCount","quadDuration","i","quad","x","y","w","h","lineY","points","roughLine","buildRoughOptions","px","py","quadStart","quadEnd","resolveColor"],"mappings":";;AAYA,MAAMA,IAAQ,KAKRC,IAA2B;AAAA,EAC/B,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,qBAAqB;AAAA,EACrB,oBAAoB;AACtB;AAuBO,SAASC,EAAmBC,GAAYC,GAAO;AACpD,QAAM,EAAE,IAAAC,GAAI,OAAAC,GAAO,KAAAC,GAAK,OAAAC,EAAK,IAAKL;AAElC,MAAI,CAACK,KAASA,EAAM,WAAW;AAC7B,WAAO,CAAA;AAGT,QAAMC,IAAU,CAAA,GACVC,IAAgBH,IAAMD,GACtBK,IAAYH,EAAM,QAClBI,IAAeF,IAAgBC;AAErC,WAASE,IAAI,GAAGA,IAAIL,EAAM,QAAQK,KAAK;AACrC,UAAMC,IAAON,EAAMK,CAAC,GACd,EAAE,GAAAE,GAAG,GAAAC,GAAG,GAAAC,GAAG,GAAAC,EAAC,IAAKJ,GAEjBK,IAAQH,IAAIE,GAUZE,IARcC;AAAA,MAClBN,IAAIf;AAAA,MACJmB,IAAQnB;AAAA,OACPe,IAAIE,KAAKjB;AAAA,MACVmB,IAAQnB;AAAA,MACRsB,EAAkBlB,GAAO,GAAGC,CAAE,IAAIQ,CAAC,IAAIZ,CAAwB;AAAA,IACrE,EAE+B,IAAI,CAAC,CAACsB,GAAIC,CAAE,MAAM,CAACD,IAAKvB,GAAOwB,IAAKxB,CAAK,CAAC,GAE/DyB,IAAYnB,IAAQO,IAAID,GACxBc,IAAUD,IAAYb;AAE5B,IAAAH,EAAQ,KAAK;AAAA,MACX,IAAI,GAAGJ,CAAE,IAAIQ,CAAC;AAAA,MACd,QAAAO;AAAA,MACA,OAAOK;AAAA,MACP,KAAKC;AAAA,MACL,OAAOC,EAAavB,GAAO,sBAAsB;AAAA,MACjD,OAAOA,EAAM,SAAS;AAAA,MACtB,SAASA,EAAM,WAAW;AAAA,IAChC,CAAK;AAAA,EACH;AAEA,SAAOK;AACT;"}
package/dist/index17.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const i=require("./index29.cjs"),e=1e3;function c(a,o){const{id:t,start:d,end:f,cx:n,cy:r,rx:u,ry:s}=a;if(typeof n!="number"||typeof r!="number"||typeof u!="number"||typeof s!="number")return[];const g=o.roughness??1,p=o.bowing??1,b=o.curveFitting??.95,h=o.curveStepCount??9,l=o.maxRandomnessOffset??2,m=o.disableMultiStroke??!1,S=i.roughEllipse(n*e,r*e,u*2*e,s*2*e,{roughness:g,bowing:p,seed:i.hashSeed(t),curveFitting:b,curveStepCount:h,maxRandomnessOffset:l,disableMultiStroke:m}).map(([v,x])=>[v/e,x/e]);return[{id:t,points:S,start:d,end:f,color:o.color||"rgba(255, 165, 0, 0.8)",width:o.width||3,lineCap:o.lineCap||"round"}]}exports.circleToStrokes=c;exports.default=c;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const P=require("./index28.cjs"),h=require("./index29.cjs"),r=1e3;function p(f,o){const{id:n,start:t,end:m,from_x:e,from_y:i,to_x:a,to_y:u}=f;if(typeof e!="number"||typeof i!="number"||typeof a!="number"||typeof u!="number")return[];const s=[],c=m-t,g=c*.7,w=c*.3,b=P.roughLine(e*r,i*r,a*r,u*r,h.buildRoughOptions(o,`${n}-line`,{roughness:.8,bowing:.8})).map(([C,S])=>[C/r,S/r]);s.push({id:`${n}-0`,points:b,start:t,end:t+g,color:h.resolveColor(o,"rgba(255, 0, 0, 0.8)"),width:o.width||2,lineCap:o.lineCap||"round"});const d=t+g,l=w/2;return s.push({id:`${n}-1`,start:d,end:d+l,color:h.resolveColor(o,"rgba(255, 0, 0, 0.8)"),width:o.width||2,lineCap:o.lineCap||"round",screenSpaceWing:{fromX:e,fromY:i,toX:a,toY:u,headAngle:Math.PI/6,wingSide:"left"}}),s.push({id:`${n}-2`,start:d,end:d+l,color:h.resolveColor(o,"rgba(255, 0, 0, 0.8)"),width:o.width||2,lineCap:o.lineCap||"round",screenSpaceWing:{fromX:e,fromY:i,toX:a,toY:u,headAngle:Math.PI/6,wingSide:"right"}}),s}exports.arrowToStrokes=p;exports.default=p;
2
2
  //# sourceMappingURL=index17.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index17.cjs","sources":["../src/converters/circle.js"],"sourcesContent":["/**\n * Circle Converter - Converts circle annotations to stroke commands\n *\n * Transforms circle/ellipse data into stroke paths that can be\n * rendered progressively on canvas with hand-drawn style.\n *\n * @module converters/circle\n */\n\nimport { roughEllipse, hashSeed } from '../rough/roughPathExtractor.js';\n\nconst SCALE = 1000;\n\n/**\n * Converts a circle annotation to stroke commands\n *\n * Generates an ellipse path that renders progressively around the perimeter.\n * Uses RoughJS for hand-drawn circle style.\n *\n * @param {Object} annotation - Circle annotation object\n * @param {string} annotation.id - Unique identifier\n * @param {number} annotation.start - Start time in seconds\n * @param {number} annotation.end - End time in seconds\n * @param {number} annotation.cx - Center x position (0-1 normalized)\n * @param {number} annotation.cy - Center y position (0-1 normalized)\n * @param {number} annotation.rx - Horizontal radius (0-1 normalized)\n * @param {number} annotation.ry - Vertical radius (0-1 normalized)\n * @param {Object} [annotation.style] - Optional style overrides\n * @param {Object} style - Resolved style configuration\n * @param {string} style.color - Stroke color\n * @param {number} style.width - Stroke width in pixels\n * @param {string} [style.lineCap='round'] - Line cap style\n * @param {number} [style.roughness=1.0] - Hand-drawn roughness\n * @param {number} [style.bowing=1.0] - Line curvature\n * @returns {Array<Object>} Array of stroke commands\n */\nexport function circleToStrokes(annotation, style) {\n const { id, start, end, cx, cy, rx, ry } = annotation;\n\n if (typeof cx !== 'number' || typeof cy !== 'number' ||\n typeof rx !== 'number' || typeof ry !== 'number') {\n return [];\n }\n\n const roughness = style.roughness ?? 1.0;\n const bowing = style.bowing ?? 1.0;\n const curveFitting = style.curveFitting ?? 0.95;\n const curveStepCount = style.curveStepCount ?? 9;\n const maxRandomnessOffset = style.maxRandomnessOffset ?? 2;\n const disableMultiStroke = style.disableMultiStroke ?? false;\n\n const roughPoints = roughEllipse(\n cx * SCALE,\n cy * SCALE,\n rx * 2 * SCALE,\n ry * 2 * SCALE,\n {\n roughness,\n bowing,\n seed: hashSeed(id),\n curveFitting,\n curveStepCount,\n maxRandomnessOffset,\n disableMultiStroke\n }\n );\n\n const points = roughPoints.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n return [{\n id,\n points,\n start,\n end,\n color: style.color || 'rgba(255, 165, 0, 0.8)',\n width: style.width || 3,\n lineCap: style.lineCap || 'round'\n }];\n}\n\nexport default circleToStrokes;\n"],"names":["SCALE","circleToStrokes","annotation","style","id","start","end","cx","cy","rx","ry","roughness","bowing","curveFitting","curveStepCount","maxRandomnessOffset","disableMultiStroke","points","roughEllipse","hashSeed","px","py"],"mappings":"6IAWMA,EAAQ,IAyBP,SAASC,EAAgBC,EAAYC,EAAO,CACjD,KAAM,CAAE,GAAAC,EAAI,MAAAC,EAAO,IAAAC,EAAK,GAAAC,EAAI,GAAAC,EAAI,GAAAC,EAAI,GAAAC,CAAE,EAAKR,EAE3C,GAAI,OAAOK,GAAO,UAAY,OAAOC,GAAO,UACxC,OAAOC,GAAO,UAAY,OAAOC,GAAO,SAC1C,MAAO,CAAA,EAGT,MAAMC,EAAYR,EAAM,WAAa,EAC/BS,EAAST,EAAM,QAAU,EACzBU,EAAeV,EAAM,cAAgB,IACrCW,EAAiBX,EAAM,gBAAkB,EACzCY,EAAsBZ,EAAM,qBAAuB,EACnDa,EAAqBb,EAAM,oBAAsB,GAkBjDc,EAhBcC,EAAAA,aAClBX,EAAKP,EACLQ,EAAKR,EACLS,EAAK,EAAIT,EACTU,EAAK,EAAIV,EACT,CACE,UAAAW,EACA,OAAAC,EACA,KAAMO,EAAAA,SAASf,CAAE,EACjB,aAAAS,EACA,eAAAC,EACA,oBAAAC,EACA,mBAAAC,CACN,CACA,EAE6B,IAAI,CAAC,CAACI,EAAIC,CAAE,IAAM,CAACD,EAAKpB,EAAOqB,EAAKrB,CAAK,CAAC,EAErE,MAAO,CAAC,CACN,GAAAI,EACA,OAAAa,EACA,MAAAZ,EACA,IAAAC,EACA,MAAOH,EAAM,OAAS,yBACtB,MAAOA,EAAM,OAAS,EACtB,QAASA,EAAM,SAAW,OAC9B,CAAG,CACH"}
1
+ {"version":3,"file":"index17.cjs","sources":["../src/converters/arrow.js"],"sourcesContent":["/**\n * Arrow Converter - Converts arrow annotations to stroke commands\n *\n * Transforms arrow data into a line stroke with arrowhead strokes\n * that can be rendered progressively on canvas with hand-drawn style.\n *\n * @module converters/arrow\n */\n\nimport { roughLine } from '../rough/roughPathExtractor.js';\nimport { buildRoughOptions, resolveColor } from './_shared.js';\n\nconst SCALE = 1000;\n\n/**\n * Converts an arrow annotation to stroke commands\n *\n * Creates a main line stroke from source to target, followed by\n * two wing strokes forming the arrowhead. Line draws first (70%),\n * then arrowhead (30%).\n *\n * The wings emit `screenSpaceWing` stroke shapes; their geometry is\n * recomputed by the renderer every frame in screen-pixel space so\n * diagonal arrows render with symmetric wings regardless of viewport\n * aspect ratio. The wing strokes carry no `points` array.\n *\n * @param {Object} annotation - Arrow annotation object\n * @param {string} annotation.id - Unique identifier\n * @param {number} annotation.start - Start time in seconds\n * @param {number} annotation.end - End time in seconds\n * @param {number} annotation.from_x - Source x position (0-1 normalized)\n * @param {number} annotation.from_y - Source y position (0-1 normalized)\n * @param {number} annotation.to_x - Target x position (0-1 normalized)\n * @param {number} annotation.to_y - Target y position (0-1 normalized)\n * @param {Object} [annotation.style] - Optional style overrides\n * @param {Object} style - Resolved style configuration\n * @param {string} [style.color] - Stroke color\n * @param {number} [style.width=2] - Stroke width in pixels\n * @param {string} [style.lineCap='round'] - Line cap style\n * @returns {Array<Object>} Array of stroke commands\n */\nexport function arrowToStrokes(annotation, style) {\n const { id, start, end, from_x, from_y, to_x, to_y } = annotation;\n\n if (typeof from_x !== 'number' || typeof from_y !== 'number' ||\n typeof to_x !== 'number' || typeof to_y !== 'number') {\n return [];\n }\n\n const strokes = [];\n const totalDuration = end - start;\n const lineDuration = totalDuration * 0.7;\n const headDuration = totalDuration * 0.3;\n\n // Main line stroke with RoughJS style\n const roughLinePoints = roughLine(\n from_x * SCALE,\n from_y * SCALE,\n to_x * SCALE,\n to_y * SCALE,\n buildRoughOptions(style, `${id}-line`, { roughness: 0.8, bowing: 0.8 })\n );\n\n const linePoints = roughLinePoints.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n strokes.push({\n id: `${id}-0`,\n points: linePoints,\n start: start,\n end: start + lineDuration,\n color: resolveColor(style, 'rgba(255, 0, 0, 0.8)'),\n width: style.width || 2,\n lineCap: style.lineCap || 'round'\n });\n\n // Arrowhead wings — geometry resolved each frame in screen-pixel space by\n // the renderer (`_drawScreenSpaceWingStroke`). No `points` array here.\n const headStart = start + lineDuration;\n const wingDuration = headDuration / 2;\n\n strokes.push({\n id: `${id}-1`,\n start: headStart,\n end: headStart + wingDuration,\n color: resolveColor(style, 'rgba(255, 0, 0, 0.8)'),\n width: style.width || 2,\n lineCap: style.lineCap || 'round',\n screenSpaceWing: {\n fromX: from_x,\n fromY: from_y,\n toX: to_x,\n toY: to_y,\n headAngle: Math.PI / 6,\n wingSide: 'left',\n },\n });\n\n strokes.push({\n id: `${id}-2`,\n start: headStart,\n end: headStart + wingDuration,\n color: resolveColor(style, 'rgba(255, 0, 0, 0.8)'),\n width: style.width || 2,\n lineCap: style.lineCap || 'round',\n screenSpaceWing: {\n fromX: from_x,\n fromY: from_y,\n toX: to_x,\n toY: to_y,\n headAngle: Math.PI / 6,\n wingSide: 'right',\n },\n });\n\n return strokes;\n}\n\nexport default arrowToStrokes;\n"],"names":["SCALE","arrowToStrokes","annotation","style","id","start","end","from_x","from_y","to_x","to_y","strokes","totalDuration","lineDuration","headDuration","linePoints","roughLine","buildRoughOptions","px","py","resolveColor","headStart","wingDuration"],"mappings":"wKAYMA,EAAQ,IA6BP,SAASC,EAAeC,EAAYC,EAAO,CAChD,KAAM,CAAE,GAAAC,EAAI,MAAAC,EAAO,IAAAC,EAAK,OAAAC,EAAQ,OAAAC,EAAQ,KAAAC,EAAM,KAAAC,CAAI,EAAKR,EAEvD,GAAI,OAAOK,GAAW,UAAY,OAAOC,GAAW,UAChD,OAAOC,GAAS,UAAY,OAAOC,GAAS,SAC9C,MAAO,CAAA,EAGT,MAAMC,EAAU,CAAA,EACVC,EAAgBN,EAAMD,EACtBQ,EAAeD,EAAgB,GAC/BE,EAAeF,EAAgB,GAW/BG,EARkBC,EAAAA,UACtBT,EAASP,EACTQ,EAASR,EACTS,EAAOT,EACPU,EAAOV,EACPiB,oBAAkBd,EAAO,GAAGC,CAAE,QAAS,CAAE,UAAW,GAAK,OAAQ,EAAG,CAAE,CAC1E,EAEqC,IAAI,CAAC,CAACc,EAAIC,CAAE,IAAM,CAACD,EAAKlB,EAAOmB,EAAKnB,CAAK,CAAC,EAE7EW,EAAQ,KAAK,CACX,GAAI,GAAGP,CAAE,KACT,OAAQW,EACR,MAAOV,EACP,IAAKA,EAAQQ,EACb,MAAOO,EAAAA,aAAajB,EAAO,sBAAsB,EACjD,MAAOA,EAAM,OAAS,EACtB,QAASA,EAAM,SAAW,OAC9B,CAAG,EAID,MAAMkB,EAAYhB,EAAQQ,EACpBS,EAAeR,EAAe,EAEpC,OAAAH,EAAQ,KAAK,CACX,GAAI,GAAGP,CAAE,KACT,MAAOiB,EACP,IAAKA,EAAYC,EACjB,MAAOF,EAAAA,aAAajB,EAAO,sBAAsB,EACjD,MAAOA,EAAM,OAAS,EACtB,QAASA,EAAM,SAAW,QAC1B,gBAAiB,CACf,MAAOI,EACP,MAAOC,EACP,IAAKC,EACL,IAAKC,EACL,UAAW,KAAK,GAAK,EACrB,SAAU,MAChB,CACA,CAAG,EAEDC,EAAQ,KAAK,CACX,GAAI,GAAGP,CAAE,KACT,MAAOiB,EACP,IAAKA,EAAYC,EACjB,MAAOF,EAAAA,aAAajB,EAAO,sBAAsB,EACjD,MAAOA,EAAM,OAAS,EACtB,QAASA,EAAM,SAAW,QAC1B,gBAAiB,CACf,MAAOI,EACP,MAAOC,EACP,IAAKC,EACL,IAAKC,EACL,UAAW,KAAK,GAAK,EACrB,SAAU,OAChB,CACA,CAAG,EAEMC,CACT"}
package/dist/index17.js CHANGED
@@ -1,36 +1,61 @@
1
- import { roughEllipse as x, hashSeed as C } from "./index29.js";
1
+ import { roughLine as S } from "./index28.js";
2
+ import { buildRoughOptions as P, resolveColor as h } from "./index29.js";
2
3
  const n = 1e3;
3
- function k(u, o) {
4
- const { id: t, start: c, end: a, cx: e, cy: r, rx: s, ry: i } = u;
5
- if (typeof e != "number" || typeof r != "number" || typeof s != "number" || typeof i != "number")
4
+ function Y(f, o) {
5
+ const { id: t, start: r, end: m, from_x: i, from_y: e, to_x: a, to_y: d } = f;
6
+ if (typeof i != "number" || typeof e != "number" || typeof a != "number" || typeof d != "number")
6
7
  return [];
7
- const f = o.roughness ?? 1, p = o.bowing ?? 1, d = o.curveFitting ?? 0.95, m = o.curveStepCount ?? 9, g = o.maxRandomnessOffset ?? 2, b = o.disableMultiStroke ?? !1, h = x(
8
+ const u = [], p = m - r, c = p * 0.7, l = p * 0.3, w = S(
9
+ i * n,
8
10
  e * n,
9
- r * n,
10
- s * 2 * n,
11
- i * 2 * n,
12
- {
13
- roughness: f,
14
- bowing: p,
15
- seed: C(t),
16
- curveFitting: d,
17
- curveStepCount: m,
18
- maxRandomnessOffset: g,
19
- disableMultiStroke: b
20
- }
21
- ).map(([S, l]) => [S / n, l / n]);
22
- return [{
23
- id: t,
24
- points: h,
25
- start: c,
26
- end: a,
27
- color: o.color || "rgba(255, 165, 0, 0.8)",
28
- width: o.width || 3,
11
+ a * n,
12
+ d * n,
13
+ P(o, `${t}-line`, { roughness: 0.8, bowing: 0.8 })
14
+ ).map(([b, C]) => [b / n, C / n]);
15
+ u.push({
16
+ id: `${t}-0`,
17
+ points: w,
18
+ start: r,
19
+ end: r + c,
20
+ color: h(o, "rgba(255, 0, 0, 0.8)"),
21
+ width: o.width || 2,
29
22
  lineCap: o.lineCap || "round"
30
- }];
23
+ });
24
+ const s = r + c, g = l / 2;
25
+ return u.push({
26
+ id: `${t}-1`,
27
+ start: s,
28
+ end: s + g,
29
+ color: h(o, "rgba(255, 0, 0, 0.8)"),
30
+ width: o.width || 2,
31
+ lineCap: o.lineCap || "round",
32
+ screenSpaceWing: {
33
+ fromX: i,
34
+ fromY: e,
35
+ toX: a,
36
+ toY: d,
37
+ headAngle: Math.PI / 6,
38
+ wingSide: "left"
39
+ }
40
+ }), u.push({
41
+ id: `${t}-2`,
42
+ start: s,
43
+ end: s + g,
44
+ color: h(o, "rgba(255, 0, 0, 0.8)"),
45
+ width: o.width || 2,
46
+ lineCap: o.lineCap || "round",
47
+ screenSpaceWing: {
48
+ fromX: i,
49
+ fromY: e,
50
+ toX: a,
51
+ toY: d,
52
+ headAngle: Math.PI / 6,
53
+ wingSide: "right"
54
+ }
55
+ }), u;
31
56
  }
32
57
  export {
33
- k as circleToStrokes,
34
- k as default
58
+ Y as arrowToStrokes,
59
+ Y as default
35
60
  };
36
61
  //# sourceMappingURL=index17.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index17.js","sources":["../src/converters/circle.js"],"sourcesContent":["/**\n * Circle Converter - Converts circle annotations to stroke commands\n *\n * Transforms circle/ellipse data into stroke paths that can be\n * rendered progressively on canvas with hand-drawn style.\n *\n * @module converters/circle\n */\n\nimport { roughEllipse, hashSeed } from '../rough/roughPathExtractor.js';\n\nconst SCALE = 1000;\n\n/**\n * Converts a circle annotation to stroke commands\n *\n * Generates an ellipse path that renders progressively around the perimeter.\n * Uses RoughJS for hand-drawn circle style.\n *\n * @param {Object} annotation - Circle annotation object\n * @param {string} annotation.id - Unique identifier\n * @param {number} annotation.start - Start time in seconds\n * @param {number} annotation.end - End time in seconds\n * @param {number} annotation.cx - Center x position (0-1 normalized)\n * @param {number} annotation.cy - Center y position (0-1 normalized)\n * @param {number} annotation.rx - Horizontal radius (0-1 normalized)\n * @param {number} annotation.ry - Vertical radius (0-1 normalized)\n * @param {Object} [annotation.style] - Optional style overrides\n * @param {Object} style - Resolved style configuration\n * @param {string} style.color - Stroke color\n * @param {number} style.width - Stroke width in pixels\n * @param {string} [style.lineCap='round'] - Line cap style\n * @param {number} [style.roughness=1.0] - Hand-drawn roughness\n * @param {number} [style.bowing=1.0] - Line curvature\n * @returns {Array<Object>} Array of stroke commands\n */\nexport function circleToStrokes(annotation, style) {\n const { id, start, end, cx, cy, rx, ry } = annotation;\n\n if (typeof cx !== 'number' || typeof cy !== 'number' ||\n typeof rx !== 'number' || typeof ry !== 'number') {\n return [];\n }\n\n const roughness = style.roughness ?? 1.0;\n const bowing = style.bowing ?? 1.0;\n const curveFitting = style.curveFitting ?? 0.95;\n const curveStepCount = style.curveStepCount ?? 9;\n const maxRandomnessOffset = style.maxRandomnessOffset ?? 2;\n const disableMultiStroke = style.disableMultiStroke ?? false;\n\n const roughPoints = roughEllipse(\n cx * SCALE,\n cy * SCALE,\n rx * 2 * SCALE,\n ry * 2 * SCALE,\n {\n roughness,\n bowing,\n seed: hashSeed(id),\n curveFitting,\n curveStepCount,\n maxRandomnessOffset,\n disableMultiStroke\n }\n );\n\n const points = roughPoints.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n return [{\n id,\n points,\n start,\n end,\n color: style.color || 'rgba(255, 165, 0, 0.8)',\n width: style.width || 3,\n lineCap: style.lineCap || 'round'\n }];\n}\n\nexport default circleToStrokes;\n"],"names":["SCALE","circleToStrokes","annotation","style","id","start","end","cx","cy","rx","ry","roughness","bowing","curveFitting","curveStepCount","maxRandomnessOffset","disableMultiStroke","points","roughEllipse","hashSeed","px","py"],"mappings":";AAWA,MAAMA,IAAQ;AAyBP,SAASC,EAAgBC,GAAYC,GAAO;AACjD,QAAM,EAAE,IAAAC,GAAI,OAAAC,GAAO,KAAAC,GAAK,IAAAC,GAAI,IAAAC,GAAI,IAAAC,GAAI,IAAAC,EAAE,IAAKR;AAE3C,MAAI,OAAOK,KAAO,YAAY,OAAOC,KAAO,YACxC,OAAOC,KAAO,YAAY,OAAOC,KAAO;AAC1C,WAAO,CAAA;AAGT,QAAMC,IAAYR,EAAM,aAAa,GAC/BS,IAAST,EAAM,UAAU,GACzBU,IAAeV,EAAM,gBAAgB,MACrCW,IAAiBX,EAAM,kBAAkB,GACzCY,IAAsBZ,EAAM,uBAAuB,GACnDa,IAAqBb,EAAM,sBAAsB,IAkBjDc,IAhBcC;AAAA,IAClBX,IAAKP;AAAA,IACLQ,IAAKR;AAAA,IACLS,IAAK,IAAIT;AAAA,IACTU,IAAK,IAAIV;AAAA,IACT;AAAA,MACE,WAAAW;AAAA,MACA,QAAAC;AAAA,MACA,MAAMO,EAASf,CAAE;AAAA,MACjB,cAAAS;AAAA,MACA,gBAAAC;AAAA,MACA,qBAAAC;AAAA,MACA,oBAAAC;AAAA,IACN;AAAA,EACA,EAE6B,IAAI,CAAC,CAACI,GAAIC,CAAE,MAAM,CAACD,IAAKpB,GAAOqB,IAAKrB,CAAK,CAAC;AAErE,SAAO,CAAC;AAAA,IACN,IAAAI;AAAA,IACA,QAAAa;AAAA,IACA,OAAAZ;AAAA,IACA,KAAAC;AAAA,IACA,OAAOH,EAAM,SAAS;AAAA,IACtB,OAAOA,EAAM,SAAS;AAAA,IACtB,SAASA,EAAM,WAAW;AAAA,EAC9B,CAAG;AACH;"}
1
+ {"version":3,"file":"index17.js","sources":["../src/converters/arrow.js"],"sourcesContent":["/**\n * Arrow Converter - Converts arrow annotations to stroke commands\n *\n * Transforms arrow data into a line stroke with arrowhead strokes\n * that can be rendered progressively on canvas with hand-drawn style.\n *\n * @module converters/arrow\n */\n\nimport { roughLine } from '../rough/roughPathExtractor.js';\nimport { buildRoughOptions, resolveColor } from './_shared.js';\n\nconst SCALE = 1000;\n\n/**\n * Converts an arrow annotation to stroke commands\n *\n * Creates a main line stroke from source to target, followed by\n * two wing strokes forming the arrowhead. Line draws first (70%),\n * then arrowhead (30%).\n *\n * The wings emit `screenSpaceWing` stroke shapes; their geometry is\n * recomputed by the renderer every frame in screen-pixel space so\n * diagonal arrows render with symmetric wings regardless of viewport\n * aspect ratio. The wing strokes carry no `points` array.\n *\n * @param {Object} annotation - Arrow annotation object\n * @param {string} annotation.id - Unique identifier\n * @param {number} annotation.start - Start time in seconds\n * @param {number} annotation.end - End time in seconds\n * @param {number} annotation.from_x - Source x position (0-1 normalized)\n * @param {number} annotation.from_y - Source y position (0-1 normalized)\n * @param {number} annotation.to_x - Target x position (0-1 normalized)\n * @param {number} annotation.to_y - Target y position (0-1 normalized)\n * @param {Object} [annotation.style] - Optional style overrides\n * @param {Object} style - Resolved style configuration\n * @param {string} [style.color] - Stroke color\n * @param {number} [style.width=2] - Stroke width in pixels\n * @param {string} [style.lineCap='round'] - Line cap style\n * @returns {Array<Object>} Array of stroke commands\n */\nexport function arrowToStrokes(annotation, style) {\n const { id, start, end, from_x, from_y, to_x, to_y } = annotation;\n\n if (typeof from_x !== 'number' || typeof from_y !== 'number' ||\n typeof to_x !== 'number' || typeof to_y !== 'number') {\n return [];\n }\n\n const strokes = [];\n const totalDuration = end - start;\n const lineDuration = totalDuration * 0.7;\n const headDuration = totalDuration * 0.3;\n\n // Main line stroke with RoughJS style\n const roughLinePoints = roughLine(\n from_x * SCALE,\n from_y * SCALE,\n to_x * SCALE,\n to_y * SCALE,\n buildRoughOptions(style, `${id}-line`, { roughness: 0.8, bowing: 0.8 })\n );\n\n const linePoints = roughLinePoints.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n strokes.push({\n id: `${id}-0`,\n points: linePoints,\n start: start,\n end: start + lineDuration,\n color: resolveColor(style, 'rgba(255, 0, 0, 0.8)'),\n width: style.width || 2,\n lineCap: style.lineCap || 'round'\n });\n\n // Arrowhead wings — geometry resolved each frame in screen-pixel space by\n // the renderer (`_drawScreenSpaceWingStroke`). No `points` array here.\n const headStart = start + lineDuration;\n const wingDuration = headDuration / 2;\n\n strokes.push({\n id: `${id}-1`,\n start: headStart,\n end: headStart + wingDuration,\n color: resolveColor(style, 'rgba(255, 0, 0, 0.8)'),\n width: style.width || 2,\n lineCap: style.lineCap || 'round',\n screenSpaceWing: {\n fromX: from_x,\n fromY: from_y,\n toX: to_x,\n toY: to_y,\n headAngle: Math.PI / 6,\n wingSide: 'left',\n },\n });\n\n strokes.push({\n id: `${id}-2`,\n start: headStart,\n end: headStart + wingDuration,\n color: resolveColor(style, 'rgba(255, 0, 0, 0.8)'),\n width: style.width || 2,\n lineCap: style.lineCap || 'round',\n screenSpaceWing: {\n fromX: from_x,\n fromY: from_y,\n toX: to_x,\n toY: to_y,\n headAngle: Math.PI / 6,\n wingSide: 'right',\n },\n });\n\n return strokes;\n}\n\nexport default arrowToStrokes;\n"],"names":["SCALE","arrowToStrokes","annotation","style","id","start","end","from_x","from_y","to_x","to_y","strokes","totalDuration","lineDuration","headDuration","linePoints","roughLine","buildRoughOptions","px","py","resolveColor","headStart","wingDuration"],"mappings":";;AAYA,MAAMA,IAAQ;AA6BP,SAASC,EAAeC,GAAYC,GAAO;AAChD,QAAM,EAAE,IAAAC,GAAI,OAAAC,GAAO,KAAAC,GAAK,QAAAC,GAAQ,QAAAC,GAAQ,MAAAC,GAAM,MAAAC,EAAI,IAAKR;AAEvD,MAAI,OAAOK,KAAW,YAAY,OAAOC,KAAW,YAChD,OAAOC,KAAS,YAAY,OAAOC,KAAS;AAC9C,WAAO,CAAA;AAGT,QAAMC,IAAU,CAAA,GACVC,IAAgBN,IAAMD,GACtBQ,IAAeD,IAAgB,KAC/BE,IAAeF,IAAgB,KAW/BG,IARkBC;AAAA,IACtBT,IAASP;AAAA,IACTQ,IAASR;AAAA,IACTS,IAAOT;AAAA,IACPU,IAAOV;AAAA,IACPiB,EAAkBd,GAAO,GAAGC,CAAE,SAAS,EAAE,WAAW,KAAK,QAAQ,IAAG,CAAE;AAAA,EAC1E,EAEqC,IAAI,CAAC,CAACc,GAAIC,CAAE,MAAM,CAACD,IAAKlB,GAAOmB,IAAKnB,CAAK,CAAC;AAE7E,EAAAW,EAAQ,KAAK;AAAA,IACX,IAAI,GAAGP,CAAE;AAAA,IACT,QAAQW;AAAA,IACR,OAAOV;AAAA,IACP,KAAKA,IAAQQ;AAAA,IACb,OAAOO,EAAajB,GAAO,sBAAsB;AAAA,IACjD,OAAOA,EAAM,SAAS;AAAA,IACtB,SAASA,EAAM,WAAW;AAAA,EAC9B,CAAG;AAID,QAAMkB,IAAYhB,IAAQQ,GACpBS,IAAeR,IAAe;AAEpC,SAAAH,EAAQ,KAAK;AAAA,IACX,IAAI,GAAGP,CAAE;AAAA,IACT,OAAOiB;AAAA,IACP,KAAKA,IAAYC;AAAA,IACjB,OAAOF,EAAajB,GAAO,sBAAsB;AAAA,IACjD,OAAOA,EAAM,SAAS;AAAA,IACtB,SAASA,EAAM,WAAW;AAAA,IAC1B,iBAAiB;AAAA,MACf,OAAOI;AAAA,MACP,OAAOC;AAAA,MACP,KAAKC;AAAA,MACL,KAAKC;AAAA,MACL,WAAW,KAAK,KAAK;AAAA,MACrB,UAAU;AAAA,IAChB;AAAA,EACA,CAAG,GAEDC,EAAQ,KAAK;AAAA,IACX,IAAI,GAAGP,CAAE;AAAA,IACT,OAAOiB;AAAA,IACP,KAAKA,IAAYC;AAAA,IACjB,OAAOF,EAAajB,GAAO,sBAAsB;AAAA,IACjD,OAAOA,EAAM,SAAS;AAAA,IACtB,SAASA,EAAM,WAAW;AAAA,IAC1B,iBAAiB;AAAA,MACf,OAAOI;AAAA,MACP,OAAOC;AAAA,MACP,KAAKC;AAAA,MACL,KAAKC;AAAA,MACL,WAAW,KAAK,KAAK;AAAA,MACrB,UAAU;AAAA,IAChB;AAAA,EACA,CAAG,GAEMC;AACT;"}
package/dist/index18.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function l(d,i){const{id:c,start:n,end:r,strokes:o}=d;if(!o||o.length===0)return[];const a=r-n;if(a<=0)return[];const f=o.reduce((t,e)=>Math.max(t,(e.timeOffset||0)+(e.duration||.5)),0)||1,s=a/f;return o.filter(t=>t.points&&t.points.length>=2).map((t,e)=>({id:`${c}-${e}`,points:t.points,start:n+(t.timeOffset||0)*s,end:Math.min(n+((t.timeOffset||0)+(t.duration||.5))*s,r),color:t.color||i.color||"#DC143C",width:t.width||i.width||2,lineCap:i.lineCap||"round"}))}exports.inkToStrokes=l;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const f=require("./index28.cjs"),s=require("./index29.cjs"),o=1e3;function c(l,r){const{id:e,start:a,end:p,cx:t,cy:n,rx:u,ry:i}=l;if(typeof t!="number"||typeof n!="number"||typeof u!="number"||typeof i!="number")return[];const d=s.buildRoughOptions(r,e,{roughness:1,bowing:1}),g=f.roughEllipse(t*o,n*o,u*2*o,i*2*o,d).map(([h,b])=>[h/o,b/o]);return[{id:e,points:g,start:a,end:p,color:s.resolveColor(r,"rgba(255, 165, 0, 0.8)"),width:r.width||3,lineCap:r.lineCap||"round"}]}exports.circleToStrokes=c;exports.default=c;
2
2
  //# sourceMappingURL=index18.cjs.map