From 67206a0aa8c229e5d237f8ba56f7f29d5a064d00 Mon Sep 17 00:00:00 2001 From: skomoroh Date: Wed, 5 Aug 2009 16:46:12 +0000 Subject: [PATCH] * improved stacks bottom * bug fixes git-svn-id: file:///home/shlomif/Backup/svn-dumps/PySolFC/svnsync-repos/pysolfc/PySolFC/trunk@246 efabe8c0-fbe8-4139-b769-b5e6d273206e --- .../cards/bottoms/french/bottom03-n.png | Bin 0 -> 2792 bytes data/images/cards/bottoms/french/bottom03.png | Bin 0 -> 2792 bytes .../cards/bottoms/french/bottom04-n.png | Bin 0 -> 1559 bytes data/images/cards/bottoms/french/bottom04.png | Bin 0 -> 1393 bytes .../cards/bottoms/french/bottom05-n.png | Bin 0 -> 1313 bytes data/images/cards/bottoms/french/bottom05.png | Bin 0 -> 1175 bytes .../cards/bottoms/french/bottom06-n.png | Bin 0 -> 1517 bytes data/images/cards/bottoms/french/bottom06.png | Bin 0 -> 1517 bytes .../cards/bottoms/french/bottom07-n.png | Bin 0 -> 1391 bytes data/images/cards/bottoms/french/bottom07.png | Bin 0 -> 1391 bytes data/images/cards/bottoms/french/l01-n.png | Bin 0 -> 994 bytes data/images/cards/bottoms/french/l01.png | Bin 0 -> 986 bytes data/images/cards/bottoms/french/l02-n.png | Bin 0 -> 824 bytes data/images/cards/bottoms/french/l02.png | Bin 0 -> 810 bytes data/images/cards/bottoms/french/l03-n.png | Bin 0 -> 909 bytes data/images/cards/bottoms/french/l03.png | Bin 0 -> 895 bytes data/images/cards/bottoms/french/l04-n.png | Bin 0 -> 843 bytes data/images/cards/bottoms/french/l04.png | Bin 0 -> 832 bytes pysollib/game.py | 10 +- pysollib/games/picturegallery.py | 2 +- pysollib/images.py | 162 +++++++----------- pysollib/resource.py | 12 ++ pysollib/tile/tkutil.py | 27 +++ pysollib/tk/tkutil.py | 27 +++ scripts/cardset_viewer.py | 4 +- 25 files changed, 134 insertions(+), 110 deletions(-) create mode 100644 data/images/cards/bottoms/french/bottom03-n.png create mode 100644 data/images/cards/bottoms/french/bottom03.png create mode 100644 data/images/cards/bottoms/french/bottom04-n.png create mode 100644 data/images/cards/bottoms/french/bottom04.png create mode 100644 data/images/cards/bottoms/french/bottom05-n.png create mode 100644 data/images/cards/bottoms/french/bottom05.png create mode 100644 data/images/cards/bottoms/french/bottom06-n.png create mode 100644 data/images/cards/bottoms/french/bottom06.png create mode 100644 data/images/cards/bottoms/french/bottom07-n.png create mode 100644 data/images/cards/bottoms/french/bottom07.png create mode 100644 data/images/cards/bottoms/french/l01-n.png create mode 100644 data/images/cards/bottoms/french/l01.png create mode 100644 data/images/cards/bottoms/french/l02-n.png create mode 100644 data/images/cards/bottoms/french/l02.png create mode 100644 data/images/cards/bottoms/french/l03-n.png create mode 100644 data/images/cards/bottoms/french/l03.png create mode 100644 data/images/cards/bottoms/french/l04-n.png create mode 100644 data/images/cards/bottoms/french/l04.png diff --git a/data/images/cards/bottoms/french/bottom03-n.png b/data/images/cards/bottoms/french/bottom03-n.png new file mode 100644 index 0000000000000000000000000000000000000000..c3b8ef87aa4838166ce99158fb2d2cc3543f6b09 GIT binary patch literal 2792 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 WR=v&Q91wpo1?-Vm5p^~`cmEH^TOK+9 literal 0 HcmV?d00001 diff --git a/data/images/cards/bottoms/french/bottom03.png b/data/images/cards/bottoms/french/bottom03.png new file mode 100644 index 0000000000000000000000000000000000000000..f4ed963648effee231272d4e6c9013819376596a GIT binary patch literal 2792 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 V+1n(+0r3}8zz%g4S!?Zm=l}ls9J~Mk literal 0 HcmV?d00001 diff --git a/data/images/cards/bottoms/french/bottom04-n.png b/data/images/cards/bottoms/french/bottom04-n.png new file mode 100644 index 0000000000000000000000000000000000000000..5606124a704a55cd6a9c7fd1cc20cfaf49ffd4d1 GIT binary patch literal 1559 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 literal 0 HcmV?d00001 diff --git a/data/images/cards/bottoms/french/bottom05-n.png b/data/images/cards/bottoms/french/bottom05-n.png new file mode 100644 index 0000000000000000000000000000000000000000..b0d9380a98078e8aa5aad9ee432ec4686d0f5d93 GIT binary patch literal 1313 zcmV++1>X9JP)Px#32;bRa{vGu5dZ)h5dotq0jvN300(qQO+^RU2n7u{F*izY=>Px(vq?ljRCwC$ zoJ(jORT#(rUrZZQmHH?)@!5byEfldYutjW%Mw4ZAB^Ghv)|Kc^r9`1(eIVF{3JMXi zm8z|70$tdGm1?SP(kgA0G?++Kh%pxX$j`-{+IY=v?qkk8?tDK8B;1pkJKt}Uhbc6<)?RYGbQMEu4&JsgI{U zdhyG6hQ@fxqZr=<{59fXn@6-U8Lhwo@$wdMiAT3~8STKQgkiV8_o_|CmB0bQvJbez zqdmWj4&Ymo;VWQ?N4>I)F5no+aum4HqyK*yD}kR$hY{d5w{Stmdf<1`Wdc~^GN1>T zCL2rvn~E;u6xm`L*qByKEJYdjN!lan(hS}!e@W^yv(F15BpPPjBdI;Z2|OK1+27Pc zfNn{9GcIGclwLDC(3C=eyCm()iH!67DQT0Lece<-fDTEAC3WVo{V^(Om6=V1K2b|T zG8RbsFsCvk=>|zVf!3xFBIy-L8*<)C-ze$D+*et^qmtffqVChfX7+wAg#arg4P~^i z(MTU@!GYFZPhW4+!GLPk_9MzStsxL`ttvo2&; z!Gy$my&)dzt&+wh6=7ESuaY{=>}+N;B>Hkmu6#XR_V-MJ=iVBpj35~jWl4)lV( z2+EYCG#1_rNm^%SvEBed-u6aca!UeD;5RGC*qK08^+?<@f(ePF9Ff$g((Jzw3`p8> zkq7NSp!5DA=>ao48sgwV$JEX2kV-G#eu}e3l(b#aW0JZmlvx&izC9`*7spka#WPgh~^$2PJ)BW@qL&&P0X& z4w9}iv&pjZ3sjmx*`w0HQkSG_X2s!@r17YQI4Eh*%tlp2fW^_0=+-LBcg=HmcUO6w zR-iL0)lo}UgqYc+nT^-b(OTEw=l^zO&1}rfrd&v4#3ICruZkOpd(6u7)oLv~yajMuSM z#&w<{VR%x~(i;C~k)-GRc8)(gmPWhv)Wccec8_AbLUuIx`ut;$Vtg`g1?eB)}va#j27UNm^UcT)m8YfFA;H<@XD) zIhsS387w0LI#pVUbcdwJC9O>G^v6}2PBaw#K5AxoS~!m5IF92uj^j9v<2a7vIQ8=n XIuBRwnYtMp00000NkvXXu0mjf^X_Xi literal 0 HcmV?d00001 diff --git a/data/images/cards/bottoms/french/bottom05.png b/data/images/cards/bottoms/french/bottom05.png new file mode 100644 index 0000000000000000000000000000000000000000..c529dfaa8d499bef68ab00549365cbd50d2a5053 GIT binary patch literal 1175 zcmV;I1Zew-P)Px#32;bRa{vGu5&!@i5&;g7Ai)3t00(qQO+^RU2n7u{5ey_xApigbDM>^@RCwC$ zon2^GWgN#puFaB?tru%1js(RTM3lNPSxYu2>r%bx$}4ZXin>ejP8d-X2~ro5UWigg z?m|H#loFkyH#1@_*rXMfuxd#L6&i{X&=bZDL^Zme&y_~cE;ru@5<#`_n zA%qY@2qA*8EGJou?Q-+QAlsfmk z-=GW|?<$4vUf>_4lwsq5(wUBC;D{p`Ha-I$QfljG8F0$6jCego?Ot`z2AuOG!^T-) zxl+A2?Z8#fGHhHj%`c(`Yk<*=WZ3u-Sgq7A)XBjsB2DVmR#_fX0urUq1QAHWs3MeBkrKd_V`hb56D#OMkxfFa7xC|Sm7>KvKBrz#Q&&t`b+{VrwrqzM=%o3^CC$fpf!*wY2=jTg)5%{Wst9Al-n`o+ZoS_=~ zU!S+%GV}KnbsqPgsb^$1pdqg{r8+})9OkJhk8BfnDb$-}K3I~mf}0+{G2m&XG+nX$YuxsUUtnQJ zmq{-p!tYR?--+6~3RO8S%D)9#X_`b{0`?Fs8JiV9n-bh*^ZgAY pOb8)_5JCtcgb+dqA%tj<{{bj&de4^z2($nI002ovPDHLkV1go)CX@gG literal 0 HcmV?d00001 diff --git a/data/images/cards/bottoms/french/bottom06-n.png b/data/images/cards/bottoms/french/bottom06-n.png new file mode 100644 index 0000000000000000000000000000000000000000..b4571ca7e4e7a51c1bbf3febbd4d3e585e147088 GIT binary patch literal 1517 zcmVPx#32;bRa{vGuQ~&@PQ~`0aAu|8~00(qQO+^RU2n7u|Iwt_Ct^fc9e@R3^RCwC$ zook3zMHqme{V0`#1*OadZ{%0x&c~F^#|^rOm30vD^mC0M5)%%w}M+(q>^$LXtQ-5qKG>%dyy3 zfQOVe|8z2z-oSj|h8$yg7r0Alv(I}WNgSO5ybp{l!1X71qhg1KB4q#!0p{EK zjuuM~;Jt!n0GtIZNaE-O?}PwP0@syvbvPE7*1_kqfQw6t0S(3NgRy^Mmy?+QMUfWv5W;S za}>*!NgR#wAwwqPmPxICe#CJs4?CSh>`hlQ(8FOT><9YVwlw(=i_&JVs|*?KxB~!s z0=4$=A(l*6npuU6!4JlI6iaQEle6B?ob5>`48$J>x)c(7(h0FgLX-#*AxAjblTJ9* zBO#H?Nxc~%*FMQAWSjJVJDNm@Uu<_Nc5HDeWTo_fJ65?AvP}9v-#^mK&oGiW z+Dh?{N<(3r(&jXm83NEC9**!%)&lYnG8;H3E;t0taV|t@vl&<{K3Ht~!g+>3x?Hro zGb@ima$A^?#L>6F1>ID}I;G8!JPNA#_7@T;v-2t_Pa$t*{n{W5|GXyOE4F*+bG^B$@S8?ssrUFQJbkntI_r$g0HrOn173NI={P}*z)9|(8S6;jC)^XX5G&;j;0vH%pfZ|(;Yynyi>|0r zMr)KdKLg|Jgcuqvz%6CSC{2i!vKqK2Kp_*AHp|PZtWsvnls0bzQv;GQQ)%-?nH5$X zG;%6AJbNyIkATO@uGGbwvm|lU(_TW3@>E76a7~`y;(9H_O6d(O1upVT#(L7NJ9fCJ zyvAkAlQ`-NET{PGIF6TJfXkIOTU`ZEk5Ea)#ls3Nt z*OGA=e@6ZSu6HfN3n5m@M$)%v_c*BjZ(w}eJyW{15G&;?dpEzo#A*+b?hN;_Fa6++ z5G!RVa0hUpq$(d(+RXQ<54;j$rF;O~TS8S&DQ&!4OICxYByltuc)FnCUsu}H`PlA? zuR@eI&ya5Gnl}r9`+RM;w;9qZQ|6N2cC*WX+9I}ht@;dU#YEu49LiY_+~~86ATq>e zNpI4nH-o!a#4ge&ew%!6YX}*F-4JXXu(J!N9|R_ZAR`zdR>~IO_AcC`)GKX*S@{x- z5G&=l{uv2Ib|L&;TXTRj&xt&y&<)&LYUM6Uw82NZs6w7WCSb3Ub@zC z^w+WLLz%>@B|}i!tOZ{EpO3x+UJSKe!3wcV;lJ-S9s(Xv+8hueZn9)&o2#xjl{PCv zZc|O*8A1|AHKhMUW-xHB(&i5Y=Te3yadf}*gdhllAP9mW2!bF8f*=Tj;0ON#SX6@R T9;p>e00000NkvXXu0mjf4}_=% literal 0 HcmV?d00001 diff --git a/data/images/cards/bottoms/french/bottom06.png b/data/images/cards/bottoms/french/bottom06.png new file mode 100644 index 0000000000000000000000000000000000000000..37346fb7d589793084a8e2a3f9502c0310cf1d7e GIT binary patch literal 1517 zcmVPx#32;bRa{vGuQ~&@PQ~`0aAu|8~00(qQO+^RU2n7u|7h>P`+W-Ise@R3^RCwC$ zook3zMHqme{V0`#1*OadZ{%0x&c~F^#|^rOm30vD^mC0M5)%%w}M+(q>^$LXtQ-5qKG>%dyy3 zfQOVe|8z2z-oSj|h8$yg7r0Alv(I}WNgSO5ybp{l!1X71qhg1KB4q#!0p{EK zjuuM~;Jt!n0GtIZNaE-O?}PwP0@syvbvPE7*1_kqfQw6t0S(3NgRy^Mmy?+QMUfWv5W;S za}>*!NgR#wAwwqPmPxICe#CJs4?CSh>`hlQ(8FOT><9YVwlw(=i_&JVs|*?KxB~!s z0=4$=A(l*6npuU6!4JlI6iaQEle6B?ob5>`48$J>x)c(7(h0FgLX-#*AxAjblTJ9* zBO#H?Nxc~%*FMQAWSjJVJDNm@Uu<_Nc5HDeWTo_fJ65?AvP}9v-#^mK&oGiW z+Dh?{N<(3r(&jXm83NEC9**!%)&lYnG8;H3E;t0taV|t@vl&<{K3Ht~!g+>3x?Hro zGb@ima$A^?#L>6F1>ID}I;G8!JPNA#_7@T;v-2t_Pa$t*{n{W5|GXyOE4F*+bG^B$@S8?ssrUFQJbkntI_r$g0HrOn173NI={P}*z)9|(8S6;jC)^XX5G&;j;0vH%pfZ|(;Yynyi>|0r zMr)KdKLg|Jgcuqvz%6CSC{2i!vKqK2Kp_*AHp|PZtWsvnls0bzQv;GQQ)%-?nH5$X zG;%6AJbNyIkATO@uGGbwvm|lU(_TW3@>E76a7~`y;(9H_O6d(O1upVT#(L7NJ9fCJ zyvAkAlQ`-NET{PGIF6TJfXkIOTU`ZEk5Ea)#ls3Nt z*OGA=e@6ZSu6HfN3n5m@M$)%v_c*BjZ(w}eJyW{15G&;?dpEzo#A*+b?hN;_Fa6++ z5G!RVa0hUpq$(d(+RXQ<54;j$rF;O~TS8S&DQ&!4OICxYByltuc)FnCUsu}H`PlA? zuR@eI&ya5Gnl}r9`+RM;w;9qZQ|6N2cC*WX+9I}ht@;dU#YEu49LiY_+~~86ATq>e zNpI4nH-o!a#4ge&ew%!6YX}*F-4JXXu(J!N9|R_ZAR`zdR>~IO_AcC`)GKX*S@{x- z5G&=l{uv2Ib|L&;TXTRj&xt&y&<)&LYUM6Uw82NZs6w7WCSb3Ub@zC z^w+WLLz%>@B|}i!tOZ{EpO3x+UJSKe!3wcV;lJ-S9s(Xv+8hueZn9)&o2#xjl{PCv zZc|O*8A1|AHKhMUW-xHB(&i5Y=Te3yadf}*gdhllAP9mW2!bF8f*=Tj;0ON#SX6@R T9;p>e00000NkvXXu0mjf9IL5y literal 0 HcmV?d00001 diff --git a/data/images/cards/bottoms/french/bottom07-n.png b/data/images/cards/bottoms/french/bottom07-n.png new file mode 100644 index 0000000000000000000000000000000000000000..3c62c3f7b2a24a1b901d88edbb9113eed0c203b1 GIT binary patch literal 1391 zcmV-#1(5oQP)Px#32;bRa{vGuO8@{GO94)3pW^@k00(qQO+^RU2n7u~0zEWvvH$=D0ZBwbRCwC$ zoPTIlRUE)S)0uQs5^Hce^@oII zvdGGmtdR%~{|K%8v2frbA|kFQj4+&MwK3Np_XJbswm0v)_uTuwA9(C-@7;Ibxu1Q{ z_nx012!bF8f*=TjAP9mW2!bF8K@e$G6KQpA5y~>AAWm)rZV@5jaJvWzi>1KqA{3;m z0Quu);3wb=aD%a~S0W@^*7=_`K)qC1*+$0XNGy()xcKC zA?24b9rzxYG{Qq3Hr9P2Ldqj!0&oPFQNm#kxXW1AE>%|YY%5U)fCBbJT3shXl8uh1 zfQC^XJ{8y%X;m#kl94fYh+Eu|GT%2MC5K$0j2hq=aAQIrxyD$xT_R+3GR6Qc3CaLy zj7)ijd)DECludSC#ox{{Z#Ix`QI* z@-pTDUlVtIq``R~DF-Bn41Rn2Wr{KYCIGFGR*e!N7t5Fl90Vq3_%*fy>y336Dq2XS z)tx{q5JLCHK46)#uB#%2L|WYkd=5+uD3$#PEHc*pR#7=5(yGD#M}{N=;11wOq}7~? z5fW*&4%i8d3$%TvfwoAirG>7tBCW;}55GQ3KIjKtGSb$T3|ZG=To4`Sa&!GA$~-!)<0$fOMq*rJdP3%7n}gvjdg!y*$%k?R0Fdr zRL0*xJJ1dE`s)!)l{E|42rQ@o5uLz0z(+~;eU&SzFY*a}S^-6zBc96ozOk-9H@Cf! zR^y3RH@!$a?ob5UfK|r2U-R5BtOfQ0H|1DFH}C@Rb~&OV^{$ght1132d4;`fj5aKYj>t~!qf+-BCS>e?*Zcj7ST^UoVz9M6K67F=m&qk z08D@~dVxocbuC$(JhLI(NUQ6C-N4*{WOM;bjCK37`U05^;Tr2s6ZZmt5QvOFf%#d= z$TUJOiI%m#A(_=0jxs z^=*^?>0|gEOGQYTd3V6`ZN|C|5t1#tfz$r^7K9*jNpqytp(2!}x*$$Y`iBS!gbvc3 x93etR5Fvsf2!bF8f*=TjAP9mW2!ap@{{ew?V?eX_yJ7$U002ovPDHLkV1lJ%YhVBX literal 0 HcmV?d00001 diff --git a/data/images/cards/bottoms/french/bottom07.png b/data/images/cards/bottoms/french/bottom07.png new file mode 100644 index 0000000000000000000000000000000000000000..aa95016030f02046b6ccea5464005a27984e236c GIT binary patch literal 1391 zcmV-#1(5oQP)Px#32;bRa{vGuO8@{GO94)3pW^@k00(qQO+^RU2n7u}A+&x{0{{R80ZBwbRCwC$ zoPTIlRUE)S)0uQs5^Hce^@oII zvdGGmtdR%~{|K%8v2frbA|kFQj4+&MwK3Np_XJbswm0v)_uTuwA9(C-@7;Ibxu1Q{ z_nx012!bF8f*=TjAP9mW2!bF8K@e$G6KQpA5y~>AAWm)rZV@5jaJvWzi>1KqA{3;m z0Quu);3wb=aD%a~S0W@^*7=_`K)qC1*+$0XNGy()xcKC zA?24b9rzxYG{Qq3Hr9P2Ldqj!0&oPFQNm#kxXW1AE>%|YY%5U)fCBbJT3shXl8uh1 zfQC^XJ{8y%X;m#kl94fYh+Eu|GT%2MC5K$0j2hq=aAQIrxyD$xT_R+3GR6Qc3CaLy zj7)ijd)DECludSC#ox{{Z#Ix`QI* z@-pTDUlVtIq``R~DF-Bn41Rn2Wr{KYCIGFGR*e!N7t5Fl90Vq3_%*fy>y336Dq2XS z)tx{q5JLCHK46)#uB#%2L|WYkd=5+uD3$#PEHc*pR#7=5(yGD#M}{N=;11wOq}7~? z5fW*&4%i8d3$%TvfwoAirG>7tBCW;}55GQ3KIjKtGSb$T3|ZG=To4`Sa&!GA$~-!)<0$fOMq*rJdP3%7n}gvjdg!y*$%k?R0Fdr zRL0*xJJ1dE`s)!)l{E|42rQ@o5uLz0z(+~;eU&SzFY*a}S^-6zBc96ozOk-9H@Cf! zR^y3RH@!$a?ob5UfK|r2U-R5BtOfQ0H|1DFH}C@Rb~&OV^{$ght1132d4;`fj5aKYj>t~!qf+-BCS>e?*Zcj7ST^UoVz9M6K67F=m&qk z08D@~dVxocbuC$(JhLI(NUQ6C-N4*{WOM;bjCK37`U05^;Tr2s6ZZmt5QvOFf%#d= z$TUJOiI%m#A(_=0jxs z^=*^?>0|gEOGQYTd3V6`ZN|C|5t1#tfz$r^7K9*jNpqytp(2!}x*$$Y`iBS!gbvc3 x93etR5Fvsf2!bF8f*=TjAP9mW2!ap@{{ew?V?eX_yJ7$U002ovPDHLkV1fgfYjOYp literal 0 HcmV?d00001 diff --git a/data/images/cards/bottoms/french/l01-n.png b/data/images/cards/bottoms/french/l01-n.png new file mode 100644 index 0000000000000000000000000000000000000000..7a3ca2d48f7ace7087d5d9ec0ee014d4ce38e159 GIT binary patch literal 994 zcmV<810DQ{P)Px#32;bRa{vGf5dZ)S5dnW>Uy%R+00(qQO+^RU2n7xu1$)!!EdT%mbV)=(RCwC$ znp;Q|VHC&z>!lWNo0b)2K^ACKSQr%)NDuW;^j3rqL7{X5!-vY(NQ;QVr06B^p#&cb zdWs;TUNRyJmdYfN)GnK#k(bEJ>A}Oa-|X%2F3(|sMsz7Xu z=6>uWRh{wY>As9#h%nYEXU32h@3y)xncVOi5e;MS40~4`~ONg1nP*2$bfqhNj=C) z`o(UaA`s}lQttWwNv-S10|0!$9RNUIYRWy;AiIsF;dx8~06zN>B+DrC$9TwAuQH>| zA0TJ20RS+GdgEM=$4`gM(rwPi|38c{U^393X>(qW5QJnO(E|hzgOBkDRlC3s$*_eL-+uSX8cR&KT zg-igzdmQ7J4Az=fK+1J#zeli>t$JG+Uao*G%DjNSanU}oy&_W^@Q@x|tJ&Cpm)Zu& zHCD(oTIM~-Mw(z}njGy}`W28W??IljD}9vf2;_+Za>DE9NHwb1YQU(YD_t)4xq;;4 z8e5%ccX(}&P9Tj~!PX7OIWg$b3OMfGeA3AALdP%gjw&@W^{>Lx9gz^)_-PJ|VaW0I zr6xbNdlQi$JyO2WO%CHxOarDBa9jG@?-DvlVUrs@bcjMWAxfy0dgCnSo2VpxAfIT& zVqY;%!&GhYGs7?q(;v&7$vE{gri#!n)Uuc^ad#X?Kf8Ac$aXj z!qy#LC%codom%OV{K;QH1VlgtL_h>YKm&K7oitqW?sH0c}cKBuJIn QRR91007*qoM6N<$f)Aj|J^%m! literal 0 HcmV?d00001 diff --git a/data/images/cards/bottoms/french/l01.png b/data/images/cards/bottoms/french/l01.png new file mode 100644 index 0000000000000000000000000000000000000000..02bd14a67992c1572096935e5432c064cc5c0e59 GIT binary patch literal 986 zcmV<0110>4P)Px#32;bRa{vGf5dZ)S5dnW>Uy%R+00(qQO+^RU2n7xv2rf^?Qvd)1Y)M2xRCwC$ znq5d0K@`V->qlKQH7hI1f<8ct!oH}eNP4J;qPL=a2>KARK!~V(4U&i;N{U{L9!h!& z3VMhLBJd?4tUxM}LNfcXLZfa*n%jfZc4xa@cW?LJowal3<$q>om-*c@XJ&Tyf|!_? zn3$NDn3&ioW_j&sn>QrQvc^h81VlgtL_h>YKm;W7Al7lqcFK;>f>?8?i*d`t8<7Sg z=>qX=_CFUkyDA=y(9diT#?#@diejY>By&^iDDz!4dCUsk)M7SKY;1b8>P_K`$XW6L zIHlE=hb$s&RN@2qDl)_6VyGfw<#Jxh({_}en5ME&MT9yf-jZiSOH5ODh?ZYw@Qwn0Opjyd#`;BLiGQ;)}Ea&ji&bWjS#=upD7ul25|} zAeO}ivH^I;9`%wT z@fAZFNVzG??=IFVb;t`wphx)xXAtofGnKnHD$* zix^O{-q$nBYt5|;9^}3fUF7=$xu?1N1KvlhDk_z%v!lK)4JzH^{;CCZE7=zpc8Q1XY)bFDfayWZ@1?D{F7lBj)+x6liJPUo89aC26J8G zSQSV_h;T=%SnM+%B~EtzE=?I(=jn)T6`tPx#32;bRa{vGf5dZ)S5dnW>Uy%R+00(qQO+^RU2n7xzB^YDl*#H0n%1J~)RCwC$ znoVdEK^TU=-Lwg9ZLJlF6-uQB^dM9`s2~OkqT)qSu)PQ>9)zCsAR>rD4+=s(sEDAI z77M0KCOc1NcXob4BnW~a z2!bF8f*=TjApA!-vwsRKqYi4Pc50^i)Idae%2SpeQJPXtk;Sis7`lm~ zg;4}EjxLKYE!5Bz>NMUe(lCusjv8nct*0tIOx?}}JKLfLL&mS3$5GU4#}l}394}$B zogxE9H8V&|Nkow{GA|IbPa|nm@dK8WO~vuW$nCUGe0GfiYS-}dO#hcR%tYSiJS(ilTC-}d-B?kyt8S7QrGN@O2jjRZa^jpKYZ z>b2hL9AAwX?kSCazI{~$gG%EnB3v~b^vwkg7yU}(GT#AW1lN?tS-$s16t|Q{58s}u zR;?+PaEPx)BOZ7fKe3muMjVg-EcRdrUyW9bcp8(~$X8!XyCTpnV#rlty3hFkKDm?dqE0;-b>%4IbZOkC*+5YMV5wwGGf?f$0S}sn$_K z+f1kmsd%D=zsYW3-gkP*jy4+I3-NFjKaNRfiB}YiOxp+br&U3`Zo4*>lH? zKbZ|n<6nz}c!$gx5kU|HK@bE%5ClOG1VIpl%J~i4-c2VM+%X3L0000R!bF literal 0 HcmV?d00001 diff --git a/data/images/cards/bottoms/french/l02.png b/data/images/cards/bottoms/french/l02.png new file mode 100644 index 0000000000000000000000000000000000000000..2a96f794907b706d8ee209ae216d7b4073288ce0 GIT binary patch literal 810 zcmV+_1J(SAP)Px#32;bRa{vGf5dZ)S5dnW>Uy%R+00(qQO+^RU2n7xz6iL0~;{X5xyh%hsRCwC$ znomd+Q5=B3-BlO0H8aW##IS`r1V)DnB0-3XE=56l2`V}Sp6U=0M1hBbzz!7=l%YgK zC7rjTgHr4%it1v!8U2%T4Yp*ft#-PMuX(AnqN}{O{l2;E+xgAT`{w=G-@F+R1VIo4 zK@bE%5ClOG{v!f&aE|4)&_ok;%%=)SlP1Yy;>5_>ahbxj6UUi!OL3Nk=4Y?Vu2s%eTD5Po^fN$;Dps?B63-rob}pLP7UlG5S3S)!BA)$G9%%b>Y%x=$N2_Ln z=(vb7Vp_~g!scl-YgPQn(g~w#`Krb3GEd}&R>8?T%>^y4$2^hup6bPX;8ajEpSTtO{HGYlh^pLc-?$~3$d8$wG&l<)ed^OK-?&Pxlrm4`B$;ta6H%>|-k2xy zl=a-<3lR5>tJg~X=H}IrJP{q*7};#^EyP`q#^9{?_5G$vrHMkTM5#t?P(w#VPRH%qg<8e7RJk^S~+MER^VPS~pv@yu4|?bQf# zUuksPJ6DD1RT|d_*{Ttss~9wbbSsT3_9loSt}Bgm_KuA*ZYzxrduOT&wWgTku)P}9 zJajdFvCm$OTArxIo}Kn;G%(<5jIzmIjg`E0HAYxxuf`gNU5yW{vR9*-w5yS%(O!*h zWL%ABHsAfVsb!uxHNKIJWcW_POpSy5b~WxXFHdYI4h}a>)HteAk>0$|1Q#)igTo>7 zG)^mxt|_GHV@bVXQ*)3@N~3cM`R!ge_8X-pX_R^%fF92qy?|3{9i?Co6G{s5D`(VO z4ns6>+4rt}8EYw1;M20|v;Y7A07*qoM6N<$f}a0(z5oCK literal 0 HcmV?d00001 diff --git a/data/images/cards/bottoms/french/l03-n.png b/data/images/cards/bottoms/french/l03-n.png new file mode 100644 index 0000000000000000000000000000000000000000..e812ca9b9548ce48c18f0d86b32e86842f101f02 GIT binary patch literal 909 zcmV;819JR{P)Px#32;bRa{vGf5dZ)S5dnW>Uy%R+00(qQO+^RU2n7x#DMyb8bN~PYA4x<(RCwC$ znoCGjQ5eVnSI1Y9Mw3NK%PfTP5pKzX`_{1w*Wx9mJ zQodtkMtQ*Cp~cl`L{Y%W7wE!A#9<{?go0uzx+!_Az`*oiC z%oJ%A5_3EjBy&P!-Y~^HjY9#wQ4%y2#{rQ#VxCB|DDY;;T&>96Hcw>SuRJf;hs>1- zk(YmS&A6DD_&*u0Iin$SlcJSrp2)c0ak$&+GEVQT~+S0OWdbMd66q^Q78?% z*)YsT9;9n|ujPuV$@V2@X3&JYXm=*Xr& z3Xyx}?xIAZO|(4rio6xA40}Z;L@UK!k$BPa+AHD?(?3>;WQ3V9|67C(_pq8c+5D-D^;=ZHwQFy1VYCQ+V`Czo!!F@aV5 zCUQMYH*HzIYsvRNy)6AR`src;Yxp`K(ZVzn-!RSv-S+YFJtu;EPx#32;bRa{vGf5dZ)S5dnW>Uy%R+00(qQO+^RU2n7x#6841QPyhe}5lKWrRCwC$ znoCF(Q5eU6>h+bR(aj>Ia*-m@g%qO4A~3LpEs8d^%dUwljid)HvPDD?xM(3lM6?pa zs1`GgIV| zkeK3Fkjx2@c}uc+8iyRCQ5-ZCORq>BF;ApXbns@#T(!vEHcwnhs+fVkyrn7 z$k;^@37i?OF&Hv8>X|m-b<-Utw^p=<%o91!``N9>VRQ2C z=`&AcfIKeH#!v*20>|8ADQ>34Q_EwkNTtwdu~j3DuR>&pts=ETqsCT^3Zc*0dAFD*t!`v~;E)v5YD%l!UR+fIAn=~_Qp$k8L%A!&p z74t}uIT{%Z&35Wi6zTm!((^c5weGc#xF8W5}63- zT3y&=HseC%tXYe|Poi_)khwetM6$^-H7+|1qI=Vv3{ne-r-C0M*GZab%ko|GzW?dM zJ9qWF$ft@ojzklwCca^u3tIN^@sW`rA304@wM=V@C@8@f#V1XE{4|nl_IqC@)r^Hz z7^RkNi*xXWF3`EyNddWRCW91GaPgaQ`gzR@T4`q*MNt$*Q4~c{6h%=KMNt%E`3t1a V-4|rbI?Mn7002ovPDHLkV1nMSkK6zN literal 0 HcmV?d00001 diff --git a/data/images/cards/bottoms/french/l04-n.png b/data/images/cards/bottoms/french/l04-n.png new file mode 100644 index 0000000000000000000000000000000000000000..d2ca90b665a71ca876229d32a38e52a5d8cfc643 GIT binary patch literal 843 zcmV-R1GM~!P)Px#32;bRa{vGf5dZ)S5dnW>Uy%R+00(qQO+^RU2n7x%0YD7G3;+NE-AP12RCwC$ znN3KPK^VuMt<`t?KteO4PYMIsA|hd-BKkN;hfawUL5G6KgQav4q9Ce6hoY|4$SwV8P2Zr#PhqoGY{|k{PvmIcV=E9K@bE% z5ClOG1VIo4LC7z-2$R!XHR@rri>F2n#x0E`N;zt*#kZ7t^m5dwzz3vq-Oasc6;NXi z-Jz94l%!uq^Am2>2;r8h!A+|o)!anRtHgV7+|U?Cn3u*OmG}svxNnGb@Y2|cpDOXA z2=K!Yxxh)I3SU*)ZA92%&5$}i8s$i+q`MFy!Z}N1ITwupag}l(mJku4!_esCQ;!>Z zlE;XM5W$!sa+{0B8NHs`t6H{O1FM;b#sQu1DcyF`64}N-< zGqTqZ>GVyb1h3!%2YdJFo&6r6bxwYf?wJ{P zb1XDq%!u}UJfR@pN3fJCjLTPx#32;bRa{vGf5dZ)S5dnW>Uy%R+00(qQO+^RU2n7x$E3lea82|tR(n&-?RCwC$ znM+7jK^TBP>*}=!5|$Y~DGbCSBH=EyX&?hBE|ur#*u(*%B) zI6s8Qg^)B#`D((h2ew)>q$(VZB05aa&Ex~;ERiLlXvAqUA$PJ6fJULw8BRWKM3X!L zKt6*)p9`8dx=9XzYywJ{8rSv_v+Cps^_$M0KL}p3oR(mj44{!> zaZ&$8h&=aSqmVZy*!Rp6^(EH8y5hS=9*<0@y_8ukdn}QCzKhhFK!>Op)pFSqDf3(7 z&vU6drL9S5^pfMV#%@MTpqEnGV)O}-2R>`8r{9EmcZ|K~T5DjP^;cs#pG}Z2m_0`O z0ZU|uuNrfBZ9?oyv!=aji4^&%k;}tq^O{K0r%h;d_?nMv(ekh=?HP(Zn5*|wqb3UQ zMA|+ZtbujJM~%wpkz1Rg*HKF(;h#n#dOI|bm!V&s&=|57B@3pLgaCFZZR1{YXu8L>1DVgJFQYj zs3HX%v&wCXxC9ZDl z`g8r7akf`dIqq_U<$AKO`={Q|P!vT`6h%=KMNt$*Q4~c{-18g1`?JwT$peT00000< KMNUMnLSTZD_H{r2 literal 0 HcmV?d00001 diff --git a/pysollib/game.py b/pysollib/game.py index 3c7161db..efe15ec8 100644 --- a/pysollib/game.py +++ b/pysollib/game.py @@ -78,9 +78,10 @@ class Game: S_INIT = 0x00 S_DEAL = 0x10 S_FILL = 0x20 - S_PLAY = 0x30 - S_UNDO = 0x40 - S_REDO = 0x50 + S_RESTORE = 0x30 + S_PLAY = 0x40 + S_UNDO = 0x50 + S_REDO = 0x60 # for loading and saving - subclasses should override if # the format for a saved game changed (see also canLoadGame()) @@ -504,6 +505,8 @@ class Game: self.snapshots = game.snapshots # 3) move cards to stacks assert len(self.allstacks) == len(game.loadinfo.stacks) + old_state = game.moves.state + game.moves.state = self.S_RESTORE for i in range(len(self.allstacks)): for t in game.loadinfo.stacks[i]: card_id, face_up = t @@ -513,6 +516,7 @@ class Game: else: card.showBack() self.allstacks[i].addCard(card) + game.moves.state = old_state # 4) update settings for stack_id, cap in self.saveinfo.stack_caps: ##print stack_id, cap diff --git a/pysollib/games/picturegallery.py b/pysollib/games/picturegallery.py index 7adfb95a..05384854 100644 --- a/pysollib/games/picturegallery.py +++ b/pysollib/games/picturegallery.py @@ -137,7 +137,7 @@ class PictureGallery_Foundation(RK_FoundationStack): def closeStack(self): if len(self.cards) == 8: - if not self.game.moves.state == self.game.S_REDO: + if self.game.moves.state not in (self.game.S_REDO, self.game.S_RESTORE): self.game.flipAllMove(self) def canFlipCard(self): diff --git a/pysollib/images.py b/pysollib/images.py index 4a1fb46e..4377ac32 100644 --- a/pysollib/images.py +++ b/pysollib/images.py @@ -24,13 +24,15 @@ # imports import os +import traceback # PySol imports +from resource import CSI from settings import TOOLKIT from mfxutil import Image, ImageTk # Toolkit imports -from pysoltk import loadImage, copyImage, createImage, shadowImage +from pysoltk import loadImage, copyImage, createImage, shadowImage, createBottom # ************************************************************************ @@ -54,6 +56,9 @@ class Images: self.reduced = r if cs is None: return + self.use_pil = False + if TOOLKIT == 'tk' and Image and Image.VERSION >= '1.1.7': + self.use_pil = True # copy from cardset self.CARDW, self.CARDH, self.CARDD = cs.CARDW/r, cs.CARDH/r, cs.CARDD/r self.CARD_XOFFSET = cs.CARD_XOFFSET @@ -89,7 +94,10 @@ class Images: f = os.path.join(self.cs.dir, filename) if not os.path.exists(f): return None - img = loadImage(file=f) + try: + img = loadImage(file=f) + except: + return None w, h = img.width(), img.height() if self.CARDW < 0: self.CARDW, self.CARDH = w, h @@ -99,6 +107,26 @@ class Images: raise ValueError("Invalid size %dx%d of image %s" % (w, h, f)) return img + def __loadBottom(self, filename, check_w=1, check_h=1, color='white'): + cs_type = CSI.TYPE_ID[self.cs.type] + imagedir = None + d = os.path.join('images', 'cards', 'bottoms') + try: + imagedir = self.d.findDir(cs_type, d) + except: + pass + if not self.use_pil or imagedir is None: + # load image + return self.__loadCard(filename+self.cs.ext, check_w, check_h) + # create image + d = os.path.join('images', 'cards', 'bottoms', cs_type) + try: + fn = self.d.findImage(filename, d) + except: + fn = None + img = createBottom(self._card[0], color, fn) + return img + def __addBack(self, im1, name): r = max(self.CARDW / 40.0, self.CARDH / 60.0) r = max(2, int(round(r))) @@ -133,20 +161,12 @@ class Images: self._letter_negative.append(neg_bottom) self._blank_bottom = createImage(self.CARDW, self.CARDH, fill=None, outline=None) - def load(self, app, progress=None, fast=0): - ##fast = 1 - ##fast = 2 - if fast > 1: - # only for testing - self.cs.backnames = () - self.cs.nbottoms = 0 - self.cs.nletters = 0 + def load(self, app, progress=None): ext = self.cs.ext[1:] pstep = 0 if progress: pstep = self.cs.ncards + len(self.cs.backnames) + self.cs.nbottoms + self.cs.nletters - if not fast: - pstep = pstep + self.cs.nshadows + 1 # shadows & shade + pstep += self.cs.nshadows + 1 # shadows & shade pstep = max(0, (80.0 - progress.percent) / pstep) # load face cards for n in self.cs.getFaceCardNames(): @@ -157,73 +177,41 @@ class Images: # load backgrounds for name in self.cs.backnames: if name: - try: - im = self.__loadCard(name) - self.__addBack(im, name) - except: - pass + im = self.__loadCard(name) + self.__addBack(im, name) if progress: progress.update(step=1) # load bottoms for i in range(self.cs.nbottoms): - try: - name = "bottom%02d.%s" % (i + 1, ext) - self._bottom_positive.append(self.__loadCard(name)) - except: - pass + name = "bottom%02d" % (i + 1) + self._bottom_positive.append(self.__loadBottom(name, color='black')) if progress: progress.update(step=pstep) # load negative bottoms - try: - name = "bottom%02d-n.%s" % (i + 1, ext) - self._bottom_negative.append(self.__loadCard(name)) - except: - pass + name = "bottom%02d-n" % (i + 1) + self._bottom_negative.append(self.__loadBottom(name, color='white')) if progress: progress.update(step=pstep) # load letters for rank in range(self.cs.nletters): - try: - name = "l%02d.%s" % (rank + 1, ext) - self._letter_positive.append(self.__loadCard(name)) - except: - pass + name = "l%02d" % (rank + 1) + self._letter_positive.append(self.__loadBottom(name, color='black')) if progress: progress.update(step=pstep) # load negative letters - try: - name = "l%02d-n.%s" % (rank + 1, ext) - self._letter_negative.append(self.__loadCard(name)) - except: - pass + name = "l%02d-n" % (rank + 1) + self._letter_negative.append(self.__loadBottom(name, color='white')) if progress: progress.update(step=pstep) # shadow - if TOOLKIT == 'tk' and Image and Image.VERSION >= '1.1.7': - if 0: - fn = self.d.findImage('shadow', 'images') - self._pil_shadow_image = Image.open(fn).convert('RGBA') - else: + if not self.use_pil: for i in range(self.cs.nshadows): - if fast: - self._shadow.append(None) - else: - name = "shadow%02d.%s" % (i, ext) - try: - im = self.__loadCard(name, check_w=0, check_h=0) - except: - im = None - self._shadow.append(im) - - if fast: - self._xshadow.append(None) - elif i > 0: # skip 0 + name = "shadow%02d.%s" % (i, ext) + im = self.__loadCard(name, check_w=0, check_h=0) + self._shadow.append(im) + if i > 0: # skip 0 name = "xshadow%02d.%s" % (i, ext) - try: - im = self.__loadCard(name, check_w=0, check_h=0) - except: - im = None + im = self.__loadCard(name, check_w=0, check_h=0) self._xshadow.append(im) - if progress: progress.update(step=pstep) # shade - if fast: - self._shade.append(None) + if self.use_pil: + self._shade.append(self._getShadow(self._card[0], None, '#3896f8')) else: self._shade.append(self.__loadCard("shade." + ext)) if progress: progress.update(step=pstep) @@ -233,7 +221,6 @@ class Images: self._bottom = self._bottom_positive self._letter = self._letter_positive # - return 1 def getFace(self, deck, suit, rank): @@ -304,46 +291,13 @@ class Images: im = c._active_image._pil_image mask.paste(im, (x, y), im) # create shadow - if 0: - sh = self._pil_shadow_image - shw, shh = sh.size - shadow = Image.new('RGBA', (w, h)) - x = 0 - while x < w: - y = 0 - while y < h: - shadow.paste(sh, (x,y)) - y += shh - x += shw - shadow = Image.composite(shadow, mask, mask) - # crop image (for speed) - sx, sy = self.SHADOW_XOFFSET, self.SHADOW_YOFFSET - mask = mask.crop((sx,sy,w,h)) - tmp = Image.new('RGBA', (w-sx,h-sy)) - shadow.paste(tmp, (0,0), mask) - elif 0: - import ImageFilter - dx, dy = 5, 5 - sh_color = (0x00,0x00,0x00,0x80) - shadow = Image.new('RGBA', (w+dx, h+dy)) - sx, sy = self.SHADOW_XOFFSET, self.SHADOW_YOFFSET - shadow.paste(sh_color, (0, 0, w, h), mask) - for i in range(3): - shadow = shadow.filter(ImageFilter.BLUR) - shadow = shadow.crop((dx,dy,w,h)) - sx, sy = self.SHADOW_XOFFSET, self.SHADOW_YOFFSET - mask = mask.crop((sx,sy,w,h)) - tmp = Image.new('RGBA', (w-sx,h-sy)) - shadow.paste(tmp, (0,0), mask) - else: - sh_color = (0x00,0x00,0x00,0x50) - shadow = Image.new('RGBA', (w, h)) - shadow.paste(sh_color, (0, 0, w, h), mask) - sx, sy = self.SHADOW_XOFFSET, self.SHADOW_YOFFSET - mask = mask.crop((sx,sy,w,h)) - tmp = Image.new('RGBA', (w-sx,h-sy)) - shadow.paste(tmp, (0,0), mask) - + sh_color = (0x00,0x00,0x00,0x50) + shadow = Image.new('RGBA', (w, h)) + shadow.paste(sh_color, (0, 0, w, h), mask) + sx, sy = self.SHADOW_XOFFSET, self.SHADOW_YOFFSET + mask = mask.crop((sx,sy,w,h)) + tmp = Image.new('RGBA', (w-sx,h-sy)) + shadow.paste(tmp, (0,0), mask) # shadow = ImageTk.PhotoImage(shadow) self._pil_shadow[(w,h)] = shadow @@ -353,7 +307,7 @@ class Images: return self._shade[self._shade_index] def _getShadow(self, image, card, color='#3896f8', factor=0.3): - if TOOLKIT == 'tk' and Image and Image.VERSION >= '1.1.7': + if self.use_pil: # use alpha image; one for each color if color in self._shadow_cards: shade = self._shadow_cards[color] diff --git a/pysollib/resource.py b/pysollib/resource.py index 49e7f835..26625a3c 100644 --- a/pysollib/resource.py +++ b/pysollib/resource.py @@ -200,6 +200,18 @@ class CSI: 9: _("Trumps only"), } + TYPE_ID = { + 1: "french", + 2: "hanafuda", + 3: "tarock", + 4: "mahjongg", + 5: "hex-a-deck", + 6: "mughal-ganjifa", + 7: "navagraha-ganjifa", + 8: "dashavatara-ganjifa", + 9: "trumps-only", + } + # cardset styles STYLE = { 1: _("Adult"), # diff --git a/pysollib/tile/tkutil.py b/pysollib/tile/tkutil.py index 78d5952f..a698a4a0 100644 --- a/pysollib/tile/tkutil.py +++ b/pysollib/tile/tkutil.py @@ -40,6 +40,7 @@ __all__ = ['wm_withdraw', 'createImage', 'shadowImage', 'markImage', + 'createBottom', 'get_text_width', ] @@ -359,6 +360,32 @@ def markImage(image): out = Image.composite(tmp, image, image) return out +def createBottom(image, color='white', backfile=None): + if not hasattr(image, '_pil_image'): + return None + im = image._pil_image + th = 1 # thickness + sh = Image.new('RGBA', im.size, color) + out = Image.composite(sh, im, im) + w, h = im.size + size = (w-th*2, h-th*2) + tmp = Image.new('RGBA', size, color) + tmp.putalpha(40) + mask = out.resize(size, Image.ANTIALIAS) + out.paste(tmp, (th,th), mask) + if backfile: + back = Image.open(backfile).convert('RGBA') + w0, h0 = back.size + w1, h1 = im.size + a = min(float(w1)/w0, float(h1)/h0) + a = a*0.9 + w0, h0 = int(w0*a), int(h0*a) + back = back.resize((w0,h0), Image.ANTIALIAS) + x, y = (w1 - w0) / 2, (h1 - h0) / 2 + out.paste(back, (x,y), back) + return PIL_Image(image=out) + + # ************************************************************************ # * font utils # ************************************************************************ diff --git a/pysollib/tk/tkutil.py b/pysollib/tk/tkutil.py index 78d5952f..a698a4a0 100644 --- a/pysollib/tk/tkutil.py +++ b/pysollib/tk/tkutil.py @@ -40,6 +40,7 @@ __all__ = ['wm_withdraw', 'createImage', 'shadowImage', 'markImage', + 'createBottom', 'get_text_width', ] @@ -359,6 +360,32 @@ def markImage(image): out = Image.composite(tmp, image, image) return out +def createBottom(image, color='white', backfile=None): + if not hasattr(image, '_pil_image'): + return None + im = image._pil_image + th = 1 # thickness + sh = Image.new('RGBA', im.size, color) + out = Image.composite(sh, im, im) + w, h = im.size + size = (w-th*2, h-th*2) + tmp = Image.new('RGBA', size, color) + tmp.putalpha(40) + mask = out.resize(size, Image.ANTIALIAS) + out.paste(tmp, (th,th), mask) + if backfile: + back = Image.open(backfile).convert('RGBA') + w0, h0 = back.size + w1, h1 = im.size + a = min(float(w1)/w0, float(h1)/h0) + a = a*0.9 + w0, h0 = int(w0*a), int(h0*a) + back = back.resize((w0,h0), Image.ANTIALIAS) + x, y = (w1 - w0) / 2, (h1 - h0) / 2 + out.paste(back, (x,y), back) + return PIL_Image(image=out) + + # ************************************************************************ # * font utils # ************************************************************************ diff --git a/scripts/cardset_viewer.py b/scripts/cardset_viewer.py index afd30417..b1ea6a1b 100755 --- a/scripts/cardset_viewer.py +++ b/scripts/cardset_viewer.py @@ -64,8 +64,8 @@ def show_cardset(*args): ls = glob(os.path.join(cs.dir, '[0-9][0-9][a-z]'+cs.ext)) ls += glob(os.path.join(cs.dir, 'back*'+cs.ext)) if all_imgs: - ls += glob(os.path.join(cs.dir, 'bottom*.gif')) - ls += glob(os.path.join(cs.dir, 'l*.gif')) + ls += glob(os.path.join(cs.dir, 'bottom*'+cs.ext)) + ls += glob(os.path.join(cs.dir, 'l*'+cs.ext)) #ls = glob(os.path.join(cs.dir, '*.gif')) ##if not ls: return ls.sort()