supervision 0.2.0-next.0 → 0.2.0-next.2

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 (192) hide show
  1. package/dist/constants/media-renderer.d.ts +3 -0
  2. package/dist/constants/media-renderer.d.ts.map +1 -1
  3. package/dist/index.d.ts +5 -5
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1722 -1395
  6. package/dist/index.js.map +1 -1
  7. package/dist/mask-preparation.worker.js +109 -31
  8. package/dist/mask-preparation.worker.js.map +1 -1
  9. package/dist/media/media-frame-clock.d.ts +4 -0
  10. package/dist/media/media-frame-clock.d.ts.map +1 -0
  11. package/dist/media/media-source-state.d.ts.map +1 -1
  12. package/dist/media/media-source.d.ts +6 -0
  13. package/dist/media/media-source.d.ts.map +1 -1
  14. package/dist/media/video-engine-media-source.d.ts +17 -7
  15. package/dist/media/video-engine-media-source.d.ts.map +1 -1
  16. package/dist/media/video-engine-media-source.js +3 -0
  17. package/dist/media/video-engine-media-source.js.map +1 -0
  18. package/dist/playback/media-playback-controller.d.ts +7 -1
  19. package/dist/playback/media-playback-controller.d.ts.map +1 -1
  20. package/dist/render-preparation/mask-frame-artifact.d.ts +2 -0
  21. package/dist/render-preparation/mask-frame-artifact.d.ts.map +1 -1
  22. package/dist/render-preparation/mask-frame-compositor.d.ts +7 -0
  23. package/dist/render-preparation/mask-frame-compositor.d.ts.map +1 -1
  24. package/dist/render-preparation/mask-preparation-worker-protocol.d.ts +1 -0
  25. package/dist/render-preparation/mask-preparation-worker-protocol.d.ts.map +1 -1
  26. package/dist/render-preparation/prepared-render-window.d.ts +21 -2
  27. package/dist/render-preparation/prepared-render-window.d.ts.map +1 -1
  28. package/dist/render-preparation/prepared-window-timeline.d.ts +1 -0
  29. package/dist/render-preparation/prepared-window-timeline.d.ts.map +1 -1
  30. package/dist/renderers/injected-pixi.d.ts +38 -0
  31. package/dist/renderers/injected-pixi.d.ts.map +1 -0
  32. package/dist/renderers/media-frame-navigation.d.ts +17 -0
  33. package/dist/renderers/media-frame-navigation.d.ts.map +1 -0
  34. package/dist/renderers/media-renderer-core.d.ts +9 -0
  35. package/dist/renderers/media-renderer-core.d.ts.map +1 -1
  36. package/dist/renderers/media-renderer-scene.d.ts +17 -5
  37. package/dist/renderers/media-renderer-scene.d.ts.map +1 -1
  38. package/dist/renderers/media-renderer-state.d.ts +9 -0
  39. package/dist/renderers/media-renderer-state.d.ts.map +1 -1
  40. package/dist/renderers/media-renderer-transport.d.ts +19 -3
  41. package/dist/renderers/media-renderer-transport.d.ts.map +1 -1
  42. package/dist/renderers/pixi-focus-layer.d.ts +1 -0
  43. package/dist/renderers/pixi-focus-layer.d.ts.map +1 -1
  44. package/dist/renderers/pixi-frame-present.d.ts +1 -1
  45. package/dist/renderers/pixi-frame-present.d.ts.map +1 -1
  46. package/dist/renderers/pixi-id-mask-shader.d.ts +4 -33
  47. package/dist/renderers/pixi-id-mask-shader.d.ts.map +1 -1
  48. package/dist/renderers/pixi-interaction-presentation-layer.d.ts +0 -1
  49. package/dist/renderers/pixi-interaction-presentation-layer.d.ts.map +1 -1
  50. package/dist/renderers/pixi-mask-halo.d.ts +4 -33
  51. package/dist/renderers/pixi-mask-halo.d.ts.map +1 -1
  52. package/dist/renderers/pixi-mask-layer.d.ts +28 -29
  53. package/dist/renderers/pixi-mask-layer.d.ts.map +1 -1
  54. package/dist/renderers/pixi-media-scene.d.ts.map +1 -1
  55. package/dist/renderers/pixi-polygon-layer.d.ts +2 -0
  56. package/dist/renderers/pixi-polygon-layer.d.ts.map +1 -1
  57. package/dist/renderers/pixi-region-coverage-mask.d.ts +4 -33
  58. package/dist/renderers/pixi-region-coverage-mask.d.ts.map +1 -1
  59. package/dist/renderers/pixi-region-layer.d.ts +6 -31
  60. package/dist/renderers/pixi-region-layer.d.ts.map +1 -1
  61. package/dist/renderers/pixi-shader-lifecycle.d.ts +14 -0
  62. package/dist/renderers/pixi-shader-lifecycle.d.ts.map +1 -0
  63. package/dist/renderers/prepared-annotation-window.d.ts.map +1 -1
  64. package/dist/renderers/presented-frame-channel.d.ts +34 -1
  65. package/dist/renderers/presented-frame-channel.d.ts.map +1 -1
  66. package/dist/sessions/media-session-defaults.d.ts.map +1 -1
  67. package/dist/sessions/media-session-detections.d.ts.map +1 -1
  68. package/dist/sessions/media-session-state.d.ts.map +1 -1
  69. package/dist/sessions/media-session.d.ts.map +1 -1
  70. package/dist/tracking.worker.js +19 -5
  71. package/dist/tracking.worker.js.map +1 -1
  72. package/dist/types/media-frame-clock.d.ts +16 -0
  73. package/dist/types/media-frame-clock.d.ts.map +1 -0
  74. package/dist/types/media-frame-navigation.d.ts +28 -0
  75. package/dist/types/media-frame-navigation.d.ts.map +1 -0
  76. package/dist/types/media-renderer-display.d.ts +12 -0
  77. package/dist/types/media-renderer-display.d.ts.map +1 -0
  78. package/dist/types/media-renderer.d.ts +13 -0
  79. package/dist/types/media-renderer.d.ts.map +1 -1
  80. package/dist/types/media-session.d.ts +35 -32
  81. package/dist/types/media-session.d.ts.map +1 -1
  82. package/dist/types/render-preparation.d.ts +78 -28
  83. package/dist/types/render-preparation.d.ts.map +1 -1
  84. package/dist/video-engine-media-source-DR-x1UfK.js +483 -0
  85. package/dist/video-engine-media-source-DR-x1UfK.js.map +1 -0
  86. package/dist/web-video-engine/analysis-session.d.ts +0 -1
  87. package/dist/web-video-engine/analysis.d.ts +0 -1
  88. package/dist/web-video-engine/analysis.js +211 -23
  89. package/dist/web-video-engine/cache-budget.d.ts +0 -1
  90. package/dist/web-video-engine/canvas-sink-scrub-cursor.d.ts +6 -2
  91. package/dist/web-video-engine/clock.d.ts +0 -1
  92. package/dist/web-video-engine/constants.d.ts +9 -1
  93. package/dist/web-video-engine/create-scrub-cursor.d.ts +6 -3
  94. package/dist/web-video-engine/decode-resolution.d.ts +0 -1
  95. package/dist/web-video-engine/decode-scheduler.d.ts +26 -5
  96. package/dist/web-video-engine/decode-session.d.ts +11 -1
  97. package/dist/web-video-engine/decode-source.d.ts +11 -1
  98. package/dist/web-video-engine/diagnostics-store.d.ts +0 -1
  99. package/dist/web-video-engine/diagnostics.d.ts +19 -19
  100. package/dist/web-video-engine/embedded-engine-worker.d.ts +0 -1
  101. package/dist/web-video-engine/engine-core.d.ts +31 -11
  102. package/dist/web-video-engine/engine.d.ts +3 -4
  103. package/dist/web-video-engine/engine.js +175 -44
  104. package/dist/web-video-engine/engine.worker.d.ts +0 -1
  105. package/dist/web-video-engine/engine.worker.js +5712 -2947
  106. package/dist/web-video-engine/frame-cache.d.ts +121 -12
  107. package/dist/web-video-engine/frame-extractor.d.ts +0 -1
  108. package/dist/web-video-engine/{frame-timeline-GINI8Gum.js → frame-timeline-DreEwsRY.js} +83 -27
  109. package/dist/web-video-engine/frame-timeline.d.ts +10 -1
  110. package/dist/web-video-engine/frame-walker.d.ts +0 -1
  111. package/dist/web-video-engine/index.d.ts +12 -2
  112. package/dist/web-video-engine/index.d.ts.map +1 -1
  113. package/dist/web-video-engine/index.js +2 -2
  114. package/dist/web-video-engine/key-packet.d.ts +0 -1
  115. package/dist/web-video-engine/keyframe-index.d.ts +0 -1
  116. package/dist/web-video-engine/mirror-store.d.ts +0 -1
  117. package/dist/web-video-engine/pausable-deadline.d.ts +11 -0
  118. package/dist/web-video-engine/renderer.d.ts +0 -1
  119. package/dist/web-video-engine/rotation.d.ts +0 -1
  120. package/dist/web-video-engine/scrub-controller.d.ts +8 -5
  121. package/dist/web-video-engine/scrub-cursor.d.ts +15 -7
  122. package/dist/web-video-engine/scrub-trajectory.d.ts +0 -1
  123. package/dist/web-video-engine/source-residency.d.ts +35 -1
  124. package/dist/web-video-engine/trace-recorder.d.ts +0 -1
  125. package/dist/web-video-engine/types.d.ts +18 -22
  126. package/dist/web-video-engine/video-engine.d.ts +39 -17
  127. package/dist/web-video-engine/webgpu-renderer.d.ts +0 -1
  128. package/dist/web-video-engine/worker-bridge.d.ts +0 -1
  129. package/dist/web-video-engine/worker-dispatch.d.ts +0 -1
  130. package/dist/web-video-engine/worker-protocol.d.ts +38 -15
  131. package/node_modules/supervision-js-core/dist/detections/buffered-detection-timeline.d.ts.map +1 -1
  132. package/node_modules/supervision-js-core/dist/index.d.ts +2 -2
  133. package/node_modules/supervision-js-core/dist/index.d.ts.map +1 -1
  134. package/node_modules/supervision-js-core/dist/index.js +182 -68
  135. package/node_modules/supervision-js-core/dist/index.js.map +1 -1
  136. package/node_modules/supervision-js-core/dist/types/detection-timeline.d.ts +20 -3
  137. package/node_modules/supervision-js-core/dist/types/detection-timeline.d.ts.map +1 -1
  138. package/node_modules/supervision-js-core/dist/types/media-rendering.d.ts +28 -26
  139. package/node_modules/supervision-js-core/dist/types/media-rendering.d.ts.map +1 -1
  140. package/node_modules/supervision-js-core/dist/types/session-lifecycle.d.ts +16 -0
  141. package/node_modules/supervision-js-core/dist/types/session-lifecycle.d.ts.map +1 -1
  142. package/node_modules/supervision-js-core/dist/utils/detection-masks.d.ts.map +1 -1
  143. package/node_modules/supervision-js-core/dist/utils/id-mask-frame.d.ts +19 -0
  144. package/node_modules/supervision-js-core/dist/utils/id-mask-frame.d.ts.map +1 -1
  145. package/package.json +3 -3
  146. package/dist/media/media-condition-probe.d.ts +0 -51
  147. package/dist/media/media-condition-probe.d.ts.map +0 -1
  148. package/dist/media/media-conditions.d.ts +0 -28
  149. package/dist/media/media-conditions.d.ts.map +0 -1
  150. package/dist/types/media-conditions.d.ts +0 -149
  151. package/dist/types/media-conditions.d.ts.map +0 -1
  152. package/dist/web-video-engine/analysis-session.d.ts.map +0 -1
  153. package/dist/web-video-engine/analysis.d.ts.map +0 -1
  154. package/dist/web-video-engine/analysis.js.map +0 -1
  155. package/dist/web-video-engine/cache-budget.d.ts.map +0 -1
  156. package/dist/web-video-engine/canvas-sink-scrub-cursor.d.ts.map +0 -1
  157. package/dist/web-video-engine/clock.d.ts.map +0 -1
  158. package/dist/web-video-engine/constants.d.ts.map +0 -1
  159. package/dist/web-video-engine/create-scrub-cursor.d.ts.map +0 -1
  160. package/dist/web-video-engine/decode-resolution.d.ts.map +0 -1
  161. package/dist/web-video-engine/decode-scheduler.d.ts.map +0 -1
  162. package/dist/web-video-engine/decode-session.d.ts.map +0 -1
  163. package/dist/web-video-engine/decode-source.d.ts.map +0 -1
  164. package/dist/web-video-engine/diagnostics-store.d.ts.map +0 -1
  165. package/dist/web-video-engine/diagnostics.d.ts.map +0 -1
  166. package/dist/web-video-engine/embedded-engine-worker.d.ts.map +0 -1
  167. package/dist/web-video-engine/engine-core.d.ts.map +0 -1
  168. package/dist/web-video-engine/engine.d.ts.map +0 -1
  169. package/dist/web-video-engine/engine.js.map +0 -1
  170. package/dist/web-video-engine/engine.worker.d.ts.map +0 -1
  171. package/dist/web-video-engine/engine.worker.js.map +0 -1
  172. package/dist/web-video-engine/frame-cache.d.ts.map +0 -1
  173. package/dist/web-video-engine/frame-extractor.d.ts.map +0 -1
  174. package/dist/web-video-engine/frame-timeline-GINI8Gum.js.map +0 -1
  175. package/dist/web-video-engine/frame-timeline.d.ts.map +0 -1
  176. package/dist/web-video-engine/frame-walker.d.ts.map +0 -1
  177. package/dist/web-video-engine/key-packet.d.ts.map +0 -1
  178. package/dist/web-video-engine/keyframe-index.d.ts.map +0 -1
  179. package/dist/web-video-engine/mirror-store.d.ts.map +0 -1
  180. package/dist/web-video-engine/renderer.d.ts.map +0 -1
  181. package/dist/web-video-engine/rotation.d.ts.map +0 -1
  182. package/dist/web-video-engine/scrub-controller.d.ts.map +0 -1
  183. package/dist/web-video-engine/scrub-cursor.d.ts.map +0 -1
  184. package/dist/web-video-engine/scrub-trajectory.d.ts.map +0 -1
  185. package/dist/web-video-engine/source-residency.d.ts.map +0 -1
  186. package/dist/web-video-engine/trace-recorder.d.ts.map +0 -1
  187. package/dist/web-video-engine/types.d.ts.map +0 -1
  188. package/dist/web-video-engine/video-engine.d.ts.map +0 -1
  189. package/dist/web-video-engine/webgpu-renderer.d.ts.map +0 -1
  190. package/dist/web-video-engine/worker-bridge.d.ts.map +0 -1
  191. package/dist/web-video-engine/worker-dispatch.d.ts.map +0 -1
  192. package/dist/web-video-engine/worker-protocol.d.ts.map +0 -1
