Pull merge.
[yaffs-website] / vendor / phenx / php-font-lib / src / FontLib / AdobeFontMetrics.php
1 <?php
2 /**
3  * @package php-font-lib
4  * @link    https://github.com/PhenX/php-font-lib
5  * @author  Fabien Ménager <fabien.menager@gmail.com>
6  * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
7  */
8
9 namespace FontLib;
10
11 use FontLib\Table\Type\name;
12 use FontLib\TrueType\File;
13
14 /**
15  * Adobe Font Metrics file creation utility class.
16  *
17  * @package php-font-lib
18  */
19 class AdobeFontMetrics {
20   private $f;
21
22   /**
23    * @var File
24    */
25   private $font;
26
27   function __construct(File $font) {
28     $this->font = $font;
29   }
30
31   function write($file, $encoding = null) {
32     $map_data = array();
33
34     if ($encoding) {
35       $encoding = preg_replace("/[^a-z0-9-_]/", "", $encoding);
36       $map_file = dirname(__FILE__) . "/../maps/$encoding.map";
37       if (!file_exists($map_file)) {
38         throw new \Exception("Unkown encoding ($encoding)");
39       }
40
41       $map      = new EncodingMap($map_file);
42       $map_data = $map->parse();
43     }
44
45     $this->f = fopen($file, "w+");
46
47     $font = $this->font;
48
49     $this->startSection("FontMetrics", 4.1);
50     $this->addPair("Notice", "Converted by PHP-font-lib");
51     $this->addPair("Comment", "https://github.com/PhenX/php-font-lib");
52
53     $encoding_scheme = ($encoding ? $encoding : "FontSpecific");
54     $this->addPair("EncodingScheme", $encoding_scheme);
55
56     $records = $font->getData("name", "records");
57     foreach ($records as $id => $record) {
58       if (!isset(name::$nameIdCodes[$id]) || preg_match("/[\r\n]/", $record->string)) {
59         continue;
60       }
61
62       $this->addPair(name::$nameIdCodes[$id], $record->string);
63     }
64
65     $os2 = $font->getData("OS/2");
66     $this->addPair("Weight", ($os2["usWeightClass"] > 400 ? "Bold" : "Medium"));
67
68     $post = $font->getData("post");
69     $this->addPair("ItalicAngle", $post["italicAngle"]);
70     $this->addPair("IsFixedPitch", ($post["isFixedPitch"] ? "true" : "false"));
71     $this->addPair("UnderlineThickness", $font->normalizeFUnit($post["underlineThickness"]));
72     $this->addPair("UnderlinePosition", $font->normalizeFUnit($post["underlinePosition"]));
73
74     $hhea = $font->getData("hhea");
75
76     if (isset($hhea["ascent"])) {
77       $this->addPair("FontHeightOffset", $font->normalizeFUnit($hhea["lineGap"]));
78       $this->addPair("Ascender", $font->normalizeFUnit($hhea["ascent"]));
79       $this->addPair("Descender", $font->normalizeFUnit($hhea["descent"]));
80     }
81     else {
82       $this->addPair("FontHeightOffset", $font->normalizeFUnit($os2["typoLineGap"]));
83       $this->addPair("Ascender", $font->normalizeFUnit($os2["typoAscender"]));
84       $this->addPair("Descender", -abs($font->normalizeFUnit($os2["typoDescender"])));
85     }
86
87     $head = $font->getData("head");
88     $this->addArray("FontBBox", array(
89       $font->normalizeFUnit($head["xMin"]),
90       $font->normalizeFUnit($head["yMin"]),
91       $font->normalizeFUnit($head["xMax"]),
92       $font->normalizeFUnit($head["yMax"]),
93     ));
94
95     $glyphIndexArray = $font->getUnicodeCharMap();
96
97     if ($glyphIndexArray) {
98       $hmtx  = $font->getData("hmtx");
99       $names = $font->getData("post", "names");
100
101       $this->startSection("CharMetrics", count($hmtx));
102
103       if ($encoding) {
104         foreach ($map_data as $code => $value) {
105           list($c, $name) = $value;
106
107           if (!isset($glyphIndexArray[$c])) {
108             continue;
109           }
110
111           $g = $glyphIndexArray[$c];
112
113           if (!isset($hmtx[$g])) {
114             $hmtx[$g] = $hmtx[0];
115           }
116
117           $this->addMetric(array(
118             "C"  => ($code > 255 ? -1 : $code),
119             "WX" => $font->normalizeFUnit($hmtx[$g][0]),
120             "N"  => $name,
121           ));
122         }
123       }
124       else {
125         foreach ($glyphIndexArray as $c => $g) {
126           if (!isset($hmtx[$g])) {
127             $hmtx[$g] = $hmtx[0];
128           }
129
130           $this->addMetric(array(
131             "U"  => $c,
132             "WX" => $font->normalizeFUnit($hmtx[$g][0]),
133             "N"  => (isset($names[$g]) ? $names[$g] : sprintf("uni%04x", $c)),
134             "G"  => $g,
135           ));
136         }
137       }
138
139       $this->endSection("CharMetrics");
140
141       $kern = $font->getData("kern", "subtable");
142       $tree = $kern["tree"];
143
144       if (!$encoding && is_array($tree)) {
145         $this->startSection("KernData");
146         $this->startSection("KernPairs", count($tree, COUNT_RECURSIVE) - count($tree));
147
148         foreach ($tree as $left => $values) {
149           if (!is_array($values)) {
150             continue;
151           }
152           if (!isset($glyphIndexArray[$left])) {
153             continue;
154           }
155
156           $left_gid = $glyphIndexArray[$left];
157
158           if (!isset($names[$left_gid])) {
159             continue;
160           }
161
162           $left_name = $names[$left_gid];
163
164           $this->addLine("");
165
166           foreach ($values as $right => $value) {
167             if (!isset($glyphIndexArray[$right])) {
168               continue;
169             }
170
171             $right_gid = $glyphIndexArray[$right];
172
173             if (!isset($names[$right_gid])) {
174               continue;
175             }
176
177             $right_name = $names[$right_gid];
178             $this->addPair("KPX", "$left_name $right_name $value");
179           }
180         }
181
182         $this->endSection("KernPairs");
183         $this->endSection("KernData");
184       }
185     }
186
187     $this->endSection("FontMetrics");
188   }
189
190   function addLine($line) {
191     fwrite($this->f, "$line\n");
192   }
193
194   function addPair($key, $value) {
195     $this->addLine("$key $value");
196   }
197
198   function addArray($key, $array) {
199     $this->addLine("$key " . implode(" ", $array));
200   }
201
202   function addMetric($data) {
203     $array = array();
204     foreach ($data as $key => $value) {
205       $array[] = "$key $value";
206     }
207     $this->addLine(implode(" ; ", $array));
208   }
209
210   function startSection($name, $value = "") {
211     $this->addLine("Start$name $value");
212   }
213
214   function endSection($name) {
215     $this->addLine("End$name");
216   }
217 }