From 62b1dc2a4b7bd90a15b8fc8a2e8da451f8565786 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 28 Dec 2023 00:26:10 +0100 Subject: [PATCH] :bug: Fix incorrect arc to curve conversion in some cases --- common/src/app/common/svg/path/Parser.java | 29 ++++++++++-------- common/src/app/common/svg/path/parser.js | 17 +++++++++- .../common/svg/path/Parser$ParserImpl.class | Bin 4529 -> 4529 bytes .../app/common/svg/path/Parser$Segment.class | Bin 1926 -> 1926 bytes .../classes/app/common/svg/path/Parser.class | Bin 8991 -> 9008 bytes 5 files changed, 33 insertions(+), 13 deletions(-) diff --git a/common/src/app/common/svg/path/Parser.java b/common/src/app/common/svg/path/Parser.java index cfceaf944..dec9ff00f 100644 --- a/common/src/app/common/svg/path/Parser.java +++ b/common/src/app/common/svg/path/Parser.java @@ -1,3 +1,11 @@ +/** + * Performance focused pure java implementation of the + * SVG path parser. + * + * @author KALEIDOS INC + * @license MPL-2.0 + */ + package app.common.svg.path; import java.util.Arrays; @@ -61,9 +69,11 @@ public class Parser { command = MOVE_TO; params = new Object[] {K_X, this.params[0], K_Y, this.params[1]}; break; + case 'Z': command = CLOSE_PATH; break; + case 'L': command = LINE_TO; params = new Object[] {K_X, this.params[0], K_Y, this.params[1]}; @@ -781,16 +791,6 @@ public class Parser { var segments = arcToBeziers(currentX, currentY, x, y, fa, fs, rx, ry, phi); result.addAll(segments); - - // if (rx == 0 || ry == 0) { - // segment.command = 'C'; - // segment.params = new double[] {currentX, currentY, x, y, x, y}; - // result.add(segment); - // } else if (currentX != x || currentY != y) { - // var segments = arcToBeziers(currentX, currentY, x, y, fa, fs, rx, ry, phi); - // result.addAll(segments); - // } - currentX = x; currentY = y; @@ -871,7 +871,6 @@ public class Parser { } private static void processCurve(double[] curve, double cx, double cy, double rx, double ry, double sinPhi, double cosPhi) { - double x0 = curve[0] * rx; double y0 = curve[1] * ry; double x1 = curve[2] * rx; @@ -911,7 +910,13 @@ public class Parser { double x1p = ((cosPhi * (x1 - x2)) / 2) + ((sinPhi * (y1 - y2)) / 2); double y1p = ((-sinPhi * (x1 - x2)) / 2) + ((cosPhi * (y1 - y2)) / 2); - if (x1p == 0 || y1p == 0 || rx == 0 || ry == 0) { + if (x1p == 0 && y1p == 0) { + // we're asked to draw line to itself + return new ArrayList<>(); + } + + if (rx == 0 || ry == 0) { + // one of the radii is zero return new ArrayList<>(); } diff --git a/common/src/app/common/svg/path/parser.js b/common/src/app/common/svg/path/parser.js index d156d6ca2..804112f07 100644 --- a/common/src/app/common/svg/path/parser.js +++ b/common/src/app/common/svg/path/parser.js @@ -1,3 +1,11 @@ +/** + * Performance focused pure javascript implementation of the + * SVG path parser. + * + * @author KALEIDOS INC + * @license MPL-2.0 + */ + import cljs from "goog:cljs.core"; const MOVE_TO = cljs.keyword("move-to"); @@ -674,7 +682,13 @@ export function arcToBeziers(x1, y1, x2, y2, fa, fs, rx, ry, phi) { let x1p = (cosPhi * (x1 - x2)) / 2 + (sinPhi * (y1 - y2)) / 2; let y1p = (-sinPhi * (x1 - x2)) / 2 + (cosPhi * (y1 - y2)) / 2; - if (x1p === 0 || y1p === 0 || rx === 0 || ry === 0) { + if (x1p === 0 && y1p === 0) { + // we're asked to draw line to itself + return []; + } + + if (rx === 0 || ry === 0) { + // one of the radii is zero return []; } @@ -877,6 +891,7 @@ function simplifyPathData(pdata) { currentX = x; currentY = y; } else if (currentX !== x || currentY !== y) { + var segments = arcToBeziers(currentX, currentY, x, y, fa, fs, rx, ry, phi); result.push(...segments); diff --git a/common/target/classes/app/common/svg/path/Parser$ParserImpl.class b/common/target/classes/app/common/svg/path/Parser$ParserImpl.class index eb42edaca5c54398efe994f6477a873c3df02aa7..e146fff62fb749455be92a4fb6fab9feba33a194 100644 GIT binary patch delta 626 zcmWO2drZ!86vy%R=UY$hdCH=qLPVJ4GBv5#GD9|2D_g5&ELt=fBbN;ola=PSpPA5@ z<{rw^+{%*cFxjwWjb+msvbDKJ3*Z0F+1cmpoL571Lv;OfSHuQ<*+?M83}q9;+01CR zFpjNGw`=*JZTPd@PInMPnK#pKgefh@!ydw^U?i19vzPJgBc1)^a)3MzvX(=3r9%lv zD5IL)9J7fUJ2}NsPTQ{5R%f`vSsFP<3m19KB|501i_7$Kl>zGILxTo!O<{O7hDJ^1 zy5iHgp=54q9=DXnZDrG>6*Q}eJK92vO1P_XT6KVXs^-3Gd7z6tR0EIH%ws*~iQ0Io zS3FZYZBDYg(Dl;3^vXH!Ugc`H)f*?&lka{@Fz>8Ir?b;@IP!xv=pu@4#`4Kpd}b~^ zEanRt^m^k0!hA}j^;yMlSI5I!oD9u4EG!ekUKmm(CTNKMoz#VJZTidL>BXqRGCp-DQCrC43iH1#Xq zxHQ9rD8WQ&rkScllc*#!OS8=irI>upHC38#4r+lpsZ>*^MaHYerb%h0Md{{+GR+$; zF&)Y>oyvAb1+`9DN`RIzRC$D1>oLkFRs~GgDw4FC6cv)HHDqWVSz7N692_rqF@37! QkE)!7LlRWvln#me4~kfrJ>_ZqG;4) znv|Hyc_q`VG%hHU7A>V!1zc1qUTx#D%DAEmuBwu2s^+@txS>Yc)JnVBxv9H!sEb>A z%x!gZ$4Pb0@PyzwUZh5C5jWB6cU_A{7|xcOu)p9!>SLilRIekYM1%;hJ!{9-k~DdMlCFhH%K zPKF0^(XFBM$;~_Y(l39$DL_WUGhU^dHl>*k%{LE~Zk}nO z=~0I1Ri-mO@b;8!{Ir-5Eg{tMj?yyXw47;L!Az}Wj#jZi`DAGgIV$q{4^Nc4gg^4| PSLIH6&#Sp>pk0Fv#h#`tm foFSf3njwKvhas8KfFXs^jUkQEpCNs+DSIFQ%RLwo delta 128 zcmZqUZ{y!!%*t!Tz`|h6z{z03z{g;^*@1NmW1F1V_%gg=@MHML;Lj+;5WpzT e5Xvac5XPv(5Xor35XI=m5X0!t5IfnFJrDqn6&D2n diff --git a/common/target/classes/app/common/svg/path/Parser.class b/common/target/classes/app/common/svg/path/Parser.class index 13d8402cf57ee7529679c676319c27f42e1df2f6..351b04b7725d058b04ee5e675aed472c50c79063 100644 GIT binary patch delta 1566 zcmYk+X>gX+6$kMD@}v;5k~d_Bga9$dLW5u_pq&U~43;P;8XKutQ5X;e6%Y`3WpgP7 z#n%Ex!X5?!VrZZ^P@xq!#I~qVpasDa3dKaDC~d?-pO3xg%bj!2+&MGnH)nNuLwUo> z1V&=D2_rjoM*?~vf@0+2T69MVZom&?$%z$7rHDgsbinmUL7&*@#D07!_G;qY@ypPW z%TdS`jctk5L3Aa=S_E8;c3guFT#F>GLn_xJ!VSn^9kRI*dEA8VtVb_y!9Z@sAijnn ze4S<7&T{^iL)pk-+`$pt$twPi)!fBja5o?39!}(&oWi}F&3$}^f8?+D7ME~8m-21C z9OXM)&i7f%160!gI>yd3ECjmGE=*VY6;zi*Df;x}9IDimi%1z^^r$7d3|8 zXdM5oN&JtdvQ5+Zou1-l&EXY2!>d{%Xql*0vg#CQo8q)fKhPi4P6rgP57j|`QGz~J zvW_W5r_@pZP@2vvqVvj7t1{K5Y(qJYSFR(f>LkugB{KPt=b+S^Ygt13XIu9o3DVr<=S`WnQeC z{TmH(tp>YJw|J|{y;HY(uPXeWhWL<%|ID9gsQ;=;AJ;IS(r};Eoj$L-{JBQ>3sw1& z?)4Q_2XVSDNY=<8Q}+is8WnWb13`fv3cBgxph#nao~#f0XhP$f$mt+D8OeGa9rXkv znt}{XMYg6PPfsFW(^04y=%JY?)>F7nv(QVk(OYxSS5frS(-@$+xJmO+rui7G1t`}- z4AHZw(sOu7&*Kp-LX#GwMN4o=FW|p=kz%DVY$}wHmzf&>UfVfa+Ef4j5c$;>iMX)@G))UOf_(>wlk(i)@TP;X(!j} z4c2Qnw`&jg>rH;3z5KKG@gu#(ziB_u=xs)u^$x$)dm)(jLl_6b;U83Ph$KHmQlvww z455tBVO8mf?$c3?3ek+#agEUlP0~qC4*@OEX)V@gs?nK{U6a=7oOXnm-qpXt>I-2s z>npW5OJ6!)Uxk9cc9FhuiN1}xmoB-t+B`ttg@i7Le7^VHy5h0A>KTR?nXa|H!GRAt z&L6v-kGQ>$yMs?U!Jj$NO-^yEQ~kX=260Xck{t;$ogNgpQ&8f};AUq970wBUIyV^R zF2P;y8dSS5xZkl^Iqmsu1i0zZmkPeQ3DqrV@+AU}aSJOv{? z72`Y&)BGgndpch94Agoi>OBkFJsWR$4)!^Ucl|W}Iu%AI!&I-pY`=;HUWr9sg$-Vf-Cl!3UWapDj}~vhMc1Lt8*$Z} z*vXsO*;`oTtt|Cx?C)*7&9C!8H*j2-o8(4(ig0HSLHt#WMM^k{|35%dthwvnp6O_h nPDn)tvXF@aWQU7B2c^ivPtX}HAe#j1fPoRE1(y*O1X~a)%BChZWizx2gNXF~xA)I`=A1cqp5NS^MH`BCu1{b> zv?5`6vn(W_71EG{mS}@^$i*+wE}EQJoRo(c+=+PPqcJ*0MZ!Fm1W4~ z(wZBIB|&5b#3%x;LL;t5Jj;>9myyCXNaI>G=Q?C^J+fGdcC12YZbVPMfBe#&sJAQbhqcLn-}R`m#M(3 zbe}8K-CNYtuc?>!=zi~4Z-1x<{C5q0(8pEilj`eJD)Ko!WQF(h6kNk6?D^6HC1WngUBc(>lvhKG}1H% z%{3O8dKOtKMYhHvSL4xM6OgBg=%`8PtUscwCgUDWL4l^Cho<3vO-CQiKwr&7k!GQv z=3toS;`fSRtmdIs3vgKraZQVGD~yPGjxlYF26oH-_0) zYbSSU7vEP64{0}#Y7hURy&=B0LSSz*a!LC_G=B?0>{q-FC|&QWrQTDvK2Qf8)Bt^? zAv&aCI;KkXM&e{4`D5%~Ybiw($7;$G^a#wxl9%={)T@CsC$3ykKpVkkap={Eu%nEuLgtz+EaJN%Oy1u>2dk{uVMJ3h#9LXhvI;6Wz`#cmPwcgtXq zTL-^(o1nzG!EYU%-6EEAY8JJ)6hy`%*3TlvrO5C&(;{O4LFn1OJ