freetype-rs-0.36.0/.cargo_vcs_info.json0000644000000001360000000000100133670ustar { "git": { "sha1": "991a5701f7ef2aef5f0084a46ab9f70e6b342357" }, "path_in_vcs": "" }freetype-rs-0.36.0/.gitignore000064400000000000000000000003601046102023000141460ustar 00000000000000.DS_Store *~ *# *.o *.so *.swp *.old *.bak *.kate-swp *.dylib *.dSYM *.dll *.rlib *.dummy *.exe *-test /bin/main /bin/test-internal /bin/test-external /doc/ /target/ /build/ /.rust/ rusti.sh watch.sh /examples/**/target .vscode Cargo.lock freetype-rs-0.36.0/.travis.yml000064400000000000000000000000171046102023000142660ustar 00000000000000language: rust freetype-rs-0.36.0/Cargo.lock0000644000000036270000000000100113520ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "bitflags" version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "libc", ] [[package]] name = "freetype-rs" version = "0.36.0" dependencies = [ "bitflags", "freetype-sys", "libc", "unicode-normalization", ] [[package]] name = "freetype-sys" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b4dbbf4b8447b92e62282bf26760e7221f4f7ac15b9b10b3c99e4033379dbe0" dependencies = [ "cc", "libc", "pkg-config", ] [[package]] name = "libc" version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "pkg-config" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "tinyvec" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "unicode-normalization" version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] freetype-rs-0.36.0/Cargo.toml0000644000000020260000000000100113650ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] name = "freetype-rs" version = "0.36.0" authors = ["Coeuvre "] description = "Bindings for FreeType font library" homepage = "https://github.com/PistonDevelopers/freetype-rs" readme = "README.md" keywords = [ "freetype", "font", "glyph", ] license = "MIT" repository = "https://github.com/PistonDevelopers/freetype-rs.git" [lib] name = "freetype" [dependencies.bitflags] version = "2.4.0" [dependencies.freetype-sys] version = "0.20.0" [dependencies.libc] version = "0.2.1" [dev-dependencies.unicode-normalization] version = "0.1.0" freetype-rs-0.36.0/Cargo.toml.orig000064400000000000000000000007641046102023000150550ustar 00000000000000[package] name = "freetype-rs" version = "0.36.0" authors = ["Coeuvre "] keywords = ["freetype", "font", "glyph"] description = "Bindings for FreeType font library" license = "MIT" readme = "README.md" repository = "https://github.com/PistonDevelopers/freetype-rs.git" homepage = "https://github.com/PistonDevelopers/freetype-rs" [lib] name = "freetype" [dependencies] bitflags = "2.4.0" libc = "0.2.1" freetype-sys = "0.20.0" [dev-dependencies] unicode-normalization = "0.1.0" freetype-rs-0.36.0/LICENSE000064400000000000000000000020721046102023000131650ustar 00000000000000The MIT License (MIT) Copyright (c) 2014 PistonDevelopers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.freetype-rs-0.36.0/README.md000064400000000000000000000014521046102023000134400ustar 00000000000000# freetype-rs [![Build Status](https://travis-ci.org/PistonDevelopers/freetype-rs.svg?branch=master)](https://travis-ci.org/PistonDevelopers/freetype-rs) Rust bindings for FreeType library ## Requirements * *Cargo*: We use Cargo to compile the project. * *FreeType2 development libraries*: For installation instructions see [freetype-sys](https://github.com/PistonDevelopers/freetype-sys). ## Build Clone this repo then run ``` cd freetype-rs cargo build ``` ## Examples To build examples, use `cargo test`. They are all built in `./target/debug/examples/*`. To run examples, use `cargo run --example name`, for example: ``` cargo run --example single_glyph examples/assets/FiraSans-Regular.ttf A ``` [How to contribute](https://github.com/PistonDevelopers/piston/blob/master/CONTRIBUTING.md) freetype-rs-0.36.0/examples/assets/FiraSans-Regular.ttf000064400000000000000000005743741046102023000211470ustar 00000000000000GDEF48*hGPOSa{^GSUBs_p%ROS/2`wp`cmapN&rcvt Bs fpgmY pgaspglyfS9 DRhead~6hhea$hmtx, locaB&  nmaxpr < name>\post|D4prepyD :[\]^o $%  DFLTcyrl,grek>latnP   "CAT 0MOL >PLK LROM ZTRK h   !"#$cpspcpspcpspcpspcpspcpspcpspcpspcpsp kernkernkernkern"kern(kern.kern4kern:kern@markFmarkPmarkZmarkdmarknmarkxmarkmarkmarkmkmkmkmkmkmkmkmkmkmkmkmkmkmkmkmkmkmk&.6>8:GMklu|p  &,28>D(*dM  !2#      <((   2   (   2  <v           ~   PZdd dd P<P<F((2 FP<$2  F       <<2   2 2 F  Z    j   (< ( ~  Je*e;          Dde+Y P     ( P P  2       2 j~(  d(Z '0'@ $jpvv|jdz                               "( . 4 :     @      FL FL   "R   z zX  ^ d j p   v | 4                                      *$ *0 $ 6 < B     H     T N    Z   ` f l r   x ~ <                               & & , 2  8 > D J P V \     b h     n t n t   > z J      V    @Sh44444_44444OzZ<"Z#"#V$T^q[ZG #ZDh#;;###V#^#Z#####%g,$!o*#Mg,$#o444 4Z4  }4494<4k474654474]44544e484444445om4 $ $*06 <BHNTZ`fllfrx`~T"(.4@:FLRXFd^Fjpv|"(.@:FLXFd^F^F"(."(."(."(.@:FL@:FLXFXFd^Fd^Fd^Fd^F $0*6<BHNTZf`lrx0*6~*6~*6lrrrTZx $  $$$0*60*60*60*60*60*60*6*6TZTZlrlrlrlrlrlrlrrxxx@Sh44444_44444OzZ<"Z#TH;aW^qX##&$!!444 4Z4 4844]4.4%B4994k454464F $ b h n  n t  z    b                   \    y r x ~ r x ~ r x ~ r x ~ r ~ r x ~ r x ~ r x ~ r x ~ r x ~                                                                        & , & , & , & , 2 , & , & , & , 8 8 & , > D J D J D J D J P V P V P V P V P V P V \ b n h \ b \ b \ b t z t z t z t z t  t z t z t z t z t z t z               8     & , P V                                                          "(. (. (. (. (. (. 4444:444444@FLFLFLFLRXRXRXRXRXRX^^^^^d d d d djd d d d d d pppvp||||  (. 4RX $ $*0*0*0*0*06<B6HNTHNTHNTHNTHNTHZTHNTHNTH`THNTHNTHNTffl l l rxrxrxrxrx~@Sh44444_44444OzZ#[Z/;"Z#"#cWTX^#H;,a^q^#U+5 KK###!%$**U$$!gg746B4994k44444444 4Z4  T44S4=4484-4O44]444.444 96445/5/m4m44X ~||@Sh44444_44444#B  #$&'16:;=ADNY_abcdhiwxy|~d%+8";G0I=<>>@@ W`!hv+{:dh (*,0235579<<>>@@CCEFHMQW[^``egmnpprrtvzz/356789;  =>?!"B./D13F55I79J<<M>>NABODDQJMROPVXZXcd[gl]''c..d 0;?@CEFNmnoppr&*-./01234 7 =?I@@JRRKiiLssMNOP $%".#%)+CFPQRT!!V%%W((X*.Y22^47_99c<<dABeE[g^^~acenrrux{  *+,-../00[24\67_::a<<bABcFoe$ &B DG=IUAYrNtxhzm&(;=_ar>wPkp 3         #$&'1166:;==AADDNNYY__acddhh iiwxyy ||~~  :&*:9:KJU:XX:cg sstxyyz~::%;;+;;=  J  ;;=J77&(-7AE7UV1``$hs7vv7{ D!?A%;8;9:: :  9:K  : : ::%;-;  ;    /(;;;0""$$&&/((=));**--+22;33556699<<;==>>@@AB0FFGG0HI%JL;MMNNQS;TTUWXX0[[\\]]%^^ddff;iiCoo#pp$rr7uu7vv wx"zz?{{B>@1 7DC 7A?0B%;;7;@"B!:: :::;;:;;;;  ;!";..115578899$<<7AA BBADD?JLAMM7OOcc;dd7elAqqrr ssuuHvvIwwxxLyy{{263 &545.5 4<'.*),*),FFF  E5%%;@@FRRFiiFssFG&&1' #4$!%%$+.&//08&;<*=B-CC0DG&II&JT4UU!VV7WWXX4Y\9]b;hrsstxyyz~ 4&4;     %'),/13  6   '6:+$(%& ''(-:.12; <<.>>@@WY5Z_``hrss tt8uu vv{+" 2 !!&*&0&4&74&&&&;4&44*&&&&!4&4&& %!    1  3 1(('))** ,,-- ..// 0022 33,55179<<>>,@@1CCEEFF1HIJJKL MM1QT UW3[[/\\#]]^^(``ee ffgg mn5pprrtt8uu:vvzz2+"5:2   ! &4&*0&!4&74!&4&!&4', 4,      !" ..(//11(22 335577588(99<<>>8AABBDD2JLMMOO(PP XZcc ddgl'';..;z F&*9:CC JUXX]bcgUhrlss!txVyyXz~iYY0OO:=AADJOJOJ      OJO:++P&L''(-+.<?@AE+FTUV'W_``aegghs+tuvv+wz{P/E$ 50OFOX3 UWXk%UoUU!X3UUiXkXkFX3oWk0OJ,O  O     J-.JOJO?O9!J""M##J$$?%%J&&-''J(())O**++,,A--D//J22O33 556678J99?:;J<<O==?>> @@AB9FFGG9HI0JLOMMNNOPQSOTTUWXX9YZJ[[ \\]]0^^L_`acJdd]eeffOggiiejloocppqqrr+stuu+vv/wx\yy^zz {{_|bPd'/+Ee/+?5 9_0OsO+Od\_$FFYF mnUi"XjFiiFiO IO6JJ7J QOJOKO*Ot  OJJ t!"O..L//11L22334455+6788L99::;;r<<+>>?@qAA/BB5CCpDD EEfGIJL5MM+OOLPQXZJ[btccOdd+el5pp>qqZrrgsshtt vvRwwxx;yyzz {{||(}}B~~G&uNSTa)2)[)24[#8@#8@<<<  1`H)%%O''..@@<QQJRR<ii<ss<C&&'      00;; ?@CCEEFFNNmo 9&*9JU9XX9cgyy z~ 99 & & &  ,  & ,&#UV.``4    999 99 9    9 9 &      && &  !&##&%%&''&(()) ++//&22 335578&:;&<< >>@@FFHIJL MMOPQS UWYZ&]]^^#ac&dd3ff oo/pp4yy5{{16.1   1  9 9 7 9 9   9   &9&& & 8    &&!" ..#11#88#994;;"?@!CCOO#XZ&cc pp-qqss)tt$vv(wwzz0~~2  : :+%'+%'  *  %% @@QQ&RRiiss&&.=pprrsstt uu#vvwwxxyyzz {{$||}}~~&) (!" %**    '  @@RRiiss ! !1&*19:/CC&JU1XX1]bWcg<hrFss8txJyyOz~=)11W) ++-KK6 + + RG9  "  + +"((&(-(AE(UVhs(vv(;?EHNB +$+O%&11<I1O<%W1/<<18O<1<=OO1O1I + +  +     + +9+D! ## %% '' (())+**U++,,K--6// 22+335578 :; <<+>>@@ABDFFGGDHI JL+MMOPQS+TTUUW9XXDYZ [[G\\!]] ^^ac dd'ff+oo*rr(uu(vv;wxCyy zzN{{>;(E;(BND> ++(+C>H)1&1<=.O711==1=++X 1  + +++  +  !"+..1155(88;;M<<(AA;BBBCCDDNEE:FF#JLBMM(NN#OOXZ cc+dd(elBmo#pp0qqrrss ttvvwwPxxyyzz{{ ||}},~~3@2 S  SLTTT  A5 %%+''W((V..W@@TQQ RRTiiTssTQ4&&  DFLTcyrlFgrekrlatn $-6?QZclu~ %.7@R[dmv &/8AS\enw: AZE bCAT jCRT KAZ MOL PLK ROM TAT "TRK * '09BT]foxH (1:CIU^gpyJK )2;DLV_hqz!*3<EMW`ir{"+4=FNXajs|O#,5>GPYbkt}aaltaaltaaltaaltaaltaaltaaltaaltaaltc2scc2scc2sc"c2sc(c2sc.c2sc4c2sc:c2sc@c2scFcaseLcaseRcaseXcase^casedcasejcasepcasevcase|dligdligdligdligdligdligdligdligdligdnomdnomdnomdnomdnomdnomdnomdnomdnomfracfracfracfrac fracfrac frac*frac4frac>ligaHligaNligaTligaZliga`ligafligalligarligaxlnum~lnumlnumlnumlnumlnumlnumlnumlnumloclloclloclloclloclloclloclloclloclnumrnumrnumrnumrnumrnumrnumrnumrnumronum onum&onum,onum2onum8onum>onumDonumJonumPordnVordn\ordnbordnhordnnordntordnzordnordnpnumpnumpnumpnumpnumpnumpnumpnumpnumsmcpsmcpsmcpsmcpsmcpsmcpsmcpsmcpsmcpsubssubssubssubs subssubssubssubs"subs(sups.sups4sups:sups@supsFsupsLsupsRsupsXsups^tnumdtnumjtnumptnumvtnum|tnumtnumtnumtnumzerozerozerozerozerozerozerozerozero                             @HPX`hpx&.6 (20Jf$4d   &rbgbgz J~~vpvbS[\HT]8efgbcdG  ,pqrstuvwxy%&'*+?@BFIJLMNOPRUVWXYZ\^_`Ypqrstuvwxyz{|}~ %&'*+,-./01?@BFIJLMNOPRUVWXYZ\^_`hijklmnopqrstuvwxyz{|}JY  2346789:;<=~ Yz{|}~  ,-.0189:;<=hijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<ABCDEFGHIQKLMNOPRSTUVWXZ[\]^_`abdefghijklmnopqrstuvwxyz{|}~^_`abcdefghijklmnopqrstuvwxyz{|}~./0123456789:;<=>@ABCDEFOPQGMJNHKRTUVWXY[\^_cdefhimn  1 !"#$%&'()*+,-./0123456789:;<ABCDEFGHIJKLMNOPQRSTU&VWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~=>?@^_`abcdefghijklmnopqrstuvwxyz{|}~./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno   a$  > !"#$%&'(*+,-./0123456789:;<ABCDEFGHIQKLMNOPRSTUVWXZ[\]^_`adefgjklmnopqrstuvwxyz{} !"#$%&'(*+,-./0123456789:;<ABCDEFGHJKLMNOPQRSTU&VWXYZ[\]^_`acdefgjklmnopqrstuvwxyz{}=>?@^_`abcdefghijklmnopqrstuvwxyz{|}~^_`abcdefghijklmnopqrstuvwxyz{|}~./0123456789:;<=>@ABCDEFOPQGMJNHKRTUVWXY[\^_cdefhimn./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno ;;/$ d .<JXft "(.26:>BFJNRX^dht "(.6<BHN\bhntz $*06<BHNTZ`flrx~ "(.4:@FLRX^bfjnv|)bhi|b~g )Ibhi|~z{|}~pqrstuvwxypqrstuvwxyz{|}~     2,3-4.6071%8&9':*<+=%8&9':*<+=,-.01~hijHebklmnaopqrSTfcstuvwx[]gdyz{|}?@BFIJLMNOPRUVWXYZ\^_`?@BFIJLMNOPRUVWXYZ\^_`hijklmnopqrstuvwxyz{|}  A`fEK^ )bi|=py RR ZZ py FF RR ZZpyJz   ,. 01h}'(  246=~#OQp  %'*1?@#BB%FF&IJ'LP)RR.UZ/\\5^`6h}9OPQRSUpy   %'*+27?@#BB%FF&IJ'LP)RR.UZ/\\5^`6~9OPQRSU    EGLOOR[]]-"/0  L!pz1D FI?L]C__UaeVg[tv   ))bbii||?EEFGLOOR[]]-()*+/1 3//7558;;9:;<!!=/EEJK^^``ff   p;<?A  B%'E*.H04M6:R<=W?@YBB[FF\IJ]LP_RRdUZe\\k^`lho=JXKX^2< CTDB )^  $ ,$  'XZpqrstuvwxyNFI%&+.9;=CDJVXY]chstyz @ INl%*VRL\OJ+QW`^MP_)?K  TUB}(Y "0235KMOikmfz /9~~7 '#/359:C_cu'quw{}      " & 0 : D p y ~ !!"!&!.!T!^!_!!!!""""""""+"H"`"e"#(#+#%%'+ 0:7 &$046:;Dbr$prvx|     & 0 9 D p t z !!"!&!.!S!U!_!!!!""""""""+"H"`"d"#&#+#%%'+@iGF%$+`:b[!cRLF7)X[[A|LN>UO.."%2%V\^`jrvz|~~zz <jlr|dlnvz~v|t~~~xxr'XZNFI%&+.9;=CDJVXY]chstyz @%*&+ P\Q   " 5023IOKMTNURmikl{WB  #!$('*)-,86174/:<>@?ABEGFHQLPUZ\[^a`_fedrojqnpv|}   Sbg     !"    $%#*/" 0)(+,-&'.!123456789:<=>?@ABCFGEHI\]JKLMNOPQRSTUVWXYZ[;Dxuw~ %*#" !]TH[SGEK`RA_OJ R  !!""##$$'%%X&&''()**++Z,,--..//09p::;;<<N==F>>I??@@AABCDDEEFG%HH+II.JJ9KK;LL=MNCOOJPPVQRXSS]TTcUUhVWsXYyZZ[[\\]]^^__``aabcddeefghhiijjkkllmnooppqrssttuuvwxyzz {{||}}~~@%*&+ P\Q   "502IOKMTNURmik{WB            #!$('  *!!"")##$$-%%&&,''((8))**6++,,1--..7//0041122/3344:5566<7899>::;;@<<==?>>??A@@AABBBCCEDDEEGFFGGFHHIIJJHKKLLQMMNNLOOPPPQQRRUSSTTZUUVV\WWXX[YYZZ^[[\\a]]^^`__``_aabbfccddeeeffdgghhriijjokklljmmnnqooppnqqrrpssttvuuvv|wwxx}yyzz {{|| }}~~ )Sbg77%           &&''!            #$%&&''()*+,,--..//034569 ::;CDEFFGGHIJK$LL#MM*NN/OO"PQRR0SSTT)UU(VX+YZ&[[.\\]]^^__!bbcc1rrss2ttuu3456789:<=>?@ABCFGEHI\JKLMNOPQRSTUVWXYZ[$$%%;&&''Dxuw~pqruvwx{!|}+# &%*-    # "                 ! " " & & 0 0Y 9 : D D p p t y z z] { {T | |H } ~  [ S G  (!!!"!"!&!&>!.!.!S!T!U!^!_!_!!!!!!!!!!!!!!!!!!!!!!!!""W""E""K""^""`""R""C""A""_""L"+"+M"H"H?"`"`V"d"dO"e"eJ""D#&#&#'#'#(#(#+#+##%%%%''++++++2${%1 @ *&-+!%!!#"&556654&#"#"&5463#"&5463{73-2 5&# ;"x4@35:- T!)!$  7 ,@)G_XHYI  +7#3#'34`xd4l׭O7"7~"i7"[7~"^7"7X"x 0+7a@GKPX@_XHYHX]I@_\XHYIY@ ## +327#"&5467'!#3#348" #9DDF/4`x(l50F9,0HOb7"7"Z:@7F^^VXHVYI +!!'!#!!!#33(Aa 8;BݭLL"Fd3 5@2 G`XXHXYI%$&!# +!#32'32654&##654&##3XᆪK6hU,4?FVihV,@&0%*./"04 4XWkqR $=3=7"7"dM'@$XXHXYI $ +##332654&&##1M`x>`AFĿvmu'Y <@9^XXH XYI   $ +###533654&&##3#3\\|x>`AFMĿ>F-vmu'FdM"kYd /@,^VXHVYI  +3#!!!u eLLLd"d~"ld"^d"^d~"ad"d"dX"{ 0+dnGKPX@(^VXHVYHX]I@%^\VXHVYIY@ #$ +!#327#"&5467#!!3#!(G48" #9D23u 50F9,)@LLd )@&^VXHYI  +3##!_n eKL79A@>G^X`HXaI#%% +&&#"3275#'3#"&54663_/8%D.5Y8_]M6z 2qERO%':9}` MpS79~"&79"&79"&79"&dD '@$^XHYI  +#3!3#__"__C OC#@@=  ^  ^XHYI +#!##5353!533!!5H__EE_"_E:"CEppppEkkdD"+d@XHYI +33d`Odw".9(".+~".:".6~".S".5". X". 0+9GKPX@XHX]I@ \XIY## +327#"&54673}48" #9D47`50F9,*BO;".w @DXI +'>53Y[.._fE*<0MwI"9dM &@# GXHYI +33!#3d_ulOpAdM";d@XHWYI +%!3 _SS"=d"=d"=d"=( 0+ &@# GXHWYI +!!'737!8&^_&#<:]c<{>.@+ GmXHYI +!&'##33pY Z997b} OdG$@! GXHYI +!#3&&53Y| YIEuS6xOdG"DdG"DdG"Dd,G#@  GDXHYI +%'>7###33&&53G$E>',0Y~ Y IX7> 6-GGqS6xdG"D7},@)X`HXaI& +#"&&5466332#IIWWIIVZdeYSrpTRqoUN7}"J7}~"J7}"J7}~"J7}"J7}"J7}X"J 0+7}3'H@E%$ GE DX`HXaI  ' &*% +#"''7&&5466327&#4&'3.OIW$#O(GOIV%%O*dR**twpTz(voU},= cz7}"R0+7}"J7K&KPX@"^ X`HX aIKPX@6^ X`H VXHV YHXaI@2^ X`HVXHV YHXaIYY@$"&! +!#"&&546632!!3#!$32654&#"#&P~HH~P(% &.1+DQbRT`_USa RqoU L&sHLJy)Lɇd% 0@-`XXHYI   $ +###3654&##3yW_PWWQUSkjqn@SJBd% 4@1``XHYI   $ +###33654&##3yW__VQVWQUS;lmtovBUMC75@2DmX`HXaI&% +$&&#"&&546632$32#"Z*>AV5;oL[7Kg@T?<\4Y=H?<"-$ ZM4R."]"]P;w@-,  GKPX@#e\X`HXaI@$m\X`HXaIY@ %,#$( +$#"&'732654&'732654&&'&&546632&&#"nb0-F60!*/ R7Kg@T?AV5lm ./"04 4XQ=H?<"-$ ZM4R.')"]P"]!@VXHYI +##5!2_ ``QQ)@&^VXHYI +3###535#5!#2}}_{{ F?FQQ"c?;@8Gm\VXHYI$$ +#"'732654##5!#b0I77 */ % <0!044c`QQh"cZ<@XHXaI#" +$#"&5332653<9mLs}_HIJH`i;j3PPOQ,Z<"hZ<~"hZ<"hZ<~"hZ<"hZ<"hZ<X"h 0+Z< Q GKPX@XHXaHX]I@\XHXaIY@ ##' +%327#"&547&&5332653O\|oQ68:TaUr+9ffo[>>q UCE.-WR7B2/4-XGTZ'80C$TTzNR,00<l/0-!"_KPX@ G E@ G EYKPX@XcHXaI@XcHYHXaIY@% +#"'#763654&#"3j2^?S9 Q\9\E@;F5="R}EF: N"chk_R!&94@1GXcHXaI$$% +&&#"3267#"&54663NN$-4!@GFA 3,HYk{8gG<fdd_?:T~F9!"9"]9-?@<, -  G`\XcI$%'$' +#"&'732654&&546632&&#"3267M0-F60!*/ Yd8gG/N$-4!@GFA 3,-/"04 4ZrT~F<fdd_?9"]9 ">`@GEKPX@XcHXYI@XcHYHXaIY@ )%# +!#'#"&54663267&&#"3Q N0^i2^?Q=\<;%=C>:I(-}Q~GA Z''"#fefd9+;@8#G E`XaI+*'%&% +#"&&546632&&''7&'77654'&&#"3L:hD>e:-[A[8 :1H?J6;U@F6?KE.yD:TS}E:pM>nDC?b&D J FJ/Ajc&''V\>"220+>F%@GEKPX@#VXHXcH XYIK&PX@'VXHXcHYH XaI@%^XcHYH XaIYY@%$&%# +##'#"&5466325#'35367&&#"3FOQ N0^i2^?Q= \O<;%=C>:^I(-}Q~GAFJ ?''"#fefd93@0 G^XcHXaI%%$" +!3267#"&546632'4&#"3L<&@#(Tdn{5cCip[>>q WR7B~RHzNR9!"w9"a9"S9"S9"V9 "9!"9"p9$+t@ GK&PX@'^XcHXaHX]I@$^\XcHXaIY@ %%#)" +!3267327#"&547&&546632'4&#"3L<&@#(,1B18" #9DSdp5cCip[>>q WR7#40F9,H*xRHzNR a@ GKPX@XZHV[HYI@`V[HYIY@# +3###5354632&#$ v\^^WN$9!-/%'IG8GHDS C+J8C@8, G7EKPX@8  mm`  XcHXYHX]I@6  mm``  XcHX]IY@999C9B)+4#%5$ +##"'332#"&&5332654&##"&5467&&5466366732654#H4]l]$ ET5R-~yUc*S>9SG82SCE.+5]9>T7(9:569q*[Od +&B*MS#F7 %))%&9+0G35T/ SA56A?9u+"K+"=+7" [ 0++ "_-@* GEXcHYI# +#4&#"#763Q\+))@\\>^VKm8.0, Uf@  GEK&PX@VXHXcHYI@^XcHYIY@# +#4&#"##53573#63Q\+))@\LL\ >^VKm8.0,^F> HFU_"`220+L "._@[HYI +33_\ !"$"3"/"L ".!"L, 'd DKPX@XbH[H YI@`[H YIY@ &%   $ +#"&5463 #"&54633'>53$$$$6$$$$\$E>'*\ $##$$##$)X7C#?7" ^ GKPX@XbH[HY]I@`][IY@   $ +#"&5463327#"&5467$$$$/G48" #9D78 $##$50F9,+C 4", "-, @D[I +'>53$E>'*\)X7C#?7,2"_ )@& GE[HYI +37!#73_\Eng  _"_ &@# G[HYI +33!#73_\BngZ @G EXaI#! +6327#"&57%)36\T@;9{ |"220+ZR"220+W"9Zj" 0+"-@*G  EXaI# +67#"&55'7773&(364S\Fe@@;9 B3[ +B>_Y@  GKPX@X[HYI@[HXcHYIY@""" +#4#"#4#"#3632663N\J'6\J(6\O;]1EK3WJmf-0mf./MY2-.1_M GKPX@X[HYI@[HXcHYIY@ # +#4&#"#3663Q\*)*@\OS2VKm8.0-N*0_!"_"%A_"f_"_,P@ GDKPX@X[HYI@[HXcHYIY@ / +'>54&#"#3663Q$E>'*+))@\OS2VKIX7C#?7S8.0-N*0_"e9 ,@)XcHXaI % +#"&546633254#{8jIo|8jJR}ER}EJ9!"9"n9"`9"c9!"9@"9"}9~&F@C$# GE DXcHXaI  & %*% +#"''7&&5466327&#54'398jI'K*6:8jJ'K*|0{}VR}E{!~UR}Ez~+DUumʁ-9~!"9"_9`$,F@C  G^XcH XaI%%%,%+#%"%"$" +!3267#"'#"&546632632'4&#"354#"3`L<&@#(Td}<>zo|8jJ~;:oip[>>q WR7BmmR}EiizNR_+h@ G DKPX@X[HXaI@[HXcHXaIY@$ +#"'366354#"3^lcX2\OR-`w'@<$|< G(+$.$!_+B@? G E DXcHXaI$ +#"'766354#"3^lcX2\\N,`w'@<$|< %'$.$!9+zKPX@GD@GDYKPX@XcHXaI@[HXcHXaIY@ &%$ +'#"&5466327367&&#"3\M/^i2^?T@O<;%=C>: '+}Q~GG;.''"#fefd_xeKPX@ GE@  GYKPX@X[HYI@[HXcHYIY@ # +&#"#3663`1<\O H0ZHLk;<_x!"NH"*Qx"3%4@1GXcHXaI%$#*% +&&#"#"'732654&&'&&54663$V'(#A$-41@XWyWxO3>T3>55TK1W6=% $LBNRE:5*##K9)B%!"U"19}@,-  GKPX@#e\XcHXaI@$m\XcHXaIY@ %,#$( +$#"&'732654&'732654&&'&&546632&&#"bK0-F60!*/ fF3>T3>55TK1W66V'(#A$-41@XWNP./"04 4X=:5*##K9)B%=% $LB"1"_)3KPX@ G@ GYKPX@XZHXaIKPX@XZHYHXaI@`YHXaIYY@32/.,* +#"'732654&'&&54676654&#"#463_Q," "#&/"1R/;+(*3/.+-5(l\i`&A()0"*D04O+@ 41-8!4(!&$%'do i2@/G EV[HXaI#  +#"&5#53573#3275BCK\\\} s"!%# MI>Gw G)%? iA@>  G E ^V[H XaI +#"&55#535#53573#3#3275BCKQQ\\\} ss i"!%# MIGcGw GcG)%? i"880+ i)D@A%)(& GE`\V[I#$$ +#"&'732654&&5#53573#3272-F60!*/ -2\\\} s"!%#/8Gw G)%? , i"ZMGKPX@[HYaI@[HYHYaIY@ ## +!'#"&533273N8EN\&+M7\R1-TMz6-[xZ!"Z"kZ"]Z"`Z!"Z@"Z"zZ![@!GKPX@[HYaHX]I@\[HYaIY@ #(## +327#"&5467'#"&53327348" #9D7#33og 4>%b__k H "5-4 +!"V +"2 +"5 +!"j )@& GV[HVYI +7!!5#5! dMME|NF!" ;"  " |9 "_ "9 " "a " GFd@ GKPX@XZHV[HYI@`V[HYIY@$ +&#"!####535463HE# 4;5(&\\TTZ\@&(F8GEFTF$KPX@#$G@#$GYKPX@"XZHV[HXaIKPX@&XZHV[HYHXaI@$`V[HYHXaIYY@ &#% +#"&5&&#"3###53546327327!)364 1' v\TTYU!8 \ ;9+ $(IG8GHER @73"(d 3"a743"h3"{a3"^4 ,@)G_HI +7#3#'3*^ra*mW4̉a?"g3"G6"9"<?"g"V46@3G_\HI##+327#"&5467'##3#348" #9DAC&*^rW50F9,/G|4b"m$" 84;@8G^^VHVI +!!'##!!3#33 6` )+|p4GG?"%d5 5@2 G`XHXI%$%!#+##32'32654&##654&##3q@.T3?CD?IG:\NpWK51? ,).#X'64.7>4@1GXHXI%$$+&#"3267#"&&54663hL&069*ippl9%D^[D7?"(7/"(s7>-?@< ,!-  G`\XI$$'$(+$#"&'732654&&546632&#"3267L10-F60!*/ buCrF6L&06A@>G^XHXI"$%+&&#"3275#'3#"&54663vV)5 :'G`OM@-e XsvGxF> 6lntiG5[E73"A76"Ay7>"A7*"Ad 4 '@$^HI +!##3353\\^4#-4@@=  ^  ^HI+####53533533!35^\66\^+Z;SSSS;XXd 6"Ftd4@HI+33d]4d4I ?"I*3"I96"I5"IR*"I4 ?"Id4"IU% "I4@G\I##+327#"&5473z48" #9Dn]50F9,U20:$"I 4 @DI+'>53QQ'(\XB#0'46"Ud4 &@# GHI+33!#3d\Xog4.d4"Wd4Wd4@HWI+%!3 \NN4?"Zd>"Z 0+d4"ZQ*"Z34 &@# GHWI+!!5'73730#S\#84&X8m>}4.@+GmHI+!'&5##33$ |X X1ywtz0[Z+Oy4gd 4$@! GHI+!#3&&53 Ux U qL4%x2d ?"ad 4ad /"a~d 4"ad, 4#@  GDHI+!'>5##3&&53 $G<+/- Ux U8K6:$6, qL4%x2d $"a }74>,@)XHXI&+#"&&546633254#s??sLLs@@sLKSTJ>D\\ED]ZFIkprj74?"h743"h746"hu74"hx74?"h74^"h74"h74&H@E$# GE DXHXI&%*%+#"''7&&5466327&#54&'3D?sL J#=D@sL"J$A! `\Edi!`[Ehl-ۑ1IN^e74?"p74$"h t7A%KPX@"^ XHX IKPX@6^ XH VHV HXI@2^ XHVHV HXIYY@#!&! +!#"&&546632!#3#!$32654&#"m!!Go>?nG$!r = '"QDFONGEP D\[G G?mG7]!Gkkrrkmqd4 0@-`XHI   $+###3654##3w{iJ\CGFE4YX^Z41@ld4 4@1``HI   $+###33654##3w{iJ\\GCGFEYX^Zn4]1@l7P>5@2DmXHXI&$+$&&#"&&546632$3254#"L<4_NKr?@sLLs?FBTJKS!3K.&C]ZFD\cv!jkpd4 8@5 G^XHI !+7#32#'6654&##3\rt>@m7?AFFO4RQ:HD.51-d?"wd/"wSd4"w>'1@.GXHXI'&$+%+&&#"#"&'732654&&'&&546631Y&3A&.:75VZtdAi&3AZ5E53]U2X8>""7&$LIL]'$9;0+"L?-E&?"{_/"{1>:@@=,-  G`\XI%,%$(+$#"&'732654&'732654&&'&&546632&&#"cW0-F60!*/ jF3AZ5E53]U2X8=Y&3A&.:75VZY\./"04 4Y A9;0+"L?-E&""7&$LI6"{1>"{>"{{5!@VHI+##5!\ LL5)@&^VHI+3###535#5!#xx\tt [@@LL0"0+5;@8Gm\VHI$$+#"'732654##5!#C0I77 */ " <0!044cLL5"Z5@HXI"!+$#"&533253pefn\xy\`kjX~~~xZ@"0+Z4"y0+Z7"k0+Z"n0+Z@"0+Z_"0+Z"0+Z5(@% Gm]I"#'+%327#"&5467&&533253D@G48" #9D20Zb\xy\Ca50F9,&>hR~~~xZc"0+Z%" j0+5!@GHI+333ýb]5$5 '@$ GHI +!#333gjtu[Yoao_Uv95?"6""?"4 &@# GHI +!'#373pcgrtc-4@GHI+!#533"]ea]?"`6"2"5?"`4 )@& GVHVI+7!!5!5!! %lMMHKI?"\/".*"A%)Q@NG`XXHX[HVYI)('&%$#$+#" +4&#"'632&&'#"&5463375#"3!5!9(+1@NH#+ A(?Ic[:!!0j"x%' >=C7@D5PH M8 =@:`XXHVYI    $ +#"&54633254&#!5Weg[\fh[dcc11ob_rpa_rEHDMM7d% 6@3`V2HX3I   $+##!!3654&##3|w [PRRO\_jhrjN>PJ@d3d@V2H3I+#!__Rd"d0EFK PX@cV2H3I@oV2H3IY+!#!53_2\Rj71@.NV2HV3I +#'!#53>77!3!7KsK/^8%#+P~Td /@,^V2HV3I +3#!!!u eLLLd"nd~"a01@. G^ 2H3I +!#####333330kR[SiɶfR[RdCCnC   &?@<$#G`X9HX:I&%$!$$++#"&'732654&##732654&#"'63YlH?DZ?pGAr)8@_GNMKB 6_5/.6CF==AN=5/;@9UdG $@! G2H3I +!47#33 z_ wPunJOdG"dG"dC '@$ G^2H3I+!###333Cn^___dC dC"/@DV2H3I+!##'>7!/_!&@>&% -a|{9J,Xa>CdD+7},@)X9HX:I&+#"&&5466332#IIWWIIVZdeYSrpTRqoUNd?!@V2H3I+!!#!_`Od%V7c! @ GDp2I+$'667#33>7!3654&##3ތ|!&@>&% -mNSRRROUkjtka|{9J,Xa?RLAd8@5 `2H Y3I$ +##!#3!33654##3u___]GO^_hcmhVU,4?FOhhR,@&0 ,SqqR $=3nwN}{=A@> G^X9HX:I"%$+#"&'7327!5!&&#"'663[@]%0"?. WI-@'1+`=("=Nxm;#$d.6~".w97@4 G`V2H3I#+#54&#"##5!#63?k_@C1H_ @lsfDE%%`QQEdLnKPX@!^X2H X:I@)^2HX9H3H X:IY@& +#"&'##33663#"3EEU|X__YuV^`TRrpSےw:@7GD`V2H3I.+'>554&#"##5!#63?kY[..@C1H_ @lsfffE*<0DE%%`QQE8@5`V2HX3I $ +###5!#3654&##3 | [PRRO\_jhrj`QQ>PJ@7}7 @ G2H3I+#3667$ff^<2-5  '@$^V2H3I+3###53!!˜_bbFWFRjK<@9 G  ^ Z 2H3I +#'#####333333KK,R[SiɶfR[RdFCCnC   6H@E+*3  Gm`]X9I#$!$*$&+$#"'732654&'&&'732654&##732654&#"'632s]KE;8*%&6\#8@_GNMKB 6U,4?FVihV,@&0%)1F3=6 ; WhqR $=3=j $@!ZV2H3I+%3#'##5!#2PKU N`QQ!z!/@, G_2H3I+##5#5333x`xbic2FFUj,)@& GZ2H3I+#'##333,K'fϽlfA1oB(jP2@/G`Z2H3I"#+#'##"&5332733PKU,O4\n_[<_P!p_ :M(d@GFK&PX@`2HV4H3I@`^2H3IY@ !+!##5#"&5353673_3; \n_t;>-_hap_ } +Md;/@, G`2H3I#+#54&#"#363k_@C1H__@lsfDE%%Edj2@/ G`Z2H3I"#+#'#54&#"#36323KU@C1H__@lakPDE%%Esfd.0"(j2@/G`Z2H3I"#+!##535#"&533273UKP,O4\n_[<_!p_ :M7"i7~"^d"l-R=@:G^X9HX:I"%+#"&547!&&#"'637!3G|Q^V]V1a {P|qA:U-R~"z0~" ~"FdGX" 0+dG~"7}~"7}=@:^X9HX:I& +#"&&54663!&&#67!3IIWWIIVSedUWefUSrpTRqoUNtyzsyy7}~"~"-!X"g 0+!~"M!"(~"Sdj "@ZV2H3I+73#'#!!PKUNRd~"!t-9 '6@3#GE`X:I'&!$+#"&54667667663654&#"3k~jj#WO;G%'#K42:#X8H;8.PG?p}s_ E%+QF.4QSg[P12@]e_"D@AG`X;HX3I"! ("$+##632&32654&#654&##3Bye]Pas1:(^27:;@M@;dS@;OMHB+:$+($t!43%_@V4H3I+!##_I \L=_!"d_$@!FoV4H3I+##353 \\L=j1@.NV4HV3I +#'!#53>77!33KK%J7!)fb;|o]d6|93@0 G^X;HX:I%%$"+!3267#"&546632'4&#"3L<&@#(Tdn{5cCip[>>q WR7B~RHzNR9!"9"V1@. G^ 4H3I +!#'##5##'3353373e}FXE~d`nFXGo_'E@B$#G`X;HX:I'&$!#$++#"'73254&##732654&#"'663W537BDbwT0#G.IAF67D:0(>-(\:!?,.8 <8RUB9^.%H(*'#7_#@ G4H3I+!5467#33o[q77!\ 9:"Sİkj9I &Na<c.@+Gm4H3I+!'&&5##33 xWpY/wgqy0'^5w7y_ '@$^4H3I +7#3353#5\\\\9 ,@)X;HX:I %+#"&546633254#{8jIo|8jJR}ER}EJ_!@V4H3I+#!#\\<_+9!@V4H3I+##5!\ <KK +@ GD4H3I+'>7#33og 4>%b__k H "5-4 +"@>+&1X@U.- GE DX;H  X:I'''1'0,*&%!$&$ +#"'#"&546326367&#"3 654#"3S`UK.XD'P]Q]Q/X.M7-@.02-[4c?)2!~C  #~: <"# !7)@&Ga4H3I##+!#5#"&553326753\U-KL\)+#M\QK2- _j: #@ O4HW3I+#'!3333:K\\P<;_ %@"4HW3I +333333_ZXZ;;_j '@$O4HW3I+#'!333333 KZXZP;;;_j )@&p4HW3I +!#'#333RK\\<# +@(G^X4H3I$!%+!#5##7&54633#"33\sog~]pe\U995;W,cNSG+/2,_ 0@-`4HY3I   $+##33654&##3wjwX\FA=9FEOe\UY[2:74 6@3`V4HX3I   $+###533654&##3jwXFA=9FEOe\UY[F2:74_ 6@3`4HY3I $ +##33#3654&##3mjwX\<\\=9F;Ee\UY[92:74%@@=G D`V4HX3I$+###'>77!3654&##3jwX 9:"OG^X;HX:I$%$+$67#"&546632&&#"3#3C7+GYn}9iF_D,5=K ?<:T~D99SNFA@>G^X;HX:I"$$+#"'73267#53&&#"'6636uvpbE,7&:G><#<*#S5:;SYFSN8L *@'`4H3I   $+#"&54633$$$$-\ $##$/", #@ D`4I $+#"&5463'>53$$$$.$E>'*\ $##$X7C#?7_nKPX@!^X4H X:I@)^4HX;H3H X:IY@& +#"&'##33663654&#"3;f75gG`t^\\_ u\CD|SN}Img#fd`h`i,"h@ GEDK&PX@V2HX;H3I@^X;H3IY@"!/+'>54&#"##53573#63Q$E>'*+))@\LL\>^VKIX7C#?7S8.0,^F> HFUj EK1PX@!`V4H X3I@^` X3IY@$ +###53573#3654&##3xu}sTT\ z7FEAA@>eWY[ZFm xFn/>739R  @ G4H3I+#3667kbiZ;/z?S23  '@$^V4H3I+3##5#535!#rr\RRI /FFLj<@9 G  ^ Z 4H3I +#'#'##5##'33533733K%}FXE~d`nFXGo_oB8Q@N+*5  G`\X;HX:I%$!#$$&+$#"'732654&'&'73254&##732654&#"'6632_NME;8*$$jM0#G.IAF67D:0(>-(\:2W537BDUS 0H3=6 :=9^.%H(*'#7!?,.8 <8_j0@-G^Z4H3I+#'#'##33733K$C\\Ee@_;@8G^^4H 3I +!'##5##3353373w/$\\$/ha|{{ss23@0 G^V4H3I+!'###53373ŒC\EeF_jB*@'^Z4H3I+#'#5##33533BKR\\\P;_j? $@!ZV4H3I+#'###!3?KR\P<;9*:@7)* Gm]X;I$%+$%+#"'732654&'&&546632&&#"3267EKE;8*''V`8gG/N$-4!@GFA 3, 0G3=6  ;pT~F<fdd_?j $@!ZV4H3I+%3#'##5!#PKR JKK +@D4I+533#Zb_ V +0@- GD4HW3I+%#5#5333hZhSb_HF FV9j)@& GZ4H3I+#'#'#'3733K/hlnohJ7j2@/GaZ4H3I##+#'#5#"&5533267533KRU-KL\)+#M\PQK2- ;75@2Ga^4H3I!+!#5#5"&5535366753\!47KL\&(7-\SIQK1,_+@( GE`3I#+#4&#"#7663Q\*)*@\\O0VK18.0- &,_j<.@+ G E`Z3I%#+#'#4&#"#766323AE<T}Cy!XQ=?"NXKS9"KZ" "  _" _" k9"c9 =@:^X;HX:I % +#"&54663!&#7!3{8jIo|8jJ|  z} ~R}ER}EJm9"Rb"* +"O +"5 +@"o7"?_j "@ZV4H3I+73#'#!#PKRI JL_"%-4d4 6@3`VHXI   $+##!#3654&##3yy}kL M?DCBKMdXV]Y4J1=82d5'd4@VHI+#!\O 4Md?"a{dEFK PX@cVHI@oVHIY+##353 \W4M4}j41@.NVHVI +#'!#53>77!33KK068  @s|\{pDd4 /@,^VHVI +3#3!!K GG4Gd?"evd"2K41@. G^ HI +!#####3353373gHVHgcHVIa+  A(B@?%$G`XHXI('$!$$++#"'732654&##732654&#"'663R,v=M9c<}H6A-6AA>: .2:/-'@!3,^;A&A'jH?3N+M46-/3J.(#.6%"d 4$@! GHI+!467#33t\q;Z:-4CW7d #"jd ?"jd*4 '@$ G^HI+!###3373*k9\\;c4d*?"m4#@ GDVHI+!##'>7!\ 99! Zlm>I+Nd >}4`d 4F74>hd4!@VHI+!##!\4d4t7>(54 @ GDpI+$'667#33"7N< <;!`]cC#A *0di#"w;(SKPX@+cda T XLKPX@*cpa T XL@)opa T XLYY@ +$#5&&546753654&'ZZ^_a\r\^_}@@~uz};;~u]YsY]Y][Z4(4)@&G`HI##+!#5#"&5533273\%C,Q`\66M0\_Q73+djZ4 #@ OHWI+#'!3333ZKd\\P4d4 %@"HWI +333333dZVZ4dj/4'@$OHWI+#'!333333/KZVZP4dj 4 MK PX@dHWI@pHWIY@ +!#'#333dK\\44 +@(G^XHI$!&+!#5##7&&54633#"33\qph88uq\LIB?4dP7S[E5524d4 0@-`HYI   $+##33654&##3yy}k\M?DCBKMjYX_Z42?:3 4 6@3`VHXI   $+###533654&##3y}kM?DCBKMjYX_ZH2?:3d4 6@3`HYI $ +##33#3654&##3oz}k\B\\DDD@EjYX_Z442?:34 @@=GD`VHXI $+###'>7!3654&##3pz}k 99! FACDEC@EjYX_Zlm>I+Nd 2?94d048@5 `H YI$ +####3353354##3uzf\\\K}}KM[VSZX4ie>{7>;@8 G^XHXI"$&!+$#"&&546632&#"3#3267Y8Js@CrF6L&06=AXWD%9 -%D^[D8)UYH`_8>A@>G^XHXI"$$+#"'7327#53&&#"'6635{|oeE-6(F?&7!.&T5>>8H^P7d4I5"I4UI57@4 G`VHI"+#54#"##5!#63]\m);\8Zv`WmHH5d>KPX@!^XH XIKPX@%^XHH XI@)^HXHH XIYY@$ +#"&'##3366354#"3qrkJ\\L~fFNOE>4tlrpiN5:@7GD`VHI-+'>554#"##5!#63]QQ'(m);\ 8Zv`WnXXB#0'kmHH5;58@5`VHXI $ +###5!#3654&##3x|k L@DCCJNdXV]YHH1=8274>= @ GHI+#3667 gbs [1)D4$|$. 4 '@$^VHI+3###535!#\WWO PHHMj 4<@9 G  ^ Z HI +#'#####33533733 K$HVHgcHVIaE+  A;@ /.8  GKPX@+e`\XHXI@,m`\XHXIY@ %$!$$$( +$#"&'732654&'732654&##732654&#"'6632bN0-F60!*/ lC6A-6AA>: .2:/-'@!3,^;7R,v=M][ 0/"04 4YF46-/3J.(#.6%"&A'jH?dj=40@-G^ZHI+#'###33733=K$9\\;cԬL4d4;@8G^^H I +!##5##33533731"ZZ"1`4鉉S47@4 G^VHI+!###533739\;cHdj]4*@'^ZHI+#'###33533]KT\\^P4djV4 $@!ZVHI+#'###!3VKN\L47>*:@7)*  Gm]XI$$+$&+$#"'732654&'&&546632&#"3267G-ME;8*''`rCrF6L&06@@=G^XHXI"$+#"&547!&&#"'6367!3ntz}NGNJ.SxCLLC>^W46G[cb\- "Xd "j74>=@:^XHXI& +#"&&54663!&&#7!3s??sLLs@@sLES>RFUF>D\\ED]ZFIY]]YIe^74"t%"%%0+"wJ"w0^"ow("{Gdj4 "@ZVHI+73#'#!#NKPO J4Md"57 ,@)G_DHEI +7#3#'34`xd4l׭Od3dA+@(GDHWEI+33'x{ONd /@,^VDHVEI +3#!!!u eLLLdD '@$^DHEI +#3!3#__"__C OC7}=@:^XLHXMI& +#"&&5466332#53IIWWIIVZdeYxSrpTRqoUNJJd@DHEI+33d`OdM;7!@GDHEI+!#3Ӷ`xbO>CdGD- =@:^VDHVEI   +5!5!5!- #[VVUUXX7},@)XLHXMI&+#"&&5466332#IIWWIIVZdeYSrpTRqoUNd?d%V( 5@2G FVDHVEI +!!55!NNNNc!@GDHEI+!#33C`icUX#5@2` `DHEI +$#5&&546753654&'\\~sqsqpsqؐDD|FFxdhdaee^gfy#(@%GmDHEI+#5$5336653_^RZ[YT^mu PN\NO7}!/@, FXLHVEI! &+3#56654&#"#53&&54663G:JnGAc[ZdCDhC:IVQml})PPv{~PP$mkT7"$"$D"+$".$}"J$m!"z$O}"$6~".!~"zU7"{7"7~"i7X"x 0+d"d"dD"dD"""+~" X" 0+7}"7}"!"v!"!~"`!X"o 0+7}"7}":%"e@ G DKPX@XGHXMI@GHXOHXMIY@"!++73&&''#"&54633267&&#FPT7 #5 1s\dg_,844+H?3KXL0)8~IjeeaXvqV_*-)B@?&G D`XFHXMI)($!+&$+#"'4632654&##732654&#"3-=f;RB\m_8]7RCOYT4 15B?5qB,~@b53 bo,Q6IT JDNQF@A::Q( -+&547&&'7|W] I;W1WڕB=%<=42?7!9 !.1@.( GXFHXMI"""."-%+%+#"&&547&&546632&&#"654&&'3]8iHEi:5+)P77T'/7"/-23ED=67BCsdEuE48bTf."5j+0<% G_+-@* GDGHXMI"(+$&&'5#"&'33273V G+4 [\OP1\PP ' *8<.j Y`l @ EEI+#&&'7xP&[q9P0W6!2)35@2,GD\XFI32!$%+&&#"33#"'6654&&'.5467&&54663HS$.5!5280F B;G::<@"KS'02.1@L,\C9@.T884-07LN<,5'%2%7O$@+!2SAQ[ G8/K*9 ,@)XOHXMI %+#"&546633254#{8jIo|8jJR}ER}EJ5,@)GDXGHEI%+%&&5##'663!# =0\ +&O&"J A@B<H KZ+;@8G DXOHXMI %+#"'463654#"3m0]B[/\mj8C}A8<%L~JB 䃉$gbij{##9)"%@"GDXOI"!%+&&#"'6654&&'&&5463NN$-4!@H780:#KS'02)+UWzl<b]6='"3%7O$@+! pd~90,@)GXGHXMI4&+#"&5463254&'"3)48jIo|i)MW$hGR}E|JyHf)VJ!@ G DXGI%(+%&&5#'663!# =0E'#+&a&"J A@BH KZ@GHXMI#$+#"&53326654'3Ci)]Zx9[Tl67&ZIA+$K@ $GDKPX@XGHMI@GHXOHMIY()+$5&&5467346326654&&#"Xy \!MS[OK ' (, wKJEJ`Xah,VHMW%7N--+'&&'7n[Od!\22*-XTg \ʉR~}<=?:{SBT?dY2E wEVZ,"!H*"4""Z,"!Z"`Z""V9,"!A,"!E:%,"!9,"!K+,"!:%!":%!"u:%"#P:%"_:%"n9!"v9!"bK+!"K+!"K+"#a !"!"/"#""*%7@4EDXFHGI$#(+'7#"&54632#"&5463&&53)!!!!!!!!:=0\VMrO!!!!!!!!q" E A@~*%7@4EDXFHGI$#(+'7#"&54632#"&5463&&53+)!!!!!!!!:=0\1rMt!!!!!!!!q" E A@~/""#0+9!"9!"Z!"Z!"Z"#\Z"kZ"zZ1C@@EX FHGHXMI10+)&%" ( +'7#"&54632#"&5463#"&53326654'3})!!!!!!!!lCi)]VMrO!!!!!!!!Zx9[Tl67&ZIZ1C@@EX FHGHXMI10+)&%" ( +'7#"&54632#"&5463#"&53326654'3)!!!!!!!!lCi)]1rMt!!!!!!!!Zx9[Tl67&ZIZ""`#\0+A!"A!"A"#4 ,@)G_HI +7#3#'3*^ra*mW4̉ad5'd4a6+@(GHWI+33'rv6I]d4 /@,^VHVI +3#3!!K GG4G4d 4 '@$^HI +!##3353\\^474>=@:^XHXI& +#"&&546633254#53s??sLLs@@sLLSTKe>D\\ED]ZFIkprjAAd4@HI+33d]4d4W4!@GHI+!#3^r4>}4`d 4a-4 =@:^VHVI   +5!5!5!-m rPPNNRR74>,@)XHXI&+#"&&546633254#s??sLLs@@sLKSTJ>D\\ED]ZFIkprjd4sd4t(4@(4 6@3G FVHVI +!!57'5! s4IHII54@GHI+!#533"]ea]#45@2a `HI +$#5&&546753654&'ZZ_^_^p^_^u99vfht99vcNRCPLRNJQ4#I4%@"GHWI+#5&553366553Iwn]ZCJWHD\`Xb =>R==74>#0@- GXHVI#"&&+3#56654&#"#535&&54663s>3>_;5RKKS7:Y84@tK>C~VUhJHj`hfghdeHJjUTEd4I5"I5"I4"5"574>h74>F4d42d 4F?".g+"#8%%0+3".G".Vd?"2vd?"2vd ?"4d ?"4d +"F#s%%0+ ?"6 ?"6:+"I#%%0+*3"6 "65<@9E`$H%I( +'7#"&54632#"&54633)!!!!!!!!]9VMrO!!!!!!!!45<@9E`$H%I( +'7#"&54632#"&546336)!!!!!!!!]91rMt!!!!!!!!4:"I"%#%0+0+74?"<74?"<"Bd ۰0+?"B`+"B#1%%0+3"B@"BO$B@?$!GE`$H%I#" ( +'7#"&54632#"&5463#533R)!!!!!!!!<]ea9VMrO!!!!!!!!]$B@?$!GE`$H%I#" ( +'7#"&54632#"&5463#533)!!!!!!!!<]ea91rMt!!!!!!!!]"B"5#10+74?"F74?"F74+"F#q%%0+7 LK1PX@XXHXaI@`XaIY@   $ +#"&546332654&#qqooqqoA??A@@@@I#C9GKPX@ XHYI@ VYIY@  +3'73(Q;_AcQ@  GK1PX@XXHVYI@`VYIY@ ' +!!5>54&#"'663 [27rt- up0<2)>!>)d>0S4=ptMI`74;"'032(h@&%GK1PX@`XXHXaI@``XaIY@('$!$$, +#"&'732654&##732654&#"'63Y/G;CT8hD=f&88/7 7O(2@/GE^VYI +%#5!53733YMPWB gIt@  GKPX@&m`VXHXaI@$m^`XaIY@$%%" +632#"&'732654&#"#!38Vh:iE=`)8D+@IB8,Hj UqcBg9+*6!PIIB QH7#o@ GK1PX@`XXHXaI@``XaIY@#"#%& +#"&546632&#"63654#"3gT29a;ul=rNL>$/8HT>c>l,J?B0`EGm;m[)=tXXK1+nh9@ GDKPX@ VXI@RVJY +'!5!T @KE-'5V@ /! GK1PX@XXHXaI@`XaIY@(((5(4'&,$ +#"&&5467&&546632&6654&#654&&''3;jCDh9CA539]54]:8:=;A-(;6=I>820H>.{7W10V7>TM46N(&M62H6202:*/8@5$1% I67=- ]@  GDK1PX@\XXI@`TXLY@ , +'667#"&&5466376&#"3mnJN14T1:a;E6;@;@<3yc&E&l$,5aADd5SoaNHFG(6>*@'`XaI& +#"&&5466332654&#{xCCxLLxCCxLHbbHHbbH>E[[FF[[EIkpqllqpk#C4!@GVYI +3'73(Q_A>.@+ G`VYI' +!!5>54&#"'663_3%y}% o(?2*F#;*eA>.Q24QlOMIbmG+09$+055 >)B@?&%G``TXL)($!$$, +#"&'732654&##732654&#"'663Z/I;GR9iF=f&85'A"0+_8>.L-:P TM:]5--4CG?A;G<5.6 7('>7@4GER^VJ +%#5!53733WMNT(@ QG4F@C Gm^`TXL$%%" +632#"&'732654&#"#!1:Vh:iE=`)8D+@IB8/0Hj qcBg9+*6!PIIBQH7#o@ GK1PX@`XXHXaI@``XaIY@#"#%& +#"&546632&#"63654#"3kV3:b$26LW?f@o-K@E0`EGm;n[)=vZXK2+ng4"@GDRVJ +'!5!TwDKE-'5V@ /! GK1PX@XXHXaI@`XaIY@(((5(4'&,$ +#"&&5467&&546632&6654&#654&&''3;jCDh9CA539]54]:8:=;A-(;6=I>820H>.{7W10V7>TM46N(&M62H6202:*/8@5$1% I67=-> <@9 GD`TXL , +'667#"&&5466376&#"3mnJO04T1:a;E6;@;@<3>xg%E$b"+4b@Cc5RmaNFEG8 ,@)X`HXaI   $ +#"&546332654&#pppppppA??A@@@@IP #@ GXHWYI +!!53'733m(QJ_A-0@- GX`HVYI' +!!5>54&#"'663C_3:vA a3@80A!>)fF2X7?vkMIf88A"'032)?@<'&G`X`HXaI)($!#%- +#"&'732654##732654&#"'63;a5M<*I,=nG?r&<Q+FO: )6JH7+C#2Us/O/>U )L2;`7/.2!#I?G<95<!7Q12@/GE^VYI +%#5!53733YMPWB QI2C@@ Gm`VXHXaI$#%" +632#"'732654&#"#!6?Vg:lGvU8=UCKA8. Hs isfDi:U6@QMLD [H?"E@BG`X`HXaI"!#$& +#"46632&#"63654#"3rW4:c<>tPL>$/8JW?b#?r,J@E1bGJn<Pr])={Y{YO2+tkL@GDVXI +'!5!S TKE/&44@1.  GX`HXaI'''4'3&%+$ +#"&&547&&5466326654&#654&&''3JA;30I>89Y20X9z:O6:Q)'O:3K9745;-5;C5(4'K8:?3 5@2 GD\X`I , +'667#"&&5466376&#"3ypKN25V2;c*@'`XaI& +#"&&5466332654&#cq>>qKKq>>qKEXYDDYXE>E\\FF\\EIjqqllqqjL4 #@ GoWYI +!!53'733n(QJ_A,>.@+ G`VYI' +!!5>54&#"'663Aa4&~/ e)A5-H#;*hC>.P34QlOMIbmF,09$+055(>(B@?%$G``TXL('$!#$, +#"'732654##732654&#"'663A\/I9ER9kHK8G,DK6 &9H?8*B"0+`;>.L-9Q UL:]5Z4# H>|G<6.5 7('3>7@4GER^VJ +%#5!53733WMNa(@ QG34F@C Gm^`TXL$%%" +632#"&'732654&#"#!1?Xk;lF@b)8E.BLE:,Ht qcBg9+*6!PIIB QH@$o@!GK1PX@`XXHXaI@``XaIY@$##%& +#"&546632&#"663654#"3wV4:c=yn>uQP>$28MX!R4 Aq/KAF0`EGm;n[)=v/+XK1,ng34"@GDRVJ +'!5!TwDKE3'4V@ .! GK1PX@XXHXaI@`XaIY@(((4(3'&,$ +#"&&5467&&546632&6654&#654&''3;kDEi9CA53:]65^:8:==A.(<7?IAS20H@.{7W10V7>TM46N(&M62H6213:*/8@55; H67=7> <@9 GD`TXL , +'667#"&&5466376&#"3~qKQ26V2;dB=C?5>xf%E%e"+4b@Cc5RmaNFEG7 ]@ GK1PX@XXHXaI@`XaIY@    $ +#"&5463&#654'3qqooqqoA?-@@.I~:߁}:O(6>8@5G`XaI& +#"&&54663&#654'3{xCCxLLxCCxLHb0!(Hb/!'>E[[FF[[EIkpx6} Hlqv5 8 :@7GX`HXaI    $ +#"&5463&#654'3pppppppA?.@@.I=Ʉ<<>8@5G`XaI& +#"&&54663&#654'3cq>>qKKq>>qKEX#%DY*/>E\\FF\\EIjqj6o Hlqs7Y+-+'k<;NA"Al"#Ap"#7p"#Ay"#4y"#Ap"#7p"#4p"#*p"#As"#4s"#Az"#4z"#4z"#C>"#T.b *@'`XaI   $ +#"&546332654&#NNLLNNL&##&&$$&oiippiio;HUVHHVVGA!@GVYI +3'73b"ER95S_7X.@+ G`VYI' +3!5>54&#"'63K!JHTH$&17UD4"?PA>:QM6"&D4\%C@@#" G``XaI%$$!$#* +#"'732654&##732654&#"'63I.(,8UHW4-&4%+)'"  ($*(:L<-&2 4.7I<*)&!$8!,4*e2@/GE^VYI +%#5#537330LBqjD5```6ii<4\D@A  Gm^`XaI##$" +632#"'732654#"#53!"8EXHP8.%3&,H9 ghH>AP:+(+)N:1_F@C G``XaI#$$ +#"&54632&#"63654#"3ES@PK^R5)!+3)< #?/""'H@BUk_i~1H@/1*Q-C<CM#@ GDRVJ +'#5!G T=7*f!-2@/( G`XaI"""-",! )# +$#"&5467&54632&6654&#654&''3fXGGV+)BR;;QHb#!$ !$*$/6*$I4ED4%4"@1<82;# !#!9"2^?@< GD`TXL, +'667#"&546376&#"3N5kZVZ14FV?(!&"&#WJUlA8G=J>@L-?6+')'.b 0+A!@GVXI +'73b"ER95S_7X-@* GZX`I' +3!5>54&#"'63K!JHTH$&17UD4"?PA>:QM6"&D4\%D@A#" G\X`HX[I%$$!$#* +#"'732654&##732654&#"'63I.(,8UHW4-&4%+)'"  ($*(:L<-&2 4.7I<*)&!$8!,4*e2@/GE^V[I +#5#537330LBqjD5p``6ii<4\E@B  Gm\VXHXcI##$" +632#"'732654#"#53!"8EXHP8.%3&,H9 whH>AP:+(+)N:1_ 0+CM@GDVXI +'#5!G T=7*f 0+2^ 0+.-b6 60+A66 60+76X6 60+4-\6 60+*6e6 60+4-\6 60+1-_6 60+C.M6 60+*-f6 60+2&^6 60+.9bB B0+ABB B0+7BXB B0+49\B B0+*BeB B0+49\B B0+19_B B0+C:MB B0+*9fB B0+22^B B0+g+@  DKPXZIfY +''7'7'37rHONHgZ54u!R=?S!i'-+7PNh}2| @TXL $ +#"&5463((((|())(2 @TXL $ +#"&5463@@00@@0A00@A00@2"p p0+&Z %@"GTVJ  +6#7&&5463(CB( ((( (2##3,@)VXHXaI  +73#"&5463O f ((((5g())(36 OK.PX@`V]I@`RVJY@   $ +#"&54633((((2 Q )(()G?KPX@(^  XH V [HYIK1PX@(   o^ V [HYI@&   o  _^YIYY@ +%3##7##7#537#53733733##37CMNN@JAJNNCLEEFF2 @XaI $ +6#"&5463((((())((<@9GmX`HXaI('#!* +#546676654&#"'63#"&5463*W,& **[(!&$6/P;?T|((((+H)'7"1)-2+<$( )-H1c())() (;@8&%Gm`Y]I ( '$" $ +&54632#&&5466766553327#((((]W,( ))[(!&%6/P;?T|d())(+H)(7"/').*:#) )-H1c<S#<@VXI +#E&Z"p p0+i'-+'ONh|r@RVJ +!5?OO3  0+  0+$ I@F^  XH V [HYI +%3##7##7#537#53733733##37CLNNAJBLNNAKEEFF$ s41 10+s41 10+xD8@5G``TXL +3"&554�,$'(#,3dR''Rd%3- *3%GEP*"L$*PEG-x)D8@5G``TXL +3"#52655467&&554R''Rd3,#('$,3DEP*$L"*PEG%3* -3%GA0(@%^RVJ +3#3xLM20(@%^RVJ +53#532xxtL M\(oM-+.54667=##=4:BG11GB:ygf{L(^yooy^((oM-+'>54&&'7G11GB:4=##=4:yooy^(L{fgyM(s 0+s 0+n: 0+-n): 0+A& 0+2& 0+(eC 0+(eC 0+s-+.54667++.1'//'1~\\~F!9TnFFnT9!s-+'6654&'7//'1.++.1TnFFnT9!F~\\~F!s 0+s 0+ ` `@RVJ +!5*`NN `@RVJ +!58`NN&t@RVJ +!5tNN<W`@RVJ +!5W`NN<W`@RVJ +!5W`NN ?--0+ ?--0+<?W--0+<?W--0+&t&t&t7'"7'"7'-+'5777&?&7'-+%'7'777&&(djk"(j LGKPX@VZI@RXLY@  +&546773#2&546773#N& C<('& C<('% %% %(j NGKPX@XZI@TVJY@  +#7&54632#7&5463& C<('& C<('% %% %( U U0+( 0+(dk %@"GTVJ  +6#7&5463& C<('k% %7TD  -+'57'5777d77L&?&&?&7TD  -+'7'7'7'77777,&&?&&7TD--0+7TD--0+j6 J@ G EKPX@pVZI@pRVJY +'7##3'7I +_o+ 7 77 Hj6 J@G EKPX@pVZI@pRVJY +3##'7go_+ 77 t|7 HH jD/@  Ef +'#'7'77 9 11 96 66 9 1q1 96 66 j.KPX@ pZI@ ofY@  +3|9f/@, GZVXI$& +$#5&&546753&&#"3267?PZfgZOA6-4!@GFA 3, ss -<fdd_?XS'j@!  GE DK1PX@\XcI@`TXLY@ '&+,% +'#"''7&547'76327654&#"3%L7N5C@5M7N$#M7N1CC5N7L%??;;@@;6K7L "N7N5CA6P7P" N7M4FHAAHHAAHe8,6@3GFp`XaI'# +$#5&'732654&&'&&546753&&#"`UP{R6Hd?Q>:g_bPP0M#5"I+5C>9!," WJF^ %!: 1.'!.N<'%@GK1PX@) ^  ^XXHXaI@'` ^  ^XaIY@%$#"! $"%! +63267#"&'#735#736632&&#"!#3#PK'A$&H,gXFUJ_cS$&@({$ҐOP|w=Z>p{8?>Z=,[@G DKPX@XZHV[I@`V[IY@# +3#'>5#5354632&#$ v$E>'*TTWN$9!-/%'IGXIX7C#?7GHDS C(!b@ GK1PX@^XXHVYI@`^VYIY@ %# +6!!5>55#5354632&&#"3##@ [#" BBdY7X$=5%15Й8MI /+uZ==Z>C'9f%XS&e8''((*+Uf/@, GZVXI$& +$#5&&546753&&#"3267?PZfgZOA6-4!@GFA 3, ss -<fdd_?XS&#fO,6@3GFp`XYI'# +$#5&'732654&&'&&546753&&#"bXP|P5If?R>;h`aPP3N#5#I+5E?=@T4wj O:",# WLE_ %!; 2.(!.O='%-+63267#"&'#735#736632&&#"!#3#PL'A$&H,hXFUJ`cS$&@(}#ғRP}=Z>x8?>Z=<!8@5G^X`HVYI%# +6!!5>55#5354632&&#"3##J Q#" BBe];Y$=7(47ڙ8MI /+<{Sg(+.86|<)>@;G _^ XHYI +#3##5#535#5333ъ^rfaZ>Z==Z>W;Uf2XS&*f9,5@2 Gp`XaI&$ +$#5&&'732654&&'&&546753&#"_SP;e&6H_=P<9d]_LP/K"4@Q3C=;=Q3oh,&;F>9!,#!UJE^ % :<1.'",N<*/&@GK1PX@) ^  ^XXHXaI@'` ^  ^XaIY@&%$#"!%"%! +63267#"&'#735#736632&&#"3#3#MI&=%&F*f~XFUJ]1W*$&='x"ˏNP|w=Z>p{?>Z=F b@ GK1PX@^XXHVYI@`^VYIY@ $# +6!!5>55#5354632&&#"3##; `#" BBbVhF=4"-4˙8MI /+u#w#/#R/0+0+Y+2|T0!+ ("-+#"'#7&&54663273&#"6654&'3Fbdn\(GB9?cdfT"G:1,iFPTQP72LZFUea;7Z2Peb2.Or+(STRTE{+1>"R_R_0+0+JFY0@-^RVJ +%#5#5FY??y??JFc0@-^RVJ +#5#5Fc??y??2s'-+'%%7!G!oJL2E"IR0+ڰ0+A7lH '3A@>0 G  \X[I(((3(2.,'&" &$& +#"&'#"&&54663266367&&#"3654&#"3Y,,Z@;f"#_A@Y,,Z@;f"$_@G!I8/::/::/4E$J8 9^99^8E:>FF>>FDD4L+T2@/G`X]I%%$ +&#"#"&'73265463D8!--'ME$2!&!OIT B&'GI C $!KL2s'-+%5%{G!o!MJ^L2E"NR0+ڰ0+>i$@!pRVJ +%5!5!cxM_+>&s@RVJ +!5sMMJFc1 10+JF'c; ;0+H -+''7'772z8zz8zz8zz83z8zz8zz9{{9>=T5@2ED^RVJ +3#'7#537#5373#P3?LzEN2=HvMjMtMgM!/@,GE`XaI! *&& +#"&&546632&&'76'&#"3G5cB:a93V5.Iz?,X0?A7lP|E4eF@c5+#j$Cde]HDJP- &1@GEDK1PX@)`  ` XXHXaI@' ``  `XaIY@"'''1'0-+&%!( +'$#"&54633254&##"&54633254&#@@r[[HG[[G,%%,Q$-ZZHH[[H,%%,Q$-** \MM\\MM\>>33''>H>GDB3=3<97'2'1-+&%!( +'$#"&54633254&##"&5463 #"&54633254&# 3254&#@@r[[HG[[G,%%,Q$-ZZHH[[HZZHH[[Hj%%,Q$->%%,Q$-** \MM\\MM\> '@$^V[I  +##5#5353TTqLLJGvd1 10+>#RZڰ0+0+JGd; ;0+9+ ;DKPX@ VXI@RVJY +##5!#ZZHC & &LL*T%@"G^YI +#73hQ{M2 V@G FKPX@VXHVYI@^VYIY@  +!!55!(mO*NNNN7H3L((0+JpF(bcA@>Bc@>A0+Ȱ0+JF@RVJ +%#5FAAJTGE ,@)R^VJ  +%##5#5353G[G[[GAWWAYYJF=0@-^RVJ +#5#5F=??y??JFc 0+JiGZd 0+#/[@X ! -,G``T `XL/.*($"$$$ +3267#"&'&&#"'633267#"&'&&#"'63, =/W. =2W, =/W. =2W  [ a  [ a#@>#w A@>`^TXL    $ +#"&5463!5#"&5463((((((((w())(MM())(>0@-^RVJ +!5!5xMMMM2s'I2E #@ EVYI   +'%%7!5!G!o iP>&sRHU>=TVW- X-wY>Z> dK!PX@!^V[H VYI@^^ VYIY@    +##5#5353!5TTLLMM9+^*T_2`G/[@X ! -,G``T `XL/.*($"$$$ +3267#"&'&&#"'633267#"&'&&#"'63, =/W. =2W, =/W. =2W  [ a  [ aG@$\#w A@>`^TXL    $ +#"&5463!5#"&54636((((((((w())(MM())(\0@-^RVJ +!5!5xMMMMPs'IPE #@ EVYI   +'%%7!5!G!o 0 G  \X[I(((3(2.,'&" &$& +#"&'#"&&54663266367&&#"3654&#"3Y,,Z@;f"#_A@Y,,Z@;f"$_@G!I8/::/::/4E$J8 9^99^8E:>FF>>FDD4L5+TM]Ps'NPE"NR0+ڰ0+\iP\&sRfU\=TV2!/@,GE`XaI! *&& +#"&&546632&&'76'&#"3G5cB:a93V5.Jz?,X0?A7rP|E4eF@c5+#r#Clde]HDJPR2&1`@]GED`  ` X`HXaI'''1'0-+&%!( +'$#"&54633254&##"&54633254&#@@r[[HG[[G,%%,Q$-ZZHH[[H,%%,Q$-** \MM\\MM\>>33''>H>GDB3=3<97'2'1-+&%!( +'$#"&54633254&##"&5463 #"&54633254&# 3254&#@@r[[HG[[G,%%,Q$-ZZHH[[HZZHH[[Hj%%,Q$->%%,Q$-** \MM\\MM\>`^TXL    $ +#"&5463!5#"&54636((((((((w())(MM())(\0@-^RVJ +!5!5xMMMMPs'IPE #@ EVYI   +'%%7!5!G!o ;954$&$%$$% +#"&'#"&546323254&&#"327#"&&5466375&#"3bda8? G6P]xb*J)""jLknXUr_a8c?ssЅ)!!&0.kk>),9xd~>3aOcoo_"GoΈyVKNQ+5D@A54%   GDX`HXaI 20 + * +67'#"&&5467&&54636654&#3267'dS.KB(V#6pBa+lFBe9FE2/_T)0&)342*P0M?/L#'F+;U'QXtQi6^//.U8>],0L0DWD0&$9'=%*/E,7>$$Z)R @DpXXI$ +#&&5463%RSrSqor > mXaj\y8@".#/GKPX@% ``\ XZI@+ ` ``TXLY@  8 720,*&$& +#"&&54663326654&&#&#"3267#"&54663TTUVTTVGtBBtGGsBBsG&6%!+)21*' 4CJZ,J-TVUTTUVT4FxHGwFFwGHxFG1@B?@0.dZ,4ӵ"GKPX@0m  ` \X ZHX [IKPX@.m `  ` \X [I@5m `  ` ^ T XLYY@".-31-4.4+)('&%$#& +#"&&546636654&&#"36#'##32254&##uCCuGEtCCtE:[33[:8Z33Z8m$JC=9Nzq6EvFFuDDuFFvE17^99_88_99^7' sjjT**RF0AV@>50 GK*PX@\XXI@`TXLY@ $"$# +$#"'732654&&'&&5467&&54632&&#"&6654&&'&'lWaG"A),835SH)!kPaJ#!@(+443TH)#'85--# "@9$A0!BN6:$B9"<r% ) *#*,-+##5!'&547####33MQ y ZCcHi[SlqG@@ !%*y7})@&\X`I& +&&546632#6654&#"3K..K++K..K+%22%%23$}&I11I&&J11I%>2//32//3Fk-+632673#"&&546632!#"!5LK(:8fqilmkooV'L43/BG]gga`l+50d, (, @ *)! -+#"&54663#3&&5332654&#!5ijZZj0Y;`Y| Y7733773xec{yeAd8CIEuS6xOyLMNLLNMLMM(H@Gof +'#3aR9* LKPX@XHV[HYI@V[HVYIY@  +###5353ԩXX MCM*^KPX@!^XH V[HYI@!^ V[HVYIY@ +%3##5#535#53533#+XXMMMM~2J$+29?ELRX_fmt{'@${yrpmlba_ZVTROKGEB=;842-)'$" -+$#"&&546632#5'67&'67&'67367&''3$'3563&'67&'#75#$67#$7#52367&'$&'67&'2ځځZ.PE7FP+\p+/8+Jzp@L)9-@3G2AONH1BAO*QC0LI/YD [,IMpAJ+?(p+'?)Lۀہۀہ`njdD1gOTDRd~TXccSYMQVHfXTPOJU~YSn_cj^COgtD0dR<@  @  -+#!%'33##"&55!5#<,,Bk//*-uuQQdt-+&5463!2#!7'7''T֚CCCC q,CEEC(  -+!2#!%'77'7>CCClᛛECCdP  -+&5463!!7'7''>|CCCC q,CEECx</?O_o&6SA(,' upe`UPE@50% -+&5463!2#!3326554&##23326554&##23326554&##23326554&##23326554&##23326554&##3326554&##23326554&##23326554&##23326554&##23326554&##3326554&##"32$3326554&##23326554&##23326554&##23326554&##23326554&##3!26554&#!` J J J J J J J J J J   J J J J J J J J J J 6 ^  J J J J J J J J J J f  q J J J J J J J J J J J J J J J J J J J J J J  J ^ J J J J J J J J J J J J z -+6332#!!!55!#w*/-w13*+ooF7}**N2C1@.!@72"G\X`I&$$$ +$#"'732654&&'&&5467&&54632&&#"&6654&&'&'m[fG"C,0958VJ)!lT8T$#!B+.656WJ*#);;//)2"GQ2>$#!A:$A3$FO:%"#B9#;r& ) *K0+9 JK!PX@XHV[HYI@^XHYIY@  +###5353XXM/M9\K!PX@!^XH V[HYI@ ^^XHYIY@ +3##5#535#53533#DXX MMMMTK}CC~!-+'7:)~1rMM =EK*PX@ X`I@TXLY@ $ +&'7327#wS=DG=U>G> LL >Gsj@Ef +#'77=(~'sq-TT-0@- G`TXL$$ +#"&'732654I-F60!*/;-+'7s5S -+'76(1kMM~ %@" ETXL $ +&'73267#xT=B"/ =V=D7 B# 7Dj@Ef +#'77=(~'n-QQ-0@- G`TXL$$ +#"&'732654I-F60!*/;?6  6?'l FKPX@XbI@TXLY@   $ +#"&54632#"&5463y!!!!!!!!!!!!!!!!' 6KPX@ XbI@TXLY@ $ +#"&5463$$$$ $##$'u-+'7'uOMk'zY@-+'7'7a:LN.:VN))'8-KPX@ VZI@RVJY +!!'E'p D OK!PX@`XXI@`TXLY@   $ +#"&546332654&#@@22@@2D=--==--=2'us@  GKPX@XbHXZIKPX@\XbI@T`XLYY@ $%$ +&'&&#"'66323267#   87$ 87  (0 *, %@"GTVJ  +#7&5463u! )5"M  Vt M %@" ETXL % +&'73267#wS= +$$. =U>?6  6?_k3-+'7-hHk/?-+'7:)1rMM3 %@"ETXL $+&'7327#wS=DG=U>G> LL >Gj/@Ef+#'77=(~'q-TT-0@- G`TXL$$+#"&'732654I-F60!*/;?6  6?c ,@)TXL   $+#"&54632#"&5463p!!!!!!!!!!!!!!!!* @TXL $+#"&5463{$$$$*$##$?-+'7)VMrP^-+'7'7X:LN.:VN))/@RVJ+!!E!@ETXL##+327#"&546748" #9D\a50F9,7P!b /@,`TXL   $+#"&546332654&#@@22@@2b=--==--=2l$4@1 GT`XL$%$+&'&&#"'66323267#   87$ 87  (0 *,S,-+'7cE%dS pwT@ GEK#PX@XFI@TXLY@(+'7#"&54632#"&5463De!!!!!!!!      lT@  GKPX@\XFI@T`XLY@ $%$+&'&&#"'66323267#   87$ 87  (0 *,-+'7cE%i  =GKPX@ XZI@TVJY@  +#7&5463u! )5"  Vt 4U'u'xV'ts'ys'l'  'u 'zY@ '8 'p D 'u*nAUr{A xskaMB;C-+7>323632#"'#"'&'&#"#"&'.'7''667'667'67'674'667'67'$7.'#'3267735&&'7667&&'73657''4675'.5667667&&'&'&'#&'.54736654&''76654&#"#&5467665&&''&'"&5477&#"#.''766323&#"'67'&&#"632#&&5'675'76635'7&&#"'$#"&'7|O;[o8 Z-/$&1(7:8 ;%:$# #4@'?$4"", K7uDyI" 5,,!   $ 1 8/V@85 %,:  ) %'  L.z b  63R  52K5$O  32T@,CL,&  M:e  !F?B4X8 [3  O0. ##/-Y$5( >.>-$/   % ";5" %-0, &7)  ) 4<3<@=:$B 9^%ZE(3/  &/4 (  6  $&11 $ ' /##-7  <>o $    65$  "4?W!  O" 1{ A  -+66326632#&#"3&5463237'73&5432&&'&&''''#7.5473&&'&&''667"&'&&'"&'7''>7'#"&5476654'&'&&547776737&5467''673&546?&&#"6327'5677.'"73277''>8X4B?F!  e:M  &,LC,@T23  O$5K25   R36  b z.L  '% )  :,% 58@V;. 1 $   !q  3[I-/## .0$ (5N?4"  $56    $ o><  7-##/  ' $ 11&$  6  ( 4/&  /3(E   !WY1 " 4 gI',5@H@FA>72-,+&!  -+&'2#"'65572'64677'7&&5632&56'3  # 3#  A+  ) <D  *      &*nAUr{?A}vskaMB;C-+7>323632#"'#"'&'&#"#"&'.'7''667'667'67'674'667'67'$7.'#'3267735&&'7667&&'73657''4675'.5667667&&'&'&'#&'.54736654&''76654&#"#&5467665&&''&'"&5477&#"#.''766323&#"'67'&&#"632#&&5'675'76635'7&&#"'$#&5467'327#"&'77&&#7&&#667&'667'667&&#665&&#"654&##|O;[o8 Z-/$&1(7:8 ;%:$# #4@'?$4"", K7uDyI" 5,,!   $ 1 8/V@85 %,:  ) %'  L.z b  63R  52K5$O  32T@,CL,&  M:e  !F?B4X8 [3  O0. ##/-' '  $5(+$  &(  ) / >.>-$/   % ";5" %-0, &7)  ) 4<3<@=:$B 9^%ZE(3/  &/4 (  6  $&11 $ ' /##-7  <>o $    65$  "4?W!  O" 1m   4 /%  !&jsF_<#$YPYXP6{  ==========00`d070707070707dddddddddddddw7w7w7w7w7d#d(dYd(((((S(( ((11MdMddddd>dddddd777777777777EdEd7]d]d]d]d!!!!!!ZZZZZZZZZZZ,:::::&&&&&    707d7!  - - - - - - - - - -V-V-R_999999V>:9>_>&9&9&9&9&9&9&9&9&9&9O J_PJ_L_ L2L___%Z%%Z%WQZ.Y_J_J__J_J_J_J_H9H9H9H9H9H9H9H9H9H9H99R_R_Q9__HQQ_i i i i i FZFZFZFZFZFZFZFZFZFZFZ      9J_H9IZIZ7qdk7+d777777Kd2Kd2ddddddddddddddd9797979797qdP#qd%d%d%%%%%R%Cd% %%ddddddQ>qdqdqdqdqdqdqdk7k7k7k7k7k7k7k7k7k7k77ddg7(d(d(d(d]Z]Z]Z]Z]Z]Z]Z]Z]Z]Z]ZA8=Cd`ddddcddd5 dddMdMd>d7dEd074(d(ddddT>d3dd!57 (d(1d7- 5 MdMddd07&&d(i(^d^d(d5d(==d--5 dd777 d(d3d: -C94____.&9&9&9X_X_X___@%<Q_H9N_R_9  0>(7b___I_'#_9_%._9LP_UH9 __<Q_N_9  (7(7E_E_%Z(7 - -&9/9/9X_X_H9H9H9   (7__0V-d+dddd)ddd qdqdqd4d4d9>qdk7ldd7(-(dCdCdnd d9dId7%d%l,dqYk7  4dd]qdd7-(;((d}d%d!(dD-D-qdk7k7-(dd=`ddGd d7(dMd=>d-7dEd(&*##7=(&m(&====dddd(((( 77&&&&77R:[_C99&PK>9ZKL_2H9SMZ9K9;ZAP AZ;Z;Z;ZH9 AR:9PKR:R:R:R:R:99PKPKPKH9H9;Z;Z;Z;Z;Z;Z;Z;Z A A A+dddqdk7%dd>qd-k7ldd((#l#k7%d%%k7k7dqdddqdqdqd%%%%% %%%k7k7k7k7k7.7#(7'- -c(# 7'- -080P0-001020?0L0/0300L0,0(03030@030307.7c(080YAAA7A4A74*A4A44hC.A74*41C*2.A74*41C*2.A74*41C*2.A74*41C*2i2D22&2332<<&i30$0$ssBB-BAB2D(D(ssBB-BAB2D(D(ssss   0<<  <<000?767T7T7((((((?767T7T70  (90@D (90@ (0U00#00<00U00*0*0F07##2>Y2T>JJ22G7v22>L_>JJH>:-->J>JV90*27JJJJJJ##>>227v22>>H>:-->>V90*20G0G0\0\0P0P9050P0P0\0\0f0\02R30\0\0&0*0D0G0G0\0\0P0P9050P0P0\0\0f0\0:R30\0\0&0R0Nzpp<(<(<P<(Mb0(0,FQZ*\CFr# 7Frd(**~<dx(xdxF 7**0N0K09090T0K0C0C,k,nM >(j#(M (_(_'''''''''''(_,kk,nM ('j'''''(''M' ''**RRRR.:F&2>6BJx@j\h$0P\R4@LXdp|   n * 6 B  @ L  ( Nr~&2>T`l*Xdp2D(4@LXdp|L&2j ,8D".:\h"4p$0<H ,8z6 T J V !P!\!h!!!!!!""F"R"^"j"v""""""""####j$$ $$$$0$<$l$x$$$$$$%%%V%b%%%& &l&x&&&' ''@'L'X'd'p'|''''(((((4(@((((((),)8)R)Z)f)r)~)))))))** *J*V*^*~*****++N+Z+b+n+z++,,,,&,2,>,J,V,,,-f--.&.f.r.~..../n/z/////0>0J0t0000000101B1R1v1111122(242@2L2X222233V3^33334 4N4|4445.5\5h5t555556,6P6X6`6h6666707Z77788V889,9t9|9:: :,:4:t:;(;l;t;;<<<==8=j==>>">V>>? ?X??????@ @T@`@l@x@@@@AA AA*A6ABAhAtA|AAB6BRB^BBCCC&C`CCCDD.D:DjDDEE*E2E:E^EEFFFLFvFFFG4GnGGHBHHHI(IZIfIIJJxJJK K6K|KL*LhLLLMRMzMMNN@NNNOO OHOTO`OlOOOOOOPPPP\PhPtPPPPPPPPPQ*Q2QRQ^QQRRRRZRRRSS,S8ShSpSxSSSSSSSTTTTUU>U|UUV.VrVW WW^WWWWXXXY YY>YjYZPZZZ[.[X[[[\\L\\\]6]>]z]]]]]^^ ^\^h^x^^^^^^^___"_L_z___`` `D`L`T````aaa>aaabb&b2b>bJbVbbbnbzbbbbbbbbbbccc"c.c:cFcRc^cpc|ccdTdzde6eeff:frffggvggh8hhhi*iiij4j@jLjXjdjpj|jjjjjjjjjjkk kk$k0kďڌ @brƍ .v~Ƽμ־é6X$4s pVP PY` P {4* &   :2l  & 8 6F & |   h T Lr , , t 4^Digitized data copyright 2012-2014, The Mozilla Foundation and Telefonica S.A.Fira SansRegular3.111;CTDB;FiraSans-RegularVersion 3.111FiraSans-RegularFira Sans is a trademark of The Mozilla Corporation.Carrois Corporate GbR & Edenspiekermann AGCarrois Corporate & Edenspiekermann AGhttp://www.carrois.comLicensed under the Open Font License, version 1.1 or laterhttp://scripts.sil.org/OFLDigitized data copyright 2012-2014, The Mozilla Foundation and Telefonica S.A.Fira SansRegular3.111;CTDB;FiraSans-RegularVersion 3.111FiraSans-RegularFira Sans is a trademark of The Mozilla Corporation.Carrois Corporate GbR & Edenspiekermann AGCarrois Corporate & Edenspiekermann AGhttp://www.carrois.comLicensed under the Open Font License, version 1.1 or laterhttp://scripts.sil.org/OFL26$bc%&d'  (e   )*+,-./01 !"#f2$g%&'345()*6+,-7./0182h345679:89:;;<<==>?@ABCDEDiFkljGHnmIEFoJKGLHpMNrsOqPQIJRSTKUVLtWvwXuYZ[\M]^N_`OabcdPQefghixRyj{|zklm}STUnopVqrsWtuvwX~xyz{|}YZ~[\]      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./012345 ?" B6789:;<^`>@ =>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstauvwx yz!{|}~_# AC      !"#$%&'()*+,-./0123456789:nullAbreveAmacronAogonekAEacute Ccircumflex CdotaccentDcaronDcroatEbreveEcaron EdotaccentEmacronEogonek Gcircumflex Gcommaaccent GdotaccentHbar HcircumflexIJIbreveImacronIogonekItilde Jcircumflex KcommaaccentLacuteLcaron LcommaaccentLdotNacuteNcaron NcommaaccentEngObreve OhungarumlautOmacron OslashacuteRacuteRcaron RcommaaccentSacute Scircumflex ScommaaccentTbarTcaronTcedillauni021AUbreve UhungarumlautUmacronUogonekUringUtildeWacute Wcircumflex WdieresisWgrave YcircumflexYgraveZacute ZdotaccentOslashacute.001Cacute.loclPLKNacute.loclPLKOacute.loclPLKSacute.loclPLKZacute.loclPLKabreveamacronaogonekaeacute ccircumflex cdotaccentdcaronebreveecaron edotaccentemacroneogonek gcircumflex gcommaaccent gdotaccenthbar hcircumflexibreve i.loclTRKijimacroniogonekitildejdotless jcircumflex kcommaaccent kgreenlandiclacutelcaron lcommaaccentldotnacute napostrophencaron ncommaaccentengobreve ohungarumlautomacron oslashacuteracutercaron rcommaaccentsacute scircumflex scommaaccenttbartcarontcedillauni021Bubreve uhungarumlautumacronuogonekuringutildewacute wcircumflex wdieresiswgrave ycircumflexygravezacute zdotaccentcacute.loclPLKnacute.loclPLKoacute.loclPLKsacute.loclPLKzacute.loclPLKf_if_lcacute.sc.loclPLKnacute.sc.loclPLKoacute.sc.loclPLKsacute.sc.loclPLKzacute.sc.loclPLKa.sc aacute.sc abreve.scacircumflex.sc adieresis.sc agrave.sc amacron.sc aogonek.scaring.sc atilde.scae.sc aeacute.scb.scc.sc cacute.sc ccaron.sc ccedilla.scccircumflex.sc cdotaccent.scd.sceth.sc dcaron.sc dcroat.sce.sc eacute.sc ebreve.sc ecaron.scecircumflex.sc edieresis.sc edotaccent.sc egrave.sc emacron.sc eogonek.scf.scf_i.scf_l.scfi.scfl.scg.sc gbreve.scgcircumflex.scgcommaaccent.sc gdotaccent.sch.schbar.schcircumflex.sci.sc dotlessi.sc iacute.sc ibreve.scicircumflex.sc idieresis.sc i.sc.loclTRK igrave.scij.sc imacron.sc iogonek.sc itilde.scj.scjcircumflex.sck.sckcommaaccent.sckgreenlandic.scl.sc lacute.sc lcaron.sclcommaaccent.scldot.sc lslash.scm.scn.sc nacute.scnapostrophe.sc ncaron.scncommaaccent.sceng.sc ntilde.sco.sc oacute.sc obreve.scocircumflex.sc odieresis.sc ograve.scohungarumlaut.sc omacron.sc oslash.scoslashacute.sc otilde.scoe.scp.scthorn.scq.scr.sc racute.sc rcaron.scrcommaaccent.scs.sc sacute.sc scaron.sc scedilla.scscircumflex.scscommaaccent.sc germandbls.sct.sctbar.sc tcaron.sc tcedilla.sc uni021B.scu.sc uacute.sc ubreve.scucircumflex.sc udieresis.sc ugrave.scuhungarumlaut.sc umacron.sc uogonek.scuring.sc utilde.scv.scw.sc wacute.scwcircumflex.sc wdieresis.sc wgrave.scx.scy.sc yacute.scycircumflex.sc ydieresis.sc ygrave.scz.sc zacute.sc zcaron.sc zdotaccent.scuni0410uni0411uni0412uni0413uni0403uni0490uni0414uni0415uni0400uni0401uni0416uni0417uni0418uni0419uni040Duni041Auni040Cuni041Buni041Cuni041Duni041Euni041Funi0420uni0421uni0422uni0423uni040Euni0424uni0425uni0427uni0426uni0428uni0429uni040Funi042Funi042Cuni042Auni042Buni0409uni040Auni0405uni0404uni042Duni0406uni0407uni0408uni040Buni042Euni0402uni0462uni0472uni0474uni0492uni0496uni0498uni049Auni049Cuni04A0uni04A2uni0524uni04AAuni04ACuni04AEuni04B0uni04B2uni04B6uni04B8uni04BAuni0526uni04C0uni04C1uni04CBuni04D0uni04D2uni04D6uni04D8uni04DAuni04DCuni04DEuni04E2uni04E4uni04E6uni04E8uni04EAuni04ECuni04EEuni04F0uni04F2uni04F4uni04F6uni04F8uni051Cuni0430uni0431uni0432uni0433uni0453uni0491uni0434uni0435uni0450uni0451uni0436uni0437uni0438uni0439uni045Duni043Auni045Cuni043Buni043Cuni043Duni043Euni043Funi0440uni0441uni0442uni0443uni045Euni0444uni0445uni0447uni0446uni0448uni0449uni045Funi044Funi044Cuni044Auni044Buni0459uni045Auni0455uni0454uni044Duni0456uni0457uni0458uni045Buni044Euni0452uni0463uni0473uni0475uni0493uni0497uni0499uni049Buni049Duni04A1uni04A3uni0525uni04ABuni04ADuni04AFuni04B1uni04B3uni04B7uni04B9uni04BBuni0527uni04CFuni04C2uni04CCuni04D1uni04D3uni04D7uni04D9uni04DBuni04DDuni04DFuni04E3uni04E5uni04E7uni04E9uni04EBuni04EDuni04EFuni04F1uni04F3uni04F5uni04F7uni04F9uni051Duni04D4uni04D5 uni0430.sc uni0431.sc uni0432.sc uni0433.sc uni0453.sc uni0491.sc uni0434.sc uni0435.sc uni0450.sc uni0451.sc uni0436.sc uni0437.sc uni0438.sc uni0439.sc uni045D.sc uni043A.sc uni045C.sc uni043B.sc uni043C.sc uni043D.sc uni043E.sc uni043F.sc uni0440.sc uni0441.sc uni0442.sc uni0443.sc uni045E.sc uni0444.sc uni0445.sc uni0447.sc uni0446.sc uni0448.sc uni0449.sc uni045F.sc uni044F.sc uni044C.sc uni044A.sc uni044B.sc uni0459.sc uni045A.sc uni0455.sc uni0454.sc uni044D.sc uni0456.sc uni0457.sc uni0458.sc uni045B.sc uni044E.sc uni0452.sc uni0463.sc uni0473.sc uni0475.sc uni0493.sc uni0497.sc uni0499.sc uni049B.sc uni049D.sc uni04A1.sc uni04A3.sc uni0525.sc uni04AB.sc uni04AD.sc uni04AF.sc uni04B1.sc uni04B3.sc uni04B7.sc uni04B9.sc uni04BB.sc uni0527.sc uni04CF.sc uni04CC.sc uni04D1.sc uni04D3.sc uni04D5.sc uni04D7.sc uni04D9.sc uni04DB.sc uni04E3.sc uni04E9.sc uni04EB.sc uni04ED.sc uni04EF.sc uni04F1.sc uni04F3.sc uni04F5.sc uni04F7.sc uni04F9.sc uni051D.scAlphaBetaGammaDeltaEpsilonZetaEtaThetaIotaKappaLambdaMuNuXiOmicronPiRhoSigmaTauUpsilonPhiChiPsi Alphatonos EpsilontonosEtatonos Iotatonos Omicrontonos Upsilontonos Omegatonos IotadieresisUpsilondieresisuni1FBAuni1FBBuni1FB8uni1FB9uni1FC8uni1FC9uni1FCAuni1FCBuni1FDAuni1FDBuni1FD8uni1FD9uni1FF8uni1FF9uni1FEAuni1FEBuni1FE8uni1FE9uni1FFAuni1FFBalphabetagammadeltaepsilonzetaetathetaiotakappalambdanuxiomicronrho sigmafinalsigmatauupsilonphichipsiomega iotatonos iotadieresisiotadieresistonos upsilontonosupsilondieresisupsilondieresistonos omicrontonos omegatonos alphatonos epsilontonosetatonosuni1F70uni1F71uni1FB6uni1FB0uni1FB1uni1F72uni1F73uni1F74uni1F75uni1FC6uni1F76uni1F77uni1FD6uni1FD0uni1FD1uni1FD2uni1FD3uni1FD7uni1F78uni1F79uni1F7Auni1F7Buni1FE6uni1FE0uni1FE1uni1FE2uni1FE3uni1FE7uni1F7Cuni1F7Duni1FF6alpha.scbeta.scgamma.scdelta.sc epsilon.sczeta.sceta.sctheta.sciota.sckappa.sc lambda.scmu.scnu.scxi.sc omicron.scpi.scrho.sc sigmafinal.scsigma.sctau.sc upsilon.scphi.scchi.scpsi.scomega.sc iotatonos.sciotadieresis.sciotadieresistonos.scupsilontonos.scupsilondieresis.scupsilondieresistonos.scomicrontonos.sc omegatonos.sc alphatonos.scepsilontonos.sc etatonos.sc uni1F71.sc uni1FB6.sc uni1FB0.sc uni1FB1.sc uni1F72.sc uni1F73.sc uni1F74.sc uni1F75.sc uni1FC6.sc uni1F76.sc uni1F77.sc uni1FD6.sc uni1FD0.sc uni1FD1.sc uni1FD2.sc uni1FD3.sc uni1FD7.sc uni1F78.sc uni1F79.sc uni1F7A.sc uni1F7B.sc uni1FE6.sc uni1FE0.sc uni1FE1.sc uni1FE2.sc uni1FE3.sc uni1FE7.sc uni1F7C.sc uni1F7D.sc uni1FF6.sczero.osfone.osftwo.osf three.osffour.osffive.osfsix.osf seven.osf eight.osfnine.osfzero.tfone.tftwo.tfthree.tffour.tffive.tfsix.tfseven.tfeight.tfnine.tf zero.tosfone.tosftwo.tosf three.tosf four.tosf five.tosfsix.tosf seven.tosf eight.tosf nine.tosf zero.zero zero.osf.zero zero.tf.zerozero.tosf.zero onefractionuni2153uni2154uni2155uni2156uni2157uni2158uni2159uni215A oneeighth threeeighths fiveeighths seveneighths zero.dnomone.dnomtwo.dnom three.dnom four.dnom five.dnomsix.dnom seven.dnom eight.dnom nine.dnom zero.numrone.numrtwo.numr three.numr four.numr five.numrsix.numr seven.numr eight.numr nine.numr zeroinferior oneinferior twoinferior threeinferior fourinferior fiveinferior sixinferior seveninferior eightinferior nineinferior zerosuperior foursuperior fivesuperior sixsuperior sevensuperior eightsuperior ninesuperiorexclamdown.casequestiondown.casenumbersign.osf numbersign.tfnumbersign.tosfuni208Duni208Eparenleftsuperiorparenrightsuperiorbraceleft.casebraceright.casebracketleft.casebracketright.caseparenleft.caseparenright.caseparenleft.dnomparenright.dnomparenleft.numrparenright.numruni2015 figuredash softhyphen emdash.case endash.case hyphen.casesofthyphen.casefiguredash.osf figuredash.tffiguredash.tosfguillemotleft.caseguillemotright.caseguilsinglleft.caseguilsinglright.caseuni2007uni2008uni00A0zerowidthspace space.fracuni200Euni200Funi200Duni200CuniFEFFEurocent.osf currency.osf dollar.osfEuro.osf sterling.osfyen.osfcent.tf currency.tf dollar.tfEuro.tf sterling.tfyen.tf cent.tosf currency.tosf dollar.tosf Euro.tosf sterling.tosfyen.tosfOhmbulletoperator divisionslashdotmathemptysetuni208C equalsuperior incrementuni00B5uni208Buni207Buni208A plussuperior infinity.case equal.dnom minus.dnom plus.dnom equal.numr minus.numr plus.numrapproxequal.osfasciitilde.osf divide.osf equal.osf greater.osfgreaterequal.osf infinity.osf integral.osfless.osf lessequal.osflogicalnot.osf minus.osf multiply.osf notequal.osfpartialdiff.osf percent.osfperthousand.osfplus.osf plusminus.osf product.osf radical.osf summation.osfapproxequal.tf asciitilde.tf divide.tfequal.tf greater.tfgreaterequal.tf infinity.tf integral.tfless.tf lessequal.tf logicalnot.tfminus.tf multiply.tf notequal.tfpartialdiff.tf percent.tfperthousand.tfplus.tf plusminus.tf product.tf radical.tf summation.tfapproxequal.tosfasciitilde.tosf divide.tosf equal.tosf greater.tosfgreaterequal.tosf infinity.tosf integral.tosf less.tosflessequal.tosflogicalnot.tosf minus.tosf multiply.tosf notequal.tosfpartialdiff.tosf percent.tosfperthousand.tosf plus.tosfplusminus.tosf product.tosf radical.tosfsummation.tosfarrowupuni2197 arrowrightuni2198 arrowdownuni2199 arrowleftuni2196uni2194 arrowupdn arrowupwhitearrowrightwhitearrowdownwhitearrowleftwhiteuni2B06uni27A1uni2B07uni2B05uni25AF lozenge.osf lozenge.tf lozenge.tosf estimateduni2116u1F310capslockclearuni232BdeleterightKeyuni2328uni23CE section.osf degree.osf dagger.osf daggerdbl.osf section.tf degree.tf dagger.tf daggerdbl.tf section.tosf degree.tosf dagger.tosfdaggerdbl.tosf caron.alt acute.case breve.case caron.case cedilla.casecircumflex.case dieresis.casedotaccent.case grave.casehungarumlaut.case macron.case ring.case tilde.case acute.loclPLKacute.case.loclPLK acutecombuni0306uni030Cuni0327uni0302uni0313uni0326uni0314breve-cyuni0308uni0307 gravecombuni030Buni0304uni030A tildecomb uni0326.case breve-cy.caseacute.sc.loclPLKacute.scbreve.sccaron.sc cedilla.sc circumflex.sc uni0326.sc breve-cy.sc dieresis.sc dotaccent.scgrave.schungarumlaut.sc macron.sc ogonek.scring.sctilde.sctonos dieresistonosuni1FC0 tonos.caseuni02BC dotlessj.sc acutecombcomb brevecombcomb caroncombcombcircumflexcombcombdieresiscombcombdotaccentcombcomb gravecombcombhungarumlautcombcombmacroncombcomb ringcombcomb tildecombcombuniE000uniE001uniE002uniE003aaII4>aaII4>ccJJ++ccJJ++ccJJ+ +, UXEY KQKSZX4(Y`f UX%acc#b!!YC#DC`B-, `f-, d P&Z( CEcER[X!#!X PPX!@Y 8PX!8YY  CEcEad(PX! CEcE 0PX!0Y PX f a PX` PX! ` 6PX!6``YYY+YY#PXeYY-, E %ad CPX#B#B!!Y`-,#!#! dbB #B CEc C`Ec*! C +0%&QX`PaRYX#Y! @SX+!@Y#PXeY-,C+C`B-,#B# #Babfc`*-, E Ccb PX@`Yfc`D`-, CEB*!C`B- ,C#DC`B- , E +#C%` E#a d PX!0PX @YY#PXeY%#aDD`- , E +#C%` E#a d$PX@Y#PXeY%#aDD`- , #B EX!#!Y*!- ,EdaD-,` CJPX #BY CJRX #BY-, bfc c#aC` ` #B#-,KTXdDY$ e#x-,KQXKSXdDY!Y$e#x-,CUXCaB+YC%B %B %B# %PXC`%B #a*!#a #a*!C`%B%a*!Y CG CG`b PX@`Yfc Ccb PX@`Yfc`#DC>C`B-,ETX#B E #B #`B `aBB`+r+"Y-,+-,+-,+-,+-,+-,+-,+-,+-,+-, +-, +ETX#B E #B #`B `aBB`+r+"Y-,+- ,+-!,+-",+-#,+-$,+-%,+-&,+-',+-(, +-), <`-*, `` C#`C%a`)*!-+,*+**-,, G Ccb PX@`Yfc`#a8# UX G Ccb PX@`Yfc`#a8!Y--,ETX,*0"Y-., +ETX,*0"Y-/, 5`-0,Ecb PX@`Yfc+ Ccb PX@`Yfc+D>#8/*-1, < G Ccb PX@`Yfc`Ca8-2,.<-3, < G Ccb PX@`Yfc`CaCc8-4,% . G#B%IG#G#a Xb!Y#B3*-5,%%G#G#a C+e.# <8-6,%% .G#G#a #B C+ `PX @QX  &YBB# C #G#G#a#F`Cb PX@`Yfc` + a C`d#CadPXCaC`Y%b PX@`Yfca# &#Fa8#CF%CG#G#a` Cb PX@`Yfc`# +#C`+%a%b PX@`Yfc&a %`d#%`dPX!#!Y# &#Fa8Y-7, & .G#G#a#<8-8, #B F#G+#a8-9,%%G#G#aTX. <#!%%G#G#a %%G#G#a%%I%acc# Xb!Ycb PX@`Yfc`#.# <8#!Y-:, C .G#G#a ` `fb PX@`Yfc# <8-;,# .F%FRX ,5+# .F%FRX +-S,>+-T,>+-U,>+-V,@+-W,@+-X,@+-Y,@+-Z,C+-[,C+-\,C+-],C+-^,?+-_,?+-`,?+-a,?+-b,7+.++-c,7+;+-d,7+<+-e,7+=+-f,8+.++-g,8+;+-h,8+<+-i,8+=+-j,9+.++-k,9+;+-l,9+<+-m,9+=+-n,:+.++-o,:+;+-p,:+<+-q,:+=+-r, EX!#!YB+e$Px0-KRXYcpBcO;)*B@ VB0"*B@ `L9)* B @ *B@@@@@ *D$QX@XdD&QX@cTXDYYYY@ XD2$ *Dfreetype-rs-0.36.0/examples/assets/LICENSE000064400000000000000000000106621046102023000163110ustar 00000000000000Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ with Reserved Font Name Fira Sans. Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ with Reserved Font Name Fira Mono. Copyright (c) 2014, Telefonica S.A. This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ----------------------------------------------------------- PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. DEFINITIONS "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. "Reserved Font Name" refers to any names specified as such after the copyright statement(s). "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. TERMINATION This license becomes null and void if any of the above conditions are not met. DISCLAIMER THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. freetype-rs-0.36.0/examples/glyph_outline.rs000064400000000000000000000036731046102023000172360ustar 00000000000000extern crate freetype as ft; fn draw_curve(curve: ft::outline::Curve) { match curve { ft::outline::Curve::Line(pt) => println!("L {} {}", pt.x, -pt.y), ft::outline::Curve::Bezier2(pt1, pt2) => { println!("Q {} {} {} {}", pt1.x, -pt1.y, pt2.x, -pt2.y) } ft::outline::Curve::Bezier3(pt1, pt2, pt3) => println!( "C {} {} {} {} {} {}", pt1.x, -pt1.y, pt2.x, -pt2.y, pt3.x, -pt3.y ), } } fn main() { let mut args = std::env::args(); if args.len() != 3 { let exe = args.next().unwrap(); println!("Usage: {} font character", exe); return; } let font = args.nth(1).unwrap(); let character = args.next().and_then(|s| s.chars().next()).unwrap() as usize; let library = ft::Library::init().unwrap(); let face = library.new_face(font, 0).unwrap(); face.set_char_size(40 * 64, 0, 50, 0).unwrap(); face.load_char(character, ft::face::LoadFlag::NO_SCALE) .unwrap(); let glyph = face.glyph(); let metrics = glyph.metrics(); let xmin = metrics.horiBearingX - 5; let width = metrics.width + 10; let ymin = -metrics.horiBearingY - 5; let height = metrics.height + 10; let outline = glyph.outline().unwrap(); println!(""); println!(""); println!( "", xmin, ymin, width, height ); for contour in outline.contours_iter() { let start = contour.start(); println!( ""); } println!(""); } freetype-rs-0.36.0/examples/single_glyph.rs000064400000000000000000000032161046102023000170310ustar 00000000000000extern crate freetype as ft; extern crate unicode_normalization; use unicode_normalization::UnicodeNormalization; const WIDTH: i32 = 32; const HEIGHT: i32 = 24; type Figure = [[u8; WIDTH as usize]; HEIGHT as usize]; fn draw_bitmap(bitmap: ft::Bitmap, x: i32, y: i32) -> Figure { let mut figure = [[0; WIDTH as usize]; HEIGHT as usize]; let w = bitmap.width() as usize; let x_max = x + w as i32; let y_max = y + bitmap.rows(); for (p, i) in (x..x_max).enumerate() { for (q, j) in (y..y_max).enumerate() { if i < 0 || j < 0 || i >= WIDTH || j >= HEIGHT { continue; } figure[j as usize][i as usize] |= bitmap.buffer()[q * w + p]; } } figure } fn main() { let mut args = std::env::args(); if args.len() != 3 { let exe = args.next().unwrap(); println!("Usage: {} font character", exe); return; } let font = args.nth(1).unwrap(); let character = args.next().and_then(|s| s.nfc().next()).unwrap() as usize; let library = ft::Library::init().unwrap(); let face = library.new_face(font, 0).unwrap(); face.set_char_size(40 * 64, 0, 50, 0).unwrap(); face.load_char(character, ft::face::LoadFlag::RENDER) .unwrap(); let glyph = face.glyph(); let x = glyph.bitmap_left(); let y = HEIGHT - glyph.bitmap_top(); let figure = draw_bitmap(glyph.bitmap(), x, y); for row in figure { for v in row { let c = match v { 0 => " ", 1..=127 => "*", _ => "+", }; print!("{}", c) } println!(" "); } } freetype-rs-0.36.0/src/bitmap.rs000064400000000000000000000113401046102023000145670ustar 00000000000000use std::slice; use {ffi, Error, FtResult}; /// An enumeration type used to describe the format of pixels in a given bitmap. Note that /// additional formats may be added in the future. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum PixelMode { /// This value is reserved. None, /// A monochrome bitmap, using 1 bit per pixel. Note that pixels are /// stored in most-significant order (MSB), which means that the left-most /// pixel in a byte has value 128. Mono, /// An 8-bit bitmap, generally used to represent anti-aliased glyph images. /// Each pixel is stored in one byte. Note that the number of `gray` /// levels is stored in the `num_grays` field of the FT_Bitmap structure /// (it generally is 256). Gray, /// A 2-bit per pixel bitmap, used to represent embedded anti-aliased /// bitmaps in font files according to the OpenType specification. We /// haven't found a single font using this format, however. Gray2, /// A 4-bit per pixel bitmap, representing embedded anti-aliased bitmaps in /// font files according to the OpenType specification. We haven't found a /// single font using this format, however. Gray4, /// An 8-bit bitmap, representing RGB or BGR decimated glyph images used /// for display on LCD displays; the bitmap is three times wider than the /// original glyph image. See also FT_RENDER_MODE_LCD. Lcd, /// An 8-bit bitmap, representing RGB or BGR decimated glyph images used for /// display on rotated LCD displays; the bitmap is three times taller than /// the original glyph image. See also FT_RENDER_MODE_LCD_V. LcdV, /// An image with four 8-bit channels per pixel, representing a color image /// (such as emoticons) with alpha channel. For each pixel, the format is /// BGRA, which means, the blue channel comes first in memory. The color /// channels are pre-multiplied and in the sRGB colorspace. For example, /// full red at half-translucent opacity will be represented as /// `00,00,80,80`, not `00,00,FF,80`. See also FT_LOAD_COLOR. Bgra, } #[allow(missing_copy_implementations)] pub struct Bitmap { raw: *const ffi::FT_Bitmap, } impl Bitmap { pub unsafe fn from_raw(raw: *const ffi::FT_Bitmap) -> Self { Bitmap { raw: raw } } /// A typeless pointer to the bitmap buffer. This value should be aligned /// on 32-bit boundaries in most cases. pub fn buffer(&self) -> &[u8] { let buffer_size = (self.pitch().abs() * self.rows()) as usize; if buffer_size > 0 { unsafe { slice::from_raw_parts((*self.raw).buffer, buffer_size) } } else { // When buffer_size is 0, the buffer pointer will be null. &[] } } /// The number of pixels in bitmap row. pub fn width(&self) -> i32 { unsafe { (*self.raw).width } } /// The number of bitmap rows. pub fn rows(&self) -> i32 { unsafe { (*self.raw).rows } } pub fn raw(&self) -> &ffi::FT_Bitmap { unsafe { &*self.raw } } /// The pixel mode, i.e., how pixel bits are stored. See `PixelMode` for /// possible values. pub fn pixel_mode(&self) -> FtResult { let pixel_mode = unsafe { (*self.raw).pixel_mode } as u32; Ok(match pixel_mode { ffi::FT_PIXEL_MODE_NONE => PixelMode::None, ffi::FT_PIXEL_MODE_MONO => PixelMode::Mono, ffi::FT_PIXEL_MODE_GRAY => PixelMode::Gray, ffi::FT_PIXEL_MODE_GRAY2 => PixelMode::Gray2, ffi::FT_PIXEL_MODE_GRAY4 => PixelMode::Gray4, ffi::FT_PIXEL_MODE_LCD => PixelMode::Lcd, ffi::FT_PIXEL_MODE_LCD_V => PixelMode::LcdV, ffi::FT_PIXEL_MODE_BGRA => PixelMode::Bgra, _ => return Err(Error::UnexpectedPixelMode), }) } /// The pitch's absolute value is the number of bytes taken by one bitmap row, including /// padding. However, the pitch is positive when the bitmap has a ‘down’ flow, and negative /// when it has an ‘up’ flow. In all cases, the pitch is an offset to add to a bitmap pointer /// in order to go down one row. /// /// Note that ‘padding’ means the alignment of a bitmap to a byte border, and FreeType /// functions normally align to the smallest possible integer value. /// For the B/W rasterizer, ‘pitch’ is always an even number. /// /// To change the pitch of a bitmap (say, to make it a multiple of 4), use FT_Bitmap_Convert. /// Alternatively, you might use callback functions to directly render to the application's /// surface; see the file ‘example2.cpp’ in the tutorial for a demonstration. pub fn pitch(&self) -> i32 { unsafe { (*self.raw).pitch } } } freetype-rs-0.36.0/src/bitmap_glyph.rs000064400000000000000000000026771046102023000160070ustar 00000000000000use std::ptr::null_mut; use {ffi, Bitmap}; pub struct BitmapGlyph { library_raw: ffi::FT_Library, raw: ffi::FT_BitmapGlyph, } impl BitmapGlyph { pub unsafe fn from_raw(library_raw: ffi::FT_Library, raw: ffi::FT_BitmapGlyph) -> Self { ffi::FT_Reference_Library(library_raw); BitmapGlyph { library_raw, raw } } #[inline(always)] pub fn left(&self) -> i32 { unsafe { (*self.raw).left } } #[inline(always)] pub fn top(&self) -> i32 { unsafe { (*self.raw).top } } #[inline(always)] pub fn bitmap(&self) -> Bitmap { unsafe { Bitmap::from_raw(&(*self.raw).bitmap) } } #[inline(always)] pub fn raw(&self) -> &ffi::FT_BitmapGlyphRec { unsafe { &*self.raw } } } impl Clone for BitmapGlyph { fn clone(&self) -> Self { let mut target = null_mut(); let err = unsafe { ffi::FT_Glyph_Copy(self.raw as ffi::FT_Glyph, &mut target) }; if err == ffi::FT_Err_Ok { unsafe { BitmapGlyph::from_raw(self.library_raw, target as ffi::FT_BitmapGlyph) } } else { panic!("Failed to copy bitmap glyph") } } } impl Drop for BitmapGlyph { fn drop(&mut self) { let err = unsafe { ffi::FT_Done_Glyph(self.raw as ffi::FT_Glyph); ffi::FT_Done_Library(self.library_raw) }; if err != ffi::FT_Err_Ok { panic!("Failed to drop library") } } } freetype-rs-0.36.0/src/charmap.rs000064400000000000000000000007501046102023000147310ustar 00000000000000use freetype_sys::FT_CharMap; pub struct CharMap { raw: FT_CharMap, } impl CharMap { pub fn new(raw: FT_CharMap) -> Self { CharMap { raw } } pub fn platform_id(&self) -> u16 { unsafe { (*self.raw).platform_id } } pub fn encoding_id(&self) -> u16 { unsafe { (*self.raw).encoding_id } } pub fn encoding(&self) -> u32 { unsafe { (*self.raw).encoding } } pub fn raw(&self) -> FT_CharMap { self.raw } } freetype-rs-0.36.0/src/error.rs000064400000000000000000000413551046102023000144550ustar 00000000000000use ffi; use std::error; use std::fmt; pub type FtResult = Result; #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[repr(i32)] pub enum Error { Ok = ffi::FT_Err_Ok, CannotOpenResource = ffi::FT_Err_Cannot_Open_Resource, UnknownFileFormat = ffi::FT_Err_Unknown_File_Format, InvalidFileFormat = ffi::FT_Err_Invalid_File_Format, InvalidVersion = ffi::FT_Err_Invalid_Version, LowerModuleVersion = ffi::FT_Err_Lower_Module_Version, InvalidArgument = ffi::FT_Err_Invalid_Argument, UnimplementedFeature = ffi::FT_Err_Unimplemented_Feature, InvalidTable = ffi::FT_Err_Invalid_Table, InvalidOffset = ffi::FT_Err_Invalid_Offset, ArrayTooLarge = ffi::FT_Err_Array_Too_Large, MissingModule = ffi::FT_Err_Missing_Module, MissingProperty = ffi::FT_Err_Missing_Property, InvalidGlyphIndex = ffi::FT_Err_Invalid_Glyph_Index, InvalidCharacterCode = ffi::FT_Err_Invalid_Character_Code, InvalidGlyphFormat = ffi::FT_Err_Invalid_Glyph_Format, CannotRenderGlyph = ffi::FT_Err_Cannot_Render_Glyph, InvalidOutline = ffi::FT_Err_Invalid_Outline, InvalidComposite = ffi::FT_Err_Invalid_Composite, TooManyHints = ffi::FT_Err_Too_Many_Hints, InvalidPixelSize = ffi::FT_Err_Invalid_Pixel_Size, InvalidHandle = ffi::FT_Err_Invalid_Handle, InvalidLibraryHandle = ffi::FT_Err_Invalid_Library_Handle, InvalidDriverHandle = ffi::FT_Err_Invalid_Driver_Handle, InvalidFaceHandle = ffi::FT_Err_Invalid_Face_Handle, InvalidSizeHandle = ffi::FT_Err_Invalid_Size_Handle, InvalidSlotHandle = ffi::FT_Err_Invalid_Slot_Handle, InvalidCharMapHandle = ffi::FT_Err_Invalid_CharMap_Handle, InvalidCacheHandle = ffi::FT_Err_Invalid_Cache_Handle, InvalidStreamHandle = ffi::FT_Err_Invalid_Stream_Handle, TooManyDrivers = ffi::FT_Err_Too_Many_Drivers, TooManyExtensions = ffi::FT_Err_Too_Many_Extensions, OutOfMemory = ffi::FT_Err_Out_Of_Memory, UnlistedObject = ffi::FT_Err_Unlisted_Object, CannotOpenStream = ffi::FT_Err_Cannot_Open_Stream, InvalidStreamSeek = ffi::FT_Err_Invalid_Stream_Seek, InvalidStreamSkip = ffi::FT_Err_Invalid_Stream_Skip, InvalidStreamRead = ffi::FT_Err_Invalid_Stream_Read, InvalidStreamOperation = ffi::FT_Err_Invalid_Stream_Operation, InvalidFrameOperation = ffi::FT_Err_Invalid_Frame_Operation, NestedFrameAccess = ffi::FT_Err_Nested_Frame_Access, InvalidFrameRead = ffi::FT_Err_Invalid_Frame_Read, RasterUninitialized = ffi::FT_Err_Raster_Uninitialized, RasterCorrupted = ffi::FT_Err_Raster_Corrupted, RasterOverflow = ffi::FT_Err_Raster_Overflow, RasterNegativeHeight = ffi::FT_Err_Raster_Negative_Height, TooManyCaches = ffi::FT_Err_Too_Many_Caches, InvalidOpcode = ffi::FT_Err_Invalid_Opcode, TooFewArguments = ffi::FT_Err_Too_Few_Arguments, StackOverflow = ffi::FT_Err_Stack_Overflow, CodeOverflow = ffi::FT_Err_Code_Overflow, BadArgument = ffi::FT_Err_Bad_Argument, DivideByZero = ffi::FT_Err_Divide_By_Zero, InvalidReference = ffi::FT_Err_Invalid_Reference, DebugOpCode = ffi::FT_Err_Debug_OpCode, ENDFInExecStream = ffi::FT_Err_ENDF_In_Exec_Stream, NestedDEFS = ffi::FT_Err_Nested_DEFS, InvalidCodeRange = ffi::FT_Err_Invalid_CodeRange, ExecutionTooLong = ffi::FT_Err_Execution_Too_Long, TooManyFunctionDefs = ffi::FT_Err_Too_Many_Function_Defs, TooManyInstructionDefs = ffi::FT_Err_Too_Many_Instruction_Defs, TableMissing = ffi::FT_Err_Table_Missing, HorizHeaderMissing = ffi::FT_Err_Horiz_Header_Missing, LocationsMissing = ffi::FT_Err_Locations_Missing, NameTableMissing = ffi::FT_Err_Name_Table_Missing, CMapTableMissing = ffi::FT_Err_CMap_Table_Missing, HmtxTableMissing = ffi::FT_Err_Hmtx_Table_Missing, PostTableMissing = ffi::FT_Err_Post_Table_Missing, InvalidHorizMetrics = ffi::FT_Err_Invalid_Horiz_Metrics, InvalidCharMapFormat = ffi::FT_Err_Invalid_CharMap_Format, InvalidPPem = ffi::FT_Err_Invalid_PPem, InvalidVertMetrics = ffi::FT_Err_Invalid_Vert_Metrics, CouldNotFindContext = ffi::FT_Err_Could_Not_Find_Context, InvalidPostTableFormat = ffi::FT_Err_Invalid_Post_Table_Format, InvalidPostTable = ffi::FT_Err_Invalid_Post_Table, Syntax = ffi::FT_Err_Syntax_Error, StackUnderflow = ffi::FT_Err_Stack_Underflow, Ignore = ffi::FT_Err_Ignore, NoUnicodeGlyphName = ffi::FT_Err_No_Unicode_Glyph_Name, MissingStartfontField = ffi::FT_Err_Missing_Startfont_Field, MissingFontField = ffi::FT_Err_Missing_Font_Field, MissingSizeField = ffi::FT_Err_Missing_Size_Field, MissingFontboundingboxField = ffi::FT_Err_Missing_Fontboundingbox_Field, MissingCharsField = ffi::FT_Err_Missing_Chars_Field, MissingStartcharField = ffi::FT_Err_Missing_Startchar_Field, MissingEncodingField = ffi::FT_Err_Missing_Encoding_Field, MissingBbxField = ffi::FT_Err_Missing_Bbx_Field, BbxTooBig = ffi::FT_Err_Bbx_Too_Big, CorruptedFontHeader = ffi::FT_Err_Corrupted_Font_Header, CorruptedFontGlyphs = ffi::FT_Err_Corrupted_Font_Glyphs, Max = ffi::FT_Err_Max, UnexpectedPixelMode, InvalidPath, Unknown, } impl From for Error { fn from(err: i32) -> Self { match err { ffi::FT_Err_Ok => Error::Ok, ffi::FT_Err_Cannot_Open_Resource => Error::CannotOpenResource, ffi::FT_Err_Unknown_File_Format => Error::UnknownFileFormat, ffi::FT_Err_Invalid_File_Format => Error::InvalidFileFormat, ffi::FT_Err_Invalid_Version => Error::InvalidVersion, ffi::FT_Err_Lower_Module_Version => Error::LowerModuleVersion, ffi::FT_Err_Invalid_Argument => Error::InvalidArgument, ffi::FT_Err_Unimplemented_Feature => Error::UnimplementedFeature, ffi::FT_Err_Invalid_Table => Error::InvalidTable, ffi::FT_Err_Invalid_Offset => Error::InvalidOffset, ffi::FT_Err_Array_Too_Large => Error::ArrayTooLarge, ffi::FT_Err_Missing_Module => Error::MissingModule, ffi::FT_Err_Missing_Property => Error::MissingProperty, ffi::FT_Err_Invalid_Glyph_Index => Error::InvalidGlyphIndex, ffi::FT_Err_Invalid_Character_Code => Error::InvalidCharacterCode, ffi::FT_Err_Invalid_Glyph_Format => Error::InvalidGlyphFormat, ffi::FT_Err_Cannot_Render_Glyph => Error::CannotRenderGlyph, ffi::FT_Err_Invalid_Outline => Error::InvalidOutline, ffi::FT_Err_Invalid_Composite => Error::InvalidComposite, ffi::FT_Err_Too_Many_Hints => Error::TooManyHints, ffi::FT_Err_Invalid_Pixel_Size => Error::InvalidPixelSize, ffi::FT_Err_Invalid_Handle => Error::InvalidHandle, ffi::FT_Err_Invalid_Library_Handle => Error::InvalidLibraryHandle, ffi::FT_Err_Invalid_Driver_Handle => Error::InvalidDriverHandle, ffi::FT_Err_Invalid_Face_Handle => Error::InvalidFaceHandle, ffi::FT_Err_Invalid_Size_Handle => Error::InvalidSizeHandle, ffi::FT_Err_Invalid_Slot_Handle => Error::InvalidSlotHandle, ffi::FT_Err_Invalid_CharMap_Handle => Error::InvalidCharMapHandle, ffi::FT_Err_Invalid_Cache_Handle => Error::InvalidCacheHandle, ffi::FT_Err_Invalid_Stream_Handle => Error::InvalidStreamHandle, ffi::FT_Err_Too_Many_Drivers => Error::TooManyDrivers, ffi::FT_Err_Too_Many_Extensions => Error::TooManyExtensions, ffi::FT_Err_Out_Of_Memory => Error::OutOfMemory, ffi::FT_Err_Unlisted_Object => Error::UnlistedObject, ffi::FT_Err_Cannot_Open_Stream => Error::CannotOpenStream, ffi::FT_Err_Invalid_Stream_Seek => Error::InvalidStreamSeek, ffi::FT_Err_Invalid_Stream_Skip => Error::InvalidStreamSkip, ffi::FT_Err_Invalid_Stream_Read => Error::InvalidStreamRead, ffi::FT_Err_Invalid_Stream_Operation => Error::InvalidStreamOperation, ffi::FT_Err_Invalid_Frame_Operation => Error::InvalidFrameOperation, ffi::FT_Err_Nested_Frame_Access => Error::NestedFrameAccess, ffi::FT_Err_Invalid_Frame_Read => Error::InvalidFrameRead, ffi::FT_Err_Raster_Uninitialized => Error::RasterUninitialized, ffi::FT_Err_Raster_Corrupted => Error::RasterCorrupted, ffi::FT_Err_Raster_Overflow => Error::RasterOverflow, ffi::FT_Err_Raster_Negative_Height => Error::RasterNegativeHeight, ffi::FT_Err_Too_Many_Caches => Error::TooManyCaches, ffi::FT_Err_Invalid_Opcode => Error::InvalidOpcode, ffi::FT_Err_Too_Few_Arguments => Error::TooFewArguments, ffi::FT_Err_Stack_Overflow => Error::StackOverflow, ffi::FT_Err_Code_Overflow => Error::CodeOverflow, ffi::FT_Err_Bad_Argument => Error::BadArgument, ffi::FT_Err_Divide_By_Zero => Error::DivideByZero, ffi::FT_Err_Invalid_Reference => Error::InvalidReference, ffi::FT_Err_Debug_OpCode => Error::DebugOpCode, ffi::FT_Err_ENDF_In_Exec_Stream => Error::ENDFInExecStream, ffi::FT_Err_Nested_DEFS => Error::NestedDEFS, ffi::FT_Err_Invalid_CodeRange => Error::InvalidCodeRange, ffi::FT_Err_Execution_Too_Long => Error::ExecutionTooLong, ffi::FT_Err_Too_Many_Function_Defs => Error::TooManyFunctionDefs, ffi::FT_Err_Too_Many_Instruction_Defs => Error::TooManyInstructionDefs, ffi::FT_Err_Table_Missing => Error::TableMissing, ffi::FT_Err_Horiz_Header_Missing => Error::HorizHeaderMissing, ffi::FT_Err_Locations_Missing => Error::LocationsMissing, ffi::FT_Err_Name_Table_Missing => Error::NameTableMissing, ffi::FT_Err_CMap_Table_Missing => Error::CMapTableMissing, ffi::FT_Err_Hmtx_Table_Missing => Error::HmtxTableMissing, ffi::FT_Err_Post_Table_Missing => Error::PostTableMissing, ffi::FT_Err_Invalid_Horiz_Metrics => Error::InvalidHorizMetrics, ffi::FT_Err_Invalid_CharMap_Format => Error::InvalidCharMapFormat, ffi::FT_Err_Invalid_PPem => Error::InvalidPPem, ffi::FT_Err_Invalid_Vert_Metrics => Error::InvalidVertMetrics, ffi::FT_Err_Could_Not_Find_Context => Error::CouldNotFindContext, ffi::FT_Err_Invalid_Post_Table_Format => Error::InvalidPostTableFormat, ffi::FT_Err_Invalid_Post_Table => Error::InvalidPostTable, ffi::FT_Err_Syntax_Error => Error::Syntax, ffi::FT_Err_Stack_Underflow => Error::StackUnderflow, ffi::FT_Err_Ignore => Error::Ignore, ffi::FT_Err_No_Unicode_Glyph_Name => Error::NoUnicodeGlyphName, ffi::FT_Err_Missing_Startfont_Field => Error::MissingStartfontField, ffi::FT_Err_Missing_Font_Field => Error::MissingFontField, ffi::FT_Err_Missing_Size_Field => Error::MissingSizeField, ffi::FT_Err_Missing_Fontboundingbox_Field => Error::MissingFontboundingboxField, ffi::FT_Err_Missing_Chars_Field => Error::MissingCharsField, ffi::FT_Err_Missing_Startchar_Field => Error::MissingStartcharField, ffi::FT_Err_Missing_Encoding_Field => Error::MissingEncodingField, ffi::FT_Err_Missing_Bbx_Field => Error::MissingBbxField, ffi::FT_Err_Bbx_Too_Big => Error::BbxTooBig, ffi::FT_Err_Corrupted_Font_Header => Error::CorruptedFontHeader, ffi::FT_Err_Corrupted_Font_Glyphs => Error::CorruptedFontGlyphs, ffi::FT_Err_Max => Error::Max, _ => Error::Unknown, } } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::Error::*; f.write_str(match *self { Ok => "Ok", CannotOpenResource => "Cannot open resource", UnknownFileFormat => "Unknown file format", InvalidFileFormat => "Invalid file format", InvalidVersion => "Invalid version", LowerModuleVersion => "Lower module version", InvalidArgument => "Invalid argument", UnimplementedFeature => "Unimplemented feature", InvalidTable => "Invalid table", InvalidOffset => "Invalid offset", ArrayTooLarge => "Array too large", MissingModule => "Missing module", MissingProperty => "Missing property", InvalidGlyphIndex => "Invalid glyph index", InvalidCharacterCode => "Invalid character code", InvalidGlyphFormat => "Invalid glyph format", CannotRenderGlyph => "Cannot render glyph", InvalidOutline => "Invalid outline", InvalidComposite => "Invalid composite", TooManyHints => "Too many hints", InvalidPixelSize => "Invalid pixel size", InvalidHandle => "Invalid handle", InvalidLibraryHandle => "Invalid library handle", InvalidDriverHandle => "Invalid driver handle", InvalidFaceHandle => "Invalid face handle", InvalidSizeHandle => "Invalid size handle", InvalidSlotHandle => "Invalid slot handle", InvalidCharMapHandle => "Invalid char map handle", InvalidCacheHandle => "Invalid cache handle", InvalidStreamHandle => "Invalid stream handle", TooManyDrivers => "Too many drivers", TooManyExtensions => "Too many extensions", OutOfMemory => "Out of memory", UnlistedObject => "Unlisted object", CannotOpenStream => "Cannot open stream", InvalidStreamSeek => "Invalid stream seek", InvalidStreamSkip => "Invalid stream skip", InvalidStreamRead => "Invalid stream read", InvalidStreamOperation => "Invalid stream operation", InvalidFrameOperation => "Invalid frame operation", NestedFrameAccess => "Nested frame access", InvalidFrameRead => "Invalid frame read", RasterUninitialized => "Raster uninitialized", RasterCorrupted => "Raster corrupted", RasterOverflow => "Raster overflow", RasterNegativeHeight => "Raster negative height", TooManyCaches => "Too many caches", InvalidOpcode => "Invalid opcode", TooFewArguments => "Too few arguments", StackOverflow => "Stack overflow", CodeOverflow => "Code overflow", BadArgument => "Bad argument", DivideByZero => "Divide by zero", InvalidReference => "Invalid reference", DebugOpCode => "Debug op code", ENDFInExecStream => "ENDF in exec stream", NestedDEFS => "Nested DEFS", InvalidCodeRange => "Invalid code range", ExecutionTooLong => "Execution too long", TooManyFunctionDefs => "Too many function defs", TooManyInstructionDefs => "Too many instruction defs", TableMissing => "Table missing", HorizHeaderMissing => "Horiz header missing", LocationsMissing => "Locations missing", NameTableMissing => "Name table missing", CMapTableMissing => "C map table missing", HmtxTableMissing => "Hmtx table missing", PostTableMissing => "Post table missing", InvalidHorizMetrics => "Invalid horiz metrics", InvalidCharMapFormat => "Invalid char map format", InvalidPPem => "Invalid p pem", InvalidVertMetrics => "Invalid vert metrics", CouldNotFindContext => "Could not find context", InvalidPostTableFormat => "Invalid post table format", InvalidPostTable => "Invalid post table", Syntax => "Syntax", StackUnderflow => "Stack underflow", Ignore => "Ignore", NoUnicodeGlyphName => "No unicode glyph name", MissingStartfontField => "Missing startfont field", MissingFontField => "Missing font field", MissingSizeField => "Missing size field", MissingFontboundingboxField => "Missing fontboundingbox field", MissingCharsField => "Missing chars field", MissingStartcharField => "Missing startchar field", MissingEncodingField => "Missing encoding field", MissingBbxField => "Missing bbx field", BbxTooBig => "Bbx too big", CorruptedFontHeader => "Corrupted font header", CorruptedFontGlyphs => "Corrupted font glyphs", Max => "Max", UnexpectedPixelMode => "Unexpected pixel mode", InvalidPath => "Invalid path", Unknown => "Unknown", }) } } impl error::Error for Error {} #[cfg(test)] mod tests { use super::*; #[test] fn print_should_halt() { use std::error::Error as _; Error::Ok.to_string(); #[allow(deprecated)] Error::Ok.description(); } } freetype-rs-0.36.0/src/face.rs000064400000000000000000000327661046102023000142300ustar 00000000000000use std::ffi::{CStr, CString}; use std::fmt; use std::num::NonZeroU32; use std::rc::Rc; use crate::charmap::CharMap; use {ffi, FtResult, GlyphSlot, Matrix, Vector}; #[repr(u32)] #[derive(Copy, Clone)] pub enum KerningMode { KerningDefault = ffi::FT_KERNING_DEFAULT, KerningUnfitted = ffi::FT_KERNING_UNFITTED, KerningUnscaled = ffi::FT_KERNING_UNSCALED, } bitflags! { #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct LoadFlag: i32 { const DEFAULT = ::ffi::FT_LOAD_DEFAULT; const NO_SCALE = ::ffi::FT_LOAD_NO_SCALE; const NO_HINTING = ::ffi::FT_LOAD_NO_HINTING; const RENDER = ::ffi::FT_LOAD_RENDER; const NO_BITMAP = ::ffi::FT_LOAD_NO_BITMAP; const VERTICAL_LAYOUT = ::ffi::FT_LOAD_VERTICAL_LAYOUT; const FORCE_AUTOHINT = ::ffi::FT_LOAD_FORCE_AUTOHINT; const CROP_BITMAP = ::ffi::FT_LOAD_CROP_BITMAP; const PEDANTIC = ::ffi::FT_LOAD_PEDANTIC; const IGNORE_GLOBAL_ADVANCE_WITH = ::ffi::FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; const NO_RECURSE = ::ffi::FT_LOAD_NO_RECURSE; const IGNORE_TRANSFORM = ::ffi::FT_LOAD_IGNORE_TRANSFORM; const MONOCHROME = ::ffi::FT_LOAD_MONOCHROME; const LINEAR_DESIGN = ::ffi::FT_LOAD_LINEAR_DESIGN; const NO_AUTOHINT = ::ffi::FT_LOAD_NO_AUTOHINT; const TARGET_NORMAL = ::ffi::FT_LOAD_TARGET_NORMAL; const TARGET_LIGHT = ::ffi::FT_LOAD_TARGET_LIGHT; const TARGET_MONO = ::ffi::FT_LOAD_TARGET_MONO; const TARGET_LCD = ::ffi::FT_LOAD_TARGET_LCD; const TARGET_LCD_V = ::ffi::FT_LOAD_TARGET_LCD_V; const COLOR = ::ffi::FT_LOAD_COLOR; } } bitflags! { #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct StyleFlag: ffi::FT_Long { const BOLD = ::ffi::FT_STYLE_FLAG_BOLD; const ITALIC = ::ffi::FT_STYLE_FLAG_ITALIC; } } pub struct CharIterator<'a, BYTES> { started: bool, face: &'a Face, gindex: ffi::FT_UInt, charcode: ffi::FT_ULong, } impl<'a, BYTES> CharIterator<'a, BYTES> { fn new(face: &'a Face) -> Self { CharIterator { started: false, face, gindex: 0, charcode: 0, } } } impl<'a, BYTES> Iterator for CharIterator<'a, BYTES> { type Item = (usize, NonZeroU32); fn next(&mut self) -> Option { // Implementing per https://freetype.org/freetype2/docs/reference/ft2-character_mapping.html#ft_get_first_char // FT_UInt gindex; // FT_ULong charcode = FT_Get_First_Char( face, &gindex ); // while ( gindex != 0 ) { // ... do something with (charcode,gindex) pair ... // charcode = FT_Get_Next_Char( face, charcode, &gindex ); // } if self.started { self.charcode = unsafe { ffi::FT_Get_Next_Char(self.face.raw, self.charcode, &mut self.gindex) }; } else { self.started = true; self.charcode = unsafe { ffi::FT_Get_First_Char(self.face.raw, &mut self.gindex) }; } if self.gindex == 0 { None } else { NonZeroU32::new(self.gindex).map(|gindex| (self.charcode as usize, gindex)) } } // TODO: implement size_hint } #[derive(Eq, PartialEq, Hash)] pub struct Face>> { library_raw: ffi::FT_Library, raw: ffi::FT_Face, glyph: GlyphSlot, bytes: Option, } impl Clone for Face { fn clone(&self) -> Self { let err = unsafe { ffi::FT_Reference_Library(self.library_raw) }; if err != ffi::FT_Err_Ok { panic!("Failed to reference library"); } let err = unsafe { ffi::FT_Reference_Face(self.raw) }; if err != ffi::FT_Err_Ok { panic!("Failed to reference face"); } Face { library_raw: self.library_raw, raw: self.raw, glyph: self.glyph, bytes: self.bytes.clone(), } } } impl Face { pub unsafe fn from_raw( library_raw: ffi::FT_Library, raw: ffi::FT_Face, bytes: Option, ) -> Self { ffi::FT_Reference_Library(library_raw); Face { library_raw, raw, glyph: GlyphSlot::from_raw(library_raw, (*raw).glyph), bytes, } } pub fn attach_file(&self, filepathname: &str) -> FtResult<()> { let err = unsafe { ffi::FT_Attach_File(self.raw, filepathname.as_ptr() as *const _) }; if err == ffi::FT_Err_Ok { Ok(()) } else { Err(err.into()) } } pub fn reference(&self) -> FtResult<()> { let err = unsafe { ffi::FT_Reference_Face(self.raw) }; if err == ffi::FT_Err_Ok { Ok(()) } else { Err(err.into()) } } pub fn set_char_size( &self, char_width: isize, char_height: isize, horz_resolution: u32, vert_resolution: u32, ) -> FtResult<()> { let err = unsafe { ffi::FT_Set_Char_Size( self.raw, char_width as ffi::FT_F26Dot6, char_height as ffi::FT_F26Dot6, horz_resolution, vert_resolution, ) }; if err == ffi::FT_Err_Ok { Ok(()) } else { Err(err.into()) } } pub fn set_pixel_sizes(&self, pixel_width: u32, pixel_height: u32) -> FtResult<()> { let err = unsafe { ffi::FT_Set_Pixel_Sizes(self.raw, pixel_width, pixel_height) }; if err == ffi::FT_Err_Ok { Ok(()) } else { Err(err.into()) } } pub fn load_glyph(&self, glyph_index: u32, load_flags: LoadFlag) -> FtResult<()> { let err = unsafe { ffi::FT_Load_Glyph(self.raw, glyph_index, load_flags.bits()) }; if err == ffi::FT_Err_Ok { Ok(()) } else { Err(err.into()) } } pub fn load_char(&self, char_code: usize, load_flags: LoadFlag) -> FtResult<()> { let err = unsafe { ffi::FT_Load_Char(self.raw, char_code as ffi::FT_ULong, load_flags.bits()) }; if err == ffi::FT_Err_Ok { Ok(()) } else { Err(err.into()) } } pub fn set_transform(&self, matrix: &mut Matrix, delta: &mut Vector) { unsafe { ffi::FT_Set_Transform(self.raw, matrix, delta); } } pub fn get_char_index(&self, charcode: usize) -> Option { let res = unsafe { ffi::FT_Get_Char_Index(self.raw, charcode as ffi::FT_ULong) }; if res == 0 { None } else { Some(res) } } pub fn get_name_index(&self, glyph_name: &str) -> Option { if !ffi::FT_HAS_GLYPH_NAMES(self.raw) { return None; } match CString::new(glyph_name) { Ok(name) => { Some(unsafe { ffi::FT_Get_Name_Index(self.raw, name.as_ptr() as *const _) }) } Err(_) => None, } } pub fn chars(&self) -> CharIterator<'_, BYTES> { CharIterator::new(self) } pub fn get_kerning( &self, left_char_index: u32, right_char_index: u32, kern_mode: KerningMode, ) -> FtResult { let mut vec = Vector { x: 0, y: 0 }; let err = unsafe { ffi::FT_Get_Kerning( self.raw, left_char_index, right_char_index, kern_mode as u32, &mut vec, ) }; if err == ffi::FT_Err_Ok { Ok(vec) } else { Err(err.into()) } } pub fn get_charmap(&self, charmap_index: isize) -> CharMap { let charmap = unsafe { *self.raw().charmaps.offset(charmap_index) }; CharMap::new(charmap) } pub fn set_charmap(&self, charmap: &CharMap) -> FtResult<()> { let err = unsafe { ffi::FT_Set_Charmap(self.raw, charmap.raw()) }; if err == ffi::FT_Err_Ok { Ok(()) } else { Err(err.into()) } } // According to FreeType doc, each time you load a new glyph image, // the previous one is erased from the glyph slot. #[inline(always)] pub fn glyph(&self) -> &GlyphSlot { &self.glyph } #[inline(always)] pub fn has_horizontal(&self) -> bool { ffi::FT_HAS_HORIZONTAL(self.raw) } #[inline(always)] pub fn has_vertical(&self) -> bool { ffi::FT_HAS_VERTICAL(self.raw) } #[inline(always)] pub fn has_kerning(&self) -> bool { ffi::FT_HAS_KERNING(self.raw) } #[inline(always)] pub fn is_scalable(&self) -> bool { ffi::FT_IS_SCALABLE(self.raw) } #[inline(always)] pub fn is_sfnt(&self) -> bool { ffi::FT_IS_SFNT(self.raw) } #[inline(always)] pub fn is_fixed_width(&self) -> bool { ffi::FT_IS_FIXED_WIDTH(self.raw) } #[inline(always)] pub fn has_fixed_sizes(&self) -> bool { ffi::FT_HAS_FIXED_SIZES(self.raw) } #[inline(always)] pub fn has_glyph_names(&self) -> bool { ffi::FT_HAS_GLYPH_NAMES(self.raw) } #[inline(always)] pub fn is_cid_keyed(&self) -> bool { ffi::FT_IS_CID_KEYED(self.raw) } #[inline(always)] pub fn is_tricky(&self) -> bool { ffi::FT_IS_TRICKY(self.raw) } #[inline(always)] pub fn has_color(&self) -> bool { ffi::FT_HAS_COLOR(self.raw) } #[inline(always)] pub fn raw(&self) -> &ffi::FT_FaceRec { unsafe { &*self.raw } } #[inline(always)] pub fn raw_mut(&mut self) -> &mut ffi::FT_FaceRec { unsafe { &mut *self.raw } } #[inline(always)] pub fn ascender(&self) -> ffi::FT_Short { unsafe { (*self.raw).ascender } } #[inline(always)] pub fn num_charmaps(&self) -> i32 { unsafe { (*self.raw).num_charmaps } } #[inline(always)] pub fn descender(&self) -> ffi::FT_Short { unsafe { (*self.raw).descender } } #[inline(always)] pub fn em_size(&self) -> ffi::FT_Short { unsafe { (*self.raw).units_per_EM as i16 } } #[inline(always)] pub fn height(&self) -> ffi::FT_Short { unsafe { (*self.raw).height } } #[inline(always)] pub fn max_advance_width(&self) -> ffi::FT_Short { unsafe { (*self.raw).max_advance_width } } #[inline(always)] pub fn max_advance_height(&self) -> ffi::FT_Short { unsafe { (*self.raw).max_advance_height } } #[inline(always)] pub fn underline_position(&self) -> ffi::FT_Short { unsafe { (*self.raw).underline_position } } #[inline(always)] pub fn underline_thickness(&self) -> ffi::FT_Short { unsafe { (*self.raw).underline_thickness } } #[inline(always)] pub fn num_faces(&self) -> ffi::FT_Short { unsafe { (*self.raw).num_faces as i16 } } #[inline(always)] pub fn num_glyphs(&self) -> ffi::FT_Long { unsafe { (*self.raw).num_glyphs } } pub fn family_name(&self) -> Option { let family_name = unsafe { (*self.raw).family_name }; if family_name.is_null() { None } else { let family_name = unsafe { CStr::from_ptr(family_name as *const _).to_bytes().to_vec() }; String::from_utf8(family_name).ok() } } pub fn style_name(&self) -> Option { let style_name = unsafe { (*self.raw).style_name }; if style_name.is_null() { None } else { let style_name = unsafe { CStr::from_ptr(style_name as *const _).to_bytes().to_vec() }; String::from_utf8(style_name).ok() } } pub fn style_flags(&self) -> StyleFlag { let style_flags = unsafe { (*self.raw).style_flags }; StyleFlag::from_bits_truncate(style_flags) } pub fn size_metrics(&self) -> Option { if self.raw.is_null() { None } else { let size = unsafe { (*self.raw).size }; if size.is_null() { None } else { Some(unsafe { (*size).metrics }) } } } pub fn postscript_name(&self) -> Option { let face_name = unsafe { ffi::FT_Get_Postscript_Name(self.raw) }; if face_name.is_null() { None } else { let face_name = unsafe { CStr::from_ptr(face_name as *const _).to_bytes().to_vec() }; String::from_utf8(face_name).ok() } } } impl fmt::Debug for Face { fn fmt(&self, form: &mut fmt::Formatter) -> fmt::Result { let name = self.style_name().unwrap_or("[unknown name]".to_owned()); form.write_str("Font Face: ")?; form.write_str(&name[..]) } } impl Drop for Face { fn drop(&mut self) { let err = unsafe { ffi::FT_Done_Face(self.raw) }; if err != ffi::FT_Err_Ok { panic!("Failed to drop face"); } let err = unsafe { ffi::FT_Done_Library(self.library_raw) }; if err != ffi::FT_Err_Ok { panic!("Failed to drop library") } self.bytes = None; } } freetype-rs-0.36.0/src/glyph.rs000064400000000000000000000121521046102023000144400ustar 00000000000000use std::ptr::null_mut; use {ffi, BBox, BitmapGlyph, FtResult, Matrix, RenderMode, Stroker, Vector}; /// Represents a retrieved glyph from the library /// /// Note that when this glyph is dropped, so is the library pub struct Glyph { library_raw: ffi::FT_Library, raw: ffi::FT_Glyph, } impl Glyph { /// Create a freetype-rs glyph object from c constituent parts pub unsafe fn from_raw(library_raw: ffi::FT_Library, raw: ffi::FT_Glyph) -> Self { ffi::FT_Reference_Library(library_raw); Glyph { library_raw, raw } } /// Transform a glyph image if its format is scalable. pub fn transform(&self, mut matrix: Option, mut delta: Option) -> FtResult<()> { let mut p_matrix = null_mut(); let mut p_delta = null_mut(); if let Some(ref mut m) = matrix { p_matrix = m as *mut Matrix; } if let Some(ref mut d) = delta { p_delta = d as *mut Vector; } let err = unsafe { ffi::FT_Glyph_Transform(self.raw, p_matrix, p_delta) }; if err == ffi::FT_Err_Ok { Ok(()) } else { Err(err.into()) } } /// Return a glyph's ‘control box’. The control box encloses all the outline's points, /// including Bézier control points. Though it coincides with the exact bounding box for most /// glyphs, it can be slightly larger in some situations (like when rotating an outline that /// contains Bézier outside arcs). /// /// Computing the control box is very fast, while getting the bounding box can take much more /// time as it needs to walk over all segments and arcs in the outline. To get the latter, you /// can use the ‘ftbbox’ component, which is dedicated to this single task. pub fn get_cbox(&self, bbox_mode: ffi::FT_Glyph_BBox_Mode) -> BBox { let mut acbox = ffi::FT_BBox { xMin: 0, yMin: 0, xMax: 0, yMax: 0, }; unsafe { ffi::FT_Glyph_Get_CBox(self.raw, bbox_mode, &mut acbox) }; acbox } /// Convert a given glyph object to a bitmap glyph object. pub fn to_bitmap( &self, render_mode: RenderMode, mut origin: Option, ) -> FtResult { let mut the_glyph = self.raw; let mut p_origin = null_mut(); if let Some(ref mut o) = origin { p_origin = o as *mut Vector; } let err = unsafe { ffi::FT_Glyph_To_Bitmap(&mut the_glyph, render_mode as u32, p_origin, 0) }; if err == ffi::FT_Err_Ok { Ok( unsafe { BitmapGlyph::from_raw(self.library_raw, the_glyph as ffi::FT_BitmapGlyph) }, ) } else { Err(err.into()) } } pub fn stroke(&self, stroker: &Stroker) -> FtResult { let mut the_glyph = self.raw; let err = unsafe { ffi::FT_Glyph_Stroke(&mut the_glyph, stroker.raw_stroker(), false as ffi::FT_Bool) }; if err == ffi::FT_Err_Ok { Ok(unsafe { Glyph::from_raw(self.library_raw, the_glyph) }) } else { Err(err.into()) } } pub fn stroke_border(&self, stroker: &Stroker, inside: bool) -> FtResult { let mut the_glyph = self.raw; let err = unsafe { ffi::FT_Glyph_StrokeBorder( &mut the_glyph, stroker.raw_stroker(), inside as ffi::FT_Bool, false as ffi::FT_Bool, ) }; if err == ffi::FT_Err_Ok { Ok(unsafe { Glyph::from_raw(self.library_raw, the_glyph) }) } else { Err(err.into()) } } pub fn advance_x(&self) -> isize { unsafe { (*self.raw).advance.x as isize } } pub fn advance_y(&self) -> isize { unsafe { (*self.raw).advance.y as isize } } /// An enumeration type used to describe the format of a given glyph image. Note that this /// version of FreeType only supports two image formats, even though future font drivers will /// be able to register their own format. #[inline(always)] pub fn format(&self) -> ffi::FT_Glyph_Format { unsafe { (*self.raw).format } } /// Get the underlying c glyph struct (The system actually calls this a GlyphRec because it can /// be a different struct in different circumstances) #[inline(always)] pub fn raw(&self) -> &ffi::FT_GlyphRec { unsafe { &*self.raw } } } impl Clone for Glyph { fn clone(&self) -> Self { let mut target = null_mut(); let err = unsafe { ffi::FT_Glyph_Copy(self.raw, &mut target) }; if err == ffi::FT_Err_Ok { unsafe { Glyph::from_raw(self.library_raw, target) } } else { panic!("Failed to copy glyph") } } } impl Drop for Glyph { fn drop(&mut self) { let err = unsafe { ffi::FT_Done_Glyph(self.raw); ffi::FT_Done_Library(self.library_raw) }; if err != ffi::FT_Err_Ok { panic!("Failed to drop library") } } } freetype-rs-0.36.0/src/glyph_slot.rs000064400000000000000000000137261046102023000155110ustar 00000000000000use std::ptr::null_mut; use {ffi, Bitmap, FtResult, Glyph, GlyphMetrics, Outline, RenderMode, Vector}; /// A description of a given subglyph returned by `GlyphSlot::get_subglyph_info` /// function. #[derive(Copy, Clone)] pub struct SubGlyphInfo { /// The glyph index of the subglyph. pub index: i32, /// The subglyph flags, see FT_SUBGLYPH_FLAG_XXX. pub flags: u32, /// The subglyph's first argument (if any). pub arg1: i32, /// The subglyph's second argument (if any). pub arg2: i32, /// The subglyph transformation (if any). pub transform: ffi::FT_Matrix, } impl Default for SubGlyphInfo { fn default() -> Self { SubGlyphInfo { index: 0, flags: 0, arg1: 0, arg2: 0, transform: ffi::FT_Matrix { xx: 0, xy: 0, yx: 0, yy: 0, }, } } } /// A struct encapsulating the space for a glyph within a `Library` #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct GlyphSlot { library_raw: ffi::FT_Library, raw: ffi::FT_GlyphSlot, } impl GlyphSlot { /// Create a `GlyphSlot` from its constituent C parts pub unsafe fn from_raw(library_raw: ffi::FT_Library, raw: ffi::FT_GlyphSlot) -> Self { GlyphSlot { library_raw, raw } } /// Convert a given glyph image to a bitmap. It does so by inspecting the glyph image format, /// finding the relevant renderer, and invoking it. pub fn render_glyph(&self, render_mode: RenderMode) -> FtResult<()> { let err = unsafe { ffi::FT_Render_Glyph(self.raw, render_mode as u32) }; if err == ffi::FT_Err_Ok { Ok(()) } else { Err(err.into()) } } /// Retrieve a description of a given subglyph. Only use it if the glyph's format is /// FT_GLYPH_FORMAT_COMPOSITE; an error is returned otherwise. pub fn get_subglyph_info(&self, sub_index: u32) -> FtResult { let mut info = SubGlyphInfo::default(); let err = unsafe { ffi::FT_Get_SubGlyph_Info( self.raw, sub_index, &mut info.index, &mut info.flags, &mut info.arg1, &mut info.arg2, &mut info.transform, ) }; if err == ffi::FT_Err_Ok { Ok(info) } else { Err(err.into()) } } /// Returns a glyph object, that is similar to a `GlyphSlot` but managed outside of the library pub fn get_glyph(&self) -> FtResult { let mut aglyph = null_mut(); let err = unsafe { ffi::FT_Get_Glyph(self.raw, &mut aglyph) }; if err == ffi::FT_Err_Ok { Ok(unsafe { Glyph::from_raw(self.library_raw, aglyph) }) } else { Err(err.into()) } } /// In freetype, the `Outline` object is a scalable glyph. This method unpacks a glyph into /// this object, or returns `None` if the glyph has no `outline` pub fn outline(&self) -> Option { let outline = unsafe { &(*self.raw).outline }; let format = unsafe { (*self.raw).format }; if format == ffi::FT_GLYPH_FORMAT_OUTLINE { let outline = unsafe { Outline::from_raw(outline) }; Some(outline) } else { None } } /// This field is used as a bitmap descriptor when the slot format is FT_GLYPH_FORMAT_BITMAP. /// Note that the address and content of the bitmap buffer can change between calls of /// FT_Load_Glyph and a few other functions. #[inline(always)] pub fn bitmap(&self) -> Bitmap { unsafe { Bitmap::from_raw(&(*self.raw).bitmap) } } /// The bitmap's left bearing expressed in integer pixels. Only valid if the format is /// FT_GLYPH_FORMAT_BITMAP, this is, if the glyph slot contains a bitmap. #[inline(always)] pub fn bitmap_left(&self) -> i32 { unsafe { (*self.raw).bitmap_left } } /// The bitmap's top bearing expressed in integer pixels. Remember that this is the distance /// from the baseline to the top-most glyph scanline, upwards y coordinates being positive. #[inline(always)] pub fn bitmap_top(&self) -> i32 { unsafe { (*self.raw).bitmap_top } } /// This shorthand is, depending on FT_LOAD_IGNORE_TRANSFORM, the transformed (hinted) advance /// width for the glyph, in 26.6 fractional pixel format. As specified with /// FT_LOAD_VERTICAL_LAYOUT, it uses either the ‘horiAdvance’ or the ‘vertAdvance’ value of /// ‘metrics’ field. #[inline(always)] pub fn advance(&self) -> Vector { unsafe { (*self.raw).advance } } /// The advance width of the unhinted glyph. Its value is expressed in 16.16 fractional pixels, /// unless FT_LOAD_LINEAR_DESIGN is set when loading the glyph. This field can be important to /// perform correct WYSIWYG layout. Only relevant for outline glyphs. #[inline(always)] pub fn linear_hori_advance(&self) -> ffi::FT_Fixed { unsafe { (*self.raw).linearHoriAdvance } } /// The advance height of the unhinted glyph. Its value is expressed in 16.16 fractional /// pixels, unless FT_LOAD_LINEAR_DESIGN is set when loading the glyph. This field can be /// important to perform correct WYSIWYG layout. Only relevant for outline glyphs. #[inline(always)] pub fn linear_vert_advance(&self) -> ffi::FT_Fixed { unsafe { (*self.raw).linearVertAdvance } } /// The metrics of the last loaded glyph in the slot. The returned values depend on the last /// load flags (see the FT_Load_Glyph API function) and can be expressed either in 26.6 /// fractional pixels or font units. #[inline(always)] pub fn metrics(&self) -> GlyphMetrics { unsafe { (*self.raw).metrics } } /// Get a pointer to the underlying c struct #[inline(always)] pub fn raw(&self) -> &ffi::FT_GlyphSlotRec { unsafe { &*self.raw } } } freetype-rs-0.36.0/src/lib.rs000064400000000000000000000036511046102023000140670ustar 00000000000000//! //! Rust wrapper around freetype 2 library //! //! # Initialization //! //! To create a new freetype context, instantiate the Library struct as below. //! The Library (along with other objects) obeys RAII and is dropped when the struct goes out of //! scope. //! //! # Example //! //! ```ignore //! extern crate freetype; //! //! fn main() { //! use freetype::Library; //! use freetype::face::LoadFlag; //! //! // Init the library //! let lib = Library::init().unwrap(); //! // Load a font face //! let face = lib.new_face("/path/to/a/font/file.ttf", 0).unwrap(); //! // Set the font size //! face.set_char_size(40 * 64, 0, 50, 0).unwrap(); //! // Load a character //! face.load_char('A' as usize, LoadFlag::RENDER).unwrap(); //! // Get the glyph instance //! let glyph = face.glyph(); //! do_something_with_bitmap(glyph.bitmap()); //! } //! ``` //! //! See in the `examples/` folder for more examples. //! //! # External links //! - See [freetype docs](http://www.freetype.org/freetype2/docs/reference/ft2-index.html) //! for more information #![deny(missing_copy_implementations)] #[macro_use] extern crate bitflags; pub extern crate freetype_sys; extern crate libc; pub use bitmap::Bitmap; pub use bitmap_glyph::BitmapGlyph; pub use error::{Error, FtResult}; pub use face::Face; pub use freetype_sys as ffi; pub use glyph::Glyph; pub use glyph_slot::GlyphSlot; pub use library::{LcdFilter, Library}; pub use outline::Outline; pub use render_mode::RenderMode; pub use stroker::{Stroker, StrokerLineCap, StrokerLineJoin}; pub mod bitmap; pub mod bitmap_glyph; pub mod charmap; pub mod error; pub mod face; pub mod glyph; pub mod glyph_slot; pub mod library; pub mod outline; pub mod render_mode; pub mod stroker; pub mod tt_os2; pub mod tt_postscript; pub type BBox = ffi::FT_BBox; pub type GlyphMetrics = ffi::FT_Glyph_Metrics; pub type Matrix = ffi::FT_Matrix; pub type Vector = ffi::FT_Vector; freetype-rs-0.36.0/src/library.rs000064400000000000000000000114151046102023000147620ustar 00000000000000use ffi; use libc::{self, c_long, c_void, size_t}; use std::borrow::Borrow; use std::ffi::{CString, OsStr}; use std::ptr::null_mut; use std::rc::Rc; use {Error, Face, FtResult, Stroker}; extern "C" fn alloc_library(_memory: ffi::FT_Memory, size: c_long) -> *mut c_void { unsafe { libc::malloc(size as size_t) } } extern "C" fn free_library(_memory: ffi::FT_Memory, block: *mut c_void) { unsafe { libc::free(block) } } extern "C" fn realloc_library( _memory: ffi::FT_Memory, _cur_size: c_long, new_size: c_long, block: *mut c_void, ) -> *mut c_void { unsafe { libc::realloc(block, new_size as size_t) } } #[repr(u32)] #[derive(Copy, Clone)] pub enum LcdFilter { LcdFilterNone = ffi::FT_LCD_FILTER_NONE, LcdFilterDefault = ffi::FT_LCD_FILTER_DEFAULT, LcdFilterLight = ffi::FT_LCD_FILTER_LIGHT, LcdFilterLegacy = ffi::FT_LCD_FILTER_LEGACY, } static mut MEMORY: ffi::FT_MemoryRec = ffi::FT_MemoryRec { user: 0 as *mut c_void, alloc: alloc_library, free: free_library, realloc: realloc_library, }; pub struct Library { raw: ffi::FT_Library, } impl Library { /// This function is used to create a new FreeType library instance and add the default /// modules. It returns a struct encapsulating the freetype library. The library is correctly /// discarded when the struct is dropped. pub fn init() -> FtResult { let mut raw = null_mut(); let err = unsafe { ffi::FT_New_Library(&mut MEMORY, &mut raw) }; if err == ffi::FT_Err_Ok { unsafe { ffi::FT_Add_Default_Modules(raw); } Ok(Library { raw }) } else { Err(err.into()) } } /// Open a font file using its pathname. `face_index` should be 0 if there is only 1 font /// in the file. pub fn new_face

