This is PHP code I have so far:
https://gist.github.com/2eeba2ff31ebecb526e2
This is the result:
https://gist.github.com/cf07fe90922ac3dfcd22
Now say I need to get information that is referenced in this table:
object(ttfTableDirectoryEntry)#6 (4) {
["tag"]=>
string(4) "cmap"
["checksum"]=>
int(2553734765)
["offset"]=>
int(1556)
["length"]=>
int(1190)
}
How do I do that?
In general, I need to parse info for every of these tables.
This is what you get if you simply try to parse the data from offset with length.
object(ttfTableDirectoryEntry)#12 (4) {
["tag"]=>
string(4) "name"
["checksum"]=>
int(3955157420)
["offset"]=>
int(400)
["length"]=>
int(1153)
}
string(1153) "���>��������:����������:��������F�������"�L��������n�������
������������������5����������������� �#��������
�:������������������ ���t#�� ����� ����� ��D��� ��$��� ��#�� ��$��� ��j=�� 开发者_如何学Go ����� � �F��� �
�t#�� ��: �� ��: Copyright (c) 2010 by YouWorkForThem. All rights reserved.YWFT HLLVTKANormalYouWorkForThem: YWFT HLLVTKA: 2010YWFT HLLVTKA NormalVersion 1.000YWFTHLLVTKA-NormalYWFT HLLVTKA Normal is a trademark of YouWorkForThem.YouWorkForThemEric Carlson & Taechit Jiropaskosolhttp://www.youworkforthem.com�C�o�p�y�r�i�g�h�t� �(�c�)� �2�0�1�0� �b�y� �Y�o�u�W�o�r�k�F�o�r�T�h�e�m�.� �A�l�l� �r�i�g�h�t�s� �r�e�s�e�r�v�e�d�.�Y�W�F�T� �H�L�L�V�T�K�A�N�o�r�m�a�l�Y�o�u�W�o�r�k�F�o�r�T�h�e�m�:� �Y�W�F�T� �H�L�L�V�T�K�A�:� �2�0�1�0�Y�W�F�T�H�L�L�V�T�K�A�-�N�o�r�m�a�l�V�e�r�s�i�o�n� �1�.�0�0�0�Y�W�F�T� �H�L�L�V�T�K�A� �N�o�r�m�a�l� �i�s� �a� �t�r�a�d�e�m�a�r�k� �o�f� �Y�o�u�W�o�r�k�F�o�r�T�h�e�m�.�Y�o�u�W�o�r�k�F�o�r�T�h�e�m�E�r�i�c� �C�a�r�l�s�o�n� �&� �T�a�e�c�h�i�t� �J�i�r�o�p�a�s�k�o�s�o�l�h�t�t�p�:�/�/�w�w�w�.�y�o�u�w�o�r�k�f�o�r�t�h�e�m�.�c�o�m"
I tried to achieve this and went close to making it. However, at the end, I decided to use Python instead when parsing data. Anyway, if anyone decide that they want to go PHP way, here is what I have until this moment. It is one step close to getting glyph map. For a documentation on how to read the data, refer to http://developer.apple.com/fonts/ttrefman/RM06/Chap6.html.
<?php
$ttr = new TrueTypeReader;
$ttr->open('font.otf');
class TrueTypeReader
{
private $position = 0;
private $offset = 0;
private $file;
public function open($file)
{
$this->file = file_get_contents($file);
// http://developer.apple.com/fonts/ttrefman/RM06/Chap6.html
// The offset subtable
$number_of_tables = $this->getUint16(4);
$this->tables = array();
for($i = 0; $i < $number_of_tables; $i++)
{
// http://developer.apple.com/fonts/ttrefman/RM06/Chap6.html
// The table directory
$table = array();
$tag = $this->getTag(12 + $i * 16);
$table = array
(
'tag' => $tag,
'check_sum' => $this->getUint32(12 + $i * 16 + 4),
'offset' => $this->getUint32(12 + $i * 16 + 8),
'length' => $this->getUint32(12 + $i * 16 + 12),
);
if($tag == 'cmap')
{
$this->parseCmapTable($table);
}
$this->tables[] = $table;
}
}
private function getTag($pt = FALSE)
{
if($pt === FALSE)
{
$pt = $this->position;
$this->position += 4;
}
return substr($this->file, $pt, 4);
}
private function getUint32($pt = FALSE)
{
if($pt === FALSE)
{
$pt = $this->position;
$this->position += 4;
}
$r = unpack("N", substr($this->file, $pt, 4) );
return $r[1];
}
private function getUint16($pt = FALSE)
{
if ($pt === FALSE)
{
$pt = $this->position;
$this->position += 2;
}
$r = unpack("n", substr($this->file, $pt, 2) );
return $r[1];
}
private function parseCmapTable($table)
{
$this->position = $table['offset'];
// http://developer.apple.com/fonts/ttrefman/RM06/Chap6cmap.html
// General table information
$data = array
(
'version' => $this->getUint16(),
'number_subtables' => $this->getUint16(),
);
$sub_tables = array();
for($i = 0; $i < $data['number_subtables']; $i++)
{
// http://developer.apple.com/fonts/ttrefman/RM06/Chap6cmap.html
// The 'cmap' encoding subtables
$sub_tables[] = array
(
'platform_id' => $this->getUint16(),
'specific_id' => $this->getUint16(),
'offset' => $this->getUint32(),
);
}
// http://developer.apple.com/fonts/ttrefman/RM06/Chap6cmap.html
// The 'cmap' formats
$formats = array();
foreach($sub_tables as $t)
{
// http://stackoverflow.com/questions/5322019/character-to-glyph-mapping-table/5322267#5322267
$this->position = $table['offset'] + $t['offset'];
$format = array
(
'format' => $this->getUint16(),
'length' => $this->getUint16(),
'language' => $this->getUint16(),
);
if($format['format'] == 4)
{
$format += array
(
'seg_count_X2' => $this->getUint16(),
'search_range' => $this->getUint16(),
'entry_selector' => $this->getUint16(),
'range_shift' => $this->getUint16(),
'end_code[segCount]' => $this->getUint16(),
'reserved_pad' => $this->getUint16(),
'start_code[segCount]' => $this->getUint16(),
'id_delta[segCount]' => $this->getUint16(),
'id_range_offset[segCount]' => $this->getUint16(),
'glyph_index_array[variable]' => $this->getUint16(),
);
$backup = $format;
$format['seg_count_X2'] = $backup['seg_count_X2']*2;
$format['search_range'] = 2 * (2 * floor(log($backup['seg_count_X2'], 2)));
$format['entry_selector'] = log($backup['search_range']/2, 2);
$format['range_shift'] = (2 * $backup['seg_count_X2']) - $backup['search_range'];
}
$formats[$t['offset']] = $format;
}
die(var_dump( $sub_tables, $formats ));
die(var_dump( $this->getUint16(), $this->getUint16(), $this->getUint16(), $this->getUint16(), $this->getUint16() ));
die(var_dump( $sub_tables[0] ));
$cmap = array
(
'format' => $this->getUint16(),
#'length' => $this->getUint16(),
#'language' => $this->getUint16(),
);
die(var_dump( $cmap ));
die(var_dump( $table, $data, $table, $cmap ));
}
private function parseNameTable($table)
{
// http://developer.apple.com/fonts/ttrefman/RM06/Chap6name.html
// Name Table Format
$data = array
(
'format' => $this->getUint16($table['offset']),
'count' => $this->getUint16($table['offset'] + 2), // $num_of_name_tables
'string_offset' => $this->getUint16($table['offset'] + 4),
);
$offset = $table['offset'] + $data['string_offset']; // $name_tables_offset
$name_tables = array();
for($i = 0; $i < $data['count']; $i ++)
{
$this->position = $table['offset'] + 6 + $i * 12;
$d = array
(
'platform_id' => $this->getUint16(),
'specific_id' => $this->getUint16(),
'lang_id' => $this->getUint16(),
'name_id' => $this->getUint16(),
'length' => $this->getUint16(),
'offset' => $this->getUint16() + $offset,
);
$key = "{$d['platform_id']}::{$d['specific_id']}::{$d['lang_id']}";
if(isset($d['name_id']) && empty($name_tables[$key][$d['name_id']]))
{
$text = substr($this->file, $d['offset'], $d['length']);
$name_tables[$key][$d['name_id']] = str_replace(chr(0), '', $text);
}
}
die(var_dump( $name_tables ));
}
}
精彩评论