makefonts.php 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394
  1. <?php
  2. ############################
  3. set_time_limit(1200);
  4. ini_set("memory_limit","128M");
  5. ############################
  6. $cpages = array('win-1252','win-1251','iso-8859-2','iso-8859-4','iso-8859-7','iso-8859-9');
  7. $map_path = '../maps/';
  8. if (isset($_REQUEST['step'])) { $step = $_REQUEST['step']; }
  9. else $step = '';
  10. echo '<html><body>';
  11. if (isset($_REQUEST['movefonts']) && $_REQUEST['movefonts']==1) { movefonts(); }
  12. if (isset($_REQUEST['moveunifonts']) && $_REQUEST['moveunifonts']==1) { moveunifonts(); }
  13. // INITIAL INSTRUCTIONS
  14. if (!$step) {
  15. echo '<h2>mPDF Utility to generate font files</h2>';
  16. echo '<p>If you have added fonts to a previous version of mDPF and want to create the extra files needed for embedded subsets - and you still have the [fontname].ufm and [fontname].t1a files: copy the .ufm and .t1a files to this directory and go directly to <a href="makefonts.php?step=7">execute Step 7</a></p>';
  17. echo '<p>Otherwise:</p>';
  18. echo '<h3>Prepare the source files</h3>';
  19. echo '<p>Copy the [fontname].ttf files to this current directory</p>';
  20. echo '<p>Rename the .ttf files if necessary:</p>';
  21. echo '<p>Only characters a-z (lowercase only), 0-9 and _ (underscore)</p>';
  22. echo '<p>Style variants should be fontname.ttf fontnameb.ttf fontnamei.ttf fontnamebi.ttf</p>';
  23. echo '<p>If you only want Unicode TrueType font files, go directly to <a href="makefonts.php?step=5">execute Step 5</a></p>';
  24. echo '<p>Otherwise go to <a href="makefonts.php?step=1">Step 1 - Unibyte (codepage) font files - A</a></p>';
  25. }
  26. // STEP 1 -
  27. else if ($step==1) {
  28. echo '<h3>Step 1 - Unibyte (codepage) font files - A</h3>';
  29. echo '<p>The next step will create and execute a file "makefonts.bat" in the current directory</p>';
  30. echo '<p><a href="makefonts.php?step=2">Execute</a> and go to Step 2</p>';
  31. }
  32. // STEP 2 -
  33. else if ($step==2) {
  34. makebatlist('C');
  35. exec('makefonts.bat');
  36. echo '<h3>Step 2 - Unibyte (codepage) font files - B</h3>';
  37. echo '<p>Check that you have the following files in the current directory (for each of your original .ttf files):</p>';
  38. echo '<ul><li>fontname.afm</li>';
  39. echo '<li>fontname.pfb</li>';
  40. echo '<li>fontname-win-1251.afm</li>';
  41. echo '<li>fontname-win-1251.pfb</li>';
  42. echo '<li>fontname-iso-8859-2.afm</li>';
  43. echo '<li>fontname-iso-8859-2.pfb</li>';
  44. echo '<li>fontname-iso-8859-4.afm</li>';
  45. echo '<li>fontname-iso-8859-4.pfb</li>';
  46. echo '<li>fontname-iso-8859-7.afm</li>';
  47. echo '<li>fontname-iso-8859-7.pfb</li>';
  48. echo '<li>fontname-iso-8859-9.afm</li>';
  49. echo '<li>fontname-iso-8859-9.pfb</li></ul>';
  50. echo '<hr />';
  51. echo '<p>If these files are not present:</p>';
  52. echo '<p>Ensure that the file "ttf2pt1.exe" is in the current directory</p>';
  53. echo '<p>Execute/Run the batch file "makefonts.bat" - (double click on the file in Windows)</p>';
  54. echo '<p>When the files are there go to step 3.</p>';
  55. echo '<p>The next step will generate the files for mPDF in the current directory</p>';
  56. echo '<p>Execute <a href="makefonts.php?step=3">Step 3</a></p>';
  57. }
  58. // STEP 3 -
  59. else if ($step==3) {
  60. $ff = scandir('./');
  61. foreach($ff AS $f) {
  62. if (substr($f,-4,4)=='.ttf') {
  63. $file = substr($f,0,(strlen($f)-4));
  64. foreach($cpages AS $cpage) {
  65. $success = false;
  66. if ($cpage =='win-1252') {
  67. $success = MakeFont($file .'.pfb', $file .'.afm', 'win-1252');
  68. if ($success) { @unlink($file .'.pfb'); @unlink($file .'.afm'); }
  69. }
  70. else {
  71. $success = MakeFont($file .'-'.$cpage.'.pfb', $file .'-'.$cpage.'.afm', $cpage);
  72. if ($success) { @unlink($file .'-'.$cpage.'.pfb'); @unlink($file .'-'.$cpage.'.afm'); }
  73. }
  74. }
  75. }
  76. }
  77. echo '<h3>Step 3 - Unibyte (codepage) font files - C</h3>';
  78. echo '<p>When you have done that, check you have the following files (for each of your original .ttf files):</p>';
  79. echo '<ul><li>fontname.z</li>';
  80. echo '<li>fontname.php</li>';
  81. echo '<li>fontname-win-1251.z</li>';
  82. echo '<li>fontname-win-1251.php</li>';
  83. echo '<li>fontname-iso-8859-2.z</li>';
  84. echo '<li>fontname-iso-8859-2.php</li>';
  85. echo '<li>fontname-iso-8859-4.z</li>';
  86. echo '<li>fontname-iso-8859-4.php</li>';
  87. echo '<li>fontname-iso-8859-7.z</li>';
  88. echo '<li>fontname-iso-8859-7.php</li>';
  89. echo '<li>fontname-iso-8859-9.z</li>';
  90. echo '<li>fontname-iso-8859-9.php</li></ul>';
  91. echo '<li>NB The .pfb and .afm files have been deleted.</p>';
  92. echo '<p>Go to <a href="makefonts.php?step=4">Step 4</a></p>';
  93. }
  94. // STEP 4 -
  95. else if ($step==4) {
  96. echo '<h3>Step 4 - Unibyte (codepage) font files - D</h3>';
  97. echo '<p>Copy all of the .php and .z files to the folder [path to mpdf]/mpdf/fonts/</p>';
  98. echo '<p>(This <a href="makefonts.php?step=4&movefonts=1">link</a> may do the job for you. <b>Note:</b> This will not overwrite files, so you may need to delete files first from the [path to mpdf]/mpdf/fonts/ folder)</p>';
  99. echo '<p>Add the font names to config_fonts.php (and if appropriate to config_cp.php)</p>';
  100. echo '<p>You have now completed font file generation for the codepage Type 1 font files.</p>';
  101. echo '<p>If you do not want to create the Unicode TrueType font files you can stop here, or ';
  102. echo 'optionally you can <a href="makefonts.php?step=9">tidy up</a> which will delete all the font files except your .ttf files from the current directory.</p>';
  103. echo '<p>Now we will create the Unicode TrueType font files.</p>';
  104. echo '<p>NB This will also delete any remaining .php and .z files from the current directory.</p>';
  105. echo '<p>To continue with Unicode TrueType font files, execute <a href="makefonts.php?step=5">Step 5</a></p>';
  106. }
  107. // STEP 5 -
  108. else if ($step==5) {
  109. // First get rid of any .php and .z files left
  110. $ff = scandir('./');
  111. foreach($ff AS $f) {
  112. if (substr($f,-4,4)=='.ttf') {
  113. $file = substr($f,0,(strlen($f)-4));
  114. foreach($cpages AS $cpage) {
  115. if ($cpage =='win-1252') {
  116. @unlink($file .'.z'); @unlink($file .'.php');
  117. }
  118. else {
  119. @unlink($file .'-'.$cpage.'.z'); @unlink($file .'-'.$cpage.'.php');
  120. }
  121. }
  122. }
  123. }
  124. makebatlist('U');
  125. exec('makefonts.bat');
  126. echo '<h3>Step 5 - Unicode TrueType font files - A</h3>';
  127. echo '<p>Check that the following files have been created in the current directory (for each of your original .ttf files):</p>';
  128. echo '<ul><li>fontname.t1a</li>';
  129. echo '<li>fontname.ufm</li>';
  130. echo '<li>fontname.afm</li></ul>';
  131. echo '<hr />';
  132. echo '<p>If these files are not present:</p>';
  133. echo '<p>Ensure that the file "ttf2ufm.exe" is in the current directory</p>';
  134. echo '<p>Execute/Run the batch file "makefonts.bat" - (double click on the file in Windows)</p>';
  135. echo '<p>When the files are there, go on to step 6.</p>';
  136. echo '<p>The next step will generate the core files for mPDF in the current directory</p>';
  137. echo '<p><a href="makefonts.php?step=6">Execute</a> Step 6</p>';
  138. }
  139. // STEP 6 -
  140. else if ($step==6) {
  141. $ff = scandir('./');
  142. foreach($ff AS $f) {
  143. if (substr($f,-4,4)=='.ttf') {
  144. $file = substr($f,0,(strlen($f)-4));
  145. MakeFontTTF($file .'.ttf', $file.'.ufm');
  146. @unlink($file .'.afm');
  147. }
  148. }
  149. echo '<h3>Step 6 - Unicode TrueType font files - B</h3>';
  150. echo '<p>When you have done that, check you have the following files (for each of your original .ttf files):</p>';
  151. echo '<ul><li>fontname.z</li>';
  152. echo '<li>fontname.ctg.z</li>';
  153. echo '<li>fontname.php</li></ul>';
  154. echo '<p>NB The .afm files have been deleted (but .t1a and .ufm should remain).</p>';
  155. echo '<p>The next step will generate the additional files for embedded subsets</p>';
  156. echo '<p><a href="makefonts.php?step=7">Execute</a> Step 7 (NB This may take several minutes for large font files; you may need to increase the time-limit or memory-limits - see the top of the /makefont/makefonts.php file)</p>';
  157. }
  158. // STEP 7 - Create .uni2gn.php files, and .dat / .dat.php
  159. else if ($step==7) {
  160. $cs_commands = array(
  161. 'abs' => array(12, 9 ),
  162. 'add' => array(12, 10 ),
  163. 'and' => array(12, 3 ),
  164. 'blend' => array(16, -1 ),
  165. 'callgsubr' => array(29, -1 ),
  166. 'callothersubr' => array(12, 16 ),
  167. 'callsubr' => array(10, -1 ),
  168. 'closepath' => array(9, -1 ),
  169. 'cntrmask' => array(20, -1 ),
  170. 'div' => array(12, 12 ),
  171. 'dotsection' => array(12, 0 ),
  172. 'drop' => array(12, 18 ),
  173. 'dup' => array(12, 27 ),
  174. 'endchar' => array(14, -1 ),
  175. 'eq' => array(12, 15 ),
  176. 'error' => array(0, -1 ),
  177. 'escape' => array(12, -1 ),
  178. 'exch' => array(12, 28 ),
  179. 'flex' => array(12, 35 ),
  180. 'flex1' => array(12, 37 ),
  181. 'get' => array(12, 21 ),
  182. 'hflex' => array(12, 34 ),
  183. 'hflex1' => array(12, 36 ),
  184. 'hhcurveto' => array(27, -1 ),
  185. 'hintmask' => array(19, -1 ),
  186. 'hlineto' => array(6, -1 ),
  187. 'hmoveto' => array(22, -1 ),
  188. 'hsbw' => array(13, -1 ),
  189. 'hstem' => array(1, -1 ),
  190. 'hstem3' => array(12, 2 ),
  191. 'hstemhm' => array(18, -1 ),
  192. 'hvcurveto' => array(31, -1 ),
  193. 'ifelse' => array(12, 22 ),
  194. 'index' => array(12, 29 ),
  195. 'load' => array(12, 13 ),
  196. 'mul' => array(12, 24 ),
  197. 'neg' => array(12, 14 ),
  198. 'not' => array(12, 5 ),
  199. 'or' => array(12, 4 ),
  200. 'pop' => array(12, 17 ),
  201. 'put' => array(12, 20 ),
  202. 'random' => array(12, 23 ),
  203. 'rcurveline' => array(24, -1 ),
  204. 'return' => array(11, -1 ),
  205. 'rlinecurve' => array(25, -1 ),
  206. 'rlineto' => array(5, -1 ),
  207. 'rmoveto' => array(21, -1 ),
  208. 'roll' => array(12, 30 ),
  209. 'rrcurveto' => array(8, -1 ),
  210. 'sbw' => array(12, 7 ),
  211. 'seac' => array(12, 6 ),
  212. 'setcurrentpoint' => array(12, 33 ),
  213. 'sqrt' => array(12, 26 ),
  214. 'store' => array(12, 8 ),
  215. 'sub' => array(12, 11 ),
  216. 'vhcurveto' => array(30, -1 ),
  217. 'vlineto' => array(7, -1 ),
  218. 'vmoveto' => array(4, -1 ),
  219. 'vstem' => array(3, -1 ),
  220. 'vstem3' => array(12, 1 ),
  221. 'vstemhm' => array(23, -1 ),
  222. 'vvcurveto' => array(26, -1 )
  223. );
  224. $lenIV = 4;
  225. $cs_start = 'RD';
  226. // Read uni2gn [code-point to glyph-name] from .ufm file if exists
  227. $ff = scandir('./');
  228. foreach($ff AS $f) {
  229. if (substr($f,-4,4)=='.ufm') {
  230. $file = substr($f,0,(strpos($f,'.')));
  231. if (!file_exists($file.'.t1a')) { die("You must have both .ufm and .t1a files in the current directory ('.$f.')"); }
  232. $uni2gn = array();
  233. $a=file($file.'.ufm');
  234. if(empty($a)) { die('ufm file found but with error'); }
  235. foreach($a as $l) {
  236. $e=explode(' ',chop($l));
  237. if(count($e)<2) { continue; }
  238. if($e[0]=='U') {
  239. $cc=(int)$e[1];
  240. if ($cc != -1) { $uni2gn[$cc] = $e[7]; }
  241. }
  242. }
  243. $s = '<?php
  244. $this->uni2gn = '.var_export($uni2gn, true).';
  245. ?>';
  246. file_put_contents($file.'.uni2gn.php', $s);
  247. // echo "File created: ".$file.'.uni2gn.php'."<br />\n";
  248. // **************** DAT
  249. $file_ip = '';
  250. $file_op = '';
  251. $op_buffer = '';
  252. $if_header = '';
  253. $if_FullName = '';
  254. $if_FontName = '';
  255. $if_FamilyName = '';
  256. $if_encs = array();
  257. $if_eexec_start = '';
  258. $if_Subrs = array();
  259. $if_CharStrings = array();
  260. $pdf_diffstr = ''; // String of /Diffs for PDF file
  261. $of_encodingstr = '';
  262. $useChars = array();
  263. //echo "Processing font: ".$file."... <br />\n";
  264. $subrs='';
  265. $CharStrings='';
  266. $Encoding='';
  267. $file_ip = $file.'.t1a';
  268. $ifh = fopen($file_ip, "rb");
  269. $target = false;
  270. $rem = '';
  271. // Header
  272. $if_header = '';
  273. while(!$target && !feof($ifh)) {
  274. $x = fread($ifh, 2048);
  275. $x = preg_replace("/\r/","",$x);
  276. $if_header .= $x;
  277. if (preg_match('/(.*?)\/Encoding (.*)/s', $if_header , $m)) {
  278. $if_header = $m[1];
  279. $rem = '/Encoding '.$m[2];
  280. $target = true;
  281. }
  282. }
  283. if (feof($ifh)) { die("Error parsing ".$file_ip ); }
  284. // Discard
  285. $target = false;
  286. if (preg_match('/(.*?)currentfile eexec(.*)/s', $rem, $m)) {
  287. $rem = $m[2];
  288. $target = true;
  289. }
  290. $discard = '';
  291. while(!$target && !feof($ifh)) {
  292. $x = fread($ifh, 2048);
  293. $x = preg_replace("/\r/","",$x);
  294. $discard .= $x;
  295. if (preg_match('/(.*?)currentfile eexec(.*)/s', $discard , $m)) {
  296. //$discard = $m[1];
  297. $rem = $m[2];
  298. $target = true;
  299. }
  300. }
  301. if (feof($ifh)) { die("Error parsing ".$file_ip ); }
  302. // eexec_start
  303. $target = false;
  304. if (preg_match('/(.*?)\/Subrs (.*)/s', $rem, $m)) {
  305. $if_eexec_start = $m[1];
  306. $rem = $m[2];
  307. $target = true;
  308. }
  309. else { $if_eexec_start = $rem; }
  310. while(!$target && !feof($ifh)) {
  311. $x = fread($ifh, 2048);
  312. $x = preg_replace("/\r/","",$x);
  313. $if_eexec_start .= $x;
  314. if (preg_match('/(.*?)\/Subrs (.*)/s', $if_eexec_start , $m)) {
  315. $if_eexec_start = $m[1];
  316. $rem = $m[2];
  317. $target = true;
  318. }
  319. }
  320. if (feof($ifh)) { die("Error parsing ".$file_ip ); }
  321. // WRITE if_header to .dat
  322. $offset = 0;
  323. $fh = fopen($file.'.dat', "wb");
  324. _fwriteint($fh, strlen($if_header));
  325. fwrite($fh, $if_header);
  326. $offset += strlen($if_header) + 4;
  327. // WRITE if_eexec_start to .dat
  328. _fwriteint($fh, strlen($if_eexec_start));
  329. fwrite($fh, $if_eexec_start);
  330. $offset += strlen($if_eexec_start) + 4;
  331. unset($if_header );
  332. unset($if_eexec_start );
  333. // SUBROUTINES
  334. $if_Subrs = array();
  335. $target = false;
  336. if (preg_match('/(.*?)\/CharStrings (.*)/s', $rem, $m)) {
  337. $subrs = $m[1];
  338. $rem = $m[2];
  339. $target = true;
  340. }
  341. else { $subrs = $rem; }
  342. preg_match_all('/dup\s+(\d+)\s+\{(.*?)\}\s+NP/s',$subrs, $mm);
  343. for($i=0;$i<count($mm[0]);$i++) {
  344. if ($mm[1][$i] > 4) { $if_Subrs[$mm[1][$i]] = preg_replace('/\s+return/', '', $mm[2][$i]); } // mPDF 4.4.016
  345. }
  346. preg_match('/(.*}\s+NP)(.*)/s', $subrs, $mm);
  347. if(isset($mm[2])) { $subrs = $mm[2]; } // mPDF 4.4.016
  348. while(!$target && !feof($ifh)) {
  349. $x = fread($ifh, 8192);
  350. $x = preg_replace("/\r/","",$x);
  351. $subrs .= $x;
  352. if (preg_match('/(.*?)\/CharStrings (.*)/s', $subrs , $m)) {
  353. $subrs = $m[1];
  354. $rem = $m[2];
  355. $target = true;
  356. }
  357. $subrs = preg_replace("/\r\n/","\n",$subrs);
  358. preg_match_all('/dup\s+(\d+)\s+\{(.*?)\}\s+NP/s',$subrs, $mm);
  359. for($i=0;$i<count($mm[0]);$i++) {
  360. if ($mm[1][$i] > 4) { $if_Subrs[$mm[1][$i]] = preg_replace('/\s+return/', '', $mm[2][$i]); } // mPDF 4.4.016
  361. }
  362. preg_match('/(.*}\s+NP)(.*)/s', $subrs, $mm);
  363. if(isset($mm[2])) { $subrs = $mm[2]; } // mPDF 4.5.003
  364. }
  365. if (feof($ifh)) { die("Error parsing ".$file_ip ); }
  366. // CHARSTRINGS
  367. $offs = array();
  368. $target = false;
  369. if (preg_match('/(.*?)mark currentfile closefile/s', $rem, $m)) {
  370. $CharStrings = $m[1];
  371. $target = true;
  372. }
  373. else { $CharStrings = $rem; }
  374. preg_match_all('/\/([a-zA-Z0-9._]+)\s+\{(.*?endchar\s+)\}\s+ND/s',$CharStrings, $m);
  375. for($i=0;$i<count($m[0]);$i++) {
  376. $cp = $m[1][$i];
  377. $cs = $m[2][$i];
  378. $cs = preg_replace('/(\d+) 4 (callgsubr|callothersubr|callsubr)/e', '" ".$if_Subrs[\\1]." "', $cs);
  379. $cs = preg_replace('/\s+/',' ',$cs);
  380. $cb = parse_charstring($cs);
  381. $offs[$cp] = $offset;
  382. // WRITE $cb to .dat AND save position in file
  383. _fwriteint($fh, strlen($cb));
  384. fwrite($fh, $cb);
  385. $offset += strlen($cb) + 4;
  386. }
  387. preg_match('/(.*}\s+ND)(.*)/s', $CharStrings, $mm);
  388. if(isset($mm[2])) { $CharStrings = $mm[2]; } // mPDF 4.4.016
  389. while(!$target && !feof($ifh)) {
  390. $x = fread($ifh, 8192);
  391. $x = preg_replace("/\r/","",$x);
  392. $CharStrings .= $x;
  393. if (preg_match('/(.*?)mark currentfile closefile(.*)/s', $CharStrings , $m)) {
  394. $CharStrings = $m[1];
  395. $target = true;
  396. }
  397. preg_match_all('/\/([a-zA-Z0-9._]+)\s+\{(.*?endchar\s+)\}\s+ND/s',$CharStrings, $m);
  398. for($i=0;$i<count($m[0]);$i++) {
  399. $cp = $m[1][$i];
  400. $cs = $m[2][$i];
  401. $cs = preg_replace('/(\d+) 4 (callgsubr|callothersubr|callsubr)/e', '" ".$if_Subrs[\\1]." "', $cs);
  402. $cs = preg_replace('/\s+/',' ',$cs);
  403. $cb = parse_charstring($cs);
  404. $offs[$cp] = $offset;
  405. // WRITE $cb to .dat AND save position in file
  406. _fwriteint($fh, strlen($cb));
  407. fwrite($fh, $cb);
  408. $offset += strlen($cb) + 4;
  409. }
  410. preg_match('/(.*}\s+ND)(.*)/s', $CharStrings, $mm);
  411. if(isset($mm[2])) { $CharStrings = $mm[2]; } // mPDF 4.4.016
  412. }
  413. fclose($ifh);
  414. fclose($fh);
  415. unset($if_Subrs);
  416. unset($CharStrings);
  417. unset($fi);
  418. // WRITE offsets to .dat.php
  419. $fh = fopen($file.'.dat.php', "w");
  420. $s = '<?php $offs = '.var_export($offs, true).'; ?>';
  421. fwrite($fh, $s);
  422. fclose($fh);
  423. // echo "Files created: ".$file." [.dat|.dat.php]<br />\n";
  424. // **************** DAT
  425. }
  426. }
  427. echo '<h3>Step 7 - Unicode TrueType font files - C</h3>';
  428. echo '<p>When you have done that, check you have the following files (for each of your original .ttf files):</p>';
  429. echo '<ul><li>fontname.uni2gn.php</li>';
  430. echo '<li>fontname.dat</li>';
  431. echo '<li>fontname.dat.php</li></ul>';
  432. echo '<p>If you have only run Step 7 to update previously added fonts, now just copy these files to your /unifont/ folder</p>';
  433. echo '<p>Go to <a href="makefonts.php?step=8">Step 8</a></p>';
  434. }
  435. // STEP 8 -
  436. else if ($step==8) {
  437. echo '<p>Copy all of the following files to the folder [path to mpdf]/mpdf/unifont/</p>';
  438. echo '<p>(6 for each font/style)</p>';
  439. echo '<p>(This <a href="makefonts.php?step=8&moveunifonts=1">link</a> should do the job for you. <b>Note:</b> This will not overwrite files, so you may need to delete files first from the [path to mpdf]/mpdf/unifont/ folder).</p>';
  440. echo '<ul><li>fontname.z</li>';
  441. echo '<li>fontname.ctg.z</li>';
  442. echo '<li>fontname.php</li>';
  443. echo '<li>fontname.dat</li>';
  444. echo '<li>fontname.dat.php</li>';
  445. echo '<li>fontname.uni2gn.php</li></ul>';
  446. echo '<p>Add the font names to config_fonts.php (and if appropriate to config_cp.php)</p>';
  447. echo '<p>Otherwise you\'re all done!</p>';
  448. echo '<p>Optionally you can <a href="makefonts.php?step=9">tidy up</a> which will delete all the font files except your .ttf files from the current directory.</p>';
  449. }
  450. // STEP 9 -
  451. else if ($step==9) {
  452. $ff = scandir('./');
  453. foreach($ff AS $f) {
  454. if (substr($f,-4,4)=='.ttf') {
  455. $file = substr($f,0,(strlen($f)-4));
  456. @unlink($file .'.afm');
  457. @unlink($file .'.ufm');
  458. @unlink($file .'.t1a');
  459. @unlink($file .'.php');
  460. @unlink($file .'.z');
  461. @unlink($file .'.ctg.z');
  462. @unlink($file .'.dat');
  463. @unlink($file .'.dat.php');
  464. @unlink($file .'.uni2gn.php');
  465. @unlink('makefonts.bat');
  466. foreach($cpages AS $cpage) {
  467. if ($cpage =='win-1252') {
  468. @unlink($file .'.z'); @unlink($file .'.php');
  469. }
  470. else {
  471. @unlink($file .'-'.$cpage.'.z'); @unlink($file .'-'.$cpage.'.php');
  472. }
  473. }
  474. }
  475. }
  476. echo '<p>All done!</p>';
  477. }
  478. echo '</body></html>';
  479. exit;
  480. /*******************************************************************************
  481. * Functions to generate Unicode font .dat files *
  482. *******************************************************************************/
  483. function _fwriteint($fh, $i)
  484. {
  485. //Write a 4-byte integer to file
  486. $s=chr(($i>>24) % 256);
  487. $s.=chr(($i>>16) % 256);
  488. $s.=chr(($i>>8) % 256);
  489. $s.=chr($i % 256);
  490. fwrite($fh, $s);
  491. }
  492. /* This function parses an entire charstring into integers and commands,
  493. outputting bytes through the charstring buffer. */
  494. function parse_charstring($cs) {
  495. global $lenIV, $cs_start, $cs_commands, $cipher_cr ;
  496. /* initializes charstring encryption. */
  497. $buffer = '';
  498. $cipher_cr = 4330;
  499. for ($i = 0; $i < $lenIV; $i++) {
  500. $buffer .= charstring_byte(chr(0));
  501. }
  502. $cc = preg_split('/\s+/',$cs,-1,PREG_SPLIT_NO_EMPTY);
  503. foreach($cc AS $c) {
  504. // Encode the integers according to charstring number encoding
  505. if (preg_match('/^[\-]{0,1}\d+$/',$c)) {
  506. $buffer .= charstring_int($c);
  507. }
  508. // Encode the commands according to charstring command encoding
  509. else if (isset($cs_commands[$c])) {
  510. $one = $cs_commands[$c][0];
  511. $two = $cs_commands[$c][1];
  512. if ($one < 0 || $one > 255)
  513. echo sprintf("bad charstring command number $d in %s in %s", $one, $c, $cs);
  514. else if ($two > 255)
  515. echo sprintf("bad charstring command number $d in %s in %s", $two, $c, $cs);
  516. else if ($two < 0) {
  517. $buffer .= charstring_byte($one);
  518. }
  519. else {
  520. $buffer .= charstring_byte($one);
  521. $buffer .= charstring_byte($two);
  522. }
  523. }
  524. else {
  525. echo sprintf("unknown charstring entry %s in %s", $c, $cs);
  526. }
  527. }
  528. $s = sprintf("%d ", strlen($buffer));
  529. $s .= sprintf("%s ", $cs_start);
  530. $s .= $buffer;
  531. $buffer = '';
  532. return $s;
  533. }
  534. /* This function encrypts and buffers a single byte of charstring data. */
  535. function charstring_byte($v) {
  536. $b = ($v & 0xff);
  537. $c = cencrypt($b);
  538. return chr($c);
  539. }
  540. /* This function encodes an integer according to charstring number encoding. */
  541. function charstring_int($num) {
  542. $c = '';
  543. if ($num >= -107 && $num <= 107) {
  544. $c .= charstring_byte($num + 139);
  545. } else if ($num >= 108 && $num <= 1131) {
  546. $x = $num - 108;
  547. $c .= charstring_byte($x / 256 + 247);
  548. $c .= charstring_byte($x % 256);
  549. } else if ($num >= -1131 && $num <= -108) {
  550. $x = abs($num) - 108;
  551. $c .= charstring_byte($x / 256 + 251);
  552. $c .= charstring_byte($x % 256);
  553. } else if ($num >= (-2147483647-1) && $num <= 2147483647) {
  554. $c .= charstring_byte(255);
  555. $c .= charstring_byte($num >> 24);
  556. $c .= charstring_byte($num >> 16);
  557. $c .= charstring_byte($num >> 8);
  558. $c .= charstring_byte($num);
  559. } else {
  560. echo sprintf("can't format huge number `%d'", $num);
  561. /* output 0 instead */
  562. $c .= charstring_byte(139);
  563. }
  564. return $c;
  565. }
  566. function cencrypt($plain) {
  567. global $lenIV, $cipher_cr;
  568. $c1 = 52845;
  569. $c2 = 22719;
  570. if ($lenIV < 0) return $plain;
  571. $cipher = ($plain ^ ($cipher_cr >> 8));
  572. $cipher_cr = (($cipher + $cipher_cr) * $c1 + $c2) & 0xffff;
  573. return $cipher;
  574. }
  575. /*******************************************************************************
  576. * Other Functions to generate font definition files - Type 1 + Unicode *
  577. *******************************************************************************/
  578. function movefonts() {
  579. global $cpages;
  580. $ff = scandir('./');
  581. foreach($ff AS $f) {
  582. if (substr($f,-4,4)=='.ttf') {
  583. $file = substr($f,0,(strlen($f)-4));
  584. foreach($cpages AS $cpage) {
  585. if ($cpage =='win-1252') {
  586. rename($file .'.php', '../font/'.$file .'.php');
  587. rename($file .'.z', '../font/'.$file .'.z');
  588. }
  589. else {
  590. rename($file .'-'.$cpage.'.php', '../font/'.$file .'-'.$cpage.'.php');
  591. rename($file .'-'.$cpage.'.z', '../font/'.$file .'-'.$cpage.'.z');
  592. }
  593. }
  594. }
  595. }
  596. }
  597. function moveunifonts() {
  598. $ff = scandir('./');
  599. foreach($ff AS $f) {
  600. if (substr($f,-4,4)=='.ttf') {
  601. $file = substr($f,0,(strlen($f)-4));
  602. rename($file .'.dat', '../unifont/'.$file .'.dat');
  603. rename($file .'.dat.php', '../unifont/'.$file .'.dat.php');
  604. rename($file .'.php', '../unifont/'.$file .'.php');
  605. rename($file .'.z', '../unifont/'.$file .'.z');
  606. rename($file .'.ctg.z', '../unifont/'.$file .'.ctg.z');
  607. rename($file .'.uni2gn.php', '../unifont/'.$file .'.uni2gn.php');
  608. }
  609. }
  610. }
  611. function makebatlist($type='U') {
  612. global $cpages;
  613. $bat = '';
  614. $ff = scandir('./');
  615. foreach($ff AS $f) {
  616. if (substr($f,-4,4)=='.ttf') {
  617. $file = substr($f,0,(strlen($f)-4));
  618. // FOR UNIFONTS
  619. if ($type=='U') {
  620. $bat .= 'ttf2ufm -a '.$f." ".$file."\r\n";
  621. }
  622. // FOR FONTS (codepaged)
  623. else {
  624. foreach($cpages AS $cpage) {
  625. if ($cpage =='win-1252') {
  626. $bat .= 'ttf2pt1 -b -L maps/'.$cpage.'.map '.$f." ".$file."\r\n";
  627. }
  628. else {
  629. $bat .= 'ttf2pt1 -b -L maps/'.$cpage.'.map '.$f." ".$file.'-'.$cpage."\r\n";
  630. }
  631. }
  632. }
  633. }
  634. }
  635. file_put_contents('makefonts.bat', $bat);
  636. }
  637. /*******************************************************************************
  638. * Common Functions to generate font definition files - Type 1 + Unicode *
  639. *******************************************************************************/
  640. function SaveToFile($file,$s,$mode='t')
  641. {
  642. $f=fopen($file,'w'.$mode);
  643. if(!$f)
  644. die('Can\'t write to file '.$file);
  645. fwrite($f,$s,strlen($s));
  646. fclose($f);
  647. }
  648. function ReadShort($f)
  649. {
  650. $a=unpack('n1n',fread($f,2));
  651. return $a['n'];
  652. }
  653. function ReadLong($f)
  654. {
  655. $a=unpack('N1N',fread($f,4));
  656. return $a['N'];
  657. }
  658. function CheckTTF($file)
  659. {
  660. //Check if font license allows embedding
  661. $f=fopen($file,'rb');
  662. if(!$f)
  663. die('<B>Error:</B> Can\'t open '.$file);
  664. //Extract number of tables
  665. fseek($f,4,SEEK_CUR);
  666. $nb=ReadShort($f);
  667. fseek($f,6,SEEK_CUR);
  668. //Seek OS/2 table
  669. $found=false;
  670. for($i=0;$i<$nb;$i++)
  671. {
  672. if(fread($f,4)=='OS/2')
  673. {
  674. $found=true;
  675. break;
  676. }
  677. fseek($f,12,SEEK_CUR);
  678. }
  679. if(!$found)
  680. {
  681. fclose($f);
  682. return;
  683. }
  684. fseek($f,4,SEEK_CUR);
  685. $offset=ReadLong($f);
  686. fseek($f,$offset,SEEK_SET);
  687. //Extract fsType flags
  688. fseek($f,8,SEEK_CUR);
  689. $fsType=ReadShort($f);
  690. $rl=($fsType & 0x02)!=0;
  691. $pp=($fsType & 0x04)!=0;
  692. $e=($fsType & 0x08)!=0;
  693. fclose($f);
  694. if($rl and !$pp and !$e)
  695. echo '<B>Warning:</B> font license does not allow embedding';
  696. }
  697. /*******************************************************************************
  698. * Functions to generate font definition files Type 1 *
  699. *******************************************************************************/
  700. function ReadMap($enc)
  701. {
  702. global $map_path;
  703. //Read a map file
  704. // $file=dirname(__FILE__).'/'.strtolower($enc).'.map';
  705. $file=$map_path.strtolower($enc).'.map';
  706. $a=file($file);
  707. if(empty($a))
  708. die('<B>Error:</B> encoding map not found: '.$enc);
  709. $cc2gn=array();
  710. foreach($a as $l)
  711. {
  712. if($l{0}=='!')
  713. {
  714. $e=preg_split('/[ \\t]+/',chop($l));
  715. $cc=hexdec(substr($e[0],1));
  716. $gn=$e[2];
  717. $cc2gn[$cc]=$gn;
  718. }
  719. }
  720. for($i=0;$i<=255;$i++)
  721. if(!isset($cc2gn[$i]))
  722. $cc2gn[$i]='.notdef';
  723. return $cc2gn;
  724. }
  725. function ReadAFM($file,&$map)
  726. {
  727. //Read a font metric file
  728. $a=file($file);
  729. if(empty($a))
  730. die('File not found (ReadAFM) - '.$file);
  731. $widths=array();
  732. $fm=array();
  733. $fix=array('Edot'=>'Edotaccent','edot'=>'edotaccent','Idot'=>'Idotaccent','Zdot'=>'Zdotaccent','zdot'=>'zdotaccent',
  734. 'Odblacute'=>'Ohungarumlaut','odblacute'=>'ohungarumlaut','Udblacute'=>'Uhungarumlaut','udblacute'=>'uhungarumlaut',
  735. 'Gcedilla'=>'Gcommaaccent','gcedilla'=>'gcommaaccent','Kcedilla'=>'Kcommaaccent','kcedilla'=>'kcommaaccent',
  736. 'Lcedilla'=>'Lcommaaccent','lcedilla'=>'lcommaaccent','Ncedilla'=>'Ncommaaccent','ncedilla'=>'ncommaaccent',
  737. 'Rcedilla'=>'Rcommaaccent','rcedilla'=>'rcommaaccent','Scedilla'=>'Scommaaccent','scedilla'=>'scommaaccent',
  738. 'Tcedilla'=>'Tcommaaccent','tcedilla'=>'tcommaaccent','Dslash'=>'Dcroat','dslash'=>'dcroat','Dmacron'=>'Dcroat','dmacron'=>'dcroat',
  739. 'combininggraveaccent'=>'gravecomb','combininghookabove'=>'hookabovecomb','combiningtildeaccent'=>'tildecomb',
  740. 'combiningacuteaccent'=>'acutecomb','combiningdotbelow'=>'dotbelowcomb','dongsign'=>'dong');
  741. foreach($a as $l)
  742. {
  743. $e=explode(' ',chop($l));
  744. if(count($e)<2)
  745. continue;
  746. $code=$e[0];
  747. $param=$e[1];
  748. if($code=='C')
  749. {
  750. //Character metrics
  751. $cc=(int)$e[1];
  752. $w=$e[4];
  753. $gn=$e[7];
  754. if(substr($gn,-4)=='20AC')
  755. $gn='Euro';
  756. if(isset($fix[$gn]))
  757. {
  758. //Fix incorrect glyph name
  759. foreach($map as $c=>$n)
  760. if($n==$fix[$gn])
  761. $map[$c]=$gn;
  762. }
  763. if(empty($map))
  764. {
  765. //Symbolic font: use built-in encoding
  766. $widths[$cc]=$w;
  767. }
  768. else
  769. {
  770. $widths[$gn]=$w;
  771. if($gn=='X')
  772. $fm['CapXHeight']=$e[13];
  773. }
  774. if($gn=='.notdef')
  775. $fm['MissingWidth']=$w;
  776. }
  777. elseif($code=='FontName')
  778. $fm['FontName']=$param;
  779. elseif($code=='Weight')
  780. $fm['Weight']=$param;
  781. elseif($code=='ItalicAngle')
  782. $fm['ItalicAngle']=(double)$param;
  783. elseif($code=='Ascender')
  784. $fm['Ascender']=(int)$param;
  785. elseif($code=='Descender')
  786. $fm['Descender']=(int)$param;
  787. elseif($code=='UnderlineThickness')
  788. $fm['UnderlineThickness']=(int)$param;
  789. elseif($code=='UnderlinePosition')
  790. $fm['UnderlinePosition']=(int)$param;
  791. elseif($code=='IsFixedPitch')
  792. $fm['IsFixedPitch']=($param=='true');
  793. elseif($code=='FontBBox')
  794. $fm['FontBBox']=array($e[1],$e[2],$e[3],$e[4]);
  795. elseif($code=='CapHeight')
  796. $fm['CapHeight']=(int)$param;
  797. elseif($code=='StdVW')
  798. $fm['StdVW']=(int)$param;
  799. }
  800. if(!isset($fm['FontName']))
  801. die('FontName not found');
  802. if(!empty($map))
  803. {
  804. if(!isset($widths['.notdef']))
  805. $widths['.notdef']=600;
  806. if(!isset($widths['Delta']) and isset($widths['increment']))
  807. $widths['Delta']=$widths['increment'];
  808. //Order widths according to map
  809. for($i=0;$i<=255;$i++)
  810. {
  811. if(!isset($widths[$map[$i]]))
  812. {
  813. echo '<B>Warning:</B> character '.$map[$i].' is missing from '.$file.'<BR>';
  814. $widths[$i]=$widths['.notdef'];
  815. }
  816. else
  817. $widths[$i]=$widths[$map[$i]];
  818. }
  819. }
  820. $fm['Widths']=$widths;
  821. return $fm;
  822. }
  823. function MakeFontDescriptor($fm,$symbolic)
  824. {
  825. //Ascent
  826. $asc=(isset($fm['Ascender']) ? $fm['Ascender'] : 1000);
  827. $fd="array('Ascent'=>".$asc;
  828. //Descent
  829. $desc=(isset($fm['Descender']) ? $fm['Descender'] : -200);
  830. $fd.=",'Descent'=>".$desc;
  831. //CapHeight
  832. if(isset($fm['CapHeight']))
  833. $ch=$fm['CapHeight'];
  834. elseif(isset($fm['CapXHeight']))
  835. $ch=$fm['CapXHeight'];
  836. else
  837. $ch=$asc;
  838. $fd.=",'CapHeight'=>".$ch;
  839. //Flags
  840. $flags=0;
  841. if(isset($fm['IsFixedPitch']) and $fm['IsFixedPitch'])
  842. $flags+=1<<0;
  843. if($symbolic)
  844. $flags+=1<<2;
  845. if(!$symbolic)
  846. $flags+=1<<5;
  847. if(isset($fm['ItalicAngle']) and $fm['ItalicAngle']!=0)
  848. $flags+=1<<6;
  849. $fd.=",'Flags'=>".$flags;
  850. //FontBBox
  851. if(isset($fm['FontBBox']))
  852. $fbb=$fm['FontBBox'];
  853. else
  854. $fbb=array(0,$des-100,1000,$asc+100);
  855. $fd.=",'FontBBox'=>'[".$fbb[0].' '.$fbb[1].' '.$fbb[2].' '.$fbb[3]."]'";
  856. //ItalicAngle
  857. $ia=(isset($fm['ItalicAngle']) ? $fm['ItalicAngle'] : 0);
  858. $fd.=",'ItalicAngle'=>".$ia;
  859. //StemV
  860. if(isset($fm['StdVW']))
  861. $stemv=$fm['StdVW'];
  862. elseif(isset($fm['Weight']) and eregi('(bold|black)',$fm['Weight']))
  863. $stemv=120;
  864. else
  865. $stemv=70;
  866. $fd.=",'StemV'=>".$stemv;
  867. //MissingWidth
  868. if(isset($fm['MissingWidth']))
  869. $fd.=",'MissingWidth'=>".$fm['MissingWidth'];
  870. $fd.=')';
  871. return $fd;
  872. }
  873. function MakeWidthArray($fm)
  874. {
  875. //Make character width array
  876. $s="array(\n\t";
  877. $cw=$fm['Widths'];
  878. for($i=0;$i<=255;$i++)
  879. {
  880. if(chr($i)=="'")
  881. $s.="'\\''";
  882. elseif(chr($i)=="\\")
  883. $s.="'\\\\'";
  884. elseif($i>=32 and $i<=126)
  885. $s.="'".chr($i)."'";
  886. else
  887. $s.="chr($i)";
  888. $s.='=>'.$fm['Widths'][$i];
  889. if($i<255)
  890. $s.=',';
  891. if(($i+1)%22==0)
  892. $s.="\n\t";
  893. }
  894. $s.=')';
  895. return $s;
  896. }
  897. function MakeFontEncoding($map)
  898. {
  899. //Build differences from reference encoding
  900. $ref=ReadMap('win-1252');
  901. $s='';
  902. $last=0;
  903. for($i=32;$i<=255;$i++)
  904. {
  905. if($map[$i]!=$ref[$i])
  906. {
  907. if($i!=$last+1)
  908. $s.=$i.' ';
  909. $last=$i;
  910. $s.='/'.$map[$i].' ';
  911. }
  912. }
  913. return chop($s);
  914. }
  915. /*******************************************************************************
  916. * $fontfile: path to TTF file (or empty string if not to be embedded) *
  917. * $afmfile: path to AFM file *
  918. * $enc: font encoding (or empty string for symbolic fonts) *
  919. * $patch: optional patch for encoding *
  920. * $type : font type if $fontfile is empty *
  921. *******************************************************************************/
  922. function MakeFont($fontfile,$afmfile,$enc='win-1252',$patch=array(),$type='TrueType')
  923. {
  924. //Generate a font definition file
  925. set_magic_quotes_runtime(0);
  926. if($enc)
  927. {
  928. $map=ReadMap($enc);
  929. foreach($patch as $cc=>$gn)
  930. $map[$cc]=$gn;
  931. }
  932. else
  933. $map=array();
  934. if(!file_exists($afmfile))
  935. die('<B>Error:</B> AFM file not found: '.$afmfile);
  936. $fm=ReadAFM($afmfile,$map);
  937. if($enc)
  938. $diff=MakeFontEncoding($map);
  939. else
  940. $diff='';
  941. $fd=MakeFontDescriptor($fm,empty($map));
  942. //Find font type
  943. if($fontfile)
  944. {
  945. $ext=strtolower(substr($fontfile,-3));
  946. if($ext=='ttf')
  947. $type='TrueType';
  948. elseif($ext=='pfb')
  949. $type='Type1';
  950. else
  951. die('<B>Error:</B> unrecognized font file extension: '.$ext);
  952. }
  953. else
  954. {
  955. if($type!='TrueType' and $type!='Type1')
  956. die('<B>Error:</B> incorrect font type: '.$type);
  957. }
  958. //Start generation
  959. $s='<?php'."\n";
  960. $s.='$type=\''.$type."';\n";
  961. $s.='$name=\''.$fm['FontName']."';\n";
  962. $s.='$desc='.$fd.";\n";
  963. if(!isset($fm['UnderlinePosition']))
  964. $fm['UnderlinePosition']=-100;
  965. if(!isset($fm['UnderlineThickness']))
  966. $fm['UnderlineThickness']=50;
  967. $s.='$up='.$fm['UnderlinePosition'].";\n";
  968. $s.='$ut='.$fm['UnderlineThickness'].";\n";
  969. $w=MakeWidthArray($fm);
  970. $s.='$cw='.$w.";\n";
  971. $s.='$enc=\''.$enc."';\n";
  972. $s.='$diff=\''.$diff."';\n";
  973. $basename=substr(basename($afmfile),0,-4);
  974. if($fontfile)
  975. {
  976. //Embedded font
  977. if(!file_exists($fontfile))
  978. die('<B>Error:</B> font file not found: '.$fontfile);
  979. if($type=='TrueType')
  980. CheckTTF($fontfile);
  981. $f=fopen($fontfile,'rb');
  982. if(!$f)
  983. die('<B>Error:</B> Can\'t open '.$fontfile);
  984. $file=fread($f,filesize($fontfile));
  985. fclose($f);
  986. if($type=='Type1')
  987. {
  988. //Find first two sections and discard third one
  989. $pos=strpos($file,'eexec');
  990. if(!$pos)
  991. die('<B>Error:</B> font file does not seem to be valid Type1');
  992. $size1=$pos+6;
  993. $pos=strpos($file,'00000000');
  994. if(!$pos)
  995. die('<B>Error:</B> font file does not seem to be valid Type1');
  996. $size2=$pos-$size1;
  997. $file=substr($file,0,$size1+$size2);
  998. }
  999. if(function_exists('gzcompress'))
  1000. {
  1001. $cmp=$basename.'.z';
  1002. SaveToFile($cmp,gzcompress($file),'b');
  1003. $s.='$file=\''.$cmp."';\n";
  1004. // echo 'Font file compressed ('.$cmp.')<BR>';
  1005. }
  1006. else
  1007. {
  1008. $s.='$file=\''.basename($fontfile)."';\n";
  1009. echo '<B>Notice:</B> font file could not be compressed (gzcompress not available)<BR>';
  1010. }
  1011. if($type=='Type1')
  1012. {
  1013. $s.='$size1='.$size1.";\n";
  1014. $s.='$size2='.$size2.";\n";
  1015. }
  1016. else
  1017. $s.='$originalsize='.filesize($fontfile).";\n";
  1018. }
  1019. else
  1020. {
  1021. //Not embedded font
  1022. $s.='$file='."'';\n";
  1023. }
  1024. $s.="?>\n";
  1025. SaveToFile($basename.'.php',$s);
  1026. //echo 'Font definition file generated ('.$basename.'.php'.')<BR>';
  1027. return true;
  1028. }
  1029. /*******************************************************************************
  1030. * Functions to generate font definition files for Unicode Truetype fonts *
  1031. *******************************************************************************/
  1032. function ReadUFM($file, &$cidtogidmap)
  1033. {
  1034. //Prepare empty CIDToGIDMap
  1035. $cidtogidmap = str_pad('', 256*256*2, "\x00");
  1036. //Read a font metric file
  1037. $a=file($file);
  1038. if(empty($a))
  1039. die('File not found (ReadUFM) - '.$file);
  1040. $widths=array();
  1041. $fm=array();
  1042. foreach($a as $l)
  1043. {
  1044. $e=explode(' ',chop($l));
  1045. if(count($e)<2)
  1046. continue;
  1047. $code=$e[0];
  1048. $param=$e[1];
  1049. if($code=='U')
  1050. {
  1051. // U 827 ; WX 0 ; N squaresubnosp ; G 675 ;
  1052. //Character metrics
  1053. $cc=(int)$e[1];
  1054. if ($cc != -1) {
  1055. $gn = $e[7];
  1056. $w = $e[4];
  1057. $glyph = $e[10];
  1058. $widths[$cc] = $w;
  1059. // if($cc == ord('X')) // mPDF 4.4.01
  1060. // $fm['CapXHeight'] = $e[13]; // Height is not set in ttf2ufm
  1061. // Set GID
  1062. if ($cc >= 0 && $cc < 0xFFFF && $glyph) {
  1063. $cidtogidmap{$cc*2} = chr($glyph >> 8);
  1064. $cidtogidmap{$cc*2 + 1} = chr($glyph & 0xFF);
  1065. }
  1066. // mPDF 4.5.003
  1067. if($gn=='.notdef' && !isset($fm['MissingWidth']))
  1068. $fm['MissingWidth']=$w;
  1069. }
  1070. }
  1071. elseif($code=='FontName')
  1072. $fm['FontName']=$param;
  1073. elseif($code=='Weight')
  1074. $fm['Weight']=$param;
  1075. elseif($code=='ItalicAngle')
  1076. $fm['ItalicAngle']=(double)$param;
  1077. elseif($code=='Ascender')
  1078. $fm['Ascender']=(int)$param;
  1079. elseif($code=='Descender')
  1080. $fm['Descender']=(int)$param;
  1081. elseif($code=='UnderlineThickness')
  1082. $fm['UnderlineThickness']=(int)$param;
  1083. elseif($code=='UnderlinePosition')
  1084. $fm['UnderlinePosition']=(int)$param;
  1085. elseif($code=='IsFixedPitch')
  1086. $fm['IsFixedPitch']=($param=='true');
  1087. elseif($code=='FontBBox')
  1088. $fm['FontBBox']=array($e[1],$e[2],$e[3],$e[4]);
  1089. elseif($code=='CapHeight')
  1090. $fm['CapHeight']=(int)$param;
  1091. elseif($code=='StdVW')
  1092. $fm['StdVW']=(int)$param;
  1093. }
  1094. if(!isset($fm['MissingWidth']))
  1095. $fm['MissingWidth']=600;
  1096. if(!isset($fm['FontName']))
  1097. die('FontName not found');
  1098. $fm['Widths']=$widths;
  1099. return $fm;
  1100. }
  1101. function MakeFontDescriptorTTF($fm)
  1102. {
  1103. //Ascent
  1104. $asc=(isset($fm['Ascender']) ? $fm['Ascender'] : 1000);
  1105. $fd="array('Ascent'=>".$asc;
  1106. //Descent
  1107. $desc=(isset($fm['Descender']) ? $fm['Descender'] : -200);
  1108. $fd.=",'Descent'=>".$desc;
  1109. //CapHeight
  1110. if(isset($fm['CapHeight']))
  1111. $ch=$fm['CapHeight'];
  1112. elseif(isset($fm['CapXHeight']))
  1113. $ch=$fm['CapXHeight'];
  1114. else
  1115. $ch=$asc;
  1116. $fd.=",'CapHeight'=>".$ch;
  1117. //Flags
  1118. $flags=0;
  1119. if(isset($fm['IsFixedPitch']) and $fm['IsFixedPitch'])
  1120. $flags+=1<<0;
  1121. $flags+=1<<5;
  1122. if(isset($fm['ItalicAngle']) and $fm['ItalicAngle']!=0)
  1123. $flags+=1<<6;
  1124. $fd.=",'Flags'=>".$flags;
  1125. //FontBBox
  1126. if(isset($fm['FontBBox']))
  1127. $fbb=$fm['FontBBox'];
  1128. else
  1129. $fbb=array(0,$des-100,1000,$asc+100);
  1130. $fd.=",'FontBBox'=>'[".$fbb[0].' '.$fbb[1].' '.$fbb[2].' '.$fbb[3]."]'";
  1131. //ItalicAngle
  1132. $ia=(isset($fm['ItalicAngle']) ? $fm['ItalicAngle'] : 0);
  1133. $fd.=",'ItalicAngle'=>".$ia;
  1134. //StemV
  1135. if(isset($fm['StdVW']))
  1136. $stemv=$fm['StdVW'];
  1137. elseif(isset($fm['Weight']) and eregi('(bold|black)',$fm['Weight']))
  1138. $stemv=120;
  1139. else
  1140. $stemv=70;
  1141. $fd.=",'StemV'=>".$stemv;
  1142. //MissingWidth
  1143. if(isset($fm['MissingWidth']))
  1144. $fd.=",'MissingWidth'=>".$fm['MissingWidth'];
  1145. $fd.=')';
  1146. return $fd;
  1147. }
  1148. function MakeWidthArrayTTF($fm)
  1149. {
  1150. //Make character width array
  1151. $s="array(";
  1152. $cw=$fm['Widths'];
  1153. $els=array();
  1154. $c=0;
  1155. foreach ($cw as $i => $w)
  1156. {
  1157. $els[] = ((($c++)%16==0)?"\n\t":'').$i.'=>'.$w;
  1158. }
  1159. $s .= implode(', ', $els);
  1160. $s.=')';
  1161. return $s;
  1162. }
  1163. /*******************************************************************************
  1164. * $fontfile: path to TTF file (or empty string if not to be embedded) *
  1165. * $ufmfile: path to UFM file *
  1166. *******************************************************************************/
  1167. function MakeFontTTF($fontfile,$ufmfile)
  1168. {
  1169. //Generate a font definition file
  1170. if (ini_get("magic_quotes_runtime")) set_magic_quotes_runtime(0);
  1171. if(!file_exists($ufmfile))
  1172. die('<B>Error:</B> UFM file not found: '.$ufmfile);
  1173. $cidtogidmap = '';
  1174. $fm=ReadUFM($ufmfile, $cidtogidmap);
  1175. $fd=MakeFontDescriptorTTF($fm);
  1176. //Find font type
  1177. if($fontfile)
  1178. {
  1179. $ext=strtolower(substr($fontfile,-3));
  1180. if($ext=='ttf')
  1181. $type='TrueTypeUnicode';
  1182. else
  1183. die('<B>Error:</B> not a truetype font: '.$ext);
  1184. }
  1185. else
  1186. {
  1187. if($type!='TrueTypeUnicode')
  1188. die('<B>Error:</B> incorrect font type: '.$type);
  1189. }
  1190. //Start generation
  1191. $s='<?php'."\n";
  1192. $s.='$type=\''.$type."';\n";
  1193. $s.='$name=\''.$fm['FontName']."';\n";
  1194. $s.='$desc='.$fd.";\n";
  1195. if(!isset($fm['UnderlinePosition']))
  1196. $fm['UnderlinePosition']=-100;
  1197. if(!isset($fm['UnderlineThickness']))
  1198. $fm['UnderlineThickness']=50;
  1199. $s.='$up='.$fm['UnderlinePosition'].";\n";
  1200. $s.='$ut='.$fm['UnderlineThickness'].";\n";
  1201. $w=MakeWidthArrayTTF($fm);
  1202. $s.='$cw='.$w.";\n";
  1203. $s.="\$enc='';\n";
  1204. $s.="\$diff='';\n";
  1205. $basename=substr(basename($ufmfile),0,-4);
  1206. if($fontfile)
  1207. {
  1208. //Embedded font
  1209. if(!file_exists($fontfile))
  1210. die('<B>Error:</B> font file not found: '.$fontfile);
  1211. CheckTTF($fontfile);
  1212. $f=fopen($fontfile,'rb');
  1213. if(!$f)
  1214. die('<B>Error:</B> Can\'t open '.$fontfile);
  1215. $file=fread($f,filesize($fontfile));
  1216. fclose($f);
  1217. if(function_exists('gzcompress'))
  1218. {
  1219. $cmp=$basename.'.z';
  1220. SaveToFile($cmp,gzcompress($file),'b');
  1221. $s.='$file=\''.$cmp."';\n";
  1222. // echo 'Font file compressed ('.$cmp.')<BR>';
  1223. $cmp=$basename.'.ctg.z';
  1224. SaveToFile($cmp,gzcompress($cidtogidmap),'b');
  1225. //echo 'CIDToGIDMap created and compressed ('.$cmp.')<BR>';
  1226. $s.='$ctg=\''.$cmp."';\n";
  1227. }
  1228. else
  1229. {
  1230. $s.='$file=\''.basename($fontfile)."';\n";
  1231. echo '<B>Notice:</B> font file could not be compressed (gzcompress not available)<BR>';
  1232. $cmp=$basename.'.ctg';
  1233. $f = fopen($cmp, 'wb');
  1234. fwrite($f, $cidtogidmap);
  1235. fclose($f);
  1236. echo 'CIDToGIDMap created ('.$cmp.')<BR>';
  1237. $s.='$ctg=\''.$cmp."';\n";
  1238. }
  1239. if($type=='Type1')
  1240. {
  1241. $s.='$size1='.$size1.";\n";
  1242. $s.='$size2='.$size2.";\n";
  1243. }
  1244. else
  1245. $s.='$originalsize='.filesize($fontfile).";\n";
  1246. }
  1247. else
  1248. {
  1249. //Not embedded font
  1250. $s.='$file='."'';\n";
  1251. }
  1252. $s.="?>\n";
  1253. SaveToFile($basename.'.php',$s);
  1254. // echo 'Font definition file generated ('.$basename.'.php'.')<BR>';
  1255. return true;
  1256. }
  1257. ?>