From 6f5b721fe56fe6e3735d03b07e3716fc39572639 Mon Sep 17 00:00:00 2001 From: Martin Haug Date: Thu, 17 Mar 2022 10:50:51 +0100 Subject: [PATCH] CR: I'm gonna make him a refactor he can't refuse --- src/eval/array.rs | 5 +++++ src/geom/angle.rs | 4 ++-- src/geom/point.rs | 6 ------ src/geom/transform.rs | 5 ++--- src/library/graphics/line.rs | 29 ++++++++++++++++------------- src/library/mod.rs | 14 +++++++++----- tests/ref/graphics/line.png | Bin 3467 -> 3472 bytes tests/typ/graphics/line.typ | 27 +++++++++++++++------------ 8 files changed, 49 insertions(+), 41 deletions(-) diff --git a/src/eval/array.rs b/src/eval/array.rs index 294d28711..5cd8df821 100644 --- a/src/eval/array.rs +++ b/src/eval/array.rs @@ -80,6 +80,11 @@ impl Array { self.0.iter() } + /// Extracts a slice of the whole array. + pub fn as_slice(&self) -> &[Value] { + self.0.as_slice() + } + /// Return a sorted version of this array. /// /// Returns an error if two values could not be compared. diff --git a/src/geom/angle.rs b/src/geom/angle.rs index 4e08a518a..b4d6f79ab 100644 --- a/src/geom/angle.rs +++ b/src/geom/angle.rs @@ -40,12 +40,12 @@ impl Angle { (self.0).0 } - /// Get the sine of this angle. + /// Get the sine of this angle in radians. pub fn sin(self) -> f64 { self.to_rad().sin() } - /// Get the cosine of this angle. + /// Get the cosine of this angle in radians. pub fn cos(self) -> f64 { self.to_rad().cos() } diff --git a/src/geom/point.rs b/src/geom/point.rs index 7ab0d3753..6d77507b4 100644 --- a/src/geom/point.rs +++ b/src/geom/point.rs @@ -49,12 +49,6 @@ impl Point { } } -impl From> for Point { - fn from(spec: Spec) -> Self { - Self::new(spec.x, spec.y) - } -} - impl Get for Point { type Component = Length; diff --git a/src/geom/transform.rs b/src/geom/transform.rs index eed51d460..5bc05d84e 100644 --- a/src/geom/transform.rs +++ b/src/geom/transform.rs @@ -36,9 +36,8 @@ impl Transform { /// A rotation transform. pub fn rotation(angle: Angle) -> Self { - let v = angle.to_rad(); - let cos = Relative::new(v.cos()); - let sin = Relative::new(v.sin()); + let cos = Relative::new(angle.cos()); + let sin = Relative::new(angle.sin()); Self { sx: cos, ky: sin, diff --git a/src/library/graphics/line.rs b/src/library/graphics/line.rs index 141abb08b..a650c76c2 100644 --- a/src/library/graphics/line.rs +++ b/src/library/graphics/line.rs @@ -2,18 +2,21 @@ use crate::library::prelude::*; /// Display a line without affecting the layout. #[derive(Debug, Hash)] -pub struct LineNode(Spec, Spec); +pub struct LineNode { + origin: Spec, + delta: Spec, +} #[node] impl LineNode { /// How the stroke the line. - pub const STROKE: Smart = Smart::Auto; + pub const STROKE: Paint = Color::BLACK.into(); /// The line's thickness. pub const THICKNESS: Length = Length::pt(1.0); fn construct(_: &mut Context, args: &mut Args) -> TypResult { let origin = args.named::>("origin")?.unwrap_or_default(); - let to = match args.named::>("to")? { + let delta = match args.named::>("to")? { Some(to) => to.zip(origin).map(|(to, from)| to - from), None => { let length = @@ -27,7 +30,7 @@ impl LineNode { } }; - Ok(Content::inline(Self(origin, to))) + Ok(Content::inline(Self { origin, delta })) } } @@ -38,23 +41,23 @@ impl Layout for LineNode { regions: &Regions, styles: StyleChain, ) -> TypResult>> { - let target = regions.expand.select(regions.first, Size::zero()); - let mut frame = Frame::new(target); - let thickness = styles.get(Self::THICKNESS); let stroke = Some(Stroke { - paint: styles.get(Self::STROKE).unwrap_or(Color::BLACK.into()), + paint: styles.get(Self::STROKE), thickness, }); let resolved_origin = - self.0.zip(regions.base).map(|(l, b)| Linear::resolve(l, b)); - let resolved_to = self.1.zip(regions.base).map(|(l, b)| Linear::resolve(l, b)); - - let geometry = Geometry::Line(resolved_to.into()); + self.origin.zip(regions.base).map(|(l, b)| Linear::resolve(l, b)); + let resolved_delta = + self.delta.zip(regions.base).map(|(l, b)| Linear::resolve(l, b)); + let geometry = Geometry::Line(resolved_delta.to_point()); let shape = Shape { geometry, fill: None, stroke }; - frame.prepend(resolved_origin.into(), Element::Shape(shape)); + + let target = regions.expand.select(regions.first, Size::zero()); + let mut frame = Frame::new(target); + frame.push(resolved_origin.to_point(), Element::Shape(shape)); Ok(vec![Arc::new(frame)]) } diff --git a/src/library/mod.rs b/src/library/mod.rs index 88f003c2d..505f1a1d1 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -174,11 +174,15 @@ castable! { castable! { Spec, - Expected: "two-dimensional length array", + Expected: "array of exactly two linears", Value::Array(array) => { - let e = "point array must contain exactly two entries"; - let a = array.get(0).map_err(|_| e)?.clone().cast::()?; - let b = array.get(1).map_err(|_| e)?.clone().cast::()?; - Spec::new(a, b) + match array.as_slice() { + [a, b] => { + let a = a.clone().cast::()?; + let b = b.clone().cast::()?; + Spec::new(a, b) + }, + _ => return Err("point array must contain exactly two entries".to_string()), + } }, } diff --git a/tests/ref/graphics/line.png b/tests/ref/graphics/line.png index 49f05f0d790e7e426535a2ede1db4b2ad990bfb3..7858b5c9a734ef9f957b4467de3de98ec9bf26f3 100644 GIT binary patch literal 3472 zcmb7H2UJr@7Y^VCe+XTq3J3zCAVd@vse;HNnR8g9ON+;9>fu*V> z6lqyBQY7>qzz8c%NNAEEq5O~4|NMH6d(Q4V@7+5y-<`SN+&kyK_hPTWjkq{OIY1x~ zm+>zb%s?QP1Hg0UAS*Cp$V*-U#;+P*IByX^re+6PSU5?B?}XV@rdT_VZPmYL#Ud~K zg3fz_#h$Fw<1c#o;qGkCQ{zjX3h270({bS(n?JQPB96!9Ni~?nJ-#Q)n|_a#(&ybR zG6&*5-5p|-Gp7~y2lZX77$d`(*7W+BsSM!sn=8BxR&X)C6qIwQw6rvaC0rQvPlc!} zBz3J1fx%!B1RSKmz-=eT0_A1nWrKnM1%iV9fv`eAz9F;UEQ&DM{DUe?1QGQhdXOI| z5D}yY`JqUaFc9Qpg$^<(mmn*St@a)swpLc{%B-S6kR#`A=dnvgH5@v8xSx&p^-k9U zOU(IN4Q&u~-V4s72eJGFBHGvO_j}oR4Y)D~fNgy3P#1xrubq8m(Fa)Asu#0MfrG;3 zHKUB~ON0y0v&2OFog(!aT)Dzauy*Z*x?=JUNP$5PpnoL7!GdhxMMN(|zWJX`D4g-qtn>pt8OsKcSwz7>|3?dRW~u~c zXndihLA1V%?|P-*(zIhAW_8~fDB*tg7-*z%fBwXt!aze;gSIB53sus?0W zx+Zus|BbHAr-Zur%o>c>F9^C}W_JS79+4YbX=!M9|03VmoU%1x(Y2)QvGm24urWzt z@?>S0&!u|9HeR3kk*QMx!H9CyW`!~|-7*cD#2WePOx$M6h*wL#U}_LVL0aWF$%%9< zUi#Ed>cDV)@qOAG^LQizfj}R+?!LE>fhz%gG1#LLd@}P*iA-&VJtE#K=|h9WaZx22RvE*VQf6ZuAZ!=S=FKY{<`k3!Op|?h3q`No=_oTi`6#gy(np~hv;ckT_(!-NpMjs6hi6jGlcqhr z^dy`+jP4_fpw>)Mw?^=>Nw`Jz^;Ans%Q12oI_JoOdT&K(>03<4M{KBsyvqpsnV?!| zUun@sHH|Fbqo&byjlefWaPkjo4Focb-U`ghvdtvC8@pv-*f`KyS+tRzWy|Ect(k^h zzy%+HY7xhL353KX_c@hb3!XZ3e3+v}`Ah!`eCLlE0hzv8YJ@3#(-3Q{Fx%W*b};&# z!P?qdF(xqcBTF=d(dbvURG=dhkl~nIF|Kh;u27LNd8MZ<5Lf7dMiH=T_Wrs`BT zHg4mt=WGOvkGx3Yd=LlQIAD79Y@F3xtr8HO2el1D>)zXHo+G+Sa7gR9u&FgpA!Xf< zi#Jw33#qQHbJjP`mD4L`5x-5D4mCel>#razacc1v(UF&@M*SUIHVATIP47)}--}oE zpv;(B(XzQPH01^39(evK;SO0)-IsVwA3Pb`i{BH{7&2}`t%vwy>G^)mrci5WFd zED6)sT{JQ@L6NM%*7?qLtM=5&fdw+tlO0G4$#HRU#kuaXi_l|a8%E zXK?UU&ogvqjDt#ws39IbE+a4h3@(}WWI$s*B=lN!30%_e@xZ--4xkQ*F`jgzm?XPh)^omY42)suDix} zg9}Ao(8)7_6qyyo2&~3xACau%E9k^@fByW_eZx00Mj?fS?J*(pL~{tT`^J2>+MU3_ z&tT5tUy%XQI?$PGQ7z2fKAJhqk7ax?P6XE&WTPG|%)_bC)dM?Bg(Y$DyW@)e&FbmUPEDEhySo%z|LzpTK_%Y2Seg9XEt-bp z;}gN5;|aSQC|Cw#e5Q=5NguYI!dmB^Y<^^7NNmmaS<*CPEZo1ox9#gbAG5l3a_OB| z{$5gal+h3a!EKIV+*=r*MGT;GW z0kP!|OQlT{=GNBMRKIIw+>&;60fBGv_sN~e!a{W?%_y73p^dFvbv#Phx`w_PI}lZS zYw=QdkMex*@+tmDt9C$5Y_E|?BG^6e(A8t^Ri@vN4?&baThPBp>&iT+%kL5Jr#5uZ zGG5v)q@WX}&QTqvJMDV=8dcs(ZM)GNlYLbBbWtTkN6S+lmc6$=YYWR9&(iX1#dMUC zQHP5Pow~3%JaB9i6V1jPeil74r)5vdJ1Q|VGXs}w7{p`gj;-;pq&1@>as-_Bs&42) z2S;L)=D>4zr zPs^P?QA5#Fx2Eg!DHDcY)YUm=Q)*UZ`dZ5=+Z)|Lu`&r6J}i{RYY-Bzn_*#PvHjen zhG+Dtb+q|^Tud%G1;U4pPZwVG0AA)?I-9xYJchy^V+;-7RBBf>G8_FhJ0|k;35#2+ z;9S8)uS16|G2jg0ha14_vlyckI%ux`4uWht=pM<^k9~1Ll{mR61LixT}NSG4O>S2;cVq z`#AMCJ^%_>fI{V*9Kh`x=YPj7%+rAz@8-yT#y2l^s`<-SwWNIW%7DFdebQ$0&Eo=s zV-U8_tAZ3Udo$7gFWZ(Yvw9}L`j)90y;Z>8&pL7AEda+bASWqbQ??&^AT){J!22ot zUuJ5AzT|FynSDDT4&dzX5(91#cb(M}_!pnBylnhzP$}Tg;)lv1~0i+k+$ W`gL~-0=IkiF=Ipcg-U(PuQzxnptd@tv`d+&em{ojAix$h-hFgJ!A7CsCD zfglJI14|HyN9q6I;J*9d!Z zV0Jvpb92Qi`J9h{fon#V1}L4O1!){sWo)+Ydj>M7{~(a0USj0;~Sn zft*1{!2i+Ic3(Jq9nKNJBzA!;+&IR^$8Cw3=x@}v1+{~h47lJNxFJmKM^KkvRB$-R zd9czP=!z>JVdXvx(FH*TzqEm2C+Gd)0=6Syz?I^K{?!2b;)H>w$HEeTgLAFBbg!2V z0#6J~|0{P*Cj46nWKNSkNgM3Il@96x!8!h(87y`FH*J);gb_#dsZ*};T)OC`cesJd7uYlC$w>a$Sw1zJpv~` zKhwo^u8c7@yQt2vH|occD<#3E-Rq5_fq2X>aGnBS0h_TI=L7sQ$9bE6Svsgw=PmqChrz0lSpf8 zPw6|jz0|E{&Mv1RiZHM6qJ~?l5pUMjJ}h?Hm=N)~te99{Uap?H;7VJ}t`@@J7fm{R zNDos6O_HRqu5;N`c^rh=d~8Hrya*essWsx=lh^EbC>SrYs2@t>yl%MI))qO3X-?ig zF`dGY><5z6-yaarNlqAv_SH9PRm}G*fpfpI^;iiQ8I#T>ZYy0PEQ6tTBTZh z9dI9DI1)qx=-VsqXpa*5?zyY_uQ|87oFuQ{^lYK;1KOJii)`g*Hb@yd#d^m~^U z+xFIrE+dXvjWzHqcD8aEKVN9)FQ4$uQ+Jnx+VmtQM&)_UI5LSg&AwF9FXS>G+|2>| zR;fZ~h(u$^3ax&!rLqpf(;RXm`9oeA6ZO&GPxnsx8IDZ9g({_^w?)+>A66DoH~31% z>YAVR7qB|c;yEM^y=s`H3XvcAoHYpB>HFT!Rz%MdiTvzFb?jPi;MWO>jog?!S;Q8_ zWbBH()2(ff6NQD`goRi-*g-=}DM~|3)$j`hYkB!Nvl#u2Lx|d(w1~H{SvtbRQ&B^k zq>8D@i|0*FkF`!5%lsw7pQ-CePebSi`cAA~nB|wbb3ZjR^mOBP@Yb;c@p|VT7d)wbZd>^VQoT3u&IkU2w zgi^!0re);TGvN=*D6GT-fPHpGukEvSWLe8_DPwN>#NujR`LMT3KaT zjhK4GR&Whvw70hxh?wi1DD9`TS{cIpuAv4pNqYRCx2ehLt;yHAE_?T*lXN&N(6+DY z#FnirN3!VHl%2pC?`e4{DP#UDtMp)yf_imgd?J29gc{xyOm9nJy~Eu0<>zEI5KBO4lA5(anH;mi>h^1>wEnY z6x=hQ^m(%!oBkwlEm!1}aMr7LV~P-4ua1XW7dP3{1E@LD+99hrMJe|(vIWG!ALkc3 zn5Wz?`(o=^=J*hF!>(?HNZA~5Q|#|+epQUe5?0V9Pp_OiwN9A?aws7GAxlc)MF7qF2#E^6q zo*#Y^pDmUPQ^Hj(M%2EkZxZ0ctxko_@6?@}NeN?*dR2!ZVZj8sDU=*Qjr#pRD4h3__MbUB$*NHn_tSTPtss-G>J zZ(dDRt!b0U`e6xG<4M+mwO8p&bRGo<%9+dLuT0Zai`Za0K@}URsi(LF<}_>{M4)Z( z7cThqeey@#Qorg|!aPE-M9b@uPhR>kA~4%6b2$=8WJW7O@4jr-l>1IVKuGtL>tqKX zLT-`rBq@2oD8gKQ;-Gh+yc=ng;mJVF;tV8t^q*dSewzvtCz2pqchZNu-^PeQn_4MI zB(g$5PE2b_zOy?Y|6qFMb$!B9`$QmNsR!zW^a73_b?Y2x{^-8Cr+nHY^WG(E6zW9a z_YyjJ-l4EqV(SNpPr~Xer{^ch%lFyiqHrd(8>;Dbhnm=57#cn^s`qwrdB5QMniB%! zZE(H)7N#pIG^;X|BS^Y(=AGOP7OAa#M?VIA&92kvmZrVaz>Hs~*BB6%0PLJ{JZ`2pw9HxKDsFyDnX$0yz^zyX(peLKFkQCRryG41ho zL=x>6p&+;?9S0N#kWq_!Wd5k-hrrvUSkYjC>~gbI%Ky2h3G+2ZnkPTy{lfdl&9`hE z92kRi)(UNWC{RCgBLYi`IY7ZkgBvl@P|u~$`I>9KGrjZg%T(J;QDb}UYb4UtrNB%L ztg96Y^|*!+p{6+Gxqeqt(J><S$4_8FTUq+)GnX*)p#alNWAEU|jw{<8OFf_|oglO8IPLU5R$dC;z z$YxczI1lH$24INCvswE@JsMTm?g_pJFoYMP9`o=Vx_TFYS5DU&B*n^=dFEI?NdY~ooG sVgyqJ|HAF3+3#}{_*lRGREF#Bz&