@@ -426,7 +426,6 @@
426
426
  const height = width === maskWidth
427
427
  ? maskHeight
428
428
  : Math.max(1, Math.round((width * maskHeight) / maskWidth));
429
- const strokeScale = width / maskWidth;
430
429
  const scaledAxes = width === maskWidth
431
430
  ? undefined
432
431
  : createScaledMaskAxes({ height, maskHeight, maskWidth, width });
@@ -437,18 +436,17 @@
437
436
  let hasStroke = false;
438
437
  let maxStrokeWidth = 0;
439
438
  for (const instruction of instructions) {
440
- const detectionMaskId = instruction.detectionIndex + 1;
441
- if (detectionMaskId <= 0 ||
442
- detectionMaskId >= MAX_ID_MASK_PALETTE_ENTRIES) {
439
+ const detectionMaskId = resolveIdMaskPaletteId(instruction.detectionIndex);
440
+ if (detectionMaskId === undefined) {
443
441
  return undefined;
444
442
  }
445
- writePaletteEntry(fillPalette, detectionMaskId, instruction.color, instruction.alpha);
443
+ writeIdMaskPaletteEntry(fillPalette, detectionMaskId, instruction.color, instruction.alpha);
446
444
  if (instruction.stroke && instruction.stroke.width > 0) {
447
- const strokeWidth = Math.min(resolveStrokeTexels(instruction.stroke.width, strokeScale), MAX_ID_MASK_STROKE_WIDTH);
445
+ const strokeWidth = resolveIdMaskStrokeTexels(instruction.stroke.width, maskWidth, width);
448
446
  hasStroke = true;
449
447
  strokeWidths[detectionMaskId] = strokeWidth;
450
448
  maxStrokeWidth = Math.max(maxStrokeWidth, strokeWidth);
451
- writePaletteEntry(strokePalette, detectionMaskId, instruction.stroke.color, instruction.stroke.alpha);
449
+ writeIdMaskPaletteEntry(strokePalette, detectionMaskId, instruction.stroke.color, instruction.stroke.alpha);
452
450
  }
453
451
  if (scaledAxes) {
454
452
  writeScaledMaskRuns(data, scaledAxes, instruction.mask, detectionMaskId);
@@ -463,6 +461,7 @@
463
461
  hasStroke,
464
462
  height,
465
463
  maxStrokeWidth,
464
+ sourceWidth: maskWidth,
466
465
  strokePalette,
467
466
  strokeWidths,
468
467
  width,
@@ -545,10 +544,14 @@
545
544
  * A stroke is measured in texels of the raster it is drawn on, so a coarser
546
545
  * raster measures it in coarser texels. A stroke of a texel or more keeps at
547
546
  * least one, the thinnest line the shader can draw; a narrower one keeps its
548
- * own width, which the shader draws as an inner boundary at any scale.
547
+ * own width, which the shader draws as an inner boundary at any scale. The
548
+ * ceiling is the widest neighbourhood the shaders scan, so a wider stroke would
549
+ * be drawn at the ceiling anyway and every layer drawing the same annotation
550
+ * has to arrive at the same width.
549
551
  */
550
- function resolveStrokeTexels(strokeWidth, scale) {
551
- return Math.max(strokeWidth * scale, Math.min(strokeWidth, 1));
552
+ function resolveIdMaskStrokeTexels(strokeWidth, maskWidth, rasterWidth) {
553
+ const scale = maskWidth > 0 ? rasterWidth / maskWidth : 1;
554
+ return Math.min(Math.max(strokeWidth * scale, Math.min(strokeWidth, 1)), MAX_ID_MASK_STROKE_WIDTH);
552
555
  }
553
556
  function createScaledMaskAxes(frame) {
554
557
  return {
@@ -565,8 +568,19 @@
565
568
  }
566
569
  return map;
567
570
  }
568
- function writePaletteEntry(palette, id, color, alpha) {
569
- const offset = id * 4;
571
+ /**
572
+ * The palette slot a detection index names, or undefined when the palette has
573
+ * no slot for it. Slot zero is the background, so the ids start at one and the
574
+ * last detection the palette can name sits one index below the last slot.
575
+ */
576
+ function resolveIdMaskPaletteId(detectionIndex) {
577
+ const detectionMaskId = detectionIndex + 1;
578
+ return detectionMaskId > 0 && detectionMaskId < MAX_ID_MASK_PALETTE_ENTRIES
579
+ ? detectionMaskId
580
+ : undefined;
581
+ }
582
+ function writeIdMaskPaletteEntry(palette, detectionMaskId, color, alpha) {
583
+ const offset = detectionMaskId * 4;
570
584
  palette[offset] = ((color >> 16) & 0xff) / 255;
571
585
  palette[offset + 1] = ((color >> 8) & 0xff) / 255;
572
586
  palette[offset + 2] = (color & 0xff) / 255;
@@ -606,7 +620,7 @@
606
620
  */
607
621
  var MediaErrorKind;
608
622
  (function (MediaErrorKind) {
609
- /** The media could not be opened or read at all. */
623
+ /** The media could not be opened or read, or was refused before any read. */
610
624
  MediaErrorKind["Unreadable"] = "unreadable";
611
625
  /** The container or codec is not supported by this platform. */
612
626
  MediaErrorKind["UnsupportedFormat"] = "unsupportedFormat";
@@ -640,8 +654,8 @@
640
654
  * A source the renderer pulls samples from can be held between any two frames,
641
655
  * because the renderer decides when each one is drawn. A source that presents
642
656
  * its own frames owns the playhead, so holding it means stopping the producer
643
- * and starting it again, which the detection gate does and the
644
- * render-preparation gate does not.
657
+ * and starting it again, and a gate that stops one has to bound its own wait
658
+ * or a producer nothing answers for never runs again.
645
659
  */
646
660
  var PlaybackGateReach;
647
661
  (function (PlaybackGateReach) {
@@ -652,8 +666,6 @@
652
666
  * missing, until they arrive or the gate's own wait bound gives up on them.
653
667
  */
654
668
  PlaybackGateReach["EveryFrame"] = "everyFrame";
655
- /** Playback waits to begin; frames after that are not held. */
656
- PlaybackGateReach["StartOfPlayback"] = "startOfPlayback";
657
669
  })(PlaybackGateReach || (PlaybackGateReach = {}));
658
670
 
659
671
  /**
@@ -707,7 +719,23 @@
707
719
  MediaSessionActivityKind["Error"] = "error";
708
720
  MediaSessionActivityKind["MediaNormalizing"] = "mediaNormalizing";
709
721
  MediaSessionActivityKind["MediaOpening"] = "mediaOpening";
722
+ /**
723
+ * The picture is waiting on media the source has not handed over yet, which
724
+ * is the bytes and their decode rather than anything downstream of them.
725
+ * `PlaybackBuffering` is what a transport reports once it has already
726
+ * stopped; this is reported from the read itself, including the reads a seek
727
+ * makes while the transport still reads as paused.
728
+ */
729
+ MediaSessionActivityKind["MediaSourceReading"] = "mediaSourceReading";
710
730
  MediaSessionActivityKind["PlaybackBuffering"] = "playbackBuffering";
731
+ /**
732
+ * The render-preparation gate held the picture for artifacts that never
733
+ * arrived and let it go. Nothing is blocked: the frames reaching the screen
734
+ * are the ones whose artifacts were given up on. What is waited on is
735
+ * preparation finishing another frame, which is what lets the gate hold the
736
+ * picture again; `RenderPreparing` covers the holds that are running.
737
+ */
738
+ MediaSessionActivityKind["RenderPreparationAbandoned"] = "renderPreparationAbandoned";
711
739
  MediaSessionActivityKind["RenderPreparing"] = "renderPreparing";
712
740
  })(MediaSessionActivityKind || (MediaSessionActivityKind = {}));
713
741
  /**
@@ -791,18 +819,33 @@
791
819
  return undefined;
792
820
  }
793
821
  }
822
+ /**
823
+ * Whether the palette has a slot for every detection this frame masks. An id
824
+ * names a detection by its index in the frame, so one masked detection past the
825
+ * last slot leaves the whole frame without an id raster however few masks it
826
+ * carries.
827
+ */
828
+ function canIdMaskPaletteNameFrame(instructions) {
829
+ return instructions.every((instruction) => instruction.visible === false ||
830
+ resolveIdMaskPaletteId(instruction.detectionIndex) !== undefined);
831
+ }
794
832
  function createIdMaskPlane(instructions, maxRasterWidth) {
833
+ // The plane carries the ids a failed cook could not. A frame the palette
834
+ // cannot name has none to carry, and cooking it again reaches the same
835
+ // refusal after rasterizing every mask a second time.
836
+ if (!canIdMaskPaletteNameFrame(instructions)) {
837
+ return undefined;
838
+ }
795
839
  const frame = createIdMaskRasterFrame(instructions, maxRasterWidth);
796
840
  return frame
797
841
  ? { data: frame.data, height: frame.height, width: frame.width }
798
842
  : undefined;
799
843
  }
800
844
  function compositeInstruction(rgba, canvasWidth, instruction) {
801
- const decodedMask = decodeCompressedRleMask(instruction.mask);
802
845
  const fill = resolveRgbaColor(instruction.color, instruction.alpha);
803
- compositeMaskFill(rgba, canvasWidth, decodedMask, fill);
804
- if (instruction.stroke) {
805
- compositeMaskStroke(rgba, canvasWidth, decodedMask, instruction.stroke);
846
+ const bounds = compositeMaskFill(rgba, canvasWidth, instruction.mask, fill);
847
+ if (instruction.stroke && bounds) {
848
+ compositeMaskStroke(rgba, canvasWidth, decodeCompressedRleMask(instruction.mask), bounds, instruction.stroke);
806
849
  }
807
850
  }
808
851
  function materializeMaskInstructions(instructions) {
@@ -822,25 +865,59 @@
822
865
  };
823
866
  });
824
867
  }
825
- function compositeMaskFill(rgba, canvasWidth, decodedMask, fill) {
826
- for (let y = 0; y < decodedMask.height; y += 1) {
827
- for (let x = 0; x < decodedMask.width; x += 1) {
828
- const maskOffset = y * decodedMask.width + x;
829
- if (!decodedMask.data[maskOffset]) {
830
- continue;
868
+ /**
869
+ * Compressed RLE counts runs down each column in turn, so a foreground run is
870
+ * a contiguous walk down one column that wraps into the next.
871
+ */
872
+ function compositeMaskFill(rgba, canvasWidth, mask, fill) {
873
+ const counts = decodeCompressedRleCounts(mask.counts);
874
+ const maskWidth = mask.width;
875
+ const maskHeight = mask.height;
876
+ const maskArea = maskWidth * maskHeight;
877
+ let maskOffset = 0;
878
+ let minX = maskWidth;
879
+ let minY = maskHeight;
880
+ let maxX = -1;
881
+ let maxY = -1;
882
+ for (let index = 0; index < counts.length; index += 1) {
883
+ const runLength = counts[index] ?? 0;
884
+ if (index % 2 === 0 || runLength <= 0) {
885
+ maskOffset += runLength;
886
+ continue;
887
+ }
888
+ let columnX = Math.floor(maskOffset / maskHeight);
889
+ let columnY = maskOffset - columnX * maskHeight;
890
+ for (let step = 0; step < runLength; step += 1) {
891
+ // A run can outlast the columns the mask has; the pixel it then names
892
+ // is wherever that column-major offset lands when read back row-major.
893
+ const rowMajorOffset = columnY * maskWidth + columnX;
894
+ if (rowMajorOffset < maskArea) {
895
+ const x = rowMajorOffset % maskWidth;
896
+ const y = (rowMajorOffset - x) / maskWidth;
897
+ writePixel(rgba, canvasWidth, x, y, fill);
898
+ minX = Math.min(minX, x);
899
+ minY = Math.min(minY, y);
900
+ maxX = Math.max(maxX, x);
901
+ maxY = Math.max(maxY, y);
902
+ }
903
+ columnY += 1;
904
+ if (columnY === maskHeight) {
905
+ columnY = 0;
906
+ columnX += 1;
831
907
  }
832
- writePixel(rgba, canvasWidth, x, y, fill);
833
908
  }
909
+ maskOffset += runLength;
834
910
  }
911
+ return maxX < minX || maxY < minY ? undefined : { maxX, maxY, minX, minY };
835
912
  }
836
- function compositeMaskStroke(rgba, canvasWidth, decodedMask, stroke) {
913
+ function compositeMaskStroke(rgba, canvasWidth, decodedMask, bounds, stroke) {
837
914
  const width = Math.round(stroke.width);
838
915
  if (width <= 0) {
839
916
  return;
840
917
  }
841
918
  const strokeColor = resolveRgbaColor(stroke.color, stroke.alpha);
842
- for (let y = 0; y < decodedMask.height; y += 1) {
843
- for (let x = 0; x < decodedMask.width; x += 1) {
919
+ for (let y = bounds.minY; y <= bounds.maxY; y += 1) {
920
+ for (let x = bounds.minX; x <= bounds.maxX; x += 1) {
844
921
  if (!isMaskPixel(decodedMask, x, y) ||
845
922
  !isBoundaryPixel(decodedMask, x, y)) {
846
923
  continue;
@@ -946,6 +1023,7 @@
946
1023
  raster: idMaskFrame.data,
947
1024
  regionMaskCoverage,
948
1025
  requestId: message.requestId,
1026
+ sourceWidth: idMaskFrame.sourceWidth,
949
1027
  strokePalette: idMaskFrame.strokePalette,
950
1028
  strokeWidths: idMaskFrame.strokeWidths,
951
1029
  type: MaskPreparationWorkerMessageType.Complete,