From 1ba4e82020816f2d1b6d6ada66d9bc022c4cdc5a Mon Sep 17 00:00:00 2001 From: Justin Georgi Date: Fri, 22 May 2026 20:46:59 -0700 Subject: [PATCH] Add leader lines Signed-off-by: Justin Georgi --- includes/AnnotationHandler.php | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/includes/AnnotationHandler.php b/includes/AnnotationHandler.php index 06aac63..020e0f9 100644 --- a/includes/AnnotationHandler.php +++ b/includes/AnnotationHandler.php @@ -86,6 +86,9 @@ class AnnotationHandler extends CodeContentHandler { * @return string Html string of the complete svg */ private function buildSvg($metadata) { + //Set SVG UID-ish for element IDs + $svgID = bin2hex(random_bytes(6)); + //Check if the image to annotate has been set if (isset($metadata['baseImage'])) { $imageTitle = Title::makeTitleSafe( NS_FILE, $metadata['baseImage'] ); @@ -131,6 +134,7 @@ class AnnotationHandler extends CodeContentHandler { if (isset($metadata['annotation'])) { $markers = []; $maskCircles = []; + $leadLines = []; foreach($metadata['annotation'] as $label => $annot) { if (isset($annot['position'])) { $attrMask = array( @@ -158,11 +162,31 @@ class AnnotationHandler extends CodeContentHandler { ); $markText = Html::rawElement('text',$attrMarkerText, isset($annot['label']) ? $annot['label'] : $label ); array_push($markers,$markText); + + if(isset($annot['leader'])) { + foreach($annot['leader'] as $line) { + $lineAttr = array( + 'd' => sprintf('M%s %s %s %s',$annot['position']['0'], $annot['position']['1'], $line['0'], $line['1']), + 'mask' => "url(#annotMask_{$svgID})", + 'style' => "fill-opacity:.35; fill: {$markColor}; stroke-linejoin:bevel; stroke-width:.4; stroke: {$markColor};" + ); + $lineText = Html::rawElement('path', $lineAttr); + array_push($leadLines, $lineText); + } + } } - } + } + $attrMaskRect = array( + 'width' => $vbWidth, + 'height' => $vbHeight, + 'fill' => 'white' + ); + $maskRect = Html::rawElement('rect',$attrMaskRect); + $markMask = Html::rawElement('mask', array('id' => 'annotMask_' . $svgID), $maskRect . implode($maskCircles)); + $svgDefs = Html::rawElement('defs',array(),$markMask); } - return Html::rawElement('svg', $attrSvg, $elBaseImg . implode($markers) ); + return Html::rawElement('svg', $attrSvg, $svgDefs . $elBaseImg . implode($markers) . implode($leadLines) ); } public function validateSave( Content $content, ValidationParams $validationParams ) {