Viewing file: BinaryStream.php (9.74 KB) -rwxr-xr-x Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php /** * @package php-font-lib * @link https://github.com/PhenX/php-font-lib * @author Fabien Ménager <fabien.menager@gmail.com> * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */
namespace FontLib;
/** * Generic font file binary stream. * * @package php-font-lib */ class BinaryStream { /** * @var resource The file pointer */ protected $f;
const uint8 = 1; const int8 = 2; const uint16 = 3; const int16 = 4; const uint32 = 5; const int32 = 6; const shortFrac = 7; const Fixed = 8; const FWord = 9; const uFWord = 10; const F2Dot14 = 11; const longDateTime = 12; const char = 13;
const modeRead = "rb"; const modeWrite = "wb"; const modeReadWrite = "rb+";
static function backtrace() { var_dump(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)); }
/** * Open a font file in read mode * * @param string $filename The file name of the font to open * * @return bool */ public function load($filename) { return $this->open($filename, self::modeRead); }
/** * Open a font file in a chosen mode * * @param string $filename The file name of the font to open * @param string $mode The opening mode * * @throws \Exception * @return bool */ public function open($filename, $mode = self::modeRead) { if (!in_array($mode, array(self::modeRead, self::modeWrite, self::modeReadWrite))) { throw new \Exception("Unkown file open mode"); }
$this->f = fopen($filename, $mode);
return $this->f != false; }
/** * Close the internal file pointer */ public function close() { return fclose($this->f) != false; }
/** * Change the internal file pointer * * @param resource $fp * * @throws \Exception */ public function setFile($fp) { if (!is_resource($fp)) { throw new \Exception('$fp is not a valid resource'); }
$this->f = $fp; }
/** * Create a temporary file in write mode * * @param bool $allow_memory Allow in-memory files * * @return resource the temporary file pointer resource */ public static function getTempFile($allow_memory = true) { $f = null;
if ($allow_memory) { $f = fopen("php://temp", "rb+"); } else { $f = fopen(tempnam(sys_get_temp_dir(), "fnt"), "rb+"); }
return $f; }
/** * Move the internal file pinter to $offset bytes * * @param int $offset * * @return bool True if the $offset position exists in the file */ public function seek($offset) { return fseek($this->f, $offset, SEEK_SET) == 0; }
/** * Gives the current position in the file * * @return int The current position */ public function pos() { return ftell($this->f); }
public function skip($n) { fseek($this->f, $n, SEEK_CUR); }
public function read($n) { if ($n < 1) { return ""; }
return fread($this->f, $n); }
public function write($data, $length = null) { if ($data === null || $data === "" || $data === false) { return 0; }
return fwrite($this->f, $data, $length); }
public function readUInt8() { return ord($this->read(1)); }
public function readUInt8Many($count) { return array_values(unpack("C*", $this->read($count))); }
public function writeUInt8($data) { return $this->write(chr($data), 1); }
public function readInt8() { $v = $this->readUInt8();
if ($v >= 0x80) { $v -= 0x100; }
return $v; }
public function readInt8Many($count) { return array_values(unpack("c*", $this->read($count))); }
public function writeInt8($data) { if ($data < 0) { $data += 0x100; }
return $this->writeUInt8($data); }
public function readUInt16() { $a = unpack("nn", $this->read(2));
return $a["n"]; }
public function readUInt16Many($count) { return array_values(unpack("n*", $this->read($count * 2))); }
public function readUFWord() { return $this->readUInt16(); }
public function writeUInt16($data) { return $this->write(pack("n", $data), 2); }
public function writeUFWord($data) { return $this->writeUInt16($data); }
public function readInt16() { $a = unpack("nn", $this->read(2)); $v = $a["n"];
if ($v >= 0x8000) { $v -= 0x10000; }
return $v; }
public function readInt16Many($count) { $vals = array_values(unpack("n*", $this->read($count * 2))); foreach ($vals as &$v) { if ($v >= 0x8000) { $v -= 0x10000; } }
return $vals; }
public function readFWord() { return $this->readInt16(); }
public function writeInt16($data) { if ($data < 0) { $data += 0x10000; }
return $this->writeUInt16($data); }
public function writeFWord($data) { return $this->writeInt16($data); }
public function readUInt32() { $a = unpack("NN", $this->read(4));
return $a["N"]; }
public function writeUInt32($data) { return $this->write(pack("N", $data), 4); }
public function readFixed() { $d = $this->readInt16(); $d2 = $this->readUInt16();
return round($d + $d2 / 0x10000, 4); }
public function writeFixed($data) { $left = floor($data); $right = ($data - $left) * 0x10000;
return $this->writeInt16($left) + $this->writeUInt16($right); }
public function readLongDateTime() { $this->readUInt32(); // ignored $date = $this->readUInt32() - 2082844800; # PHP_INT_MIN isn't defined in PHP < 7.0 $php_int_min = defined("PHP_INT_MIN") ? PHP_INT_MIN : ~PHP_INT_MAX;
if (is_string($date) || $date > PHP_INT_MAX || $date < $php_int_min) { $date = 0; }
return strftime("%Y-%m-%d %H:%M:%S", $date); }
public function writeLongDateTime($data) { $date = strtotime($data); $date += 2082844800;
return $this->writeUInt32(0) + $this->writeUInt32($date); }
public function unpack($def) { $d = array(); foreach ($def as $name => $type) { $d[$name] = $this->r($type); }
return $d; }
public function pack($def, $data) { $bytes = 0; foreach ($def as $name => $type) { $bytes += $this->w($type, $data[$name]); }
return $bytes; }
/** * Read a data of type $type in the file from the current position * * @param mixed $type The data type to read * * @return mixed The data that was read */ public function r($type) { switch ($type) { case self::uint8: return $this->readUInt8(); case self::int8: return $this->readInt8(); case self::uint16: return $this->readUInt16(); case self::int16: return $this->readInt16(); case self::uint32: return $this->readUInt32(); case self::int32: return $this->readUInt32(); case self::shortFrac: return $this->readFixed(); case self::Fixed: return $this->readFixed(); case self::FWord: return $this->readInt16(); case self::uFWord: return $this->readUInt16(); case self::F2Dot14: return $this->readInt16(); case self::longDateTime: return $this->readLongDateTime(); case self::char: return $this->read(1); default: if (is_array($type)) { if ($type[0] == self::char) { return $this->read($type[1]); } if ($type[0] == self::uint16) { return $this->readUInt16Many($type[1]); } if ($type[0] == self::int16) { return $this->readInt16Many($type[1]); } if ($type[0] == self::uint8) { return $this->readUInt8Many($type[1]); } if ($type[0] == self::int8) { return $this->readInt8Many($type[1]); }
$ret = array(); for ($i = 0; $i < $type[1]; $i++) { $ret[] = $this->r($type[0]); }
return $ret; }
return null; } }
/** * Write $data of type $type in the file from the current position * * @param mixed $type The data type to write * @param mixed $data The data to write * * @return int The number of bytes read */ public function w($type, $data) { switch ($type) { case self::uint8: return $this->writeUInt8($data); case self::int8: return $this->writeInt8($data); case self::uint16: return $this->writeUInt16($data); case self::int16: return $this->writeInt16($data); case self::uint32: return $this->writeUInt32($data); case self::int32: return $this->writeUInt32($data); case self::shortFrac: return $this->writeFixed($data); case self::Fixed: return $this->writeFixed($data); case self::FWord: return $this->writeInt16($data); case self::uFWord: return $this->writeUInt16($data); case self::F2Dot14: return $this->writeInt16($data); case self::longDateTime: return $this->writeLongDateTime($data); case self::char: return $this->write($data, 1); default: if (is_array($type)) { if ($type[0] == self::char) { return $this->write($data, $type[1]); }
$ret = 0; for ($i = 0; $i < $type[1]; $i++) { if (isset($data[$i])) { $ret += $this->w($type[0], $data[$i]); } }
return $ret; }
return null; } }
/** * Converts a Uint32 value to string * * @param int $uint32 * * @return string The string */ public function convertUInt32ToStr($uint32) { return chr(($uint32 >> 24) & 0xFF) . chr(($uint32 >> 16) & 0xFF) . chr(($uint32 >> 8) & 0xFF) . chr($uint32 & 0xFF); } }
|