From d547cdf66f0118dc9c5093399f19d16075cb29ca Mon Sep 17 00:00:00 2001 From: sakamotch Date: Thu, 26 Mar 2026 22:34:15 +0900 Subject: [PATCH] Fix incorrect lineJoin and pathfactor in get_drawings() Bug 1: lineJoin was multiplied by pathfactor. stroke->linejoin is an enum (0=Miter, 1=Round, 2=Bevel) and should not be scaled. Note that lineCap is already correctly handled as plain integers without pathfactor multiplication. Bug 2: pathfactor calculation only handled some transform patterns correctly. Use sqrt(abs(a*d - b*c)) so uniform scaling with arbitrary rotation is handled correctly; for non-uniform scaling this yields the geometric mean of the scale factors. Fixed in: - src/extra.i (rebased build) - src/__init__.py (Python fallback) --- src/__init__.py | 8 ++------ src/extra.i | 11 ++--------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/__init__.py b/src/__init__.py index 1256fc450..7414983a4 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -23208,11 +23208,7 @@ def jm_lineart_stroke_path( dev, ctx, path, stroke, ctm, colorspace, color, alph #log(f'{dev.pathdict=} {dev.clips=}') try: assert isinstance( ctm, mupdf.fz_matrix) - dev.pathfactor = 1 - if ctm.a != 0 and abs(ctm.a) == abs(ctm.d): - dev.pathfactor = abs(ctm.a) - elif ctm.b != 0 and abs(ctm.b) == abs(ctm.c): - dev.pathfactor = abs(ctm.b) + dev.pathfactor = math.sqrt(abs(ctm.a * ctm.d - ctm.b * ctm.c)) dev.ctm = mupdf.FzMatrix( ctm) # fz_concat(ctm, dev_ptm); dev.path_type = trace_device_STROKE_PATH @@ -23228,7 +23224,7 @@ def jm_lineart_stroke_path( dev, ctx, path, stroke, ctm, colorspace, color, alph stroke.dash_cap, stroke.end_cap, ) - dev.pathdict[ 'lineJoin'] = dev.pathfactor * stroke.linejoin + dev.pathdict[ 'lineJoin'] = float(stroke.linejoin) if 'closePath' not in dev.pathdict: #log('setting dev.pathdict["closePath"] to false') dev.pathdict['closePath'] = False diff --git a/src/extra.i b/src/extra.i index d2d96811a..6ce80c481 100644 --- a/src/extra.i +++ b/src/extra.i @@ -2719,14 +2719,7 @@ jm_lineart_stroke_path(fz_context *ctx, fz_device *dev_, const fz_path *path, jm_lineart_device *dev = (jm_lineart_device *)dev_; //printf("extra.jm_lineart_stroke_path(): dev->seqno=%zi\n", dev->seqno); int i; - dev->pathfactor = 1; - if (ctm.a != 0 && fz_abs(ctm.a) == fz_abs(ctm.d)) { - dev->pathfactor = fz_abs(ctm.a); - } else { - if (ctm.b != 0 && fz_abs(ctm.b) == fz_abs(ctm.c)) { - dev->pathfactor = fz_abs(ctm.b); - } - } + dev->pathfactor = sqrtf(fabsf(ctm.a * ctm.d - ctm.b * ctm.c)); dev->ctm = ctm; // fz_concat(ctm, trace_device_ptm); dev->path_type = STROKE_PATH; @@ -2739,7 +2732,7 @@ jm_lineart_stroke_path(fz_context *ctx, fz_device *dev_, const fz_path *path, DICT_SETITEMSTR_DROP(dev->pathdict, "color", jm_lineart_color(colorspace, color)); DICT_SETITEM_DROP(dev->pathdict, dictkey_width, Py_BuildValue("f", dev->pathfactor * stroke->linewidth)); DICT_SETITEMSTR_DROP(dev->pathdict, "lineCap", Py_BuildValue("iii", stroke->start_cap, stroke->dash_cap, stroke->end_cap)); - DICT_SETITEMSTR_DROP(dev->pathdict, "lineJoin", Py_BuildValue("f", dev->pathfactor * stroke->linejoin)); + DICT_SETITEMSTR_DROP(dev->pathdict, "lineJoin", Py_BuildValue("f", (float)stroke->linejoin)); if (!PyDict_GetItemString(dev->pathdict, "closePath")) { DICT_SETITEMSTR_DROP(dev->pathdict, "closePath", JM_BOOL(0)); }