From 9a7a0841df9af423dedd03665a68ff51acaddd47 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Sat, 30 May 2026 08:32:13 -0400 Subject: [PATCH] PPTX import: derive line stroke width from a:ln@w MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Imported lines were rendering ~25x thicker than their PowerPoint source because shape.strokeWidth was left at the _LINE_DEFAULTS value of 6 viewBox units. The Artstr line renderer treats that viewBox stroke as 6% of the layer's width, so a 4.58"-wide line shape produced a 0.27" tall "bar" instead of a hairline. The shapes were correctly positioned — they just looked like big filled bars because the strokes were huge. Fix: derive shape.strokeWidth from the source a:ln@w. Math: the renderer sets vbH = 100·lh/lw so both viewBox axes share a uniform scale of (lw_inches / 100) inches per viewBox unit. So to target an on-screen stroke equal to the source thickness in inches, set: shape.strokeWidth = (stroke.width_in_inches / lw_inches) · 100 The renderer's internal clamp to [0.5, 50] viewBox units acts as a soft floor / ceiling for very wide or narrow lines (a 0.011" hairline on a 5"-wide horizontal line bottoms out at ~0.5px thick — visibly a line, just slightly thicker than source). User-visible: re-importing gallery_template_layout_set.pptx now yields lines at roughly their source thickness — the bottom-of- slide #69746C hairlines look like hairlines, not bars. --- src/pptx-importer.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/pptx-importer.js b/src/pptx-importer.js index 8ef0059..5c8238f 100644 --- a/src/pptx-importer.js +++ b/src/pptx-importer.js @@ -1096,14 +1096,20 @@ window.ArtstrPptxImporter = (function () { // Quirk of the renderer: for shape.kind === 'line' the inner SVG // uses the layer's *fill* paint as the stroke colour, not // the layer's `stroke` field. PPTX puts the line's colour on - // a:ln, so for lines we copy the stroke colour over to fill. The - // shape.strokeWidth from _LINE_DEFAULTS (6 viewBox units) drives - // the on-screen thickness; deriving from a:ln@w would need to - // account for preserveAspectRatio="none" distortion which is - // out of scope here. If lines come out too thick / thin the user - // can adjust strokeWidth on the layer. + // a:ln, so for lines we copy the stroke colour over to fill. + // + // Thickness: the renderer's viewBox is 0..100 (x) × 0..vbH (y) + // where vbH = 100·lh/lw, deliberately picking vbH so both axes + // share the same in/unit scale (lw/100 in per viewBox unit). So + // shape.strokeWidth = (stroke.width_inches / lw_inches) · 100 + // gives an on-screen stroke that matches the source PPTX a:ln@w. + // The renderer's hard clamp to [0.5, 50] viewBox units becomes + // the effective floor / ceiling for very wide or very narrow + // layers (a hairline on a 5"-wide line floors at ~0.5px thick). if (shape.kind === 'line' && stroke.type === 'solid') { fill = { type: 'solid', color: stroke.color }; + const refW = bounds.w || bounds.h || 1; + shape.strokeWidth = (stroke.width / refW) * 100; } return {