From 8ff67ad95522784394c390e43ae73921b7f066c4 Mon Sep 17 00:00:00 2001 From: Alexander Mankuta Date: Fri, 6 Dec 2019 12:55:52 +0200 Subject: [PATCH] Add OpenType Fonts support --- data/fonts/Bodoni-Book.otf | Bin 0 -> 35348 bytes lib/prawn/font.rb | 7 +++++-- lib/prawn/fonts/afm.rb | 6 ++++-- lib/prawn/fonts/otf.rb | 11 ++++++++++ lib/prawn/fonts/ttf.rb | 3 +++ lib/prawn/text.rb | 2 +- lib/prawn/text/box.rb | 2 +- manual/text/line_wrapping.rb | 3 ++- manual/text/registering_families.rb | 2 +- manual/text/utf8.rb | 2 +- prawn.gemspec | 2 +- spec/prawn/font_spec.rb | 31 ++++++++++++++++++++++++++++ spec/prawn_manual_spec.rb | 8 +++---- 13 files changed, 65 insertions(+), 14 deletions(-) create mode 100644 data/fonts/Bodoni-Book.otf create mode 100644 lib/prawn/fonts/otf.rb diff --git a/data/fonts/Bodoni-Book.otf b/data/fonts/Bodoni-Book.otf new file mode 100644 index 0000000000000000000000000000000000000000..a4e55f9033d53dd8da1d676eb8fce6def59e0773 GIT binary patch literal 35348 zcmc$G33wDm`givvJ)QKB3D+QGikUzN;Yc9i%y0?e#&Cs8ki!5Wgd^b!2w4tMKnQ{d zf+7MdEP^P11XS==L|_3C4+LRcKx948B?zhNuAcGxRdDjG&kGRI}MUqsUElJY7JqPq3 z)Md}K2DslUNpZ7!4jPgb_3EXXlJrn*Ns=GvKd5<&sn4ySir?wzfB(3txzip!Y^ah{ ze}E)8)=tdJ9p8BQJ8$9Has0KJh=#P6Ngec$#(jf{Q)fNUzt!ILlJxLnlB7I5HTQvO zaxPw#S2=&l4pX-wsL2UwM73H;{sN3EVuibuIFsn(T)LD{vv^`f<$vFYfpA>!6kyXSc z5mdmy(gIxN=ve%ogg^VYEY-xF{o5hAZ}o|iT1YD^+M^|(^iIWZMM{v)SNwKLL@KZN z9p}3)SFiZ(mRco7SNyIf#Uy4*U8N#vnlx9MAr(mZ(nM(%U}_|dlN#gNLQ0o1q_$Ej ze)pH=NO@8resz~}(R&J7#Ygn+j%P)9mV+mGc+wf;2B}zT4_XI`;;nxH}G{=H74=r|&DY%Za@G=wMnZ{f5 zCZhjD{1R{Xma=i}4@}!QtQk=rOT>C+c<10=z%HH&EOe0uTEAyW?Er<~ky)6hozxtk znOMKzooQ&B2`B}&r{G$I)_gqgkN30jmiVOofB9&);eP;lwV$=7{1PxIe@>5)EC^JjbApm2x{ho7B;;T z@oNHFB7FJh{3v#}O+g_K#2ytR&ayaXCawk8+4k<8Rlzxe?o+S>1P_UQpjqFu@k{XH zH1rocKe%JsUzB_StwY@L}(%2^LKDosbtA;E%`#@hsQElaQ)2Amzla74mD2C7H%q zJ2SFAA*ZIIzu-f$;}ZeHMBIxt3wacQMNldNiT%VLbDGt67RI+_rI3Bo08gb1D5}7z zkfcHiRdSZi8Db7WK_O`bG!Y8iDWe1|x5I4X#)h~U?+KU$RRw;F@!OVSqGc*Z7WWe> z+9GSxD%NPzM984AcvJA9J(s|M;5vbsTnjP*qo8Bt-iFkEZgX}adI&BOvQcocz^Qm{ z_nd0MIRz3^P`Vk~2LsoF$17JRAQqS%hxhGuL}o0sMzVE7fhBbX&)A$Ep|s7}f)53~ zZS06u2_6x$*~U>Ga3Y?K$0ySEpRr+cL36BX2F9&iT_u%853y45>`qM=;ToHN1x^Gu z#6GntA>I<$6EvJ*tw->4A$o|tE;u40HzL@L&^vDf=g`fxm}A#FjKh?1P10>`!ymv?&S4Kcx|do2L%f(992p` z!7+jsm7F6+6&hJUBX+dCKW~Rb;QjaPjzsW55#AEGj;t&f@J++2<^l`$xRG^;zT*H< zB`lQ^GO~K1#cjT|IsZ;LZOH8>VqIc>LHj$oIwCE)K^ygemhFeX!T1xJcMzbe{~zqD z`W1MXV2x`_6@i-wG=ffo|7;y1B!i%z==blmynP2J{*Jw?Nxd+R*zIBsjWCMPb^jgS zBOEApyWk(8`^0__^b?ZX#-}ZPW@1bsyCd9TQ__~*nuYI(%&?_+5&F--8{)2Vg+jgv zi6B-i_TruPm%SrJ`){di>s2BDY#Cl3bg*rHL1`hue{1{v84V(u+t$eu8{4Kx4`9^R z+=DC{-EKMCdQ)g@p>sqpTSm+TPY5|LG{A4A`Jd4+@pot#S!Z9&bf^9pig_#jfPf zyZuJm4zOSmmhDUn4>nA;3=)(Pa?_@qy>IC@|6@)Q9AB2G*d$w}dX}6@1y)y+R zBfMaH;kCW@KF<5y(S_U*(25zw)rL**<9KVfh{t8`gvu3&9iRb5(Jpkpkc^d9pTM(# z_4hp3B0LeW+5T~4p4;&(uqxgcHlr9<>{X#(ZR_+-+sc-$Gb;8@D{Joz#)`!Z5uYw% zBi|{@x?0$}lUIJvvbOhn1k<R(u!s-(IES?BX5`NU5$tQc%2f*Wb;2Xi05zRObzJP#l4qz2n z7kbIwGvaDX?b|H^TXz2*KD6KQV1Cc~y>n-ZS$-eWLb6AAG6Iq9(}}$$JV>$Ag;W*& zY9X*zJqTf6#RFIDKPf$8q=o4?`c!f-`+WYW*G}@BVu#HLWt-J zp{IV&yAZ1p)V6&`u|xhF?@z#DOC_;}$V|6$;UD`mw~udgm*78pPY8PSTEKgSa^3pZkR5qXR3`#1z4+Y|ZCMrb^}}0YUXeQy9*CfofOIh0D`&M=7J;fa z`q=aJ02DS}x?&AB%v~_H$dQS$hFkNCh|yroE8Y_C3CsydyWnpCzH{(YWNwDwEpaDW zhu}H@{p?JR7+F9ipcS#Fei$Riy7t7V0s?_8;QL zWiXz1!KmVWG3z~6s|}gJiJ-E8rE-*JxD#{RaER>b(2DVdG!*O4#z%}S-WAgQw{QsQ z-XDF$tYYjeTy5M7tchID?bxv?Udev~>TZ}tz$?~WN%Py`6`21m4Kxex-||3&r^Hx- zIszZr78V8pf87DU7|CuC>lWN2_`7Qb21T3bBUU4@8tH4}(Dq#g{RV=Xb`N_z?Ki6s z>l$X^tP<-so&|)0PsEH7zqpddVom{b1RlY&f|nvYp%N=%mkCJ3OoGI@!-ggi(A!*SuS>jlCw?QlCDJeQ-hYx1_E?d*1?N_-UEovT(uPn_*~Z47 zkJ}7d;D4Xd6&ZAqffxUYstQrZP*YSESl4LBVqCLO37}X{e5qb7_5+Xp^;e9A@)NA7 zk+fO*oAkQ$hAhbq@mYGaI#9A~UCswUP>Bp4$-v7(??#y2=q1NQWCP}*J6!#a>F0>HWirS7&_|*rTJ`L9y(reOw z$p9=3igQ~F3cE&U?jEw`6DN&k|XCB! zUg>SQqx72GS2`$Nlw+i;(wFjmQb-;s$4Y0Ue@Zu{pQKNuALPbzJ?Xq$Q#vN!V^OiQ zbX4|9CnYX>q$_e0xt2U!`dIeL)#Ms-OIekNN=KwGc7B=?kp(gC@v^p!kHt}FMG?H?#If{9r&D1JU^!_T*zRgmDE}h5z zT3TB9tBT66)&2EX`3xOA9Z9pCDG)ubmeAqZbZsxH+5GdBb~ zw~zvoC~@fp0Wm}x1vZ!rwwfy~l$J=#rPb0}X#=*+i_$CDI`0Bqe+Rn101NyR%e@K2 z%W@SUyAIIX0Ibp)WbY#P!qyrpkCeyC1@bg`j=WfYL|!dFC2x?o$UEe{@*DE|@^Se~ z`D^)G`KtVjY&ax`;&3^tVH5cr$&OTPrB06Sj(Z#f9m5>Cj(o>d#{-Us9IG5pIW{<+ zckFQdkK;AR+m0iSla4PO7aad|TzBY>U!#;LSCl8pAC(-H8r3qYT~z0&o>4hbqoT$~ zO^TWxH79C8)S{@RQ7fa?MQx1Q8ue1tYf*1UeHe8->P*zvQQt-V9Cb5_MX~6{(V5X% zBXY+T&&uo5EO*MRZsTSY<<2TDEa;Khy-Pt+eo2};ubJD0`5X<3B@xC3iG>IFZLN%Fk@Wt z)Cp7a947waLa*_z8>z@@~zVZ_P5! zdSCQw(XwrxJwX?Hf+^Oc0;`)fP@5LwlAhiz&+ag+a@K4MnC^Caq4i>y%7x>d-WEJP zZ_RGan30J~kF4}oGb=}$RQc1Iv}KmvCmk1{JVP|5XSEcU78xyOSyK%WSQ}yiI><&N zo@TUYF|+cfRcrA^M(Z|n?i{~GMqr2yXg6!98P<1y8#lM09c;DsvxY0o6=j7pil$A> z8(uk9&&r=Rpxv!YM#hX=Fr;U-=x&XJCmG!Xq63!Da@-wnVr_x0)+>YVXa|;BbiJb` zJ)=#_aaPYf3)-I6ckf#;cdz_qJ?VcNJ-XP~%xFC?0v*P0Ik9s5xs^Y~Ix;fa={1Lh!q7J)C{yW88FE^BTava*(xVb2w)DOO3R`+k zlAe;JW0G`4mQF~J<3cOJ(D+!AK9!`C4ybMEGl%qoBz-AK=OpQjjABmdD@lSOf{Ia? zEnhpNOOo`w1hpqUF2UG?1tBj}p(f#{UYl5c3z!;<`~69$9>nl>mo)F|l@$>CC=wH!5MIaesUMzD@2B9>Mv zl|iBOj`Bqfje0bCZS=@YyJE>2_q{Xa{*%|X@%=wt| z*xIp$TDCS=JEDEAeXV`xs_RN|HFvdkb#nD|^>IDsTIbs0`l(7vmGmlYs&uc?x5{6t zEUR*^%H=9o<448k#qW-PJ^sC_nN|B#eXr`T)jCysqk2L0b=6<1v91QKxw7WQ zntMEcPczS7Jdb&?86SeqVad*|btJPgS?;3g6w7WjMtGu?e_Fc7; zYqzf5t@e=GV{1>Vy{`6-+HcqXwD#rNdY!mBfjVdE{Id>Ch)$@H&@iDmA>?&?6TNBP zPTm~vIN~9BWFC2pY$0!wljIw6vu>5To9g~g-4E)XuKUlrhOerxsqbaqTfXDIGrk{u zy1%Z!xxbyihkt;7jDMg1d}5Ep>4^^}ewFw`qF&EcFRk9tdinKM)Vp5aSHF4vcJ&9; zUz`+| zjYc$D(CD#7+Z(;q=&eS7Z}fTNfsJ=I-rxAc#>bnun*^G4Yci}!VUq<-9&PemlfzBU zG`ZZgdDBi!vzs1j`f1ben}$-=)S9V{Q#+;(PR&n!Aaz;lY zviXAMk2im|`Sx@z-JhP8-Z8yP`jGVT>4(x!r~jO8W~dppG7>YgGe&3pC1ZKU$&3pb zH(EGa+|{CWiy^!v%?%y#5a$F^RU-O&a!qp5T$<}4?g=FNI4N6Ccq`RSc&((1<0z%pJvoD-T|iuR#_QeGoGR0;V5dQB(Vhbh5Y=rl}>BktTM zh}w&2Ii7VT!?%w1azFPb^Gx20`qODV?Nv@2(E)TXKTJ28$_YO`*nq#LK00&8%9-BY z_bgqMjh1A7R^_3ld>h|pdK1iX^c|j0zvZob#F(h^Uk(GIed|+C%)+gE=bi9UKP6=} zllJ2ND?Fa}O5~0B06v?p=O43&GyHsi8Qq~ieCX&S$Gk6WTe)(Zpa1nbeMx1LKBjx= z1@?FX+huCB(5yi_`AGCfDt%!z9l^Wp;mI)}FN^c6eX4ZDT0h|<)#iILUTM2G#&}76 z_S3UZUhsyxn6G%~1GFmbN{j#D3y)Cw7#hVJ(z>)Hfn6cxMV@;{KDv6epD44{%j2)) zT^t`nj9=BIdi4y&nEG@4~0^ce-KfcU8K9*P`QiOa5Vko2a>yHR9Y)jQyS> zjSZWj8K07veMBAU39y&c;bsdy*zCw(;Gc(<7-h9tQ#yfuPrI=W3G_U_L?@el%p!h` z&o>pG^fk}D$CL1rO^(2hz#(A2i#izejjKg*V}2`Cl^lQZKr0qA${Oes`#VD9?vfkNFtD-l<>E zwkMZ+#XXrv`TS90X z-x*qEqQSSjyP~Jly=<~R#ORk`^fM>x+d^pYxmjJ~E24DpEGsOXGb4ewx{yI#)OGP& z+G=a*re)iGx%Acg`xmkrG|0!y=L((2`#eAQxd%5dr2h7_$_t0De{_8!t-^ihir3A1 zYT7!!wLHBSzf60^0Ezcp=}EUzY1`W8p4$90^`F~CwE@@rU*~Z6mAz!spRGv!0v#)a-TKe~wov>fc~M zgI&A|^|k-&!VM2@TS&JiUip|_<~?KhKlwfBC;3(`OfO(*`zDl33&!;s6b^UI$6U_~J0z?@ZG=~w_uF!V@ zHjdobs=D`+n2xpd%y#@R(O*Cd(d!b*ae?XzM@Wgma+sk%xp{_H19Lp@T(9=Z}JW_sx^%-qjw#*rg8?k zYjoklWhFkU9-%{MTYAt7OlR{K`9Z#Zk~t>i_jgqFUeswm!VhBdTvIYj%sM=ej@+Qp z^K84{P3MuA6G0C@tgm20gXT~YGl8FX5~Cxby%eG>39T^e1dLCy{YD$jJS6&iqE1u@ zds=lv5^khdJr8Z&^w54UI9Uw>37Ne1@nlFsM{C}Jzexc$Ys12<9UI2BGlMgxm@o4i zd=_uVlT!S~XGD2|T?z1FViXc1hDNF1AHl}$Ob>gROb3|B7S7_KceVlrLul^zWBu-n zB&Nhz(H(S!V)o}#Bf0-j@wSbIK;zGoJn@v&y7X#stfxxoPZpv7#b z`3GjSIm~nev}akf&OWoa6Q9Z7GutPyg+#gPp;vFRx=d#BO|vdAb+sP9V9KUkk6xfx zeF0+B^e_)iVX>?UYeG}ZSg@{#r|=tQ6SE0Vp*OG!f!D@F)jaw&vl>`0Y=(Im<}^at zY!2VcTF~$4y)>0B_}Ld~f1kN5R1#|E?XDWh`U3s3F~?8zt8|5j<^RNmd?G!`fLmg$q?trrlBi*uM-QtI1{Dq6qMy_*(iOxhc>qx8 zaA}a}?ey)$`H{W@zgcrm9*RjC@Gbl#zt79p_oc__Hb~IJVC;kR`9tPp z-r4WgUk?VGX`M6{OO#%<^b|1C3TCh&{AW7Fyzii&-SauXn#Zyd*mkoCoo$AFFkAvm zfmk(_fRjXTg`oA&W8nLFSWpRsR0n>{Z)QOXJK1DnNR9`F?nk4W^)RIQ~}9t`%!?R=W8Qbtv-@@@X0elFmI*i_Rv^YLt= zJgO&+)d)RkgXDDUdBj;xqW9mciKX?|o`4<-2HR;c`fiXa(gcm27R{?P_k7ScdQBM= zhMpSadx>^dH4cy)FMV5TJVIQ%vBG2ge85;Fp1DTSy}?j{8oEZxYlb_K*sDrtQ~)C3 z##T(ZB^b=t-1;h_d^xtG7SOUZin%=j!w8zuAUzwZ>Vm$I&1^fzH8dCIU#|*~^>Y~B z!|Ku*W`@|_TwLq=A+?<~G59JHvpSpw&TL7C=#!TFA^BsNPp_xHm=MrH&$C(~qPOSO ze4*@>XZTV5hBuT=;=l1ct?4y_!JgVmP3)<$!$Dy^$x@E4JWZV@o&p^$G>q>Y%^vZD z4v^S46xJaq$V*Q;jn~KxPq5TDL0ms7^g=LPC&2QZZsIhEYdT224EQ}F);Kw6PEhr~ z6Q!O06fr(h_|E|nT@vKSoZ)H2xkK+tqW3DSmNh`SGgLc#Aymz{pfERPS`wfKocd*A zbOJfDt``VMDHP_l$+=wZoPdu+(42;kJO&i!jBbd;P;z;PeZMNmZ60=usGss znW(XG;mJ7~9a2`H5%oZ5w#`+ldy%$4Ft{OxpeCJr1Pb*kHt%@8r=g~Qrm}VySw5>q z=U%_{U~fZ>L?6Xw1-)i8@6H$S7u)$^IX4Jo0K)cK zUu_x9G_pEqcWa%2gEFvd0CePgh_Yyk#`0}c-0YK}Io%E|l zypZ@Tw%jjYu5#H>mLTq&MLd1&tS_#GZg-0z~~X=OPry>#s>DW-c6w=toIyF zbG6CLHn4=~_F(wo0Nv%(<#7E_%g{TD`>cL2v}&McO8V>2RD-neS!1SPX_Y_0@1o=B zT0g|6pJu`krN?=nfA9@o0^_G?pG)*OEK@w8#}epTdKV1OCwxKGyuv&4`%T$z9-=FF zU%oa0A~!z3`(%ed1pG_ydoxhg5Cv& zTI=V>z`>bjvjl#e_GwEu-0kBVI`clQ_;Irt#S?xk0RY{_bNLf+nW%0OXV}Bqm6#s3 zL0GqYXaSq-Z|8(LoSDJb`pmjxna3RFgXkgJP&DG zG%Hl$DO@%auGfI~cp~iOA#c(|I>2{U9j)i_=4=f!5&}-s;OXX?(V;w_`?f7h_wiK} zwmS%LEx^lE^ZX3{g_&(WlVJXf)i9&j#sxlpI7pAGtma_1aznK6Q24JZ^1_-@b%^o{PVNs2_M!QzmN6`T6oXqE7&1n!d{@A*%dz& z;AMVc1kePuXHpoyUcQSr=W%>ey8kqc<@-L@0}0>G`KIU_pS~>^`oP(n_HRW;&{YZ0 z{Eb)-b^>-l0e_cA`Bs+<->^@E!-|P6^XKX1P--Z}>`G&pJyW`@ikE#N6n%H1ik!xy4eo= z^*Z&^=ZE^1J^SHI+r#-D8!M%85dKY4174kXFpFSWG@vG%OwYju=mb?g-PrCaf91-H z$9(h(AH`-5;$;b0llzSv?BiEyra56d{Vu^>s*#w1W*g54Ctp32-^Zu$Lte8pZ^HVp zL2M8e*Ut1wI*SkH+qe4PVk;*&xyI`$*X!}7f9LJI=2CveOfp|L_fuTiQkp|se@vxv ze>rcW>~^|Ct4OqoDLna`l(r*>O&jAKFnRY|e)gkEM?OGD0SU8sL1UiQ^8Jxt9Qpdy zpT5f8IeMLM$IHQ&spO@@H$rd+{9NLxD!qoPHmp(bL%yT^IPIL-bj98iH8y*R9RM(FF`;?L_L`liat%){Y!>=W-d-#_#GUjJVX zD1Vt)uoxSDKf6~ye=tD2lZZv`JNuZzeN2u3SeW7GXMgX2A8wmCv9v`1ANo z=eYW4aV+ zODT8Is5C!+ek&Z?`t)*w?ozqq3Qg`!i@dBBaJ`nkdC70C(Hp?7Y@kioxcp4R7hC&6 z8&y+*IESH0-@OR_Zbj1*sm8sK+m=`5%!f0wj2$Jh|Mc+B=oG$%{tKTebPN5Ae#UX- z|H23D{4*b2TZ@*wLjO)T(apR0-+2iynZS<l?631(}vnK?PZT*RvKbL=!51DBOydw1ZDi#$G=*M`}HZL0>TYyb9j ztDp7p^s$IRZsb?tA2p`emRAmZh5zH1Ac}lZK)gW>_(!1F+1EW&!6+EoekrUI_ua%=hu-L>ZuG!!6M@C(#>{ z8##*J+8FAAF|8v0!uG4e_i;WQnxCtI8Q)Uq=D*T8H)sZJNqh2DwU6lMyKCY4>|m&= z{_!$D|IWPcVU0aU;(9gKi~ylcg?B{M!Dy(bv9p8@wi=>eYNF|T2pwYGDTC9oFrywR zA1&@f(`l47Kq2`>YlmB+ykWg>RwKW(6b<^eCK}HqzqArJMnCcPP;$LvJK>udC45By zuDMYnoIc|UJRMJvUqdK~)lnaSleR>-L2##tdn{0Vnv`9$JR;+568Ax44Q9u6kL?-3 z-%!6qBLH7Wu6MfCh*+)$wz_`cR!elLH5dYfWyQA|om&N5!nFUuZkxcy=umP(?ZwGXzO12potdxj_`(tm7<`E-HG#E|byD8@oP5ZW^h|T&xff0UJ zz4yCp^1byTC5LD)FFn7LzlDed@5P_MdJ$z=&##&Yc5oLA+D{>v6X@gD{Cp)%p^w9e z4|>^sbSI=WyXjBS_;x<6G4H_}`DjKTUJpqg7z?ooPi68a{3OOO>v+OxPF8;_l?zz@T*N<`2$pLv2Xi%Tj^R^hywl+`t(*^Y>~si$YcFK&#j?I3#73g@*Raps^E zvR1j9=!0*yM$c=Crd~w<aQ9zX>5BpCKXXy5r}%&Wd9I8n?4;QaSR;JFcEr1?;-H!OyOxmLc$@{RRT)|$-& z$h_G;@-jpbtRTl9>kn%M)X+lmH#tu>H&o#@vheH3p6TKO47P3+c-(222H zq87>yCBY_9MBKxS#g$-mM`Q znoJMz$7l~flh{oN#2?I)%2(XW+Z^E8FKhH3>T1Pned!DRjUaZDN&C!2<|H@4SXs;T z^c7)u80#_TXx!aCXaU8ioZ-Em<$r-knjkl&=aSf#o;8RKh&&Z>qL>Cd3 zqnf80!+?3%?7`FFfv#HS>%OmS=tYqut_@2u33-E>U%>Ip}-cv*m!5u+k-`X1JexYlS~DwOC*r<;B*Ldxp*o~iVq9Z5!s%BqLA zzf{U3OmH{@50h6-OZl{&&NI>TLRO=WpIcw6H|+DN6H zH^Ln0@83Z$gk^qVyOZ|c2#^uYNkLzCWk4yw8mhcF4I-iwe>qcYt1Z-6OUpVH0jyr| zJf^d1B>ur6<6+nw(W}AK+7@BTU*etmY2mtrF0CLa?_8)EkJK6lYi)2OHf8~>BK(YCOAgGW zFM}RoXTPXXcs^qr!!yg|>%=l?>l4VcOF=&^4?5kG^ln58CTpxN(FX_}P#MgN*+M@L z^3V0YRv^pd+ze1NEKSsqKDqj+#`>Fo^Axi2+j$$dnL^t93PFFPr!H>5yk`o~NA?=pf!O$Y=V@c~fbd@J=T^W9;l15hn$uZkKd$g}bvT}h)Ru11M!lmqh7XiB$;FEjID8ACn zQIKk7glGK&RkvS+i%u|*)WvvO*rqQ_1~oT zd_af!*!;C@9z1}#BKuICo;SmxRI{eJ!Hn}Ejm(lE;b0{x4|aw3xto;rvclcVP!OY) zCTnIn(UU4rFhYd+4Pm@2(DZm1Gg(=!M2Wu5O%NPM!vvyG8pG@7Mrp-twF!5VvCWE_n9!X9EsMn5k?yS#zZ z9Hie*l;ZCQ@8D-I?SpMMi%q{Ron-6}u%Uvro)rPxxg=&QEZ(;W{Zc4T7`D!bgq{06 zToGZ`>b9juqKim*erwI#Dunp`-Qf7tdQv!p(T|b%waHreQ*!Ms;k=pSjD5nd;d>^) ztr>?GkjAxDKxj`b=m9uJ`Qt$j19o#e%jkXz0X#54`%|=vIfE);UZyCiw^yuRNvCG7W?>wCWuG{__N?5 zVb_ne?fSi#)8bi*FiKtG%EUUlksC)m_iOXe@pWW?nrPv6@X16XD=gg+-41;b4qz+R zI6{);byBm4=dwev1hzC(pgDZWHI)B`A;+X$~^Ki2MrNz}Qw@v=QNtE0QeXpY^@KV2)Ogz1a_N{!8zDm5hOf3ZX8IA@q3nX6-h4*mUy|sji7URF7XFCb?0QQkK(){YmiX_BJzAk$ zDl%p|v?D~V0#Q4NKB2Jnd75(?6i%)i=I~4A4}w=Ze?j}vxG($^(c)or-UYflMx=W- zY$#och{mu+u=HE=<(ZlZ*JJrCK^yQ=6IeWtn$gQ}y9V+ZSx?U&1rq4`T<7dpmC$GA zp-@yfIh@RJ)j#uZepSh}qY&y$jg*(OdLFo)Z!it*!MKB%OSbWAWBPM|Tm52G#HRzJ^E%$0>3@it2Un4t5>7kwIy9nhX^z{gL zvuH2EMG_)F+x-YQ=(~8Xz9IpxRUVy+st6Bq%InOMpf9MO@8?89WRpUBBZxlxBH!*s zbxmEUpkWBc!(*YdL+2Av5wV^xF?*oqWD9KECIMd{bl$12GapL=3X+6#3mZ@vmQ^Gb zsw-1D-Im9_$uqpjXwT>A_)GRvxfySMnh&3&k=W))7<+m_ve242WiP(?_}Ulzr2O;H z`Hfom6wmeS){3=PH8aP^Z>n)vGoz55`kC!-s_8rVo*Zm3{jymibgwmY?5O9pU|_^P zUoUM3tSmki=Hwin;J=>6o1Wr1m@oP|(W;2~8sF&m!(#sWjpr0{egAMlU@QL)9hGGo zYQ|WeVpcOB^M-oyj{4$B+FxOtyg~HLB;bZ9Q!MMA19KNgXm%c5-)NQ#k~r;@B7&Qb zqx`Xew(;>|+J$cA)#&j%UFl;809QrfOh+Hh=WY3FO8BQQYujM@9W?690>E}29E^DV zRFY=2AkObWlX#-{UJW2_Syo)5wP@cibi9|=E)j8N3LzRV`F@P(Zmw5`rOc&3h5~dJ=)_n-V*i_cwVU} z2iQVlUb5&&_~YORMDJM9KBB$aO$6_5K3AcOm47tRW?SlLv=%-Lg(`R5i?#{jiyDQ%o8fBLzkD*C?IWxVq{r)>+o6CY{u6i zhR&MNbx>x*kTzOLlx>#F$iIijXk~l(F5+xN)B#I{^j9@eUsxX>WV>JLs$mD;ED*+& zamdlUSqB8^8GVkBtoq^&(Aljcy64-q2^ztJ6ZCAvn-YfQiU_Ov!o;;Z$L{fKrz3 zYN{EV&5ISdpTG_gb^ct-^h8xw+;ky*Pm^-VGCx7jElo5t88Oh|TDb*#%z;XQ)K>YT z4X+{u5^4lK83T#1`IZE#ak~UMw-Nd96Jjqzfdea+ohx+BH>A9YHPe$3ayZ`z`ZwbO*WFO^{VzWpo}d6zTPRo6ChJCJKqH$#oKIf~0fKuq;WMZYqO-tWy?3 ztCa855R`lZiee#8^V6tiJmU<%PsrERME!@SSlg|I_7JF1)TbhruJ=+6j-R4zHM9ah zU^zL6yK%O*iTpC^R&9m{?vQq|x8^=eq7i$f4sv7VK%@iT7ivA$FUkU66vcM%7k7fI z7O_QqC*6Z^Qwvme?lBkn$c+;SkK}6@MdXKBei>?Pm(rzWC^5`8^OI3$x0EkUMj=+d zkEetei7FQ?vmS|_XIV#d6QSQ!;C2#Q(N8l^11-XfMLfnCgZ<7LW4~ipi~VTK6xB&Y zX<4GdPmV{i$^_^JW2`k)=>AaIAZ@Eamx17M9f62kfe3TM7v?L-GWOzxy590VxnbEl z5e9LIveisp<3mv)8r24s2Pk6WlTZl1okp>l>}AA29u1$O=T)|WI-b&yihltWF3^k! zCBm>H{4R2H8nh$oP`5%Q)zgrJKuLOqw}zMiu>xZ9+=HleE?{w_6UlM$jz44<`Cs# zP+mX$TS(+ai3U%+qT}@Y3LTCi%FvLb(tv9JnT6vZQO ze5NOAUzmK5$hUPfPhrchK#jXvYDSxj9@g|$A`>QT+b@J^3psdu5z+};pyclq1c3N} zzf-~1%PqFXN#NL#HSry@$@5GNX`MJIrAS_>p432UiUa*aagghE9JW4UMp{w56Fk))AIMS>4j+Ksg9G^KZJAR3hqPj-S zi+U<*XVm_vgHgw$KUWfzk;)UwM@qS~wzHjch;zDgrSnDSd(N}Y?@?J1t9sNVwYl0( z?W#VizORu}W;i*j};uv5RBZ$L@*!F!pThPnxXN)KXA^*G(G; zUvZK)6IDRVw8veh(8x^ zR`pfwP<2?KUfFJZD#*IC3`OZ1+oCE%b#a^TnG3iYs&&0V-EF;oWMXq=3tV zT;VF5O<<@`4niQT@}XfAZ(v^y zUN2)_#AaM}49|^yXgkuw=}G z5czmyWg{6HU+6m&jm^^fY*$*3?f};|1toeph-#*~5>O&FzaG4h*HIpyjT(KQ3x^gq z;LyU(NZt^uwS_AdVAa8)+z$BJPEBMLPP;t%XKa=@?BIgLdj`HYYE6)fbD=gAKTxQA znxmt+-N&+OG0#y^dA&_@d(7SR@Yu0zs5y*oDrH02u(A8VTPB-@^AWH@kc@myo3{RmQVHa3pi+!Z4TrAq_g<| z`b3tWKRyHjZ8y(Ppdq6OPH`DxvzFno3VtgNzO91caApn~5Bict%8tfA2SYFQ7vItk z4?hA&%Hu@+d#Y6(6$c-8xY-1*b3Da~DZkruYEG*o^}PJ9v@|3)(rJx8Wi}SE>ii_Qq8jQ`PO`7r z*PPLl<~Va4N4xp8&&9pS?M9*I%nRPMuA)K+=)?^82od~;p0fLoBO;Gzb~@m9oYobn zfIR`eJ4g>6$AN`5W}80X8Zbj|1S#A2Ty$>Pt%_fi0^1e8E=1-xAu`{p&9|tvbG6Rk zt!9+YL0sNNl#{6V%O-{gCEBZDTF*3J_M;|K5waQPiVJZeAaf{=4c_Go#bfjMd8g z6)?sG`D|x+1cK9g0ShYhd@$TFz=k-(HA2G_mvvMPqE#QoIk8uypQ?xUFg07cq{QEun#s;NcX7~?CJ-*3eQ@%`1_$s_C~J=#W2(>r%g2$AwD9W2j^#s>56}g1(57L=`3`RBJ_q-98)R3YrT=>q3a86LyZn z#fx|Ibtr#Z1qIocuKx*O)PUJuO9cEe#I9TQ`>tC_sO75_SJ-naf#uR0;q*YQt(wcq zc@n1Bqy&^aE~EAN-}q|OerEFS4L`p3 z^P^|?{B*JBTV1Ekd-#zDeV^>6F+b5hUeqZ%czce3>I3`*)9W9pvX-A9n%@VNgz@01 z15g#!Xq8VE`j@YH?xAhoPfvb$_VU2Dy0q>)pds&0Gf-K2o&Jpcz;ODRpiGndc;9fY zs`u7WYhN32wqz6^Aey^^4@Ony&peFkj1s<&r+(J=;)PE>`srfUyIpg~7f+t%qm!OO z#cvLM(u>ILrsl|cVb zf|iJ|WFy>%vwI;Erml5T7bdKA#hrCh7bSDJ`hvCeV|pumj)`liRp=N#x2~ey=Q19~ zAu9c<$PuQ{^ewwj_-C9|X5_#PDnf0izUdjhk1Giz_QXPfY8kI!bd z33u(yP57YQM8Q@q_8?1Pjo4y*Qp`r?gXUs01)s&@iYJQ!kEvoyUe-S%MlS_PP8`}o z-JCOg09zb^zn>M>7EV%t^@SahL-bb^;_P3U>ca_Rz>!9jo(jET89#40*^fA0a=jG! z4P`ot{*BdOO4B-O@=Gu*2UrKE*^L<2MG$OaA(<474|j%RiE&6l zqTxQiV1%9s*eA2MJ^C^PRFDN+1@}ln8E8)cXQtVgi~szFw=-Jf#5`(vi^>h zy8pM%g`0W<<=or7acM?|k5$`FM+`t(r+3AfO-02}5E!617-^c4!z6qbzz;1Jt8 zPEh3%N{OF`j=PHLi({x)JOC%|Fm&MSbR*wrLhI?RXb1aHxm}+L_Xo$xEnRJuZ~EOq ze$p9!73bgrrQs7e6{i>@a8}O47UOWU5`GG91|3D=wok_gPW&iwcw<$7?u1{fw8Ot+ zunPQ@0K{6gl{h6S&L~gktHc?pf(aGtk)y){uQ!cIXH#B z9tx=*vYCrfo8u$S#Wu~wp>|lk?CqfWwjEk)3gvcQ`1O`@!vTi%_y-$m@u4_(^JXg_ zTT{s^t4j*k!S8T!H6SXNXl<6tz?PjjXY7;XH{YTrkNS;DB|XTjlpYbB#*`)>SQRR3Psu&9(pkRCca0 zQk`WSf6m-5dtqTHwXM5owX)!)WkE~ov}%h`+NwJxt-{!B)s7!f1dGP*G?+%mOH;G4 zRT>sFMwen@+$L(wCKx|}(WbD8#t(RjA)7{H06$rlAnc64|MQ-+JH^I?_vAhA^|?Rq zd(N55bBG|4-*x3-#X@=bV(uq17k@X%EkXP+&T2~@#`!$t(l0OZx3!;NdU4aji~Jsd zr;9RA*I(tY)MNZf>xs*s{m12F&kvQu*LCNf8u~`#n|xhY=2@l5MSdl}m@e~UFaG+U z^1uFHAO8BEFZ(}Ia$WyODZ8O^!BDI2#ZcS}+;rj9rO&7P_!HK9xtlmSbn)5CPv=+~ ziY6G5{Y9RXDQZ!aCFh7gm?HjRkvgB1Q7=a$)Hg&MsBa|BVML6=d#GIFhGeM&R)KP&C#Eul9$%;`>DrBbKfX>lIW*@io(JH(w@*xDxcmD0jiFKRk7 zra7LHnr0K@TVtyEym*G%o_r+KV)zbmw3HGoq2)a>RN$&z(Tq3`cUo{+@03)EQhP4I z(^ijxwIW{HyqC6%0zDyhT5ZB-`OMSpO1sgS4)x9njWY%XpE-DW8YeE;v#|~<3zOn19yyV4CLUcf*T1)>rQw(d=QD;$ zv?dwRv-8plTr&e{;g4Wu;G2fScs6afX>7rmKE2SB+`>XD!40fygSK+Aqj&O9Bw#B6XtLZ7M%_r03S1*7BWlA zvavXFeC^X7yVc=)sTX7 z-8p2oMxat+sAe^|5SM||mbZr0a*HF6;}%rCb3XPrwa^q$p5$qZb@w@~tHm+tFmPK# z#;a18CvR|^OQXYhM!c_xdy*uV=Pc1W;U1MxlE-)Z{Nk<@4FTiOY+^%k-WvE17^1zA zbH*1VL%id7KAGJ`E664Nc#w|O2^``w0?{_Om-$)p=j#Tj; zCJ$CibYnbfg|)2GcPA|4^W`I=FW*i$bx3v$mrGWN<%Tl$mK}h_>ezM4>rRJJVRYXJ z96BY|HXb|Oaox15?l)V7Lvll5xIL%6Pc6IzXgu6C5;zX{#bIoJ=Tekh%3yQkRbnTa zk@SqDcNYftiOXVwW=ILgtpbYgCDe=ydn3CNVthmgU{GqL?L{R zkhcd2vAErSK`6x?eC>72>V#1IH4%}2L&(HW5Iy)MLN=b{c#H_ge;{z^}rDT(FKciF=%~{am5* z_T{L^wfU*2pLoPyA&Bk@YY~fhm3@tHx;NU_i9HMUd!-?@Qhtg@L^f0hhsSw>jOO3g`&W{gQ8PkhYihEa`e(x(gE0@&RIHUg^l4~O_(IHS?)t#0B%A}(mwW5#(=s{=u}ue%J*0$>JX)4r zu8aGHJ77(?k__TrWuHqSjDZ)gaLW5=h|nJTL`T+C$+ay`ic2o9QA+G7yh%!XZz=YJ z&>OzGR$O+$$af!cohC3zDJqqikEHMQOYWVKDA+%gH^i;buf8|nd1W-Z9KEmV(vC0= zz+dp95*EoLPlj{e{Vc^)saHS}DQmg4YVwd|4$~*BZ||7Xv=7k+7m8G$Jo7#`cl#%9c7L zSEvhPzhg}?PkPk~Nnry?rkOd1PyD_Fb#aw=>N4=itI{!7k$b&*!oHIR*9yl&*P^y$ zx1}VRL`^tVE{pk*PbdW)_c1QXddPwZQpn2M!}^g_`qAtlx%L%}rhwDj5&_xw{NHCT ztqQFcUwNM-zOk()RPv*C%j1vVdYiqS^Lks)d4y*-%?ujS$`VxINN4@*qsLa;2Ck65 zqNP6K`6BZK=ZGJJboFr^QQyk0zI_B3mVUI4Z{xZtIw`K1+G_-<)mh<6e6zikK=W_o z?qx0Uc;9L7;!S{e^A3x9fx4eJSm^C255~}M;YTP5bik)omh^}No?my8k6R78wbG2ul(|zc@+?>^S*^T> zHe=AM<$iC~(j5JRR_kR>nftTyL7OQurm{>wcxQx1b^5CPWZXsgW=CvJJX1Cc zGtp$>Lg#F5l)nAodD0sBSCHpP_}$1H@D}etp1L(MKeA@#`Sxsa%o^E2YxEur{e?q5 zzag01QETMpYzEv_!4zJyN>9})#T>N%WtBWUXLi_JdODh>Y?f2eWcG&WfM~L?oX2!4 zn#|u~&0g$~Jz|d_MAM3QQ1?pLTnR|T7IMF)!q-R`v>bmo2XrSa5lZUgDPM1O:fallback_fonts:: # An array of font names. Each name must be the name of an AFM font or - # the name that was used to register a family of TTF fonts (see + # the name that was used to register a family of external fonts (see # Prawn::Document#font_families). If present, then each glyph will be # rendered using the first font that includes the glyph, starting with # the current font and then moving through :fallback_fonts from diff --git a/manual/text/line_wrapping.rb b/manual/text/line_wrapping.rb index cf6c1883c..2357d87d3 100644 --- a/manual/text/line_wrapping.rb +++ b/manual/text/line_wrapping.rb @@ -5,7 +5,8 @@ # display space without allowing for a break. # # For writing styles that do not make use of spaces, the zero width space serves -# to mark word boundaries. Zero width spaces are available only with TTF fonts. +# to mark word boundaries. Zero width spaces are available only with external +# fonts. require_relative '../example_helper' diff --git a/manual/text/registering_families.rb b/manual/text/registering_families.rb index bb891018c..b1f99f25e 100644 --- a/manual/text/registering_families.rb +++ b/manual/text/registering_families.rb @@ -12,7 +12,7 @@ filename = File.basename(__FILE__).gsub('.rb', '.pdf') Prawn::ManualBuilder::Example.generate(filename) do - # Registering a single TTF font + # Registering a single external font font_families.update( 'DejaVu Sans' => { normal: "#{Prawn::DATADIR}/fonts/DejaVuSans.ttf" diff --git a/manual/text/utf8.rb b/manual/text/utf8.rb index d7fbd1037..348f64e07 100644 --- a/manual/text/utf8.rb +++ b/manual/text/utf8.rb @@ -17,7 +17,7 @@ move_down 20 - text 'For full internationalized text support, we need to use TTF fonts:' + text 'For full internationalized text support, we need to use external fonts:' move_down 20 font("#{Prawn::DATADIR}/fonts/DejaVuSans.ttf") do diff --git a/prawn.gemspec b/prawn.gemspec index 0d78f984c..b8dbe51a9 100644 --- a/prawn.gemspec +++ b/prawn.gemspec @@ -37,7 +37,7 @@ Gem::Specification.new do |spec| spec.licenses = %w[PRAWN GPL-2.0 GPL-3.0] spec.add_dependency('pdf-core', '~> 0.8.1') - spec.add_dependency('ttfunk', '~> 1.5') + spec.add_dependency('ttfunk', '~> 1.6') spec.add_development_dependency('pdf-inspector', '>= 1.2.1', '< 2.0.a') spec.add_development_dependency('pdf-reader', ['~> 1.4', '>= 1.4.1']) diff --git a/spec/prawn/font_spec.rb b/spec/prawn/font_spec.rb index f654e305f..0df17f3a9 100644 --- a/spec/prawn/font_spec.rb +++ b/spec/prawn/font_spec.rb @@ -457,6 +457,37 @@ def page_should_not_include_font(font) end end + describe 'OTF fonts' do + let(:font) { pdf.find_font "#{Prawn::DATADIR}/fonts/Bodoni-Book.otf" } + + it 'calculates string width taking into account accented characters' do + expect(font.compute_width_of('é', size: 12)).to eq( + font.compute_width_of('e', size: 12) + ) + end + + it 'uses the ascender, descender, and cap height from the OTF verbatim' do + # These metrics are relative to the font's own bbox. They should not be + # scaled with font size. + ref = pdf.ref!({}) + font.send :embed, ref, 0 + + # Pull out the embedded font descriptor + descriptor = ref.data[:FontDescriptor].data + expect(descriptor[:Ascent]).to eq(1023) + expect(descriptor[:Descent]).to eq(-200) + expect(descriptor[:CapHeight]).to eq(3072) + end + + describe 'when normalizing encoding' do + it 'does not modify the original string with normalize_encoding()' do + original = 'Foo' + normalized = font.normalize_encoding(original) + expect(original).to_not be_equal(normalized) + end + end + end + describe 'DFont fonts' do let(:file) { "#{Prawn::DATADIR}/fonts/Panic+Sans.dfont" } diff --git a/spec/prawn_manual_spec.rb b/spec/prawn_manual_spec.rb index 1f1c6e8a0..4f66897a3 100644 --- a/spec/prawn_manual_spec.rb +++ b/spec/prawn_manual_spec.rb @@ -6,11 +6,11 @@ MANUAL_HASH = case RUBY_ENGINE when 'ruby' - '85d2ded146d1e6659e9db389a071896d6e57d7cc4210c6b7fc75fc4afe2b5697'\ - '8a86baca785acd717964619dc234327ef59f5ba6d750dfd626279af0166f6c5e' + 'b38bd8aaa7b419a2f594ee8837cd62f813141000393995b0c0456644b823a62a'\ + '2f8031b2db0fc9e7c544b3946a9b0e60570d510564e6fed3931e0717dd49188a' when 'jruby' - '85d2ded146d1e6659e9db389a071896d6e57d7cc4210c6b7fc75fc4afe2b5697'\ - '8a86baca785acd717964619dc234327ef59f5ba6d750dfd626279af0166f6c5e' + 'b38bd8aaa7b419a2f594ee8837cd62f813141000393995b0c0456644b823a62a'\ + '2f8031b2db0fc9e7c544b3946a9b0e60570d510564e6fed3931e0717dd49188a' end RSpec.describe Prawn do