From 1661c1791aef1688ca1a1f79e4fc915da0546fe9 Mon Sep 17 00:00:00 2001 From: Johannes Wolf <519002+johannes-wolf@users.noreply.github.com> Date: Fri, 18 Oct 2024 13:51:21 +0200 Subject: [PATCH] Add fill-rule style key (#722) * line: Add fill-rule style key * changelog * tests: Update ref images * docs: Mention new fill-rule style --- CHANGES.md | 5 ++++- docs/basics/styling.mdx | 4 ++++ src/canvas.typ | 1 + src/draw/shapes.typ | 6 +++++- src/drawable.typ | 4 +++- src/styles.typ | 9 +++++++-- tests/line/fill-rule/ref/1.png | Bin 0 -> 3323 bytes tests/line/fill-rule/test.typ | 24 ++++++++++++++++++++++++ 8 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 tests/line/fill-rule/ref/1.png create mode 100644 tests/line/fill-rule/test.typ diff --git a/CHANGES.md b/CHANGES.md index 0413e4ca2..56f2a526f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,10 +1,13 @@ # 0.3.1 +CeTZ 0.3.1 requires Typst 0.12.0. + - Added a new `padding` parameter to the canvas element. +- Some elements now support Typst 0.12.0 `fill-rule` style. # 0.3.0 -CeTZ 0.3.0 requires Typst 0.11.0 +CeTZ 0.3.0 requires Typst 0.11.0. The licence changed from Apache-2.0 to LGPLv3. CeTZ' plotting and charting functionality has been moved to a separate diff --git a/docs/basics/styling.mdx b/docs/basics/styling.mdx index c017d3778..c64d7ac70 100644 --- a/docs/basics/styling.mdx +++ b/docs/basics/styling.mdx @@ -20,6 +20,10 @@ You can style draw elements by passing the relevant named arguments to their dra documentation for more details.](https://typst.app/docs/reference/visualize/line/#parameters-stroke) + + How to fill self-intersecting paths. Can be "non-zero" or "even-odd". + [See Typst's path documentation for more details.](https://typst.app/docs/reference/visualize/path/#parameters-fill-rule) + diff --git a/src/canvas.typ b/src/canvas.typ index 57c7df766..cebefb64c 100644 --- a/src/canvas.typ +++ b/src/canvas.typ @@ -126,6 +126,7 @@ path( stroke: drawable.stroke, fill: drawable.fill, + fill-rule: drawable.at("fill-rule", default: "non-zero"), closed: drawable.at("close", default: false), ..vertices, ) diff --git a/src/draw/shapes.typ b/src/draw/shapes.typ index f52779cb5..dcea8f0d9 100644 --- a/src/draw/shapes.typ +++ b/src/draw/shapes.typ @@ -553,6 +553,7 @@ let drawables = drawable.path( (path-util.line-segment(pts),), fill: style.fill, + fill-rule: style.fill-rule, stroke: style.stroke, close: close ) @@ -1223,6 +1224,7 @@ let drawables = drawable.path( (path-util.cubic-segment(start, end, ..ctrl),), fill: style.fill, + fill-rule: style.fill-rule, stroke: style.stroke, ) @@ -1325,6 +1327,7 @@ let drawables = drawable.path( segments, fill: style.fill, + fill-rule: style.fill-rule, stroke: style.stroke, close: close) @@ -1402,6 +1405,7 @@ let drawables = drawable.path( segments, fill: style.fill, + fill-rule: style.fill-rule, stroke: style.stroke, close: close) @@ -1492,7 +1496,7 @@ } let style = styles.resolve(ctx.style, merge: style) - let drawables = drawable.path(fill: style.fill, stroke: style.stroke, close: close, segments) + let drawables = drawable.path(fill: style.fill, fill-rule: style.fill-rule, stroke: style.stroke, close: close, segments) let (transform, anchors) = anchor_.setup( name => { diff --git a/src/drawable.typ b/src/drawable.typ index f7e6d0194..615bde394 100644 --- a/src/drawable.typ +++ b/src/drawable.typ @@ -36,9 +36,10 @@ /// - segments (array): The segments to create the path from. /// - close (bool): If `true` the path will be closed. /// - fill (color,none): The color to fill the path with. +/// - fill-rule (string): One of "even-odd" or "non-zero". /// - stroke (stroke): The stroke of the path. /// -> drawable -#let path(close: false, fill: none, stroke: none, segments) = { +#let path(close: false, fill: none, stroke: none, fill-rule: "non-zero", segments) = { let segments = segments // Handle case where only one segment has been passed if type(segments.first()) == str { @@ -58,6 +59,7 @@ close: close, segments: segments, fill: fill, + fill-rule: fill-rule, stroke: stroke, hidden: false, bounds: true, diff --git a/src/styles.typ b/src/styles.typ index 98c7bb096..f746db3b4 100644 --- a/src/styles.typ +++ b/src/styles.typ @@ -2,6 +2,7 @@ #let default = ( fill: none, + fill-rule: "non-zero", stroke: black + 1pt, radius: 1, /// Bezier shortening mode: @@ -69,11 +70,13 @@ line: ( mark: auto, fill: auto, + fill-rule: auto, stroke: auto, ), bezier: ( stroke: auto, fill: auto, + fill-rule: auto, mark: auto, shorten: auto, ), @@ -82,7 +85,8 @@ mark: auto, shorten: auto, stroke: auto, - fill: auto + fill: auto, + fill-rule: auto, ), hobby: ( /// Curve start and end omega (curlyness) @@ -90,7 +94,8 @@ mark: auto, shorten: auto, stroke: auto, - fill: auto + fill: auto, + fill-rule: auto, ), rect: ( /// Rect corner radius that supports the following types: diff --git a/tests/line/fill-rule/ref/1.png b/tests/line/fill-rule/ref/1.png new file mode 100644 index 0000000000000000000000000000000000000000..03687335ad8cb527d6e22f54c040b527110a1695 GIT binary patch literal 3323 zcmb`JeN+=y8pcPZAaX)z5m7;cRg4rBT+~!0L_|c25I~R$N)Xy2UxpPGDwQc>{bCWc zet|VX1VK>(2PFoS@e^7th9qc#2xCPgL1Ku80F%tj-qE$EYyaA_os*n9ci#KF@142N z{mmQ<3HGN=nm!4FAX>nhRbdb`4hDZ>;skKTcPB9yba)|a!~IBbym_tFYDr}$ilSs& zD=Ga|dmE8TrR1dwvZ?|>5b1^U(#mr3SiVRkLVhYjP8SJy6}B(b}YV zZDL$uVPQc*fpE|FWRNepb|nnM(&&i79q9!-(n+5sNCX!N57x3h)6&xTe7-1n4Z74r zx_Dk%bQC{ogK)J^Y-}u#$Ah+aA`4xi)CYx}<)Zm6yr8wvH%%cSAzUt3==v!XQv*ew zgCa`{T^K7?tbjs}b2uD$rUMjk01DX8@$^iaF_k}KDzq{S^4S$KduGV2nI0Y-DGICue;r3 z=jqd-87vQ)6*OZBG{qH~GS|k&hHhiyY-vHK(-{*j=rkHccZBE;bPEfckId-cXJ$5T zA`O~o4O!5@quwrHh#|--GGLWYcxIQT`}cIaglYS93f~ghm*@6hsSm9>Uv{Ljbz91W zfZTxm`TiHK2*Q4BGf(_v(y0T(&k551bFX#FB;v-->&xAF)o8}PqP(JnYrnjbj|0j7 zzGK6U?M-*3(uz?T_hDmt*@7LLtMB%U`}-fJ^y&JRvU~>=BRpB|JxN^=xvJoWO86L# zkq=AizBGM-9UxjUa@&it#-oG*TN@9L7L)~gGOw>D?-M=WtoLu}5)3XycD zT0@pupQM+umIbZtX(yLhM3urT$(nPI;^uDB>X`L^yw2bo855*W;CmJ2!9ulfWZ4fwQtYY{WWkI1jMfD7-Zs1 zppPEV+J3GlT{TWGJ*wdYxH2UU11+%y6TCb;V(BPmcF?-y^YG}GRFpg9ut;u(D~v`ngVOeyIh%oiJJ#BE z@C(oq-Do*%h3_7()YLjm2KxEnb_c~R{I*P!9LWduaKk8V`j&%)8t*>5FFVU*uBq~e zPl8o@t?Xs38IYspsPJ@{TB8%@$q<~lA##~-f3<%0CXJjUK{#k#MQiEfHM#MrTsh|| z)xXeP`mp%0pxYTN%1DBhF)TEpa^YEmf8E zmwL4(_5s2b$2)IF%$RbkL)bQIF5{d`va@b)9X4}HlnkP|D)bT<9&6jt zq6KS@u~cC2sF^{x`~~X(LBm=!3%zr8o6H-1^qdH|k?mbG(83?1l_EOAPTVplZCIF( zI%B_$h_11hHgoBm{`eFr*L4xb=&3u=%zf#f_K-}E%I|0J;i zGxpa!JHx~JRa)VlLmAm>VHLUf`0k-YAk@-$lep!E^$(!OO}UYJsT^gd{fmbssDYD! zP1Aur9Dz+h4zt6+r1OAvT7ZR40H?%LWntmXg&<)$!hJdw`9lsWy_MH}Ab0#g9{7P= z_TSat%O#+?Q&JAm30m*=$+#yly_XXx_XuSUtq9ahAA?q~OAm+Q_KS`+P;G@vDxg9P z87XDG=Bru#r$@)(ZWzlT+5TL#%vSeVF-?U84b4CGm{`%URF?Rhrj9M4 z^&o3hj51>2$SZC}uqZ2H`jqJ6ayX70{dEN#xvMcf>PO|W7zTXmd*T3na zw$MvS`$v!{73XZIZf|$VMWrpT?;P0Sy@6R^z*gxxV{s{5@{Wy7?d5P7Om6$_zrfKz=fFK zki&B^v+2G+xtCaylS>745#9jWBbF&tmZ=52Cio~=lA7)kfKlL{L<%^x&k#0cl`asV zGz+uGh_G$I0NH@jcY&wkzsuuL07`2N9kfGW8dHG%>Xq@V zxnN@`fy3Vdbw}zDKBgyvqYQwLTLSC!8ERaV_?$xO8e6J^>Xg0TxL{%hD%6Hn^z7LV z7X!HBV}e;5zRXx>Ay?|Tue8#UC-RjQ5BDAx;wb{+AQg^C6}}+v<_TLBoLT_V^s-+R zriv@Nx^Jl`onVFcM^(EG3ptEc)aah1&$l`25ov7Uetbs4f@Sg|LbniG{hHPeT2w28a0*{#nnzo z^4HP;1+p1N*th1?&;LzE|JeBByJZyJX=qOf6)+`z?1LSyN@LI>0B7)?h0Ie+%0lJ z&?BWR_VV4Fo}Vr*CfIWhrcO^e=R!;B8S5Jp8;nN4yoVIq3IIkK`&7bm*yLG3G1Ck0 z-4vSzn7Q;lGZWMd?RcYwh#GX=YLIcg6s{(SrI)DhhRX`EZ?*C z@PAnQzrYf_z$sYvfDK&)TBiblbnxkr=|#aGSbu)2oD&Up&8(m{(r;L+4p}|}Ln;Z| zqf=C99Ld|5^1NFA_}-kDa@db-_HJXPx3(dzL>_jG7{eO<-Sqqif%e5&+CHoNGqZLi jH_ZMMGXMY6pKg=mO1oYU4z|`?QrQChf>%|qjNS8Zrc3^u literal 0 HcmV?d00001 diff --git a/tests/line/fill-rule/test.typ b/tests/line/fill-rule/test.typ new file mode 100644 index 000000000..a0de82d0c --- /dev/null +++ b/tests/line/fill-rule/test.typ @@ -0,0 +1,24 @@ +#set page(width: auto, height: auto) + +#import "/src/lib.typ": * +#import "/tests/helper.typ": * + +#test-case({ + import draw: * + + line((25pt, 0pt), + (10pt, 50pt), + (50pt, 20pt), + (0pt, 20pt), + (40pt, 50pt), close: true, fill: blue, fill-rule: "non-zero") +}) + +#test-case({ + import draw: * + + line((25pt, 0pt), + (10pt, 50pt), + (50pt, 20pt), + (0pt, 20pt), + (40pt, 50pt), close: true, fill: blue, fill-rule: "even-odd") +})