From bce415364036f8cc06309934aad5c064c63a6836 Mon Sep 17 00:00:00 2001 From: Egon Elbre Date: Sat, 4 Feb 2023 23:44:52 +0200 Subject: [PATCH] internal/stroke: fix line overlap When the line overlaps itself backtracking exactly, e.g. path.MoveTo(0, 100) path.LineTo(100, 0) path.LineTo(0, 100) then acos calculation is relatively unstable. By using atan2 it avoids some of such problems in the calculation. Additionally, it simpliflies the round join calculation. Fixes: https://todo.sr.ht/~eliasnaur/gio/474 Signed-off-by: Egon Elbre --- .../rendertest/refs/TestPathReuse.png | Bin 1278 -> 1309 bytes .../TestStrokedPathCoincidentControlPoint.png | Bin 1895 -> 1756 bytes .../rendertest/refs/TestStrokedRect.png | Bin 564 -> 584 bytes internal/stroke/stroke.go | 39 +++++------------- 4 files changed, 11 insertions(+), 28 deletions(-) diff --git a/gpu/internal/rendertest/refs/TestPathReuse.png b/gpu/internal/rendertest/refs/TestPathReuse.png index 7a178e546633c6c327a1840e19faeb96c2e368e6..f16df74143324bf4b2a7d456c78737bd2e7939ea 100644 GIT binary patch literal 1309 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7xzrV0q%{;uumf=gqAB-7%pOZTEGK ztz;4GiMT1P>ys*wB+Y%WN;>fMj+5~Uuk97YGE22Rm9PCw)Q#p;y3yh4p;IDSlALgS zX650T*5=h^-_pLF>#sgn{_eY7LBjKQd&|$A`<~MF@T6Evwn{@WCX(SaxWlA2KP3Cb zi}zy2JGduo-a5P5TuF0}6z~4H@Z$GgDv5uj4m7hd@~yhxDfhX8pw0E&xehn+)?4?l$2UMV+t!kFjs{%iBj^^E4rp1ZW?J-xR#f;+C;{&xMLdw0tBA6)sq>EWE6 z&ex0nizcc5`1WOPt=WnEjrCbKe3@EA&-Kd5g?<-eHLQ|+@VBaC{=@RV4{6zqhju=k z_2R|p&+X1nM6#~J@0EI#IF@7=KBkm1?Ek|rKgaTp8PGZJMBhou-daB|SmI&Ilgf^}Va>VP4iQ~$X_;L%Z`*eD zFoc+FI`Kp4fcsa6K4pJ%CKH#%?pNhp*u-4ttz!u=F*>s7#O1jlMF*Z-u25U9?7y99 zgP~NbZ70i?PMf>j4z7!3w)EO$0+o85GWm38W&E3?6V-bea{AoLMS86gXP%hs$Dk#( zG~won$zec7=}E1L>U$Zw+~#h`dg7_iAlkbt;p&OW?m(&BNu^5uc8n`Bws7u9dva3S zq1a^6qCjguw|TF%UFY3l3c2`V*P@GBGVb%VwcY3aVJZ;oU8fn-w!OAz>4)ZT+gg()9W=OxNk@`f_l_4BVyEFXia9gSDAIY@g z{>6^zm)+-mVo4}A*)^xSD*KX1<-HUCoT5b)_L$jrxmhav&t%#Ve^Dd-iDo#%H)W}( zeKx7w2Qp1|iQDUFN=0_qJmn6^Fxezjc}lz?)lFG@;&OSW4Qnz|G(UZDXP73~yT)~1 z9cO}#RAi4$t?+>olT8wpztkCW-IP~PTt1)aLYT=WnaW?<47o1KuO}|Q&r~AWdv0#+ zsf(2lekRsDk^a-c{i9m={CtsZzngtOvBw=UyVu2km-Sx_{|)dd5q#+*&~z_&1yqQj*Vm!DNI7iH*jtJ|UXiAS43wAW^X&L9u*x>EOE9FjKnnm}o91Rpmd~o7%Jj1a*H)r>GHY^EeGECf_oOEwUxR|l##N^2g3m09Cn5eGL zD4{IXD_QwTxFOYj@kV9;c}yG5WK2=|^hDbs@uEiPlat{L(}13KowtWILGq$T>XVc4 z49{eHgWTsCv79iGs_d{yk+ESIBHmRHkY!(HIR?fR-KEv$O6!im5 z8DFjhntT$g^b$Ex3ZhSmG}tY^_+|62v_CHMidY{U%1ANxXu5tPcpJkP!Co8pd7oG% zjHGhc+AZZ0wrBdW!0wZ5-9g2KVoc;cvF? zY3~#@vH!N3f8U;c%>EiiNP1{ diff --git a/gpu/internal/rendertest/refs/TestStrokedPathCoincidentControlPoint.png b/gpu/internal/rendertest/refs/TestStrokedPathCoincidentControlPoint.png index f589f753dc5d8d55af052a8466701ee8679b6fb5..6011a09d54aa8c824bddd8aeeb288c4329e50b45 100644 GIT binary patch delta 1741 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 TH&ooQ00000NkvXXu0mjfFvMN- diff --git a/gpu/internal/rendertest/refs/TestStrokedRect.png b/gpu/internal/rendertest/refs/TestStrokedRect.png index 77b74a46ed85508d5fde8049910bde7bdf58fafb..27c1c918d51c4552ab8c6f19f3329c144f4147b8 100644 GIT binary patch delta 323 zcmdnOa)M=ovJ(@(r;B4q#hf>H4gItYMcf|Ne~Rl~;c-~&2H(O&S(8M~jyLV07aUrH zoCUaYyAqAIy_@sd)Wc-oVwscc-h{TKF%(RG$Y?oPfQbtWW=;RT|2so)t=j9*qUlc- zeb-6f^xv!O|D^3=-MqSDGfyk-^!haE$u6Myw^>ipJnlV@Tk%V5L*#@0`S z#V~y@`;5TJ`K#p`)U@h3Y!Yu*H%#1hcJ~p6ZO)%=RCgHi9k-8FD&U@&nB^D!B=%tY zJ>j0`sTb?F*nRw;wY{}GxR!gzTU&?HtIQRzY!CF!df@JrG`cyc47^yCCaIq5s)3=9na|0jHw6}q*wv>M1^ N@O1TaS?83{1OPqhkaqw8 delta 285 zcmV+&0pkA11hfQ@BRT>5Nkl= 0.0 + angle := angleBetween(n0, n1) switch { - case cw: + case angle <= 0: // Path bends to the right, ie. CW (or 180 degree turn). c := pivot.Sub(lhs.pen()) - angle := -math.Acos(float64(cosPt(n0, n1))) - if !math.IsNaN(angle) { - lhs.arc(c, c, float32(angle)) - } + lhs.arc(c, c, float32(angle)) lhs.lineTo(lp) // Add a line to accommodate for rounding errors. rhs.lineTo(rp) default: // Path bends to the left, ie. CCW. - angle := math.Acos(float64(cosPt(n0, n1))) c := pivot.Sub(rhs.pen()) - if !math.IsNaN(angle) { - rhs.arc(c, c, float32(angle)) - } + rhs.arc(c, c, float32(angle)) rhs.lineTo(rp) // Add a line to accommodate for rounding errors. lhs.lineTo(lp) }