From 16a81ef7656c5c692fb831927e75edde25dd77a0 Mon Sep 17 00:00:00 2001 From: Niki Roo Date: Sun, 3 Dec 2017 04:11:48 +0100 Subject: [PATCH] Remove or move java.awt dependencies --- configure.sh | 6 +- ...es.jar => nikiroo-utils-4.0.0-sources.jar} | Bin 277629 -> 279694 bytes src/be/nikiroo/fanfix/DataLoader.java | 65 +++++++----------- src/be/nikiroo/fanfix/data/MetaData.java | 9 +-- src/be/nikiroo/fanfix/data/Paragraph.java | 8 +-- src/be/nikiroo/fanfix/data/Story.java | 19 ++++- .../nikiroo/fanfix/library/BasicLibrary.java | 6 +- .../nikiroo/fanfix/library/CacheLibrary.java | 6 +- .../nikiroo/fanfix/library/LocalLibrary.java | 28 ++++---- .../nikiroo/fanfix/library/RemoteLibrary.java | 14 ++-- src/be/nikiroo/fanfix/output/BasicOutput.java | 4 +- src/be/nikiroo/fanfix/output/Epub.java | 11 +-- src/be/nikiroo/fanfix/output/Html.java | 8 +-- src/be/nikiroo/fanfix/output/InfoCover.java | 8 +-- src/be/nikiroo/fanfix/output/Text.java | 6 +- src/be/nikiroo/fanfix/reader/BasicReader.java | 47 +++++++++---- src/be/nikiroo/fanfix/reader/Reader.java | 20 +++++- .../fanfix/reader/{ => cli}/CliReader.java | 3 +- .../fanfix/reader/{ => tui}/TuiReader.java | 4 +- .../{ => tui}/TuiReaderApplication.java | 11 ++- .../reader/{ => tui}/TuiReaderMainWindow.java | 3 +- .../{ => tui}/TuiReaderStoryWindow.java | 2 +- .../fanfix/reader/{ => ui}/GuiReader.java | 16 ++++- .../fanfix/reader/{ => ui}/GuiReaderBook.java | 20 ++++-- .../reader/{ => ui}/GuiReaderFrame.java | 11 +-- .../reader/{ => ui}/GuiReaderGroup.java | 4 +- .../fanfix/supported/BasicSupport.java | 29 +++++--- src/be/nikiroo/fanfix/supported/Cbz.java | 7 +- src/be/nikiroo/fanfix/supported/E621.java | 4 +- src/be/nikiroo/fanfix/supported/EHentai.java | 13 ++-- src/be/nikiroo/fanfix/supported/Epub.java | 7 +- .../nikiroo/fanfix/supported/Fanfiction.java | 18 +++-- .../nikiroo/fanfix/supported/Fimfiction.java | 4 +- .../nikiroo/fanfix/supported/InfoReader.java | 7 +- src/be/nikiroo/fanfix/supported/MangaFox.java | 14 ++-- src/be/nikiroo/fanfix/supported/Text.java | 4 +- src/be/nikiroo/fanfix/supported/YiffStar.java | 5 +- 37 files changed, 265 insertions(+), 186 deletions(-) rename libs/{nikiroo-utils-3.1.6-sources.jar => nikiroo-utils-4.0.0-sources.jar} (87%) rename src/be/nikiroo/fanfix/reader/{ => cli}/CliReader.java (96%) rename src/be/nikiroo/fanfix/reader/{ => tui}/TuiReader.java (93%) rename src/be/nikiroo/fanfix/reader/{ => tui}/TuiReaderApplication.java (94%) rename src/be/nikiroo/fanfix/reader/{ => tui}/TuiReaderMainWindow.java (98%) rename src/be/nikiroo/fanfix/reader/{ => tui}/TuiReaderStoryWindow.java (99%) rename src/be/nikiroo/fanfix/reader/{ => ui}/GuiReader.java (92%) rename src/be/nikiroo/fanfix/reader/{ => ui}/GuiReaderBook.java (96%) rename src/be/nikiroo/fanfix/reader/{ => ui}/GuiReaderFrame.java (98%) rename src/be/nikiroo/fanfix/reader/{ => ui}/GuiReaderGroup.java (97%) diff --git a/configure.sh b/configure.sh index 520afba..eb20f7d 100755 --- a/configure.sh +++ b/configure.sh @@ -4,9 +4,9 @@ PREFIX=/usr/local PROGS="java javac jar make sed" -CLI=be/nikiroo/fanfix/reader/CliReader +CLI=be/nikiroo/fanfix/reader/cli/CliReader TUI= -GUI=be/nikiroo/fanfix/reader/GuiReader +GUI=be/nikiroo/fanfix/reader/ui/GuiReader JCLI= JTUI= JGUI= @@ -35,7 +35,7 @@ while [ "$*" != "" ]; do --tui) #=yes Enable TUI support (Jexer, experimental) [ "$val" = no -o "$val" = false ] && TUI= && JTUI= if [ "$val" = yes -o "$val" = true ]; then - TUI=be/nikiroo/fanfix/reader/TuiReader + TUI=be/nikiroo/fanfix/reader/tui/TuiReader JTUI="-C bin/ jexer" fi ;; diff --git a/libs/nikiroo-utils-3.1.6-sources.jar b/libs/nikiroo-utils-4.0.0-sources.jar similarity index 87% rename from libs/nikiroo-utils-3.1.6-sources.jar rename to libs/nikiroo-utils-4.0.0-sources.jar index 5f2dbae17e1ec5c599c565d6a1e040b0db80cfbc..72ad2349c73e1b4c1588223cf5403a3de34debf7 100644 GIT binary patch delta 27900 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 delta 25927 zcmV)VK(D`!i4pzy5DidE0|XQR2nYxOf}(=^nd^v=daJLZ#vYZ(MJCWzG;dudjRl-v3WUkl}G9@jS7FJq4 zz$N~z(GGvO#ZVYXetwq=xdpW9iKH!<;mdJKe|}fIrH@MsEYH=>IH6WKaa!eI)B^|Q z2w_02Pz7lI&r)c<1SMg|7hs$YyI~fs0jVqr+%dETqlp zJ#t)lU|a5#YRJWk!&0nPA}e!?e%cKfTNYwT0<(V&&$h5GOpAo;Gbl8iA_ z1B%rEZJT54@F;WJ0`v!qo>I5T{d!k0%^uJq_bvLd8xHpf+H|(&9>~&g`l#bgJ2W>4 zT!w!DPNxJscTs4|av{V(`8b8>Vet6GFV(SFk2@VmPpv0qOk=!Ke7) zgAl6_jYb?P9QB6Oa2pqoB>s}l=JWHLyMKSouCCmfMvbDA@A--$8_=O!lU&9XS-mv`(r{FXlOCnrf3%U&TBtwZ^w&^$$rOvy;5R1a1pit2fwZfjLojg%Ky6naMSicL*l}MxAP^v;S0<={V z+8Oo^l5=@_4P0yG2oT{H>2rD#G?IVZ7{jsrn8R)_?wi2jmn`#+-+us@{i(phPkhC7 zce;cfSWn%SiOayc6uXuwIbRx|l|rsmL%uinuPiV5QT>ekiO&?u*cf`*ikfp<&h-o*f^Xa6Gjs7z*p`1yV6?z& zLpgu*KcjJXt^98i`guN2h!!mhOpwk4obJB!y=xLCjJU|rJkY-~ zvsxy%ZEM*vh?IJ5f0XP)7OjP3`F;24YPlh1!7%}G;*ony$t8|KZhQxoAt?WkX=I*H zqyJ?Fg&Dd(g;p*?^fij6<6VD8a&@Lnlf8YJ6Op=8%7Nr0;onFu8eZJE;>VX{R1L0Y zFoLgLzjH%s<28|9sw56Ngu&tI5BQ!_jT&7E>awumrWbvB3O9j2XO3AliH1EOI1f>O z?JZ5bVg*V40N%XuE!NeKL4D$YA046ecjuC@;VXX%e)+|NRy`Oy+h2dY@Qw>2Zi3$KbIn>S2uc9;l{pamVp;Y+MVX6;&6JZDKa zB~6@v;rnDf34#Zs`@4Vdr+*razaZ=6&9Bo`iS`(zkHoX<)xiKqJVXGiOjEhz0`XHy z_qwF~O;BQW$vsbdCD*noZJtmgUOur1BX{cOZeV_GWO-EV8o!@x^YK{T@ z{l6NFe)9z6norN`K<6xi+R~;yA@_PK)8SeY%hLTUT($L9TQY7$)RkN#6qTn36VN2RP+!Ug8$@o_2-xDZaq$w7iz>G2`p5)r;) ztT*Dx-?M+xa*lPTexHdhp`O6_djnxX&;lF1p0M4NIwyl0(>UoS95HuYov9~ygg;rRtRin}Clemv!kGZ>k ze|_fvgMm5?b$;fMRNLY4d2d>qB=t<(0HsC6X9i7Aq}aiAFQ8-ke9qloe_g9RT1KVy zgco6NgY5%oe;kcU51LIjON7+$lg_C_U$k>7WQcM^ ze~HwjH?ufLuAP%WGr@=Uc|T;tltzxSs`Kio7sey!@-)?2@Ih_vi=;DL*KIBTT8c=b zQiGj{l&wIg)Gi@O{g?$1#8fFLrM^*~(s*k21MtVVq;ufDXmRjQwuTvoQN)rLZy_Ybkiazl}J z#%fBGL&K05gPjV%nT&6yUvrvVyJ!;de+%K_owO#Xt!*u!>%Pm4`j)iXdD#*+Liu(# zK9A=pB@5BM6z4M+ECiatuTee7SiDX)(4Bn-1-C+>T%y_3;fGn#!|e=(ZE z4jlfMgIup?^}4RRTd{Yv=B!HgmK~U7d;hp+y-GXO2!1%Kr|iDLx$hu8?%=FFi4tdj z4`+V|Xa7y_dq_X+G+)Ph7YdH|b!3ZX_QMViviF7gT5R0wjaz*-yqXTbucpI<{YG-= znkmySq)qS~A88uvvsfq`Cn%}CRCFXC#Ln=?#q?o(^>8*CPlh>seb& z?CeU0ssI} z2bQM;9Jffb0?QWz{h@-FsEq?6m!L8P34bnXVRm7il1*#FFbsyz@vjg)rDaWjz%FIC z!M-5dE@KBbQ4>?g4wljnO8@(8C(y2xFcyf34Z(krl!UGov=jS(|mNG-Zs$ z_d+aYGXXPr_YuL`IvA*VPldhkE@j8{uD!!omPT~hpO9u$3ik2^40RR9v0{{R}O9KQH00;;O0JrYaL*aVG;We^}ph6E_fkw*Ly@r!%-`9y-jF5Qad*OlC3(lR!HIRc~jike* zkpI2AE8U&$mkBM2t8Z6V@Z_3b3APe(F0Z9lDlV;p%1#^mogKBgC}`W+Doei-ww*pe@nYx;dd?Vz=9{|#~%|>SgG>9 zY|om3Y-B6r9${$Wzhn`=mBn#x_071rZDhKZ;dne~_5IFW}I>E&zFo7b+>_)JZ zTh6SafA3fFgUH#ZXPL~e83y<^CT)5=E4b!cCUg1~{Hv`PRq8~9%9iUZVTUF-No%cO zDZ9~XhmO}kc5Q$kEP;?fu-M7+oC&R!My2I+;x}(BxA5^n$&~GIzfk}%%wN#5-jg}& zuZaPhglI8UT6V~Cv18r*jJ%lxm;&h2)QMXae^-KuB)Vm5ne#033NRcenKB}B(kcA^ zDv&}K{w-MG%$JdBE%@UR>!LBoD2^bvx`F7eh@0NM_pssEyPqFE`sF>wdkseh;IS-& zh#sjiq#^xK5jkZ@v*31v>lRuR z0_etP-rJK`5Sg_CKOu51GkIc5o^_41c8S*RMhY$`M`P3u&%AH*#9S!Vv;6Yt^zxX= zHQNcu0YTg0As7{9!{LO4z@RLhy+zm5f9s1k$JKOc8Mov%ltznL?PK&kPX$05brJx_ z7FZEvenrl=cx{0xyHY9>m}EheMhOoB<;g6T=GQ9P(cGs$itn`z(Krckd3Fd#t;{m^ z`7^l#R*tuYZ7hI4q~_g;;qQ!ZJq02~iVVb|>VrczTh7>nu^IHl>Iy+Q6CW+1e;MI< zub_3FJwP*aH;X0_0Z_Eo_;_3`kV#{4*fdUK+8} zpj~}A50Iqa}yxcpw78qwW$*P3(A{k0^nxF zQekYLTR8-S7^`9~iofPtp zzF}nGJa}@ccfYSD-?f`U)9qerfc5<3jwGsjt$|Ff5Akfaa2sj79?V-jO1;GWXFZ&U z+7b0FOH^(Jv>uQO`x|b^*1@!_l9=r_0*kS7EmOEw(^h+1n6Wvq#gM_)f03z`{6z2V z(7aIeJ$u2+EyNtXb7=_sud80Qt$M)wv@a8>j)9R_d<3#@h#rTw*YGqIo>NDZ?y~88 z(Z303>r_aWP8?M~Bl53uY(8)=sBC!ptXv+rCA8JYa}6)81j%j#N3soQm2SkSypxRm zq^qfIPm%sRj$rmjK5OXC=S8JsmGg{T z9lPG9A``y)^j{+_m}|kd{05UHfhG+wgyvaMM@Gi#g68u3N%7PbP=wJSk6Ks-(^TfA z2vd*Ju74=L`0j~Xe@k?Fyzqb=K=lk$y(s$R3&OkiL^`JF-GghxfiE#m!(-+_>D@X= zsk#nSYt~fcyX9%??iD-NYoIT0j1}7$Vi6aBmCf>K_JZd*^oLIKF>7BMj#frxr4_H> zb{@@#cRnJK8P%&bGR)cS) z-U7I`5lle~4y2x)@XTeka^>!k@oY){(h0ns{tZw|2M9XGi?~(>005mA002-+0|W{H z00;m8hTa=);q8**51*t>hv)e%3adC!Cxef0(IdlUL<%tONW?$t;4C4|)UI8&<|<7qYwr zy3GqUYXEaqWZ^gxHa)6qxjM~t6B+x1)K@R$GBUDZ!D%&%6>tWmvm` zay0c%b+uG=v$AuawPhCFsXt+Vd-s!1w#6sn;wsl-R!FUdDra)3+d?)R>nFcW#YrP%QB*ftG!;UsRa58cy%O(b(JCzfWHrkHSOyb>ECGJIP_@L9 zOyGNFm+NW)8)jLKBeFnP3)NgznNIQZ{_+ri(RR8L8V?50#SO4lP75V}W>>&aB^GkY zU{_TuX0V@@fXoyWM>JOoL6{@iqX1TOkXvz+H&@}<<93+=;waS#NFDHEye3@m-x=C&P69SG#A(djpu)f?n-2<0gWCAL5*UJ-gz~y;iVbk&bqh zdk#j36r@x);i2`KPpiab{$7=$lnX^C7WAKy8zcmM_kN_P+p@_)4f0YqvYaUkiDdve z>%&0EeHb_!pWBr^)coZGQpR9;lPoNcBkKuFl8wkU=v;q!WIBM$@>wTdA$)@}Yf2wl zK-0cVqMn14y?lLtdO98m7tcxp9hf+gLt;&~x3;$K60|XD+7?Q2N_uu+m5HAj(S^qd z(LEl3feBF==IJPp2P9L*yY!_o89UHUF7LBKtH#iQ4lLLgrC^!9QghiBO){Q{Iha<3 z)7PG)zfw(GmmOyYHo`I`2UD&)m%-bwhoYZnF+qdXKL3q>+4L6I9UdMAGG`au}2j6Q*sO#vIrPNx}iKvk*LYI zPr7rk`yY{RW*t3`E$s%vv%jwZs18nUrHR)t9rTa@6Eps>A|y1#s`&@S=O;gnORTYE zkfV1zYa|kXXOc$mMidJ02>TrhB=GkebWK%Rtc09lWMy~JY|`dcy`XUA0|aw;ayaCJ zv4ppZt+j{pX8b#d|6f8WFa#wrFpt3gfgN&^fEIOYMxf!@Ctqmg(@jM*_z z(x!U7gy{9T)T}~i-|7{?-U3n{kf~1Tq-XPltvBp{MrJLhj5M%@*sqygiR7dx)TJzr z>PrYa%f>~~f}|K{Zg)D3I6j~b|Bnmqz3tB?(-W1tm?`?WGUyvZ&jS7+8GI0X`K+o6 zCCh(_&kgxzcE;uAqvtR!`m{sLGzvNuJs{7D@2i;03rbgbv z5atI6>@+U06E^^;v)EbDp0e=T*`D-Ht?Z6}J&!cq^LPiqej@8!&T~>W>QdDoLC4L` zxZHg7blh1>1J2Ay0X41QOA_dPXdZj^@WI6%K9tRWuB-#{KVHspagSjWdg$cavNdP< zwlh8X&SUbOKdgLP@qT^lIWL0+rS0`mlYGj5 zI`H!t_y?upM-qFa(~p;XT0LOngr7Uv|9KhufLehqoR6UqxG#|rKX{tJ12g*nz({UK z&*|kI1f5={x{-CG-#|{3j2=S>1z{gPc7%p#{R@n%de440Hsp5>XA7+vVli+zxJx_L zjKpUX@$2zKeD)iT*=g0~ovVI55uf*eS55C+_4!16(O)HD)vrGP+&q{M4*NTEuB|P3 zC;TraFx`W{rvDu`)D1H(sVCwRBASViJkfdFm+fMz>aQVFl>KZZfP{P%ySt!~rV6gN z&2}W`FmeHGn69|w45xyO6GC`bgD~ti@Qf4b^N)IOU=;BG1I9e1f;UztX%J3-Z%%44 zOK94dSK+*bK!>Lso{TX^#62~gaewruXZ=4}OLb^*39)E_A2{p=hskrNtP|lWD$@XX z_WVlCuCY!)Y|Ci0tu+v{){P&_5%ItMj;X9SFh{dmZy~(I=jBtg&Po+Z0`rS=AQp?U zllw4@cAS0bN~>Lp&LoInLc(cO6CuI%E3pQ8m05x{tcsqdY4%-M{ z2e`$x%S}*{yL8EY=3HrV;*q)(bv$9}qSB2h@@rMBunU{z1O&8Y3OO%-S_+&*fk0L% ze;;a@RLOv9s+mIF>5ky*?jt-w|*jVDNCnit2Cf zgOm;^$_~{-V`u9qfm1YwHDQ14G4@mPTFsiOUM1u89!50#)5909&oB0OrwnVVP)U6= z(OlKo0rzf4^tB$hnj!LkU@}h5gsSVR))DRZI@V(`1WUr>%`s@FA=>{JgrOk#c6lkA ztC(5F=NJLkaUucq8Za~BAYPu4NPsx>VPPr%=avp*auDT>f`Sv7H5ARg?pD(>iul57 zM06WN*&rkwOYqU~3Qt0&9LM^%hY}(`u##??j7(XUcK8Eb^GSGrH!^YjF{NM0=xsUL z_;fq!s<5QX-B9pufU|XN#@@bAjl}CHXm_1wIx0b0Nm3FVXTLahB}1D2CqxST`Ccm+=&4_|J%+q47kRdO#Qa84$Cg z!kT%{WL*5Ps{^rrae{OI`vSLJ5Fk*&B>`Wly=>?XltY#3T^JzY={5F~pko~A`}eZL zqLSJ0+QwRd;z_n4Lu-U7c5_jgHh$kU&}c_I&eb^&Z}}3INV1B|Zc$a&SQ@GZokI9o zR$Aw1XTg@%JphE*gj-ULyk_fH)%j(P_qck1f~Dh#k*bM*3W=@5hR1WAXG33e>te%w zhTht~Tca@8H~~1fssUZP5d=6k5`2j#P_WUE^zbm|2e1v*V8&#^?1-$@tuplv^m>*G z?#hZiyhY@XYGo}pcAb2oa<@QIe=^O2?0FG+-Xp^|L8^nMF*vnB)A(Ui$nmM=y3YiS zJJ1hFDvMfwuunj(!Cj3$sVJP@NT;x#)6K)I()Res;*n9m6Tl+2^uGONCO-rsuzKRk zX6|Mqn0cy@U1Qr9Mi*)U5!(bwPQX?G3=}fU^>rj}+027`wQDz(iX0z$_eMG{#9Fo; zox$NJG>J*jwQ1?sQ+{j;NE>dJ%&C&0Ag_U=FAKSUdO|TFdORE;BUM)m-?XA5U9;CE zNF?y7IF^t{!UV;UqbzRZN((MlaR*;g?liM?#UYu|Gsoz+VdH_c`&ff+m=lF}Jjx;U zJ1uZAf{R*$YA3oO2qy5ke?5)Uc-I%Jt9EH;(H9=4K!*!QhU#__e@ncC_S^4(lG;tc z&*3J2$Y5fWnPI>CKy2(o6Yz5gLgEE&J4{~^j*517g|Yh+p%%+#W#fb=hsKJKJ|h9T zI@}H+Y`()c+%KroeTsF;M??<_l;E2?1bns>IS?M5(({W~CojJVt%R`zY#sQd&)U3z zs8&qPZw{h^F>`kQlFH>$m02=+EJkDd1<&Ju%BiNx9d-NAalqc}5J|26)Zj9i!`@?<$@NKjcj|U6V|4E#m%tcop&860CTEzi%;NG znBGOW>7!?E*Z-7SK-^RNnRJl8Z!8FeStFPoEFZ=>vLiMm;g8MZI7?hz-DE6Y#}F(_ zs?v!Vz4+_9ldsU^uinkt8qCZ)lHL)4npgNX35L)sb2%TK`2%nS6Qg?-_3es(pOb5x zng>jq2=30^#=3q+?{4i5E@#}v9ZE+3OZanF%$sMw)PpAUzlNPQ{ORAlrsml_^wSh< zLhZv21N%C3Awj@xT#0#R8WCQ2LeX5Qunoi!d96U-XX>aZz~3|@;QU+qX~36(Daf0y zutXjayP$Z<teqlG7bJ39t}0AZT+ZT?+XRqHPmPsC@|3-+p7Z_BrDJ&(4b z=(YLorFT8LOU(N3`nbG;l>;lI4_h&gJ4u6^!3ImG>w$n#{WdJz24!E*YufrNRdy%N ziI&cod#DY}_jArq$sV*dYJ9Qc2w+N7;`i~m5`}M%nO5?UO!s-Ai9w=&7Gs&nUtLfM z=oXv7HKMh7G4H>whBnBua2U%H`V}cUzACY~rfH}H4 zu$Nj{i64dAVd{hcA8ouL5Hup}+pZ+Aux`Td*jZ=BN3&NisObzV`=xPyQ&`mei*v2P zE69n}3vYxQ78vGt?TO!i+8BL{4hAHnmGRed6W-Icv@M0)ePa{pyW8Vukt-Ss6cXg@ zypgl(iyF*u(hJ>*%mmsjv5jd`rUTdT_!GZUo{YQR1L-@)b{<*xLXNm&hDS4`NnKEw zOj+uzxY=FlWxUghXgr=+ikddi2bG0jpF=uXS4A=&-+99W^Zqw~5If^bzhz~ug|prs zn&&GGsZk2PnMqlc$>^oG0+|Bqo>G)c$1n`*SlnGXiTM$2Dtq|uF;X7ucU{;-`Ek&* zu*MQ_<$^`dIflUqu*bT^&}vRMzP#Dl%2~Bs#qGofPMWpeOOFfR4j2J58-%(=&i;7N zSwk}fjKl_Q(>2zAJek@GQsx7LLE6Qp+#)N3`ydWAtRngooKW4fs_2W=rZ?|9DO+#g z`URS9DRe29`l@maHXg4l*>bu$d|!G28UdlP$t{%_0dq$7J$RAy-cR@5(F5YzIB~pA z({wCk<9v|u$^u`|i6q?~zUH0v$h+_$Ct%&xxtW=qO}__!DH`{BV*Hdmn438WG&a4c z>io^H%1e6(h{6tK1kW|;PwkY?9G%Hvxxh?uur_KI&WPz%$KIeL@#T5D#2c^rjjT&J zkxoW!Nv#c);aebKmn%k2g532i@LMlDkNRZ4isshYyAU9PFDy`RJzk=VFkwt67%SUB z<&1;4_ljSC^m0mJ{o#nYgc|ILyEJ?ei&i&S{L89RVUI$(S(cjMN}VGB4`l1zTmqlT zI&*StR*r5lzAjJ>-g2}pXF*--+M44qJ{-yc#27I#$ZW{N(Wr_1?i0`wE_4Tlym5kZ zjDHy-R&N^rm>4&nG|;Jm4GS`Jn;HuImk@075CmI)UGV3U(nwUvvW9;IW#9e{1s>2Q z&T@ZM#g2D3gLz`lqnNE`;FHl^92jsENbobR&ik+TSxVV>#7*4uAmZPEY4H#0_#jWs z!@FU2GhKT6$bw9BeT-f_p{vc04DQ`itB{5=sm!v3UrBUGff78y2WG98$!^%`ZkW9w zF_>sa3Il$yZMzhHMH|*QQrNqlcDl_XT~Ll&!~94B*@fmQ_m(^Krw|}t?{(Gg9x{Gq zdY+qG6zlDO0#Hi_2)KGTPZkmY031n|A$J2Dms#)w6_+qW0}8h>Rs)g<0~xPuh`4Yv@+OAY(fYm;RsDaeN#vV(z$k+OlB>w>}_PpBdrK& z$^U-uz1`KfZ0B0;I0kUM`@X;5!jgM8d?wgLxS_m}aTK|!l0kCN?aIY6iWU2ff8s8` zRqlygh%k{+cu>0Vt{}U$g_Ar>Y(5Oa^uOc({u6`26&as`daxN3*1w2Vuga%?sv=9t&q>>_G6P}1E<8hRR zQ$~O65*P9C&nup)c@#6`1mCy2%XAV*&yXXIKO=MYN4JCQI)L*-6n+vQpqdLdlb=M$ z{&*G0@J55*vuN_0@D!7wiWq0Ff&1Pri^Vb)i3k-(1A(AK3P~g!q-~<$5(xeEYRO~1 z(8AL};TO_q6ad(JTGRreSg14(38_)C0;qqQ$I&eqA@^&QHR#AZpaSXu7!z?E#R#+A z?IcLfW5%4|dKu0@BF)n&MY2|_$Ljph>K!Yw#U168i0BUyLk7e_y6GZz6H{%fy|vwOBhI>ImUkg zM@QQGbl$OtY-<_Lwjd%XBszvLu`xeuG=yj@gDgssOek(yM`8&OhC3IGVM!Zu6#;>{{^Dq>xgzwS+7S&WC)d-+NYV?UL>OYm z(FK}oGen2hnv}@Wfryxp#)fd;kO_aah{+@P8!kzO76mj~tC5XY(ETrsDibi1)HlF% zus?i0y3%11D(1n}4l=r(1AFE;cpyU;$V?r;?6aLdQg8zi&eXiuV=vi`$r6kd9kCYB z>*-w4cYcs2bBB(AVlk%5s;-RBT7>tAU`v$dgx3aXYh3bj09Oh=QERK%lf8f4DOY@b z&6XMeLV>P@Zd0BAI+0thqkbGMOb8n<8O2&dxM@&C=9M5V+&UOR9pmt+K!-b)3whXj z6l5_NkU|x&9l$!MdjL?LP=jcLR=MwAatT<-Hukh>g{m-Y!Mc)Ey z0Fo!5dpH&7(&mUG0W;;>3*2$yN$HfjZnn^nf_;VqHA&t_PfwyK5SUpcPOmtHVT5EJ zvdvG^AasiZWx$k)&1bYc-tL(LCC-~;#H0bt?m-aULUIH!h^wgBg9?90f5+0GoZdaA zDQpi)!78v6v7hwTR);>=I$6RGWHFHJ^q27&Q+6eza+5HL_2zEVj@O{pw^un#wr<$` z-tzc{PXbX{1({kb$6=un;yoT_N8LQA$V*5>_pSwy{E#kj;}cWUe_+zfpiKKx@tyvm zL;a2%jj)}2&|E>JI7NS1Emo(<%;!NOG>)ASn>ZCp*?W6cs%aWkYln)ux`bVd#S*_d zTQ1xUC^feFjJ|CVUZ%tNoOVh(L56*_l~yOSB;;9(wH>^xo*@BEVTJreT&tjKTyR&j zE?7j%@VC;CZ6wRvc*oeWN($kiMFc`wFm3HMH6V9XQ#JTsr0;+CnMmJ*N$`mQelMUU zaTUdPy>BbMWBCcYXg$BHAy7&5)_u!NoKY<8v{j1W!Z`#hbjH)q(x(?JFn5+GHZ|*s zxxLN8sNyA9o^I;22g5Ao%9-D=O#--G&S)eiIZT=xfKpJC=DMZj$~#+U9Fl8V*j2z% zU^Qycl+}3^06l-+MM}J26d*Vku{lqm`9Mhf^xgzYj6>)|p-=}J0Vkjvb{C}(jZt{F zh*FIiyT<6Za;oN79qG{zjQcMhb0KGQRRs8vPBcX2HIebkcU@a5P-ZYsZY4Ra z-~w$b3cukCG+F~aQ}sI&u=>q`1s}a&pzT>8m+Y4YL^pqdelDEB(1l$D{?f&w3PjNn zKx{h$G7D@jy#`)Sh}XrK#gW|^SJ5)0v>}@r6CvTeeYD166^`y}$PF6V;k>zHF{4 z=S#gfR)y);0o}`AFHWytkAE7!J3W4{t5K!IXN|%hn0>VfRL<$sE(Oq8#P{8f7Q$;kg+6Gj;wr?!k+tv5E%3go;KA#vGrWfW1e5N1ba1zlyuR6~h zE??5;`j#YZOIq2DkmRP8R5o0D0QKV)6M%V5O6tJF z)8Wp}m2Jx~nOu_^=8+E1WOBWTU|x&@u8%Pi(ARuQBRm8upZ1wI7v2r6t^d3@eZxMS zkJ*1?hLW=5i;E#?gU{SB#UM?h1RsZN7d{?8rYSCy?xVaayb9(6P!6zjg$cg%`Rt5+ z`I4*kacIs@_9^g7ccT`ZC+7Tg*efg_gOSzrjnGp*u6ekQWBdqQ%=Hr`gjxzJk%Fk3 zIXyy6jRNfOknOWCxkf!p`zH-7LoZ0DBEf$*A`$p~mPBlkCioACj3Y@7KaVsIz&eZY zF##6^GB7#Ru&rV38OgwW1_Wd&DN56+xf>j@{eyyoiGJ0=TX?$F?$W(K<<+{>^k}rmOD7z>E*RZUmQHd9=n^$`?MX< z$a7S1@7`7M=J3$e8GG=!2>a}6wMn0CD&pRQM11-H5qGcbP=p)}#7kQY2COL?bpaJP zy_lMvh}lBu-cfEfVY-+=E+U+ag@>;-l)Ly}L13X*9EQ9p&J8pmVJKuS*QkHjk$?HFvIMn_>MK)+HBJSvC~=qNlUw|3UEBn^W66 zFFfjCv5{0$cM5&*;GmFF^`I~{`XOP_$-)9Tny}F4=xoph&a%jF@p4ClwYt~d=f<@s zs~lSLXgiA>{y}W6vUgYgo@-yoV}aZmT0`nB5RIs}f~tp%p#Xm{XbXVmx&RUlN7cfM znOS7klVa@a3rP6qq3J~!s;poOB1@V@(RP)i30 zp0d_yJqiE-nJAZS(*hi~B4q>h2n4OQeoL3#F#{o&e>nsSf9+aPbK5o&ewKa(qMNCy zSf<^VKEzEg9Xq*tCXIWE^VXRRL_!v7lF$*L9Z&1~?cH5~AV@+=>~k{rkWMO#z+$o3 z-EViX)P`qQ{8F%`NGo|IYo*f0$U+}ar?T9r+OR+PHBY5VU&%ro#|F=;O=I4fTJSPD z|3;Zts;Tmqe;+fkF;Z0{sC-8D%6?{-q7t>t zSjMxpVER@YQ7+hxG;5|eB9pvey4etum8#jFFA7;*G2nftQ{?dD<|q7fv6kBL;DuJK z9h^Wk*Ue=G|WrQlk#6Jqw~bh4@CH3-d6 zT`ZUNaW_<`>XI3y&WrqH&8tgUUB+kM8NNgd`MHalXW|!L<%Ou3!H1eXXO+0=%_MVB z)dY1l0eMeA&#;senNtKwdB@c950ROa$mrw6hS$7Aap^Jm&#dVbK(6Xr5RWw)csk{U zYuBo&D0O?R7?-Lkmms!USyIMV1|DzLGFyX?#4l$n)S6jyFacNt2rt)W#Fy=F0~mh< zY<2KGy1|gatP3O;ND#zGF||ITatJHaeNlNyrHfl~?eo5lWNE zUAXqSTl?2v(Y17N!dh_lWOl-xOdyiA z5DeTz65wUknR$GcrY>R!3AtssN4SO;g}S*QmmjXBDGE56K|H8X4B&UmAgDy*Nyt@4 zgB*9`Hi#t@#d1{%y=U5hMZAA7@Xp!60V8I@jO_!7BKOB}a#^kz6iO8k zR8`zYTm^@rSZUc>pCS9keTCr3x422`ukkR_Wl7qvm9=j=%pNqIw1#nl_hN~qa5D=G zh4Y7Mszv6dM4$}9@RwENZYAn)TaxQEUWg53CUl`B53+(QEw`FsVN2Ln9%~h(2EKrn zBXngvThd|ZnWs(*01SUl^g%;llKQkgfuEcp)BWc|b0huSVulF-i6cfcSr;j`ctZkd|mawhr?~#L?AjBoeL5|UU(dXb+KB~KXx+XyleRG&c zb(s4XD_a}|ij^<#BQ}$MbCWOUCN3Y3{G`jm`8|9E6Q5n=i&wn$ZYf(^_HE(X-f1Dr z^-5U0Z~e;aE2MuK^a~T58;)7N^EQQN++=H8FpN5hObp6py!}SYWj7JJ_B(zpg4!;0 z$sKnwIqHibu|)Y<&JF*Zl*+q=>iwor8SfXMyUS&mZ3=_g!(D_?L3fYc&>=t4pr|Bt zFThU#5|6i=LJ>xjxL$FX6hD1_d-5_DZKWdRc<6EtAcK#mU z)ucByT+#-5_jh3$85rWNC{^4P{rvvD3gi3VXHx==bjkB;8`HJY4i9Nt{2F$*+wwedoNZlZD|6o^^Hm$T zjN7NJ%B`d!quKr}(wiI84LPT^*c9Mm$t+E03pV@kVbZGkz4FelhxfEdm;p+#B zL;TSN{(Ym2doO;g8o>N5NNXcC&vU%LH_L;rxeeh)t5Q(ib5%igo$$n5vuXI_Z^2vA6q39$$O05Z2AcLV(kmwD3y5SO)$ z0~H8KZDD6+RAqRVtMvnIf9~3vzlftG6Tg#Jav+!4;6)Tf$!=r#rN2;N>PKOd^eU0D z=TFimRbfYAQe| z^OVS8PEY{~E-p_7$c6vEka^}si9i(LdAJtm&1zGB{Ri?!e=jw z(E?AA`d{0G^DObhIazIuj-x10;9;WV^u`*09Zi*3z^@iwpMU|-dWc$&U;_o=RM8A5 zm5MZv5qI!=d;@+1f2=l$=*tQb(I}Ia3d$+NjOGrAO1~;Fnb9Gb$Y`lBU$E(b6I+K& zm#Gp@AQF@pVJ6lmkc)Yeu8Sq)mnUSRgq&b7gBx)f`V-K=lG>yfo=kv2C16$&Zt#_v z_VVDl{uKDn(^yWFaK?cQ-}m>1FjCTjXem-pf_=`%+wbbse}$U*V1L2zeVxJc=Uz$v zp-!IVK_JFKGeB6P_-0 zA;LLEj5R3$dXkB0gi*nqgR}?Cq9CUgGLAA2R{#dypTG)|;Z#6W{jVcfM1dd#2dwH% z1c^sWD)mFae|5Xfq!3pI7^Nfx6O@Bp7}6AtR4yx8DzWqdA6R~3N1H8T;M_J3Gsvsu z(6cNZl!(2(JUl)6>g?$J?dj#k$=f##`4mpt)>Wf2&I${J=oY{VNrU7_=@Fs7(jr zrJBh+fJ&J~YYi`I7L&6g#D$MbkZVcGSQm?&lyhaH0qX}XNI`I-s^!8K#KPAmH}gZt zF03fTLIqhSbCp$#Na3_&Ram!HSo>6Au&z0pj-xI)J!phU%w&+N{_anN`2QIyBfOw8 z*%Zcce-X`eZAZu|ww49o`nfo}Ji=L+sxwXBEqnE0T#5sZ(9UM9b zQHMgT2T+THTFd}-GAE?S(faC<^<+3#oe}sE0j#ISstUwa2(EUa=wjMd$cG`uD<9(A)Sk+br7YS+APfZYC?jhdcLGO=Hz?-QB~wq_W5sgWC>c z%pmh94eO=O8N#XCIEua0%%}Bkf7hm4>NT!Se@yf58mecg+5tmGdga(C#_)ux z35&WyaF(v{Tt=fp7+n13S4Ur+yt(-5;Oy05pLLoOteDTPK^rO^K#0t+quH$TmQ2pM zP|bDeEBB^eNkp>>AxDoFE^oU=kM^@)0DxAEil-ZXGLfn3*{dtjz*AQb{X8Zif5;ndMeg~y)u&@soLeN1{` zNo)cg)a#THDoE8sd}^`FGU{%hns`*4)jlon@@c7ky0(4#HR>gomX=FJBq7}f(?l+< z_Qn<0uDEdp^2V9e{g{vWOy=@f6zDqS=_ccv6S|vuGB`dCHI1 zdW~?N@fd-@AFC=bT(R?}yp$s=^0;4?pPC4R0q1*&tMfA=8{RCrF%w^S zNExJoQn9l&8fmOoVj?p*OFAbZG~7uZ!$xs*Jy9{0a%B{)%83YZKaHbQf0WR$b8~aqej4c>;9DZJwEjImz>7y;r<~Fi>*C|>cOP%R z|9Jbu$J=k$yS3B#_{V7;Y;NpF&puh#v23CbTFivH_SgV!mjKq}5GK5!pgF~GXsqhB zBIb58hz+rIFO$o;1p$4CrUv7kTX(@%#C26)M!F+35M&WA6o&+ef5j96zQ)8Mt727~ zp;FrJ--;HgyM-%HHs~O+@o9*K`9#(Pfva z=OU|>)^*Qr>P+*en|d<9fn%lCB%!5s<| zcXxM(;#%B_7bxx?yg0N4g1b{(i$ifK6nA&0XesigukU-m_x{ORSvmXcb7t! zXL`O1m4~f;5GC-rT}jzpMcOafS^VTm9Ut60OXettpk>T zL(+)TxhqV~yF+&*BkyrNaSc{PdeD= zd}*bvocw3i@*>;{2m7vBXN8TMW-w@fN%lG}<@M}pF6)bcYYE9>norV`t=*+^R9LUB z8r{r{#o*3SS6FZCs|#JBS1AMV=ZGhzL2paz)`v{b){~{&hB4zIa-AX|z7dXNh?iadSAcL1FeK zp?d86XYkrlezcW`&w$FJQWMxKgUNb=njP!DlAnhj1ET`(lsrNtl8CrdB??>kDbgIW z_Ac;6JD=!!l`SYp&VqknHp;~|Ga%e&v#MVd`k6^mE`>-dWsC^V_-d zj!iiUKWeoC<)|wI^||{slf5qGhL}XdEKmajAb@c>}qc9AFdkMPS^nY_PV; zfDe~~dA{?dd7?z0?r8&u{LCmB&AZJ*c47C!@bdEhwLN6QJ#~Bw(0kiSG%e^!*TwT{ ziNYk{r?$<4F4k+brY@& zfvtQ&X@{|;_l+!C4nGR(S{4|623#9cSATh`tZj^Qa)&RVJPk0RoLVB+sgn+~bV}QE zY1nwwOUAP_4zo;l3~Y(e!nXH%7L4B1`>ao`p#@L2YQ#g97ZKb!V)mrZ>brU+_L#6* zxFF^8VFyJIIC9I#X0jFsKvj_?px(i_!wp35_-Uo;M^%Z>DKDKen1^Xe3*Keai+bOj zfii1oC`V05zJKupBqshtA<$cbrQ zKsO~vjm+*$d<=Pc@4>=2^K{uHRYt}~suUK4-;8b(F)&q(7g;^@D3@UF>7iZM* z;yKsnC{BY2mj>z^&iS_jI$+5{Q#_chLF9*58Xq=gF*vHNbR~6_dyd70{gLxDHb9A&GVy%UGAo30F?nTCiH`JH0r8YSQgzj@xdpo;6hc`M80MR*Y3t_) zs6ridPaQb0-}*knteB{jKCWG8E6krhVi;aHoIbtVrLi@nHJcak!2(>1^nWy7=NDb6M{5ZB&d_Oby(Dslph|>JjGJWgJpO6c{;NTRK1lm_&iFH$ z=GW@M>0vmjiOhJdZ3?d}Fi5VVhMk$0tt(V%ky-2_pYahYyq^w3i1O?3m zI{V-*m;FGs+=)LZSE}QNH}`_w4OXH`3m=HjDJg`W=@6!qttuZ9%>GDPU9yJPULRoS zrOx?vEGLfoT9z{4NAGa}_atYeVgumiB*1E>l8--pjED1wS zjhX86>E~gN`alk_e|rcL3twfbllN{RqtiIpC;%LRBJR~xrOzp@mkBOXgE!+;jck!2 zhy}ibp%1KCnY2a|H4b;(z}RugC8m|#5gsR%6I;^AsaoEV$g0v(7mqk!>AOwKuBZ?o zoFPv(n4GjEEFE_&|8a6`sa>f4eSiz`hgNb~;P-`N7cFhDx9xES9$HnOc={t!W5_p~ zjBzz-z7-Xzr6pzrvE48pt-+c?g^?O^2K*j|cEZa0i%;}BFYL6aKz-2Tq^fL0*x%uw zCj14DW-KWQu_^J(N1M~Hc>XF$mhDfd>LhbAy*{}{*ucGfWZ=Z?d@Oz=L|9CC^J65e zVcBpfA~_l?rati#rrYlw^Qb3GfV>b4f}|*|V4@z=hH3@IP@mOTm-`q{CT@m43TW~J z)z38lM*q$W6`s*4XAFd49sk|V)hTd=J$9hmEYZWt=5@RxEImkjOlQ1wxkhMi^2%Qq z{Q1M8aXw9s1lA*lJIF#?3av&_;&3Gi=GTdx!^KZxkuELUPZl<&c~TsqU9JOQCpJl zTDB)q@$&3M%ZHw2u5y*nXz8mG2@w@C3$?4yk>~S1HrewzaXC4nA^V1cC*-%0MJ}DO zXIjHxcQT2oH*Coh8&2u6ota`5cS=D@B*RIPbG!2iF(j1w{1HLF%$WDu<1iCH=Y)Rg zlI%LIZD&o^n4X=`$W^Mb57+hx*G2PjtUY4P=+vH&v7;MUdYiYtF2_BJr?`(=4O8?g zD}xM0yucYCf^bXK;y>{U=VQXp_h*_rnuGSs;QfMZ)9PrEfoa6syH*^FYsedN*f~8? z9SS1$S%nc3*Sn0|?}izN*{PwD(z{L5rzvuWqmI@z8TkBF3=Tw#FoaE^^+&#Md>ip* zd&I>ajLiz9@eGHi?;MtLKe;_(cO)88e0zATx*g~rL>n+s_P~F$yfcehtk={EE?j4l z1_R%|*Yx`YGT`RsQX!(5ZE1PI7}WDL!p;=0yUL<_0h26SY+B-V)l(=MWX(qTvgt|+ z9tiCZO&EtDs2n}{R?R}o;4x!w>yLtG2MjdVRTuD@4g&abp^AO5tkWr zG1k_V8ODz}6=)6%(Iii_mLe{4MabV?>4Q^yQ5I6ob^4)`ClJO3ftC-I)sc;CtL}Fb zAH?4SNH9<9_2 z@+bla-dzcZY~+znyV1vCtkcO3*_FDanMbAe4n?a5sbhaE5}FRFta(l;f7;PYdJWdr zOxf{n=#@U6GAA+Z)qI6hGZ=+Eov9pj7uCa!VdKn#HKY;OsxYH$<_KS|fO!RYOOr#!Er$9%15A%Ft7TBJKg6 zf^J1*)Hw2y<_xC=QW|Tq)Y6m)4 zYD;EhMjrY%lUJr5##u&JagDUJQ*Utyxehrhy#0dj-9A08D~10MBncMpPuVCQqS~b> z{;+F3ewp#Mi&3~6sYx~y*=qOmjH0Qz7^IJwyh=x=6c1*)71MtNH;#AQDJuzDno%Qc zQSm)j-k?_}mn(U<7;TBqO1kl7+rrKlr2IE>R+Zhq(5y6(mrMr+EfV!c_t07b($z~4 z-kE(8dI6Rs>j|z@psW{WC)^9Pq$J(tDBw1_S$O4etbDAnFu!fHj1gsY)P9<)K6o9_ zjcjLgh0(CtWVJ<9zrxI#fJ_Sn_rkxg@Xqnc6|w#0@~K0p6LYm0+<2cCfF&!eTYrY` zEhmdJev`;0)!}?k^i9iaj*qE=hyps17dKzfm&!5dYWdQd)|DdauUmc+UfJJqPmF^kiAF7cXm-(lD*1o%Ls=pg#@St?b)vhg<-|x?Lp# zn_LPUm!gU>!LKT+v|RIp%5z5y*l`f-W_EW<5-~Ejb)Y_J0H`U|n0(J6O6w9anlhp!%&UbM zA}xXwc6%n8fnt_z!Hb1otTVTFUkz96J{)5=n)ub}A))Zs*dzcC8NA2Y-Unl>;EuRy zl4`J1rbVsv(@od4u~5ay%JJH(F%@a4r7)(_S8x~}&)KyR4PYQU6rXL!=Rhc1{6!pr zHsRX`ZINBqWDoU~f<{>H zzkOe6aV&joCdAP(R)f=EEyUAym230ZX#NyScPe3odoRlB{;(1$Lawj?+we?~nE%So zWyP0vW9UPv>ew=0@nN5`W>uoH=6r~AT2J7;EAH3Hm(|gqho!)u7+Un?>B7juIb#A; zx9L=-B6AzS+!d}L(<4hh<*G zBVf$fQ8>Kn(z5Y=B}(C5GJPwg(%V$zWf}voyJaRP2IHGHy2DU8P3j@x|1F+Scpe#R z3B||%?kRgM`}r4m?BM89YFrLA%6@g?b?gzA$`p|x%I0NL-L8wFs>86&Hpz+WpvR&a z{v`6Dp2^Cgb6jEp%l|R@@D^$ z$z`~^)q#UA(cDW!L2h@q`8eg8!Vm|lZ|Fj49@QLZ2$*VMU9v<~QXOczSy2 zBMaNoWyfn*ga+aoqd;GmC0ktWpNcm+%|=}l%?+%%9Q!mYFw`m-xp8cWJHi}$j6_c6 zM{X%+=M$w5R^3srKR$%znd{C@CM!&QKyIAUG?G+=(Tf0S_$QM4(xvujH zh&IH8zQM&c!p$gC+id7~DSOUuccuoMlCRB61}ByRTa>Nu&wjC)H?=6bLS{&>7m?38 z-LjTlqwIbJvyhLX1ow6`&3w9+Ux|Ag%kOV&752p(Y>NzE>wWvh^&1NA0m%7Kj}e$9 zj6bdqF@m@${R-GeE~hbF_g0$2h*uP@(b@d$MTjuZ>)C=YMu@4c&hySHc*dmhl`Y8- z#?VT40A*WMjc$qOREN%{b@#V|t9i`A1DE9%_l6VD+-O-Fmxn)bd;V&!U+I9Zs#{kH z*jG3TZ1YQIUrZjd9+4VSPu8-d@DXL*qE$A@FPd0&@lDA; zZz-PMC5~r{As|LCVg&HF-#e*%^*wq=*m$D71wM8D7<7D1yv64iR)A8LX{Av$cZ{&? zl_&Gw5Mf#xMv+)J?t-8`V=S5(r$eUxGAX12QfRjj`|Pr*Moe^aNYoTCNr)&I)85CH%(uC=uNs^^{w0Zo@%iSq00RKHY~osk zT|ydd2Ln>)^chVwwz*j40qqV!8O@j)j0bK7{=$5q^g$O^a3M?&R z3T!yPR7yiQGqgsVBpE54u!0+vaY_AUDwaljPT0>RN9gPb;EwjD?u@WIDe?ry^I)EN z7xf9=L#nYO%^g4*>$s8XRiqBH%x~@uOUrcYKSh={Bh2 zUZIm-R7DyL3B^ZUaR3Ah#N`hE6V|E0ZEofWRLu!HVcv8!`(_xVNu||b2*(~5^X@{d z6+)ko37A`0Eb=u$q{q=#vFgEGuAstZjkH7@%`HV-!FaxFuWy0BKVIwmk@SJ_^a^zT zucP#IKeFnpC_L0I?u3(?a*m^5LZ#tCW|XY27hGq>uj9!gQqVaha;S5xHCXb=#EOKs zOgs>|eApf(0&rDKaw6NkNVc`+!(X#zRRE;*r1Z}{NB zht7&)JBB|V9Lwdoz%NhPjcbbyojK1EmZ#Z2sYZS8V1P?PtlL>cZ{6I`f)l*;X%B~$ z!~8vh-4ewnmq~ATUQ0oheP(S##kqUy$proJ zg#Ahu?cjg<$U8J5W%=!mF80fcZ7;~aIC4c;OymX@zjO3kT-~olYcw67wvNeFZCe1R zy8;C8ZNwt!5reFmte0GDhJ^M!+a}`HBZa!+Uo4m!*m*jdIyTM2k_zoS^0-hAxx45C zV_&r&CLHjUoz@%#B#7Z}*z%~WoI(sG;wJJEXJ{IaQgqA%sH%M zYD+rE&7%SA%}rd(CC61pt>sV2bf;}F;XX9H>4zm#nI|>MrKxuuMk)N&716Sb)weP5 z791@QEimi``W~OxaVGU}$mq^EOrC^-Q!v6Gv^%i_Pg7Qc$sZA#OR2|NW%!8j zgl$37N=$R8-Q^~Rx2uBaOHE}iXpB0=68CUoo%Unf}9(%b*?qLKhtylXLB4DJdk z?ugwyK8T^d0OkDzwwJz|3E4SwPHO~>en}uv(sK7t?spVzayVjk-Ce!rFkgolNM^M{K z*{Ng3q!ZSxOLW_4EM;Jv3Veik?OB=^5n2aKi)J=jgd*uYx%Mru`(?C`g0av&N!tYB zO2S+mRJmSH^uX~%!%kfHU>{oV3%9HYiUnBWE=Rz!slvvH7~}y^&*t1)-Fd)*2alyQ zH74e|=6A58{bB+AKS;b_)LE^@^SmZy?C4K3tD}=}`5?&UOl4|nDCm_%J)3Q5f<6?u z8x-}*uNfta;fil=L}HZ2_cVsbE5l6%K=pdL{Sv+dV*<)rQyS zv+eIanNKN;b_vlW4wp$%uRsclk1QPJo_@g@7C_EPwl8fvSW#L%DQ_%Wo1I7#n6`~T zu%fMrmxCK&AE{ZyjwKJv0*>N^02>aFI{0+nOA$`*~JUK;j{9jl6&V` z=M$y@AY}#K_-KhUjXXV=SzGGxrgzHg^2{<2n{KT=FV34!VE2rE&yUO$RPclwu%GIo zvgHtht6UN3GVRn%+gmeeGhD#nXr4B9c-)1+)62|Fmg6}o+Fn0asyH=XnF0tSzI$l>>-wg(lefPx|G}Hg*h<;6N>v20+wzht_c0-&2YV-v zcGt(#&EvDVy+;f&qxQ}Y;*R#0S*Y>%`1xzo7H+Cq=>FD)=Oen{gg^zEGl*~y@KTm* z|BZUtvwHb#)Z$drbd9sdRr4b%c*ztwn3UK#CEc^^#@y!9# z!)Ie8Hn`;7NvCJ4MAO4+`LPQrT*&Zz6tWss8&ci2N*$--w$5!Q+=QOJQOS~h>lO$Y zuTO@vR*>2xIluy?j;C2 zH%J4Pcja$R1~*6$R%7FD>zo@T3Y6c2u=9Wz$)TF1ivL!UBl%C8AVvs<00;*X%LBrM z?DBwUfradUklz)+5GGy_BXIS92qwgb7sL*n;`|q9h!-Req~iU91oDG$A;NqhHlV5a z-v}RwjvT5~r})1*V*r5mKb@G9_$M7ML2Lyt^34jQJv2TC-n8<(Emi)6hlLi1F`cHrS|VG2VZSK>^S!;E?YhBi|8V{4H4j~gA*Ed&in`GX`2 zgQS4MCI9k@6~p2{MpIx>Ac|tp-X;ixNP#nD|0SS7-lRhb2hfT$pnKK-^*v|9VnG;1 zp}{61&|t^9|4V=d!$Y3)p&2?wpc#4^|4ShK9n1*iX!!>w`;#tF6q>HD;~y9u@>gf~ zMWN>>sOJxSUJFb1yXTBR_<{ct(I5#;uyByF-#&uze|#?>k76Kva_IWA;y?de1pom0 z|BNsC;y-)@h>AG$jzT>A7h<;v9o#!s5GpxT|6B2Y&n^If;y-B?Fa89bi-U+Er@!wY zVhIpBQ1jsrEG7X$fQU;%@2T*=5s?d6Y)Gsm^i+yVL63bG05OpQaY8V;K_FrjuX&gW z5CC8gT}CJWPcsj2ziD{MXwbO7F6Z^%!GtKu(jawU1jb)ZNDLkb15Zs64yqRk0JuWm O!O*LE2M?MM@c#f#HtVqf diff --git a/src/be/nikiroo/fanfix/DataLoader.java b/src/be/nikiroo/fanfix/DataLoader.java index 395f683..222c614 100644 --- a/src/be/nikiroo/fanfix/DataLoader.java +++ b/src/be/nikiroo/fanfix/DataLoader.java @@ -1,18 +1,16 @@ package be.nikiroo.fanfix; -import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Map; -import javax.imageio.ImageIO; - import be.nikiroo.fanfix.bundles.Config; import be.nikiroo.fanfix.supported.BasicSupport; import be.nikiroo.utils.Cache; import be.nikiroo.utils.Downloader; +import be.nikiroo.utils.Image; import be.nikiroo.utils.ImageUtils; /** @@ -50,7 +48,9 @@ public class DataLoader { public DataLoader(File dir, String UA, int hoursChanging, int hoursStable) throws IOException { cache = new Cache(dir, hoursChanging, hoursStable); + cache.setTraceHandler(Instance.getTraceHandler()); downloader = new Downloader(UA); + downloader.setTraceHandler(Instance.getTraceHandler()); } /** @@ -216,64 +216,49 @@ public class DataLoader { /** * Save the given resource as an image on disk using the default image - * format for content. + * format for content or cover -- will automatically add the extension, too. * - * @param url + * @param img * the resource * @param target - * the target file + * the target file without extension + * @param cover + * use the cover image format instead of the content image format * * @throws IOException * in case of I/O error */ - public void saveAsImage(URL url, File target) throws IOException { - InputStream in = open(url, null, true); - try { - saveAsImage(ImageUtils.fromStream(in), target); - } finally { - in.close(); + public void saveAsImage(Image img, File target, boolean cover) + throws IOException { + String format; + if (cover) { + format = Instance.getConfig().getString(Config.IMAGE_FORMAT_COVER) + .toLowerCase(); + } else { + format = Instance.getConfig() + .getString(Config.IMAGE_FORMAT_CONTENT).toLowerCase(); } + saveAsImage(img, new File(target.toString() + "." + format), format); } /** - * Save the given resource as an image on disk using the default image - * format for content. + * Save the given resource as an image on disk using the given image format + * for content, or with "png" format if it fails. * - * @param image + * @param img * the resource * @param target * the target file + * @param format + * the file format ("png", "jpeg", "bmp"...) * * @throws IOException * in case of I/O error */ - public void saveAsImage(BufferedImage image, File target) + public void saveAsImage(Image img, File target, String format) throws IOException { - try { - String format = Instance.getConfig() - .getString(Config.IMAGE_FORMAT_CONTENT).toLowerCase(); - - boolean ok = false; - try { - ok = ImageIO.write(image, format, target); - } catch (IOException e) { - ok = false; - } - - // Some formats are not reliable - // Second change: PNG - if (!ok && !format.equals("png")) { - ok = ImageIO.write(image, "png", target); - } + ImageUtils.getInstance().saveAsImage(img, target, format); - if (!ok) { - throw new IOException( - "Cannot find a writer for this image and format: " - + format); - } - } catch (IOException e) { - throw new IOException("Cannot write image to " + target, e); - } } /** diff --git a/src/be/nikiroo/fanfix/data/MetaData.java b/src/be/nikiroo/fanfix/data/MetaData.java index 8185ddd..d72b557 100644 --- a/src/be/nikiroo/fanfix/data/MetaData.java +++ b/src/be/nikiroo/fanfix/data/MetaData.java @@ -1,9 +1,10 @@ package be.nikiroo.fanfix.data; -import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; +import be.nikiroo.utils.Image; + /** * The meta data associated to a {@link Story} object. * @@ -15,7 +16,7 @@ public class MetaData implements Cloneable, Comparable { private String date; private Chapter resume; private List tags; - private BufferedImage cover; + private Image cover; private String subject; private String source; private String url; @@ -129,7 +130,7 @@ public class MetaData implements Cloneable, Comparable { * * @return the cover */ - public BufferedImage getCover() { + public Image getCover() { return cover; } @@ -139,7 +140,7 @@ public class MetaData implements Cloneable, Comparable { * @param cover * the cover to set */ - public void setCover(BufferedImage cover) { + public void setCover(Image cover) { this.cover = cover; } diff --git a/src/be/nikiroo/fanfix/data/Paragraph.java b/src/be/nikiroo/fanfix/data/Paragraph.java index 7a1a1c4..91e95f8 100644 --- a/src/be/nikiroo/fanfix/data/Paragraph.java +++ b/src/be/nikiroo/fanfix/data/Paragraph.java @@ -1,6 +1,6 @@ package be.nikiroo.fanfix.data; -import java.awt.image.BufferedImage; +import be.nikiroo.utils.Image; /** * A paragraph in a chapter of the story. @@ -28,7 +28,7 @@ public class Paragraph implements Cloneable { private ParagraphType type; private String content; - private BufferedImage contentImage; + private Image contentImage; private long words; /** @@ -45,7 +45,7 @@ public class Paragraph implements Cloneable { * @param contentImage * the image */ - public Paragraph(BufferedImage contentImage) { + public Paragraph(Image contentImage) { this(ParagraphType.IMAGE, null, 1); this.contentImage = contentImage; } @@ -109,7 +109,7 @@ public class Paragraph implements Cloneable { * * @return the content */ - public BufferedImage getContentImage() { + public Image getContentImage() { return contentImage; } diff --git a/src/be/nikiroo/fanfix/data/Story.java b/src/be/nikiroo/fanfix/data/Story.java index 7e58571..fd4f2a8 100644 --- a/src/be/nikiroo/fanfix/data/Story.java +++ b/src/be/nikiroo/fanfix/data/Story.java @@ -92,9 +92,22 @@ public class Story implements Iterable, Cloneable { resume += "\n"; } - String cover = (meta == null || meta.getCover() == null) ? "none" - : meta.getCover().getWidth() + "x" - + meta.getCover().getHeight(); + String cover = "none"; + if (meta != null && meta.getCover() != null) { + cover = " bytes"; + + int size = meta.getCover().getData().length; + if (size > 1000) { + size /= 1000; + cover = " kb"; + if (size > 1000) { + size /= 1000; + cover = " mb"; + } + } + + cover = size + cover; + } return String.format( "Title: [%s]\nAuthor: [%s]\nDate: [%s]\nTags: [%s]\n" + "Resume: [%s]\nCover: [%s]", title, meta == null ? "" diff --git a/src/be/nikiroo/fanfix/library/BasicLibrary.java b/src/be/nikiroo/fanfix/library/BasicLibrary.java index 9e7d464..8c86fc9 100644 --- a/src/be/nikiroo/fanfix/library/BasicLibrary.java +++ b/src/be/nikiroo/fanfix/library/BasicLibrary.java @@ -1,6 +1,5 @@ package be.nikiroo.fanfix.library; -import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.net.URL; @@ -16,6 +15,7 @@ import be.nikiroo.fanfix.output.BasicOutput; import be.nikiroo.fanfix.output.BasicOutput.OutputType; import be.nikiroo.fanfix.supported.BasicSupport; import be.nikiroo.fanfix.supported.BasicSupport.SupportType; +import be.nikiroo.utils.Image; import be.nikiroo.utils.Progress; /** @@ -89,7 +89,7 @@ abstract public class BasicLibrary { * * @return the cover image */ - public abstract BufferedImage getCover(String luid); + public abstract Image getCover(String luid); /** * Return the cover image associated to this source. @@ -101,7 +101,7 @@ abstract public class BasicLibrary { * * @return the cover image or NULL */ - public BufferedImage getSourceCover(String source) { + public Image getSourceCover(String source) { List metas = getListBySource(source); if (metas.size() > 0) { return getCover(metas.get(0).getLuid()); diff --git a/src/be/nikiroo/fanfix/library/CacheLibrary.java b/src/be/nikiroo/fanfix/library/CacheLibrary.java index 7f4bb37..2620415 100644 --- a/src/be/nikiroo/fanfix/library/CacheLibrary.java +++ b/src/be/nikiroo/fanfix/library/CacheLibrary.java @@ -1,6 +1,5 @@ package be.nikiroo.fanfix.library; -import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.net.URL; @@ -10,6 +9,7 @@ import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.bundles.UiConfig; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Story; +import be.nikiroo.utils.Image; import be.nikiroo.utils.Progress; /** @@ -101,7 +101,7 @@ public class CacheLibrary extends BasicLibrary { } @Override - public BufferedImage getCover(final String luid) { + public Image getCover(final String luid) { if (isCached(luid)) { return cacheLib.getCover(luid); } @@ -111,7 +111,7 @@ public class CacheLibrary extends BasicLibrary { } @Override - public BufferedImage getSourceCover(String source) { + public Image getSourceCover(String source) { // no cache for the source cover return lib.getSourceCover(source); } diff --git a/src/be/nikiroo/fanfix/library/LocalLibrary.java b/src/be/nikiroo/fanfix/library/LocalLibrary.java index 92676b3..041db10 100644 --- a/src/be/nikiroo/fanfix/library/LocalLibrary.java +++ b/src/be/nikiroo/fanfix/library/LocalLibrary.java @@ -1,6 +1,5 @@ package be.nikiroo.fanfix.library; -import java.awt.image.BufferedImage; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; @@ -11,8 +10,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.imageio.ImageIO; - import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.bundles.Config; import be.nikiroo.fanfix.data.MetaData; @@ -22,7 +19,7 @@ import be.nikiroo.fanfix.output.BasicOutput.OutputType; import be.nikiroo.fanfix.output.InfoCover; import be.nikiroo.fanfix.supported.InfoReader; import be.nikiroo.utils.IOUtils; -import be.nikiroo.utils.ImageUtils; +import be.nikiroo.utils.Image; import be.nikiroo.utils.MarkableFileInputStream; import be.nikiroo.utils.Progress; @@ -34,7 +31,7 @@ import be.nikiroo.utils.Progress; public class LocalLibrary extends BasicLibrary { private int lastId; private Map stories; // Files: [ infoFile, TargetFile ] - private Map sourceCovers; + private Map sourceCovers; private File baseDir; private OutputType text; @@ -90,7 +87,7 @@ public class LocalLibrary extends BasicLibrary { this.lastId = 0; this.stories = null; - this.sourceCovers = new HashMap(); + this.sourceCovers = new HashMap(); baseDir.mkdirs(); } @@ -111,7 +108,7 @@ public class LocalLibrary extends BasicLibrary { } @Override - public BufferedImage getCover(String luid) { + public Image getCover(String luid) { MetaData meta = getInfo(luid); if (meta != null) { File[] files = getStories(null).get(meta); @@ -133,7 +130,7 @@ public class LocalLibrary extends BasicLibrary { @Override protected void invalidateInfo(String luid) { stories = null; - sourceCovers = new HashMap(); + sourceCovers = new HashMap(); } @Override @@ -197,7 +194,7 @@ public class LocalLibrary extends BasicLibrary { } @Override - public BufferedImage getSourceCover(String source) { + public Image getSourceCover(String source) { if (!sourceCovers.containsKey(source)) { sourceCovers.put(source, super.getSourceCover(source)); } @@ -210,7 +207,8 @@ public class LocalLibrary extends BasicLibrary { sourceCovers.put(source, getCover(luid)); File cover = new File(getExpectedDir(source), ".cover.png"); try { - ImageIO.write(sourceCovers.get(source), "png", cover); + Instance.getCache().saveAsImage(sourceCovers.get(source), cover, + true); } catch (IOException e) { Instance.getTraceHandler().error(e); sourceCovers.remove(source); @@ -487,10 +485,9 @@ public class LocalLibrary extends BasicLibrary { File cover = new File(dir, ".cover.png"); if (cover.exists()) { try { - InputStream in = new MarkableFileInputStream( - new FileInputStream(cover)); + InputStream in = new FileInputStream(cover); try { - sourceCovers.put(source, ImageUtils.fromStream(in)); + sourceCovers.put(source, new Image(in)); } finally { in.close(); } @@ -516,11 +513,12 @@ public class LocalLibrary extends BasicLibrary { * @param coverImage * the cover image */ - void setSourceCover(String source, BufferedImage coverImage) { + void setSourceCover(String source, Image coverImage) { sourceCovers.put(source, coverImage); File cover = new File(getExpectedDir(source), ".cover.png"); try { - ImageIO.write(sourceCovers.get(source), "png", cover); + Instance.getCache().saveAsImage(sourceCovers.get(source), cover, + true); } catch (IOException e) { Instance.getTraceHandler().error(e); sourceCovers.remove(source); diff --git a/src/be/nikiroo/fanfix/library/RemoteLibrary.java b/src/be/nikiroo/fanfix/library/RemoteLibrary.java index 326a488..5052fa2 100644 --- a/src/be/nikiroo/fanfix/library/RemoteLibrary.java +++ b/src/be/nikiroo/fanfix/library/RemoteLibrary.java @@ -1,6 +1,5 @@ package be.nikiroo.fanfix.library; -import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.net.URL; @@ -11,6 +10,7 @@ import java.util.List; import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Story; +import be.nikiroo.utils.Image; import be.nikiroo.utils.Progress; import be.nikiroo.utils.StringUtils; import be.nikiroo.utils.Version; @@ -95,15 +95,15 @@ public class RemoteLibrary extends BasicLibrary { } @Override - public BufferedImage getCover(final String luid) { - final BufferedImage[] result = new BufferedImage[1]; + public Image getCover(final String luid) { + final Image[] result = new Image[1]; try { new ConnectActionClientObject(host, port, true) { @Override public void action(Version serverVersion) throws Exception { Object rep = send(new Object[] { md5, "GET_COVER", luid }); - result[0] = (BufferedImage) rep; + result[0] = (Image) rep; } @Override @@ -119,8 +119,8 @@ public class RemoteLibrary extends BasicLibrary { } @Override - public BufferedImage getSourceCover(final String source) { - final BufferedImage[] result = new BufferedImage[1]; + public Image getSourceCover(final String source) { + final Image[] result = new Image[1]; try { new ConnectActionClientObject(host, port, true) { @@ -128,7 +128,7 @@ public class RemoteLibrary extends BasicLibrary { public void action(Version serverVersion) throws Exception { Object rep = send(new Object[] { md5, "GET_SOURCE_COVER", source }); - result[0] = (BufferedImage) rep; + result[0] = (Image) rep; } @Override diff --git a/src/be/nikiroo/fanfix/output/BasicOutput.java b/src/be/nikiroo/fanfix/output/BasicOutput.java index 97920cb..5109cce 100644 --- a/src/be/nikiroo/fanfix/output/BasicOutput.java +++ b/src/be/nikiroo/fanfix/output/BasicOutput.java @@ -376,13 +376,13 @@ public abstract class BasicOutput { int num = 0; String paragraphNumber = String.format("%04d", num++); - imageName = chapterNameNum + "_" + paragraphNumber + ".png"; + imageName = chapterNameNum + "_" + paragraphNumber; writeChapterHeader(chap); int i = 1; for (Paragraph para : chap) { paragraphNumber = String.format("%04d", num++); - imageName = chapterNameNum + "_" + paragraphNumber + ".png"; + imageName = chapterNameNum + "_" + paragraphNumber; writeParagraph(para); if (chapPg != null) { chapPg.setProgress(i++); diff --git a/src/be/nikiroo/fanfix/output/Epub.java b/src/be/nikiroo/fanfix/output/Epub.java index 48da65a..09a9944 100644 --- a/src/be/nikiroo/fanfix/output/Epub.java +++ b/src/be/nikiroo/fanfix/output/Epub.java @@ -7,8 +7,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; -import javax.imageio.ImageIO; - import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.bundles.Config; import be.nikiroo.fanfix.bundles.StringId; @@ -26,6 +24,7 @@ class Epub extends BasicOutput { private boolean inDialogue = false; private boolean inNormal = false; private File images; + private boolean nextParaIsCover = true; @Override public File process(Story story, File targetDir, String targetName) @@ -104,7 +103,8 @@ class Epub extends BasicOutput { String format = Instance.getConfig() .getString(Config.IMAGE_FORMAT_COVER).toLowerCase(); File file = new File(images, "cover." + format); - ImageIO.write(story.getMeta().getCover(), format, file); + Instance.getCache().saveAsImage(story.getMeta().getCover(), file, + true); } // OPS/* except chapters @@ -209,11 +209,14 @@ class Epub extends BasicOutput { break; case IMAGE: File file = new File(images, getCurrentImageBestName(false)); - Instance.getCache().saveAsImage(para.getContentImage(), file); + Instance.getCache().saveAsImage(para.getContentImage(), file, + nextParaIsCover); writer.write(" "); break; } + + nextParaIsCover = false; } @Override diff --git a/src/be/nikiroo/fanfix/output/Html.java b/src/be/nikiroo/fanfix/output/Html.java index d1559b4..e91c6f4 100644 --- a/src/be/nikiroo/fanfix/output/Html.java +++ b/src/be/nikiroo/fanfix/output/Html.java @@ -7,8 +7,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; -import javax.imageio.ImageIO; - import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.bundles.Config; import be.nikiroo.fanfix.data.Chapter; @@ -51,11 +49,9 @@ class Html extends BasicOutput { writer = null; } - String format = Instance.getConfig() - .getString(Config.IMAGE_FORMAT_COVER).toLowerCase(); if (story.getMeta().getCover() != null) { - ImageIO.write(story.getMeta().getCover(), format, new File(dir, - "cover." + format)); + Instance.getCache().saveAsImage(story.getMeta().getCover(), + new File(dir, "cover"), true); } return target; diff --git a/src/be/nikiroo/fanfix/output/InfoCover.java b/src/be/nikiroo/fanfix/output/InfoCover.java index a1b3791..1e6ccd3 100644 --- a/src/be/nikiroo/fanfix/output/InfoCover.java +++ b/src/be/nikiroo/fanfix/output/InfoCover.java @@ -6,8 +6,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; -import javax.imageio.ImageIO; - import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.bundles.Config; import be.nikiroo.fanfix.data.MetaData; @@ -69,10 +67,8 @@ public class InfoCover { MetaData meta) { if (meta != null && meta.getCover() != null) { try { - String format = Instance.getConfig() - .getString(Config.IMAGE_FORMAT_COVER).toLowerCase(); - ImageIO.write(meta.getCover(), format, new File(targetDir, - targetName + "." + format)); + Instance.getCache().saveAsImage(meta.getCover(), + new File(targetDir, targetName), true); } catch (IOException e) { // Allow to continue without cover Instance.getTraceHandler().error( diff --git a/src/be/nikiroo/fanfix/output/Text.java b/src/be/nikiroo/fanfix/output/Text.java index ee72385..b45a512 100644 --- a/src/be/nikiroo/fanfix/output/Text.java +++ b/src/be/nikiroo/fanfix/output/Text.java @@ -17,6 +17,7 @@ import be.nikiroo.fanfix.data.Story; class Text extends BasicOutput { protected BufferedWriter writer; protected File targetDir; + private boolean nextParaIsCover = true; @Override public File process(Story story, File targetDir, String targetName) @@ -104,8 +105,11 @@ class Text extends BasicOutput { protected void writeParagraphHeader(Paragraph para) throws IOException { if (para.getType() == ParagraphType.IMAGE) { File file = new File(targetDir, getCurrentImageBestName(true)); - Instance.getCache().saveAsImage(para.getContentImage(), file); + Instance.getCache().saveAsImage(para.getContentImage(), file, + nextParaIsCover); } + + nextParaIsCover = false; } @Override diff --git a/src/be/nikiroo/fanfix/reader/BasicReader.java b/src/be/nikiroo/fanfix/reader/BasicReader.java index 0ea403c..4b44494 100644 --- a/src/be/nikiroo/fanfix/reader/BasicReader.java +++ b/src/be/nikiroo/fanfix/reader/BasicReader.java @@ -1,6 +1,5 @@ package be.nikiroo.fanfix.reader; -import java.awt.Desktop; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; @@ -133,8 +132,9 @@ public abstract class BasicReader implements Reader { .getTypeName()); } } catch (Exception e) { - Instance.getTraceHandler().error(new Exception("Cannot create a reader of type: " - + defaultType + " (Not compiled in?)", e)); + Instance.getTraceHandler().error( + new Exception("Cannot create a reader of type: " + + defaultType + " (Not compiled in?)", e)); } return null; @@ -212,8 +212,8 @@ public abstract class BasicReader implements Reader { * @throws IOException * in case of I/O error */ - public static void openExternal(BasicLibrary lib, String luid) - throws IOException { + @Override + public void openExternal(BasicLibrary lib, String luid) throws IOException { MetaData meta = lib.getInfo(luid); File target = lib.getFile(luid, null); @@ -232,8 +232,7 @@ public abstract class BasicReader implements Reader { * @throws IOException * in case of I/O error */ - protected static void openExternal(MetaData meta, File target) - throws IOException { + protected void openExternal(MetaData meta, File target) throws IOException { String program = null; if (meta.isImageDocument()) { program = Instance.getUiConfig().getString( @@ -247,13 +246,35 @@ public abstract class BasicReader implements Reader { program = null; } - if (program == null) { - try { - Desktop.getDesktop().browse(target.toURI()); - } catch (UnsupportedOperationException e) { - Runtime.getRuntime().exec( - new String[] { "xdg-open", target.getAbsolutePath() }); + start(target, program); + } + /** + * Start a file and open it with the given program if given or the first + * default system starter we can find. + * + * @param target + * the target to open + * @param program + * the program to use or NULL for the default system starter + * + * @throws IOException + * in case of I/O error + */ + protected void start(File target, String program) throws IOException { + if (program == null) { + boolean ok = false; + for (String starter : new String[] { "xdg-open", "start", "run" }) { + try { + Runtime.getRuntime().exec( + new String[] { starter, target.getAbsolutePath() }); + ok = true; + break; + } catch (IOException e) { + } + } + if (!ok) { + throw new IOException("Cannot find a program to start the file"); } } else { Runtime.getRuntime().exec( diff --git a/src/be/nikiroo/fanfix/reader/Reader.java b/src/be/nikiroo/fanfix/reader/Reader.java index d540d39..f98f12c 100644 --- a/src/be/nikiroo/fanfix/reader/Reader.java +++ b/src/be/nikiroo/fanfix/reader/Reader.java @@ -40,11 +40,11 @@ public interface Reader { String pkg = "be.nikiroo.fanfix.reader."; switch (this) { case CLI: - return pkg + "CliReader"; + return pkg + "cli.CliReader"; case TUI: - return pkg + "TuiReader"; + return pkg + "tui.TuiReader"; case GUI: - return pkg + "GuiReader"; + return pkg + "ui.GuiReader"; } return null; @@ -158,4 +158,18 @@ public interface Reader { * all */ public void browse(String source); + + /** + * Open the {@link Story} with an external reader (the program will be + * passed the main file associated with this {@link Story}). + * + * @param lib + * the {@link BasicLibrary} to select the {@link Story} from + * @param luid + * the {@link Story} LUID + * + * @throws IOException + * in case of I/O error + */ + public void openExternal(BasicLibrary lib, String luid) throws IOException; } diff --git a/src/be/nikiroo/fanfix/reader/CliReader.java b/src/be/nikiroo/fanfix/reader/cli/CliReader.java similarity index 96% rename from src/be/nikiroo/fanfix/reader/CliReader.java rename to src/be/nikiroo/fanfix/reader/cli/CliReader.java index 2f0b8ce..b28d4d4 100644 --- a/src/be/nikiroo/fanfix/reader/CliReader.java +++ b/src/be/nikiroo/fanfix/reader/cli/CliReader.java @@ -1,4 +1,4 @@ -package be.nikiroo.fanfix.reader; +package be.nikiroo.fanfix.reader.cli; import java.io.IOException; import java.util.List; @@ -9,6 +9,7 @@ import be.nikiroo.fanfix.data.Chapter; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Paragraph; import be.nikiroo.fanfix.data.Story; +import be.nikiroo.fanfix.reader.BasicReader; /** * Command line {@link Story} reader. diff --git a/src/be/nikiroo/fanfix/reader/TuiReader.java b/src/be/nikiroo/fanfix/reader/tui/TuiReader.java similarity index 93% rename from src/be/nikiroo/fanfix/reader/TuiReader.java rename to src/be/nikiroo/fanfix/reader/tui/TuiReader.java index 30b9dce..7192854 100644 --- a/src/be/nikiroo/fanfix/reader/TuiReader.java +++ b/src/be/nikiroo/fanfix/reader/tui/TuiReader.java @@ -1,10 +1,12 @@ -package be.nikiroo.fanfix.reader; +package be.nikiroo.fanfix.reader.tui; import java.io.IOException; import jexer.TApplication; import jexer.TApplication.BackendType; import be.nikiroo.fanfix.Instance; +import be.nikiroo.fanfix.reader.BasicReader; +import be.nikiroo.fanfix.reader.Reader; /** * This {@link Reader}is based upon the TUI widget library 'jexer' diff --git a/src/be/nikiroo/fanfix/reader/TuiReaderApplication.java b/src/be/nikiroo/fanfix/reader/tui/TuiReaderApplication.java similarity index 94% rename from src/be/nikiroo/fanfix/reader/TuiReaderApplication.java rename to src/be/nikiroo/fanfix/reader/tui/TuiReaderApplication.java index c1bba5a..9e991e4 100644 --- a/src/be/nikiroo/fanfix/reader/TuiReaderApplication.java +++ b/src/be/nikiroo/fanfix/reader/tui/TuiReaderApplication.java @@ -1,4 +1,4 @@ -package be.nikiroo.fanfix.reader; +package be.nikiroo.fanfix.reader.tui; import java.awt.Toolkit; import java.awt.datatransfer.DataFlavor; @@ -17,6 +17,8 @@ import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Story; import be.nikiroo.fanfix.library.BasicLibrary; +import be.nikiroo.fanfix.reader.BasicReader; +import be.nikiroo.fanfix.reader.Reader; import be.nikiroo.utils.Progress; /** @@ -77,7 +79,7 @@ class TuiReaderApplication extends TApplication implements Reader { getChapter()); } else { try { - BasicReader.openExternal(getLibrary(), meta.getLuid()); + openExternal(getLibrary(), meta.getLuid()); } catch (IOException e) { messageBox("Error when trying to open the story", e.getMessage(), TMessageBox.Type.OK); @@ -225,4 +227,9 @@ class TuiReaderApplication extends TApplication implements Reader { return false; } } + + @Override + public void openExternal(BasicLibrary lib, String luid) throws IOException { + reader.openExternal(lib, luid); + } } diff --git a/src/be/nikiroo/fanfix/reader/TuiReaderMainWindow.java b/src/be/nikiroo/fanfix/reader/tui/TuiReaderMainWindow.java similarity index 98% rename from src/be/nikiroo/fanfix/reader/TuiReaderMainWindow.java rename to src/be/nikiroo/fanfix/reader/tui/TuiReaderMainWindow.java index 10c6466..0fccfaf 100644 --- a/src/be/nikiroo/fanfix/reader/TuiReaderMainWindow.java +++ b/src/be/nikiroo/fanfix/reader/tui/TuiReaderMainWindow.java @@ -1,4 +1,4 @@ -package be.nikiroo.fanfix.reader; +package be.nikiroo.fanfix.reader.tui; import java.io.IOException; import java.util.ArrayList; @@ -15,6 +15,7 @@ import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.library.BasicLibrary; import be.nikiroo.fanfix.output.BasicOutput.OutputType; +import be.nikiroo.fanfix.reader.Reader; /** * The library window, that will list all the (filtered) stories available in diff --git a/src/be/nikiroo/fanfix/reader/TuiReaderStoryWindow.java b/src/be/nikiroo/fanfix/reader/tui/TuiReaderStoryWindow.java similarity index 99% rename from src/be/nikiroo/fanfix/reader/TuiReaderStoryWindow.java rename to src/be/nikiroo/fanfix/reader/tui/TuiReaderStoryWindow.java index e8dafc3..e4587e7 100644 --- a/src/be/nikiroo/fanfix/reader/TuiReaderStoryWindow.java +++ b/src/be/nikiroo/fanfix/reader/tui/TuiReaderStoryWindow.java @@ -1,4 +1,4 @@ -package be.nikiroo.fanfix.reader; +package be.nikiroo.fanfix.reader.tui; import java.util.ArrayList; import java.util.List; diff --git a/src/be/nikiroo/fanfix/reader/GuiReader.java b/src/be/nikiroo/fanfix/reader/ui/GuiReader.java similarity index 92% rename from src/be/nikiroo/fanfix/reader/GuiReader.java rename to src/be/nikiroo/fanfix/reader/ui/GuiReader.java index b9d5954..576ac9c 100644 --- a/src/be/nikiroo/fanfix/reader/GuiReader.java +++ b/src/be/nikiroo/fanfix/reader/ui/GuiReader.java @@ -1,4 +1,4 @@ -package be.nikiroo.fanfix.reader; +package be.nikiroo.fanfix.reader.ui; import java.awt.Desktop; import java.awt.EventQueue; @@ -18,6 +18,7 @@ import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Story; import be.nikiroo.fanfix.library.BasicLibrary; import be.nikiroo.fanfix.library.CacheLibrary; +import be.nikiroo.fanfix.reader.BasicReader; import be.nikiroo.utils.Progress; import be.nikiroo.utils.Version; import be.nikiroo.utils.ui.UIUtils; @@ -147,6 +148,19 @@ class GuiReader extends BasicReader { }); } + @Override + public void start(File target, String program) throws IOException { + if (program == null) { + try { + Desktop.getDesktop().browse(target.toURI()); + } catch (UnsupportedOperationException e) { + super.start(target, program); + } + } else { + super.start(target, program); + } + } + // delete from local reader library void clearLocalReaderCache(String luid) { try { diff --git a/src/be/nikiroo/fanfix/reader/GuiReaderBook.java b/src/be/nikiroo/fanfix/reader/ui/GuiReaderBook.java similarity index 96% rename from src/be/nikiroo/fanfix/reader/GuiReaderBook.java rename to src/be/nikiroo/fanfix/reader/ui/GuiReaderBook.java index c70f30a..4343ca5 100644 --- a/src/be/nikiroo/fanfix/reader/GuiReaderBook.java +++ b/src/be/nikiroo/fanfix/reader/ui/GuiReaderBook.java @@ -1,4 +1,4 @@ -package be.nikiroo.fanfix.reader; +package be.nikiroo.fanfix.reader.ui; import java.awt.BorderLayout; import java.awt.Color; @@ -27,7 +27,9 @@ import javax.swing.JPanel; import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Story; -import be.nikiroo.utils.ImageUtils; +import be.nikiroo.fanfix.reader.Reader; +import be.nikiroo.utils.Image; +import be.nikiroo.utils.ui.ImageUtilsAwt; import be.nikiroo.utils.ui.UIUtils; /** @@ -380,7 +382,7 @@ class GuiReaderBook extends JPanel { InputStream in = Instance.getCache().getFromCache(id); if (in != null) { try { - resizedImage = ImageUtils.fromStream(in); + resizedImage = ImageUtilsAwt.fromImage(new Image(in)); in.close(); in = null; } catch (IOException e) { @@ -390,7 +392,7 @@ class GuiReaderBook extends JPanel { if (resizedImage == null) { try { - BufferedImage cover = null; + Image cover = null; if (meta.getLuid() == null) { cover = reader.getLibrary() .getSourceCover(meta.getSource()); @@ -398,6 +400,8 @@ class GuiReaderBook extends JPanel { cover = reader.getLibrary().getCover(meta.getLuid()); } + BufferedImage coverb = ImageUtilsAwt.fromImage(cover); + resizedImage = new BufferedImage(SPINE_WIDTH + COVER_WIDTH, SPINE_HEIGHT + COVER_HEIGHT + HOFFSET, BufferedImage.TYPE_4BYTE_ABGR); @@ -405,7 +409,7 @@ class GuiReaderBook extends JPanel { g.setColor(Color.white); g.fillRect(0, HOFFSET, COVER_WIDTH, COVER_HEIGHT); if (cover != null) { - g.drawImage(cover, 0, HOFFSET, COVER_WIDTH, COVER_HEIGHT, + g.drawImage(coverb, 0, HOFFSET, COVER_WIDTH, COVER_HEIGHT, null); } else { g.setColor(Color.black); @@ -430,7 +434,11 @@ class GuiReaderBook extends JPanel { } } - return new ImageIcon(resizedImage); + if (resizedImage != null) { + return new ImageIcon(resizedImage); + } + + return null; } /** diff --git a/src/be/nikiroo/fanfix/reader/GuiReaderFrame.java b/src/be/nikiroo/fanfix/reader/ui/GuiReaderFrame.java similarity index 98% rename from src/be/nikiroo/fanfix/reader/GuiReaderFrame.java rename to src/be/nikiroo/fanfix/reader/ui/GuiReaderFrame.java index 99091d3..b98bed2 100644 --- a/src/be/nikiroo/fanfix/reader/GuiReaderFrame.java +++ b/src/be/nikiroo/fanfix/reader/ui/GuiReaderFrame.java @@ -1,4 +1,4 @@ -package be.nikiroo.fanfix.reader; +package be.nikiroo.fanfix.reader.ui; import java.awt.BorderLayout; import java.awt.Color; @@ -45,7 +45,8 @@ import be.nikiroo.fanfix.library.BasicLibrary; import be.nikiroo.fanfix.library.BasicLibrary.Status; import be.nikiroo.fanfix.library.LocalLibrary; import be.nikiroo.fanfix.output.BasicOutput.OutputType; -import be.nikiroo.fanfix.reader.GuiReaderBook.BookActionListener; +import be.nikiroo.fanfix.reader.BasicReader; +import be.nikiroo.fanfix.reader.ui.GuiReaderBook.BookActionListener; import be.nikiroo.utils.Progress; import be.nikiroo.utils.Version; import be.nikiroo.utils.ui.ConfigEditor; @@ -107,8 +108,10 @@ class GuiReaderFrame extends JFrame { pane = new JPanel(); pane.setLayout(new BoxLayout(pane, BoxLayout.PAGE_AXIS)); - color = Instance.getUiConfig().getColor(UiConfig.BACKGROUND_COLOR); - if (color != null) { + Integer icolor = Instance.getUiConfig().getColor( + UiConfig.BACKGROUND_COLOR); + if (icolor != null) { + color = new Color(icolor); setBackground(color); pane.setBackground(color); } diff --git a/src/be/nikiroo/fanfix/reader/GuiReaderGroup.java b/src/be/nikiroo/fanfix/reader/ui/GuiReaderGroup.java similarity index 97% rename from src/be/nikiroo/fanfix/reader/GuiReaderGroup.java rename to src/be/nikiroo/fanfix/reader/ui/GuiReaderGroup.java index a087c4c..c96b02d 100644 --- a/src/be/nikiroo/fanfix/reader/GuiReaderGroup.java +++ b/src/be/nikiroo/fanfix/reader/ui/GuiReaderGroup.java @@ -1,4 +1,4 @@ -package be.nikiroo.fanfix.reader; +package be.nikiroo.fanfix.reader.ui; import java.awt.BorderLayout; import java.awt.Color; @@ -12,7 +12,7 @@ import javax.swing.JLabel; import javax.swing.JPanel; import be.nikiroo.fanfix.data.MetaData; -import be.nikiroo.fanfix.reader.GuiReaderBook.BookActionListener; +import be.nikiroo.fanfix.reader.ui.GuiReaderBook.BookActionListener; import be.nikiroo.utils.ui.WrapLayout; /** diff --git a/src/be/nikiroo/fanfix/supported/BasicSupport.java b/src/be/nikiroo/fanfix/supported/BasicSupport.java index 66ba64d..f16cdc7 100644 --- a/src/be/nikiroo/fanfix/supported/BasicSupport.java +++ b/src/be/nikiroo/fanfix/supported/BasicSupport.java @@ -1,6 +1,5 @@ package be.nikiroo.fanfix.supported; -import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; @@ -25,7 +24,7 @@ import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Paragraph; import be.nikiroo.fanfix.data.Paragraph.ParagraphType; import be.nikiroo.fanfix.data.Story; -import be.nikiroo.utils.ImageUtils; +import be.nikiroo.utils.Image; import be.nikiroo.utils.Progress; import be.nikiroo.utils.StringUtils; @@ -750,7 +749,7 @@ public abstract class BasicSupport { * @return the {@link Paragraph} */ private Paragraph makeParagraph(URL source, String line) { - BufferedImage image = null; + Image image = null; if (line.startsWith("[") && line.endsWith("]")) { image = getImage(this, source, line.substring(1, line.length() - 1) .trim()); @@ -817,7 +816,7 @@ public abstract class BasicSupport { * * @return the cover if any, or NULL */ - static BufferedImage getDefaultCover(String subject) { + static Image getDefaultCover(String subject) { if (subject != null && !subject.isEmpty() && Instance.getCoverDir() != null) { try { @@ -860,13 +859,18 @@ public abstract class BasicSupport { * @return the image if found, or NULL * */ - static BufferedImage getImage(BasicSupport support, URL source, String line) { + static Image getImage(BasicSupport support, URL source, String line) { URL url = getImageUrl(support, source, line); if (url != null) { + if ("file".equals(url.getProtocol())) { + if (new File(url.getPath()).isDirectory()) { + return null; + } + } InputStream in = null; try { in = Instance.getCache().open(url, getSupport(url), true); - return ImageUtils.fromStream(in); + return new Image(in); } catch (IOException e) { } finally { if (in != null) { @@ -918,11 +922,14 @@ public abstract class BasicSupport { } for (String ext : getImageExt(true)) { - if (absPath != null && new File(absPath + ext).exists()) { - url = new File(absPath + ext).toURI().toURL(); - } else if (relPath != null - && new File(relPath + ext).exists()) { - url = new File(relPath + ext).toURI().toURL(); + File absFile = new File(absPath + ext); + File relFile = new File(relPath + ext); + if (absPath != null && absFile.exists() + && absFile.isFile()) { + url = absFile.toURI().toURL(); + } else if (relPath != null && relFile.exists() + && relFile.isFile()) { + url = relFile.toURI().toURL(); } } } catch (Exception e) { diff --git a/src/be/nikiroo/fanfix/supported/Cbz.java b/src/be/nikiroo/fanfix/supported/Cbz.java index 77a4008..b6524ac 100644 --- a/src/be/nikiroo/fanfix/supported/Cbz.java +++ b/src/be/nikiroo/fanfix/supported/Cbz.java @@ -1,6 +1,5 @@ package be.nikiroo.fanfix.supported; -import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.net.URL; @@ -16,7 +15,7 @@ import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.data.Chapter; import be.nikiroo.fanfix.data.Paragraph; import be.nikiroo.fanfix.data.Story; -import be.nikiroo.utils.ImageUtils; +import be.nikiroo.utils.Image; import be.nikiroo.utils.Progress; /** @@ -76,7 +75,7 @@ class Cbz extends Epub { ZipInputStream zipIn = new ZipInputStream(getInput()); - Map images = new HashMap(); + Map images = new HashMap(); for (ZipEntry entry = zipIn.getNextEntry(); entry != null; entry = zipIn .getNextEntry()) { if (!entry.isDirectory() @@ -92,7 +91,7 @@ class Cbz extends Epub { if (imageEntry) { String uuid = meta.getUuid() + "_" + entry.getName(); try { - images.put(uuid, ImageUtils.fromStream(zipIn)); + images.put(uuid, new Image(zipIn)); } catch (Exception e) { Instance.getTraceHandler().error(e); } diff --git a/src/be/nikiroo/fanfix/supported/E621.java b/src/be/nikiroo/fanfix/supported/E621.java index 1baa620..72c68b1 100644 --- a/src/be/nikiroo/fanfix/supported/E621.java +++ b/src/be/nikiroo/fanfix/supported/E621.java @@ -1,6 +1,5 @@ package be.nikiroo.fanfix.supported; -import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.net.URL; @@ -13,6 +12,7 @@ import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.data.Chapter; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Story; +import be.nikiroo.utils.Image; import be.nikiroo.utils.Progress; import be.nikiroo.utils.StringUtils; @@ -87,7 +87,7 @@ class E621 extends BasicSupport { return true; } - private BufferedImage getCover(URL source) throws IOException { + private Image getCover(URL source) throws IOException { InputStream in = Instance.getCache().open(source, this, true); String images = getChapterContent(new URL(source.toString() + "?page=" + 1), in, 1, null); diff --git a/src/be/nikiroo/fanfix/supported/EHentai.java b/src/be/nikiroo/fanfix/supported/EHentai.java index a25a994..c082b91 100644 --- a/src/be/nikiroo/fanfix/supported/EHentai.java +++ b/src/be/nikiroo/fanfix/supported/EHentai.java @@ -1,6 +1,5 @@ package be.nikiroo.fanfix.supported; -import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; @@ -14,6 +13,7 @@ import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.data.Chapter; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Story; +import be.nikiroo.utils.Image; import be.nikiroo.utils.Progress; import be.nikiroo.utils.StringUtils; @@ -78,8 +78,8 @@ class EHentai extends BasicSupport { return true; } - private BufferedImage getCover(URL source, InputStream in) { - BufferedImage author = null; + private Image getCover(URL source, InputStream in) { + Image author = null; String coverLine = getKeyLine(in, "

> chaps = getChapters(source, in, null); if (!chaps.isEmpty()) { -- 2.27.0