(&self, path: P, face_index: isize) -> FtResult where P: AsRef, { let mut face = null_mut(); let path = path .as_ref() .to_str() .and_then(|s| CString::new(s).ok()) .ok_or(Error::InvalidPath)?; let err = unsafe { ffi::FT_New_Face( self.raw, path.as_ptr() as *const _, face_index as ffi::FT_Long, &mut face, ) }; if err == ffi::FT_Err_Ok { Ok(unsafe { Face::from_raw(self.raw, face, None) }) } else { Err(err.into()) } } pub fn new_stroker(&self) -> FtResult { let mut stroker = null_mut(); let err = unsafe { ffi::FT_Stroker_New(self.raw, &mut stroker) }; if err == ffi::FT_Err_Ok { Ok(unsafe { Stroker::from_raw(self.raw, stroker) }) } else { Err(err.into()) } } /// Similar to `new_face`, but loads file data from a byte array in memory pub fn new_memory_face(&self, buffer: T, face_index: isize) -> FtResult where T: Into>>, { let mut face = null_mut(); let buffer = buffer.into(); let err = unsafe { ffi::FT_New_Memory_Face( self.raw, buffer.as_ptr(), buffer.len() as ffi::FT_Long, face_index as ffi::FT_Long, &mut face, ) }; if err == ffi::FT_Err_Ok { Ok(unsafe { Face::from_raw(self.raw, face, Some(buffer)) }) } else { Err(err.into()) } } /// Similar to `new_face`, but loads file data from a byte array in memory pub fn new_memory_face2(&self, buffer: T, face_index: isize) -> FtResult> where T: Borrow<[u8]>, { let mut face = null_mut(); let buf = buffer.borrow(); let err = unsafe { ffi::FT_New_Memory_Face( self.raw, buf.as_ptr(), buf.len() as ffi::FT_Long, face_index as ffi::FT_Long, &mut face, ) }; if err == ffi::FT_Err_Ok { Ok(unsafe { Face::from_raw(self.raw, face, Some(buffer)) }) } else { Err(err.into()) } } pub fn set_lcd_filter(&self, lcd_filter: LcdFilter) -> FtResult<()> { let err = unsafe { ffi::FT_Library_SetLcdFilter(self.raw, lcd_filter as u32) }; if err == ffi::FT_Err_Ok { Ok(()) } else { Err(err.into()) } } /// Get the underlying library object pub fn raw(&self) -> ffi::FT_Library { self.raw } } impl Drop for Library { fn drop(&mut self) { let err = unsafe { ffi::FT_Done_Library(self.raw) }; if err != ffi::FT_Err_Ok { panic!("Failed to drop library") } } } freetype-rs-0.36.0/src/outline.rs000064400000000000000000000113621046102023000147760ustar 00000000000000use libc::{c_char, c_short}; use std::marker::PhantomData; use std::slice; use {ffi, Vector}; #[derive(Copy, Clone)] pub enum Curve { Line(Vector), Bezier2(Vector, Vector), Bezier3(Vector, Vector, Vector), } pub struct Outline<'a> { raw: &'a ffi::FT_Outline, } impl<'a> Outline<'a> { pub unsafe fn from_raw(raw: &'a ffi::FT_Outline) -> Self { Outline { raw } } pub fn points(&self) -> &'a [Vector] { unsafe { slice::from_raw_parts(self.raw.points, self.raw.n_points as usize) } } pub fn tags(&self) -> &'a [c_char] { unsafe { slice::from_raw_parts(self.raw.tags, self.raw.n_points as usize) } } pub fn contours(&self) -> &'a [c_short] { unsafe { slice::from_raw_parts(self.raw.contours, self.raw.n_contours as usize) } } pub fn contours_iter(&self) -> ContourIterator<'a> { unsafe { ContourIterator::from_raw(self.raw) } } } const TAG_ONCURVE: c_char = 0x01; const TAG_BEZIER3: c_char = 0x02; pub struct CurveIterator<'a> { start_point: *const Vector, start_tag: *const c_char, idx: isize, length: isize, marker: PhantomData<&'a ()>, } impl<'a> CurveIterator<'a> { pub unsafe fn from_raw(outline: &'a ffi::FT_Outline, start_idx: isize, end_idx: isize) -> Self { CurveIterator { start_point: outline.points.offset(start_idx), start_tag: outline.tags.offset(start_idx), idx: 0, length: end_idx - start_idx + 1, marker: PhantomData, } } pub fn start(&self) -> &'a Vector { unsafe { &*self.start_point } } // Retrieves the point at offset i from the current point. Note that contours implicitly repeat their // first point at the end. unsafe fn pt(&self, i: isize) -> Vector { if self.idx + i < self.length { *self.start_point.offset(self.idx + i) } else { *self.start_point } } unsafe fn tg(&self, i: isize) -> c_char { if self.idx + i < self.length { *self.start_tag.offset(self.idx + i) } else { *self.start_tag } } } impl<'a> Iterator for CurveIterator<'a> { type Item = Curve; fn next(&mut self) -> Option { if self.idx >= self.length { None } else { unsafe { let tag1 = self.tg(1); let (shift, curve) = if (tag1 & TAG_ONCURVE) == TAG_ONCURVE { (1, Curve::Line(self.pt(1))) } else if (tag1 & TAG_BEZIER3) == TAG_BEZIER3 { (3, Curve::Bezier3(self.pt(1), self.pt(2), self.pt(3))) } else { // We are some kind of quadratic Bezier. // Quadratic Bezier curves have a special treatment in TTF outlines: // as an optimization, curves are often constructed from sequences // of off-curve control points. In this case, there are implied on-curve // points in between each pair of off-curve points. if (self.tg(2) & TAG_ONCURVE) == TAG_ONCURVE { (2, Curve::Bezier2(self.pt(1), self.pt(2))) } else { let pt = ffi::FT_Vector { x: (self.pt(1).x + self.pt(2).x) / 2, y: (self.pt(1).y + self.pt(2).y) / 2, }; (1, Curve::Bezier2(self.pt(1), pt)) } }; self.idx += shift; Some(curve) } } } } pub struct ContourIterator<'a> { outline: &'a ffi::FT_Outline, contour_start: c_short, contour_end_idx: *const c_short, last_end_idx: *const c_short, } impl<'a> ContourIterator<'a> { pub unsafe fn from_raw(outline: &'a ffi::FT_Outline) -> Self { ContourIterator { outline, contour_start: 0, contour_end_idx: outline.contours, last_end_idx: outline.contours.offset(outline.n_contours as isize - 1), } } } impl<'a> Iterator for ContourIterator<'a> { type Item = CurveIterator<'a>; fn next(&mut self) -> Option { if self.contour_end_idx > self.last_end_idx { None } else { unsafe { let contour_end = *self.contour_end_idx; let curves = CurveIterator::from_raw( self.outline, self.contour_start as isize, contour_end as isize, ); self.contour_start = contour_end + 1; self.contour_end_idx = self.contour_end_idx.offset(1); Some(curves) } } } } freetype-rs-0.36.0/src/render_mode.rs000064400000000000000000000005121046102023000155750ustar 00000000000000use ffi; #[repr(u32)] #[derive(Copy, Clone)] pub enum RenderMode { Normal = ffi::FT_RENDER_MODE_NORMAL, Light = ffi::FT_RENDER_MODE_LIGHT, Mono = ffi::FT_RENDER_MODE_MONO, Lcd = ffi::FT_RENDER_MODE_LCD, LcdV = ffi::FT_RENDER_MODE_LCD_V, Sdf = ffi::FT_RENDER_MODE_SDF, Max = ffi::FT_RENDER_MODE_MAX, } freetype-rs-0.36.0/src/stroker.rs000064400000000000000000000033271046102023000150120ustar 00000000000000use ffi; #[repr(u32)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum StrokerLineCap { Butt = ffi::FT_STROKER_LINECAP_BUTT, Round = ffi::FT_STROKER_LINECAP_ROUND, Square = ffi::FT_STROKER_LINECAP_SQUARE, } #[repr(u32)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum StrokerLineJoin { Round = ffi::FT_STROKER_LINEJOIN_ROUND, Bevel = ffi::FT_STROKER_LINEJOIN_BEVEL, MiterVariable = ffi::FT_STROKER_LINEJOIN_MITER_VARIABLE, MiterFixed = ffi::FT_STROKER_LINEJOIN_MITER_FIXED, } pub struct Stroker { library_raw: ffi::FT_Library, raw: ffi::FT_Stroker, } impl Stroker { pub unsafe fn from_raw(library_raw: ffi::FT_Library, raw: ffi::FT_Stroker) -> Self { ffi::FT_Reference_Library(library_raw); Stroker { library_raw, raw } } pub fn set( &self, radius: ffi::FT_Fixed, line_cap: StrokerLineCap, line_join: StrokerLineJoin, miter_limit: ffi::FT_Fixed, ) { unsafe { ffi::FT_Stroker_Set( self.raw, radius, line_cap as u32, line_join as u32, miter_limit, ); } } pub fn raw(&self) -> &ffi::FT_StrokerRec { unsafe { &*self.raw } } pub fn raw_mut(&mut self) -> &mut ffi::FT_StrokerRec { unsafe { &mut *self.raw } } pub(crate) fn raw_stroker(&self) -> ffi::FT_Stroker { self.raw } } impl Drop for Stroker { fn drop(&mut self) { let err = unsafe { ffi::FT_Stroker_Done(self.raw); ffi::FT_Done_Library(self.library_raw) }; if err != ffi::FT_Err_Ok { panic!("Failed to drop library"); } } } freetype-rs-0.36.0/src/tt_os2.rs000064400000000000000000000075461046102023000145420ustar 00000000000000use face::Face; use ffi; #[derive(Copy, Clone)] pub struct TrueTypeOS2Table { raw: ffi::TT_OS2_Internal, } impl TrueTypeOS2Table { pub fn from_face(face: &mut Face) -> Option { unsafe { let os2 = ffi::FT_Get_Sfnt_Table(face.raw_mut() as *mut ffi::FT_FaceRec, ffi::ft_sfnt_os2) as ffi::TT_OS2_Internal; if !os2.is_null() && (*os2).version != 0xffff { Some(TrueTypeOS2Table { raw: os2 }) } else { None } } } #[inline(always)] pub fn version(&self) -> ffi::FT_UShort { unsafe { (*self.raw).version } } #[inline(always)] pub fn avg_char_width(&self) -> ffi::FT_Short { unsafe { (*self.raw).xAvgCharWidth } } #[inline(always)] pub fn us_weight_class(&self) -> ffi::FT_UShort { unsafe { (*self.raw).usWeightClass } } #[inline(always)] pub fn us_width_class(&self) -> ffi::FT_UShort { unsafe { (*self.raw).usWidthClass } } #[inline(always)] pub fn fs_type(&self) -> ffi::FT_UShort { unsafe { (*self.raw).fsType } } #[inline(always)] pub fn y_subscript_x_size(&self) -> ffi::FT_Short { unsafe { (*self.raw).ySubscriptXSize } } #[inline(always)] pub fn y_subscript_y_size(&self) -> ffi::FT_Short { unsafe { (*self.raw).ySubscriptYSize } } #[inline(always)] pub fn y_subscript_x_offset(&self) -> ffi::FT_Short { unsafe { (*self.raw).ySubscriptXOffset } } #[inline(always)] pub fn y_subscript_y_offset(&self) -> ffi::FT_Short { unsafe { (*self.raw).ySubscriptYOffset } } #[inline(always)] pub fn y_superscript_x_size(&self) -> ffi::FT_Short { unsafe { (*self.raw).ySuperscriptXSize } } #[inline(always)] pub fn y_superscript_y_size(&self) -> ffi::FT_Short { unsafe { (*self.raw).ySuperscriptYSize } } #[inline(always)] pub fn y_superscript_x_offset(&self) -> ffi::FT_Short { unsafe { (*self.raw).ySuperscriptXOffset } } #[inline(always)] pub fn y_superscript_y_offset(&self) -> ffi::FT_Short { unsafe { (*self.raw).ySuperscriptYOffset } } #[inline(always)] pub fn y_strikeout_size(&self) -> ffi::FT_Short { unsafe { (*self.raw).yStrikeoutSize } } #[inline(always)] pub fn y_strikeout_position(&self) -> ffi::FT_Short { unsafe { (*self.raw).yStrikeoutPosition } } #[inline(always)] pub fn s_family_class(&self) -> ffi::FT_Short { unsafe { (*self.raw).sFamilyClass } } #[inline(always)] pub fn fs_selection(&self) -> ffi::FT_UShort { unsafe { (*self.raw).fsSelection } } #[inline(always)] pub fn s_typo_ascender(&self) -> ffi::FT_Short { unsafe { (*self.raw).sTypoAscender } } #[inline(always)] pub fn s_typo_descender(&self) -> ffi::FT_Short { unsafe { (*self.raw).sTypoDescender } } #[inline(always)] pub fn s_typo_line_gap(&self) -> ffi::FT_Short { unsafe { (*self.raw).sTypoLineGap } } #[inline(always)] pub fn x_height(&self) -> ffi::FT_Short { unsafe { (*self.raw).sxHeight } } } #[cfg(test)] mod tests { use std::path::PathBuf; use library::Library; use super::*; /// Sanity-check reading basic line metrics from the OS/2 table. #[test] fn line_metrics() { let mut fira_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); fira_path.push("examples/assets/FiraSans-Regular.ttf"); let library = Library::init().unwrap(); let mut face = library.new_face(fira_path, 0).unwrap(); let os2 = TrueTypeOS2Table::from_face(&mut face).unwrap(); assert_eq!(os2.s_typo_ascender(), 785); assert_eq!(os2.s_typo_descender(), -215); assert_eq!(os2.s_typo_line_gap(), 400); } } freetype-rs-0.36.0/src/tt_postscript.rs000064400000000000000000000033071046102023000162400ustar 00000000000000use face::Face; use ffi; #[derive(Copy, Clone)] pub struct TrueTypePostscriptTable { raw: ffi::TT_Postscript_Internal, } impl TrueTypePostscriptTable { pub fn from_face(face: &mut Face) -> Option { unsafe { let post = ffi::FT_Get_Sfnt_Table(face.raw_mut() as *mut ffi::FT_FaceRec, ffi::ft_sfnt_post) as ffi::TT_Postscript_Internal; if !post.is_null() && (*post).formatType != 0 { Some(TrueTypePostscriptTable { raw: post }) } else { None } } } #[inline(always)] pub fn format_type(&self) -> ffi::FT_Fixed { unsafe { (*self.raw).formatType } } #[inline(always)] pub fn italic_angle(&self) -> ffi::FT_Fixed { unsafe { (*self.raw).italicAngle } } #[inline(always)] pub fn underline_position(&self) -> ffi::FT_Short { unsafe { (*self.raw).underlinePosition } } #[inline(always)] pub fn underline_thickness(&self) -> ffi::FT_Short { unsafe { (*self.raw).underlineThickness } } #[inline(always)] pub fn is_fixed_pitch(&self) -> ffi::FT_ULong { unsafe { (*self.raw).isFixedPitch } } #[inline(always)] pub fn min_mem_type_42(&self) -> ffi::FT_ULong { unsafe { (*self.raw).minMemType42 } } #[inline(always)] pub fn max_mem_type_42(&self) -> ffi::FT_ULong { unsafe { (*self.raw).maxMemType42 } } #[inline(always)] pub fn min_mem_type_1(&self) -> ffi::FT_ULong { unsafe { (*self.raw).minMemType1 } } #[inline(always)] pub fn max_mem_type_1(&self) -> ffi::FT_ULong { unsafe { (*self.raw).maxMemType1 } } }