From 989b65a5e109c3ab51602e5b399ec1fce0a155cc Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Fri, 22 Oct 2021 18:45:18 -0400 Subject: [PATCH] Implement Pyer redesign of Merge and Split. --- res/DSEG-LICENSE.txt | 95 ++++ res/DSEG7ClassicMini-Bold.ttf | Bin 0 -> 9440 bytes res/DSEG7ClassicMini-BoldItalic.ttf | Bin 0 -> 23344 bytes res/Merge.svg | 769 ++++++++++++++-------------- res/Split.svg | 752 ++++++++++++++------------- src/Merge.cpp | 116 ++--- src/Split.cpp | 78 ++- src/plugin.hpp | 46 ++ 8 files changed, 982 insertions(+), 874 deletions(-) create mode 100755 res/DSEG-LICENSE.txt create mode 100755 res/DSEG7ClassicMini-Bold.ttf create mode 100644 res/DSEG7ClassicMini-BoldItalic.ttf diff --git a/res/DSEG-LICENSE.txt b/res/DSEG-LICENSE.txt new file mode 100755 index 0000000..ad4c0bf --- /dev/null +++ b/res/DSEG-LICENSE.txt @@ -0,0 +1,95 @@ +Copyright (c) 2017, keshikan (http://www.keshikan.net), +with Reserved Font Name "DSEG". + + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/res/DSEG7ClassicMini-Bold.ttf b/res/DSEG7ClassicMini-Bold.ttf new file mode 100755 index 0000000000000000000000000000000000000000..4cdd3e70a1d9a27b745aabe81d1d977152980175 GIT binary patch literal 9440 zcmeHNTWl298UD}A-ggby#@O8KF&Jz}ytdcCI>vU*#fCy?!ll$DMz9zgJJ@U2Ue!QR z6@^MgZPmUYKv9Y+f}*MlNVrlSnyOMEG*J`LHbQMwswz#Ril!l|BDD_{c>A3*=bYKu zou%}teejHS=3HjZfBXK+%q%e?nny2?Nr!uT_wAZ^@Xnuz>fXfYvTa*?dTBmYqkjec z>Sy*gC7%2G$Qwj#82!ToW2uP?pKUxwWSqv>k%6yfEUGn55}6-h-ghiDHIdC?WvY7_ z{m`+|lS6GE_C0~A4AIiQ;lb3=$lb2LW9}3DHVk7RaK{W_tvdAUhQ~4|lGhfVNB?c~ zXGX^dQuqG&A?D4G(EsjO>cj+nj}BpeJNi~SH8yx@bpKtVns-6Nni!wT1jE5iL@W9F z*NDqXt*xn9t87S2T9vCr%SYGJtApb+#VH^HasJUi5L zlzu=Kosv8Vp2gbWN{m^=*eKQVJJ>E9pe?gm{H_vZZ=ij|Y&Le=XSyoS7~|v45BII+ zefMtccK08r_gMFEcDc;_x6GD@`qAUkFC!my;~W!K@IkgXwbKDQ1w0XS(MZj-iBj2Y z_Rrb(v%ky!Ci{+D0n_%zIF3}C+k^jdH%ywooB@A;f}wCE8Y`JMe?h4|QC7aNVo_z) z;w4L$Ew8SzYFDhRTeZ5rVa-~Am~T%u#+#a360PgjZ%DR1)xNQ#v+Hx+n>KIR+GEfE z?~lSCX|3Kns1IoR8U2g3vFF*V>{G)sCXJt%WNtUVVZLU5>|5>Y^PThk!uP&E;_vmR z{Xg=*7w`qT1E&KQ1HTMB2(Abo4*oFsmrz}3f9O)^_hBR49X=ht7XCQ0EE10#j=UUs zGfL5h=z-|@=zGymV^(ZW>_qJK*lbBh$*Gdppb~>)m8~^ig0+Jbzs{(sV~-Ue zk${g8s|?oGCyk!Y&e>NxJB>saHqd3~M8ITXt4Y?W|^_CH=S9$r5(F2IpNhH3uL3 z7zeYqdiES)Iy2$^}-TYwZvsz%IkFl_rHm$~sVq;?b6LlRDH>06F`EY(Eq;OB90V1$R{@$x$3#1x+VMRv zy30UeNB8`&uGnA~R9NTc^Wxy)eFR4ByQaV~&sp48$~1oMuxO_eSLoFQ)Y>B2ibbJT zmmGXOo~M)?xodi)r$Q05k_%~hz)R9TlVejSuM~|!PG(f}3&M}0?j3nlyve1jB=(?M zoL*5fxq8jTYaW$H##SBRblUg8hm-L&K2$7KxJ2G^*Bmw~{YCM3(}Ru(70>Hhg4wkM z`zLShu&)u948Pg>n{$k}0dqufIK90_M*EBqT=Enq2X{Dx%$*ci% zrI_rZR+#OV!bu;LwN!b&hI5=ylp9*EJit7B1!5_zk(u+-j&O?nBG|D~VJ^;3HHNT}iuVc?wmw~P zUWp)-X2&?k|9D(?*AeoeL)s#jO`R~#@=+Iu?o=f0eMb9%V{exw3j9IpLlaW0=f-Q5 zpln~eEn*FiBT54@isWKRhmRaD=8;2#N7dU-Y%K6IsTOx(rTt8Ma?xin;nQBZPStjb zw&(Mpt70g|L%#Nk@*+?y^ytBmik*rdkC-F5`A>W}Pdi?AWcd$0#cB?hFL|258>HGe zg-G=fTg50*bJ%{Y5amk8w$Q@Cba2&~n3I&UnkxV>*E2Wdo2ymrw+?f)ss^V@bh^|~ zVDj`C{ggactK!vIZXse9R4N3zs*&96;S?ovwJNW}ogA&Bo&7SaAUCTdnup7|TGe^I zH&?65x3zP%>Mf_nLf)UNRr9`GsH~?e{kdAz{;2c+Q>zj!q<`vg}~V^nGUO}5J^W-jMnZhc{_ z`hr-Qw;9#ZO*xJa-1I=UO*+b=vhAZdyCU0uTEsq)?EtMc7RYv(wiVY+oD4x!&BHt zXaN0PIH&QWt$Ta6C9N%^si~=v0c+Pt8e^Nm)hMK<&EumuK1#55to1l_8ug+URA7Op zMry$?0rj+?M{cRwtwO#UIX70jm27NjOf*8VIu0$jDwQG~0c|=`qgk>cXe?3$G2A=q8WdHyG literal 0 HcmV?d00001 diff --git a/res/DSEG7ClassicMini-BoldItalic.ttf b/res/DSEG7ClassicMini-BoldItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..81a895e740cc656df1cec551c57d167f3409fe86 GIT binary patch literal 23344 zcmeHPZERdwc|J4#N^YF&=7ZhrvYVWEzY?&W#L31Xq%;$IoXo}^d+qUVvMgH0GuQTP z#xuj689T0!x`je%OQn9$1)To|?mhS1bKZ~Vectz+xgM2JO6^h4sUG##sj1w|b00lEqSTuY zp!L2>lj$k-8inJhe#G7_y>}&Fuid(Zk=0W_!1<1q^5*i@iTt;4>Agzbe|FW)7YCOsHP(`&>e{QV2+ z6Tp>%O-9rSl|oCNEw}#d)<50)+O03&`rBJyy7hj4G;|C8CHjpsO#`j2_zM5Sygj|4 zhQ59^uw$pQYjF3TJMP>o7xwKx@S3~sK6uZ)uf6a7Lx=T|p$8s(=;23>9(&#Ed3{)o zj2=I6a_rRUN6(C(eZ#pop8vTw{rrX0#R&$}ZT-7+TfKgoP9{dx>smkO)m8Oj^|?ec zaWQct@u{Rro=Ltp`PH67JkCe-os zFAVgmm&ZQY-}lewU+78VP<^t8&3$ZsVW2*i(tS2aY^4o_y@=#LYiFJCPiF6aHb|1fyQO;7Nz=udSQ!xwOj31_W+TPC^i1b{!@n&13d!| z>>s~-plAFDW=(M7Bm3{}dEj_reE;~Vo`FZk-*Ug+H@LX(jeGVT9$MUc;7H>A_Z4q` zGckJPX6e3S;=aF&T)uKBQQrOZ=M$T|6W0&pedh4txBU3e@vG;^p_}i+m7Bk^`{w%& zJ^gvw5z%)AEcPKtxSLvsXH9-3GH%a@I&O!h0=))dmxJnXODi#9j8eWfiC-1t-rGeT ztH-a?_KEkmYk|4n<=eDR?NWPX?yi&imb4!2HmPr7ad_vXA=80#mRq(Pgir5PYQH$L z&wwXt%y*0L63>XziGPjQHmSu~j~QLBcNn@4bE)JP!QuVL2)>;ovqkJIsA-$BL*+jf zk)m_A?3|ePQ6kutxdpq2)x#|>``8tgV}yu8*Q(!57VC2#yJC(`ky^GFdxUK-B0LlU zvTul1+|6}ueu{8 zBI0&{iOSXmHyuLtpf3D|`ita$f^Y6Z)>Hc}agLwi&)D5};V0>nX}GO8=aXt*-wwyw zd1$BO?C3ij)0X)5H!R@}?%J`lueY~v=Z;-BuZ9|(Ui@=*>=G^}=g~%8xj5|2D44eK zV-#Cm@f?FQ;nFYqTr4>v7Gr*fh)WGNz7nf`YVcz`PL7|v3`%W9IV&sTocT|%W9Jr1 zl}X#EyETm+-*B}VShaEka|=0(IWKO^*i>heLu-a8_B!Y5fSo`8pN0G!^c>~$=5N=&4G>Ms){(wv}n;P7mt~sjtF5!^b9bI z92m!neR1=)u=T0}@e;745;9uyV}43~u~p6(yR*&`%$dC4%hT7r ztV(=ft2*jEag`He^@^X5Er-Nv?q|fU^l#a`YEw9Op}R==c4 zRD3Pl?EI5If`S%HVP3qKHFngSamh7`-WHg)i_El#_qZPYj_ZH?W9Lj#Tr0zvQ)%_(iRi^(Wa)7f}v;lVdyo4JK28vKYi+ZA* zOU`M5%dW9xjYdxEh)dr@kz%e5TsHdS^QfzqjJ#hIiVkfXMU#9kL82(E*g zKfv|=&J6`06?bjD=I$8+03&+_h|`2wZ(qaS2lhuEGU+sV&Ce-^{T#xzVmOCvfs^fX zNjF0D6I!f)xK`|>r&gV0aT2aYW1>HH+r^60&N*>%v{BEiwKey&+8D`?x>mZg(D+%B)`X{ zvbOx*V!2mq>n?eql~&{U|JB-BK2qquiP28{cBK-nC%fAA)!G_KpwkHdU$r&X!1(Mj zQp0y=m~E&fvSu)aQ)r_=9ZWpj`n>ysdWV0U!2ayN`^QPOD{;U-?osCw&-=%{>QM3y z|F};LCNKNP{pz*J-|&xjs-fif{o_G(ch5!tc=z6iANq)Yyhq(T-sd0hS9gqGKy{qx z*R;U&ij^`QD2|2T{>6WP5i!sv$|SUC3PLw zD#}qCIBuXtt0`4QOT)Z-Y6U&D8pBfvC-8n0JsS9_;hBWv_*wS*@?H9lV%%l)uHe3g zI;PZw=jI!3Q7>)kD{g(YbUj~jHcE|EJyoqVrmEhGtH(x9=%cHRM(y13m-Fv6r-P-%5ZjYEJ5JSdUJ6m^JO!1)Z`D|o5Nh4iIyJyFir>!pI8DOJ#R5mJ?n z))~l>$1!hG7pvu>&NTAn5>B?#_8ca-oykYK%%ou@txl>(@x;a{yvATdzEo88bGlRb zk&ux3oId&J$f=RB6Jxmdrx7T|O5ur=dIDbajB$wp4OvIkX>|q{T(4fLR`iL{(>M!c zi2B2NBQQwB@J3DFMf8xF+d85hl1Ej}2PL8F!IT#ORtwt-T)PH$KBLa!r-tiQg3TiA zXbuo-xZb%7*NM4Gb*=Qw*|RmTiat>UZ(x!QXc-JG5n&Omd|Ym9Y>b+*fM4Pgz{Zp{ zM3VGt`JsW_R(}s*Xq^ECd(6$aKNjYV_3)3Bk&Qs8xc6AWj zKZ_qHWdAu(WY*|3i}xIkrs10j(@Og6W_>H|i|iv3H*p_jqU~tkCXR*0*s_L^dA{toS)CkXLtf!M`fq#rp#ASo?pkDJSNAL5Yy7VA(eVuai*HX=fKt%x7nwzV|`1;?Qk^HQK);AQrpC3r2G=`3ml zzw{%mLFvU4yo+e2ZEUV}Fq&YPc5b(>^|!6Fx3fuL=_rOQw&U)nC7G*;O4oSIGx!qQ zT0e`0DLt)ARM4KzMwRW zXo=7EdP4GdbUqE4tGJ7{wwmQ3UkzGq!U{63)q{NtkSLIa89coDp?^3#BgIB@ICcd^ za)o+ve%dOEYReXr$VOAhvRS-xcro)XK&qioJ+{z>x*?27nU>AC60773D-Hb=~0arXr~34`xp=OpJ!@X;b2Nu$C%`9 ziw^OmaJOUZZ8?M7$~bId4AzE3iPez&LPp>@$Bx!t5|M0g_p-1J^Ph0|5bA|!%!aE{ zTOW7xgT+!f%IhW~3Xm+!)M3pj9l1r~N_^=+!*-8QE3QP@)1p-TVr8F&Ww@RoN|}Ay z>$YxkTm0CnL+S~s3v4V;K^}?Gc2wG&&uWADlD()Od4qLMd?wlse>w(#R?ivC6wQ6n z)j>Bst$*U;QqajOmVa6Ga26Z!Rl}6*K~%G{;T7_!%^yu*P%0s2YukfWGV5gaXU)bK zkSHZbNGod?MjL0B-d5IVZ7S7OyQRZ@95Bh&D3DlTJTmS$k06G;Cj86jvo#=P6kpkD zGO&nL(pw?Jax62Si=3nJyMnw!ek58fj;&`?#%{EQ2PTYXJ8Kzwf{eUk#+E$B(M229 zks02yGCa9~Yphx&7R9gO499Ae6(41n%9H#{uMqXTH(YIr z_BOh@+ex(NDr_Drl??I#*T&2U8c&#$oq0UjmMP|pEUe09OG{)D{-kHf`Qkazof6u* z$ku^2x&;Zc3rBodze)8I)w+sN$wS0}V8OweSb;gjj=8su*S+dvU*bn{1S7d@Mz(j`T>{&O`L46l7H*c6O*d`1zK+(6oSWHh zskLIWcD9yc^w~9ojWWR&d5C;MAJ@%(gM-}p4FGDI%=ihIM{F&Q(Ozw$Y| z`HXu~QJ+axAg1G29o>;86%H-=O4b*|%2q23R#lAIAnK%IV2n#-(vubo+{3DxYCq^N z{^EY7t&U~KEr<`^Eo>64t4DE14%ehk;)ukNSg5^XqZOj~lr^SQGPKT!!548&-;<$k z7@4BA-74aSD5;=7d5yU_*qNg&vPVH~rgyy-G6Ng1@@LlJ?-KfRF7YodNgTVeqmy@N zRnEwFsXK|sqM6OE79|n_4Md71Gct2NQ50w;^-=ulyNYosn^cT;p0J&1Ra%nuF2`l8 zGQY|?Em~U%w|ai;obp+Nd274qd?j%rvjy1eUQavVE?EtSR~NEkp%;k+uGNT3ascx! zJ;%?GnCBTGXYjl{M^h}05{O0kY0#WA>*n6sI@J%3nF+coBC<7aMc*M0*q=M z+{Mgc?HI1tf*#@BRGWu7^C7b#>rctSc7-lHE1Hl!#99)$%*6CP*^vm~YK{@lSm6;Z zRWv-u3Y-4n70GhWwrH18ZvbsBY)!n`DyV=pE9KjOtc)=ET+`Y>GIY556AZ-JV|#Sj zyC}8jFI9HDrKz*!AL|v_d)O{|h^Nlzk^K5-1UJ@$o!OBV>#UB%6LFOj`wL5Mw+doq z!98^537dNvp*$xCgsW^Kf!<~$3LDwGP|6`Mt;5FLZ6$`tFoEU6eA8a*Fp8KnZ0*eZh!n0!=`&eZH2mzyHP!+$ zz%-=JfHAltqtusi#GN4f`Pc%ErqKQ*`tcJcZSK?N^QKvRR++(SEsYmHNljryxjtl= z>q%VYh_h-D@7f<@9{u>)+cmUsY;DeYb_M;p`eRI_@x24`nHJZG>^YC$lyuH~X2&^+ zY~DdF7IDtwOK7|3&zHqroR^>RakWWbQPLdRgIPs0D^&)4WWFg#A$FO74kB|3WAn3I zj&;q<&z;R2=H*?ykCvmPDZJ+JdmdN$3F9K};u%{P@ji!s@`)oyrc{)cd!$*6F>l^4 zVN^;$YjL-Ow&DtT4s)}|CCHUCQg9|}$DXuG4%br{mG^VjE2dQ>qfO{#$`XviT+g{h z4vp(i_~VfcssA*7I5O`gySK~1EINxmoRwo=#Jkv@R^w-qVe4d#{{#F{>PgH(d8v2c z^RT?Me7g@EBX>InXjNj0W6?Xb$F#A+0_>ND{2WPIs5j9=d{6imWE=ZX8(P)&6&uPv z1^xFpyeU0oJf}?y>h+|tSzvXsGbJQWIHTPI34F{sDYKP_m?f5MBm`Drlu;7SL|^la zGhBj~h@@HAl-Fz&${Zq%hV+6$(Tn#*?Q5gO_OthG#Sk)I=`MTmGetwSDRD0`{=`_sZ>Xj<=*41TW%MLs0qfqderu7?DU2l}unq@o{r#Grz zxwug(x=ztuhZSpUEhpP@KloOV7H6Mt#@}(X7>~Uc=00t`_*1 z9iGr~++{pI*D#{w3;CkEhR5OPnR2PJ(kx->0tR1OYgS5)l8eE34KiW$b;zOfdf9XF zRw+7FqG8zsoFL|PU8?Af)ly;ANK@Bq`As-p*H@ubQGCC~L2!bewY=A;;F+=2QcW;g z1;)I(0i>&848R1SsT&1aXrv}+s&e2a;5iIaHH(1QuwJVcOUncsCBux+#49Z|`D7sl zE^q2QU|p@O@EvpE9LBCx8@kTN{qXc58rSM>dEKp#YIw{slMO@ILK$=L#>%EfG?doG z=u{f^DdZ~@X9$YMrhym^jUDdKJ2VkH-I0{NK2g|u;-TDd=TPP&iFt#Hft^+=38Bi;kj>X zmOR(M5BTxtfhW+Ghd(V(1l*yERY=Xr^0iud(?MTjz-pmsMlpbdD$P1=3*-A^VsM<4 zys!d*1->XMlg;EZv)Kh_Xo`5Zd^H3amVq7Og2U8Z6Cul`GUjh-DGt^x9(69m?XGvU zek@LQ8n6KSc)-nC-n&j*)pfmDSfx3jB+%^$GB9Da=@lS8CmaS4O2CuPUqmAeAu5~r zgDOLvd>qz+RuY%jYi_{@wM?$_%Xny!S~{RsKOxi`U<#TPx^VPa^6XcVTbY2TmlI-nrzS`BbF>QE*XZYB4?o4;8oZ(B((6W({2KIWm6Yc^A#9o1vvB8 z@?=1d&7?_-z^E~ZSf}D{Xt%On@~Rcun98P_jn%5xsbamf0!jk|a2l6K2!f2BoRKAa;mVfwlB{7hzH0fC?&))TYYNk1s& zTyL#}hnq1H@ChgN8hdm=Zi+!hOhQO$12*o?!&EZXpLZw1XPK zZIhaxGBB1~UWQY~j%|HsShE&!+0kt3h#1WzvhMl9V2cUaPZ(|T7_>M)F9Ys8HM+4a;_`&9!`G1hqxc z6m$IYN>XvvqcO=gAb+n~^Gd8{)*vJzBj~>7HgIDDHATrS7we`LBhX zN78o{!ut34`4_pY1hQT)xf_xnIXTek!8@k_jcSKGyZZ#U8QCK|?XYf^bOD~PYxhPC z)+;qM!?}S<2(c6jKtJ-xFhaT>@;SJbq~}bu93m|0Cl&NS^!wCYVabBb$++;T0A@ro zf{kz% z#Fm9?)do1htrV*s?8ZPVqSR=VZ~}^P+M@_vZxq~`3Fmy_dZoI7vI&3WAy)F~4>29c z(P1uLVq)bjA)!54OQ03iL%VyNz&)_dqhgx~N%-W&8WKtbM?(bXB+Hf-zaxH30@XVZB;HMZat&@G)jt$FehPSBF|7-ZA!MW?^DF zm6=J;JGskgS&uEuPUW6V&8Kx{LC?+4K9QMBPwJu60?vnq^^=+0<=MrYMvwVaHg^pR z1f9xW(^oRt$zdmb6)UZU1wA{jGc$A3ne^na&SWR17bi2>OZp=2%g%DeH(A=!K z)gLO8#(h%`WSO{(ky95l)0y10VLg?}WjW>)22JU?)O;>8u{fQY*K>>WbF)}Drm~Y5 zHk-*#&107IOgfu$Al1a|+_m}4rOUZt+>}G(u+Gh=Cet&i`76Vea26`hYtv;EQeq69 zegggU!sXQTw8mAZHHN-CJ3Wcs7t@eFg_Wd;1I3N~hV^7>CUuD#*m2oSG;jh7&{CJu z+4OvBdRQ;ar6)2xfax;x=?Msko-j9*M=M4`O|g)Ed=U-k=lD~=2ba@EbjX~-{|Q2a zen59<$Z>MB^SPENPi7X@MYgjq_DQ0Dyc2yyu-l(#*gxTk*>m8ZGI6(&J2i{gO&T$OWOfoy zC!E7yY@NpC%%x0rab{#(pBy`P3Jv&r6nwkz|KRmb^osk(Z)HxPSC8t&clhqbx8@wc z_etNS?#8!z-h*$vc`d%<_kQ)DdI--2J%Xn)kKr3>UypsP5$sgTZ6$UUYh$a@(QKZd=}X~@jo)j90e&11hS2Q8k!uH04Z5I&{ete#eH oQSUTDCh* - - - - + id="svg132" + sodipodi:docname="MERGE.svg" + inkscape:version="0.92.3 (2405546, 2018-03-11)"> + id="metadata136"> image/svg+xml - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + id="f39dfd3f-f470-46a6-8d6e-edc86f15578f" + data-name="FND BG"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/Split.svg b/res/Split.svg index 51c88ce..498a88b 100644 --- a/res/Split.svg +++ b/res/Split.svg @@ -1,6 +1,4 @@ - - - - + id="svg132" + sodipodi:docname="SPLIT.svg" + inkscape:version="0.92.3 (2405546, 2018-03-11)"> + id="metadata136"> image/svg+xml - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + id="ad801b06-58dc-4a73-ad49-57908275371c" + data-name="FND BG"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Merge.cpp b/src/Merge.cpp index eff22dc..2daf960 100644 --- a/src/Merge.cpp +++ b/src/Merge.cpp @@ -19,7 +19,8 @@ struct Merge : Module { }; dsp::ClockDivider lightDivider; - int channels; + int channels = -1; + int automaticChannels = 0; Merge() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); @@ -45,17 +46,10 @@ struct Merge : Module { } outputs[POLY_OUTPUT].setVoltage(v, c); } + automaticChannels = lastChannel + 1; - // In order to allow 0 channels, modify channels directly instead of using `setChannels()` - outputs[POLY_OUTPUT].channels = (channels >= 0) ? channels : (lastChannel + 1); - - // Set channel lights infrequently - if (lightDivider.process()) { - for (int c = 0; c < 16; c++) { - bool active = (c < outputs[POLY_OUTPUT].getChannels()); - lights[CHANNEL_LIGHTS + c].setBrightness(active); - } - } + // In order to allow 0 channels, modify `channels` directly instead of using `setChannels()` + outputs[POLY_OUTPUT].channels = (channels >= 0) ? channels : automaticChannels; } json_t* dataToJson() override { @@ -72,6 +66,21 @@ struct Merge : Module { }; +struct MergeChannelDisplay : ChannelDisplay { + Merge* module; + void step() override { + int channels = 16; + if (module) { + channels = module->channels; + if (channels < 0) + channels = module->automaticChannels; + } + + text = string::f("%d", channels); + } +}; + + struct MergeWidget : ModuleWidget { MergeWidget(Merge* module) { setModule(module); @@ -82,41 +91,29 @@ struct MergeWidget : ModuleWidget { addChild(createWidget(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); - addInput(createInputCentered(mm2px(Vec(6.771, 37.02)), module, Merge::MONO_INPUTS + 0)); - addInput(createInputCentered(mm2px(Vec(6.771, 48.02)), module, Merge::MONO_INPUTS + 1)); - addInput(createInputCentered(mm2px(Vec(6.77, 59.02)), module, Merge::MONO_INPUTS + 2)); - addInput(createInputCentered(mm2px(Vec(6.77, 70.02)), module, Merge::MONO_INPUTS + 3)); - addInput(createInputCentered(mm2px(Vec(6.77, 81.02)), module, Merge::MONO_INPUTS + 4)); - addInput(createInputCentered(mm2px(Vec(6.77, 92.02)), module, Merge::MONO_INPUTS + 5)); - addInput(createInputCentered(mm2px(Vec(6.771, 103.02)), module, Merge::MONO_INPUTS + 6)); - addInput(createInputCentered(mm2px(Vec(6.771, 114.02)), module, Merge::MONO_INPUTS + 7)); - addInput(createInputCentered(mm2px(Vec(18.275, 37.02)), module, Merge::MONO_INPUTS + 8)); - addInput(createInputCentered(mm2px(Vec(18.275, 48.02)), module, Merge::MONO_INPUTS + 9)); - addInput(createInputCentered(mm2px(Vec(18.274, 59.02)), module, Merge::MONO_INPUTS + 10)); - addInput(createInputCentered(mm2px(Vec(18.274, 70.02)), module, Merge::MONO_INPUTS + 11)); - addInput(createInputCentered(mm2px(Vec(18.274, 81.02)), module, Merge::MONO_INPUTS + 12)); - addInput(createInputCentered(mm2px(Vec(18.274, 92.02)), module, Merge::MONO_INPUTS + 13)); - addInput(createInputCentered(mm2px(Vec(18.275, 103.02)), module, Merge::MONO_INPUTS + 14)); - addInput(createInputCentered(mm2px(Vec(18.275, 114.02)), module, Merge::MONO_INPUTS + 15)); - - addOutput(createOutputCentered(mm2px(Vec(6.77, 21.347)), module, Merge::POLY_OUTPUT)); - - addChild(createLightCentered>(mm2px(Vec(15.276, 17.775)), module, Merge::CHANNEL_LIGHTS + 0)); - addChild(createLightCentered>(mm2px(Vec(17.275, 17.775)), module, Merge::CHANNEL_LIGHTS + 1)); - addChild(createLightCentered>(mm2px(Vec(19.275, 17.775)), module, Merge::CHANNEL_LIGHTS + 2)); - addChild(createLightCentered>(mm2px(Vec(21.275, 17.775)), module, Merge::CHANNEL_LIGHTS + 3)); - addChild(createLightCentered>(mm2px(Vec(15.276, 19.775)), module, Merge::CHANNEL_LIGHTS + 4)); - addChild(createLightCentered>(mm2px(Vec(17.275, 19.775)), module, Merge::CHANNEL_LIGHTS + 5)); - addChild(createLightCentered>(mm2px(Vec(19.275, 19.775)), module, Merge::CHANNEL_LIGHTS + 6)); - addChild(createLightCentered>(mm2px(Vec(21.275, 19.775)), module, Merge::CHANNEL_LIGHTS + 7)); - addChild(createLightCentered>(mm2px(Vec(15.276, 21.775)), module, Merge::CHANNEL_LIGHTS + 8)); - addChild(createLightCentered>(mm2px(Vec(17.275, 21.775)), module, Merge::CHANNEL_LIGHTS + 9)); - addChild(createLightCentered>(mm2px(Vec(19.275, 21.775)), module, Merge::CHANNEL_LIGHTS + 10)); - addChild(createLightCentered>(mm2px(Vec(21.276, 21.775)), module, Merge::CHANNEL_LIGHTS + 11)); - addChild(createLightCentered>(mm2px(Vec(15.276, 23.775)), module, Merge::CHANNEL_LIGHTS + 12)); - addChild(createLightCentered>(mm2px(Vec(17.275, 23.775)), module, Merge::CHANNEL_LIGHTS + 13)); - addChild(createLightCentered>(mm2px(Vec(19.275, 23.775)), module, Merge::CHANNEL_LIGHTS + 14)); - addChild(createLightCentered>(mm2px(Vec(21.276, 23.775)), module, Merge::CHANNEL_LIGHTS + 15)); + addInput(createInputCentered(mm2px(Vec(7.281, 41.995)), module, Merge::MONO_INPUTS + 0)); + addInput(createInputCentered(mm2px(Vec(7.281, 52.155)), module, Merge::MONO_INPUTS + 1)); + addInput(createInputCentered(mm2px(Vec(7.281, 62.315)), module, Merge::MONO_INPUTS + 2)); + addInput(createInputCentered(mm2px(Vec(7.281, 72.475)), module, Merge::MONO_INPUTS + 3)); + addInput(createInputCentered(mm2px(Vec(7.281, 82.635)), module, Merge::MONO_INPUTS + 4)); + addInput(createInputCentered(mm2px(Vec(7.281, 92.795)), module, Merge::MONO_INPUTS + 5)); + addInput(createInputCentered(mm2px(Vec(7.281, 102.955)), module, Merge::MONO_INPUTS + 6)); + addInput(createInputCentered(mm2px(Vec(7.281, 113.115)), module, Merge::MONO_INPUTS + 7)); + addInput(createInputCentered(mm2px(Vec(18.119, 41.995)), module, Merge::MONO_INPUTS + 8)); + addInput(createInputCentered(mm2px(Vec(18.119, 52.155)), module, Merge::MONO_INPUTS + 9)); + addInput(createInputCentered(mm2px(Vec(18.119, 62.315)), module, Merge::MONO_INPUTS + 10)); + addInput(createInputCentered(mm2px(Vec(18.119, 72.475)), module, Merge::MONO_INPUTS + 11)); + addInput(createInputCentered(mm2px(Vec(18.119, 82.635)), module, Merge::MONO_INPUTS + 12)); + addInput(createInputCentered(mm2px(Vec(18.119, 92.795)), module, Merge::MONO_INPUTS + 13)); + addInput(createInputCentered(mm2px(Vec(18.119, 102.955)), module, Merge::MONO_INPUTS + 14)); + addInput(createInputCentered(mm2px(Vec(18.119, 113.115)), module, Merge::MONO_INPUTS + 15)); + + addOutput(createOutputCentered(mm2px(Vec(7.281, 21.967)), module, Merge::POLY_OUTPUT)); + + MergeChannelDisplay* display = createWidget(mm2px(Vec(14.02, 18.611))); + display->box.size = mm2px(Vec(8.197, 8.197)); + display->module = module; + addChild(display); } void appendContextMenu(Menu* menu) override { @@ -124,24 +121,15 @@ struct MergeWidget : ModuleWidget { menu->addChild(new MenuSeparator); - struct MergeChannelsItem : MenuItem { - Merge* module; - Menu* createChildMenu() override { - Menu* menu = new Menu; - for (int c = -1; c <= 16; c++) { - menu->addChild(createCheckMenuItem((c < 0) ? "Automatic" : string::f("%d", c), "", - [=]() {return module->channels == c;}, - [=]() {module->channels = c;} - )); - } - return menu; - } - }; - MergeChannelsItem* channelsItem = new MergeChannelsItem; - channelsItem->text = "Channels"; - channelsItem->rightText = RIGHT_ARROW; - channelsItem->module = module; - menu->addChild(channelsItem); + std::vector channelLabels; + channelLabels.push_back(string::f("Automatic (%d)", module->automaticChannels)); + for (int i = 0; i <= 16; i++) { + channelLabels.push_back(string::f("%d", i)); + } + menu->addChild(createIndexSubmenuItem("Channels", channelLabels, + [=]() {return module->channels + 1;}, + [=](int i) {module->channels = i - 1;} + )); } }; diff --git a/src/Split.cpp b/src/Split.cpp index c2e95dd..d69e334 100644 --- a/src/Split.cpp +++ b/src/Split.cpp @@ -18,12 +18,13 @@ struct Split : Module { NUM_LIGHTS }; + int lastChannels = 0; dsp::ClockDivider lightDivider; Split() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configInput(POLY_INPUT, "Polyphonic"); - for (int i = 0; i < 8; i++) + for (int i = 0; i < 16; i++) configOutput(MONO_OUTPUTS + i, string::f("Channel %d", i + 1)); lightDivider.setDivision(512); @@ -36,13 +37,16 @@ struct Split : Module { outputs[MONO_OUTPUTS + c].setVoltage(v); } - // Set channel lights infrequently - if (lightDivider.process()) { - for (int c = 0; c < 16; c++) { - bool active = (c < inputs[POLY_INPUT].getChannels()); - lights[CHANNEL_LIGHTS + c].setBrightness(active); - } - } + lastChannels = inputs[POLY_INPUT].getChannels(); + } +}; + + +struct SplitChannelDisplay : ChannelDisplay { + Split* module; + void step() override { + int channels = module ? module->lastChannels : 16; + text = string::f("%d", channels); } }; @@ -57,41 +61,29 @@ struct SplitWidget : ModuleWidget { addChild(createWidget(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); - addInput(createInputCentered(mm2px(Vec(6.77, 21.347)), module, Split::POLY_INPUT)); - - addOutput(createOutputCentered(mm2px(Vec(6.771, 37.02)), module, Split::MONO_OUTPUTS + 0)); - addOutput(createOutputCentered(mm2px(Vec(6.771, 48.02)), module, Split::MONO_OUTPUTS + 1)); - addOutput(createOutputCentered(mm2px(Vec(6.77, 59.02)), module, Split::MONO_OUTPUTS + 2)); - addOutput(createOutputCentered(mm2px(Vec(6.77, 70.02)), module, Split::MONO_OUTPUTS + 3)); - addOutput(createOutputCentered(mm2px(Vec(6.77, 81.02)), module, Split::MONO_OUTPUTS + 4)); - addOutput(createOutputCentered(mm2px(Vec(6.77, 92.02)), module, Split::MONO_OUTPUTS + 5)); - addOutput(createOutputCentered(mm2px(Vec(6.771, 103.02)), module, Split::MONO_OUTPUTS + 6)); - addOutput(createOutputCentered(mm2px(Vec(6.771, 114.02)), module, Split::MONO_OUTPUTS + 7)); - addOutput(createOutputCentered(mm2px(Vec(18.275, 37.02)), module, Split::MONO_OUTPUTS + 8)); - addOutput(createOutputCentered(mm2px(Vec(18.275, 48.02)), module, Split::MONO_OUTPUTS + 9)); - addOutput(createOutputCentered(mm2px(Vec(18.274, 59.02)), module, Split::MONO_OUTPUTS + 10)); - addOutput(createOutputCentered(mm2px(Vec(18.274, 70.02)), module, Split::MONO_OUTPUTS + 11)); - addOutput(createOutputCentered(mm2px(Vec(18.274, 81.02)), module, Split::MONO_OUTPUTS + 12)); - addOutput(createOutputCentered(mm2px(Vec(18.274, 92.02)), module, Split::MONO_OUTPUTS + 13)); - addOutput(createOutputCentered(mm2px(Vec(18.275, 103.02)), module, Split::MONO_OUTPUTS + 14)); - addOutput(createOutputCentered(mm2px(Vec(18.275, 114.02)), module, Split::MONO_OUTPUTS + 15)); - - addChild(createLightCentered>(mm2px(Vec(15.276, 17.775)), module, Split::CHANNEL_LIGHTS + 0)); - addChild(createLightCentered>(mm2px(Vec(17.275, 17.775)), module, Split::CHANNEL_LIGHTS + 1)); - addChild(createLightCentered>(mm2px(Vec(19.275, 17.775)), module, Split::CHANNEL_LIGHTS + 2)); - addChild(createLightCentered>(mm2px(Vec(21.275, 17.775)), module, Split::CHANNEL_LIGHTS + 3)); - addChild(createLightCentered>(mm2px(Vec(15.276, 19.775)), module, Split::CHANNEL_LIGHTS + 4)); - addChild(createLightCentered>(mm2px(Vec(17.275, 19.775)), module, Split::CHANNEL_LIGHTS + 5)); - addChild(createLightCentered>(mm2px(Vec(19.275, 19.775)), module, Split::CHANNEL_LIGHTS + 6)); - addChild(createLightCentered>(mm2px(Vec(21.275, 19.775)), module, Split::CHANNEL_LIGHTS + 7)); - addChild(createLightCentered>(mm2px(Vec(15.276, 21.775)), module, Split::CHANNEL_LIGHTS + 8)); - addChild(createLightCentered>(mm2px(Vec(17.275, 21.775)), module, Split::CHANNEL_LIGHTS + 9)); - addChild(createLightCentered>(mm2px(Vec(19.275, 21.775)), module, Split::CHANNEL_LIGHTS + 10)); - addChild(createLightCentered>(mm2px(Vec(21.276, 21.775)), module, Split::CHANNEL_LIGHTS + 11)); - addChild(createLightCentered>(mm2px(Vec(15.276, 23.775)), module, Split::CHANNEL_LIGHTS + 12)); - addChild(createLightCentered>(mm2px(Vec(17.275, 23.775)), module, Split::CHANNEL_LIGHTS + 13)); - addChild(createLightCentered>(mm2px(Vec(19.275, 23.775)), module, Split::CHANNEL_LIGHTS + 14)); - addChild(createLightCentered>(mm2px(Vec(21.276, 23.775)), module, Split::CHANNEL_LIGHTS + 15)); + addInput(createInputCentered(mm2px(Vec(7.281, 21.967)), module, Split::POLY_INPUT)); + + addOutput(createOutputCentered(mm2px(Vec(7.281, 41.995)), module, Split::MONO_OUTPUTS + 0)); + addOutput(createOutputCentered(mm2px(Vec(7.281, 52.155)), module, Split::MONO_OUTPUTS + 1)); + addOutput(createOutputCentered(mm2px(Vec(7.281, 62.315)), module, Split::MONO_OUTPUTS + 2)); + addOutput(createOutputCentered(mm2px(Vec(7.281, 72.475)), module, Split::MONO_OUTPUTS + 3)); + addOutput(createOutputCentered(mm2px(Vec(7.281, 82.635)), module, Split::MONO_OUTPUTS + 4)); + addOutput(createOutputCentered(mm2px(Vec(7.281, 92.795)), module, Split::MONO_OUTPUTS + 5)); + addOutput(createOutputCentered(mm2px(Vec(7.281, 102.955)), module, Split::MONO_OUTPUTS + 6)); + addOutput(createOutputCentered(mm2px(Vec(7.281, 113.115)), module, Split::MONO_OUTPUTS + 7)); + addOutput(createOutputCentered(mm2px(Vec(18.119, 41.995)), module, Split::MONO_OUTPUTS + 8)); + addOutput(createOutputCentered(mm2px(Vec(18.119, 52.155)), module, Split::MONO_OUTPUTS + 9)); + addOutput(createOutputCentered(mm2px(Vec(18.119, 62.315)), module, Split::MONO_OUTPUTS + 10)); + addOutput(createOutputCentered(mm2px(Vec(18.119, 72.475)), module, Split::MONO_OUTPUTS + 11)); + addOutput(createOutputCentered(mm2px(Vec(18.119, 82.635)), module, Split::MONO_OUTPUTS + 12)); + addOutput(createOutputCentered(mm2px(Vec(18.119, 92.795)), module, Split::MONO_OUTPUTS + 13)); + addOutput(createOutputCentered(mm2px(Vec(18.119, 102.955)), module, Split::MONO_OUTPUTS + 14)); + addOutput(createOutputCentered(mm2px(Vec(18.119, 113.115)), module, Split::MONO_OUTPUTS + 15)); + + SplitChannelDisplay* display = createWidget(mm2px(Vec(14.02, 18.611))); + display->box.size = mm2px(Vec(8.197, 8.197)); + display->module = module; + addChild(display); } }; diff --git a/src/plugin.hpp b/src/plugin.hpp index d5dd055..57db473 100644 --- a/src/plugin.hpp +++ b/src/plugin.hpp @@ -33,3 +33,49 @@ extern Model* modelViz; extern Model* modelMidSide; extern Model* modelNoise; extern Model* modelRandom; + + +struct DigitalDisplay : Widget { + std::string fontPath; + std::string bgText; + std::string text; + float fontSize; + NVGcolor bgColor = nvgRGB(0x46,0x46, 0x46); + NVGcolor fgColor = SCHEME_YELLOW; + Vec textPos; + + void draw(const DrawArgs &args) override { + // Background + nvgBeginPath(args.vg); + nvgRoundedRect(args.vg, 0, 0, box.size.x, box.size.y, 2); + nvgFillColor(args.vg, nvgRGB(0x19, 0x19, 0x19)); + nvgFill(args.vg); + + // Get font + std::shared_ptr font = APP->window->loadFont(fontPath); + if (font->handle < 0) + return; + nvgFontFaceId(args.vg, font->handle); + nvgFontSize(args.vg, fontSize); + nvgTextLetterSpacing(args.vg, 0.0); + nvgTextAlign(args.vg, NVG_ALIGN_RIGHT); + + // Background text + nvgFillColor(args.vg, bgColor); + nvgText(args.vg, textPos.x, textPos.y, bgText.c_str(), NULL); + + // Foreground text + nvgFillColor(args.vg, fgColor); + nvgText(args.vg, textPos.x, textPos.y, text.c_str(), NULL); + } +}; + + +struct ChannelDisplay : DigitalDisplay { + ChannelDisplay() { + fontPath = asset::plugin(pluginInstance, "res/DSEG7ClassicMini-BoldItalic.ttf"); + textPos = Vec(22, 20); + bgText = "18"; + fontSize = 16; + } +};