changes
This commit is contained in:
parent
6a156d1444
commit
f33c00a650
|
|
@ -637,4 +637,24 @@ input:not([type="checkbox"], [type="radio"]), select {
|
|||
color: white;
|
||||
font-size: 2rem;
|
||||
margin: 0 auto 1rem;
|
||||
}
|
||||
|
||||
/* Стили для страницы автора */
|
||||
.author-books .book-cover {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.author-books .book-cover:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
/* Адаптивность для страницы автора */
|
||||
@media (max-width: 768px) {
|
||||
.author-books article {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.author-books .book-cover {
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
32
author.php
32
author.php
|
|
@ -1,7 +1,6 @@
|
|||
<?php
|
||||
require_once 'config/config.php';
|
||||
require_once 'models/Book.php';
|
||||
//require_once 'views/header.php';
|
||||
|
||||
$author_id = (int)($_GET['id'] ?? 0);
|
||||
if (!$author_id) {
|
||||
|
|
@ -23,7 +22,7 @@ if (!$author) {
|
|||
}
|
||||
|
||||
$bookModel = new Book($pdo);
|
||||
$books = $bookModel->findByUser($author_id, true); // только опубликованные (нужен параметр в модели)
|
||||
$books = $bookModel->findByUser($author_id, true); // только опубликованные
|
||||
|
||||
$page_title = ($author['display_name'] ?: $author['username']) . ' — публичная страница';
|
||||
include 'views/header.php';
|
||||
|
|
@ -36,15 +35,30 @@ include 'views/header.php';
|
|||
<?php else: ?>
|
||||
<div class="grid">
|
||||
<?php foreach ($books as $b): ?>
|
||||
<article>
|
||||
<article style="display: flex; gap: 1rem; align-items: flex-start;">
|
||||
<?php if ($b['cover_image']): ?>
|
||||
<img src="<?= e($b['cover_image']) ?>" alt="<?= e($b['title']) ?>" style="max-width:100%; height:auto;">
|
||||
<div style="flex-shrink: 0;">
|
||||
<img src="<?= COVERS_URL . e($b['cover_image']) ?>"
|
||||
alt="<?= e($b['title']) ?>"
|
||||
style="max-width: 120px; height: auto; border-radius: 4px; border: 1px solid #ddd;"
|
||||
onerror="this.style.display='none'">
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div style="flex-shrink: 0;">
|
||||
<div class="cover-placeholder" style="width: 120px; height: 160px;">📚</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<h3><?= e($b['title']) ?></h3>
|
||||
<?php if ($b['description']): ?>
|
||||
<p><?= nl2br(e($b['description'])) ?></p>
|
||||
<?php endif; ?>
|
||||
<a href="view_book.php?share_token=<?= e($b['share_token']) ?>">Читать</a>
|
||||
|
||||
<div style="flex: 1;">
|
||||
<h3 style="margin-top: 0;"><?= e($b['title']) ?></h3>
|
||||
<?php if ($b['genre']): ?>
|
||||
<p style="color: #666; margin: 0.5rem 0;"><em><?= e($b['genre']) ?></em></p>
|
||||
<?php endif; ?>
|
||||
<?php if ($b['description']): ?>
|
||||
<p style="margin-bottom: 1rem;"><?= nl2br(e($b['description'])) ?></p>
|
||||
<?php endif; ?>
|
||||
<a href="view_book.php?share_token=<?= e($b['share_token']) ?>" class="adaptive-button">Читать</a>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -239,9 +239,6 @@ function copyShareLink() {
|
|||
<a href="export_book.php?book_id=<?= $book_id ?>&format=docx" class="adaptive-button secondary" target="_blank">
|
||||
📝 DOCX
|
||||
</a>
|
||||
<a href="export_book.php?book_id=<?= $book_id ?>&format=odt" class="adaptive-button secondary" target="_blank">
|
||||
📄 ODT
|
||||
</a>
|
||||
<a href="export_book.php?book_id=<?= $book_id ?>&format=html" class="adaptive-button secondary" target="_blank">
|
||||
🌐 HTML
|
||||
</a>
|
||||
|
|
|
|||
12
books.php
12
books.php
|
|
@ -58,19 +58,19 @@ include 'views/header.php';
|
|||
<header>
|
||||
<h3><?= e($book['title']) ?>
|
||||
<div style="display: flex; gap: 3px; float:right;">
|
||||
<a href="export_book.php?book_id=<?= $book['id'] ?>&format=pdf" class="compact-button secondary" title="Экспорт в PDF" target="_blank">
|
||||
📄
|
||||
<a href="book_edit.php?id=<?= $book['id'] ?>" class="compact-button secondary" title="Редактировать книгу">
|
||||
✏️
|
||||
</a>
|
||||
<a href="view_book.php?share_token=<?= $book['share_token'] ?>" class="compact-button secondary" title="Просмотреть книгу" target="_blank">
|
||||
👁️
|
||||
</a>
|
||||
<a href="book_edit.php?id=<?= $book['id'] ?>" class="compact-button secondary" title="Редактировать книгу">
|
||||
✏️
|
||||
</a>
|
||||
<a href="chapters.php?book_id=<?= $book['id'] ?>" class="compact-button secondary" title="Просмотр глав">
|
||||
📑
|
||||
</a>
|
||||
<form method="post" action="book_delete.php" style="display: inline;" onsubmit="return confirm('Вы уверены, что хотите удалить книгу «<?= e($book['title']) ?>»? Все главы также будут удалены.');">
|
||||
<a href="export_book.php?book_id=<?= $book['id'] ?>&format=pdf" class="compact-button secondary" title="Экспорт в PDF" target="_blank">
|
||||
📄
|
||||
</a>
|
||||
<form method="post" action="book_delete.php" style="display: inline; margin-top: -0.1em;" onsubmit="return confirm('Вы уверены, что хотите удалить книгу «<?= e($book['title']) ?>»? Все главы также будут удалены.');">
|
||||
<input type="hidden" name="book_id" value="<?= $book['id'] ?>">
|
||||
<input type="hidden" name="csrf_token" value="<?= generate_csrf_token() ?>">
|
||||
<button type="submit" class="compact-button secondary" style="background: #ff4444; border-color: #ff4444; color: white;" title="Удалить книгу">
|
||||
|
|
|
|||
|
|
@ -4,226 +4,46 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "2a08fae47e0b8e59039cdc770c12dc3c",
|
||||
"content-hash": "493a3be12648bbe702ed126df05ead04",
|
||||
"packages": [
|
||||
{
|
||||
"name": "dompdf/dompdf",
|
||||
"version": "v2.0.8",
|
||||
"name": "cybermonde/odtphp",
|
||||
"version": "v1.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dompdf/dompdf.git",
|
||||
"reference": "c20247574601700e1f7c8dab39310fca1964dc52"
|
||||
"url": "https://github.com/cybermonde/odtphp.git",
|
||||
"reference": "23aba70923ca3c07af15a5600f4072751c1b4a36"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dompdf/dompdf/zipball/c20247574601700e1f7c8dab39310fca1964dc52",
|
||||
"reference": "c20247574601700e1f7c8dab39310fca1964dc52",
|
||||
"url": "https://api.github.com/repos/cybermonde/odtphp/zipball/23aba70923ca3c07af15a5600f4072751c1b4a36",
|
||||
"reference": "23aba70923ca3c07af15a5600f4072751c1b4a36",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-mbstring": "*",
|
||||
"masterminds/html5": "^2.0",
|
||||
"phenx/php-font-lib": ">=0.5.4 <1.0.0",
|
||||
"phenx/php-svg-lib": ">=0.5.2 <1.0.0",
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-json": "*",
|
||||
"ext-zip": "*",
|
||||
"mockery/mockery": "^1.3",
|
||||
"phpunit/phpunit": "^7.5 || ^8 || ^9",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gd": "Needed to process images",
|
||||
"ext-gmagick": "Improves image processing performance",
|
||||
"ext-imagick": "Improves image processing performance",
|
||||
"ext-zlib": "Needed for pdf stream compression"
|
||||
"php": ">=5.2.4"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Dompdf\\": "src/"
|
||||
},
|
||||
"classmap": [
|
||||
"lib/"
|
||||
"library"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-2.1"
|
||||
"GPL"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "The Dompdf Community",
|
||||
"homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md"
|
||||
}
|
||||
],
|
||||
"description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
|
||||
"homepage": "https://github.com/dompdf/dompdf",
|
||||
"support": {
|
||||
"issues": "https://github.com/dompdf/dompdf/issues",
|
||||
"source": "https://github.com/dompdf/dompdf/tree/v2.0.8"
|
||||
},
|
||||
"time": "2024-04-29T13:06:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "masterminds/html5",
|
||||
"version": "2.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Masterminds/html5-php.git",
|
||||
"reference": "fcf91eb64359852f00d921887b219479b4f21251"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251",
|
||||
"reference": "fcf91eb64359852f00d921887b219479b4f21251",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.7-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Masterminds\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Matt Butcher",
|
||||
"email": "technosophos@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Matt Farina",
|
||||
"email": "matt@mattfarina.com"
|
||||
},
|
||||
{
|
||||
"name": "Asmir Mustafic",
|
||||
"email": "goetas@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "An HTML5 parser and serializer.",
|
||||
"homepage": "http://masterminds.github.io/html5-php",
|
||||
"description": "ODT document generator",
|
||||
"homepage": "https://github.com/cybermonde/odtphp",
|
||||
"keywords": [
|
||||
"HTML5",
|
||||
"dom",
|
||||
"html",
|
||||
"parser",
|
||||
"querypath",
|
||||
"serializer",
|
||||
"xml"
|
||||
"odt",
|
||||
"php"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Masterminds/html5-php/issues",
|
||||
"source": "https://github.com/Masterminds/html5-php/tree/2.10.0"
|
||||
"issues": "https://github.com/cybermonde/odtphp/issues",
|
||||
"source": "https://github.com/cybermonde/odtphp/tree/v1.7"
|
||||
},
|
||||
"time": "2025-07-25T09:04:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phenx/php-font-lib",
|
||||
"version": "0.5.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dompdf/php-font-lib.git",
|
||||
"reference": "a1681e9793040740a405ac5b189275059e2a9863"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/a1681e9793040740a405ac5b189275059e2a9863",
|
||||
"reference": "a1681e9793040740a405ac5b189275059e2a9863",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FontLib\\": "src/FontLib"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-2.1-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Ménager",
|
||||
"email": "fabien.menager@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A library to read, parse, export and make subsets of different types of font files.",
|
||||
"homepage": "https://github.com/PhenX/php-font-lib",
|
||||
"support": {
|
||||
"issues": "https://github.com/dompdf/php-font-lib/issues",
|
||||
"source": "https://github.com/dompdf/php-font-lib/tree/0.5.6"
|
||||
},
|
||||
"time": "2024-01-29T14:45:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phenx/php-svg-lib",
|
||||
"version": "0.5.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dompdf/php-svg-lib.git",
|
||||
"reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/46b25da81613a9cf43c83b2a8c2c1bdab27df691",
|
||||
"reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"php": "^7.1 || ^8.0",
|
||||
"sabberworm/php-css-parser": "^8.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Svg\\": "src/Svg"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-3.0-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Ménager",
|
||||
"email": "fabien.menager@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A library to read, parse and export to PDF SVG files.",
|
||||
"homepage": "https://github.com/PhenX/php-svg-lib",
|
||||
"support": {
|
||||
"issues": "https://github.com/dompdf/php-svg-lib/issues",
|
||||
"source": "https://github.com/dompdf/php-svg-lib/tree/0.5.4"
|
||||
},
|
||||
"time": "2024-04-08T12:52:34+00:00"
|
||||
"time": "2015-06-02T07:28:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpoffice/math",
|
||||
|
|
@ -385,72 +205,6 @@
|
|||
},
|
||||
"time": "2025-06-05T10:32:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sabberworm/php-css-parser",
|
||||
"version": "v8.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MyIntervals/PHP-CSS-Parser.git",
|
||||
"reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/d8e916507b88e389e26d4ab03c904a082aa66bb9",
|
||||
"reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-iconv": "*",
|
||||
"php": "^5.6.20 || ^7.0.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.41",
|
||||
"rawr/cross-data-providers": "^2.0.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mbstring": "for parsing UTF-8 CSS"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "9.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Sabberworm\\CSS\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Raphael Schweikert"
|
||||
},
|
||||
{
|
||||
"name": "Oliver Klee",
|
||||
"email": "github@oliverklee.de"
|
||||
},
|
||||
{
|
||||
"name": "Jake Hotson",
|
||||
"email": "jake.github@qzdesign.co.uk"
|
||||
}
|
||||
],
|
||||
"description": "Parser for CSS Files written in PHP",
|
||||
"homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser",
|
||||
"keywords": [
|
||||
"css",
|
||||
"parser",
|
||||
"stylesheet"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues",
|
||||
"source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.9.0"
|
||||
},
|
||||
"time": "2025-07-11T13:20:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "tecnickcom/tcpdf",
|
||||
"version": "6.10.0",
|
||||
|
|
@ -526,10 +280,10 @@
|
|||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.3.0"
|
||||
"platform": {},
|
||||
"platform-dev": {},
|
||||
"plugin-api-version": "2.9.0"
|
||||
}
|
||||
|
|
|
|||
472
export_book.php
472
export_book.php
|
|
@ -46,7 +46,15 @@ if (!$book) {
|
|||
$_SESSION['error'] = "Книга не найдена";
|
||||
redirect('books.php');
|
||||
}
|
||||
// Получаем информацию об авторе
|
||||
$author_info = null;
|
||||
if ($book) {
|
||||
$stmt = $pdo->prepare("SELECT display_name, username FROM users WHERE id = ?");
|
||||
$stmt->execute([$book['user_id']]);
|
||||
$author_info = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
$author_name = $author_info['display_name'] ?? $author_info['username'] ?? 'Неизвестный автор';
|
||||
// Функция для очистки имени файла
|
||||
// function cleanFilename($filename) {
|
||||
// return preg_replace('/[^a-zA-Z0-9_\-]/', '_', $filename);
|
||||
|
|
@ -57,7 +65,104 @@ function markdownToPlainText($markdown) {
|
|||
// Обрабатываем диалоги (заменяем - на —)
|
||||
$markdown = preg_replace('/^- (.+)$/m', "— $1", $markdown);
|
||||
|
||||
// Убираем Markdown разметку
|
||||
// Убираем Markdown разметку, но сохраняем переносы строк
|
||||
$text = $markdown;
|
||||
|
||||
// Убираем заголовки
|
||||
$text = preg_replace('/^#+\s+/m', '', $text);
|
||||
|
||||
// Убираем жирный и курсив
|
||||
$text = preg_replace('/\*\*(.*?)\*\*/', '$1', $text);
|
||||
$text = preg_replace('/\*(.*?)\*/', '$1', $text);
|
||||
$text = preg_replace('/__(.*?)__/', '$1', $text);
|
||||
$text = preg_replace('/_(.*?)_/', '$1', $text);
|
||||
|
||||
// Убираем зачеркивание
|
||||
$text = preg_replace('/~~(.*?)~~/', '$1', $text);
|
||||
|
||||
// Убираем код (встроенный)
|
||||
$text = preg_replace('/`(.*?)`/', '$1', $text);
|
||||
|
||||
// Убираем блоки кода (сохраняем содержимое)
|
||||
$text = preg_replace('/```.*?\n(.*?)```/s', '$1', $text);
|
||||
|
||||
// Убираем ссылки
|
||||
$text = preg_replace('/\[(.*?)\]\(.*?\)/', '$1', $text);
|
||||
|
||||
// Обрабатываем списки - заменяем маркеры на *
|
||||
$text = preg_replace('/^[\*\-+]\s+/m', '* ', $text);
|
||||
$text = preg_replace('/^\d+\.\s+/m', '* ', $text);
|
||||
|
||||
// Обрабатываем цитаты
|
||||
$text = preg_replace('/^>\s+/m', '', $text);
|
||||
|
||||
return $text;
|
||||
}
|
||||
// Улучшенная функция для разбивки Markdown на абзацы с сохранением структуры
|
||||
function markdownToParagraphs($markdown) {
|
||||
// Нормализуем переносы строк
|
||||
$text = str_replace(["\r\n", "\r"], "\n", $markdown);
|
||||
|
||||
// Обрабатываем диалоги (заменяем - на —)
|
||||
$text = preg_replace('/^- (.+)$/m', "— $1", $text);
|
||||
|
||||
// Разбиваем на строки
|
||||
$lines = explode("\n", $text);
|
||||
$paragraphs = [];
|
||||
$currentParagraph = '';
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$trimmedLine = trim($line);
|
||||
|
||||
// Пустая строка - конец абзаца
|
||||
if (empty($trimmedLine)) {
|
||||
if (!empty($currentParagraph)) {
|
||||
$paragraphs[] = $currentParagraph;
|
||||
$currentParagraph = '';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Диалог (начинается с —) всегда начинает новый абзац
|
||||
if (str_starts_with($trimmedLine, '—')) {
|
||||
if (!empty($currentParagraph)) {
|
||||
$paragraphs[] = $currentParagraph;
|
||||
}
|
||||
$currentParagraph = $trimmedLine;
|
||||
$paragraphs[] = $currentParagraph;
|
||||
$currentParagraph = '';
|
||||
continue;
|
||||
}
|
||||
|
||||
// Заголовки (начинаются с #) всегда начинают новый абзац
|
||||
if (str_starts_with($trimmedLine, '#')) {
|
||||
if (!empty($currentParagraph)) {
|
||||
$paragraphs[] = $currentParagraph;
|
||||
}
|
||||
$currentParagraph = preg_replace('/^#+\s+/', '', $trimmedLine);
|
||||
$paragraphs[] = $currentParagraph;
|
||||
$currentParagraph = '';
|
||||
continue;
|
||||
}
|
||||
|
||||
// Обычный текст - добавляем к текущему абзацу
|
||||
if (!empty($currentParagraph)) {
|
||||
$currentParagraph .= ' ' . $trimmedLine;
|
||||
} else {
|
||||
$currentParagraph = $trimmedLine;
|
||||
}
|
||||
}
|
||||
|
||||
// Добавляем последний абзац
|
||||
if (!empty($currentParagraph)) {
|
||||
$paragraphs[] = $currentParagraph;
|
||||
}
|
||||
|
||||
return $paragraphs;
|
||||
}
|
||||
|
||||
// Функция для очистки Markdown разметки
|
||||
function cleanMarkdown($markdown) {
|
||||
$text = $markdown;
|
||||
|
||||
// Убираем заголовки
|
||||
|
|
@ -79,7 +184,7 @@ function markdownToPlainText($markdown) {
|
|||
// Убираем ссылки
|
||||
$text = preg_replace('/\[(.*?)\]\(.*?\)/', '$1', $text);
|
||||
|
||||
// Обрабатываем списки
|
||||
// Обрабатываем списки - убираем маркеры
|
||||
$text = preg_replace('/^[\*\-+]\s+/m', '', $text);
|
||||
$text = preg_replace('/^\d+\.\s+/m', '', $text);
|
||||
|
||||
|
|
@ -129,38 +234,38 @@ function formatPlainText($text) {
|
|||
// Обработка экспорта
|
||||
switch ($format) {
|
||||
case 'pdf':
|
||||
exportPDF($book, $chapters, $is_public);
|
||||
exportPDF($book, $chapters, $is_public, $author_name);
|
||||
break;
|
||||
case 'docx':
|
||||
exportDOCX($book, $chapters, $is_public);
|
||||
exportDOCX($book, $chapters, $is_public, $author_name);
|
||||
break;
|
||||
case 'odt':
|
||||
exportODT($book, $chapters, $is_public);
|
||||
exportODT($book, $chapters, $is_public, $author_name);
|
||||
break;
|
||||
case 'html':
|
||||
exportHTML($book, $chapters, $is_public);
|
||||
exportHTML($book, $chapters, $is_public, $author_name);
|
||||
break;
|
||||
case 'txt':
|
||||
exportTXT($book, $chapters, $is_public);
|
||||
exportTXT($book, $chapters, $is_public, $author_name);
|
||||
break;
|
||||
default:
|
||||
$_SESSION['error'] = "Неверный формат экспорта";
|
||||
redirect($share_token ? "view_book.php?share_token=$share_token" : "book_edit.php?id=$book_id");
|
||||
}
|
||||
|
||||
function exportPDF($book, $chapters, $is_public) {
|
||||
function exportPDF($book, $chapters, $is_public, $author_name) {
|
||||
global $Parsedown;
|
||||
|
||||
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
|
||||
|
||||
// Устанавливаем метаданные документа
|
||||
$pdf->SetCreator(APP_NAME);
|
||||
$pdf->SetAuthor($is_public ? 'Автор' : ($_SESSION['display_name'] ?? 'Автор'));
|
||||
$pdf->SetAuthor($author_name);
|
||||
$pdf->SetTitle($book['title']);
|
||||
$pdf->SetSubject($book['genre'] ?? '');
|
||||
|
||||
// Устанавливаем margins
|
||||
$pdf->SetMargins(15, 20, 15);
|
||||
$pdf->SetMargins(15, 25, 15);
|
||||
$pdf->SetHeaderMargin(10);
|
||||
$pdf->SetFooterMargin(10);
|
||||
|
||||
|
|
@ -174,10 +279,30 @@ function exportPDF($book, $chapters, $is_public) {
|
|||
$pdf->SetFont('dejavusans', '', 12);
|
||||
|
||||
// Заголовок книги
|
||||
$pdf->SetFont('dejavusans', 'B', 16);
|
||||
$pdf->SetFont('dejavusans', 'B', 18);
|
||||
$pdf->Cell(0, 10, $book['title'], 0, 1, 'C');
|
||||
$pdf->Ln(2);
|
||||
|
||||
// Автор
|
||||
$pdf->SetFont('dejavusans', 'I', 14);
|
||||
$pdf->Cell(0, 10, $author_name, 0, 1, 'C');
|
||||
$pdf->Ln(5);
|
||||
|
||||
// Обложка книги
|
||||
if (!empty($book['cover_image'])) {
|
||||
$cover_path = COVERS_PATH . $book['cover_image'];
|
||||
if (file_exists($cover_path)) {
|
||||
list($width, $height) = getimagesize($cover_path);
|
||||
$max_width = 80;
|
||||
$ratio = $width / $height;
|
||||
$new_height = $max_width / $ratio;
|
||||
|
||||
$x = (210 - $max_width) / 2;
|
||||
$pdf->Image($cover_path, $x, $pdf->GetY(), $max_width, $new_height, '', '', 'N', false, 300, '', false, false, 0, false, false, false);
|
||||
$pdf->Ln($new_height + 5);
|
||||
}
|
||||
}
|
||||
|
||||
// Жанр
|
||||
if (!empty($book['genre'])) {
|
||||
$pdf->SetFont('dejavusans', 'I', 12);
|
||||
|
|
@ -187,8 +312,27 @@ function exportPDF($book, $chapters, $is_public) {
|
|||
|
||||
// Описание
|
||||
if (!empty($book['description'])) {
|
||||
$pdf->SetFont('dejavusans', '', 12);
|
||||
$pdf->MultiCell(0, 8, $book['description'], 0, 'J');
|
||||
$pdf->SetFont('dejavusans', '', 11);
|
||||
$pdf->MultiCell(0, 6, $book['description'], 0, 'J');
|
||||
$pdf->Ln(10);
|
||||
}
|
||||
|
||||
// Интерактивное оглавление - СОЗДАЕМ ССЫЛКИ
|
||||
$chapterLinks = [];
|
||||
if (!empty($chapters)) {
|
||||
$pdf->SetFont('dejavusans', 'B', 14);
|
||||
$pdf->Cell(0, 10, 'Оглавление', 0, 1, 'C');
|
||||
$pdf->Ln(5);
|
||||
|
||||
$toc_page = $pdf->getPage();
|
||||
|
||||
$pdf->SetFont('dejavusans', '', 11);
|
||||
foreach ($chapters as $index => $chapter) {
|
||||
$chapter_number = $index + 1;
|
||||
$link = $pdf->AddLink();
|
||||
$chapterLinks[$chapter['id']] = $link; // Сохраняем ссылку для этой главы
|
||||
$pdf->Cell(0, 6, "{$chapter_number}. {$chapter['title']}", 0, 1, 'L', false, $link);
|
||||
}
|
||||
$pdf->Ln(10);
|
||||
}
|
||||
|
||||
|
|
@ -196,34 +340,37 @@ function exportPDF($book, $chapters, $is_public) {
|
|||
$pdf->Line(15, $pdf->GetY(), 195, $pdf->GetY());
|
||||
$pdf->Ln(10);
|
||||
|
||||
// Главы
|
||||
// Главы с закладками и правильными ссылками
|
||||
foreach ($chapters as $index => $chapter) {
|
||||
$pdf->SetFont('dejavusans', '', 12);
|
||||
// Добавляем новую страницу для каждой главы
|
||||
$pdf->AddPage();
|
||||
|
||||
// УСТАНАВЛИВАЕМ ЯКОРЬ ДЛЯ ССЫЛКИ
|
||||
if (isset($chapterLinks[$chapter['id']])) {
|
||||
$pdf->SetLink($chapterLinks[$chapter['id']]);
|
||||
}
|
||||
|
||||
// Устанавливаем закладку для этой главы
|
||||
$pdf->Bookmark($chapter['title'], 0, 0, '', 'B', array(0, 0, 0));
|
||||
|
||||
// Название главы
|
||||
$pdf->SetFont('dejavusans', 'B', 14);
|
||||
$pdf->Cell(0, 8, $chapter['title'], 0, 1);
|
||||
$pdf->Ln(2);
|
||||
|
||||
// Контент главы (форматированный HTML)
|
||||
// Контент главы
|
||||
$pdf->SetFont('dejavusans', '', 11);
|
||||
$htmlContent = $Parsedown->text($chapter['content']);
|
||||
$pdf->writeHTML($htmlContent, true, false, true, false, '');
|
||||
|
||||
$pdf->Ln(8);
|
||||
|
||||
// Разделитель между главами (кроме последней)
|
||||
if ($index < count($chapters) - 1) {
|
||||
$pdf->Line(15, $pdf->GetY(), 195, $pdf->GetY());
|
||||
$pdf->Ln(8);
|
||||
}
|
||||
}
|
||||
|
||||
// Футер с информацией
|
||||
$pdf->SetY(-25);
|
||||
$pdf->SetFont('dejavusans', 'I', 8);
|
||||
$pdf->Cell(0, 6, 'Экспортировано из ' . APP_NAME . ' - ' . date('d.m.Y H:i'), 0, 1, 'C');
|
||||
$pdf->Cell(0, 6, 'Всего глав: ' . count($chapters) . ' | Всего слов: ' . array_sum(array_column($chapters, 'word_count')), 0, 1, 'C');
|
||||
$pdf->Cell(0, 6, 'Автор: ' . $author_name . ' | Всего глав: ' . count($chapters) . ' | Всего слов: ' . array_sum(array_column($chapters, 'word_count')), 0, 1, 'C');
|
||||
|
||||
// Отправляем файл
|
||||
$filename = cleanFilename($book['title']) . '.pdf';
|
||||
|
|
@ -231,7 +378,7 @@ function exportPDF($book, $chapters, $is_public) {
|
|||
exit;
|
||||
}
|
||||
|
||||
function exportDOCX($book, $chapters, $is_public) {
|
||||
function exportDOCX($book, $chapters, $is_public, $author_name) {
|
||||
global $Parsedown;
|
||||
|
||||
$phpWord = new PhpWord();
|
||||
|
|
@ -245,8 +392,25 @@ function exportDOCX($book, $chapters, $is_public) {
|
|||
|
||||
// Заголовок книги
|
||||
$section->addText($book['title'], ['bold' => true, 'size' => 16], ['alignment' => 'center']);
|
||||
$section->addTextBreak(1);
|
||||
|
||||
// Автор
|
||||
$section->addText($author_name, ['italic' => true, 'size' => 14], ['alignment' => 'center']);
|
||||
$section->addTextBreak(2);
|
||||
|
||||
// Обложка книги
|
||||
if (!empty($book['cover_image'])) {
|
||||
$cover_path = COVERS_PATH . $book['cover_image'];
|
||||
if (file_exists($cover_path)) {
|
||||
$section->addImage($cover_path, [
|
||||
'width' => 150,
|
||||
'height' => 225,
|
||||
'alignment' => 'center'
|
||||
]);
|
||||
$section->addTextBreak(2);
|
||||
}
|
||||
}
|
||||
|
||||
// Жанр
|
||||
if (!empty($book['genre'])) {
|
||||
$section->addText('Жанр: ' . $book['genre'], ['italic' => true], ['alignment' => 'center']);
|
||||
|
|
@ -255,33 +419,52 @@ function exportDOCX($book, $chapters, $is_public) {
|
|||
|
||||
// Описание
|
||||
if (!empty($book['description'])) {
|
||||
$section->addText($book['description']);
|
||||
$descriptionParagraphs = markdownToParagraphs($book['description']);
|
||||
foreach ($descriptionParagraphs as $paragraph) {
|
||||
$section->addText($paragraph);
|
||||
}
|
||||
$section->addTextBreak(2);
|
||||
}
|
||||
|
||||
// Интерактивное оглавление
|
||||
if (!empty($chapters)) {
|
||||
$section->addText('Оглавление', ['bold' => true, 'size' => 14], ['alignment' => 'center']);
|
||||
$section->addTextBreak(1);
|
||||
|
||||
foreach ($chapters as $index => $chapter) {
|
||||
$chapter_number = $index + 1;
|
||||
// Создаем гиперссылку на заголовок главы - ИСПРАВЛЕННЫЙ СИНТАКСИС
|
||||
$section->addLink("chapter_{$chapter['id']}", "{$chapter_number}. {$chapter['title']}", null, null, true);
|
||||
$section->addTextBreak(1);
|
||||
}
|
||||
$section->addTextBreak(2);
|
||||
}
|
||||
|
||||
// Разделитель
|
||||
$section->addText('СОДЕРЖАНИЕ', ['bold' => true, 'size' => 14], ['alignment' => 'center']);
|
||||
$section->addTextBreak(2);
|
||||
$section->addPageBreak();
|
||||
|
||||
// Главы
|
||||
// Главы с закладками - ДОБАВЛЯЕМ ПРАВИЛЬНЫЕ ЗАКЛАДКИ
|
||||
foreach ($chapters as $index => $chapter) {
|
||||
// Добавляем закладку для главы ПЕРЕД заголовком
|
||||
$section->addBookmark("chapter_{$chapter['id']}");
|
||||
|
||||
// Заголовок главы
|
||||
$section->addText($chapter['title'], ['bold' => true, 'size' => 14]);
|
||||
$section->addTextBreak(1);
|
||||
|
||||
// Контент главы (форматированный HTML)
|
||||
$htmlContent = $Parsedown->text($chapter['content']);
|
||||
|
||||
// Упрощенное добавление HTML контента
|
||||
$plainContent = strip_tags($htmlContent);
|
||||
$paragraphs = explode("\n\n", $plainContent);
|
||||
// Получаем очищенный текст и разбиваем на абзацы
|
||||
$cleanContent = cleanMarkdown($chapter['content']);
|
||||
$paragraphs = markdownToParagraphs($cleanContent);
|
||||
|
||||
// Добавляем каждый абзац
|
||||
foreach ($paragraphs as $paragraph) {
|
||||
if (trim($paragraph)) {
|
||||
if (!empty(trim($paragraph))) {
|
||||
$section->addText($paragraph);
|
||||
$section->addTextBreak(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Разрыв страницы между главами (кроме последней)
|
||||
// Добавляем разрыв страницы между главами (кроме последней)
|
||||
if ($index < count($chapters) - 1) {
|
||||
$section->addPageBreak();
|
||||
}
|
||||
|
|
@ -290,7 +473,7 @@ function exportDOCX($book, $chapters, $is_public) {
|
|||
// Футер
|
||||
$section->addTextBreak(2);
|
||||
$section->addText('Экспортировано из ' . APP_NAME . ' - ' . date('d.m.Y H:i'), ['italic' => true, 'size' => 9]);
|
||||
$section->addText('Всего глав: ' . count($chapters) . ' | Всего слов: ' . array_sum(array_column($chapters, 'word_count')), ['italic' => true, 'size' => 9]);
|
||||
$section->addText('Автор: ' . $author_name . ' | Всего глав: ' . count($chapters) . ' | Всего слов: ' . array_sum(array_column($chapters, 'word_count')), ['italic' => true, 'size' => 9]);
|
||||
|
||||
// Сохраняем и отправляем
|
||||
$filename = cleanFilename($book['title']) . '.docx';
|
||||
|
|
@ -302,69 +485,7 @@ function exportDOCX($book, $chapters, $is_public) {
|
|||
exit;
|
||||
}
|
||||
|
||||
function exportODT($book, $chapters, $is_public) {
|
||||
global $Parsedown;
|
||||
|
||||
$phpWord = new PhpWord();
|
||||
|
||||
// Стили документа
|
||||
$phpWord->setDefaultFontName('Liberation Serif');
|
||||
$phpWord->setDefaultFontSize(12);
|
||||
|
||||
// Секция документа
|
||||
$section = $phpWord->addSection();
|
||||
|
||||
// Заголовок книги
|
||||
$section->addText($book['title'], ['bold' => true, 'size' => 16], ['alignment' => 'center']);
|
||||
$section->addTextBreak(2);
|
||||
|
||||
// Жанр
|
||||
if (!empty($book['genre'])) {
|
||||
$section->addText('Жанр: ' . $book['genre'], ['italic' => true], ['alignment' => 'center']);
|
||||
$section->addTextBreak(1);
|
||||
}
|
||||
|
||||
// Описание
|
||||
if (!empty($book['description'])) {
|
||||
$section->addText($book['description']);
|
||||
$section->addTextBreak(2);
|
||||
}
|
||||
|
||||
// Главы
|
||||
foreach ($chapters as $index => $chapter) {
|
||||
// Заголовок главы
|
||||
$section->addText($chapter['title'], ['bold' => true, 'size' => 14]);
|
||||
|
||||
// Контент главы (форматированный HTML)
|
||||
$htmlContent = $Parsedown->text($chapter['content']);
|
||||
$plainContent = strip_tags($htmlContent);
|
||||
$paragraphs = explode("\n\n", $plainContent);
|
||||
|
||||
foreach ($paragraphs as $paragraph) {
|
||||
if (trim($paragraph)) {
|
||||
$section->addText($paragraph);
|
||||
}
|
||||
}
|
||||
|
||||
$section->addTextBreak(2);
|
||||
}
|
||||
|
||||
// Футер
|
||||
$section->addTextBreak(2);
|
||||
$section->addText('Экспортировано из ' . APP_NAME . ' - ' . date('d.m.Y H:i'), ['italic' => true, 'size' => 9]);
|
||||
$section->addText('Всего глав: ' . count($chapters) . ' | Всего слов: ' . array_sum(array_column($chapters, 'word_count')), ['italic' => true, 'size' => 9]);
|
||||
|
||||
// Сохраняем и отправляем
|
||||
$filename = cleanFilename($book['title']) . '.odt';
|
||||
header('Content-Type: application/vnd.oasis.opendocument.text');
|
||||
header('Content-Disposition: attachment; filename="' . $filename . '"');
|
||||
|
||||
$objWriter = IOFactory::createWriter($phpWord, 'ODText');
|
||||
$objWriter->save('php://output');
|
||||
exit;
|
||||
}
|
||||
|
||||
function exportHTML($book, $chapters, $is_public) {
|
||||
function exportHTML($book, $chapters, $is_public, $author_name) {
|
||||
global $Parsedown;
|
||||
|
||||
$html = '<!DOCTYPE html>
|
||||
|
|
@ -378,7 +499,7 @@ function exportHTML($book, $chapters, $is_public) {
|
|||
font-family: "Times New Roman", serif;
|
||||
line-height: 1.6;
|
||||
margin: 40px;
|
||||
max-width: 800px;
|
||||
max-width: 900px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
color: #333;
|
||||
|
|
@ -387,7 +508,24 @@ function exportHTML($book, $chapters, $is_public) {
|
|||
text-align: center;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.book-author {
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
font-style: italic;
|
||||
color: #666;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.book-cover {
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.book-cover img {
|
||||
max-width: 200px;
|
||||
height: auto;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
.book-genre {
|
||||
text-align: center;
|
||||
|
|
@ -402,11 +540,41 @@ function exportHTML($book, $chapters, $is_public) {
|
|||
margin: 20px 0;
|
||||
border-left: 4px solid #007bff;
|
||||
}
|
||||
.table-of-contents {
|
||||
background: #f8f9fa;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
margin: 20px 0;
|
||||
columns: 2;
|
||||
column-gap: 2rem;
|
||||
}
|
||||
.table-of-contents h3 {
|
||||
margin-top: 0;
|
||||
text-align: center;
|
||||
column-span: all;
|
||||
}
|
||||
.table-of-contents ul {
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
.table-of-contents li {
|
||||
margin-bottom: 5px;
|
||||
padding: 5px 0;
|
||||
break-inside: avoid;
|
||||
}
|
||||
.table-of-contents a {
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
}
|
||||
.table-of-contents a:hover {
|
||||
color: #007bff;
|
||||
}
|
||||
.chapter-title {
|
||||
border-bottom: 2px solid #007bff;
|
||||
padding-bottom: 10px;
|
||||
margin-top: 30px;
|
||||
font-size: 20px;
|
||||
scroll-margin-top: 2rem;
|
||||
}
|
||||
.chapter-content {
|
||||
margin: 20px 0;
|
||||
|
|
@ -420,13 +588,22 @@ function exportHTML($book, $chapters, $is_public) {
|
|||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
/* Улучшаем отображение абзацев */
|
||||
.chapter-content p {
|
||||
margin-bottom: 1em;
|
||||
text-align: justify;
|
||||
}
|
||||
.dialogue {
|
||||
margin-left: 2rem;
|
||||
font-style: italic;
|
||||
color: #2c5aa0;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
/* Остальные стили */
|
||||
.chapter-content h1, .chapter-content h2, .chapter-content h3 {
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
.chapter-content p {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
.chapter-content blockquote {
|
||||
border-left: 4px solid #007bff;
|
||||
padding-left: 15px;
|
||||
|
|
@ -462,29 +639,51 @@ function exportHTML($book, $chapters, $is_public) {
|
|||
.chapter-content th {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
.dialogue {
|
||||
margin-left: 2rem;
|
||||
font-style: italic;
|
||||
color: #2c5aa0;
|
||||
@media (max-width: 768px) {
|
||||
.table-of-contents {
|
||||
columns: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="book-title">' . htmlspecialchars($book['title']) . '</div>';
|
||||
<div class="book-title">' . htmlspecialchars($book['title']) . '</div>
|
||||
<div class="book-author">' . htmlspecialchars($author_name) . '</div>';
|
||||
|
||||
if (!empty($book['genre'])) {
|
||||
$html .= '<div class="book-genre">Жанр: ' . htmlspecialchars($book['genre']) . '</div>';
|
||||
}
|
||||
|
||||
// Обложка книги
|
||||
if (!empty($book['cover_image'])) {
|
||||
$cover_url = COVERS_URL . $book['cover_image'];
|
||||
$html .= '<div class="book-cover">';
|
||||
$html .= '<img src="' . $cover_url . '" alt="' . htmlspecialchars($book['title']) . '">';
|
||||
$html .= '</div>';
|
||||
}
|
||||
|
||||
if (!empty($book['description'])) {
|
||||
$html .= '<div class="book-description">' . nl2br(htmlspecialchars($book['description'])) . '</div>';
|
||||
}
|
||||
|
||||
// Интерактивное оглавление
|
||||
if (!empty($chapters)) {
|
||||
$html .= '<div>';
|
||||
$html .= '<h3>Оглавление</h3>';
|
||||
$html .= '<ul>';
|
||||
foreach ($chapters as $index => $chapter) {
|
||||
$chapter_number = $index + 1;
|
||||
$html .= '<li><a href="#chapter-' . $chapter['id'] . '">' . $chapter_number . '. ' . htmlspecialchars($chapter['title']) . '</a></li>';
|
||||
}
|
||||
$html .= '</ul>';
|
||||
$html .= '</div>';
|
||||
}
|
||||
|
||||
$html .= '<hr style="margin: 30px 0;">';
|
||||
|
||||
foreach ($chapters as $index => $chapter) {
|
||||
$html .= '<div class="chapter">';
|
||||
$html .= '<div class="chapter-title">' . htmlspecialchars($chapter['title']) . '</div>';
|
||||
$html .= '<div class="chapter-title" id="chapter-' . $chapter['id'] . '" name="chapter-' . $chapter['id'] . '">' . htmlspecialchars($chapter['title']) . '</div>';
|
||||
|
||||
$htmlContent = $Parsedown->text($chapter['content']);
|
||||
$html .= '<div class="chapter-content">' . $htmlContent . '</div>';
|
||||
|
|
@ -497,7 +696,7 @@ function exportHTML($book, $chapters, $is_public) {
|
|||
|
||||
$html .= '<div class="footer">
|
||||
Экспортировано из ' . APP_NAME . ' - ' . date('d.m.Y H:i') . '<br>
|
||||
Всего глав: ' . count($chapters) . ' | Всего слов: ' . array_sum(array_column($chapters, 'word_count')) . '
|
||||
Автор: ' . htmlspecialchars($author_name) . ' | Всего глав: ' . count($chapters) . ' | Всего слов: ' . array_sum(array_column($chapters, 'word_count')) . '
|
||||
</div>
|
||||
</body>
|
||||
</html>';
|
||||
|
|
@ -509,10 +708,11 @@ function exportHTML($book, $chapters, $is_public) {
|
|||
exit;
|
||||
}
|
||||
|
||||
function exportTXT($book, $chapters, $is_public) {
|
||||
$content = "=" . str_repeat("=", 60) . "=\n";
|
||||
$content .= str_pad($book['title'], 60, " ", STR_PAD_BOTH) . "\n";
|
||||
$content .= "=" . str_repeat("=", 60) . "=\n\n";
|
||||
function exportTXT($book, $chapters, $is_public, $author_name) {
|
||||
$content = "=" . str_repeat("=", 80) . "=\n";
|
||||
$content .= str_pad($book['title'], 80, " ", STR_PAD_BOTH) . "\n";
|
||||
$content .= str_pad($author_name, 80, " ", STR_PAD_BOTH) . "\n";
|
||||
$content .= "=" . str_repeat("=", 80) . "=\n\n";
|
||||
|
||||
if (!empty($book['genre'])) {
|
||||
$content .= "Жанр: " . $book['genre'] . "\n\n";
|
||||
|
|
@ -520,29 +720,47 @@ function exportTXT($book, $chapters, $is_public) {
|
|||
|
||||
if (!empty($book['description'])) {
|
||||
$content .= "ОПИСАНИЕ:\n";
|
||||
$content .= wordwrap($book['description'], 80) . "\n\n";
|
||||
// Увеличиваем ширину до 144 символов (80 * 1.8)
|
||||
$content .= wordwrap($book['description'], 144) . "\n\n";
|
||||
}
|
||||
|
||||
$content .= str_repeat("-", 80) . "\n\n";
|
||||
// Оглавление
|
||||
if (!empty($chapters)) {
|
||||
$content .= "ОГЛАВЛЕНИЕ:\n";
|
||||
$content .= str_repeat("-", 60) . "\n";
|
||||
foreach ($chapters as $index => $chapter) {
|
||||
$chapter_number = $index + 1;
|
||||
$content .= "{$chapter_number}. {$chapter['title']}\n";
|
||||
}
|
||||
$content .= "\n";
|
||||
}
|
||||
|
||||
$content .= str_repeat("-", 144) . "\n\n";
|
||||
|
||||
foreach ($chapters as $index => $chapter) {
|
||||
$content .= $chapter['title'] . "\n";
|
||||
$content .= str_repeat("-", 40) . "\n\n";
|
||||
$content .= str_repeat("-", 60) . "\n\n";
|
||||
|
||||
// Форматируем текст для TXT
|
||||
$plainText = markdownToPlainText($chapter['content']);
|
||||
$formattedText = formatPlainText($plainText);
|
||||
$content .= wordwrap($formattedText, 80) . "\n\n";
|
||||
// Получаем очищенный текст и разбиваем на абзацы
|
||||
$cleanContent = cleanMarkdown($chapter['content']);
|
||||
$paragraphs = markdownToParagraphs($cleanContent);
|
||||
|
||||
foreach ($paragraphs as $paragraph) {
|
||||
if (!empty(trim($paragraph))) {
|
||||
// Увеличиваем ширину до 144 символов
|
||||
$content .= wordwrap($paragraph, 144) . "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($index < count($chapters) - 1) {
|
||||
$content .= str_repeat("-", 80) . "\n\n";
|
||||
$content .= str_repeat("-", 144) . "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
$content .= "\n" . str_repeat("=", 80) . "\n";
|
||||
$content .= "\n" . str_repeat("=", 144) . "\n";
|
||||
$content .= "Экспортировано из " . APP_NAME . " - " . date('d.m.Y H:i') . "\n";
|
||||
$content .= "Всего глав: " . count($chapters) . " | Всего слов: " . array_sum(array_column($chapters, 'word_count')) . "\n";
|
||||
$content .= str_repeat("=", 80) . "\n";
|
||||
$content .= "Автор: " . $author_name . " | Всего глав: " . count($chapters) . " | Всего слов: " . array_sum(array_column($chapters, 'word_count')) . "\n";
|
||||
$content .= str_repeat("=", 144) . "\n";
|
||||
|
||||
$filename = cleanFilename($book['title']) . '.txt';
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 172 KiB |
|
|
@ -8,9 +8,18 @@ $baseDir = dirname($vendorDir);
|
|||
return array(
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
'Datamatrix' => $vendorDir . '/tecnickcom/tcpdf/include/barcodes/datamatrix.php',
|
||||
'Dompdf\\Cpdf' => $vendorDir . '/dompdf/dompdf/lib/Cpdf.php',
|
||||
'Odf' => $vendorDir . '/cybermonde/odtphp/library/Odf.php',
|
||||
'OdfException' => $vendorDir . '/cybermonde/odtphp/library/Odf.php',
|
||||
'PDF417' => $vendorDir . '/tecnickcom/tcpdf/include/barcodes/pdf417.php',
|
||||
'PclZip' => $vendorDir . '/cybermonde/odtphp/library/zip/pclzip/pclzip.lib.php',
|
||||
'PclZipProxy' => $vendorDir . '/cybermonde/odtphp/library/zip/PclZipProxy.php',
|
||||
'PclZipProxyException' => $vendorDir . '/cybermonde/odtphp/library/zip/PclZipProxy.php',
|
||||
'PhpZipProxy' => $vendorDir . '/cybermonde/odtphp/library/zip/PhpZipProxy.php',
|
||||
'PhpZipProxyException' => $vendorDir . '/cybermonde/odtphp/library/zip/PhpZipProxy.php',
|
||||
'QRcode' => $vendorDir . '/tecnickcom/tcpdf/include/barcodes/qrcode.php',
|
||||
'Segment' => $vendorDir . '/cybermonde/odtphp/library/Segment.php',
|
||||
'SegmentException' => $vendorDir . '/cybermonde/odtphp/library/Segment.php',
|
||||
'SegmentIterator' => $vendorDir . '/cybermonde/odtphp/library/SegmentIterator.php',
|
||||
'TCPDF' => $vendorDir . '/tecnickcom/tcpdf/tcpdf.php',
|
||||
'TCPDF2DBarcode' => $vendorDir . '/tecnickcom/tcpdf/tcpdf_barcodes_2d.php',
|
||||
'TCPDFBarcode' => $vendorDir . '/tecnickcom/tcpdf/tcpdf_barcodes_1d.php',
|
||||
|
|
@ -20,4 +29,5 @@ return array(
|
|||
'TCPDF_FONT_DATA' => $vendorDir . '/tecnickcom/tcpdf/include/tcpdf_font_data.php',
|
||||
'TCPDF_IMAGES' => $vendorDir . '/tecnickcom/tcpdf/include/tcpdf_images.php',
|
||||
'TCPDF_STATIC' => $vendorDir . '/tecnickcom/tcpdf/include/tcpdf_static.php',
|
||||
'ZipInterface' => $vendorDir . '/cybermonde/odtphp/library/zip/ZipInterface.php',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -6,11 +6,6 @@ $vendorDir = dirname(__DIR__);
|
|||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Svg\\' => array($vendorDir . '/phenx/php-svg-lib/src/Svg'),
|
||||
'Sabberworm\\CSS\\' => array($vendorDir . '/sabberworm/php-css-parser/src'),
|
||||
'PhpOffice\\PhpWord\\' => array($vendorDir . '/phpoffice/phpword/src/PhpWord'),
|
||||
'PhpOffice\\Math\\' => array($vendorDir . '/phpoffice/math/src/Math'),
|
||||
'Masterminds\\' => array($vendorDir . '/masterminds/html5/src'),
|
||||
'FontLib\\' => array($vendorDir . '/phenx/php-font-lib/src/FontLib'),
|
||||
'Dompdf\\' => array($vendorDir . '/dompdf/dompdf/src'),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -7,39 +7,14 @@ namespace Composer\Autoload;
|
|||
class ComposerStaticInitfc3c92cecb1ffdb92cb5808b88609e81
|
||||
{
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'S' =>
|
||||
array (
|
||||
'Svg\\' => 4,
|
||||
'Sabberworm\\CSS\\' => 15,
|
||||
),
|
||||
'P' =>
|
||||
array (
|
||||
'PhpOffice\\PhpWord\\' => 18,
|
||||
'PhpOffice\\Math\\' => 15,
|
||||
),
|
||||
'M' =>
|
||||
array (
|
||||
'Masterminds\\' => 12,
|
||||
),
|
||||
'F' =>
|
||||
array (
|
||||
'FontLib\\' => 8,
|
||||
),
|
||||
'D' =>
|
||||
array (
|
||||
'Dompdf\\' => 7,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'Svg\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/phenx/php-svg-lib/src/Svg',
|
||||
),
|
||||
'Sabberworm\\CSS\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabberworm/php-css-parser/src',
|
||||
),
|
||||
'PhpOffice\\PhpWord\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/phpoffice/phpword/src/PhpWord',
|
||||
|
|
@ -48,26 +23,23 @@ class ComposerStaticInitfc3c92cecb1ffdb92cb5808b88609e81
|
|||
array (
|
||||
0 => __DIR__ . '/..' . '/phpoffice/math/src/Math',
|
||||
),
|
||||
'Masterminds\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/masterminds/html5/src',
|
||||
),
|
||||
'FontLib\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/phenx/php-font-lib/src/FontLib',
|
||||
),
|
||||
'Dompdf\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/dompdf/dompdf/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
'Datamatrix' => __DIR__ . '/..' . '/tecnickcom/tcpdf/include/barcodes/datamatrix.php',
|
||||
'Dompdf\\Cpdf' => __DIR__ . '/..' . '/dompdf/dompdf/lib/Cpdf.php',
|
||||
'Odf' => __DIR__ . '/..' . '/cybermonde/odtphp/library/Odf.php',
|
||||
'OdfException' => __DIR__ . '/..' . '/cybermonde/odtphp/library/Odf.php',
|
||||
'PDF417' => __DIR__ . '/..' . '/tecnickcom/tcpdf/include/barcodes/pdf417.php',
|
||||
'PclZip' => __DIR__ . '/..' . '/cybermonde/odtphp/library/zip/pclzip/pclzip.lib.php',
|
||||
'PclZipProxy' => __DIR__ . '/..' . '/cybermonde/odtphp/library/zip/PclZipProxy.php',
|
||||
'PclZipProxyException' => __DIR__ . '/..' . '/cybermonde/odtphp/library/zip/PclZipProxy.php',
|
||||
'PhpZipProxy' => __DIR__ . '/..' . '/cybermonde/odtphp/library/zip/PhpZipProxy.php',
|
||||
'PhpZipProxyException' => __DIR__ . '/..' . '/cybermonde/odtphp/library/zip/PhpZipProxy.php',
|
||||
'QRcode' => __DIR__ . '/..' . '/tecnickcom/tcpdf/include/barcodes/qrcode.php',
|
||||
'Segment' => __DIR__ . '/..' . '/cybermonde/odtphp/library/Segment.php',
|
||||
'SegmentException' => __DIR__ . '/..' . '/cybermonde/odtphp/library/Segment.php',
|
||||
'SegmentIterator' => __DIR__ . '/..' . '/cybermonde/odtphp/library/SegmentIterator.php',
|
||||
'TCPDF' => __DIR__ . '/..' . '/tecnickcom/tcpdf/tcpdf.php',
|
||||
'TCPDF2DBarcode' => __DIR__ . '/..' . '/tecnickcom/tcpdf/tcpdf_barcodes_2d.php',
|
||||
'TCPDFBarcode' => __DIR__ . '/..' . '/tecnickcom/tcpdf/tcpdf_barcodes_1d.php',
|
||||
|
|
@ -77,6 +49,7 @@ class ComposerStaticInitfc3c92cecb1ffdb92cb5808b88609e81
|
|||
'TCPDF_FONT_DATA' => __DIR__ . '/..' . '/tecnickcom/tcpdf/include/tcpdf_font_data.php',
|
||||
'TCPDF_IMAGES' => __DIR__ . '/..' . '/tecnickcom/tcpdf/include/tcpdf_images.php',
|
||||
'TCPDF_STATIC' => __DIR__ . '/..' . '/tecnickcom/tcpdf/include/tcpdf_static.php',
|
||||
'ZipInterface' => __DIR__ . '/..' . '/cybermonde/odtphp/library/zip/ZipInterface.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
|
|
|
|||
|
|
@ -1,235 +1,46 @@
|
|||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "dompdf/dompdf",
|
||||
"version": "v2.0.8",
|
||||
"version_normalized": "2.0.8.0",
|
||||
"name": "cybermonde/odtphp",
|
||||
"version": "v1.7",
|
||||
"version_normalized": "1.7.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dompdf/dompdf.git",
|
||||
"reference": "c20247574601700e1f7c8dab39310fca1964dc52"
|
||||
"url": "https://github.com/cybermonde/odtphp.git",
|
||||
"reference": "23aba70923ca3c07af15a5600f4072751c1b4a36"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dompdf/dompdf/zipball/c20247574601700e1f7c8dab39310fca1964dc52",
|
||||
"reference": "c20247574601700e1f7c8dab39310fca1964dc52",
|
||||
"url": "https://api.github.com/repos/cybermonde/odtphp/zipball/23aba70923ca3c07af15a5600f4072751c1b4a36",
|
||||
"reference": "23aba70923ca3c07af15a5600f4072751c1b4a36",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-mbstring": "*",
|
||||
"masterminds/html5": "^2.0",
|
||||
"phenx/php-font-lib": ">=0.5.4 <1.0.0",
|
||||
"phenx/php-svg-lib": ">=0.5.2 <1.0.0",
|
||||
"php": "^7.1 || ^8.0"
|
||||
"php": ">=5.2.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-json": "*",
|
||||
"ext-zip": "*",
|
||||
"mockery/mockery": "^1.3",
|
||||
"phpunit/phpunit": "^7.5 || ^8 || ^9",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gd": "Needed to process images",
|
||||
"ext-gmagick": "Improves image processing performance",
|
||||
"ext-imagick": "Improves image processing performance",
|
||||
"ext-zlib": "Needed for pdf stream compression"
|
||||
},
|
||||
"time": "2024-04-29T13:06:17+00:00",
|
||||
"time": "2015-06-02T07:28:25+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Dompdf\\": "src/"
|
||||
},
|
||||
"classmap": [
|
||||
"lib/"
|
||||
"library"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-2.1"
|
||||
"GPL"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "The Dompdf Community",
|
||||
"homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md"
|
||||
}
|
||||
],
|
||||
"description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
|
||||
"homepage": "https://github.com/dompdf/dompdf",
|
||||
"support": {
|
||||
"issues": "https://github.com/dompdf/dompdf/issues",
|
||||
"source": "https://github.com/dompdf/dompdf/tree/v2.0.8"
|
||||
},
|
||||
"install-path": "../dompdf/dompdf"
|
||||
},
|
||||
{
|
||||
"name": "masterminds/html5",
|
||||
"version": "2.10.0",
|
||||
"version_normalized": "2.10.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Masterminds/html5-php.git",
|
||||
"reference": "fcf91eb64359852f00d921887b219479b4f21251"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251",
|
||||
"reference": "fcf91eb64359852f00d921887b219479b4f21251",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9"
|
||||
},
|
||||
"time": "2025-07-25T09:04:22+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.7-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Masterminds\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Matt Butcher",
|
||||
"email": "technosophos@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Matt Farina",
|
||||
"email": "matt@mattfarina.com"
|
||||
},
|
||||
{
|
||||
"name": "Asmir Mustafic",
|
||||
"email": "goetas@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "An HTML5 parser and serializer.",
|
||||
"homepage": "http://masterminds.github.io/html5-php",
|
||||
"description": "ODT document generator",
|
||||
"homepage": "https://github.com/cybermonde/odtphp",
|
||||
"keywords": [
|
||||
"HTML5",
|
||||
"dom",
|
||||
"html",
|
||||
"parser",
|
||||
"querypath",
|
||||
"serializer",
|
||||
"xml"
|
||||
"odt",
|
||||
"php"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Masterminds/html5-php/issues",
|
||||
"source": "https://github.com/Masterminds/html5-php/tree/2.10.0"
|
||||
"issues": "https://github.com/cybermonde/odtphp/issues",
|
||||
"source": "https://github.com/cybermonde/odtphp/tree/v1.7"
|
||||
},
|
||||
"install-path": "../masterminds/html5"
|
||||
},
|
||||
{
|
||||
"name": "phenx/php-font-lib",
|
||||
"version": "0.5.6",
|
||||
"version_normalized": "0.5.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dompdf/php-font-lib.git",
|
||||
"reference": "a1681e9793040740a405ac5b189275059e2a9863"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/a1681e9793040740a405ac5b189275059e2a9863",
|
||||
"reference": "a1681e9793040740a405ac5b189275059e2a9863",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6"
|
||||
},
|
||||
"time": "2024-01-29T14:45:26+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FontLib\\": "src/FontLib"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-2.1-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Ménager",
|
||||
"email": "fabien.menager@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A library to read, parse, export and make subsets of different types of font files.",
|
||||
"homepage": "https://github.com/PhenX/php-font-lib",
|
||||
"support": {
|
||||
"issues": "https://github.com/dompdf/php-font-lib/issues",
|
||||
"source": "https://github.com/dompdf/php-font-lib/tree/0.5.6"
|
||||
},
|
||||
"install-path": "../phenx/php-font-lib"
|
||||
},
|
||||
{
|
||||
"name": "phenx/php-svg-lib",
|
||||
"version": "0.5.4",
|
||||
"version_normalized": "0.5.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dompdf/php-svg-lib.git",
|
||||
"reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/46b25da81613a9cf43c83b2a8c2c1bdab27df691",
|
||||
"reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"php": "^7.1 || ^8.0",
|
||||
"sabberworm/php-css-parser": "^8.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5"
|
||||
},
|
||||
"time": "2024-04-08T12:52:34+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Svg\\": "src/Svg"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-3.0-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Ménager",
|
||||
"email": "fabien.menager@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A library to read, parse and export to PDF SVG files.",
|
||||
"homepage": "https://github.com/PhenX/php-svg-lib",
|
||||
"support": {
|
||||
"issues": "https://github.com/dompdf/php-svg-lib/issues",
|
||||
"source": "https://github.com/dompdf/php-svg-lib/tree/0.5.4"
|
||||
},
|
||||
"install-path": "../phenx/php-svg-lib"
|
||||
"install-path": "../cybermonde/odtphp"
|
||||
},
|
||||
{
|
||||
"name": "phpoffice/math",
|
||||
|
|
@ -397,75 +208,6 @@
|
|||
},
|
||||
"install-path": "../phpoffice/phpword"
|
||||
},
|
||||
{
|
||||
"name": "sabberworm/php-css-parser",
|
||||
"version": "v8.9.0",
|
||||
"version_normalized": "8.9.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MyIntervals/PHP-CSS-Parser.git",
|
||||
"reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/d8e916507b88e389e26d4ab03c904a082aa66bb9",
|
||||
"reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-iconv": "*",
|
||||
"php": "^5.6.20 || ^7.0.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.41",
|
||||
"rawr/cross-data-providers": "^2.0.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mbstring": "for parsing UTF-8 CSS"
|
||||
},
|
||||
"time": "2025-07-11T13:20:48+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "9.0.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Sabberworm\\CSS\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Raphael Schweikert"
|
||||
},
|
||||
{
|
||||
"name": "Oliver Klee",
|
||||
"email": "github@oliverklee.de"
|
||||
},
|
||||
{
|
||||
"name": "Jake Hotson",
|
||||
"email": "jake.github@qzdesign.co.uk"
|
||||
}
|
||||
],
|
||||
"description": "Parser for CSS Files written in PHP",
|
||||
"homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser",
|
||||
"keywords": [
|
||||
"css",
|
||||
"parser",
|
||||
"stylesheet"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues",
|
||||
"source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.9.0"
|
||||
},
|
||||
"install-path": "../sabberworm/php-css-parser"
|
||||
},
|
||||
{
|
||||
"name": "tecnickcom/tcpdf",
|
||||
"version": "6.10.0",
|
||||
|
|
|
|||
|
|
@ -19,39 +19,12 @@
|
|||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'dompdf/dompdf' => array(
|
||||
'pretty_version' => 'v2.0.8',
|
||||
'version' => '2.0.8.0',
|
||||
'reference' => 'c20247574601700e1f7c8dab39310fca1964dc52',
|
||||
'cybermonde/odtphp' => array(
|
||||
'pretty_version' => 'v1.7',
|
||||
'version' => '1.7.0.0',
|
||||
'reference' => '23aba70923ca3c07af15a5600f4072751c1b4a36',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../dompdf/dompdf',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'masterminds/html5' => array(
|
||||
'pretty_version' => '2.10.0',
|
||||
'version' => '2.10.0.0',
|
||||
'reference' => 'fcf91eb64359852f00d921887b219479b4f21251',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../masterminds/html5',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'phenx/php-font-lib' => array(
|
||||
'pretty_version' => '0.5.6',
|
||||
'version' => '0.5.6.0',
|
||||
'reference' => 'a1681e9793040740a405ac5b189275059e2a9863',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phenx/php-font-lib',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'phenx/php-svg-lib' => array(
|
||||
'pretty_version' => '0.5.4',
|
||||
'version' => '0.5.4.0',
|
||||
'reference' => '46b25da81613a9cf43c83b2a8c2c1bdab27df691',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phenx/php-svg-lib',
|
||||
'install_path' => __DIR__ . '/../cybermonde/odtphp',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
|
|
@ -73,15 +46,6 @@
|
|||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'sabberworm/php-css-parser' => array(
|
||||
'pretty_version' => 'v8.9.0',
|
||||
'version' => '8.9.0.0',
|
||||
'reference' => 'd8e916507b88e389e26d4ab03c904a082aa66bb9',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sabberworm/php-css-parser',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'tecnickcom/tcpdf' => array(
|
||||
'pretty_version' => '6.10.0',
|
||||
'version' => '6.10.0.0',
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
Matt Butcher [technosophos] <technosophos@gmail.com> (lead)
|
||||
Matt Farina [mattfarina] <matt@mattfarina.com> (lead)
|
||||
Asmir Mustafic [goetas] <goetas@lignano.it> (contributor)
|
||||
Edward Z. Yang [ezyang] <ezyang@mit.edu> (contributor)
|
||||
Geoffrey Sneddon [gsnedders] <geoffers@gmail.com> (contributor)
|
||||
Kukhar Vasily [ngreduce] <ngreduce@gmail.com> (contributor)
|
||||
Rune Christensen [MrElectronic] <mrelectronic@example.com> (contributor)
|
||||
Mišo Belica [miso-belica] <miso-belica@example.com> (contributor)
|
||||
Asmir Mustafic [goetas] <goetas@example.com> (contributor)
|
||||
KITAITI Makoto [KitaitiMakoto] <KitaitiMakoto@example.com> (contributor)
|
||||
Jacob Floyd [cognifloyd] <cognifloyd@gmail.com> (contributor)
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
## HTML5-PHP License
|
||||
|
||||
Copyright (c) 2013 The Authors of HTML5-PHP
|
||||
|
||||
Matt Butcher - mattbutcher@google.com
|
||||
Matt Farina - matt@mattfarina.com
|
||||
Asmir Mustafic - goetas@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
## HTML5Lib License
|
||||
|
||||
Portions of this are based on html5lib's PHP version, which was a
|
||||
sub-project of html5lib. The following is the list of contributors from
|
||||
html5lib:
|
||||
|
||||
html5lib:
|
||||
|
||||
Copyright (c) 2006-2009 The Authors
|
||||
|
||||
Contributors:
|
||||
James Graham - jg307@cam.ac.uk
|
||||
Anne van Kesteren - annevankesteren@gmail.com
|
||||
Lachlan Hunt - lachlan.hunt@lachy.id.au
|
||||
Matt McDonald - kanashii@kanashii.ca
|
||||
Sam Ruby - rubys@intertwingly.net
|
||||
Ian Hickson (Google) - ian@hixie.ch
|
||||
Thomas Broyer - t.broyer@ltgt.net
|
||||
Jacques Distler - distler@golem.ph.utexas.edu
|
||||
Henri Sivonen - hsivonen@iki.fi
|
||||
Adam Barth - abarth@webkit.org
|
||||
Eric Seidel - eric@webkit.org
|
||||
The Mozilla Foundation (contributions from Henri Sivonen since 2008)
|
||||
David Flanagan (Mozilla) - dflanagan@mozilla.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -1,270 +0,0 @@
|
|||
> # UKRAINE NEEDS YOUR HELP NOW!
|
||||
>
|
||||
> On 24 February 2022, Russian [President Vladimir Putin ordered an invasion of Ukraine by Russian Armed Forces](https://www.bbc.com/news/world-europe-60504334).
|
||||
>
|
||||
> Your support is urgently needed.
|
||||
>
|
||||
> - Donate to the volunteers. Here is the volunteer fund helping the Ukrainian army to provide all the necessary equipment:
|
||||
> https://bank.gov.ua/en/news/all/natsionalniy-bank-vidkriv-spetsrahunok-dlya-zboru-koshtiv-na-potrebi-armiyi or https://savelife.in.ua/en/donate/
|
||||
> - Triple-check social media sources. Russian disinformation is attempting to coverup and distort the reality in Ukraine.
|
||||
> - Help Ukrainian refugees who are fleeing Russian attacks and shellings: https://www.globalcitizen.org/en/content/ways-to-help-ukraine-conflict/
|
||||
> - Put pressure on your political representatives to provide help to Ukraine.
|
||||
> - Believe in the Ukrainian people, they will not surrender, they don't have another Ukraine.
|
||||
>
|
||||
> THANK YOU!
|
||||
----
|
||||
|
||||
# HTML5-PHP
|
||||
|
||||
HTML5 is a standards-compliant HTML5 parser and writer written entirely in PHP.
|
||||
It is stable and used in many production websites, and has
|
||||
well over [five million downloads](https://packagist.org/packages/masterminds/html5).
|
||||
|
||||
HTML5 provides the following features.
|
||||
|
||||
- An HTML5 serializer
|
||||
- Support for PHP namespaces
|
||||
- Composer support
|
||||
- Event-based (SAX-like) parser
|
||||
- A DOM tree builder
|
||||
- Interoperability with [QueryPath](https://github.com/technosophos/querypath)
|
||||
- Runs on **PHP** 5.3.0 or newer
|
||||
|
||||
[](https://github.com/Masterminds/html5-php/actions/workflows/ci.yaml)
|
||||
[](https://packagist.org/packages/masterminds/html5)
|
||||
[](https://scrutinizer-ci.com/g/Masterminds/html5-php/?branch=master)
|
||||
[](https://scrutinizer-ci.com/g/Masterminds/html5-php/?branch=master)
|
||||
[](https://masterminds.github.io/stability/sustained.html)
|
||||
|
||||
## Installation
|
||||
|
||||
Install HTML5-PHP using [composer](http://getcomposer.org/).
|
||||
|
||||
By adding the `masterminds/html5` dependency to your `composer.json` file:
|
||||
|
||||
```json
|
||||
{
|
||||
"require" : {
|
||||
"masterminds/html5": "^2.0"
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
By invoking require command via composer executable:
|
||||
|
||||
```bash
|
||||
composer require masterminds/html5
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
|
||||
HTML5-PHP has a high-level API and a low-level API.
|
||||
|
||||
Here is how you use the high-level `HTML5` library API:
|
||||
|
||||
```php
|
||||
<?php
|
||||
// Assuming you installed from Composer:
|
||||
require "vendor/autoload.php";
|
||||
|
||||
use Masterminds\HTML5;
|
||||
|
||||
// An example HTML document:
|
||||
$html = <<< 'HERE'
|
||||
<html>
|
||||
<head>
|
||||
<title>TEST</title>
|
||||
</head>
|
||||
<body id='foo'>
|
||||
<h1>Hello World</h1>
|
||||
<p>This is a test of the HTML5 parser.</p>
|
||||
</body>
|
||||
</html>
|
||||
HERE;
|
||||
|
||||
// Parse the document. $dom is a DOMDocument.
|
||||
$html5 = new HTML5();
|
||||
$dom = $html5->loadHTML($html);
|
||||
|
||||
// Render it as HTML5:
|
||||
print $html5->saveHTML($dom);
|
||||
|
||||
// Or save it to a file:
|
||||
$html5->save($dom, 'out.html');
|
||||
```
|
||||
|
||||
The `$dom` created by the parser is a full `DOMDocument` object. And the
|
||||
`save()` and `saveHTML()` methods will take any DOMDocument.
|
||||
|
||||
### Options
|
||||
|
||||
It is possible to pass in an array of configuration options when loading
|
||||
an HTML5 document.
|
||||
|
||||
```php
|
||||
// An associative array of options
|
||||
$options = array(
|
||||
'option_name' => 'option_value',
|
||||
);
|
||||
|
||||
// Provide the options to the constructor
|
||||
$html5 = new HTML5($options);
|
||||
|
||||
$dom = $html5->loadHTML($html);
|
||||
```
|
||||
|
||||
The following options are supported:
|
||||
|
||||
* `encode_entities` (boolean): Indicates that the serializer should aggressively
|
||||
encode characters as entities. Without this, it only encodes the bare
|
||||
minimum.
|
||||
* `disable_html_ns` (boolean): Prevents the parser from automatically
|
||||
assigning the HTML5 namespace to the DOM document. This is for
|
||||
non-namespace aware DOM tools.
|
||||
* `target_document` (\DOMDocument): A DOM document that will be used as the
|
||||
destination for the parsed nodes.
|
||||
* `implicit_namespaces` (array): An assoc array of namespaces that should be
|
||||
used by the parser. Name is tag prefix, value is NS URI.
|
||||
|
||||
## The Low-Level API
|
||||
|
||||
This library provides the following low-level APIs that you can use to
|
||||
create more customized HTML5 tools:
|
||||
|
||||
- A SAX-like event-based parser that you can hook into for special kinds
|
||||
of parsing.
|
||||
- A flexible error-reporting mechanism that can be tuned to document
|
||||
syntax checking.
|
||||
- A DOM implementation that uses PHP's built-in DOM library.
|
||||
|
||||
The unit tests exercise each piece of the API, and every public function
|
||||
is well-documented.
|
||||
|
||||
### Parser Design
|
||||
|
||||
The parser is designed as follows:
|
||||
|
||||
- The `Scanner` handles scanning on behalf of the parser.
|
||||
- The `Tokenizer` requests data off of the scanner, parses it, clasifies
|
||||
it, and sends it to an `EventHandler`. It is a *recursive descent parser.*
|
||||
- The `EventHandler` receives notifications and data for each specific
|
||||
semantic event that occurs during tokenization.
|
||||
- The `DOMBuilder` is an `EventHandler` that listens for tokenizing
|
||||
events and builds a document tree (`DOMDocument`) based on the events.
|
||||
|
||||
### Serializer Design
|
||||
|
||||
The serializer takes a data structure (the `DOMDocument`) and transforms
|
||||
it into a character representation -- an HTML5 document.
|
||||
|
||||
The serializer is broken into three parts:
|
||||
|
||||
- The `OutputRules` contain the rules to turn DOM elements into strings. The
|
||||
rules are an implementation of the interface `RulesInterface` allowing for
|
||||
different rule sets to be used.
|
||||
- The `Traverser`, which is a special-purpose tree walker. It visits
|
||||
each node node in the tree and uses the `OutputRules` to transform the node
|
||||
into a string.
|
||||
- `HTML5` manages the `Traverser` and stores the resultant data
|
||||
in the correct place.
|
||||
|
||||
The serializer (`save()`, `saveHTML()`) follows the
|
||||
[section 8.9 of the HTML 5.0 spec](http://www.w3.org/TR/2012/CR-html5-20121217/syntax.html#serializing-html-fragments).
|
||||
So tags are serialized according to these rules:
|
||||
|
||||
- A tag with children: <foo>CHILDREN</foo>
|
||||
- A tag that cannot have content: <foo> (no closing tag)
|
||||
- A tag that could have content, but doesn't: <foo></foo>
|
||||
|
||||
## Known Issues (Or, Things We Designed Against the Spec)
|
||||
|
||||
Please check the issue queue for a full list, but the following are
|
||||
issues known issues that are not presently on the roadmap:
|
||||
|
||||
- Namespaces: HTML5 only [supports a selected list of namespaces](http://www.w3.org/TR/html5/infrastructure.html#namespaces)
|
||||
and they do not operate in the same way as XML namespaces. A `:` has no special
|
||||
meaning.
|
||||
By default the parser does not support XML style namespaces via `:`;
|
||||
to enable the XML namespaces see the [XML Namespaces section](#xml-namespaces)
|
||||
- Scripts: This parser does not contain a JavaScript or a CSS
|
||||
interpreter. While one may be supplied, not all features will be
|
||||
supported.
|
||||
- Reentrance: The current parser is not re-entrant. (Thus you can't pause
|
||||
the parser to modify the HTML string mid-parse.)
|
||||
- Validation: The current tree builder is **not** a validating parser.
|
||||
While it will correct some HTML, it does not check that the HTML
|
||||
conforms to the standard. (Should you wish, you can build a validating
|
||||
parser by extending DOMTree or building your own EventHandler
|
||||
implementation.)
|
||||
* There is limited support for insertion modes.
|
||||
* Some autocorrection is done automatically.
|
||||
* Per the spec, many legacy tags are admitted and correctly handled,
|
||||
even though they are technically not part of HTML5.
|
||||
- Attribute names and values: Due to the implementation details of the
|
||||
PHP implementation of DOM, attribute names that do not follow the
|
||||
XML 1.0 standard are not inserted into the DOM. (Effectively, they
|
||||
are ignored.) If you've got a clever fix for this, jump in!
|
||||
- Processor Instructions: The HTML5 spec does not allow processor
|
||||
instructions. We do. Since this is a server-side library, we think
|
||||
this is useful. And that means, dear reader, that in some cases you
|
||||
can parse the HTML from a mixed PHP/HTML document. This, however,
|
||||
is an incidental feature, not a core feature.
|
||||
- HTML manifests: Unsupported.
|
||||
- PLAINTEXT: Unsupported.
|
||||
- Adoption Agency Algorithm: Not yet implemented. (8.2.5.4.7)
|
||||
|
||||
## XML Namespaces
|
||||
|
||||
To use XML style namespaces you have to configure well the main `HTML5` instance.
|
||||
|
||||
```php
|
||||
use Masterminds\HTML5;
|
||||
$html = new HTML5(array(
|
||||
"xmlNamespaces" => true
|
||||
));
|
||||
|
||||
$dom = $html->loadHTML('<t:tag xmlns:t="http://www.example.com"/>');
|
||||
|
||||
$dom->documentElement->namespaceURI; // http://www.example.com
|
||||
|
||||
```
|
||||
|
||||
You can also add some default prefixes that will not require the namespace declaration,
|
||||
but its elements will be namespaced.
|
||||
|
||||
```php
|
||||
use Masterminds\HTML5;
|
||||
$html = new HTML5(array(
|
||||
"implicitNamespaces"=>array(
|
||||
"t"=>"http://www.example.com"
|
||||
)
|
||||
));
|
||||
|
||||
$dom = $html->loadHTML('<t:tag/>');
|
||||
|
||||
$dom->documentElement->namespaceURI; // http://www.example.com
|
||||
|
||||
```
|
||||
|
||||
## Thanks to...
|
||||
|
||||
The dedicated (and patient) contributors of patches small and large,
|
||||
who have already made this library better.See the CREDITS file for
|
||||
a list of contributors.
|
||||
|
||||
We owe a huge debt of gratitude to the original authors of html5lib.
|
||||
|
||||
While not much of the original parser remains, we learned a lot from
|
||||
reading the html5lib library. And some pieces remain here. In
|
||||
particular, much of the UTF-8 and Unicode handling is derived from the
|
||||
html5lib project.
|
||||
|
||||
## License
|
||||
|
||||
This software is released under the MIT license. The original html5lib
|
||||
library was also released under the MIT license.
|
||||
|
||||
See LICENSE.txt
|
||||
|
||||
Certain files contain copyright assertions by specific individuals
|
||||
involved with html5lib. Those have been retained where appropriate.
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
# Release Notes
|
||||
|
||||
2.7.6 (2021-08-18)
|
||||
|
||||
- #218: Address comment handling issues
|
||||
|
||||
2.7.5 (2021-07-01)
|
||||
|
||||
- #204: Travis: Enable tests on PHP 8.0
|
||||
- #207: Fix PHP 8.1 deprecations
|
||||
|
||||
2.7.4 (2020-10-01)
|
||||
|
||||
- #191: Fix travisci build
|
||||
- #195: Add .gitattributes file with export-ignore rules
|
||||
- #194: Fix query parameter parsed as character entity
|
||||
|
||||
2.7.3 (2020-07-05)
|
||||
|
||||
- #190: mitigate cyclic reference between output rules and the traverser objects
|
||||
|
||||
2.7.2 (2020-07-01)
|
||||
|
||||
- #187: Fixed memory leak in HTML5::saveHTML()
|
||||
- #186: Add special case for end tag </br>
|
||||
|
||||
2.7.1 (2020-06-14)
|
||||
|
||||
- #171: add PHP 7.4 job
|
||||
- #178: Prevent infinite loop on un-terminated entity declaration at EOF
|
||||
|
||||
2.7.0 (2019-07-25)
|
||||
|
||||
- #164: Drop HHVM support
|
||||
- #168: Set default encoding in the DOMDocument object
|
||||
|
||||
2.6.0 (2019-03-10)
|
||||
|
||||
- #163: Allow to pass a charset to the Scanner
|
||||
|
||||
2.5.0 (2018-12-27)
|
||||
|
||||
- #162, #161, #155, #154, #153, #151: big performance improvements
|
||||
- #156: fixed typos
|
||||
- #160: adopt and enforce code style
|
||||
- #159: remove deprecated php unit base test case
|
||||
- #150: backport changes from old master branch
|
||||
|
||||
2.4.0 (2018-11-17)
|
||||
|
||||
- #148: Improve performance by moving sequence matching
|
||||
- #147: Improve the Tokenizer performance
|
||||
- #146: Improve performance by relying on a native string instead of InputStream
|
||||
- #144: Add DOM extension in composer.json
|
||||
- #145: Add more extensions on composer.json, improve phpdocs and remove dead code
|
||||
- #143: Remove experimental comment
|
||||
|
||||
2.3.1 (2018-10-18)
|
||||
|
||||
- #121: Audio is not a block tag (fixed by #141)
|
||||
- #136: Handle illegal self-closing according to spec (fixed by #137)
|
||||
- #141: Minor fixes in the README
|
||||
|
||||
2.3.0 (2017-09-04)
|
||||
|
||||
- #129: image within inline svg breaks system (fixed by #133)
|
||||
- #131: ² does not work (fixed by #132)
|
||||
- #134: Improve tokenizer performance by 20% (alternative version of #130 thanks to @MichaelHeerklotz)
|
||||
- #135: Raw & in attributes
|
||||
|
||||
2.2.2 (2016-09-22)
|
||||
|
||||
- #116: In XML mode, tags are case sensitive
|
||||
- #115: Fix PHP Notice in OutputRules
|
||||
- #112: fix parsing of options of an optgroup
|
||||
- #111: Adding test for the address tag
|
||||
|
||||
2.2.1 (2016-05-10)
|
||||
|
||||
- #109: Fixed issue where address tag could be written without closing tag (thanks sylus)
|
||||
|
||||
2.2.0 (2016-04-11)
|
||||
|
||||
- #105: Enable composer cache (for CI/CD)
|
||||
- #100: Use mb_substitute_character inset of ini_set for environments where ini_set is disable (e.g., shared hosting)
|
||||
- #98: Allow link, meta, style tags in noscript tags
|
||||
- #96: Fixed xml:href on svgs that use the "use" breaking
|
||||
- #94: Counting UTF8 characters performance improvement
|
||||
- #93: Use newer version of coveralls package
|
||||
- #90: Remove duplicate test
|
||||
- #87: Allow multiple root nodes
|
||||
|
||||
2.1.2 (2015-06-07)
|
||||
- #82: Support for PHP7
|
||||
- #84: Improved boolean attribute handling
|
||||
|
||||
2.1.1 (2015-03-23)
|
||||
- #78: Fixes bug where unmatched entity like string drops everything after &.
|
||||
|
||||
2.1.0 (2015-02-01)
|
||||
- #74: Added `disable_html_ns` and `target_doc` dom parsing options
|
||||
- Unified option names
|
||||
- #73: Fixed alphabet, ß now can be detected
|
||||
- #75 and #76: Allow whitespace in RCDATA tags
|
||||
- #77: Fixed parsing blunder for json embeds
|
||||
- #72: Add options to HTML methods
|
||||
|
||||
2.0.2 (2014-12-17)
|
||||
- #50: empty document handling
|
||||
- #63: tags with strange capitalization
|
||||
- #65: dashes and underscores as allowed characters in tag names
|
||||
- #68: Fixed issue with non-inline elements inside inline containers
|
||||
|
||||
2.0.1 (2014-09-23)
|
||||
- #59: Fixed issue parsing some fragments.
|
||||
- #56: Incorrectly saw 0 as empty string
|
||||
- Sami as new documentation generator
|
||||
|
||||
2.0.0 (2014-07-28)
|
||||
- #53: Improved boolean attributes handling
|
||||
- #52: Facebook HHVM compatibility
|
||||
- #48: Adopted PSR-2 as coding standard
|
||||
- #47: Moved everything to Masterminds namespace
|
||||
- #45: Added custom namespaces
|
||||
- #44: Added support to XML-style namespaces
|
||||
- #37: Refactored HTML5 class removing static methods
|
||||
|
||||
1.0.5 (2014-06-10)
|
||||
- #38: Set the dev-master branch as the 1.0.x branch for composer (goetas)
|
||||
- #34: Tests use PSR-4 for autoloading. (goetas)
|
||||
- #40, #41: Fix entity handling in RCDATA sections. (KitaitiMakoto)
|
||||
- #32: Fixed issue where wharacter references were being incorrectly encoded in style tags.
|
||||
|
||||
1.0.4 (2014-04-29)
|
||||
- #30/#31 Don't throw an exception for invalid tag names.
|
||||
|
||||
1.0.3 (2014-02-28)
|
||||
- #23 and #29: Ignore attributes with illegal chars in name for the PHP DOM.
|
||||
|
||||
1.0.2 (2014-02-12)
|
||||
- #23: Handle missing tag close in attribute list.
|
||||
- #25: Fixed text escaping in the serializer (HTML% 8.3).
|
||||
- #27: Fixed tests on Windows: changed "\n" -> PHP_EOL.
|
||||
- #28: Fixed infinite loop for char "&" in unquoted attribute in parser.
|
||||
- #26: Updated tag name case handling to deal with uppercase usage.
|
||||
- #24: Newlines and tabs are allowed inside quoted attributes (HTML5 8.2.4).
|
||||
- Fixed Travis CI testing.
|
||||
|
||||
1.0.1 (2013-11-07)
|
||||
- CDATA encoding is improved. (Non-standard; Issue #19)
|
||||
- Some parser rules were not returning the new current element. (Issue #20)
|
||||
- Added, to the README, details on code test coverage and to packagist version.
|
||||
- Fixed processor instructions.
|
||||
- Improved test coverage and documentation coverage.
|
||||
|
||||
1.0.0 (2013-10-02)
|
||||
- Initial release.
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
From 1.x to 2.x
|
||||
=================
|
||||
|
||||
- All classes uses `Masterminds` namespace.
|
||||
- All public static methods has been removed from `HTML5` class and the general API to access the HTML5 functionalities has changed.
|
||||
|
||||
Before:
|
||||
|
||||
$dom = \HTML5::loadHTML('<html>....');
|
||||
\HTML5::saveHTML($dom);
|
||||
|
||||
After:
|
||||
|
||||
use Masterminds\HTML5;
|
||||
|
||||
$html5 = new HTML5();
|
||||
|
||||
$dom = $html5->loadHTML('<html>....');
|
||||
echo $html5->saveHTML($dom);
|
||||
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Fetch the entities.json file and convert to PHP datastructure.
|
||||
*/
|
||||
|
||||
// The URL to the official entities JSON file.
|
||||
$ENTITIES_URL = 'http://www.w3.org/TR/2012/CR-html5-20121217/entities.json';
|
||||
|
||||
$payload = file_get_contents($ENTITIES_URL);
|
||||
$json = json_decode($payload);
|
||||
|
||||
$table = array();
|
||||
foreach ($json as $name => $obj) {
|
||||
$sname = substr($name, 1, -1);
|
||||
$table[$sname] = $obj->characters;
|
||||
}
|
||||
|
||||
echo '<?php
|
||||
namespace Masterminds\\HTML5;
|
||||
/** Entity lookup tables. This class is automatically generated. */
|
||||
class Entities {
|
||||
public static $byName = ';
|
||||
var_export($table);
|
||||
echo ';
|
||||
}' . PHP_EOL;
|
||||
//print serialize($table);
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
{
|
||||
"name": "masterminds/html5",
|
||||
"description": "An HTML5 parser and serializer.",
|
||||
"type": "library",
|
||||
"homepage": "http://masterminds.github.io/html5-php",
|
||||
"license": "MIT",
|
||||
"keywords": ["xml", "html", "html5", "dom", "parser", "serializer", "querypath"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Matt Butcher",
|
||||
"email": "technosophos@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Matt Farina",
|
||||
"email": "matt@mattfarina.com"
|
||||
},
|
||||
{
|
||||
"name": "Asmir Mustafic",
|
||||
"email": "goetas@gmail.com"
|
||||
}
|
||||
],
|
||||
"require" : {
|
||||
"ext-dom": "*",
|
||||
"php" : ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit" : "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {"Masterminds\\": "src"}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {"Masterminds\\HTML5\\Tests\\": "test/HTML5"}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.7-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,245 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Masterminds;
|
||||
|
||||
use Masterminds\HTML5\Parser\DOMTreeBuilder;
|
||||
use Masterminds\HTML5\Parser\Scanner;
|
||||
use Masterminds\HTML5\Parser\Tokenizer;
|
||||
use Masterminds\HTML5\Serializer\OutputRules;
|
||||
use Masterminds\HTML5\Serializer\Traverser;
|
||||
|
||||
/**
|
||||
* This class offers convenience methods for parsing and serializing HTML5.
|
||||
* It is roughly designed to mirror the \DOMDocument native class.
|
||||
*/
|
||||
class HTML5
|
||||
{
|
||||
/**
|
||||
* Global options for the parser and serializer.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $defaultOptions = array(
|
||||
// Whether the serializer should aggressively encode all characters as entities.
|
||||
'encode_entities' => false,
|
||||
|
||||
// Prevents the parser from automatically assigning the HTML5 namespace to the DOM document.
|
||||
'disable_html_ns' => false,
|
||||
);
|
||||
|
||||
protected $errors = array();
|
||||
|
||||
public function __construct(array $defaultOptions = array())
|
||||
{
|
||||
$this->defaultOptions = array_merge($this->defaultOptions, $defaultOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current default options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
return $this->defaultOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and parse an HTML file.
|
||||
*
|
||||
* This will apply the HTML5 parser, which is tolerant of many
|
||||
* varieties of HTML, including XHTML 1, HTML 4, and well-formed HTML
|
||||
* 3. Note that in these cases, not all of the old data will be
|
||||
* preserved. For example, XHTML's XML declaration will be removed.
|
||||
*
|
||||
* The rules governing parsing are set out in the HTML 5 spec.
|
||||
*
|
||||
* @param string|resource $file The path to the file to parse. If this is a resource, it is
|
||||
* assumed to be an open stream whose pointer is set to the first
|
||||
* byte of input.
|
||||
* @param array $options Configuration options when parsing the HTML.
|
||||
*
|
||||
* @return \DOMDocument A DOM document. These object type is defined by the libxml
|
||||
* library, and should have been included with your version of PHP.
|
||||
*/
|
||||
public function load($file, array $options = array())
|
||||
{
|
||||
// Handle the case where file is a resource.
|
||||
if (is_resource($file)) {
|
||||
return $this->parse(stream_get_contents($file), $options);
|
||||
}
|
||||
|
||||
return $this->parse(file_get_contents($file), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a HTML Document from a string.
|
||||
*
|
||||
* Take a string of HTML 5 (or earlier) and parse it into a
|
||||
* DOMDocument.
|
||||
*
|
||||
* @param string $string A html5 document as a string.
|
||||
* @param array $options Configuration options when parsing the HTML.
|
||||
*
|
||||
* @return \DOMDocument A DOM document. DOM is part of libxml, which is included with
|
||||
* almost all distribtions of PHP.
|
||||
*/
|
||||
public function loadHTML($string, array $options = array())
|
||||
{
|
||||
return $this->parse($string, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to load an HTML file.
|
||||
*
|
||||
* This is here to provide backwards compatibility with the
|
||||
* PHP DOM implementation. It simply calls load().
|
||||
*
|
||||
* @param string $file The path to the file to parse. If this is a resource, it is
|
||||
* assumed to be an open stream whose pointer is set to the first
|
||||
* byte of input.
|
||||
* @param array $options Configuration options when parsing the HTML.
|
||||
*
|
||||
* @return \DOMDocument A DOM document. These object type is defined by the libxml
|
||||
* library, and should have been included with your version of PHP.
|
||||
*/
|
||||
public function loadHTMLFile($file, array $options = array())
|
||||
{
|
||||
return $this->load($file, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a HTML fragment from a string.
|
||||
*
|
||||
* @param string $string the HTML5 fragment as a string
|
||||
* @param array $options Configuration options when parsing the HTML
|
||||
*
|
||||
* @return \DOMDocumentFragment A DOM fragment. The DOM is part of libxml, which is included with
|
||||
* almost all distributions of PHP.
|
||||
*/
|
||||
public function loadHTMLFragment($string, array $options = array())
|
||||
{
|
||||
return $this->parseFragment($string, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all errors encountered into parsing phase.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getErrors()
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true it some errors were encountered into parsing phase.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasErrors()
|
||||
{
|
||||
return count($this->errors) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an input string.
|
||||
*
|
||||
* @param string $input
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
public function parse($input, array $options = array())
|
||||
{
|
||||
$this->errors = array();
|
||||
$options = array_merge($this->defaultOptions, $options);
|
||||
$events = new DOMTreeBuilder(false, $options);
|
||||
$scanner = new Scanner($input, !empty($options['encoding']) ? $options['encoding'] : 'UTF-8');
|
||||
$parser = new Tokenizer($scanner, $events, !empty($options['xmlNamespaces']) ? Tokenizer::CONFORMANT_XML : Tokenizer::CONFORMANT_HTML);
|
||||
|
||||
$parser->parse();
|
||||
$this->errors = $events->getErrors();
|
||||
|
||||
return $events->document();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an input stream where the stream is a fragment.
|
||||
*
|
||||
* Lower-level loading function. This requires an input stream instead
|
||||
* of a string, file, or resource.
|
||||
*
|
||||
* @param string $input The input data to parse in the form of a string.
|
||||
* @param array $options An array of options.
|
||||
*
|
||||
* @return \DOMDocumentFragment
|
||||
*/
|
||||
public function parseFragment($input, array $options = array())
|
||||
{
|
||||
$options = array_merge($this->defaultOptions, $options);
|
||||
$events = new DOMTreeBuilder(true, $options);
|
||||
$scanner = new Scanner($input, !empty($options['encoding']) ? $options['encoding'] : 'UTF-8');
|
||||
$parser = new Tokenizer($scanner, $events, !empty($options['xmlNamespaces']) ? Tokenizer::CONFORMANT_XML : Tokenizer::CONFORMANT_HTML);
|
||||
|
||||
$parser->parse();
|
||||
$this->errors = $events->getErrors();
|
||||
|
||||
return $events->fragment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a DOM into a given file as HTML5.
|
||||
*
|
||||
* @param mixed $dom The DOM to be serialized.
|
||||
* @param string|resource $file The filename to be written or resource to write to.
|
||||
* @param array $options Configuration options when serializing the DOM. These include:
|
||||
* - encode_entities: Text written to the output is escaped by default and not all
|
||||
* entities are encoded. If this is set to true all entities will be encoded.
|
||||
* Defaults to false.
|
||||
*/
|
||||
public function save($dom, $file, $options = array())
|
||||
{
|
||||
$close = true;
|
||||
if (is_resource($file)) {
|
||||
$stream = $file;
|
||||
$close = false;
|
||||
} else {
|
||||
$stream = fopen($file, 'wb');
|
||||
}
|
||||
$options = array_merge($this->defaultOptions, $options);
|
||||
$rules = new OutputRules($stream, $options);
|
||||
$trav = new Traverser($dom, $stream, $rules, $options);
|
||||
|
||||
$trav->walk();
|
||||
/*
|
||||
* release the traverser to avoid cyclic references and allow PHP to free memory without waiting for gc_collect_cycles
|
||||
*/
|
||||
$rules->unsetTraverser();
|
||||
if ($close) {
|
||||
fclose($stream);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a DOM into an HTML5 string.
|
||||
*
|
||||
* @param mixed $dom The DOM to be serialized.
|
||||
* @param array $options Configuration options when serializing the DOM. These include:
|
||||
* - encode_entities: Text written to the output is escaped by default and not all
|
||||
* entities are encoded. If this is set to true all entities will be encoded.
|
||||
* Defaults to false.
|
||||
*
|
||||
* @return string A HTML5 documented generated from the DOM.
|
||||
*/
|
||||
public function saveHTML($dom, $options = array())
|
||||
{
|
||||
$stream = fopen('php://temp', 'wb');
|
||||
$this->save($dom, $stream, array_merge($this->defaultOptions, $options));
|
||||
|
||||
$html = stream_get_contents($stream, -1, 0);
|
||||
|
||||
fclose($stream);
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,637 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Provide general element functions.
|
||||
*/
|
||||
|
||||
namespace Masterminds\HTML5;
|
||||
|
||||
/**
|
||||
* This class provides general information about HTML5 elements,
|
||||
* including syntactic and semantic issues.
|
||||
* Parsers and serializers can
|
||||
* use this class as a reference point for information about the rules
|
||||
* of various HTML5 elements.
|
||||
*
|
||||
* @todo consider using a bitmask table lookup. There is enough overlap in
|
||||
* naming that this could significantly shrink the size and maybe make it
|
||||
* faster. See the Go teams implementation at https://code.google.com/p/go/source/browse/html/atom.
|
||||
*/
|
||||
class Elements
|
||||
{
|
||||
/**
|
||||
* Indicates an element is described in the specification.
|
||||
*/
|
||||
const KNOWN_ELEMENT = 1;
|
||||
|
||||
// From section 8.1.2: "script", "style"
|
||||
// From 8.2.5.4.7 ("in body" insertion mode): "noembed"
|
||||
// From 8.4 "style", "xmp", "iframe", "noembed", "noframes"
|
||||
/**
|
||||
* Indicates the contained text should be processed as raw text.
|
||||
*/
|
||||
const TEXT_RAW = 2;
|
||||
|
||||
// From section 8.1.2: "textarea", "title"
|
||||
/**
|
||||
* Indicates the contained text should be processed as RCDATA.
|
||||
*/
|
||||
const TEXT_RCDATA = 4;
|
||||
|
||||
/**
|
||||
* Indicates the tag cannot have content.
|
||||
*/
|
||||
const VOID_TAG = 8;
|
||||
|
||||
// "address", "article", "aside", "blockquote", "center", "details", "dialog", "dir", "div", "dl",
|
||||
// "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "menu",
|
||||
// "nav", "ol", "p", "section", "summary", "ul"
|
||||
// "h1", "h2", "h3", "h4", "h5", "h6"
|
||||
// "pre", "listing"
|
||||
// "form"
|
||||
// "plaintext"
|
||||
/**
|
||||
* Indicates that if a previous event is for a P tag, that element
|
||||
* should be considered closed.
|
||||
*/
|
||||
const AUTOCLOSE_P = 16;
|
||||
|
||||
/**
|
||||
* Indicates that the text inside is plaintext (pre).
|
||||
*/
|
||||
const TEXT_PLAINTEXT = 32;
|
||||
|
||||
// See https://developer.mozilla.org/en-US/docs/HTML/Block-level_elements
|
||||
/**
|
||||
* Indicates that the tag is a block.
|
||||
*/
|
||||
const BLOCK_TAG = 64;
|
||||
|
||||
/**
|
||||
* Indicates that the tag allows only inline elements as child nodes.
|
||||
*/
|
||||
const BLOCK_ONLY_INLINE = 128;
|
||||
|
||||
/**
|
||||
* Elements with optional end tags that cause auto-closing of previous and parent tags,
|
||||
* as example most of the table related tags, see https://www.w3.org/TR/html401/struct/tables.html
|
||||
* Structure is as follows:
|
||||
* TAG-NAME => [PARENT-TAG-NAME-TO-CLOSE1, PARENT-TAG-NAME-TO-CLOSE2, ...].
|
||||
*
|
||||
* Order is important, after auto-closing one parent with might have to close also their parent.
|
||||
*
|
||||
* @var array<string, string[]>
|
||||
*/
|
||||
public static $optionalEndElementsParentsToClose = array(
|
||||
'tr' => array('td', 'tr'),
|
||||
'td' => array('td', 'th'),
|
||||
'th' => array('td', 'th'),
|
||||
'tfoot' => array('td', 'th', 'tr', 'tbody', 'thead'),
|
||||
'tbody' => array('td', 'th', 'tr', 'thead'),
|
||||
);
|
||||
|
||||
/**
|
||||
* The HTML5 elements as defined in http://dev.w3.org/html5/markup/elements.html.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $html5 = array(
|
||||
'a' => 1,
|
||||
'abbr' => 1,
|
||||
'address' => 65, // NORMAL | BLOCK_TAG
|
||||
'area' => 9, // NORMAL | VOID_TAG
|
||||
'article' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'aside' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'audio' => 1, // NORMAL
|
||||
'b' => 1,
|
||||
'base' => 9, // NORMAL | VOID_TAG
|
||||
'bdi' => 1,
|
||||
'bdo' => 1,
|
||||
'blockquote' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'body' => 1,
|
||||
'br' => 9, // NORMAL | VOID_TAG
|
||||
'button' => 1,
|
||||
'canvas' => 65, // NORMAL | BLOCK_TAG
|
||||
'caption' => 1,
|
||||
'cite' => 1,
|
||||
'code' => 1,
|
||||
'col' => 9, // NORMAL | VOID_TAG
|
||||
'colgroup' => 1,
|
||||
'command' => 9, // NORMAL | VOID_TAG
|
||||
// "data" => 1, // This is highly experimental and only part of the whatwg spec (not w3c). See https://developer.mozilla.org/en-US/docs/HTML/Element/data
|
||||
'datalist' => 1,
|
||||
'dd' => 65, // NORMAL | BLOCK_TAG
|
||||
'del' => 1,
|
||||
'details' => 17, // NORMAL | AUTOCLOSE_P,
|
||||
'dfn' => 1,
|
||||
'dialog' => 17, // NORMAL | AUTOCLOSE_P,
|
||||
'div' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'dl' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'dt' => 1,
|
||||
'em' => 1,
|
||||
'embed' => 9, // NORMAL | VOID_TAG
|
||||
'fieldset' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'figcaption' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'figure' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'footer' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'form' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'h1' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'h2' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'h3' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'h4' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'h5' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'h6' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'head' => 1,
|
||||
'header' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'hgroup' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'hr' => 73, // NORMAL | VOID_TAG
|
||||
'html' => 1,
|
||||
'i' => 1,
|
||||
'iframe' => 3, // NORMAL | TEXT_RAW
|
||||
'img' => 9, // NORMAL | VOID_TAG
|
||||
'input' => 9, // NORMAL | VOID_TAG
|
||||
'kbd' => 1,
|
||||
'ins' => 1,
|
||||
'keygen' => 9, // NORMAL | VOID_TAG
|
||||
'label' => 1,
|
||||
'legend' => 1,
|
||||
'li' => 1,
|
||||
'link' => 9, // NORMAL | VOID_TAG
|
||||
'map' => 1,
|
||||
'mark' => 1,
|
||||
'menu' => 17, // NORMAL | AUTOCLOSE_P,
|
||||
'meta' => 9, // NORMAL | VOID_TAG
|
||||
'meter' => 1,
|
||||
'nav' => 17, // NORMAL | AUTOCLOSE_P,
|
||||
'noscript' => 65, // NORMAL | BLOCK_TAG
|
||||
'object' => 1,
|
||||
'ol' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'optgroup' => 1,
|
||||
'option' => 1,
|
||||
'output' => 65, // NORMAL | BLOCK_TAG
|
||||
'p' => 209, // NORMAL | AUTOCLOSE_P | BLOCK_TAG | BLOCK_ONLY_INLINE
|
||||
'param' => 9, // NORMAL | VOID_TAG
|
||||
'pre' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'progress' => 1,
|
||||
'q' => 1,
|
||||
'rp' => 1,
|
||||
'rt' => 1,
|
||||
'ruby' => 1,
|
||||
's' => 1,
|
||||
'samp' => 1,
|
||||
'script' => 3, // NORMAL | TEXT_RAW
|
||||
'section' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'select' => 1,
|
||||
'small' => 1,
|
||||
'source' => 9, // NORMAL | VOID_TAG
|
||||
'span' => 1,
|
||||
'strong' => 1,
|
||||
'style' => 3, // NORMAL | TEXT_RAW
|
||||
'sub' => 1,
|
||||
'summary' => 17, // NORMAL | AUTOCLOSE_P,
|
||||
'sup' => 1,
|
||||
'table' => 65, // NORMAL | BLOCK_TAG
|
||||
'tbody' => 1,
|
||||
'td' => 1,
|
||||
'textarea' => 5, // NORMAL | TEXT_RCDATA
|
||||
'tfoot' => 65, // NORMAL | BLOCK_TAG
|
||||
'th' => 1,
|
||||
'thead' => 1,
|
||||
'time' => 1,
|
||||
'title' => 5, // NORMAL | TEXT_RCDATA
|
||||
'tr' => 1,
|
||||
'track' => 9, // NORMAL | VOID_TAG
|
||||
'u' => 1,
|
||||
'ul' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
|
||||
'var' => 1,
|
||||
'video' => 1,
|
||||
'wbr' => 9, // NORMAL | VOID_TAG
|
||||
|
||||
// Legacy?
|
||||
'basefont' => 8, // VOID_TAG
|
||||
'bgsound' => 8, // VOID_TAG
|
||||
'noframes' => 2, // RAW_TEXT
|
||||
'frame' => 9, // NORMAL | VOID_TAG
|
||||
'frameset' => 1,
|
||||
'center' => 16,
|
||||
'dir' => 16,
|
||||
'listing' => 16, // AUTOCLOSE_P
|
||||
'plaintext' => 48, // AUTOCLOSE_P | TEXT_PLAINTEXT
|
||||
'applet' => 0,
|
||||
'marquee' => 0,
|
||||
'isindex' => 8, // VOID_TAG
|
||||
'xmp' => 20, // AUTOCLOSE_P | VOID_TAG | RAW_TEXT
|
||||
'noembed' => 2, // RAW_TEXT
|
||||
);
|
||||
|
||||
/**
|
||||
* The MathML elements.
|
||||
* See http://www.w3.org/wiki/MathML/Elements.
|
||||
*
|
||||
* In our case we are only concerned with presentation MathML and not content
|
||||
* MathML. There is a nice list of this subset at https://developer.mozilla.org/en-US/docs/MathML/Element.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $mathml = array(
|
||||
'maction' => 1,
|
||||
'maligngroup' => 1,
|
||||
'malignmark' => 1,
|
||||
'math' => 1,
|
||||
'menclose' => 1,
|
||||
'merror' => 1,
|
||||
'mfenced' => 1,
|
||||
'mfrac' => 1,
|
||||
'mglyph' => 1,
|
||||
'mi' => 1,
|
||||
'mlabeledtr' => 1,
|
||||
'mlongdiv' => 1,
|
||||
'mmultiscripts' => 1,
|
||||
'mn' => 1,
|
||||
'mo' => 1,
|
||||
'mover' => 1,
|
||||
'mpadded' => 1,
|
||||
'mphantom' => 1,
|
||||
'mroot' => 1,
|
||||
'mrow' => 1,
|
||||
'ms' => 1,
|
||||
'mscarries' => 1,
|
||||
'mscarry' => 1,
|
||||
'msgroup' => 1,
|
||||
'msline' => 1,
|
||||
'mspace' => 1,
|
||||
'msqrt' => 1,
|
||||
'msrow' => 1,
|
||||
'mstack' => 1,
|
||||
'mstyle' => 1,
|
||||
'msub' => 1,
|
||||
'msup' => 1,
|
||||
'msubsup' => 1,
|
||||
'mtable' => 1,
|
||||
'mtd' => 1,
|
||||
'mtext' => 1,
|
||||
'mtr' => 1,
|
||||
'munder' => 1,
|
||||
'munderover' => 1,
|
||||
);
|
||||
|
||||
/**
|
||||
* The svg elements.
|
||||
*
|
||||
* The Mozilla documentation has a good list at https://developer.mozilla.org/en-US/docs/SVG/Element.
|
||||
* The w3c list appears to be lacking in some areas like filter effect elements.
|
||||
* That list can be found at http://www.w3.org/wiki/SVG/Elements.
|
||||
*
|
||||
* Note, FireFox appears to do a better job rendering filter effects than chrome.
|
||||
* While they are in the spec I'm not sure how widely implemented they are.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $svg = array(
|
||||
'a' => 1,
|
||||
'altGlyph' => 1,
|
||||
'altGlyphDef' => 1,
|
||||
'altGlyphItem' => 1,
|
||||
'animate' => 1,
|
||||
'animateColor' => 1,
|
||||
'animateMotion' => 1,
|
||||
'animateTransform' => 1,
|
||||
'circle' => 1,
|
||||
'clipPath' => 1,
|
||||
'color-profile' => 1,
|
||||
'cursor' => 1,
|
||||
'defs' => 1,
|
||||
'desc' => 1,
|
||||
'ellipse' => 1,
|
||||
'feBlend' => 1,
|
||||
'feColorMatrix' => 1,
|
||||
'feComponentTransfer' => 1,
|
||||
'feComposite' => 1,
|
||||
'feConvolveMatrix' => 1,
|
||||
'feDiffuseLighting' => 1,
|
||||
'feDisplacementMap' => 1,
|
||||
'feDistantLight' => 1,
|
||||
'feFlood' => 1,
|
||||
'feFuncA' => 1,
|
||||
'feFuncB' => 1,
|
||||
'feFuncG' => 1,
|
||||
'feFuncR' => 1,
|
||||
'feGaussianBlur' => 1,
|
||||
'feImage' => 1,
|
||||
'feMerge' => 1,
|
||||
'feMergeNode' => 1,
|
||||
'feMorphology' => 1,
|
||||
'feOffset' => 1,
|
||||
'fePointLight' => 1,
|
||||
'feSpecularLighting' => 1,
|
||||
'feSpotLight' => 1,
|
||||
'feTile' => 1,
|
||||
'feTurbulence' => 1,
|
||||
'filter' => 1,
|
||||
'font' => 1,
|
||||
'font-face' => 1,
|
||||
'font-face-format' => 1,
|
||||
'font-face-name' => 1,
|
||||
'font-face-src' => 1,
|
||||
'font-face-uri' => 1,
|
||||
'foreignObject' => 1,
|
||||
'g' => 1,
|
||||
'glyph' => 1,
|
||||
'glyphRef' => 1,
|
||||
'hkern' => 1,
|
||||
'image' => 1,
|
||||
'line' => 1,
|
||||
'linearGradient' => 1,
|
||||
'marker' => 1,
|
||||
'mask' => 1,
|
||||
'metadata' => 1,
|
||||
'missing-glyph' => 1,
|
||||
'mpath' => 1,
|
||||
'path' => 1,
|
||||
'pattern' => 1,
|
||||
'polygon' => 1,
|
||||
'polyline' => 1,
|
||||
'radialGradient' => 1,
|
||||
'rect' => 1,
|
||||
'script' => 3, // NORMAL | RAW_TEXT
|
||||
'set' => 1,
|
||||
'stop' => 1,
|
||||
'style' => 3, // NORMAL | RAW_TEXT
|
||||
'svg' => 1,
|
||||
'switch' => 1,
|
||||
'symbol' => 1,
|
||||
'text' => 1,
|
||||
'textPath' => 1,
|
||||
'title' => 1,
|
||||
'tref' => 1,
|
||||
'tspan' => 1,
|
||||
'use' => 1,
|
||||
'view' => 1,
|
||||
'vkern' => 1,
|
||||
);
|
||||
|
||||
/**
|
||||
* Some attributes in SVG are case sensitive.
|
||||
*
|
||||
* This map contains key/value pairs with the key as the lowercase attribute
|
||||
* name and the value with the correct casing.
|
||||
*/
|
||||
public static $svgCaseSensitiveAttributeMap = array(
|
||||
'attributename' => 'attributeName',
|
||||
'attributetype' => 'attributeType',
|
||||
'basefrequency' => 'baseFrequency',
|
||||
'baseprofile' => 'baseProfile',
|
||||
'calcmode' => 'calcMode',
|
||||
'clippathunits' => 'clipPathUnits',
|
||||
'contentscripttype' => 'contentScriptType',
|
||||
'contentstyletype' => 'contentStyleType',
|
||||
'diffuseconstant' => 'diffuseConstant',
|
||||
'edgemode' => 'edgeMode',
|
||||
'externalresourcesrequired' => 'externalResourcesRequired',
|
||||
'filterres' => 'filterRes',
|
||||
'filterunits' => 'filterUnits',
|
||||
'glyphref' => 'glyphRef',
|
||||
'gradienttransform' => 'gradientTransform',
|
||||
'gradientunits' => 'gradientUnits',
|
||||
'kernelmatrix' => 'kernelMatrix',
|
||||
'kernelunitlength' => 'kernelUnitLength',
|
||||
'keypoints' => 'keyPoints',
|
||||
'keysplines' => 'keySplines',
|
||||
'keytimes' => 'keyTimes',
|
||||
'lengthadjust' => 'lengthAdjust',
|
||||
'limitingconeangle' => 'limitingConeAngle',
|
||||
'markerheight' => 'markerHeight',
|
||||
'markerunits' => 'markerUnits',
|
||||
'markerwidth' => 'markerWidth',
|
||||
'maskcontentunits' => 'maskContentUnits',
|
||||
'maskunits' => 'maskUnits',
|
||||
'numoctaves' => 'numOctaves',
|
||||
'pathlength' => 'pathLength',
|
||||
'patterncontentunits' => 'patternContentUnits',
|
||||
'patterntransform' => 'patternTransform',
|
||||
'patternunits' => 'patternUnits',
|
||||
'pointsatx' => 'pointsAtX',
|
||||
'pointsaty' => 'pointsAtY',
|
||||
'pointsatz' => 'pointsAtZ',
|
||||
'preservealpha' => 'preserveAlpha',
|
||||
'preserveaspectratio' => 'preserveAspectRatio',
|
||||
'primitiveunits' => 'primitiveUnits',
|
||||
'refx' => 'refX',
|
||||
'refy' => 'refY',
|
||||
'repeatcount' => 'repeatCount',
|
||||
'repeatdur' => 'repeatDur',
|
||||
'requiredextensions' => 'requiredExtensions',
|
||||
'requiredfeatures' => 'requiredFeatures',
|
||||
'specularconstant' => 'specularConstant',
|
||||
'specularexponent' => 'specularExponent',
|
||||
'spreadmethod' => 'spreadMethod',
|
||||
'startoffset' => 'startOffset',
|
||||
'stddeviation' => 'stdDeviation',
|
||||
'stitchtiles' => 'stitchTiles',
|
||||
'surfacescale' => 'surfaceScale',
|
||||
'systemlanguage' => 'systemLanguage',
|
||||
'tablevalues' => 'tableValues',
|
||||
'targetx' => 'targetX',
|
||||
'targety' => 'targetY',
|
||||
'textlength' => 'textLength',
|
||||
'viewbox' => 'viewBox',
|
||||
'viewtarget' => 'viewTarget',
|
||||
'xchannelselector' => 'xChannelSelector',
|
||||
'ychannelselector' => 'yChannelSelector',
|
||||
'zoomandpan' => 'zoomAndPan',
|
||||
);
|
||||
|
||||
/**
|
||||
* Some SVG elements are case sensitive.
|
||||
* This map contains these.
|
||||
*
|
||||
* The map contains key/value store of the name is lowercase as the keys and
|
||||
* the correct casing as the value.
|
||||
*/
|
||||
public static $svgCaseSensitiveElementMap = array(
|
||||
'altglyph' => 'altGlyph',
|
||||
'altglyphdef' => 'altGlyphDef',
|
||||
'altglyphitem' => 'altGlyphItem',
|
||||
'animatecolor' => 'animateColor',
|
||||
'animatemotion' => 'animateMotion',
|
||||
'animatetransform' => 'animateTransform',
|
||||
'clippath' => 'clipPath',
|
||||
'feblend' => 'feBlend',
|
||||
'fecolormatrix' => 'feColorMatrix',
|
||||
'fecomponenttransfer' => 'feComponentTransfer',
|
||||
'fecomposite' => 'feComposite',
|
||||
'feconvolvematrix' => 'feConvolveMatrix',
|
||||
'fediffuselighting' => 'feDiffuseLighting',
|
||||
'fedisplacementmap' => 'feDisplacementMap',
|
||||
'fedistantlight' => 'feDistantLight',
|
||||
'feflood' => 'feFlood',
|
||||
'fefunca' => 'feFuncA',
|
||||
'fefuncb' => 'feFuncB',
|
||||
'fefuncg' => 'feFuncG',
|
||||
'fefuncr' => 'feFuncR',
|
||||
'fegaussianblur' => 'feGaussianBlur',
|
||||
'feimage' => 'feImage',
|
||||
'femerge' => 'feMerge',
|
||||
'femergenode' => 'feMergeNode',
|
||||
'femorphology' => 'feMorphology',
|
||||
'feoffset' => 'feOffset',
|
||||
'fepointlight' => 'fePointLight',
|
||||
'fespecularlighting' => 'feSpecularLighting',
|
||||
'fespotlight' => 'feSpotLight',
|
||||
'fetile' => 'feTile',
|
||||
'feturbulence' => 'feTurbulence',
|
||||
'foreignobject' => 'foreignObject',
|
||||
'glyphref' => 'glyphRef',
|
||||
'lineargradient' => 'linearGradient',
|
||||
'radialgradient' => 'radialGradient',
|
||||
'textpath' => 'textPath',
|
||||
);
|
||||
|
||||
/**
|
||||
* Check whether the given element meets the given criterion.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* Elements::isA('script', Elements::TEXT_RAW); // Returns true.
|
||||
*
|
||||
* Elements::isA('script', Elements::TEXT_RCDATA); // Returns false.
|
||||
*
|
||||
* @param string $name The element name.
|
||||
* @param int $mask One of the constants on this class.
|
||||
*
|
||||
* @return bool true if the element matches the mask, false otherwise.
|
||||
*/
|
||||
public static function isA($name, $mask)
|
||||
{
|
||||
return (static::element($name) & $mask) === $mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if an element is a valid html5 element.
|
||||
*
|
||||
* @param string $name The name of the element.
|
||||
*
|
||||
* @return bool true if a html5 element and false otherwise.
|
||||
*/
|
||||
public static function isHtml5Element($name)
|
||||
{
|
||||
// html5 element names are case insensitive. Forcing lowercase for the check.
|
||||
// Do we need this check or will all data passed here already be lowercase?
|
||||
return isset(static::$html5[strtolower($name)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if an element name is a valid MathML presentation element.
|
||||
*
|
||||
* @param string $name The name of the element.
|
||||
*
|
||||
* @return bool true if a MathML name and false otherwise.
|
||||
*/
|
||||
public static function isMathMLElement($name)
|
||||
{
|
||||
// MathML is case-sensitive unlike html5 elements.
|
||||
return isset(static::$mathml[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if an element is a valid SVG element.
|
||||
*
|
||||
* @param string $name The name of the element.
|
||||
*
|
||||
* @return bool true if a SVG element and false otherise.
|
||||
*/
|
||||
public static function isSvgElement($name)
|
||||
{
|
||||
// SVG is case-sensitive unlike html5 elements.
|
||||
return isset(static::$svg[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is an element name valid in an html5 document.
|
||||
* This includes html5 elements along with other allowed embedded content
|
||||
* such as svg and mathml.
|
||||
*
|
||||
* @param string $name The name of the element.
|
||||
*
|
||||
* @return bool true if valid and false otherwise.
|
||||
*/
|
||||
public static function isElement($name)
|
||||
{
|
||||
return static::isHtml5Element($name) || static::isMathMLElement($name) || static::isSvgElement($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element mask for the given element name.
|
||||
*
|
||||
* @param string $name The name of the element.
|
||||
*
|
||||
* @return int the element mask.
|
||||
*/
|
||||
public static function element($name)
|
||||
{
|
||||
if (isset(static::$html5[$name])) {
|
||||
return static::$html5[$name];
|
||||
}
|
||||
if (isset(static::$svg[$name])) {
|
||||
return static::$svg[$name];
|
||||
}
|
||||
if (isset(static::$mathml[$name])) {
|
||||
return static::$mathml[$name];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a SVG element name to its proper case and form.
|
||||
*
|
||||
* @param string $name The name of the element.
|
||||
*
|
||||
* @return string the normalized form of the element name.
|
||||
*/
|
||||
public static function normalizeSvgElement($name)
|
||||
{
|
||||
$name = strtolower($name);
|
||||
if (isset(static::$svgCaseSensitiveElementMap[$name])) {
|
||||
$name = static::$svgCaseSensitiveElementMap[$name];
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a SVG attribute name to its proper case and form.
|
||||
*
|
||||
* @param string $name The name of the attribute.
|
||||
*
|
||||
* @return string The normalized form of the attribute name.
|
||||
*/
|
||||
public static function normalizeSvgAttribute($name)
|
||||
{
|
||||
$name = strtolower($name);
|
||||
if (isset(static::$svgCaseSensitiveAttributeMap[$name])) {
|
||||
$name = static::$svgCaseSensitiveAttributeMap[$name];
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a MathML attribute name to its proper case and form.
|
||||
* Note, all MathML element names are lowercase.
|
||||
*
|
||||
* @param string $name The name of the attribute.
|
||||
*
|
||||
* @return string The normalized form of the attribute name.
|
||||
*/
|
||||
public static function normalizeMathMlAttribute($name)
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
// Only one attribute has a mixed case form for MathML.
|
||||
if ('definitionurl' === $name) {
|
||||
$name = 'definitionURL';
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Masterminds\HTML5;
|
||||
|
||||
/**
|
||||
* The base exception for the HTML5 project.
|
||||
*/
|
||||
class Exception extends \Exception
|
||||
{
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* A handler for processor instructions.
|
||||
*/
|
||||
|
||||
namespace Masterminds\HTML5;
|
||||
|
||||
/**
|
||||
* Provide an processor to handle embedded instructions.
|
||||
*
|
||||
* XML defines a mechanism for inserting instructions (like PHP) into a
|
||||
* document. These are called "Processor Instructions." The HTML5 parser
|
||||
* provides an opportunity to handle these processor instructions during
|
||||
* the tree-building phase (before the DOM is constructed), which makes
|
||||
* it possible to alter the document as it is being created.
|
||||
*
|
||||
* One could, for example, use this mechanism to execute well-formed PHP
|
||||
* code embedded inside of an HTML5 document.
|
||||
*/
|
||||
interface InstructionProcessor
|
||||
{
|
||||
/**
|
||||
* Process an individual processing instruction.
|
||||
*
|
||||
* The process() function is responsible for doing the following:
|
||||
* - Determining whether $name is an instruction type it can handle.
|
||||
* - Determining what to do with the data passed in.
|
||||
* - Making any subsequent modifications to the DOM by modifying the
|
||||
* DOMElement or its attached DOM tree.
|
||||
*
|
||||
* @param \DOMElement $element The parent element for the current processing instruction.
|
||||
* @param string $name The instruction's name. E.g. `<?php` has the name `php`.
|
||||
* @param string $data All of the data between the opening and closing PI marks.
|
||||
*
|
||||
* @return \DOMElement The element that should be considered "Current". This may just be
|
||||
* the element passed in, but if the processor added more elements,
|
||||
* it may choose to reset the current element to one of the elements
|
||||
* it created. (When in doubt, return the element passed in.)
|
||||
*/
|
||||
public function process(\DOMElement $element, $name, $data);
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Masterminds\HTML5\Parser;
|
||||
|
||||
use Masterminds\HTML5\Entities;
|
||||
|
||||
/**
|
||||
* Manage entity references.
|
||||
*
|
||||
* This is a simple resolver for HTML5 character reference entitites. See Entities for the list of supported entities.
|
||||
*/
|
||||
class CharacterReference
|
||||
{
|
||||
protected static $numeric_mask = array(
|
||||
0x0,
|
||||
0x2FFFF,
|
||||
0,
|
||||
0xFFFF,
|
||||
);
|
||||
|
||||
/**
|
||||
* Given a name (e.g. 'amp'), lookup the UTF-8 character ('&').
|
||||
*
|
||||
* @param string $name The name to look up.
|
||||
*
|
||||
* @return string The character sequence. In UTF-8 this may be more than one byte.
|
||||
*/
|
||||
public static function lookupName($name)
|
||||
{
|
||||
// Do we really want to return NULL here? or FFFD
|
||||
return isset(Entities::$byName[$name]) ? Entities::$byName[$name] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a decimal number, return the UTF-8 character.
|
||||
*
|
||||
* @param $int
|
||||
*
|
||||
* @return false|string|string[]|null
|
||||
*/
|
||||
public static function lookupDecimal($int)
|
||||
{
|
||||
$entity = '&#' . $int . ';';
|
||||
|
||||
// UNTESTED: This may fail on some planes. Couldn't find full documentation
|
||||
// on the value of the mask array.
|
||||
return mb_decode_numericentity($entity, static::$numeric_mask, 'utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a hexadecimal number, return the UTF-8 character.
|
||||
*
|
||||
* @param $hexdec
|
||||
*
|
||||
* @return false|string|string[]|null
|
||||
*/
|
||||
public static function lookupHex($hexdec)
|
||||
{
|
||||
return static::lookupDecimal(hexdec($hexdec));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,713 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Masterminds\HTML5\Parser;
|
||||
|
||||
use Masterminds\HTML5\Elements;
|
||||
use Masterminds\HTML5\InstructionProcessor;
|
||||
|
||||
/**
|
||||
* Create an HTML5 DOM tree from events.
|
||||
*
|
||||
* This attempts to create a DOM from events emitted by a parser. This
|
||||
* attempts (but does not guarantee) to up-convert older HTML documents
|
||||
* to HTML5. It does this by applying HTML5's rules, but it will not
|
||||
* change the architecture of the document itself.
|
||||
*
|
||||
* Many of the error correction and quirks features suggested in the specification
|
||||
* are implemented herein; however, not all of them are. Since we do not
|
||||
* assume a graphical user agent, no presentation-specific logic is conducted
|
||||
* during tree building.
|
||||
*
|
||||
* FIXME: The present tree builder does not exactly follow the state machine rules
|
||||
* for insert modes as outlined in the HTML5 spec. The processor needs to be
|
||||
* re-written to accomodate this. See, for example, the Go language HTML5
|
||||
* parser.
|
||||
*/
|
||||
class DOMTreeBuilder implements EventHandler
|
||||
{
|
||||
/**
|
||||
* Defined in http://www.w3.org/TR/html51/infrastructure.html#html-namespace-0.
|
||||
*/
|
||||
const NAMESPACE_HTML = 'http://www.w3.org/1999/xhtml';
|
||||
|
||||
const NAMESPACE_MATHML = 'http://www.w3.org/1998/Math/MathML';
|
||||
|
||||
const NAMESPACE_SVG = 'http://www.w3.org/2000/svg';
|
||||
|
||||
const NAMESPACE_XLINK = 'http://www.w3.org/1999/xlink';
|
||||
|
||||
const NAMESPACE_XML = 'http://www.w3.org/XML/1998/namespace';
|
||||
|
||||
const NAMESPACE_XMLNS = 'http://www.w3.org/2000/xmlns/';
|
||||
|
||||
const OPT_DISABLE_HTML_NS = 'disable_html_ns';
|
||||
|
||||
const OPT_TARGET_DOC = 'target_document';
|
||||
|
||||
const OPT_IMPLICIT_NS = 'implicit_namespaces';
|
||||
|
||||
/**
|
||||
* Holds the HTML5 element names that causes a namespace switch.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $nsRoots = array(
|
||||
'html' => self::NAMESPACE_HTML,
|
||||
'svg' => self::NAMESPACE_SVG,
|
||||
'math' => self::NAMESPACE_MATHML,
|
||||
);
|
||||
|
||||
/**
|
||||
* Holds the always available namespaces (which does not require the XMLNS declaration).
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $implicitNamespaces = array(
|
||||
'xml' => self::NAMESPACE_XML,
|
||||
'xmlns' => self::NAMESPACE_XMLNS,
|
||||
'xlink' => self::NAMESPACE_XLINK,
|
||||
);
|
||||
|
||||
/**
|
||||
* Holds a stack of currently active namespaces.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $nsStack = array();
|
||||
|
||||
/**
|
||||
* Holds the number of namespaces declared by a node.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $pushes = array();
|
||||
|
||||
/**
|
||||
* Defined in 8.2.5.
|
||||
*/
|
||||
const IM_INITIAL = 0;
|
||||
|
||||
const IM_BEFORE_HTML = 1;
|
||||
|
||||
const IM_BEFORE_HEAD = 2;
|
||||
|
||||
const IM_IN_HEAD = 3;
|
||||
|
||||
const IM_IN_HEAD_NOSCRIPT = 4;
|
||||
|
||||
const IM_AFTER_HEAD = 5;
|
||||
|
||||
const IM_IN_BODY = 6;
|
||||
|
||||
const IM_TEXT = 7;
|
||||
|
||||
const IM_IN_TABLE = 8;
|
||||
|
||||
const IM_IN_TABLE_TEXT = 9;
|
||||
|
||||
const IM_IN_CAPTION = 10;
|
||||
|
||||
const IM_IN_COLUMN_GROUP = 11;
|
||||
|
||||
const IM_IN_TABLE_BODY = 12;
|
||||
|
||||
const IM_IN_ROW = 13;
|
||||
|
||||
const IM_IN_CELL = 14;
|
||||
|
||||
const IM_IN_SELECT = 15;
|
||||
|
||||
const IM_IN_SELECT_IN_TABLE = 16;
|
||||
|
||||
const IM_AFTER_BODY = 17;
|
||||
|
||||
const IM_IN_FRAMESET = 18;
|
||||
|
||||
const IM_AFTER_FRAMESET = 19;
|
||||
|
||||
const IM_AFTER_AFTER_BODY = 20;
|
||||
|
||||
const IM_AFTER_AFTER_FRAMESET = 21;
|
||||
|
||||
const IM_IN_SVG = 22;
|
||||
|
||||
const IM_IN_MATHML = 23;
|
||||
|
||||
protected $options = array();
|
||||
|
||||
protected $stack = array();
|
||||
|
||||
protected $current; // Pointer in the tag hierarchy.
|
||||
protected $rules;
|
||||
protected $doc;
|
||||
|
||||
protected $frag;
|
||||
|
||||
protected $processor;
|
||||
|
||||
protected $insertMode = 0;
|
||||
|
||||
/**
|
||||
* Track if we are in an element that allows only inline child nodes.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $onlyInline;
|
||||
|
||||
/**
|
||||
* Quirks mode is enabled by default.
|
||||
* Any document that is missing the DT will be considered to be in quirks mode.
|
||||
*/
|
||||
protected $quirks = true;
|
||||
|
||||
protected $errors = array();
|
||||
|
||||
public function __construct($isFragment = false, array $options = array())
|
||||
{
|
||||
$this->options = $options;
|
||||
|
||||
if (isset($options[self::OPT_TARGET_DOC])) {
|
||||
$this->doc = $options[self::OPT_TARGET_DOC];
|
||||
} else {
|
||||
$impl = new \DOMImplementation();
|
||||
// XXX:
|
||||
// Create the doctype. For now, we are always creating HTML5
|
||||
// documents, and attempting to up-convert any older DTDs to HTML5.
|
||||
$dt = $impl->createDocumentType('html');
|
||||
// $this->doc = \DOMImplementation::createDocument(NULL, 'html', $dt);
|
||||
$this->doc = $impl->createDocument(null, '', $dt);
|
||||
$this->doc->encoding = !empty($options['encoding']) ? $options['encoding'] : 'UTF-8';
|
||||
}
|
||||
|
||||
$this->errors = array();
|
||||
|
||||
$this->current = $this->doc; // ->documentElement;
|
||||
|
||||
// Create a rules engine for tags.
|
||||
$this->rules = new TreeBuildingRules();
|
||||
|
||||
$implicitNS = array();
|
||||
if (isset($this->options[self::OPT_IMPLICIT_NS])) {
|
||||
$implicitNS = $this->options[self::OPT_IMPLICIT_NS];
|
||||
} elseif (isset($this->options['implicitNamespaces'])) {
|
||||
$implicitNS = $this->options['implicitNamespaces'];
|
||||
}
|
||||
|
||||
// Fill $nsStack with the defalut HTML5 namespaces, plus the "implicitNamespaces" array taken form $options
|
||||
array_unshift($this->nsStack, $implicitNS + array('' => self::NAMESPACE_HTML) + $this->implicitNamespaces);
|
||||
|
||||
if ($isFragment) {
|
||||
$this->insertMode = static::IM_IN_BODY;
|
||||
$this->frag = $this->doc->createDocumentFragment();
|
||||
$this->current = $this->frag;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the document.
|
||||
*/
|
||||
public function document()
|
||||
{
|
||||
return $this->doc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DOM fragment for the body.
|
||||
*
|
||||
* This returns a DOMNodeList because a fragment may have zero or more
|
||||
* DOMNodes at its root.
|
||||
*
|
||||
* @see http://www.w3.org/TR/2012/CR-html5-20121217/syntax.html#concept-frag-parse-context
|
||||
*
|
||||
* @return \DOMDocumentFragment
|
||||
*/
|
||||
public function fragment()
|
||||
{
|
||||
return $this->frag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide an instruction processor.
|
||||
*
|
||||
* This is used for handling Processor Instructions as they are
|
||||
* inserted. If omitted, PI's are inserted directly into the DOM tree.
|
||||
*/
|
||||
public function setInstructionProcessor(InstructionProcessor $proc)
|
||||
{
|
||||
$this->processor = $proc;
|
||||
}
|
||||
|
||||
public function doctype($name, $idType = 0, $id = null, $quirks = false)
|
||||
{
|
||||
// This is used solely for setting quirks mode. Currently we don't
|
||||
// try to preserve the inbound DT. We convert it to HTML5.
|
||||
$this->quirks = $quirks;
|
||||
|
||||
if ($this->insertMode > static::IM_INITIAL) {
|
||||
$this->parseError('Illegal placement of DOCTYPE tag. Ignoring: ' . $name);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->insertMode = static::IM_BEFORE_HTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the start tag.
|
||||
*
|
||||
* @todo - XMLNS namespace handling (we need to parse, even if it's not valid)
|
||||
* - XLink, MathML and SVG namespace handling
|
||||
* - Omission rules: 8.1.2.4 Optional tags
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $attributes
|
||||
* @param bool $selfClosing
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function startTag($name, $attributes = array(), $selfClosing = false)
|
||||
{
|
||||
$lname = $this->normalizeTagName($name);
|
||||
|
||||
// Make sure we have an html element.
|
||||
if (!$this->doc->documentElement && 'html' !== $name && !$this->frag) {
|
||||
$this->startTag('html');
|
||||
}
|
||||
|
||||
// Set quirks mode if we're at IM_INITIAL with no doctype.
|
||||
if ($this->insertMode === static::IM_INITIAL) {
|
||||
$this->quirks = true;
|
||||
$this->parseError('No DOCTYPE specified.');
|
||||
}
|
||||
|
||||
// SPECIAL TAG HANDLING:
|
||||
// Spec says do this, and "don't ask."
|
||||
// find the spec where this is defined... looks problematic
|
||||
if ('image' === $name && !($this->insertMode === static::IM_IN_SVG || $this->insertMode === static::IM_IN_MATHML)) {
|
||||
$name = 'img';
|
||||
}
|
||||
|
||||
// Autoclose p tags where appropriate.
|
||||
if ($this->insertMode >= static::IM_IN_BODY && Elements::isA($name, Elements::AUTOCLOSE_P)) {
|
||||
$this->autoclose('p');
|
||||
}
|
||||
|
||||
// Set insert mode:
|
||||
switch ($name) {
|
||||
case 'html':
|
||||
$this->insertMode = static::IM_BEFORE_HEAD;
|
||||
break;
|
||||
case 'head':
|
||||
if ($this->insertMode > static::IM_BEFORE_HEAD) {
|
||||
$this->parseError('Unexpected head tag outside of head context.');
|
||||
} else {
|
||||
$this->insertMode = static::IM_IN_HEAD;
|
||||
}
|
||||
break;
|
||||
case 'body':
|
||||
$this->insertMode = static::IM_IN_BODY;
|
||||
break;
|
||||
case 'svg':
|
||||
$this->insertMode = static::IM_IN_SVG;
|
||||
break;
|
||||
case 'math':
|
||||
$this->insertMode = static::IM_IN_MATHML;
|
||||
break;
|
||||
case 'noscript':
|
||||
if ($this->insertMode === static::IM_IN_HEAD) {
|
||||
$this->insertMode = static::IM_IN_HEAD_NOSCRIPT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Special case handling for SVG.
|
||||
if ($this->insertMode === static::IM_IN_SVG) {
|
||||
$lname = Elements::normalizeSvgElement($lname);
|
||||
}
|
||||
|
||||
$pushes = 0;
|
||||
// when we found a tag thats appears inside $nsRoots, we have to switch the defalut namespace
|
||||
if (isset($this->nsRoots[$lname]) && $this->nsStack[0][''] !== $this->nsRoots[$lname]) {
|
||||
array_unshift($this->nsStack, array(
|
||||
'' => $this->nsRoots[$lname],
|
||||
) + $this->nsStack[0]);
|
||||
++$pushes;
|
||||
}
|
||||
$needsWorkaround = false;
|
||||
if (isset($this->options['xmlNamespaces']) && $this->options['xmlNamespaces']) {
|
||||
// when xmlNamespaces is true a and we found a 'xmlns' or 'xmlns:*' attribute, we should add a new item to the $nsStack
|
||||
foreach ($attributes as $aName => $aVal) {
|
||||
if ('xmlns' === $aName) {
|
||||
$needsWorkaround = $aVal;
|
||||
array_unshift($this->nsStack, array(
|
||||
'' => $aVal,
|
||||
) + $this->nsStack[0]);
|
||||
++$pushes;
|
||||
} elseif ('xmlns' === (($pos = strpos($aName, ':')) ? substr($aName, 0, $pos) : '')) {
|
||||
array_unshift($this->nsStack, array(
|
||||
substr($aName, $pos + 1) => $aVal,
|
||||
) + $this->nsStack[0]);
|
||||
++$pushes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->onlyInline && Elements::isA($lname, Elements::BLOCK_TAG)) {
|
||||
$this->autoclose($this->onlyInline);
|
||||
$this->onlyInline = null;
|
||||
}
|
||||
|
||||
// some elements as table related tags might have optional end tags that force us to auto close multiple tags
|
||||
// https://www.w3.org/TR/html401/struct/tables.html
|
||||
if ($this->current instanceof \DOMElement && isset(Elements::$optionalEndElementsParentsToClose[$lname])) {
|
||||
foreach (Elements::$optionalEndElementsParentsToClose[$lname] as $parentElName) {
|
||||
if ($this->current instanceof \DOMElement && $this->current->tagName === $parentElName) {
|
||||
$this->autoclose($parentElName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$prefix = ($pos = strpos($lname, ':')) ? substr($lname, 0, $pos) : '';
|
||||
|
||||
if (false !== $needsWorkaround) {
|
||||
$xml = "<$lname xmlns=\"$needsWorkaround\" " . (strlen($prefix) && isset($this->nsStack[0][$prefix]) ? ("xmlns:$prefix=\"" . $this->nsStack[0][$prefix] . '"') : '') . '/>';
|
||||
|
||||
$frag = new \DOMDocument('1.0', 'UTF-8');
|
||||
$frag->loadXML($xml);
|
||||
|
||||
$ele = $this->doc->importNode($frag->documentElement, true);
|
||||
} else {
|
||||
if (!isset($this->nsStack[0][$prefix]) || ('' === $prefix && isset($this->options[self::OPT_DISABLE_HTML_NS]) && $this->options[self::OPT_DISABLE_HTML_NS])) {
|
||||
$ele = $this->doc->createElement($lname);
|
||||
} else {
|
||||
$ele = $this->doc->createElementNS($this->nsStack[0][$prefix], $lname);
|
||||
}
|
||||
}
|
||||
} catch (\DOMException $e) {
|
||||
$this->parseError("Illegal tag name: <$lname>. Replaced with <invalid>.");
|
||||
$ele = $this->doc->createElement('invalid');
|
||||
}
|
||||
|
||||
if (Elements::isA($lname, Elements::BLOCK_ONLY_INLINE)) {
|
||||
$this->onlyInline = $lname;
|
||||
}
|
||||
|
||||
// When we add some namespacess, we have to track them. Later, when "endElement" is invoked, we have to remove them.
|
||||
// When we are on a void tag, we do not need to care about namesapce nesting.
|
||||
if ($pushes > 0 && !Elements::isA($name, Elements::VOID_TAG)) {
|
||||
// PHP tends to free the memory used by DOM,
|
||||
// to avoid spl_object_hash collisions whe have to avoid garbage collection of $ele storing it into $pushes
|
||||
// see https://bugs.php.net/bug.php?id=67459
|
||||
$this->pushes[spl_object_hash($ele)] = array($pushes, $ele);
|
||||
}
|
||||
|
||||
foreach ($attributes as $aName => $aVal) {
|
||||
// xmlns attributes can't be set
|
||||
if ('xmlns' === $aName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->insertMode === static::IM_IN_SVG) {
|
||||
$aName = Elements::normalizeSvgAttribute($aName);
|
||||
} elseif ($this->insertMode === static::IM_IN_MATHML) {
|
||||
$aName = Elements::normalizeMathMlAttribute($aName);
|
||||
}
|
||||
|
||||
$aVal = (string) $aVal;
|
||||
|
||||
try {
|
||||
$prefix = ($pos = strpos($aName, ':')) ? substr($aName, 0, $pos) : false;
|
||||
|
||||
if ('xmlns' === $prefix) {
|
||||
$ele->setAttributeNS(self::NAMESPACE_XMLNS, $aName, $aVal);
|
||||
} elseif (false !== $prefix && isset($this->nsStack[0][$prefix])) {
|
||||
$ele->setAttributeNS($this->nsStack[0][$prefix], $aName, $aVal);
|
||||
} else {
|
||||
$ele->setAttribute($aName, $aVal);
|
||||
}
|
||||
} catch (\DOMException $e) {
|
||||
$this->parseError("Illegal attribute name for tag $name. Ignoring: $aName");
|
||||
continue;
|
||||
}
|
||||
|
||||
// This is necessary on a non-DTD schema, like HTML5.
|
||||
if ('id' === $aName) {
|
||||
$ele->setIdAttribute('id', true);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->frag !== $this->current && $this->rules->hasRules($name)) {
|
||||
// Some elements have special processing rules. Handle those separately.
|
||||
$this->current = $this->rules->evaluate($ele, $this->current);
|
||||
} else {
|
||||
// Otherwise, it's a standard element.
|
||||
$this->current->appendChild($ele);
|
||||
|
||||
if (!Elements::isA($name, Elements::VOID_TAG)) {
|
||||
$this->current = $ele;
|
||||
}
|
||||
|
||||
// Self-closing tags should only be respected on foreign elements
|
||||
// (and are implied on void elements)
|
||||
// See: https://www.w3.org/TR/html5/syntax.html#start-tags
|
||||
if (Elements::isHtml5Element($name)) {
|
||||
$selfClosing = false;
|
||||
}
|
||||
}
|
||||
|
||||
// This is sort of a last-ditch attempt to correct for cases where no head/body
|
||||
// elements are provided.
|
||||
if ($this->insertMode <= static::IM_BEFORE_HEAD && 'head' !== $name && 'html' !== $name) {
|
||||
$this->insertMode = static::IM_IN_BODY;
|
||||
}
|
||||
|
||||
// When we are on a void tag, we do not need to care about namesapce nesting,
|
||||
// but we have to remove the namespaces pushed to $nsStack.
|
||||
if ($pushes > 0 && Elements::isA($name, Elements::VOID_TAG)) {
|
||||
// remove the namespaced definded by current node
|
||||
for ($i = 0; $i < $pushes; ++$i) {
|
||||
array_shift($this->nsStack);
|
||||
}
|
||||
}
|
||||
|
||||
if ($selfClosing) {
|
||||
$this->endTag($name);
|
||||
}
|
||||
|
||||
// Return the element mask, which the tokenizer can then use to set
|
||||
// various processing rules.
|
||||
return Elements::element($name);
|
||||
}
|
||||
|
||||
public function endTag($name)
|
||||
{
|
||||
$lname = $this->normalizeTagName($name);
|
||||
|
||||
// Special case within 12.2.6.4.7: An end tag whose tag name is "br" should be treated as an opening tag
|
||||
if ('br' === $name) {
|
||||
$this->parseError('Closing tag encountered for void element br.');
|
||||
|
||||
$this->startTag('br');
|
||||
}
|
||||
// Ignore closing tags for other unary elements.
|
||||
elseif (Elements::isA($name, Elements::VOID_TAG)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->insertMode <= static::IM_BEFORE_HTML) {
|
||||
// 8.2.5.4.2
|
||||
if (in_array($name, array(
|
||||
'html',
|
||||
'br',
|
||||
'head',
|
||||
'title',
|
||||
))) {
|
||||
$this->startTag('html');
|
||||
$this->endTag($name);
|
||||
$this->insertMode = static::IM_BEFORE_HEAD;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore the tag.
|
||||
$this->parseError('Illegal closing tag at global scope.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Special case handling for SVG.
|
||||
if ($this->insertMode === static::IM_IN_SVG) {
|
||||
$lname = Elements::normalizeSvgElement($lname);
|
||||
}
|
||||
|
||||
$cid = spl_object_hash($this->current);
|
||||
|
||||
// XXX: HTML has no parent. What do we do, though,
|
||||
// if this element appears in the wrong place?
|
||||
if ('html' === $lname) {
|
||||
return;
|
||||
}
|
||||
|
||||
// remove the namespaced definded by current node
|
||||
if (isset($this->pushes[$cid])) {
|
||||
for ($i = 0; $i < $this->pushes[$cid][0]; ++$i) {
|
||||
array_shift($this->nsStack);
|
||||
}
|
||||
unset($this->pushes[$cid]);
|
||||
}
|
||||
|
||||
if (!$this->autoclose($lname)) {
|
||||
$this->parseError('Could not find closing tag for ' . $lname);
|
||||
}
|
||||
|
||||
switch ($lname) {
|
||||
case 'head':
|
||||
$this->insertMode = static::IM_AFTER_HEAD;
|
||||
break;
|
||||
case 'body':
|
||||
$this->insertMode = static::IM_AFTER_BODY;
|
||||
break;
|
||||
case 'svg':
|
||||
case 'mathml':
|
||||
$this->insertMode = static::IM_IN_BODY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function comment($cdata)
|
||||
{
|
||||
// TODO: Need to handle case where comment appears outside of the HTML tag.
|
||||
$node = $this->doc->createComment($cdata);
|
||||
$this->current->appendChild($node);
|
||||
}
|
||||
|
||||
public function text($data)
|
||||
{
|
||||
// XXX: Hmmm.... should we really be this strict?
|
||||
if ($this->insertMode < static::IM_IN_HEAD) {
|
||||
// Per '8.2.5.4.3 The "before head" insertion mode' the characters
|
||||
// " \t\n\r\f" should be ignored but no mention of a parse error. This is
|
||||
// practical as most documents contain these characters. Other text is not
|
||||
// expected here so recording a parse error is necessary.
|
||||
$dataTmp = trim($data, " \t\n\r\f");
|
||||
if (!empty($dataTmp)) {
|
||||
// fprintf(STDOUT, "Unexpected insert mode: %d", $this->insertMode);
|
||||
$this->parseError('Unexpected text. Ignoring: ' . $dataTmp);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
// fprintf(STDOUT, "Appending text %s.", $data);
|
||||
$node = $this->doc->createTextNode($data);
|
||||
$this->current->appendChild($node);
|
||||
}
|
||||
|
||||
public function eof()
|
||||
{
|
||||
// If the $current isn't the $root, do we need to do anything?
|
||||
}
|
||||
|
||||
public function parseError($msg, $line = 0, $col = 0)
|
||||
{
|
||||
$this->errors[] = sprintf('Line %d, Col %d: %s', $line, $col, $msg);
|
||||
}
|
||||
|
||||
public function getErrors()
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
public function cdata($data)
|
||||
{
|
||||
$node = $this->doc->createCDATASection($data);
|
||||
$this->current->appendChild($node);
|
||||
}
|
||||
|
||||
public function processingInstruction($name, $data = null)
|
||||
{
|
||||
// XXX: Ignore initial XML declaration, per the spec.
|
||||
if ($this->insertMode === static::IM_INITIAL && 'xml' === strtolower($name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Important: The processor may modify the current DOM tree however it sees fit.
|
||||
if ($this->processor instanceof InstructionProcessor) {
|
||||
$res = $this->processor->process($this->current, $name, $data);
|
||||
if (!empty($res)) {
|
||||
$this->current = $res;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, this is just a dumb PI element.
|
||||
$node = $this->doc->createProcessingInstruction($name, $data);
|
||||
|
||||
$this->current->appendChild($node);
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// UTILITIES
|
||||
// ==========================================================================
|
||||
|
||||
/**
|
||||
* Apply normalization rules to a tag name.
|
||||
* See sections 2.9 and 8.1.2.
|
||||
*
|
||||
* @param string $tagName
|
||||
*
|
||||
* @return string The normalized tag name.
|
||||
*/
|
||||
protected function normalizeTagName($tagName)
|
||||
{
|
||||
/*
|
||||
* Section 2.9 suggests that we should not do this. if (strpos($name, ':') !== false) { // We know from the grammar that there must be at least one other // char besides :, since : is not a legal tag start. $parts = explode(':', $name); return array_pop($parts); }
|
||||
*/
|
||||
return $tagName;
|
||||
}
|
||||
|
||||
protected function quirksTreeResolver($name)
|
||||
{
|
||||
throw new \Exception('Not implemented.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically climb the tree and close the closest node with the matching $tag.
|
||||
*
|
||||
* @param string $tagName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function autoclose($tagName)
|
||||
{
|
||||
$working = $this->current;
|
||||
do {
|
||||
if (XML_ELEMENT_NODE !== $working->nodeType) {
|
||||
return false;
|
||||
}
|
||||
if ($working->tagName === $tagName) {
|
||||
$this->current = $working->parentNode;
|
||||
|
||||
return true;
|
||||
}
|
||||
} while ($working = $working->parentNode);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given tagname is an ancestor of the present candidate.
|
||||
*
|
||||
* If $this->current or anything above $this->current matches the given tag
|
||||
* name, this returns true.
|
||||
*
|
||||
* @param string $tagName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isAncestor($tagName)
|
||||
{
|
||||
$candidate = $this->current;
|
||||
while (XML_ELEMENT_NODE === $candidate->nodeType) {
|
||||
if ($candidate->tagName === $tagName) {
|
||||
return true;
|
||||
}
|
||||
$candidate = $candidate->parentNode;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the immediate parent element is of the given tagname.
|
||||
*
|
||||
* @param string $tagName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isParent($tagName)
|
||||
{
|
||||
return $this->current->tagName === $tagName;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Masterminds\HTML5\Parser;
|
||||
|
||||
/**
|
||||
* Standard events for HTML5.
|
||||
*
|
||||
* This is roughly analogous to a SAX2 or expat-style interface.
|
||||
* However, it is tuned specifically for HTML5, according to section 8
|
||||
* of the HTML5 specification.
|
||||
*
|
||||
* An event handler receives parser events. For a concrete
|
||||
* implementation, see DOMTreeBuilder.
|
||||
*
|
||||
* Quirks support in the parser is limited to close-in syntax (malformed
|
||||
* tags or attributes). Higher order syntax and semantic issues with a
|
||||
* document (e.g. mismatched tags, illegal nesting, etc.) are the
|
||||
* responsibility of the event handler implementation.
|
||||
*
|
||||
* See HTML5 spec section 8.2.4
|
||||
*/
|
||||
interface EventHandler
|
||||
{
|
||||
const DOCTYPE_NONE = 0;
|
||||
|
||||
const DOCTYPE_PUBLIC = 1;
|
||||
|
||||
const DOCTYPE_SYSTEM = 2;
|
||||
|
||||
/**
|
||||
* A doctype declaration.
|
||||
*
|
||||
* @param string $name The name of the root element.
|
||||
* @param int $idType One of DOCTYPE_NONE, DOCTYPE_PUBLIC, or DOCTYPE_SYSTEM
|
||||
* @param string $id The identifier. For DOCTYPE_PUBLIC, this is the public ID. If DOCTYPE_SYSTEM,
|
||||
* then this is a system ID.
|
||||
* @param bool $quirks Indicates whether the builder should enter quirks mode.
|
||||
*/
|
||||
public function doctype($name, $idType = 0, $id = null, $quirks = false);
|
||||
|
||||
/**
|
||||
* A start tag.
|
||||
*
|
||||
* IMPORTANT: The parser watches the return value of this event. If this returns
|
||||
* an integer, the parser will switch TEXTMODE patters according to the int.
|
||||
*
|
||||
* This is how the Tree Builder can tell the Tokenizer when a certain tag should
|
||||
* cause the parser to go into RAW text mode.
|
||||
*
|
||||
* The HTML5 standard requires that the builder is the one that initiates this
|
||||
* step, and this is the only way short of a circular reference that we can
|
||||
* do that.
|
||||
*
|
||||
* Example: if a startTag even for a `script` name is fired, and the startTag()
|
||||
* implementation returns Tokenizer::TEXTMODE_RAW, then the tokenizer will
|
||||
* switch into RAW text mode and consume data until it reaches a closing
|
||||
* `script` tag.
|
||||
*
|
||||
* The textmode is automatically reset to Tokenizer::TEXTMODE_NORMAL when the
|
||||
* closing tag is encounter. **This behavior may change.**
|
||||
*
|
||||
* @param string $name The tag name.
|
||||
* @param array $attributes An array with all of the tag's attributes.
|
||||
* @param bool $selfClosing An indicator of whether or not this tag is self-closing (<foo/>).
|
||||
*
|
||||
* @return int one of the Tokenizer::TEXTMODE_* constants
|
||||
*/
|
||||
public function startTag($name, $attributes = array(), $selfClosing = false);
|
||||
|
||||
/**
|
||||
* An end-tag.
|
||||
*/
|
||||
public function endTag($name);
|
||||
|
||||
/**
|
||||
* A comment section (unparsed character data).
|
||||
*/
|
||||
public function comment($cdata);
|
||||
|
||||
/**
|
||||
* A unit of parsed character data.
|
||||
*
|
||||
* Entities in this text are *already decoded*.
|
||||
*/
|
||||
public function text($cdata);
|
||||
|
||||
/**
|
||||
* Indicates that the document has been entirely processed.
|
||||
*/
|
||||
public function eof();
|
||||
|
||||
/**
|
||||
* Emitted when the parser encounters an error condition.
|
||||
*/
|
||||
public function parseError($msg, $line, $col);
|
||||
|
||||
/**
|
||||
* A CDATA section.
|
||||
*
|
||||
* @param string $data
|
||||
* The unparsed character data
|
||||
*/
|
||||
public function cdata($data);
|
||||
|
||||
/**
|
||||
* This is a holdover from the XML spec.
|
||||
*
|
||||
* While user agents don't get PIs, server-side does.
|
||||
*
|
||||
* @param string $name The name of the processor (e.g. 'php').
|
||||
* @param string $data The unparsed data.
|
||||
*/
|
||||
public function processingInstruction($name, $data = null);
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Masterminds\HTML5\Parser;
|
||||
|
||||
/**
|
||||
* The FileInputStream loads a file to be parsed.
|
||||
*
|
||||
* So right now we read files into strings and then process the
|
||||
* string. We chose to do this largely for the sake of expediency of
|
||||
* development, and also because we could optimize toward processing
|
||||
* arbitrarily large chunks of the input. But in the future, we'd
|
||||
* really like to rewrite this class to efficiently handle lower level
|
||||
* stream reads (and thus efficiently handle large documents).
|
||||
*
|
||||
* @deprecated since 2.4, to remove in 3.0. Use a string in the scanner instead.
|
||||
*/
|
||||
class FileInputStream extends StringInputStream implements InputStream
|
||||
{
|
||||
/**
|
||||
* Load a file input stream.
|
||||
*
|
||||
* @param string $data The file or url path to load.
|
||||
* @param string $encoding The encoding to use for the data.
|
||||
* @param string $debug A fprintf format to use to echo the data on stdout.
|
||||
*/
|
||||
public function __construct($data, $encoding = 'UTF-8', $debug = '')
|
||||
{
|
||||
// Get the contents of the file.
|
||||
$content = file_get_contents($data);
|
||||
|
||||
parent::__construct($content, $encoding, $debug);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Masterminds\HTML5\Parser;
|
||||
|
||||
/**
|
||||
* Interface for stream readers.
|
||||
*
|
||||
* The parser only reads from streams. Various input sources can write
|
||||
* an adapater to this InputStream.
|
||||
*
|
||||
* Currently provided InputStream implementations include
|
||||
* FileInputStream and StringInputStream.
|
||||
*
|
||||
* @deprecated since 2.4, to remove in 3.0. Use a string in the scanner instead.
|
||||
*/
|
||||
interface InputStream extends \Iterator
|
||||
{
|
||||
/**
|
||||
* Returns the current line that is being consumed.
|
||||
*
|
||||
* TODO: Move this to the scanner.
|
||||
*/
|
||||
public function currentLine();
|
||||
|
||||
/**
|
||||
* Returns the current column of the current line that the tokenizer is at.
|
||||
*
|
||||
* Newlines are column 0. The first char after a newline is column 1.
|
||||
*
|
||||
* @TODO Move this to the scanner.
|
||||
*
|
||||
* @return int The column number.
|
||||
*/
|
||||
public function columnOffset();
|
||||
|
||||
/**
|
||||
* Get all characters until EOF.
|
||||
*
|
||||
* This consumes characters until the EOF.
|
||||
*/
|
||||
public function remainingChars();
|
||||
|
||||
/**
|
||||
* Read to a particular match (or until $max bytes are consumed).
|
||||
*
|
||||
* This operates on byte sequences, not characters.
|
||||
*
|
||||
* Matches as far as possible until we reach a certain set of bytes
|
||||
* and returns the matched substring.
|
||||
*
|
||||
* @see strcspn
|
||||
*
|
||||
* @param string $bytes Bytes to match.
|
||||
* @param int $max Maximum number of bytes to scan.
|
||||
*
|
||||
* @return mixed Index or false if no match is found. You should use strong
|
||||
* equality when checking the result, since index could be 0.
|
||||
*/
|
||||
public function charsUntil($bytes, $max = null);
|
||||
|
||||
/**
|
||||
* Returns the string so long as $bytes matches.
|
||||
*
|
||||
* Matches as far as possible with a certain set of bytes
|
||||
* and returns the matched substring.
|
||||
*
|
||||
* @see strspn
|
||||
*
|
||||
* @param string $bytes A mask of bytes to match. If ANY byte in this mask matches the
|
||||
* current char, the pointer advances and the char is part of the
|
||||
* substring.
|
||||
* @param int $max The max number of chars to read.
|
||||
*/
|
||||
public function charsWhile($bytes, $max = null);
|
||||
|
||||
/**
|
||||
* Unconsume one character.
|
||||
*
|
||||
* @param int $howMany The number of characters to move the pointer back.
|
||||
*/
|
||||
public function unconsume($howMany = 1);
|
||||
|
||||
/**
|
||||
* Retrieve the next character without advancing the pointer.
|
||||
*/
|
||||
public function peek();
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Masterminds\HTML5\Parser;
|
||||
|
||||
/**
|
||||
* Emit when the parser has an error.
|
||||
*/
|
||||
class ParseError extends \Exception
|
||||
{
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
# The Parser Model
|
||||
|
||||
The parser model here follows the model in section
|
||||
[8.2.1](http://www.w3.org/TR/2012/CR-html5-20121217/syntax.html#parsing)
|
||||
of the HTML5 specification, though we do not assume a networking layer.
|
||||
|
||||
[ InputStream ] // Generic support for reading input.
|
||||
||
|
||||
[ Scanner ] // Breaks down the stream into characters.
|
||||
||
|
||||
[ Tokenizer ] // Groups characters into syntactic
|
||||
||
|
||||
[ Tree Builder ] // Organizes units into a tree of objects
|
||||
||
|
||||
[ DOM Document ] // The final state of the parsed document.
|
||||
|
||||
|
||||
## InputStream
|
||||
|
||||
This is an interface with at least two concrete implementations:
|
||||
|
||||
- StringInputStream: Reads an HTML5 string.
|
||||
- FileInputStream: Reads an HTML5 file.
|
||||
|
||||
## Scanner
|
||||
|
||||
This is a mechanical piece of the parser.
|
||||
|
||||
## Tokenizer
|
||||
|
||||
This follows section 8.4 of the HTML5 spec. It is (roughly) a recursive
|
||||
descent parser. (Though there are plenty of optimizations that are less
|
||||
than purely functional.
|
||||
|
||||
## EventHandler and DOMTree
|
||||
|
||||
EventHandler is the interface for tree builders. Since not all
|
||||
implementations will necessarily build trees, we've chosen a more
|
||||
generic name.
|
||||
|
||||
The event handler emits tokens during tokenization.
|
||||
|
||||
The DOMTree is an event handler that builds a DOM tree. The output of
|
||||
the DOMTree builder is a DOMDocument.
|
||||
|
||||
## DOMDocument
|
||||
|
||||
PHP has a DOMDocument class built-in (technically, it's part of libxml.)
|
||||
We use that, thus rendering the output of this process compatible with
|
||||
SimpleXML, QueryPath, and many other XML/HTML processing tools.
|
||||
|
||||
For cases where the HTML5 is a fragment of a HTML5 document a
|
||||
DOMDocumentFragment is returned instead. This is another built-in class.
|
||||
|
|
@ -1,416 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Masterminds\HTML5\Parser;
|
||||
|
||||
use Masterminds\HTML5\Exception;
|
||||
|
||||
/**
|
||||
* The scanner scans over a given data input to react appropriately to characters.
|
||||
*/
|
||||
class Scanner
|
||||
{
|
||||
const CHARS_HEX = 'abcdefABCDEF01234567890';
|
||||
const CHARS_ALNUM = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890';
|
||||
const CHARS_ALPHA = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
/**
|
||||
* The string data we're parsing.
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* The current integer byte position we are in $data.
|
||||
*/
|
||||
private $char;
|
||||
|
||||
/**
|
||||
* Length of $data; when $char === $data, we are at the end-of-file.
|
||||
*/
|
||||
private $EOF;
|
||||
|
||||
/**
|
||||
* Parse errors.
|
||||
*/
|
||||
public $errors = array();
|
||||
|
||||
/**
|
||||
* Create a new Scanner.
|
||||
*
|
||||
* @param string $data Data to parse.
|
||||
* @param string $encoding The encoding to use for the data.
|
||||
*
|
||||
* @throws Exception If the given data cannot be encoded to UTF-8.
|
||||
*/
|
||||
public function __construct($data, $encoding = 'UTF-8')
|
||||
{
|
||||
if ($data instanceof InputStream) {
|
||||
@trigger_error('InputStream objects are deprecated since version 2.4 and will be removed in 3.0. Use strings instead.', E_USER_DEPRECATED);
|
||||
$data = (string) $data;
|
||||
}
|
||||
|
||||
$data = UTF8Utils::convertToUTF8($data, $encoding);
|
||||
|
||||
// There is good reason to question whether it makes sense to
|
||||
// do this here, since most of these checks are done during
|
||||
// parsing, and since this check doesn't actually *do* anything.
|
||||
$this->errors = UTF8Utils::checkForIllegalCodepoints($data);
|
||||
|
||||
$data = $this->replaceLinefeeds($data);
|
||||
|
||||
$this->data = $data;
|
||||
$this->char = 0;
|
||||
$this->EOF = strlen($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if upcomming chars match the given sequence.
|
||||
*
|
||||
* This will read the stream for the $sequence. If it's
|
||||
* found, this will return true. If not, return false.
|
||||
* Since this unconsumes any chars it reads, the caller
|
||||
* will still need to read the next sequence, even if
|
||||
* this returns true.
|
||||
*
|
||||
* Example: $this->scanner->sequenceMatches('</script>') will
|
||||
* see if the input stream is at the start of a
|
||||
* '</script>' string.
|
||||
*
|
||||
* @param string $sequence
|
||||
* @param bool $caseSensitive
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function sequenceMatches($sequence, $caseSensitive = true)
|
||||
{
|
||||
$portion = substr($this->data, $this->char, strlen($sequence));
|
||||
|
||||
return $caseSensitive ? $portion === $sequence : 0 === strcasecmp($portion, $sequence);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current position.
|
||||
*
|
||||
* @return int The current intiger byte position.
|
||||
*/
|
||||
public function position()
|
||||
{
|
||||
return $this->char;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a peek at the next character in the data.
|
||||
*
|
||||
* @return string The next character.
|
||||
*/
|
||||
public function peek()
|
||||
{
|
||||
if (($this->char + 1) < $this->EOF) {
|
||||
return $this->data[$this->char + 1];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next character.
|
||||
* Note: This advances the pointer.
|
||||
*
|
||||
* @return string The next character.
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
++$this->char;
|
||||
|
||||
if ($this->char < $this->EOF) {
|
||||
return $this->data[$this->char];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current character.
|
||||
* Note, this does not advance the pointer.
|
||||
*
|
||||
* @return string The current character.
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
if ($this->char < $this->EOF) {
|
||||
return $this->data[$this->char];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Silently consume N chars.
|
||||
*
|
||||
* @param int $count
|
||||
*/
|
||||
public function consume($count = 1)
|
||||
{
|
||||
$this->char += $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconsume some of the data.
|
||||
* This moves the data pointer backwards.
|
||||
*
|
||||
* @param int $howMany The number of characters to move the pointer back.
|
||||
*/
|
||||
public function unconsume($howMany = 1)
|
||||
{
|
||||
if (($this->char - $howMany) >= 0) {
|
||||
$this->char -= $howMany;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next group of that contains hex characters.
|
||||
* Note, along with getting the characters the pointer in the data will be
|
||||
* moved as well.
|
||||
*
|
||||
* @return string The next group that is hex characters.
|
||||
*/
|
||||
public function getHex()
|
||||
{
|
||||
return $this->doCharsWhile(static::CHARS_HEX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next group of characters that are ASCII Alpha characters.
|
||||
* Note, along with getting the characters the pointer in the data will be
|
||||
* moved as well.
|
||||
*
|
||||
* @return string The next group of ASCII alpha characters.
|
||||
*/
|
||||
public function getAsciiAlpha()
|
||||
{
|
||||
return $this->doCharsWhile(static::CHARS_ALPHA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next group of characters that are ASCII Alpha characters and numbers.
|
||||
* Note, along with getting the characters the pointer in the data will be
|
||||
* moved as well.
|
||||
*
|
||||
* @return string The next group of ASCII alpha characters and numbers.
|
||||
*/
|
||||
public function getAsciiAlphaNum()
|
||||
{
|
||||
return $this->doCharsWhile(static::CHARS_ALNUM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next group of numbers.
|
||||
* Note, along with getting the characters the pointer in the data will be
|
||||
* moved as well.
|
||||
*
|
||||
* @return string The next group of numbers.
|
||||
*/
|
||||
public function getNumeric()
|
||||
{
|
||||
return $this->doCharsWhile('0123456789');
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume whitespace.
|
||||
* Whitespace in HTML5 is: formfeed, tab, newline, space.
|
||||
*
|
||||
* @return int The length of the matched whitespaces.
|
||||
*/
|
||||
public function whitespace()
|
||||
{
|
||||
if ($this->char >= $this->EOF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$len = strspn($this->data, "\n\t\f ", $this->char);
|
||||
|
||||
$this->char += $len;
|
||||
|
||||
return $len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current line that is being consumed.
|
||||
*
|
||||
* @return int The current line number.
|
||||
*/
|
||||
public function currentLine()
|
||||
{
|
||||
if (empty($this->EOF) || 0 === $this->char) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Add one to $this->char because we want the number for the next
|
||||
// byte to be processed.
|
||||
return substr_count($this->data, "\n", 0, min($this->char, $this->EOF)) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read chars until something in the mask is encountered.
|
||||
*
|
||||
* @param string $mask
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function charsUntil($mask)
|
||||
{
|
||||
return $this->doCharsUntil($mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read chars as long as the mask matches.
|
||||
*
|
||||
* @param string $mask
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function charsWhile($mask)
|
||||
{
|
||||
return $this->doCharsWhile($mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current column of the current line that the tokenizer is at.
|
||||
*
|
||||
* Newlines are column 0. The first char after a newline is column 1.
|
||||
*
|
||||
* @return int The column number.
|
||||
*/
|
||||
public function columnOffset()
|
||||
{
|
||||
// Short circuit for the first char.
|
||||
if (0 === $this->char) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// strrpos is weird, and the offset needs to be negative for what we
|
||||
// want (i.e., the last \n before $this->char). This needs to not have
|
||||
// one (to make it point to the next character, the one we want the
|
||||
// position of) added to it because strrpos's behaviour includes the
|
||||
// final offset byte.
|
||||
$backwardFrom = $this->char - 1 - strlen($this->data);
|
||||
$lastLine = strrpos($this->data, "\n", $backwardFrom);
|
||||
|
||||
// However, for here we want the length up until the next byte to be
|
||||
// processed, so add one to the current byte ($this->char).
|
||||
if (false !== $lastLine) {
|
||||
$findLengthOf = substr($this->data, $lastLine + 1, $this->char - 1 - $lastLine);
|
||||
} else {
|
||||
// After a newline.
|
||||
$findLengthOf = substr($this->data, 0, $this->char);
|
||||
}
|
||||
|
||||
return UTF8Utils::countChars($findLengthOf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all characters until EOF.
|
||||
*
|
||||
* This consumes characters until the EOF.
|
||||
*
|
||||
* @return int The number of characters remaining.
|
||||
*/
|
||||
public function remainingChars()
|
||||
{
|
||||
if ($this->char < $this->EOF) {
|
||||
$data = substr($this->data, $this->char);
|
||||
$this->char = $this->EOF;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
return ''; // false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace linefeed characters according to the spec.
|
||||
*
|
||||
* @param $data
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function replaceLinefeeds($data)
|
||||
{
|
||||
/*
|
||||
* U+000D CARRIAGE RETURN (CR) characters and U+000A LINE FEED (LF) characters are treated specially.
|
||||
* Any CR characters that are followed by LF characters must be removed, and any CR characters not
|
||||
* followed by LF characters must be converted to LF characters. Thus, newlines in HTML DOMs are
|
||||
* represented by LF characters, and there are never any CR characters in the input to the tokenization
|
||||
* stage.
|
||||
*/
|
||||
$crlfTable = array(
|
||||
"\0" => "\xEF\xBF\xBD",
|
||||
"\r\n" => "\n",
|
||||
"\r" => "\n",
|
||||
);
|
||||
|
||||
return strtr($data, $crlfTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read to a particular match (or until $max bytes are consumed).
|
||||
*
|
||||
* This operates on byte sequences, not characters.
|
||||
*
|
||||
* Matches as far as possible until we reach a certain set of bytes
|
||||
* and returns the matched substring.
|
||||
*
|
||||
* @param string $bytes Bytes to match.
|
||||
* @param int $max Maximum number of bytes to scan.
|
||||
*
|
||||
* @return mixed Index or false if no match is found. You should use strong
|
||||
* equality when checking the result, since index could be 0.
|
||||
*/
|
||||
private function doCharsUntil($bytes, $max = null)
|
||||
{
|
||||
if ($this->char >= $this->EOF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 === $max || $max) {
|
||||
$len = strcspn($this->data, $bytes, $this->char, $max);
|
||||
} else {
|
||||
$len = strcspn($this->data, $bytes, $this->char);
|
||||
}
|
||||
|
||||
$string = (string) substr($this->data, $this->char, $len);
|
||||
$this->char += $len;
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string so long as $bytes matches.
|
||||
*
|
||||
* Matches as far as possible with a certain set of bytes
|
||||
* and returns the matched substring.
|
||||
*
|
||||
* @param string $bytes A mask of bytes to match. If ANY byte in this mask matches the
|
||||
* current char, the pointer advances and the char is part of the
|
||||
* substring.
|
||||
* @param int $max The max number of chars to read.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function doCharsWhile($bytes, $max = null)
|
||||
{
|
||||
if ($this->char >= $this->EOF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 === $max || $max) {
|
||||
$len = strspn($this->data, $bytes, $this->char, $max);
|
||||
} else {
|
||||
$len = strspn($this->data, $bytes, $this->char);
|
||||
}
|
||||
|
||||
$string = (string) substr($this->data, $this->char, $len);
|
||||
$this->char += $len;
|
||||
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,336 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Loads a string to be parsed.
|
||||
*/
|
||||
|
||||
namespace Masterminds\HTML5\Parser;
|
||||
|
||||
/*
|
||||
*
|
||||
* Based on code from html5lib:
|
||||
|
||||
Copyright 2009 Geoffrey Sneddon <http://gsnedders.com/>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Some conventions:
|
||||
// - /* */ indicates verbatim text from the HTML 5 specification
|
||||
// MPB: Not sure which version of the spec. Moving from HTML5lib to
|
||||
// HTML5-PHP, I have been using this version:
|
||||
// http://www.w3.org/TR/2012/CR-html5-20121217/Overview.html#contents
|
||||
//
|
||||
// - // indicates regular comments
|
||||
|
||||
/**
|
||||
* @deprecated since 2.4, to remove in 3.0. Use a string in the scanner instead.
|
||||
*/
|
||||
class StringInputStream implements InputStream
|
||||
{
|
||||
/**
|
||||
* The string data we're parsing.
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* The current integer byte position we are in $data.
|
||||
*/
|
||||
private $char;
|
||||
|
||||
/**
|
||||
* Length of $data; when $char === $data, we are at the end-of-file.
|
||||
*/
|
||||
private $EOF;
|
||||
|
||||
/**
|
||||
* Parse errors.
|
||||
*/
|
||||
public $errors = array();
|
||||
|
||||
/**
|
||||
* Create a new InputStream wrapper.
|
||||
*
|
||||
* @param string $data Data to parse.
|
||||
* @param string $encoding The encoding to use for the data.
|
||||
* @param string $debug A fprintf format to use to echo the data on stdout.
|
||||
*/
|
||||
public function __construct($data, $encoding = 'UTF-8', $debug = '')
|
||||
{
|
||||
$data = UTF8Utils::convertToUTF8($data, $encoding);
|
||||
if ($debug) {
|
||||
fprintf(STDOUT, $debug, $data, strlen($data));
|
||||
}
|
||||
|
||||
// There is good reason to question whether it makes sense to
|
||||
// do this here, since most of these checks are done during
|
||||
// parsing, and since this check doesn't actually *do* anything.
|
||||
$this->errors = UTF8Utils::checkForIllegalCodepoints($data);
|
||||
|
||||
$data = $this->replaceLinefeeds($data);
|
||||
|
||||
$this->data = $data;
|
||||
$this->char = 0;
|
||||
$this->EOF = strlen($data);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace linefeed characters according to the spec.
|
||||
*/
|
||||
protected function replaceLinefeeds($data)
|
||||
{
|
||||
/*
|
||||
* U+000D CARRIAGE RETURN (CR) characters and U+000A LINE FEED (LF) characters are treated specially.
|
||||
* Any CR characters that are followed by LF characters must be removed, and any CR characters not
|
||||
* followed by LF characters must be converted to LF characters. Thus, newlines in HTML DOMs are
|
||||
* represented by LF characters, and there are never any CR characters in the input to the tokenization
|
||||
* stage.
|
||||
*/
|
||||
$crlfTable = array(
|
||||
"\0" => "\xEF\xBF\xBD",
|
||||
"\r\n" => "\n",
|
||||
"\r" => "\n",
|
||||
);
|
||||
|
||||
return strtr($data, $crlfTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current line that the tokenizer is at.
|
||||
*/
|
||||
public function currentLine()
|
||||
{
|
||||
if (empty($this->EOF) || 0 === $this->char) {
|
||||
return 1;
|
||||
}
|
||||
// Add one to $this->char because we want the number for the next
|
||||
// byte to be processed.
|
||||
return substr_count($this->data, "\n", 0, min($this->char, $this->EOF)) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function getCurrentLine()
|
||||
{
|
||||
return $this->currentLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current column of the current line that the tokenizer is at.
|
||||
* Newlines are column 0. The first char after a newline is column 1.
|
||||
*
|
||||
* @return int The column number.
|
||||
*/
|
||||
public function columnOffset()
|
||||
{
|
||||
// Short circuit for the first char.
|
||||
if (0 === $this->char) {
|
||||
return 0;
|
||||
}
|
||||
// strrpos is weird, and the offset needs to be negative for what we
|
||||
// want (i.e., the last \n before $this->char). This needs to not have
|
||||
// one (to make it point to the next character, the one we want the
|
||||
// position of) added to it because strrpos's behaviour includes the
|
||||
// final offset byte.
|
||||
$backwardFrom = $this->char - 1 - strlen($this->data);
|
||||
$lastLine = strrpos($this->data, "\n", $backwardFrom);
|
||||
|
||||
// However, for here we want the length up until the next byte to be
|
||||
// processed, so add one to the current byte ($this->char).
|
||||
if (false !== $lastLine) {
|
||||
$findLengthOf = substr($this->data, $lastLine + 1, $this->char - 1 - $lastLine);
|
||||
} else {
|
||||
// After a newline.
|
||||
$findLengthOf = substr($this->data, 0, $this->char);
|
||||
}
|
||||
|
||||
return UTF8Utils::countChars($findLengthOf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function getColumnOffset()
|
||||
{
|
||||
return $this->columnOffset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current character.
|
||||
*
|
||||
* @return string The current character.
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function current()
|
||||
{
|
||||
return $this->data[$this->char];
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance the pointer.
|
||||
* This is part of the Iterator interface.
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function next()
|
||||
{
|
||||
++$this->char;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind to the start of the string.
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function rewind()
|
||||
{
|
||||
$this->char = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the current pointer location valid.
|
||||
*
|
||||
* @return bool Whether the current pointer location is valid.
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function valid()
|
||||
{
|
||||
return $this->char < $this->EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all characters until EOF.
|
||||
*
|
||||
* This reads to the end of the file, and sets the read marker at the
|
||||
* end of the file.
|
||||
*
|
||||
* Note this performs bounds checking.
|
||||
*
|
||||
* @return string Returns the remaining text. If called when the InputStream is
|
||||
* already exhausted, it returns an empty string.
|
||||
*/
|
||||
public function remainingChars()
|
||||
{
|
||||
if ($this->char < $this->EOF) {
|
||||
$data = substr($this->data, $this->char);
|
||||
$this->char = $this->EOF;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
return ''; // false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read to a particular match (or until $max bytes are consumed).
|
||||
*
|
||||
* This operates on byte sequences, not characters.
|
||||
*
|
||||
* Matches as far as possible until we reach a certain set of bytes
|
||||
* and returns the matched substring.
|
||||
*
|
||||
* @param string $bytes Bytes to match.
|
||||
* @param int $max Maximum number of bytes to scan.
|
||||
*
|
||||
* @return mixed Index or false if no match is found. You should use strong
|
||||
* equality when checking the result, since index could be 0.
|
||||
*/
|
||||
public function charsUntil($bytes, $max = null)
|
||||
{
|
||||
if ($this->char >= $this->EOF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 === $max || $max) {
|
||||
$len = strcspn($this->data, $bytes, $this->char, $max);
|
||||
} else {
|
||||
$len = strcspn($this->data, $bytes, $this->char);
|
||||
}
|
||||
|
||||
$string = (string) substr($this->data, $this->char, $len);
|
||||
$this->char += $len;
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string so long as $bytes matches.
|
||||
*
|
||||
* Matches as far as possible with a certain set of bytes
|
||||
* and returns the matched substring.
|
||||
*
|
||||
* @param string $bytes A mask of bytes to match. If ANY byte in this mask matches the
|
||||
* current char, the pointer advances and the char is part of the
|
||||
* substring.
|
||||
* @param int $max The max number of chars to read.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function charsWhile($bytes, $max = null)
|
||||
{
|
||||
if ($this->char >= $this->EOF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 === $max || $max) {
|
||||
$len = strspn($this->data, $bytes, $this->char, $max);
|
||||
} else {
|
||||
$len = strspn($this->data, $bytes, $this->char);
|
||||
}
|
||||
$string = (string) substr($this->data, $this->char, $len);
|
||||
$this->char += $len;
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconsume characters.
|
||||
*
|
||||
* @param int $howMany The number of characters to unconsume.
|
||||
*/
|
||||
public function unconsume($howMany = 1)
|
||||
{
|
||||
if (($this->char - $howMany) >= 0) {
|
||||
$this->char -= $howMany;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Look ahead without moving cursor.
|
||||
*/
|
||||
public function peek()
|
||||
{
|
||||
if (($this->char + 1) <= $this->EOF) {
|
||||
return $this->data[$this->char + 1];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function key()
|
||||
{
|
||||
return $this->char;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,126 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Masterminds\HTML5\Parser;
|
||||
|
||||
/**
|
||||
* Handles special-case rules for the DOM tree builder.
|
||||
*
|
||||
* Many tags have special rules that need to be accomodated on an
|
||||
* individual basis. This class handles those rules.
|
||||
*
|
||||
* See section 8.1.2.4 of the spec.
|
||||
*
|
||||
* @todo - colgroup and col special behaviors
|
||||
* - body and head special behaviors
|
||||
*/
|
||||
class TreeBuildingRules
|
||||
{
|
||||
protected static $tags = array(
|
||||
'li' => 1,
|
||||
'dd' => 1,
|
||||
'dt' => 1,
|
||||
'rt' => 1,
|
||||
'rp' => 1,
|
||||
'tr' => 1,
|
||||
'th' => 1,
|
||||
'td' => 1,
|
||||
'thead' => 1,
|
||||
'tfoot' => 1,
|
||||
'tbody' => 1,
|
||||
'table' => 1,
|
||||
'optgroup' => 1,
|
||||
'option' => 1,
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns true if the given tagname has special processing rules.
|
||||
*/
|
||||
public function hasRules($tagname)
|
||||
{
|
||||
return isset(static::$tags[$tagname]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the rule for the current tag name.
|
||||
*
|
||||
* This may modify the existing DOM.
|
||||
*
|
||||
* @return \DOMElement The new Current DOM element.
|
||||
*/
|
||||
public function evaluate($new, $current)
|
||||
{
|
||||
switch ($new->tagName) {
|
||||
case 'li':
|
||||
return $this->handleLI($new, $current);
|
||||
case 'dt':
|
||||
case 'dd':
|
||||
return $this->handleDT($new, $current);
|
||||
case 'rt':
|
||||
case 'rp':
|
||||
return $this->handleRT($new, $current);
|
||||
case 'optgroup':
|
||||
return $this->closeIfCurrentMatches($new, $current, array(
|
||||
'optgroup',
|
||||
));
|
||||
case 'option':
|
||||
return $this->closeIfCurrentMatches($new, $current, array(
|
||||
'option',
|
||||
));
|
||||
case 'tr':
|
||||
return $this->closeIfCurrentMatches($new, $current, array(
|
||||
'tr',
|
||||
));
|
||||
case 'td':
|
||||
case 'th':
|
||||
return $this->closeIfCurrentMatches($new, $current, array(
|
||||
'th',
|
||||
'td',
|
||||
));
|
||||
case 'tbody':
|
||||
case 'thead':
|
||||
case 'tfoot':
|
||||
case 'table': // Spec isn't explicit about this, but it's necessary.
|
||||
return $this->closeIfCurrentMatches($new, $current, array(
|
||||
'thead',
|
||||
'tfoot',
|
||||
'tbody',
|
||||
));
|
||||
}
|
||||
|
||||
return $current;
|
||||
}
|
||||
|
||||
protected function handleLI($ele, $current)
|
||||
{
|
||||
return $this->closeIfCurrentMatches($ele, $current, array(
|
||||
'li',
|
||||
));
|
||||
}
|
||||
|
||||
protected function handleDT($ele, $current)
|
||||
{
|
||||
return $this->closeIfCurrentMatches($ele, $current, array(
|
||||
'dt',
|
||||
'dd',
|
||||
));
|
||||
}
|
||||
|
||||
protected function handleRT($ele, $current)
|
||||
{
|
||||
return $this->closeIfCurrentMatches($ele, $current, array(
|
||||
'rt',
|
||||
'rp',
|
||||
));
|
||||
}
|
||||
|
||||
protected function closeIfCurrentMatches($ele, $current, $match)
|
||||
{
|
||||
if (in_array($current->tagName, $match, true)) {
|
||||
$current->parentNode->appendChild($ele);
|
||||
} else {
|
||||
$current->appendChild($ele);
|
||||
}
|
||||
|
||||
return $ele;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,177 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Masterminds\HTML5\Parser;
|
||||
|
||||
/*
|
||||
Portions based on code from html5lib files with the following copyright:
|
||||
|
||||
Copyright 2009 Geoffrey Sneddon <http://gsnedders.com/>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
use Masterminds\HTML5\Exception;
|
||||
|
||||
class UTF8Utils
|
||||
{
|
||||
/**
|
||||
* The Unicode replacement character.
|
||||
*/
|
||||
const FFFD = "\xEF\xBF\xBD";
|
||||
|
||||
/**
|
||||
* Count the number of characters in a string.
|
||||
* UTF-8 aware. This will try (in order) iconv, MB, and finally a custom counter.
|
||||
*
|
||||
* @param string $string
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function countChars($string)
|
||||
{
|
||||
// Get the length for the string we need.
|
||||
if (function_exists('mb_strlen')) {
|
||||
return mb_strlen($string, 'utf-8');
|
||||
}
|
||||
|
||||
if (function_exists('iconv_strlen')) {
|
||||
return iconv_strlen($string, 'utf-8');
|
||||
}
|
||||
|
||||
$count = count_chars($string);
|
||||
|
||||
// 0x80 = 0x7F - 0 + 1 (one added to get inclusive range)
|
||||
// 0x33 = 0xF4 - 0x2C + 1 (one added to get inclusive range)
|
||||
return array_sum(array_slice($count, 0, 0x80)) + array_sum(array_slice($count, 0xC2, 0x33));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert data from the given encoding to UTF-8.
|
||||
*
|
||||
* This has not yet been tested with charactersets other than UTF-8.
|
||||
* It should work with ISO-8859-1/-13 and standard Latin Win charsets.
|
||||
*
|
||||
* @param string $data The data to convert
|
||||
* @param string $encoding A valid encoding. Examples: http://www.php.net/manual/en/mbstring.supported-encodings.php
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function convertToUTF8($data, $encoding = 'UTF-8')
|
||||
{
|
||||
/*
|
||||
* From the HTML5 spec: Given an encoding, the bytes in the input stream must be converted
|
||||
* to Unicode characters for the tokeniser, as described by the rules for that encoding,
|
||||
* except that the leading U+FEFF BYTE ORDER MARK character, if any, must not be stripped
|
||||
* by the encoding layer (it is stripped by the rule below). Bytes or sequences of bytes
|
||||
* in the original byte stream that could not be converted to Unicode characters must be
|
||||
* converted to U+FFFD REPLACEMENT CHARACTER code points.
|
||||
*/
|
||||
|
||||
// mb_convert_encoding is chosen over iconv because of a bug. The best
|
||||
// details for the bug are on http://us1.php.net/manual/en/function.iconv.php#108643
|
||||
// which contains links to the actual but reports as well as work around
|
||||
// details.
|
||||
if (function_exists('mb_convert_encoding')) {
|
||||
// mb library has the following behaviors:
|
||||
// - UTF-16 surrogates result in false.
|
||||
// - Overlongs and outside Plane 16 result in empty strings.
|
||||
|
||||
// Before we run mb_convert_encoding we need to tell it what to do with
|
||||
// characters it does not know. This could be different than the parent
|
||||
// application executing this library so we store the value, change it
|
||||
// to our needs, and then change it back when we are done. This feels
|
||||
// a little excessive and it would be great if there was a better way.
|
||||
$save = mb_substitute_character();
|
||||
mb_substitute_character('none');
|
||||
$data = mb_convert_encoding($data, 'UTF-8', $encoding);
|
||||
mb_substitute_character($save);
|
||||
}
|
||||
// @todo Get iconv running in at least some environments if that is possible.
|
||||
elseif (function_exists('iconv') && 'auto' !== $encoding) {
|
||||
// fprintf(STDOUT, "iconv found\n");
|
||||
// iconv has the following behaviors:
|
||||
// - Overlong representations are ignored.
|
||||
// - Beyond Plane 16 is replaced with a lower char.
|
||||
// - Incomplete sequences generate a warning.
|
||||
$data = @iconv($encoding, 'UTF-8//IGNORE', $data);
|
||||
} else {
|
||||
throw new Exception('Not implemented, please install mbstring or iconv');
|
||||
}
|
||||
|
||||
/*
|
||||
* One leading U+FEFF BYTE ORDER MARK character must be ignored if any are present.
|
||||
*/
|
||||
if ("\xEF\xBB\xBF" === substr($data, 0, 3)) {
|
||||
$data = substr($data, 3);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for Unicode code points that are not valid in a document.
|
||||
*
|
||||
* @param string $data A string to analyze
|
||||
*
|
||||
* @return array An array of (string) error messages produced by the scanning
|
||||
*/
|
||||
public static function checkForIllegalCodepoints($data)
|
||||
{
|
||||
// Vestigal error handling.
|
||||
$errors = array();
|
||||
|
||||
/*
|
||||
* All U+0000 null characters in the input must be replaced by U+FFFD REPLACEMENT CHARACTERs.
|
||||
* Any occurrences of such characters is a parse error.
|
||||
*/
|
||||
for ($i = 0, $count = substr_count($data, "\0"); $i < $count; ++$i) {
|
||||
$errors[] = 'null-character';
|
||||
}
|
||||
|
||||
/*
|
||||
* Any occurrences of any characters in the ranges U+0001 to U+0008, U+000B, U+000E to U+001F, U+007F
|
||||
* to U+009F, U+D800 to U+DFFF , U+FDD0 to U+FDEF, and characters U+FFFE, U+FFFF, U+1FFFE, U+1FFFF,
|
||||
* U+2FFFE, U+2FFFF, U+3FFFE, U+3FFFF, U+4FFFE, U+4FFFF, U+5FFFE, U+5FFFF, U+6FFFE, U+6FFFF, U+7FFFE,
|
||||
* U+7FFFF, U+8FFFE, U+8FFFF, U+9FFFE, U+9FFFF, U+AFFFE, U+AFFFF, U+BFFFE, U+BFFFF, U+CFFFE, U+CFFFF,
|
||||
* U+DFFFE, U+DFFFF, U+EFFFE, U+EFFFF, U+FFFFE, U+FFFFF, U+10FFFE, and U+10FFFF are parse errors.
|
||||
* (These are all control characters or permanently undefined Unicode characters.)
|
||||
*/
|
||||
// Check PCRE is loaded.
|
||||
$count = preg_match_all(
|
||||
'/(?:
|
||||
[\x01-\x08\x0B\x0E-\x1F\x7F] # U+0001 to U+0008, U+000B, U+000E to U+001F and U+007F
|
||||
|
|
||||
\xC2[\x80-\x9F] # U+0080 to U+009F
|
||||
|
|
||||
\xED(?:\xA0[\x80-\xFF]|[\xA1-\xBE][\x00-\xFF]|\xBF[\x00-\xBF]) # U+D800 to U+DFFFF
|
||||
|
|
||||
\xEF\xB7[\x90-\xAF] # U+FDD0 to U+FDEF
|
||||
|
|
||||
\xEF\xBF[\xBE\xBF] # U+FFFE and U+FFFF
|
||||
|
|
||||
[\xF0-\xF4][\x8F-\xBF]\xBF[\xBE\xBF] # U+nFFFE and U+nFFFF (1 <= n <= 10_{16})
|
||||
)/x', $data, $matches);
|
||||
for ($i = 0; $i < $count; ++$i) {
|
||||
$errors[] = 'invalid-codepoint';
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,559 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @file
|
||||
* The rules for generating output in the serializer.
|
||||
*
|
||||
* These output rules are likely to generate output similar to the document that
|
||||
* was parsed. It is not intended to output exactly the document that was parsed.
|
||||
*/
|
||||
|
||||
namespace Masterminds\HTML5\Serializer;
|
||||
|
||||
use Masterminds\HTML5\Elements;
|
||||
|
||||
/**
|
||||
* Generate the output html5 based on element rules.
|
||||
*/
|
||||
class OutputRules implements RulesInterface
|
||||
{
|
||||
/**
|
||||
* Defined in http://www.w3.org/TR/html51/infrastructure.html#html-namespace-0.
|
||||
*/
|
||||
const NAMESPACE_HTML = 'http://www.w3.org/1999/xhtml';
|
||||
|
||||
const NAMESPACE_MATHML = 'http://www.w3.org/1998/Math/MathML';
|
||||
|
||||
const NAMESPACE_SVG = 'http://www.w3.org/2000/svg';
|
||||
|
||||
const NAMESPACE_XLINK = 'http://www.w3.org/1999/xlink';
|
||||
|
||||
const NAMESPACE_XML = 'http://www.w3.org/XML/1998/namespace';
|
||||
|
||||
const NAMESPACE_XMLNS = 'http://www.w3.org/2000/xmlns/';
|
||||
|
||||
/**
|
||||
* Holds the HTML5 element names that causes a namespace switch.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $implicitNamespaces = array(
|
||||
self::NAMESPACE_HTML,
|
||||
self::NAMESPACE_SVG,
|
||||
self::NAMESPACE_MATHML,
|
||||
self::NAMESPACE_XML,
|
||||
self::NAMESPACE_XMLNS,
|
||||
);
|
||||
|
||||
const IM_IN_HTML = 1;
|
||||
|
||||
const IM_IN_SVG = 2;
|
||||
|
||||
const IM_IN_MATHML = 3;
|
||||
|
||||
/**
|
||||
* Used as cache to detect if is available ENT_HTML5.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $hasHTML5 = false;
|
||||
|
||||
protected $traverser;
|
||||
|
||||
protected $encode = false;
|
||||
|
||||
protected $out;
|
||||
|
||||
protected $outputMode;
|
||||
|
||||
private $xpath;
|
||||
|
||||
protected $nonBooleanAttributes = array(
|
||||
/*
|
||||
array(
|
||||
'nodeNamespace'=>'http://www.w3.org/1999/xhtml',
|
||||
'attrNamespace'=>'http://www.w3.org/1999/xhtml',
|
||||
|
||||
'nodeName'=>'img', 'nodeName'=>array('img', 'a'),
|
||||
'attrName'=>'alt', 'attrName'=>array('title', 'alt'),
|
||||
),
|
||||
*/
|
||||
array(
|
||||
'nodeNamespace' => 'http://www.w3.org/1999/xhtml',
|
||||
'attrName' => array('href',
|
||||
'hreflang',
|
||||
'http-equiv',
|
||||
'icon',
|
||||
'id',
|
||||
'keytype',
|
||||
'kind',
|
||||
'label',
|
||||
'lang',
|
||||
'language',
|
||||
'list',
|
||||
'maxlength',
|
||||
'media',
|
||||
'method',
|
||||
'name',
|
||||
'placeholder',
|
||||
'rel',
|
||||
'rows',
|
||||
'rowspan',
|
||||
'sandbox',
|
||||
'spellcheck',
|
||||
'scope',
|
||||
'seamless',
|
||||
'shape',
|
||||
'size',
|
||||
'sizes',
|
||||
'span',
|
||||
'src',
|
||||
'srcdoc',
|
||||
'srclang',
|
||||
'srcset',
|
||||
'start',
|
||||
'step',
|
||||
'style',
|
||||
'summary',
|
||||
'tabindex',
|
||||
'target',
|
||||
'title',
|
||||
'type',
|
||||
'value',
|
||||
'width',
|
||||
'border',
|
||||
'charset',
|
||||
'cite',
|
||||
'class',
|
||||
'code',
|
||||
'codebase',
|
||||
'color',
|
||||
'cols',
|
||||
'colspan',
|
||||
'content',
|
||||
'coords',
|
||||
'data',
|
||||
'datetime',
|
||||
'default',
|
||||
'dir',
|
||||
'dirname',
|
||||
'enctype',
|
||||
'for',
|
||||
'form',
|
||||
'formaction',
|
||||
'headers',
|
||||
'height',
|
||||
'accept',
|
||||
'accept-charset',
|
||||
'accesskey',
|
||||
'action',
|
||||
'align',
|
||||
'alt',
|
||||
'bgcolor',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'nodeNamespace' => 'http://www.w3.org/1999/xhtml',
|
||||
'xpath' => 'starts-with(local-name(), \'data-\')',
|
||||
),
|
||||
);
|
||||
|
||||
const DOCTYPE = '<!DOCTYPE html>';
|
||||
|
||||
public function __construct($output, $options = array())
|
||||
{
|
||||
if (isset($options['encode_entities'])) {
|
||||
$this->encode = $options['encode_entities'];
|
||||
}
|
||||
|
||||
$this->outputMode = static::IM_IN_HTML;
|
||||
$this->out = $output;
|
||||
$this->hasHTML5 = defined('ENT_HTML5');
|
||||
}
|
||||
|
||||
public function addRule(array $rule)
|
||||
{
|
||||
$this->nonBooleanAttributes[] = $rule;
|
||||
}
|
||||
|
||||
public function setTraverser(Traverser $traverser)
|
||||
{
|
||||
$this->traverser = $traverser;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function unsetTraverser()
|
||||
{
|
||||
$this->traverser = null;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function document($dom)
|
||||
{
|
||||
$this->doctype();
|
||||
if ($dom->documentElement) {
|
||||
foreach ($dom->childNodes as $node) {
|
||||
$this->traverser->node($node);
|
||||
}
|
||||
$this->nl();
|
||||
}
|
||||
}
|
||||
|
||||
protected function doctype()
|
||||
{
|
||||
$this->wr(static::DOCTYPE);
|
||||
$this->nl();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DOMElement $ele
|
||||
*/
|
||||
public function element($ele)
|
||||
{
|
||||
$name = $ele->tagName;
|
||||
|
||||
// Per spec:
|
||||
// If the element has a declared namespace in the HTML, MathML or
|
||||
// SVG namespaces, we use the lname instead of the tagName.
|
||||
if ($this->traverser->isLocalElement($ele)) {
|
||||
$name = $ele->localName;
|
||||
}
|
||||
|
||||
// If we are in SVG or MathML there is special handling.
|
||||
// Using if/elseif instead of switch because it's faster in PHP.
|
||||
if ('svg' == $name) {
|
||||
$this->outputMode = static::IM_IN_SVG;
|
||||
$name = Elements::normalizeSvgElement($name);
|
||||
} elseif ('math' == $name) {
|
||||
$this->outputMode = static::IM_IN_MATHML;
|
||||
}
|
||||
|
||||
$this->openTag($ele);
|
||||
// The tag is already self-closed (`<svg />` or `<math />`) in `openTag` if there are no child nodes.
|
||||
$handledAsVoidTag = $this->outputMode !== static::IM_IN_HTML && !$ele->hasChildNodes();
|
||||
|
||||
if (Elements::isA($name, Elements::TEXT_RAW)) {
|
||||
foreach ($ele->childNodes as $child) {
|
||||
if ($child instanceof \DOMCharacterData) {
|
||||
$this->wr($child->data);
|
||||
} elseif ($child instanceof \DOMElement) {
|
||||
$this->element($child);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Handle children.
|
||||
if ($ele->hasChildNodes()) {
|
||||
$this->traverser->children($ele->childNodes);
|
||||
}
|
||||
|
||||
// Close out the SVG or MathML special handling.
|
||||
if ('svg' == $name || 'math' == $name) {
|
||||
$this->outputMode = static::IM_IN_HTML;
|
||||
}
|
||||
}
|
||||
|
||||
// If not unary, add a closing tag.
|
||||
if (!$handledAsVoidTag && !Elements::isA($name, Elements::VOID_TAG)) {
|
||||
$this->closeTag($ele);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a text node.
|
||||
*
|
||||
* @param \DOMText $ele The text node to write.
|
||||
*/
|
||||
public function text($ele)
|
||||
{
|
||||
if (isset($ele->parentNode) && isset($ele->parentNode->tagName) && Elements::isA($ele->parentNode->localName, Elements::TEXT_RAW)) {
|
||||
$this->wr($ele->data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: This probably needs some flags set.
|
||||
$this->wr($this->enc($ele->data));
|
||||
}
|
||||
|
||||
public function cdata($ele)
|
||||
{
|
||||
// This encodes CDATA.
|
||||
$this->wr($ele->ownerDocument->saveXML($ele));
|
||||
}
|
||||
|
||||
public function comment($ele)
|
||||
{
|
||||
// These produce identical output.
|
||||
// $this->wr('<!--')->wr($ele->data)->wr('-->');
|
||||
$this->wr($ele->ownerDocument->saveXML($ele));
|
||||
}
|
||||
|
||||
public function processorInstruction($ele)
|
||||
{
|
||||
$this->wr('<?')
|
||||
->wr($ele->target)
|
||||
->wr(' ')
|
||||
->wr($ele->data)
|
||||
->wr('?>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the namespace attributes.
|
||||
*
|
||||
* @param \DOMNode $ele The element being written.
|
||||
*/
|
||||
protected function namespaceAttrs($ele)
|
||||
{
|
||||
if (!$this->xpath || $this->xpath->document !== $ele->ownerDocument) {
|
||||
$this->xpath = new \DOMXPath($ele->ownerDocument);
|
||||
}
|
||||
|
||||
foreach ($this->xpath->query('namespace::*[not(.=../../namespace::*)]', $ele) as $nsNode) {
|
||||
if (!in_array($nsNode->nodeValue, $this->implicitNamespaces)) {
|
||||
$this->wr(' ')->wr($nsNode->nodeName)->wr('="')->wr($nsNode->nodeValue)->wr('"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the opening tag.
|
||||
*
|
||||
* Tags for HTML, MathML, and SVG are in the local name. Otherwise, use the
|
||||
* qualified name (8.3).
|
||||
*
|
||||
* @param \DOMNode $ele The element being written.
|
||||
*/
|
||||
protected function openTag($ele)
|
||||
{
|
||||
$this->wr('<')->wr($this->traverser->isLocalElement($ele) ? $ele->localName : $ele->tagName);
|
||||
|
||||
$this->attrs($ele);
|
||||
$this->namespaceAttrs($ele);
|
||||
|
||||
if ($this->outputMode == static::IM_IN_HTML) {
|
||||
$this->wr('>');
|
||||
} // If we are not in html mode we are in SVG, MathML, or XML embedded content.
|
||||
else {
|
||||
if ($ele->hasChildNodes()) {
|
||||
$this->wr('>');
|
||||
} // If there are no children this is self closing.
|
||||
else {
|
||||
$this->wr(' />');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function attrs($ele)
|
||||
{
|
||||
// FIXME: Needs support for xml, xmlns, xlink, and namespaced elements.
|
||||
if (!$ele->hasAttributes()) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
// TODO: Currently, this always writes name="value", and does not do
|
||||
// value-less attributes.
|
||||
$map = $ele->attributes;
|
||||
$len = $map->length;
|
||||
for ($i = 0; $i < $len; ++$i) {
|
||||
$node = $map->item($i);
|
||||
$val = $this->enc($node->value, true);
|
||||
|
||||
// XXX: The spec says that we need to ensure that anything in
|
||||
// the XML, XMLNS, or XLink NS's should use the canonical
|
||||
// prefix. It seems that DOM does this for us already, but there
|
||||
// may be exceptions.
|
||||
$name = $node->nodeName;
|
||||
|
||||
// Special handling for attributes in SVG and MathML.
|
||||
// Using if/elseif instead of switch because it's faster in PHP.
|
||||
if ($this->outputMode == static::IM_IN_SVG) {
|
||||
$name = Elements::normalizeSvgAttribute($name);
|
||||
} elseif ($this->outputMode == static::IM_IN_MATHML) {
|
||||
$name = Elements::normalizeMathMlAttribute($name);
|
||||
}
|
||||
|
||||
$this->wr(' ')->wr($name);
|
||||
|
||||
if ((isset($val) && '' !== $val) || $this->nonBooleanAttribute($node)) {
|
||||
$this->wr('="')->wr($val)->wr('"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function nonBooleanAttribute(\DOMAttr $attr)
|
||||
{
|
||||
$ele = $attr->ownerElement;
|
||||
foreach ($this->nonBooleanAttributes as $rule) {
|
||||
if (isset($rule['nodeNamespace']) && $rule['nodeNamespace'] !== $ele->namespaceURI) {
|
||||
continue;
|
||||
}
|
||||
if (isset($rule['attNamespace']) && $rule['attNamespace'] !== $attr->namespaceURI) {
|
||||
continue;
|
||||
}
|
||||
if (isset($rule['nodeName']) && !is_array($rule['nodeName']) && $rule['nodeName'] !== $ele->localName) {
|
||||
continue;
|
||||
}
|
||||
if (isset($rule['nodeName']) && is_array($rule['nodeName']) && !in_array($ele->localName, $rule['nodeName'], true)) {
|
||||
continue;
|
||||
}
|
||||
if (isset($rule['attrName']) && !is_array($rule['attrName']) && $rule['attrName'] !== $attr->localName) {
|
||||
continue;
|
||||
}
|
||||
if (isset($rule['attrName']) && is_array($rule['attrName']) && !in_array($attr->localName, $rule['attrName'], true)) {
|
||||
continue;
|
||||
}
|
||||
if (isset($rule['xpath'])) {
|
||||
$xp = $this->getXPath($attr);
|
||||
if (isset($rule['prefixes'])) {
|
||||
foreach ($rule['prefixes'] as $nsPrefix => $ns) {
|
||||
$xp->registerNamespace($nsPrefix, $ns);
|
||||
}
|
||||
}
|
||||
if (!$xp->evaluate($rule['xpath'], $attr)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getXPath(\DOMNode $node)
|
||||
{
|
||||
if (!$this->xpath) {
|
||||
$this->xpath = new \DOMXPath($node->ownerDocument);
|
||||
}
|
||||
|
||||
return $this->xpath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the closing tag.
|
||||
*
|
||||
* Tags for HTML, MathML, and SVG are in the local name. Otherwise, use the
|
||||
* qualified name (8.3).
|
||||
*
|
||||
* @param \DOMNode $ele The element being written.
|
||||
*/
|
||||
protected function closeTag($ele)
|
||||
{
|
||||
if ($this->outputMode == static::IM_IN_HTML || $ele->hasChildNodes()) {
|
||||
$this->wr('</')->wr($this->traverser->isLocalElement($ele) ? $ele->localName : $ele->tagName)->wr('>');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to the output.
|
||||
*
|
||||
* @param string $text The string to put into the output
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function wr($text)
|
||||
{
|
||||
fwrite($this->out, $text);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a new line character.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function nl()
|
||||
{
|
||||
fwrite($this->out, PHP_EOL);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode text.
|
||||
*
|
||||
* When encode is set to false, the default value, the text passed in is
|
||||
* escaped per section 8.3 of the html5 spec. For details on how text is
|
||||
* escaped see the escape() method.
|
||||
*
|
||||
* When encoding is set to true the text is converted to named character
|
||||
* references where appropriate. Section 8.1.4 Character references of the
|
||||
* html5 spec refers to using named character references. This is useful for
|
||||
* characters that can't otherwise legally be used in the text.
|
||||
*
|
||||
* The named character references are listed in section 8.5.
|
||||
*
|
||||
* @see http://www.w3.org/TR/2013/CR-html5-20130806/syntax.html#named-character-references True encoding will turn all named character references into their entities.
|
||||
* This includes such characters as +.# and many other common ones. By default
|
||||
* encoding here will just escape &'<>".
|
||||
*
|
||||
* Note, PHP 5.4+ has better html5 encoding.
|
||||
*
|
||||
* @todo Use the Entities class in php 5.3 to have html5 entities.
|
||||
*
|
||||
* @param string $text Text to encode.
|
||||
* @param bool $attribute True if we are encoding an attrubute, false otherwise.
|
||||
*
|
||||
* @return string The encoded text.
|
||||
*/
|
||||
protected function enc($text, $attribute = false)
|
||||
{
|
||||
// Escape the text rather than convert to named character references.
|
||||
if (!$this->encode) {
|
||||
return $this->escape($text, $attribute);
|
||||
}
|
||||
|
||||
// If we are in PHP 5.4+ we can use the native html5 entity functionality to
|
||||
// convert the named character references.
|
||||
|
||||
if ($this->hasHTML5) {
|
||||
return htmlentities($text, ENT_HTML5 | ENT_SUBSTITUTE | ENT_QUOTES, 'UTF-8', false);
|
||||
} // If a version earlier than 5.4 html5 entities are not entirely handled.
|
||||
// This manually handles them.
|
||||
else {
|
||||
return strtr($text, HTML5Entities::$map);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape test.
|
||||
*
|
||||
* According to the html5 spec section 8.3 Serializing HTML fragments, text
|
||||
* within tags that are not style, script, xmp, iframe, noembed, and noframes
|
||||
* need to be properly escaped.
|
||||
*
|
||||
* The & should be converted to &, no breaking space unicode characters
|
||||
* converted to , when in attribute mode the " should be converted to
|
||||
* ", and when not in attribute mode the < and > should be converted to
|
||||
* < and >.
|
||||
*
|
||||
* @see http://www.w3.org/TR/2013/CR-html5-20130806/syntax.html#escapingString
|
||||
*
|
||||
* @param string $text Text to escape.
|
||||
* @param bool $attribute True if we are escaping an attrubute, false otherwise.
|
||||
*/
|
||||
protected function escape($text, $attribute = false)
|
||||
{
|
||||
// Not using htmlspecialchars because, while it does escaping, it doesn't
|
||||
// match the requirements of section 8.5. For example, it doesn't handle
|
||||
// non-breaking spaces.
|
||||
if ($attribute) {
|
||||
$replace = array(
|
||||
'"' => '"',
|
||||
'&' => '&',
|
||||
"\xc2\xa0" => ' ',
|
||||
);
|
||||
} else {
|
||||
$replace = array(
|
||||
'<' => '<',
|
||||
'>' => '>',
|
||||
'&' => '&',
|
||||
"\xc2\xa0" => ' ',
|
||||
);
|
||||
}
|
||||
|
||||
return strtr($text, $replace);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
# The Serializer (Writer) Model
|
||||
|
||||
The serializer roughly follows sections _8.1 Writing HTML documents_ and section
|
||||
_8.3 Serializing HTML fragments_ by converting DOMDocument, DOMDocumentFragment,
|
||||
and DOMNodeList into HTML5.
|
||||
|
||||
[ HTML5 ] // Interface for saving.
|
||||
||
|
||||
[ Traverser ] // Walk the DOM
|
||||
||
|
||||
[ Rules ] // Convert DOM elements into strings.
|
||||
||
|
||||
[ HTML5 ] // HTML5 document or fragment in text.
|
||||
|
||||
|
||||
## HTML5 Class
|
||||
|
||||
Provides the top level interface for saving.
|
||||
|
||||
## The Traverser
|
||||
|
||||
Walks the DOM finding each element and passing it off to the output rules to
|
||||
convert to HTML5.
|
||||
|
||||
## Output Rules
|
||||
|
||||
The output rules are defined in the RulesInterface which can have multiple
|
||||
implementations. Currently, the OutputRules is the default implementation that
|
||||
converts a DOM as is into HTML5.
|
||||
|
||||
## HTML5 String
|
||||
|
||||
The output of the process it HTML5 as a string or saved to a file.
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @file
|
||||
* The interface definition for Rules to generate output.
|
||||
*/
|
||||
|
||||
namespace Masterminds\HTML5\Serializer;
|
||||
|
||||
/**
|
||||
* To create a new rule set for writing output the RulesInterface needs to be implemented.
|
||||
* The resulting class can be specified in the options with the key of rules.
|
||||
*
|
||||
* For an example implementation see Serializer\OutputRules.
|
||||
*/
|
||||
interface RulesInterface
|
||||
{
|
||||
/**
|
||||
* The class constructor.
|
||||
*
|
||||
* Note, before the rules can be used a traverser must be registered.
|
||||
*
|
||||
* @param mixed $output The output stream to write output to.
|
||||
* @param array $options An array of options.
|
||||
*/
|
||||
public function __construct($output, $options = array());
|
||||
|
||||
/**
|
||||
* Register the traverser used in but the rules.
|
||||
*
|
||||
* Note, only one traverser can be used by the rules.
|
||||
*
|
||||
* @param Traverser $traverser The traverser used in the rules.
|
||||
*
|
||||
* @return RulesInterface $this for the current object.
|
||||
*/
|
||||
public function setTraverser(Traverser $traverser);
|
||||
|
||||
/**
|
||||
* Write a document element (\DOMDocument).
|
||||
*
|
||||
* Instead of returning the result write it to the output stream ($output)
|
||||
* that was passed into the constructor.
|
||||
*
|
||||
* @param \DOMDocument $dom
|
||||
*/
|
||||
public function document($dom);
|
||||
|
||||
/**
|
||||
* Write an element.
|
||||
*
|
||||
* Instead of returning the result write it to the output stream ($output)
|
||||
* that was passed into the constructor.
|
||||
*
|
||||
* @param mixed $ele
|
||||
*/
|
||||
public function element($ele);
|
||||
|
||||
/**
|
||||
* Write a text node.
|
||||
*
|
||||
* Instead of returning the result write it to the output stream ($output)
|
||||
* that was passed into the constructor.
|
||||
*
|
||||
* @param mixed $ele
|
||||
*/
|
||||
public function text($ele);
|
||||
|
||||
/**
|
||||
* Write a CDATA node.
|
||||
*
|
||||
* Instead of returning the result write it to the output stream ($output)
|
||||
* that was passed into the constructor.
|
||||
*
|
||||
* @param mixed $ele
|
||||
*/
|
||||
public function cdata($ele);
|
||||
|
||||
/**
|
||||
* Write a comment node.
|
||||
*
|
||||
* Instead of returning the result write it to the output stream ($output)
|
||||
* that was passed into the constructor.
|
||||
*
|
||||
* @param mixed $ele
|
||||
*/
|
||||
public function comment($ele);
|
||||
|
||||
/**
|
||||
* Write a processor instruction.
|
||||
*
|
||||
* To learn about processor instructions see InstructionProcessor
|
||||
*
|
||||
* Instead of returning the result write it to the output stream ($output)
|
||||
* that was passed into the constructor.
|
||||
*
|
||||
* @param mixed $ele
|
||||
*/
|
||||
public function processorInstruction($ele);
|
||||
}
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Masterminds\HTML5\Serializer;
|
||||
|
||||
/**
|
||||
* Traverser for walking a DOM tree.
|
||||
*
|
||||
* This is a concrete traverser designed to convert a DOM tree into an
|
||||
* HTML5 document. It is not intended to be a generic DOMTreeWalker
|
||||
* implementation.
|
||||
*
|
||||
* @see http://www.w3.org/TR/2012/CR-html5-20121217/syntax.html#serializing-html-fragments
|
||||
*/
|
||||
class Traverser
|
||||
{
|
||||
/**
|
||||
* Namespaces that should be treated as "local" to HTML5.
|
||||
*/
|
||||
protected static $local_ns = array(
|
||||
'http://www.w3.org/1999/xhtml' => 'html',
|
||||
'http://www.w3.org/1998/Math/MathML' => 'math',
|
||||
'http://www.w3.org/2000/svg' => 'svg',
|
||||
);
|
||||
|
||||
protected $dom;
|
||||
|
||||
protected $options;
|
||||
|
||||
protected $encode = false;
|
||||
|
||||
protected $rules;
|
||||
|
||||
protected $out;
|
||||
|
||||
/**
|
||||
* Create a traverser.
|
||||
*
|
||||
* @param \DOMNode|\DOMNodeList $dom The document or node to traverse.
|
||||
* @param resource $out A stream that allows writing. The traverser will output into this
|
||||
* stream.
|
||||
* @param array $options An array of options for the traverser as key/value pairs. These include:
|
||||
* - encode_entities: A bool to specify if full encding should happen for all named
|
||||
* charachter references. Defaults to false which escapes &'<>".
|
||||
* - output_rules: The path to the class handling the output rules.
|
||||
*/
|
||||
public function __construct($dom, $out, RulesInterface $rules, $options = array())
|
||||
{
|
||||
$this->dom = $dom;
|
||||
$this->out = $out;
|
||||
$this->rules = $rules;
|
||||
$this->options = $options;
|
||||
|
||||
$this->rules->setTraverser($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the traverser to walk the DOM.
|
||||
*
|
||||
* @return resource $out Returns the output stream.
|
||||
*/
|
||||
public function walk()
|
||||
{
|
||||
if ($this->dom instanceof \DOMDocument) {
|
||||
$this->rules->document($this->dom);
|
||||
} elseif ($this->dom instanceof \DOMDocumentFragment) {
|
||||
// Document fragments are a special case. Only the children need to
|
||||
// be serialized.
|
||||
if ($this->dom->hasChildNodes()) {
|
||||
$this->children($this->dom->childNodes);
|
||||
}
|
||||
} // If NodeList, loop
|
||||
elseif ($this->dom instanceof \DOMNodeList) {
|
||||
// If this is a NodeList of DOMDocuments this will not work.
|
||||
$this->children($this->dom);
|
||||
} // Else assume this is a DOMNode-like datastructure.
|
||||
else {
|
||||
$this->node($this->dom);
|
||||
}
|
||||
|
||||
return $this->out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a node in the DOM.
|
||||
*
|
||||
* @param mixed $node A node implementing \DOMNode.
|
||||
*/
|
||||
public function node($node)
|
||||
{
|
||||
// A listing of types is at http://php.net/manual/en/dom.constants.php
|
||||
switch ($node->nodeType) {
|
||||
case XML_ELEMENT_NODE:
|
||||
$this->rules->element($node);
|
||||
break;
|
||||
case XML_TEXT_NODE:
|
||||
$this->rules->text($node);
|
||||
break;
|
||||
case XML_CDATA_SECTION_NODE:
|
||||
$this->rules->cdata($node);
|
||||
break;
|
||||
case XML_PI_NODE:
|
||||
$this->rules->processorInstruction($node);
|
||||
break;
|
||||
case XML_COMMENT_NODE:
|
||||
$this->rules->comment($node);
|
||||
break;
|
||||
// Currently we don't support embedding DTDs.
|
||||
default:
|
||||
//print '<!-- Skipped -->';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk through all the nodes on a node list.
|
||||
*
|
||||
* @param \DOMNodeList $nl A list of child elements to walk through.
|
||||
*/
|
||||
public function children($nl)
|
||||
{
|
||||
foreach ($nl as $node) {
|
||||
$this->node($node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is an element local?
|
||||
*
|
||||
* @param mixed $ele An element that implement \DOMNode.
|
||||
*
|
||||
* @return bool true if local and false otherwise.
|
||||
*/
|
||||
public function isLocalElement($ele)
|
||||
{
|
||||
$uri = $ele->namespaceURI;
|
||||
if (empty($uri)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isset(static::$local_ns[$uri]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,456 +0,0 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
[](https://github.com/dompdf/php-font-lib/actions/workflows/phpunit.yml)
|
||||
|
||||
# PHP Font Lib
|
||||
|
||||
This library can be used to:
|
||||
* Read TrueType, OpenType (with TrueType glyphs), WOFF font files
|
||||
* Extract basic info (name, style, etc)
|
||||
* Extract advanced info (horizontal metrics, glyph names, glyph shapes, etc)
|
||||
* Make an Adobe Font Metrics (AFM) file from a font
|
||||
|
||||
This project was initiated by the need to read font files in the [DOMPDF project](https://github.com/dompdf/dompdf).
|
||||
|
||||
Usage Example
|
||||
-------------
|
||||
|
||||
### Base font information
|
||||
|
||||
```php
|
||||
$font = \FontLib\Font::load('fontfile.ttf');
|
||||
$font->parse(); // for getFontWeight() to work this call must be done first!
|
||||
echo $font->getFontName() .'<br>';
|
||||
echo $font->getFontSubfamily() .'<br>';
|
||||
echo $font->getFontSubfamilyID() .'<br>';
|
||||
echo $font->getFontFullName() .'<br>';
|
||||
echo $font->getFontVersion() .'<br>';
|
||||
echo $font->getFontWeight() .'<br>';
|
||||
echo $font->getFontPostscriptName() .'<br>';
|
||||
$font->close();
|
||||
```
|
||||
|
||||
### Font Metrics Generation
|
||||
|
||||
```php
|
||||
$font = FontLib\Font::load('fontfile.ttf');
|
||||
$font->parse();
|
||||
$font->saveAdobeFontMetrics('fontfile.ufm');
|
||||
```
|
||||
|
||||
### Create a font subset
|
||||
|
||||
```php
|
||||
$font = FontLib\Font::load('fontfile.ttf');
|
||||
$font->parse();
|
||||
$font->setSubset("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ.:,;' (!?)+-*/== 1234567890"); // characters to include
|
||||
$font->reduce();
|
||||
touch('fontfile.subset.ttf');
|
||||
$font->open('fontfile.subset.ttf', FontLib\BinaryStream::modeReadWrite);
|
||||
$font->encode(array("OS/2"));
|
||||
$font->close();
|
||||
```
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
{
|
||||
"name": "phenx/php-font-lib",
|
||||
"type": "library",
|
||||
"description": "A library to read, parse, export and make subsets of different types of font files.",
|
||||
"homepage": "https://github.com/PhenX/php-font-lib",
|
||||
"license": "LGPL-2.1-or-later",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Ménager",
|
||||
"email": "fabien.menager@gmail.com"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FontLib\\": "src/FontLib"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"FontLib\\Tests\\": "tests/FontLib"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"bin-dir": "bin"
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge" : "^3 || ^4 || ^5 || ^6"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,231 +0,0 @@
|
|||
// Adobe Standard Encoding table for ttf2pt1
|
||||
// Thomas Henlich <Thomas.Henlich@mailbox.tu-dresden.de>
|
||||
|
||||
=20 U+0020 SPACE
|
||||
=21 U+0021 EXCLAMATION MARK
|
||||
=22 U+0022 QUOTATION MARK
|
||||
=23 U+0023 NUMBER SIGN
|
||||
=24 U+0024 DOLLAR SIGN
|
||||
=25 U+0025 PERCENT SIGN
|
||||
=26 U+0026 AMPERSAND
|
||||
=27 U+2019 RIGHT SINGLE QUOTATION MARK
|
||||
=28 U+0028 LEFT PARENTHESIS
|
||||
=29 U+0029 RIGHT PARENTHESIS
|
||||
=2A U+002A ASTERISK
|
||||
=2B U+002B PLUS SIGN
|
||||
=2C U+002C COMMA
|
||||
=2D U+002D HYPHEN-MINUS
|
||||
=2E U+002E FULL STOP
|
||||
=2F U+002F SOLIDUS
|
||||
=30 U+0030 DIGIT ZERO
|
||||
=31 U+0031 DIGIT ONE
|
||||
=32 U+0032 DIGIT TWO
|
||||
=33 U+0033 DIGIT THREE
|
||||
=34 U+0034 DIGIT FOUR
|
||||
=35 U+0035 DIGIT FIVE
|
||||
=36 U+0036 DIGIT SIX
|
||||
=37 U+0037 DIGIT SEVEN
|
||||
=38 U+0038 DIGIT EIGHT
|
||||
=39 U+0039 DIGIT NINE
|
||||
=3A U+003A COLON
|
||||
=3B U+003B SEMICOLON
|
||||
=3C U+003C LESS-THAN SIGN
|
||||
=3D U+003D EQUALS SIGN
|
||||
=3E U+003E GREATER-THAN SIGN
|
||||
=3F U+003F QUESTION MARK
|
||||
=40 U+0040 COMMERCIAL AT
|
||||
=41 U+0041 LATIN CAPITAL LETTER A
|
||||
=42 U+0042 LATIN CAPITAL LETTER B
|
||||
=43 U+0043 LATIN CAPITAL LETTER C
|
||||
=44 U+0044 LATIN CAPITAL LETTER D
|
||||
=45 U+0045 LATIN CAPITAL LETTER E
|
||||
=46 U+0046 LATIN CAPITAL LETTER F
|
||||
=47 U+0047 LATIN CAPITAL LETTER G
|
||||
=48 U+0048 LATIN CAPITAL LETTER H
|
||||
=49 U+0049 LATIN CAPITAL LETTER I
|
||||
=4A U+004A LATIN CAPITAL LETTER J
|
||||
=4B U+004B LATIN CAPITAL LETTER K
|
||||
=4C U+004C LATIN CAPITAL LETTER L
|
||||
=4D U+004D LATIN CAPITAL LETTER M
|
||||
=4E U+004E LATIN CAPITAL LETTER N
|
||||
=4F U+004F LATIN CAPITAL LETTER O
|
||||
=50 U+0050 LATIN CAPITAL LETTER P
|
||||
=51 U+0051 LATIN CAPITAL LETTER Q
|
||||
=52 U+0052 LATIN CAPITAL LETTER R
|
||||
=53 U+0053 LATIN CAPITAL LETTER S
|
||||
=54 U+0054 LATIN CAPITAL LETTER T
|
||||
=55 U+0055 LATIN CAPITAL LETTER U
|
||||
=56 U+0056 LATIN CAPITAL LETTER V
|
||||
=57 U+0057 LATIN CAPITAL LETTER W
|
||||
=58 U+0058 LATIN CAPITAL LETTER X
|
||||
=59 U+0059 LATIN CAPITAL LETTER Y
|
||||
=5A U+005A LATIN CAPITAL LETTER Z
|
||||
=5B U+005B LEFT SQUARE BRACKET
|
||||
=5C U+005C REVERSE SOLIDUS
|
||||
=5D U+005D RIGHT SQUARE BRACKET
|
||||
=5E U+005E CIRCUMFLEX ACCENT
|
||||
=5F U+005F LOW LINE
|
||||
=60 U+2018 LEFT SINGLE QUOTATION MARK
|
||||
=61 U+0061 LATIN SMALL LETTER A
|
||||
=62 U+0062 LATIN SMALL LETTER B
|
||||
=63 U+0063 LATIN SMALL LETTER C
|
||||
=64 U+0064 LATIN SMALL LETTER D
|
||||
=65 U+0065 LATIN SMALL LETTER E
|
||||
=66 U+0066 LATIN SMALL LETTER F
|
||||
=67 U+0067 LATIN SMALL LETTER G
|
||||
=68 U+0068 LATIN SMALL LETTER H
|
||||
=69 U+0069 LATIN SMALL LETTER I
|
||||
=6A U+006A LATIN SMALL LETTER J
|
||||
=6B U+006B LATIN SMALL LETTER K
|
||||
=6C U+006C LATIN SMALL LETTER L
|
||||
=6D U+006D LATIN SMALL LETTER M
|
||||
=6E U+006E LATIN SMALL LETTER N
|
||||
=6F U+006F LATIN SMALL LETTER O
|
||||
=70 U+0070 LATIN SMALL LETTER P
|
||||
=71 U+0071 LATIN SMALL LETTER Q
|
||||
=72 U+0072 LATIN SMALL LETTER R
|
||||
=73 U+0073 LATIN SMALL LETTER S
|
||||
=74 U+0074 LATIN SMALL LETTER T
|
||||
=75 U+0075 LATIN SMALL LETTER U
|
||||
=76 U+0076 LATIN SMALL LETTER V
|
||||
=77 U+0077 LATIN SMALL LETTER W
|
||||
=78 U+0078 LATIN SMALL LETTER X
|
||||
=79 U+0079 LATIN SMALL LETTER Y
|
||||
=7A U+007A LATIN SMALL LETTER Z
|
||||
=7B U+007B LEFT CURLY BRACKET
|
||||
=7C U+007C VERTICAL LINE
|
||||
=7D U+007D RIGHT CURLY BRACKET
|
||||
=7E U+007E TILDE
|
||||
=A1 U+00A1 INVERTED EXCLAMATION MARK
|
||||
=A2 U+00A2 CENT SIGN
|
||||
=A3 U+00A3 POUND SIGN
|
||||
=A4 U+2044 FRACTION SLASH
|
||||
=A5 U+00A5 YEN SIGN
|
||||
=A6 U+0192 LATIN SMALL LETTER F WITH HOOK
|
||||
=A7 U+00A7 SECTION SIGN
|
||||
=A8 U+00A4 CURRENCY SIGN
|
||||
=A9 U+0027 APOSTROPHE
|
||||
=AA U+201C LEFT DOUBLE QUOTATION MARK
|
||||
=AB U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
|
||||
=AC U+2039 SINGLE LEFT-POINTING ANGLE QUOTATION MARK
|
||||
=AD U+203A SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
|
||||
=AE U+FB01 LATIN SMALL LIGATURE FI
|
||||
=AF U+FB02 LATIN SMALL LIGATURE FL
|
||||
=B1 U+2013 EN DASH
|
||||
=B2 U+2020 DAGGER
|
||||
=B3 U+2021 DOUBLE DAGGER
|
||||
=B4 U+00B7 MIDDLE DOT
|
||||
=B6 U+00B6 PILCROW SIGN
|
||||
=B7 U+2022 BULLET
|
||||
=B8 U+201A SINGLE LOW-9 QUOTATION MARK
|
||||
=B9 U+201E DOUBLE LOW-9 QUOTATION MARK
|
||||
=BA U+201D RIGHT DOUBLE QUOTATION MARK
|
||||
=BB U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
|
||||
=BC U+2026 HORIZONTAL ELLIPSIS
|
||||
=BD U+2030 PER MILLE SIGN
|
||||
=BF U+00BF INVERTED QUESTION MARK
|
||||
=C1 U+0060 GRAVE ACCENT
|
||||
=C2 U+00B4 ACUTE ACCENT
|
||||
=C3 U+02C6 MODIFIER LETTER CIRCUMFLEX ACCENT
|
||||
=C4 U+02DC SMALL TILDE
|
||||
=C5 U+00AF MACRON
|
||||
=C6 U+02D8 BREVE
|
||||
=C7 U+02D9 DOT ABOVE
|
||||
=C8 U+00A8 DIAERESIS
|
||||
=CA U+02DA RING ABOVE
|
||||
=CB U+00B8 CEDILLA
|
||||
=CD U+02DD DOUBLE ACUTE ACCENT
|
||||
=CE U+02DB OGONEK
|
||||
=CF U+02C7 CARON
|
||||
=D0 U+2014 EM DASH
|
||||
=E1 U+00C6 LATIN CAPITAL LETTER AE
|
||||
=E3 U+00AA FEMININE ORDINAL INDICATOR
|
||||
=E8 U+0141 LATIN CAPITAL LETTER L WITH STROKE
|
||||
=E9 U+00D8 LATIN CAPITAL LETTER O WITH STROKE
|
||||
=EA U+0152 LATIN CAPITAL LIGATURE OE
|
||||
=EB U+00BA MASCULINE ORDINAL INDICATOR
|
||||
=F1 U+00E6 LATIN SMALL LETTER AE
|
||||
=F5 U+0131 LATIN SMALL LETTER DOTLESS I
|
||||
=F8 U+0142 LATIN SMALL LETTER L WITH STROKE
|
||||
=F9 U+00F8 LATIN SMALL LETTER O WITH STROKE
|
||||
=FA U+0153 LATIN SMALL LIGATURE OE
|
||||
=FB U+00DF LATIN SMALL LETTER SHARP S
|
||||
|
||||
// unencoded characters:
|
||||
=100 U+00E7 LATIN SMALL LETTER C WITH CEDILLA
|
||||
=101 U+00FF LATIN SMALL LETTER Y WITH DIAERESIS
|
||||
=102 U+00E3 LATIN SMALL LETTER A WITH TILDE
|
||||
=103 U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX
|
||||
=104 U+00B3 SUPERSCRIPT THREE
|
||||
=105 U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX
|
||||
=106 U+00FE LATIN SMALL LETTER THORN
|
||||
=107 U+00E8 LATIN SMALL LETTER E WITH GRAVE
|
||||
=108 U+00B2 SUPERSCRIPT TWO
|
||||
=109 U+00E9 LATIN SMALL LETTER E WITH ACUTE
|
||||
=10A U+00F5 LATIN SMALL LETTER O WITH TILDE
|
||||
=10B U+00C1 LATIN CAPITAL LETTER A WITH ACUTE
|
||||
=10C U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX
|
||||
=10D U+00FD LATIN SMALL LETTER Y WITH ACUTE
|
||||
=10E U+00FC LATIN SMALL LETTER U WITH DIAERESIS
|
||||
=10F U+00BE VULGAR FRACTION THREE QUARTERS
|
||||
=110 U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX
|
||||
=111 U+00D0 LATIN CAPITAL LETTER ETH
|
||||
=112 U+00EB LATIN SMALL LETTER E WITH DIAERESIS
|
||||
=113 U+00F9 LATIN SMALL LETTER U WITH GRAVE
|
||||
=114 U+2122 TRADE MARK SIGN
|
||||
=115 U+00F2 LATIN SMALL LETTER O WITH GRAVE
|
||||
=116 U+0161 LATIN SMALL LETTER S WITH CARON
|
||||
=117 U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS
|
||||
=118 U+00FA LATIN SMALL LETTER U WITH ACUTE
|
||||
=119 U+00E0 LATIN SMALL LETTER A WITH GRAVE
|
||||
=11A U+00F1 LATIN SMALL LETTER N WITH TILDE
|
||||
=11B U+00E5 LATIN SMALL LETTER A WITH RING ABOVE
|
||||
=11C U+017E LATIN SMALL LETTER Z WITH CARON
|
||||
=11D U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX
|
||||
=11E U+00D1 LATIN CAPITAL LETTER N WITH TILDE
|
||||
=11F U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX
|
||||
=120 U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX
|
||||
=121 U+00CD LATIN CAPITAL LETTER I WITH ACUTE
|
||||
=122 U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA
|
||||
=123 U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS
|
||||
=124 U+0160 LATIN CAPITAL LETTER S WITH CARON
|
||||
=125 U+00CC LATIN CAPITAL LETTER I WITH GRAVE
|
||||
=126 U+00E4 LATIN SMALL LETTER A WITH DIAERESIS
|
||||
=127 U+00D2 LATIN CAPITAL LETTER O WITH GRAVE
|
||||
=128 U+00C8 LATIN CAPITAL LETTER E WITH GRAVE
|
||||
=129 U+0178 LATIN CAPITAL LETTER Y WITH DIAERESIS
|
||||
=12A U+00AE REGISTERED SIGN
|
||||
=12B U+00D5 LATIN CAPITAL LETTER O WITH TILDE
|
||||
=12C U+00BC VULGAR FRACTION ONE QUARTER
|
||||
=12D U+00D9 LATIN CAPITAL LETTER U WITH GRAVE
|
||||
=12E U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX
|
||||
=12F U+00DE LATIN CAPITAL LETTER THORN
|
||||
=130 U+00F7 DIVISION SIGN
|
||||
=131 U+00C3 LATIN CAPITAL LETTER A WITH TILDE
|
||||
=132 U+00DA LATIN CAPITAL LETTER U WITH ACUTE
|
||||
=133 U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX
|
||||
=134 U+00AC NOT SIGN
|
||||
=135 U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE
|
||||
=136 U+00EF LATIN SMALL LETTER I WITH DIAERESIS
|
||||
=137 U+00ED LATIN SMALL LETTER I WITH ACUTE
|
||||
=138 U+00E1 LATIN SMALL LETTER A WITH ACUTE
|
||||
=139 U+00B1 PLUS-MINUS SIGN
|
||||
=13A U+00D7 MULTIPLICATION SIGN
|
||||
=13B U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS
|
||||
=13C U+2212 MINUS SIGN
|
||||
=13D U+00B9 SUPERSCRIPT ONE
|
||||
=13E U+00C9 LATIN CAPITAL LETTER E WITH ACUTE
|
||||
=13F U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX
|
||||
=140 U+00A9 COPYRIGHT SIGN
|
||||
=141 U+00C0 LATIN CAPITAL LETTER A WITH GRAVE
|
||||
=142 U+00F6 LATIN SMALL LETTER O WITH DIAERESIS
|
||||
=143 U+00F3 LATIN SMALL LETTER O WITH ACUTE
|
||||
=144 U+00B0 DEGREE SIGN
|
||||
=145 U+00EC LATIN SMALL LETTER I WITH GRAVE
|
||||
=146 U+00B5 MICRO SIGN
|
||||
=147 U+00D3 LATIN CAPITAL LETTER O WITH ACUTE
|
||||
=148 U+00F0 LATIN SMALL LETTER ETH
|
||||
=149 U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS
|
||||
=14A U+00DD LATIN CAPITAL LETTER Y WITH ACUTE
|
||||
=14B U+00A6 BROKEN BAR
|
||||
=14C U+00BD VULGAR FRACTION ONE HALF
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+20AC Euro
|
||||
!82 U+201A quotesinglbase
|
||||
!84 U+201E quotedblbase
|
||||
!85 U+2026 ellipsis
|
||||
!86 U+2020 dagger
|
||||
!87 U+2021 daggerdbl
|
||||
!89 U+2030 perthousand
|
||||
!8A U+0160 Scaron
|
||||
!8B U+2039 guilsinglleft
|
||||
!8C U+015A Sacute
|
||||
!8D U+0164 Tcaron
|
||||
!8E U+017D Zcaron
|
||||
!8F U+0179 Zacute
|
||||
!91 U+2018 quoteleft
|
||||
!92 U+2019 quoteright
|
||||
!93 U+201C quotedblleft
|
||||
!94 U+201D quotedblright
|
||||
!95 U+2022 bullet
|
||||
!96 U+2013 endash
|
||||
!97 U+2014 emdash
|
||||
!99 U+2122 trademark
|
||||
!9A U+0161 scaron
|
||||
!9B U+203A guilsinglright
|
||||
!9C U+015B sacute
|
||||
!9D U+0165 tcaron
|
||||
!9E U+017E zcaron
|
||||
!9F U+017A zacute
|
||||
!A0 U+00A0 space
|
||||
!A1 U+02C7 caron
|
||||
!A2 U+02D8 breve
|
||||
!A3 U+0141 Lslash
|
||||
!A4 U+00A4 currency
|
||||
!A5 U+0104 Aogonek
|
||||
!A6 U+00A6 brokenbar
|
||||
!A7 U+00A7 section
|
||||
!A8 U+00A8 dieresis
|
||||
!A9 U+00A9 copyright
|
||||
!AA U+015E Scedilla
|
||||
!AB U+00AB guillemotleft
|
||||
!AC U+00AC logicalnot
|
||||
!AD U+00AD hyphen
|
||||
!AE U+00AE registered
|
||||
!AF U+017B Zdotaccent
|
||||
!B0 U+00B0 degree
|
||||
!B1 U+00B1 plusminus
|
||||
!B2 U+02DB ogonek
|
||||
!B3 U+0142 lslash
|
||||
!B4 U+00B4 acute
|
||||
!B5 U+00B5 mu
|
||||
!B6 U+00B6 paragraph
|
||||
!B7 U+00B7 periodcentered
|
||||
!B8 U+00B8 cedilla
|
||||
!B9 U+0105 aogonek
|
||||
!BA U+015F scedilla
|
||||
!BB U+00BB guillemotright
|
||||
!BC U+013D Lcaron
|
||||
!BD U+02DD hungarumlaut
|
||||
!BE U+013E lcaron
|
||||
!BF U+017C zdotaccent
|
||||
!C0 U+0154 Racute
|
||||
!C1 U+00C1 Aacute
|
||||
!C2 U+00C2 Acircumflex
|
||||
!C3 U+0102 Abreve
|
||||
!C4 U+00C4 Adieresis
|
||||
!C5 U+0139 Lacute
|
||||
!C6 U+0106 Cacute
|
||||
!C7 U+00C7 Ccedilla
|
||||
!C8 U+010C Ccaron
|
||||
!C9 U+00C9 Eacute
|
||||
!CA U+0118 Eogonek
|
||||
!CB U+00CB Edieresis
|
||||
!CC U+011A Ecaron
|
||||
!CD U+00CD Iacute
|
||||
!CE U+00CE Icircumflex
|
||||
!CF U+010E Dcaron
|
||||
!D0 U+0110 Dcroat
|
||||
!D1 U+0143 Nacute
|
||||
!D2 U+0147 Ncaron
|
||||
!D3 U+00D3 Oacute
|
||||
!D4 U+00D4 Ocircumflex
|
||||
!D5 U+0150 Ohungarumlaut
|
||||
!D6 U+00D6 Odieresis
|
||||
!D7 U+00D7 multiply
|
||||
!D8 U+0158 Rcaron
|
||||
!D9 U+016E Uring
|
||||
!DA U+00DA Uacute
|
||||
!DB U+0170 Uhungarumlaut
|
||||
!DC U+00DC Udieresis
|
||||
!DD U+00DD Yacute
|
||||
!DE U+0162 Tcommaaccent
|
||||
!DF U+00DF germandbls
|
||||
!E0 U+0155 racute
|
||||
!E1 U+00E1 aacute
|
||||
!E2 U+00E2 acircumflex
|
||||
!E3 U+0103 abreve
|
||||
!E4 U+00E4 adieresis
|
||||
!E5 U+013A lacute
|
||||
!E6 U+0107 cacute
|
||||
!E7 U+00E7 ccedilla
|
||||
!E8 U+010D ccaron
|
||||
!E9 U+00E9 eacute
|
||||
!EA U+0119 eogonek
|
||||
!EB U+00EB edieresis
|
||||
!EC U+011B ecaron
|
||||
!ED U+00ED iacute
|
||||
!EE U+00EE icircumflex
|
||||
!EF U+010F dcaron
|
||||
!F0 U+0111 dcroat
|
||||
!F1 U+0144 nacute
|
||||
!F2 U+0148 ncaron
|
||||
!F3 U+00F3 oacute
|
||||
!F4 U+00F4 ocircumflex
|
||||
!F5 U+0151 ohungarumlaut
|
||||
!F6 U+00F6 odieresis
|
||||
!F7 U+00F7 divide
|
||||
!F8 U+0159 rcaron
|
||||
!F9 U+016F uring
|
||||
!FA U+00FA uacute
|
||||
!FB U+0171 uhungarumlaut
|
||||
!FC U+00FC udieresis
|
||||
!FD U+00FD yacute
|
||||
!FE U+0163 tcommaaccent
|
||||
!FF U+02D9 dotaccent
|
||||
|
|
@ -1,255 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+0402 afii10051
|
||||
!81 U+0403 afii10052
|
||||
!82 U+201A quotesinglbase
|
||||
!83 U+0453 afii10100
|
||||
!84 U+201E quotedblbase
|
||||
!85 U+2026 ellipsis
|
||||
!86 U+2020 dagger
|
||||
!87 U+2021 daggerdbl
|
||||
!88 U+20AC Euro
|
||||
!89 U+2030 perthousand
|
||||
!8A U+0409 afii10058
|
||||
!8B U+2039 guilsinglleft
|
||||
!8C U+040A afii10059
|
||||
!8D U+040C afii10061
|
||||
!8E U+040B afii10060
|
||||
!8F U+040F afii10145
|
||||
!90 U+0452 afii10099
|
||||
!91 U+2018 quoteleft
|
||||
!92 U+2019 quoteright
|
||||
!93 U+201C quotedblleft
|
||||
!94 U+201D quotedblright
|
||||
!95 U+2022 bullet
|
||||
!96 U+2013 endash
|
||||
!97 U+2014 emdash
|
||||
!99 U+2122 trademark
|
||||
!9A U+0459 afii10106
|
||||
!9B U+203A guilsinglright
|
||||
!9C U+045A afii10107
|
||||
!9D U+045C afii10109
|
||||
!9E U+045B afii10108
|
||||
!9F U+045F afii10193
|
||||
!A0 U+00A0 space
|
||||
!A1 U+040E afii10062
|
||||
!A2 U+045E afii10110
|
||||
!A3 U+0408 afii10057
|
||||
!A4 U+00A4 currency
|
||||
!A5 U+0490 afii10050
|
||||
!A6 U+00A6 brokenbar
|
||||
!A7 U+00A7 section
|
||||
!A8 U+0401 afii10023
|
||||
!A9 U+00A9 copyright
|
||||
!AA U+0404 afii10053
|
||||
!AB U+00AB guillemotleft
|
||||
!AC U+00AC logicalnot
|
||||
!AD U+00AD hyphen
|
||||
!AE U+00AE registered
|
||||
!AF U+0407 afii10056
|
||||
!B0 U+00B0 degree
|
||||
!B1 U+00B1 plusminus
|
||||
!B2 U+0406 afii10055
|
||||
!B3 U+0456 afii10103
|
||||
!B4 U+0491 afii10098
|
||||
!B5 U+00B5 mu
|
||||
!B6 U+00B6 paragraph
|
||||
!B7 U+00B7 periodcentered
|
||||
!B8 U+0451 afii10071
|
||||
!B9 U+2116 afii61352
|
||||
!BA U+0454 afii10101
|
||||
!BB U+00BB guillemotright
|
||||
!BC U+0458 afii10105
|
||||
!BD U+0405 afii10054
|
||||
!BE U+0455 afii10102
|
||||
!BF U+0457 afii10104
|
||||
!C0 U+0410 afii10017
|
||||
!C1 U+0411 afii10018
|
||||
!C2 U+0412 afii10019
|
||||
!C3 U+0413 afii10020
|
||||
!C4 U+0414 afii10021
|
||||
!C5 U+0415 afii10022
|
||||
!C6 U+0416 afii10024
|
||||
!C7 U+0417 afii10025
|
||||
!C8 U+0418 afii10026
|
||||
!C9 U+0419 afii10027
|
||||
!CA U+041A afii10028
|
||||
!CB U+041B afii10029
|
||||
!CC U+041C afii10030
|
||||
!CD U+041D afii10031
|
||||
!CE U+041E afii10032
|
||||
!CF U+041F afii10033
|
||||
!D0 U+0420 afii10034
|
||||
!D1 U+0421 afii10035
|
||||
!D2 U+0422 afii10036
|
||||
!D3 U+0423 afii10037
|
||||
!D4 U+0424 afii10038
|
||||
!D5 U+0425 afii10039
|
||||
!D6 U+0426 afii10040
|
||||
!D7 U+0427 afii10041
|
||||
!D8 U+0428 afii10042
|
||||
!D9 U+0429 afii10043
|
||||
!DA U+042A afii10044
|
||||
!DB U+042B afii10045
|
||||
!DC U+042C afii10046
|
||||
!DD U+042D afii10047
|
||||
!DE U+042E afii10048
|
||||
!DF U+042F afii10049
|
||||
!E0 U+0430 afii10065
|
||||
!E1 U+0431 afii10066
|
||||
!E2 U+0432 afii10067
|
||||
!E3 U+0433 afii10068
|
||||
!E4 U+0434 afii10069
|
||||
!E5 U+0435 afii10070
|
||||
!E6 U+0436 afii10072
|
||||
!E7 U+0437 afii10073
|
||||
!E8 U+0438 afii10074
|
||||
!E9 U+0439 afii10075
|
||||
!EA U+043A afii10076
|
||||
!EB U+043B afii10077
|
||||
!EC U+043C afii10078
|
||||
!ED U+043D afii10079
|
||||
!EE U+043E afii10080
|
||||
!EF U+043F afii10081
|
||||
!F0 U+0440 afii10082
|
||||
!F1 U+0441 afii10083
|
||||
!F2 U+0442 afii10084
|
||||
!F3 U+0443 afii10085
|
||||
!F4 U+0444 afii10086
|
||||
!F5 U+0445 afii10087
|
||||
!F6 U+0446 afii10088
|
||||
!F7 U+0447 afii10089
|
||||
!F8 U+0448 afii10090
|
||||
!F9 U+0449 afii10091
|
||||
!FA U+044A afii10092
|
||||
!FB U+044B afii10093
|
||||
!FC U+044C afii10094
|
||||
!FD U+044D afii10095
|
||||
!FE U+044E afii10096
|
||||
!FF U+044F afii10097
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+20AC Euro
|
||||
!82 U+201A quotesinglbase
|
||||
!83 U+0192 florin
|
||||
!84 U+201E quotedblbase
|
||||
!85 U+2026 ellipsis
|
||||
!86 U+2020 dagger
|
||||
!87 U+2021 daggerdbl
|
||||
!88 U+02C6 circumflex
|
||||
!89 U+2030 perthousand
|
||||
!8A U+0160 Scaron
|
||||
!8B U+2039 guilsinglleft
|
||||
!8C U+0152 OE
|
||||
!8E U+017D Zcaron
|
||||
!91 U+2018 quoteleft
|
||||
!92 U+2019 quoteright
|
||||
!93 U+201C quotedblleft
|
||||
!94 U+201D quotedblright
|
||||
!95 U+2022 bullet
|
||||
!96 U+2013 endash
|
||||
!97 U+2014 emdash
|
||||
!98 U+02DC tilde
|
||||
!99 U+2122 trademark
|
||||
!9A U+0161 scaron
|
||||
!9B U+203A guilsinglright
|
||||
!9C U+0153 oe
|
||||
!9E U+017E zcaron
|
||||
!9F U+0178 Ydieresis
|
||||
!A0 U+00A0 space
|
||||
!A1 U+00A1 exclamdown
|
||||
!A2 U+00A2 cent
|
||||
!A3 U+00A3 sterling
|
||||
!A4 U+00A4 currency
|
||||
!A5 U+00A5 yen
|
||||
!A6 U+00A6 brokenbar
|
||||
!A7 U+00A7 section
|
||||
!A8 U+00A8 dieresis
|
||||
!A9 U+00A9 copyright
|
||||
!AA U+00AA ordfeminine
|
||||
!AB U+00AB guillemotleft
|
||||
!AC U+00AC logicalnot
|
||||
!AD U+00AD hyphen
|
||||
!AE U+00AE registered
|
||||
!AF U+00AF macron
|
||||
!B0 U+00B0 degree
|
||||
!B1 U+00B1 plusminus
|
||||
!B2 U+00B2 twosuperior
|
||||
!B3 U+00B3 threesuperior
|
||||
!B4 U+00B4 acute
|
||||
!B5 U+00B5 mu
|
||||
!B6 U+00B6 paragraph
|
||||
!B7 U+00B7 periodcentered
|
||||
!B8 U+00B8 cedilla
|
||||
!B9 U+00B9 onesuperior
|
||||
!BA U+00BA ordmasculine
|
||||
!BB U+00BB guillemotright
|
||||
!BC U+00BC onequarter
|
||||
!BD U+00BD onehalf
|
||||
!BE U+00BE threequarters
|
||||
!BF U+00BF questiondown
|
||||
!C0 U+00C0 Agrave
|
||||
!C1 U+00C1 Aacute
|
||||
!C2 U+00C2 Acircumflex
|
||||
!C3 U+00C3 Atilde
|
||||
!C4 U+00C4 Adieresis
|
||||
!C5 U+00C5 Aring
|
||||
!C6 U+00C6 AE
|
||||
!C7 U+00C7 Ccedilla
|
||||
!C8 U+00C8 Egrave
|
||||
!C9 U+00C9 Eacute
|
||||
!CA U+00CA Ecircumflex
|
||||
!CB U+00CB Edieresis
|
||||
!CC U+00CC Igrave
|
||||
!CD U+00CD Iacute
|
||||
!CE U+00CE Icircumflex
|
||||
!CF U+00CF Idieresis
|
||||
!D0 U+00D0 Eth
|
||||
!D1 U+00D1 Ntilde
|
||||
!D2 U+00D2 Ograve
|
||||
!D3 U+00D3 Oacute
|
||||
!D4 U+00D4 Ocircumflex
|
||||
!D5 U+00D5 Otilde
|
||||
!D6 U+00D6 Odieresis
|
||||
!D7 U+00D7 multiply
|
||||
!D8 U+00D8 Oslash
|
||||
!D9 U+00D9 Ugrave
|
||||
!DA U+00DA Uacute
|
||||
!DB U+00DB Ucircumflex
|
||||
!DC U+00DC Udieresis
|
||||
!DD U+00DD Yacute
|
||||
!DE U+00DE Thorn
|
||||
!DF U+00DF germandbls
|
||||
!E0 U+00E0 agrave
|
||||
!E1 U+00E1 aacute
|
||||
!E2 U+00E2 acircumflex
|
||||
!E3 U+00E3 atilde
|
||||
!E4 U+00E4 adieresis
|
||||
!E5 U+00E5 aring
|
||||
!E6 U+00E6 ae
|
||||
!E7 U+00E7 ccedilla
|
||||
!E8 U+00E8 egrave
|
||||
!E9 U+00E9 eacute
|
||||
!EA U+00EA ecircumflex
|
||||
!EB U+00EB edieresis
|
||||
!EC U+00EC igrave
|
||||
!ED U+00ED iacute
|
||||
!EE U+00EE icircumflex
|
||||
!EF U+00EF idieresis
|
||||
!F0 U+00F0 eth
|
||||
!F1 U+00F1 ntilde
|
||||
!F2 U+00F2 ograve
|
||||
!F3 U+00F3 oacute
|
||||
!F4 U+00F4 ocircumflex
|
||||
!F5 U+00F5 otilde
|
||||
!F6 U+00F6 odieresis
|
||||
!F7 U+00F7 divide
|
||||
!F8 U+00F8 oslash
|
||||
!F9 U+00F9 ugrave
|
||||
!FA U+00FA uacute
|
||||
!FB U+00FB ucircumflex
|
||||
!FC U+00FC udieresis
|
||||
!FD U+00FD yacute
|
||||
!FE U+00FE thorn
|
||||
!FF U+00FF ydieresis
|
||||
|
|
@ -1,239 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+20AC Euro
|
||||
!82 U+201A quotesinglbase
|
||||
!83 U+0192 florin
|
||||
!84 U+201E quotedblbase
|
||||
!85 U+2026 ellipsis
|
||||
!86 U+2020 dagger
|
||||
!87 U+2021 daggerdbl
|
||||
!89 U+2030 perthousand
|
||||
!8B U+2039 guilsinglleft
|
||||
!91 U+2018 quoteleft
|
||||
!92 U+2019 quoteright
|
||||
!93 U+201C quotedblleft
|
||||
!94 U+201D quotedblright
|
||||
!95 U+2022 bullet
|
||||
!96 U+2013 endash
|
||||
!97 U+2014 emdash
|
||||
!99 U+2122 trademark
|
||||
!9B U+203A guilsinglright
|
||||
!A0 U+00A0 space
|
||||
!A1 U+0385 dieresistonos
|
||||
!A2 U+0386 Alphatonos
|
||||
!A3 U+00A3 sterling
|
||||
!A4 U+00A4 currency
|
||||
!A5 U+00A5 yen
|
||||
!A6 U+00A6 brokenbar
|
||||
!A7 U+00A7 section
|
||||
!A8 U+00A8 dieresis
|
||||
!A9 U+00A9 copyright
|
||||
!AB U+00AB guillemotleft
|
||||
!AC U+00AC logicalnot
|
||||
!AD U+00AD hyphen
|
||||
!AE U+00AE registered
|
||||
!AF U+2015 afii00208
|
||||
!B0 U+00B0 degree
|
||||
!B1 U+00B1 plusminus
|
||||
!B2 U+00B2 twosuperior
|
||||
!B3 U+00B3 threesuperior
|
||||
!B4 U+0384 tonos
|
||||
!B5 U+00B5 mu
|
||||
!B6 U+00B6 paragraph
|
||||
!B7 U+00B7 periodcentered
|
||||
!B8 U+0388 Epsilontonos
|
||||
!B9 U+0389 Etatonos
|
||||
!BA U+038A Iotatonos
|
||||
!BB U+00BB guillemotright
|
||||
!BC U+038C Omicrontonos
|
||||
!BD U+00BD onehalf
|
||||
!BE U+038E Upsilontonos
|
||||
!BF U+038F Omegatonos
|
||||
!C0 U+0390 iotadieresistonos
|
||||
!C1 U+0391 Alpha
|
||||
!C2 U+0392 Beta
|
||||
!C3 U+0393 Gamma
|
||||
!C4 U+0394 Delta
|
||||
!C5 U+0395 Epsilon
|
||||
!C6 U+0396 Zeta
|
||||
!C7 U+0397 Eta
|
||||
!C8 U+0398 Theta
|
||||
!C9 U+0399 Iota
|
||||
!CA U+039A Kappa
|
||||
!CB U+039B Lambda
|
||||
!CC U+039C Mu
|
||||
!CD U+039D Nu
|
||||
!CE U+039E Xi
|
||||
!CF U+039F Omicron
|
||||
!D0 U+03A0 Pi
|
||||
!D1 U+03A1 Rho
|
||||
!D3 U+03A3 Sigma
|
||||
!D4 U+03A4 Tau
|
||||
!D5 U+03A5 Upsilon
|
||||
!D6 U+03A6 Phi
|
||||
!D7 U+03A7 Chi
|
||||
!D8 U+03A8 Psi
|
||||
!D9 U+03A9 Omega
|
||||
!DA U+03AA Iotadieresis
|
||||
!DB U+03AB Upsilondieresis
|
||||
!DC U+03AC alphatonos
|
||||
!DD U+03AD epsilontonos
|
||||
!DE U+03AE etatonos
|
||||
!DF U+03AF iotatonos
|
||||
!E0 U+03B0 upsilondieresistonos
|
||||
!E1 U+03B1 alpha
|
||||
!E2 U+03B2 beta
|
||||
!E3 U+03B3 gamma
|
||||
!E4 U+03B4 delta
|
||||
!E5 U+03B5 epsilon
|
||||
!E6 U+03B6 zeta
|
||||
!E7 U+03B7 eta
|
||||
!E8 U+03B8 theta
|
||||
!E9 U+03B9 iota
|
||||
!EA U+03BA kappa
|
||||
!EB U+03BB lambda
|
||||
!EC U+03BC mu
|
||||
!ED U+03BD nu
|
||||
!EE U+03BE xi
|
||||
!EF U+03BF omicron
|
||||
!F0 U+03C0 pi
|
||||
!F1 U+03C1 rho
|
||||
!F2 U+03C2 sigma1
|
||||
!F3 U+03C3 sigma
|
||||
!F4 U+03C4 tau
|
||||
!F5 U+03C5 upsilon
|
||||
!F6 U+03C6 phi
|
||||
!F7 U+03C7 chi
|
||||
!F8 U+03C8 psi
|
||||
!F9 U+03C9 omega
|
||||
!FA U+03CA iotadieresis
|
||||
!FB U+03CB upsilondieresis
|
||||
!FC U+03CC omicrontonos
|
||||
!FD U+03CD upsilontonos
|
||||
!FE U+03CE omegatonos
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+20AC Euro
|
||||
!82 U+201A quotesinglbase
|
||||
!83 U+0192 florin
|
||||
!84 U+201E quotedblbase
|
||||
!85 U+2026 ellipsis
|
||||
!86 U+2020 dagger
|
||||
!87 U+2021 daggerdbl
|
||||
!88 U+02C6 circumflex
|
||||
!89 U+2030 perthousand
|
||||
!8A U+0160 Scaron
|
||||
!8B U+2039 guilsinglleft
|
||||
!8C U+0152 OE
|
||||
!91 U+2018 quoteleft
|
||||
!92 U+2019 quoteright
|
||||
!93 U+201C quotedblleft
|
||||
!94 U+201D quotedblright
|
||||
!95 U+2022 bullet
|
||||
!96 U+2013 endash
|
||||
!97 U+2014 emdash
|
||||
!98 U+02DC tilde
|
||||
!99 U+2122 trademark
|
||||
!9A U+0161 scaron
|
||||
!9B U+203A guilsinglright
|
||||
!9C U+0153 oe
|
||||
!9F U+0178 Ydieresis
|
||||
!A0 U+00A0 space
|
||||
!A1 U+00A1 exclamdown
|
||||
!A2 U+00A2 cent
|
||||
!A3 U+00A3 sterling
|
||||
!A4 U+00A4 currency
|
||||
!A5 U+00A5 yen
|
||||
!A6 U+00A6 brokenbar
|
||||
!A7 U+00A7 section
|
||||
!A8 U+00A8 dieresis
|
||||
!A9 U+00A9 copyright
|
||||
!AA U+00AA ordfeminine
|
||||
!AB U+00AB guillemotleft
|
||||
!AC U+00AC logicalnot
|
||||
!AD U+00AD hyphen
|
||||
!AE U+00AE registered
|
||||
!AF U+00AF macron
|
||||
!B0 U+00B0 degree
|
||||
!B1 U+00B1 plusminus
|
||||
!B2 U+00B2 twosuperior
|
||||
!B3 U+00B3 threesuperior
|
||||
!B4 U+00B4 acute
|
||||
!B5 U+00B5 mu
|
||||
!B6 U+00B6 paragraph
|
||||
!B7 U+00B7 periodcentered
|
||||
!B8 U+00B8 cedilla
|
||||
!B9 U+00B9 onesuperior
|
||||
!BA U+00BA ordmasculine
|
||||
!BB U+00BB guillemotright
|
||||
!BC U+00BC onequarter
|
||||
!BD U+00BD onehalf
|
||||
!BE U+00BE threequarters
|
||||
!BF U+00BF questiondown
|
||||
!C0 U+00C0 Agrave
|
||||
!C1 U+00C1 Aacute
|
||||
!C2 U+00C2 Acircumflex
|
||||
!C3 U+00C3 Atilde
|
||||
!C4 U+00C4 Adieresis
|
||||
!C5 U+00C5 Aring
|
||||
!C6 U+00C6 AE
|
||||
!C7 U+00C7 Ccedilla
|
||||
!C8 U+00C8 Egrave
|
||||
!C9 U+00C9 Eacute
|
||||
!CA U+00CA Ecircumflex
|
||||
!CB U+00CB Edieresis
|
||||
!CC U+00CC Igrave
|
||||
!CD U+00CD Iacute
|
||||
!CE U+00CE Icircumflex
|
||||
!CF U+00CF Idieresis
|
||||
!D0 U+011E Gbreve
|
||||
!D1 U+00D1 Ntilde
|
||||
!D2 U+00D2 Ograve
|
||||
!D3 U+00D3 Oacute
|
||||
!D4 U+00D4 Ocircumflex
|
||||
!D5 U+00D5 Otilde
|
||||
!D6 U+00D6 Odieresis
|
||||
!D7 U+00D7 multiply
|
||||
!D8 U+00D8 Oslash
|
||||
!D9 U+00D9 Ugrave
|
||||
!DA U+00DA Uacute
|
||||
!DB U+00DB Ucircumflex
|
||||
!DC U+00DC Udieresis
|
||||
!DD U+0130 Idotaccent
|
||||
!DE U+015E Scedilla
|
||||
!DF U+00DF germandbls
|
||||
!E0 U+00E0 agrave
|
||||
!E1 U+00E1 aacute
|
||||
!E2 U+00E2 acircumflex
|
||||
!E3 U+00E3 atilde
|
||||
!E4 U+00E4 adieresis
|
||||
!E5 U+00E5 aring
|
||||
!E6 U+00E6 ae
|
||||
!E7 U+00E7 ccedilla
|
||||
!E8 U+00E8 egrave
|
||||
!E9 U+00E9 eacute
|
||||
!EA U+00EA ecircumflex
|
||||
!EB U+00EB edieresis
|
||||
!EC U+00EC igrave
|
||||
!ED U+00ED iacute
|
||||
!EE U+00EE icircumflex
|
||||
!EF U+00EF idieresis
|
||||
!F0 U+011F gbreve
|
||||
!F1 U+00F1 ntilde
|
||||
!F2 U+00F2 ograve
|
||||
!F3 U+00F3 oacute
|
||||
!F4 U+00F4 ocircumflex
|
||||
!F5 U+00F5 otilde
|
||||
!F6 U+00F6 odieresis
|
||||
!F7 U+00F7 divide
|
||||
!F8 U+00F8 oslash
|
||||
!F9 U+00F9 ugrave
|
||||
!FA U+00FA uacute
|
||||
!FB U+00FB ucircumflex
|
||||
!FC U+00FC udieresis
|
||||
!FD U+0131 dotlessi
|
||||
!FE U+015F scedilla
|
||||
!FF U+00FF ydieresis
|
||||
|
|
@ -1,233 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+20AC Euro
|
||||
!82 U+201A quotesinglbase
|
||||
!83 U+0192 florin
|
||||
!84 U+201E quotedblbase
|
||||
!85 U+2026 ellipsis
|
||||
!86 U+2020 dagger
|
||||
!87 U+2021 daggerdbl
|
||||
!88 U+02C6 circumflex
|
||||
!89 U+2030 perthousand
|
||||
!8B U+2039 guilsinglleft
|
||||
!91 U+2018 quoteleft
|
||||
!92 U+2019 quoteright
|
||||
!93 U+201C quotedblleft
|
||||
!94 U+201D quotedblright
|
||||
!95 U+2022 bullet
|
||||
!96 U+2013 endash
|
||||
!97 U+2014 emdash
|
||||
!98 U+02DC tilde
|
||||
!99 U+2122 trademark
|
||||
!9B U+203A guilsinglright
|
||||
!A0 U+00A0 space
|
||||
!A1 U+00A1 exclamdown
|
||||
!A2 U+00A2 cent
|
||||
!A3 U+00A3 sterling
|
||||
!A4 U+20AA afii57636
|
||||
!A5 U+00A5 yen
|
||||
!A6 U+00A6 brokenbar
|
||||
!A7 U+00A7 section
|
||||
!A8 U+00A8 dieresis
|
||||
!A9 U+00A9 copyright
|
||||
!AA U+00D7 multiply
|
||||
!AB U+00AB guillemotleft
|
||||
!AC U+00AC logicalnot
|
||||
!AD U+00AD sfthyphen
|
||||
!AE U+00AE registered
|
||||
!AF U+00AF macron
|
||||
!B0 U+00B0 degree
|
||||
!B1 U+00B1 plusminus
|
||||
!B2 U+00B2 twosuperior
|
||||
!B3 U+00B3 threesuperior
|
||||
!B4 U+00B4 acute
|
||||
!B5 U+00B5 mu
|
||||
!B6 U+00B6 paragraph
|
||||
!B7 U+00B7 middot
|
||||
!B8 U+00B8 cedilla
|
||||
!B9 U+00B9 onesuperior
|
||||
!BA U+00F7 divide
|
||||
!BB U+00BB guillemotright
|
||||
!BC U+00BC onequarter
|
||||
!BD U+00BD onehalf
|
||||
!BE U+00BE threequarters
|
||||
!BF U+00BF questiondown
|
||||
!C0 U+05B0 afii57799
|
||||
!C1 U+05B1 afii57801
|
||||
!C2 U+05B2 afii57800
|
||||
!C3 U+05B3 afii57802
|
||||
!C4 U+05B4 afii57793
|
||||
!C5 U+05B5 afii57794
|
||||
!C6 U+05B6 afii57795
|
||||
!C7 U+05B7 afii57798
|
||||
!C8 U+05B8 afii57797
|
||||
!C9 U+05B9 afii57806
|
||||
!CB U+05BB afii57796
|
||||
!CC U+05BC afii57807
|
||||
!CD U+05BD afii57839
|
||||
!CE U+05BE afii57645
|
||||
!CF U+05BF afii57841
|
||||
!D0 U+05C0 afii57842
|
||||
!D1 U+05C1 afii57804
|
||||
!D2 U+05C2 afii57803
|
||||
!D3 U+05C3 afii57658
|
||||
!D4 U+05F0 afii57716
|
||||
!D5 U+05F1 afii57717
|
||||
!D6 U+05F2 afii57718
|
||||
!D7 U+05F3 gereshhebrew
|
||||
!D8 U+05F4 gershayimhebrew
|
||||
!E0 U+05D0 afii57664
|
||||
!E1 U+05D1 afii57665
|
||||
!E2 U+05D2 afii57666
|
||||
!E3 U+05D3 afii57667
|
||||
!E4 U+05D4 afii57668
|
||||
!E5 U+05D5 afii57669
|
||||
!E6 U+05D6 afii57670
|
||||
!E7 U+05D7 afii57671
|
||||
!E8 U+05D8 afii57672
|
||||
!E9 U+05D9 afii57673
|
||||
!EA U+05DA afii57674
|
||||
!EB U+05DB afii57675
|
||||
!EC U+05DC afii57676
|
||||
!ED U+05DD afii57677
|
||||
!EE U+05DE afii57678
|
||||
!EF U+05DF afii57679
|
||||
!F0 U+05E0 afii57680
|
||||
!F1 U+05E1 afii57681
|
||||
!F2 U+05E2 afii57682
|
||||
!F3 U+05E3 afii57683
|
||||
!F4 U+05E4 afii57684
|
||||
!F5 U+05E5 afii57685
|
||||
!F6 U+05E6 afii57686
|
||||
!F7 U+05E7 afii57687
|
||||
!F8 U+05E8 afii57688
|
||||
!F9 U+05E9 afii57689
|
||||
!FA U+05EA afii57690
|
||||
!FD U+200E afii299
|
||||
!FE U+200F afii300
|
||||
|
|
@ -1,244 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+20AC Euro
|
||||
!82 U+201A quotesinglbase
|
||||
!84 U+201E quotedblbase
|
||||
!85 U+2026 ellipsis
|
||||
!86 U+2020 dagger
|
||||
!87 U+2021 daggerdbl
|
||||
!89 U+2030 perthousand
|
||||
!8B U+2039 guilsinglleft
|
||||
!8D U+00A8 dieresis
|
||||
!8E U+02C7 caron
|
||||
!8F U+00B8 cedilla
|
||||
!91 U+2018 quoteleft
|
||||
!92 U+2019 quoteright
|
||||
!93 U+201C quotedblleft
|
||||
!94 U+201D quotedblright
|
||||
!95 U+2022 bullet
|
||||
!96 U+2013 endash
|
||||
!97 U+2014 emdash
|
||||
!99 U+2122 trademark
|
||||
!9B U+203A guilsinglright
|
||||
!9D U+00AF macron
|
||||
!9E U+02DB ogonek
|
||||
!A0 U+00A0 space
|
||||
!A2 U+00A2 cent
|
||||
!A3 U+00A3 sterling
|
||||
!A4 U+00A4 currency
|
||||
!A6 U+00A6 brokenbar
|
||||
!A7 U+00A7 section
|
||||
!A8 U+00D8 Oslash
|
||||
!A9 U+00A9 copyright
|
||||
!AA U+0156 Rcommaaccent
|
||||
!AB U+00AB guillemotleft
|
||||
!AC U+00AC logicalnot
|
||||
!AD U+00AD hyphen
|
||||
!AE U+00AE registered
|
||||
!AF U+00C6 AE
|
||||
!B0 U+00B0 degree
|
||||
!B1 U+00B1 plusminus
|
||||
!B2 U+00B2 twosuperior
|
||||
!B3 U+00B3 threesuperior
|
||||
!B4 U+00B4 acute
|
||||
!B5 U+00B5 mu
|
||||
!B6 U+00B6 paragraph
|
||||
!B7 U+00B7 periodcentered
|
||||
!B8 U+00F8 oslash
|
||||
!B9 U+00B9 onesuperior
|
||||
!BA U+0157 rcommaaccent
|
||||
!BB U+00BB guillemotright
|
||||
!BC U+00BC onequarter
|
||||
!BD U+00BD onehalf
|
||||
!BE U+00BE threequarters
|
||||
!BF U+00E6 ae
|
||||
!C0 U+0104 Aogonek
|
||||
!C1 U+012E Iogonek
|
||||
!C2 U+0100 Amacron
|
||||
!C3 U+0106 Cacute
|
||||
!C4 U+00C4 Adieresis
|
||||
!C5 U+00C5 Aring
|
||||
!C6 U+0118 Eogonek
|
||||
!C7 U+0112 Emacron
|
||||
!C8 U+010C Ccaron
|
||||
!C9 U+00C9 Eacute
|
||||
!CA U+0179 Zacute
|
||||
!CB U+0116 Edotaccent
|
||||
!CC U+0122 Gcommaaccent
|
||||
!CD U+0136 Kcommaaccent
|
||||
!CE U+012A Imacron
|
||||
!CF U+013B Lcommaaccent
|
||||
!D0 U+0160 Scaron
|
||||
!D1 U+0143 Nacute
|
||||
!D2 U+0145 Ncommaaccent
|
||||
!D3 U+00D3 Oacute
|
||||
!D4 U+014C Omacron
|
||||
!D5 U+00D5 Otilde
|
||||
!D6 U+00D6 Odieresis
|
||||
!D7 U+00D7 multiply
|
||||
!D8 U+0172 Uogonek
|
||||
!D9 U+0141 Lslash
|
||||
!DA U+015A Sacute
|
||||
!DB U+016A Umacron
|
||||
!DC U+00DC Udieresis
|
||||
!DD U+017B Zdotaccent
|
||||
!DE U+017D Zcaron
|
||||
!DF U+00DF germandbls
|
||||
!E0 U+0105 aogonek
|
||||
!E1 U+012F iogonek
|
||||
!E2 U+0101 amacron
|
||||
!E3 U+0107 cacute
|
||||
!E4 U+00E4 adieresis
|
||||
!E5 U+00E5 aring
|
||||
!E6 U+0119 eogonek
|
||||
!E7 U+0113 emacron
|
||||
!E8 U+010D ccaron
|
||||
!E9 U+00E9 eacute
|
||||
!EA U+017A zacute
|
||||
!EB U+0117 edotaccent
|
||||
!EC U+0123 gcommaaccent
|
||||
!ED U+0137 kcommaaccent
|
||||
!EE U+012B imacron
|
||||
!EF U+013C lcommaaccent
|
||||
!F0 U+0161 scaron
|
||||
!F1 U+0144 nacute
|
||||
!F2 U+0146 ncommaaccent
|
||||
!F3 U+00F3 oacute
|
||||
!F4 U+014D omacron
|
||||
!F5 U+00F5 otilde
|
||||
!F6 U+00F6 odieresis
|
||||
!F7 U+00F7 divide
|
||||
!F8 U+0173 uogonek
|
||||
!F9 U+0142 lslash
|
||||
!FA U+015B sacute
|
||||
!FB U+016B umacron
|
||||
!FC U+00FC udieresis
|
||||
!FD U+017C zdotaccent
|
||||
!FE U+017E zcaron
|
||||
!FF U+02D9 dotaccent
|
||||
|
|
@ -1,247 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+20AC Euro
|
||||
!82 U+201A quotesinglbase
|
||||
!83 U+0192 florin
|
||||
!84 U+201E quotedblbase
|
||||
!85 U+2026 ellipsis
|
||||
!86 U+2020 dagger
|
||||
!87 U+2021 daggerdbl
|
||||
!88 U+02C6 circumflex
|
||||
!89 U+2030 perthousand
|
||||
!8B U+2039 guilsinglleft
|
||||
!8C U+0152 OE
|
||||
!91 U+2018 quoteleft
|
||||
!92 U+2019 quoteright
|
||||
!93 U+201C quotedblleft
|
||||
!94 U+201D quotedblright
|
||||
!95 U+2022 bullet
|
||||
!96 U+2013 endash
|
||||
!97 U+2014 emdash
|
||||
!98 U+02DC tilde
|
||||
!99 U+2122 trademark
|
||||
!9B U+203A guilsinglright
|
||||
!9C U+0153 oe
|
||||
!9F U+0178 Ydieresis
|
||||
!A0 U+00A0 space
|
||||
!A1 U+00A1 exclamdown
|
||||
!A2 U+00A2 cent
|
||||
!A3 U+00A3 sterling
|
||||
!A4 U+00A4 currency
|
||||
!A5 U+00A5 yen
|
||||
!A6 U+00A6 brokenbar
|
||||
!A7 U+00A7 section
|
||||
!A8 U+00A8 dieresis
|
||||
!A9 U+00A9 copyright
|
||||
!AA U+00AA ordfeminine
|
||||
!AB U+00AB guillemotleft
|
||||
!AC U+00AC logicalnot
|
||||
!AD U+00AD hyphen
|
||||
!AE U+00AE registered
|
||||
!AF U+00AF macron
|
||||
!B0 U+00B0 degree
|
||||
!B1 U+00B1 plusminus
|
||||
!B2 U+00B2 twosuperior
|
||||
!B3 U+00B3 threesuperior
|
||||
!B4 U+00B4 acute
|
||||
!B5 U+00B5 mu
|
||||
!B6 U+00B6 paragraph
|
||||
!B7 U+00B7 periodcentered
|
||||
!B8 U+00B8 cedilla
|
||||
!B9 U+00B9 onesuperior
|
||||
!BA U+00BA ordmasculine
|
||||
!BB U+00BB guillemotright
|
||||
!BC U+00BC onequarter
|
||||
!BD U+00BD onehalf
|
||||
!BE U+00BE threequarters
|
||||
!BF U+00BF questiondown
|
||||
!C0 U+00C0 Agrave
|
||||
!C1 U+00C1 Aacute
|
||||
!C2 U+00C2 Acircumflex
|
||||
!C3 U+0102 Abreve
|
||||
!C4 U+00C4 Adieresis
|
||||
!C5 U+00C5 Aring
|
||||
!C6 U+00C6 AE
|
||||
!C7 U+00C7 Ccedilla
|
||||
!C8 U+00C8 Egrave
|
||||
!C9 U+00C9 Eacute
|
||||
!CA U+00CA Ecircumflex
|
||||
!CB U+00CB Edieresis
|
||||
!CC U+0300 gravecomb
|
||||
!CD U+00CD Iacute
|
||||
!CE U+00CE Icircumflex
|
||||
!CF U+00CF Idieresis
|
||||
!D0 U+0110 Dcroat
|
||||
!D1 U+00D1 Ntilde
|
||||
!D2 U+0309 hookabovecomb
|
||||
!D3 U+00D3 Oacute
|
||||
!D4 U+00D4 Ocircumflex
|
||||
!D5 U+01A0 Ohorn
|
||||
!D6 U+00D6 Odieresis
|
||||
!D7 U+00D7 multiply
|
||||
!D8 U+00D8 Oslash
|
||||
!D9 U+00D9 Ugrave
|
||||
!DA U+00DA Uacute
|
||||
!DB U+00DB Ucircumflex
|
||||
!DC U+00DC Udieresis
|
||||
!DD U+01AF Uhorn
|
||||
!DE U+0303 tildecomb
|
||||
!DF U+00DF germandbls
|
||||
!E0 U+00E0 agrave
|
||||
!E1 U+00E1 aacute
|
||||
!E2 U+00E2 acircumflex
|
||||
!E3 U+0103 abreve
|
||||
!E4 U+00E4 adieresis
|
||||
!E5 U+00E5 aring
|
||||
!E6 U+00E6 ae
|
||||
!E7 U+00E7 ccedilla
|
||||
!E8 U+00E8 egrave
|
||||
!E9 U+00E9 eacute
|
||||
!EA U+00EA ecircumflex
|
||||
!EB U+00EB edieresis
|
||||
!EC U+0301 acutecomb
|
||||
!ED U+00ED iacute
|
||||
!EE U+00EE icircumflex
|
||||
!EF U+00EF idieresis
|
||||
!F0 U+0111 dcroat
|
||||
!F1 U+00F1 ntilde
|
||||
!F2 U+0323 dotbelowcomb
|
||||
!F3 U+00F3 oacute
|
||||
!F4 U+00F4 ocircumflex
|
||||
!F5 U+01A1 ohorn
|
||||
!F6 U+00F6 odieresis
|
||||
!F7 U+00F7 divide
|
||||
!F8 U+00F8 oslash
|
||||
!F9 U+00F9 ugrave
|
||||
!FA U+00FA uacute
|
||||
!FB U+00FB ucircumflex
|
||||
!FC U+00FC udieresis
|
||||
!FD U+01B0 uhorn
|
||||
!FE U+20AB dong
|
||||
!FF U+00FF ydieresis
|
||||
|
|
@ -1,225 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+20AC Euro
|
||||
!85 U+2026 ellipsis
|
||||
!91 U+2018 quoteleft
|
||||
!92 U+2019 quoteright
|
||||
!93 U+201C quotedblleft
|
||||
!94 U+201D quotedblright
|
||||
!95 U+2022 bullet
|
||||
!96 U+2013 endash
|
||||
!97 U+2014 emdash
|
||||
!A0 U+00A0 space
|
||||
!A1 U+0E01 kokaithai
|
||||
!A2 U+0E02 khokhaithai
|
||||
!A3 U+0E03 khokhuatthai
|
||||
!A4 U+0E04 khokhwaithai
|
||||
!A5 U+0E05 khokhonthai
|
||||
!A6 U+0E06 khorakhangthai
|
||||
!A7 U+0E07 ngonguthai
|
||||
!A8 U+0E08 chochanthai
|
||||
!A9 U+0E09 chochingthai
|
||||
!AA U+0E0A chochangthai
|
||||
!AB U+0E0B sosothai
|
||||
!AC U+0E0C chochoethai
|
||||
!AD U+0E0D yoyingthai
|
||||
!AE U+0E0E dochadathai
|
||||
!AF U+0E0F topatakthai
|
||||
!B0 U+0E10 thothanthai
|
||||
!B1 U+0E11 thonangmonthothai
|
||||
!B2 U+0E12 thophuthaothai
|
||||
!B3 U+0E13 nonenthai
|
||||
!B4 U+0E14 dodekthai
|
||||
!B5 U+0E15 totaothai
|
||||
!B6 U+0E16 thothungthai
|
||||
!B7 U+0E17 thothahanthai
|
||||
!B8 U+0E18 thothongthai
|
||||
!B9 U+0E19 nonuthai
|
||||
!BA U+0E1A bobaimaithai
|
||||
!BB U+0E1B poplathai
|
||||
!BC U+0E1C phophungthai
|
||||
!BD U+0E1D fofathai
|
||||
!BE U+0E1E phophanthai
|
||||
!BF U+0E1F fofanthai
|
||||
!C0 U+0E20 phosamphaothai
|
||||
!C1 U+0E21 momathai
|
||||
!C2 U+0E22 yoyakthai
|
||||
!C3 U+0E23 roruathai
|
||||
!C4 U+0E24 ruthai
|
||||
!C5 U+0E25 lolingthai
|
||||
!C6 U+0E26 luthai
|
||||
!C7 U+0E27 wowaenthai
|
||||
!C8 U+0E28 sosalathai
|
||||
!C9 U+0E29 sorusithai
|
||||
!CA U+0E2A sosuathai
|
||||
!CB U+0E2B hohipthai
|
||||
!CC U+0E2C lochulathai
|
||||
!CD U+0E2D oangthai
|
||||
!CE U+0E2E honokhukthai
|
||||
!CF U+0E2F paiyannoithai
|
||||
!D0 U+0E30 saraathai
|
||||
!D1 U+0E31 maihanakatthai
|
||||
!D2 U+0E32 saraaathai
|
||||
!D3 U+0E33 saraamthai
|
||||
!D4 U+0E34 saraithai
|
||||
!D5 U+0E35 saraiithai
|
||||
!D6 U+0E36 sarauethai
|
||||
!D7 U+0E37 saraueethai
|
||||
!D8 U+0E38 sarauthai
|
||||
!D9 U+0E39 sarauuthai
|
||||
!DA U+0E3A phinthuthai
|
||||
!DF U+0E3F bahtthai
|
||||
!E0 U+0E40 saraethai
|
||||
!E1 U+0E41 saraaethai
|
||||
!E2 U+0E42 saraothai
|
||||
!E3 U+0E43 saraaimaimuanthai
|
||||
!E4 U+0E44 saraaimaimalaithai
|
||||
!E5 U+0E45 lakkhangyaothai
|
||||
!E6 U+0E46 maiyamokthai
|
||||
!E7 U+0E47 maitaikhuthai
|
||||
!E8 U+0E48 maiekthai
|
||||
!E9 U+0E49 maithothai
|
||||
!EA U+0E4A maitrithai
|
||||
!EB U+0E4B maichattawathai
|
||||
!EC U+0E4C thanthakhatthai
|
||||
!ED U+0E4D nikhahitthai
|
||||
!EE U+0E4E yamakkanthai
|
||||
!EF U+0E4F fongmanthai
|
||||
!F0 U+0E50 zerothai
|
||||
!F1 U+0E51 onethai
|
||||
!F2 U+0E52 twothai
|
||||
!F3 U+0E53 threethai
|
||||
!F4 U+0E54 fourthai
|
||||
!F5 U+0E55 fivethai
|
||||
!F6 U+0E56 sixthai
|
||||
!F7 U+0E57 seventhai
|
||||
!F8 U+0E58 eightthai
|
||||
!F9 U+0E59 ninethai
|
||||
!FA U+0E5A angkhankhuthai
|
||||
!FB U+0E5B khomutthai
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+0080 .notdef
|
||||
!81 U+0081 .notdef
|
||||
!82 U+0082 .notdef
|
||||
!83 U+0083 .notdef
|
||||
!84 U+0084 .notdef
|
||||
!85 U+0085 .notdef
|
||||
!86 U+0086 .notdef
|
||||
!87 U+0087 .notdef
|
||||
!88 U+0088 .notdef
|
||||
!89 U+0089 .notdef
|
||||
!8A U+008A .notdef
|
||||
!8B U+008B .notdef
|
||||
!8C U+008C .notdef
|
||||
!8D U+008D .notdef
|
||||
!8E U+008E .notdef
|
||||
!8F U+008F .notdef
|
||||
!90 U+0090 .notdef
|
||||
!91 U+0091 .notdef
|
||||
!92 U+0092 .notdef
|
||||
!93 U+0093 .notdef
|
||||
!94 U+0094 .notdef
|
||||
!95 U+0095 .notdef
|
||||
!96 U+0096 .notdef
|
||||
!97 U+0097 .notdef
|
||||
!98 U+0098 .notdef
|
||||
!99 U+0099 .notdef
|
||||
!9A U+009A .notdef
|
||||
!9B U+009B .notdef
|
||||
!9C U+009C .notdef
|
||||
!9D U+009D .notdef
|
||||
!9E U+009E .notdef
|
||||
!9F U+009F .notdef
|
||||
!A0 U+00A0 space
|
||||
!A1 U+00A1 exclamdown
|
||||
!A2 U+00A2 cent
|
||||
!A3 U+00A3 sterling
|
||||
!A4 U+00A4 currency
|
||||
!A5 U+00A5 yen
|
||||
!A6 U+00A6 brokenbar
|
||||
!A7 U+00A7 section
|
||||
!A8 U+00A8 dieresis
|
||||
!A9 U+00A9 copyright
|
||||
!AA U+00AA ordfeminine
|
||||
!AB U+00AB guillemotleft
|
||||
!AC U+00AC logicalnot
|
||||
!AD U+00AD hyphen
|
||||
!AE U+00AE registered
|
||||
!AF U+00AF macron
|
||||
!B0 U+00B0 degree
|
||||
!B1 U+00B1 plusminus
|
||||
!B2 U+00B2 twosuperior
|
||||
!B3 U+00B3 threesuperior
|
||||
!B4 U+00B4 acute
|
||||
!B5 U+00B5 mu
|
||||
!B6 U+00B6 paragraph
|
||||
!B7 U+00B7 periodcentered
|
||||
!B8 U+00B8 cedilla
|
||||
!B9 U+00B9 onesuperior
|
||||
!BA U+00BA ordmasculine
|
||||
!BB U+00BB guillemotright
|
||||
!BC U+00BC onequarter
|
||||
!BD U+00BD onehalf
|
||||
!BE U+00BE threequarters
|
||||
!BF U+00BF questiondown
|
||||
!C0 U+00C0 Agrave
|
||||
!C1 U+00C1 Aacute
|
||||
!C2 U+00C2 Acircumflex
|
||||
!C3 U+00C3 Atilde
|
||||
!C4 U+00C4 Adieresis
|
||||
!C5 U+00C5 Aring
|
||||
!C6 U+00C6 AE
|
||||
!C7 U+00C7 Ccedilla
|
||||
!C8 U+00C8 Egrave
|
||||
!C9 U+00C9 Eacute
|
||||
!CA U+00CA Ecircumflex
|
||||
!CB U+00CB Edieresis
|
||||
!CC U+00CC Igrave
|
||||
!CD U+00CD Iacute
|
||||
!CE U+00CE Icircumflex
|
||||
!CF U+00CF Idieresis
|
||||
!D0 U+00D0 Eth
|
||||
!D1 U+00D1 Ntilde
|
||||
!D2 U+00D2 Ograve
|
||||
!D3 U+00D3 Oacute
|
||||
!D4 U+00D4 Ocircumflex
|
||||
!D5 U+00D5 Otilde
|
||||
!D6 U+00D6 Odieresis
|
||||
!D7 U+00D7 multiply
|
||||
!D8 U+00D8 Oslash
|
||||
!D9 U+00D9 Ugrave
|
||||
!DA U+00DA Uacute
|
||||
!DB U+00DB Ucircumflex
|
||||
!DC U+00DC Udieresis
|
||||
!DD U+00DD Yacute
|
||||
!DE U+00DE Thorn
|
||||
!DF U+00DF germandbls
|
||||
!E0 U+00E0 agrave
|
||||
!E1 U+00E1 aacute
|
||||
!E2 U+00E2 acircumflex
|
||||
!E3 U+00E3 atilde
|
||||
!E4 U+00E4 adieresis
|
||||
!E5 U+00E5 aring
|
||||
!E6 U+00E6 ae
|
||||
!E7 U+00E7 ccedilla
|
||||
!E8 U+00E8 egrave
|
||||
!E9 U+00E9 eacute
|
||||
!EA U+00EA ecircumflex
|
||||
!EB U+00EB edieresis
|
||||
!EC U+00EC igrave
|
||||
!ED U+00ED iacute
|
||||
!EE U+00EE icircumflex
|
||||
!EF U+00EF idieresis
|
||||
!F0 U+00F0 eth
|
||||
!F1 U+00F1 ntilde
|
||||
!F2 U+00F2 ograve
|
||||
!F3 U+00F3 oacute
|
||||
!F4 U+00F4 ocircumflex
|
||||
!F5 U+00F5 otilde
|
||||
!F6 U+00F6 odieresis
|
||||
!F7 U+00F7 divide
|
||||
!F8 U+00F8 oslash
|
||||
!F9 U+00F9 ugrave
|
||||
!FA U+00FA uacute
|
||||
!FB U+00FB ucircumflex
|
||||
!FC U+00FC udieresis
|
||||
!FD U+00FD yacute
|
||||
!FE U+00FE thorn
|
||||
!FF U+00FF ydieresis
|
||||
|
|
@ -1,248 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+0080 .notdef
|
||||
!81 U+0081 .notdef
|
||||
!82 U+0082 .notdef
|
||||
!83 U+0083 .notdef
|
||||
!84 U+0084 .notdef
|
||||
!85 U+0085 .notdef
|
||||
!86 U+0086 .notdef
|
||||
!87 U+0087 .notdef
|
||||
!88 U+0088 .notdef
|
||||
!89 U+0089 .notdef
|
||||
!8A U+008A .notdef
|
||||
!8B U+008B .notdef
|
||||
!8C U+008C .notdef
|
||||
!8D U+008D .notdef
|
||||
!8E U+008E .notdef
|
||||
!8F U+008F .notdef
|
||||
!90 U+0090 .notdef
|
||||
!91 U+0091 .notdef
|
||||
!92 U+0092 .notdef
|
||||
!93 U+0093 .notdef
|
||||
!94 U+0094 .notdef
|
||||
!95 U+0095 .notdef
|
||||
!96 U+0096 .notdef
|
||||
!97 U+0097 .notdef
|
||||
!98 U+0098 .notdef
|
||||
!99 U+0099 .notdef
|
||||
!9A U+009A .notdef
|
||||
!9B U+009B .notdef
|
||||
!9C U+009C .notdef
|
||||
!9D U+009D .notdef
|
||||
!9E U+009E .notdef
|
||||
!9F U+009F .notdef
|
||||
!A0 U+00A0 space
|
||||
!A1 U+0E01 kokaithai
|
||||
!A2 U+0E02 khokhaithai
|
||||
!A3 U+0E03 khokhuatthai
|
||||
!A4 U+0E04 khokhwaithai
|
||||
!A5 U+0E05 khokhonthai
|
||||
!A6 U+0E06 khorakhangthai
|
||||
!A7 U+0E07 ngonguthai
|
||||
!A8 U+0E08 chochanthai
|
||||
!A9 U+0E09 chochingthai
|
||||
!AA U+0E0A chochangthai
|
||||
!AB U+0E0B sosothai
|
||||
!AC U+0E0C chochoethai
|
||||
!AD U+0E0D yoyingthai
|
||||
!AE U+0E0E dochadathai
|
||||
!AF U+0E0F topatakthai
|
||||
!B0 U+0E10 thothanthai
|
||||
!B1 U+0E11 thonangmonthothai
|
||||
!B2 U+0E12 thophuthaothai
|
||||
!B3 U+0E13 nonenthai
|
||||
!B4 U+0E14 dodekthai
|
||||
!B5 U+0E15 totaothai
|
||||
!B6 U+0E16 thothungthai
|
||||
!B7 U+0E17 thothahanthai
|
||||
!B8 U+0E18 thothongthai
|
||||
!B9 U+0E19 nonuthai
|
||||
!BA U+0E1A bobaimaithai
|
||||
!BB U+0E1B poplathai
|
||||
!BC U+0E1C phophungthai
|
||||
!BD U+0E1D fofathai
|
||||
!BE U+0E1E phophanthai
|
||||
!BF U+0E1F fofanthai
|
||||
!C0 U+0E20 phosamphaothai
|
||||
!C1 U+0E21 momathai
|
||||
!C2 U+0E22 yoyakthai
|
||||
!C3 U+0E23 roruathai
|
||||
!C4 U+0E24 ruthai
|
||||
!C5 U+0E25 lolingthai
|
||||
!C6 U+0E26 luthai
|
||||
!C7 U+0E27 wowaenthai
|
||||
!C8 U+0E28 sosalathai
|
||||
!C9 U+0E29 sorusithai
|
||||
!CA U+0E2A sosuathai
|
||||
!CB U+0E2B hohipthai
|
||||
!CC U+0E2C lochulathai
|
||||
!CD U+0E2D oangthai
|
||||
!CE U+0E2E honokhukthai
|
||||
!CF U+0E2F paiyannoithai
|
||||
!D0 U+0E30 saraathai
|
||||
!D1 U+0E31 maihanakatthai
|
||||
!D2 U+0E32 saraaathai
|
||||
!D3 U+0E33 saraamthai
|
||||
!D4 U+0E34 saraithai
|
||||
!D5 U+0E35 saraiithai
|
||||
!D6 U+0E36 sarauethai
|
||||
!D7 U+0E37 saraueethai
|
||||
!D8 U+0E38 sarauthai
|
||||
!D9 U+0E39 sarauuthai
|
||||
!DA U+0E3A phinthuthai
|
||||
!DF U+0E3F bahtthai
|
||||
!E0 U+0E40 saraethai
|
||||
!E1 U+0E41 saraaethai
|
||||
!E2 U+0E42 saraothai
|
||||
!E3 U+0E43 saraaimaimuanthai
|
||||
!E4 U+0E44 saraaimaimalaithai
|
||||
!E5 U+0E45 lakkhangyaothai
|
||||
!E6 U+0E46 maiyamokthai
|
||||
!E7 U+0E47 maitaikhuthai
|
||||
!E8 U+0E48 maiekthai
|
||||
!E9 U+0E49 maithothai
|
||||
!EA U+0E4A maitrithai
|
||||
!EB U+0E4B maichattawathai
|
||||
!EC U+0E4C thanthakhatthai
|
||||
!ED U+0E4D nikhahitthai
|
||||
!EE U+0E4E yamakkanthai
|
||||
!EF U+0E4F fongmanthai
|
||||
!F0 U+0E50 zerothai
|
||||
!F1 U+0E51 onethai
|
||||
!F2 U+0E52 twothai
|
||||
!F3 U+0E53 threethai
|
||||
!F4 U+0E54 fourthai
|
||||
!F5 U+0E55 fivethai
|
||||
!F6 U+0E56 sixthai
|
||||
!F7 U+0E57 seventhai
|
||||
!F8 U+0E58 eightthai
|
||||
!F9 U+0E59 ninethai
|
||||
!FA U+0E5A angkhankhuthai
|
||||
!FB U+0E5B khomutthai
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+0080 .notdef
|
||||
!81 U+0081 .notdef
|
||||
!82 U+0082 .notdef
|
||||
!83 U+0083 .notdef
|
||||
!84 U+0084 .notdef
|
||||
!85 U+0085 .notdef
|
||||
!86 U+0086 .notdef
|
||||
!87 U+0087 .notdef
|
||||
!88 U+0088 .notdef
|
||||
!89 U+0089 .notdef
|
||||
!8A U+008A .notdef
|
||||
!8B U+008B .notdef
|
||||
!8C U+008C .notdef
|
||||
!8D U+008D .notdef
|
||||
!8E U+008E .notdef
|
||||
!8F U+008F .notdef
|
||||
!90 U+0090 .notdef
|
||||
!91 U+0091 .notdef
|
||||
!92 U+0092 .notdef
|
||||
!93 U+0093 .notdef
|
||||
!94 U+0094 .notdef
|
||||
!95 U+0095 .notdef
|
||||
!96 U+0096 .notdef
|
||||
!97 U+0097 .notdef
|
||||
!98 U+0098 .notdef
|
||||
!99 U+0099 .notdef
|
||||
!9A U+009A .notdef
|
||||
!9B U+009B .notdef
|
||||
!9C U+009C .notdef
|
||||
!9D U+009D .notdef
|
||||
!9E U+009E .notdef
|
||||
!9F U+009F .notdef
|
||||
!A0 U+00A0 space
|
||||
!A1 U+00A1 exclamdown
|
||||
!A2 U+00A2 cent
|
||||
!A3 U+00A3 sterling
|
||||
!A4 U+20AC Euro
|
||||
!A5 U+00A5 yen
|
||||
!A6 U+0160 Scaron
|
||||
!A7 U+00A7 section
|
||||
!A8 U+0161 scaron
|
||||
!A9 U+00A9 copyright
|
||||
!AA U+00AA ordfeminine
|
||||
!AB U+00AB guillemotleft
|
||||
!AC U+00AC logicalnot
|
||||
!AD U+00AD hyphen
|
||||
!AE U+00AE registered
|
||||
!AF U+00AF macron
|
||||
!B0 U+00B0 degree
|
||||
!B1 U+00B1 plusminus
|
||||
!B2 U+00B2 twosuperior
|
||||
!B3 U+00B3 threesuperior
|
||||
!B4 U+017D Zcaron
|
||||
!B5 U+00B5 mu
|
||||
!B6 U+00B6 paragraph
|
||||
!B7 U+00B7 periodcentered
|
||||
!B8 U+017E zcaron
|
||||
!B9 U+00B9 onesuperior
|
||||
!BA U+00BA ordmasculine
|
||||
!BB U+00BB guillemotright
|
||||
!BC U+0152 OE
|
||||
!BD U+0153 oe
|
||||
!BE U+0178 Ydieresis
|
||||
!BF U+00BF questiondown
|
||||
!C0 U+00C0 Agrave
|
||||
!C1 U+00C1 Aacute
|
||||
!C2 U+00C2 Acircumflex
|
||||
!C3 U+00C3 Atilde
|
||||
!C4 U+00C4 Adieresis
|
||||
!C5 U+00C5 Aring
|
||||
!C6 U+00C6 AE
|
||||
!C7 U+00C7 Ccedilla
|
||||
!C8 U+00C8 Egrave
|
||||
!C9 U+00C9 Eacute
|
||||
!CA U+00CA Ecircumflex
|
||||
!CB U+00CB Edieresis
|
||||
!CC U+00CC Igrave
|
||||
!CD U+00CD Iacute
|
||||
!CE U+00CE Icircumflex
|
||||
!CF U+00CF Idieresis
|
||||
!D0 U+00D0 Eth
|
||||
!D1 U+00D1 Ntilde
|
||||
!D2 U+00D2 Ograve
|
||||
!D3 U+00D3 Oacute
|
||||
!D4 U+00D4 Ocircumflex
|
||||
!D5 U+00D5 Otilde
|
||||
!D6 U+00D6 Odieresis
|
||||
!D7 U+00D7 multiply
|
||||
!D8 U+00D8 Oslash
|
||||
!D9 U+00D9 Ugrave
|
||||
!DA U+00DA Uacute
|
||||
!DB U+00DB Ucircumflex
|
||||
!DC U+00DC Udieresis
|
||||
!DD U+00DD Yacute
|
||||
!DE U+00DE Thorn
|
||||
!DF U+00DF germandbls
|
||||
!E0 U+00E0 agrave
|
||||
!E1 U+00E1 aacute
|
||||
!E2 U+00E2 acircumflex
|
||||
!E3 U+00E3 atilde
|
||||
!E4 U+00E4 adieresis
|
||||
!E5 U+00E5 aring
|
||||
!E6 U+00E6 ae
|
||||
!E7 U+00E7 ccedilla
|
||||
!E8 U+00E8 egrave
|
||||
!E9 U+00E9 eacute
|
||||
!EA U+00EA ecircumflex
|
||||
!EB U+00EB edieresis
|
||||
!EC U+00EC igrave
|
||||
!ED U+00ED iacute
|
||||
!EE U+00EE icircumflex
|
||||
!EF U+00EF idieresis
|
||||
!F0 U+00F0 eth
|
||||
!F1 U+00F1 ntilde
|
||||
!F2 U+00F2 ograve
|
||||
!F3 U+00F3 oacute
|
||||
!F4 U+00F4 ocircumflex
|
||||
!F5 U+00F5 otilde
|
||||
!F6 U+00F6 odieresis
|
||||
!F7 U+00F7 divide
|
||||
!F8 U+00F8 oslash
|
||||
!F9 U+00F9 ugrave
|
||||
!FA U+00FA uacute
|
||||
!FB U+00FB ucircumflex
|
||||
!FC U+00FC udieresis
|
||||
!FD U+00FD yacute
|
||||
!FE U+00FE thorn
|
||||
!FF U+00FF ydieresis
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+0080 .notdef
|
||||
!81 U+0081 .notdef
|
||||
!82 U+0082 .notdef
|
||||
!83 U+0083 .notdef
|
||||
!84 U+0084 .notdef
|
||||
!85 U+0085 .notdef
|
||||
!86 U+0086 .notdef
|
||||
!87 U+0087 .notdef
|
||||
!88 U+0088 .notdef
|
||||
!89 U+0089 .notdef
|
||||
!8A U+008A .notdef
|
||||
!8B U+008B .notdef
|
||||
!8C U+008C .notdef
|
||||
!8D U+008D .notdef
|
||||
!8E U+008E .notdef
|
||||
!8F U+008F .notdef
|
||||
!90 U+0090 .notdef
|
||||
!91 U+0091 .notdef
|
||||
!92 U+0092 .notdef
|
||||
!93 U+0093 .notdef
|
||||
!94 U+0094 .notdef
|
||||
!95 U+0095 .notdef
|
||||
!96 U+0096 .notdef
|
||||
!97 U+0097 .notdef
|
||||
!98 U+0098 .notdef
|
||||
!99 U+0099 .notdef
|
||||
!9A U+009A .notdef
|
||||
!9B U+009B .notdef
|
||||
!9C U+009C .notdef
|
||||
!9D U+009D .notdef
|
||||
!9E U+009E .notdef
|
||||
!9F U+009F .notdef
|
||||
!A0 U+00A0 space
|
||||
!A1 U+0104 Aogonek
|
||||
!A2 U+0105 aogonek
|
||||
!A3 U+0141 Lslash
|
||||
!A4 U+20AC Euro
|
||||
!A5 U+201E quotedblbase
|
||||
!A6 U+0160 Scaron
|
||||
!A7 U+00A7 section
|
||||
!A8 U+0161 scaron
|
||||
!A9 U+00A9 copyright
|
||||
!AA U+0218 Scommaaccent
|
||||
!AB U+00AB guillemotleft
|
||||
!AC U+0179 Zacute
|
||||
!AD U+00AD hyphen
|
||||
!AE U+017A zacute
|
||||
!AF U+017B Zdotaccent
|
||||
!B0 U+00B0 degree
|
||||
!B1 U+00B1 plusminus
|
||||
!B2 U+010C Ccaron
|
||||
!B3 U+0142 lslash
|
||||
!B4 U+017D Zcaron
|
||||
!B5 U+201D quotedblright
|
||||
!B6 U+00B6 paragraph
|
||||
!B7 U+00B7 periodcentered
|
||||
!B8 U+017E zcaron
|
||||
!B9 U+010D ccaron
|
||||
!BA U+0219 scommaaccent
|
||||
!BB U+00BB guillemotright
|
||||
!BC U+0152 OE
|
||||
!BD U+0153 oe
|
||||
!BE U+0178 Ydieresis
|
||||
!BF U+017C zdotaccent
|
||||
!C0 U+00C0 Agrave
|
||||
!C1 U+00C1 Aacute
|
||||
!C2 U+00C2 Acircumflex
|
||||
!C3 U+0102 Abreve
|
||||
!C4 U+00C4 Adieresis
|
||||
!C5 U+0106 Cacute
|
||||
!C6 U+00C6 AE
|
||||
!C7 U+00C7 Ccedilla
|
||||
!C8 U+00C8 Egrave
|
||||
!C9 U+00C9 Eacute
|
||||
!CA U+00CA Ecircumflex
|
||||
!CB U+00CB Edieresis
|
||||
!CC U+00CC Igrave
|
||||
!CD U+00CD Iacute
|
||||
!CE U+00CE Icircumflex
|
||||
!CF U+00CF Idieresis
|
||||
!D0 U+0110 Dcroat
|
||||
!D1 U+0143 Nacute
|
||||
!D2 U+00D2 Ograve
|
||||
!D3 U+00D3 Oacute
|
||||
!D4 U+00D4 Ocircumflex
|
||||
!D5 U+0150 Ohungarumlaut
|
||||
!D6 U+00D6 Odieresis
|
||||
!D7 U+015A Sacute
|
||||
!D8 U+0170 Uhungarumlaut
|
||||
!D9 U+00D9 Ugrave
|
||||
!DA U+00DA Uacute
|
||||
!DB U+00DB Ucircumflex
|
||||
!DC U+00DC Udieresis
|
||||
!DD U+0118 Eogonek
|
||||
!DE U+021A Tcommaaccent
|
||||
!DF U+00DF germandbls
|
||||
!E0 U+00E0 agrave
|
||||
!E1 U+00E1 aacute
|
||||
!E2 U+00E2 acircumflex
|
||||
!E3 U+0103 abreve
|
||||
!E4 U+00E4 adieresis
|
||||
!E5 U+0107 cacute
|
||||
!E6 U+00E6 ae
|
||||
!E7 U+00E7 ccedilla
|
||||
!E8 U+00E8 egrave
|
||||
!E9 U+00E9 eacute
|
||||
!EA U+00EA ecircumflex
|
||||
!EB U+00EB edieresis
|
||||
!EC U+00EC igrave
|
||||
!ED U+00ED iacute
|
||||
!EE U+00EE icircumflex
|
||||
!EF U+00EF idieresis
|
||||
!F0 U+0111 dcroat
|
||||
!F1 U+0144 nacute
|
||||
!F2 U+00F2 ograve
|
||||
!F3 U+00F3 oacute
|
||||
!F4 U+00F4 ocircumflex
|
||||
!F5 U+0151 ohungarumlaut
|
||||
!F6 U+00F6 odieresis
|
||||
!F7 U+015B sacute
|
||||
!F8 U+0171 uhungarumlaut
|
||||
!F9 U+00F9 ugrave
|
||||
!FA U+00FA uacute
|
||||
!FB U+00FB ucircumflex
|
||||
!FC U+00FC udieresis
|
||||
!FD U+0119 eogonek
|
||||
!FE U+021B tcommaaccent
|
||||
!FF U+00FF ydieresis
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+0080 .notdef
|
||||
!81 U+0081 .notdef
|
||||
!82 U+0082 .notdef
|
||||
!83 U+0083 .notdef
|
||||
!84 U+0084 .notdef
|
||||
!85 U+0085 .notdef
|
||||
!86 U+0086 .notdef
|
||||
!87 U+0087 .notdef
|
||||
!88 U+0088 .notdef
|
||||
!89 U+0089 .notdef
|
||||
!8A U+008A .notdef
|
||||
!8B U+008B .notdef
|
||||
!8C U+008C .notdef
|
||||
!8D U+008D .notdef
|
||||
!8E U+008E .notdef
|
||||
!8F U+008F .notdef
|
||||
!90 U+0090 .notdef
|
||||
!91 U+0091 .notdef
|
||||
!92 U+0092 .notdef
|
||||
!93 U+0093 .notdef
|
||||
!94 U+0094 .notdef
|
||||
!95 U+0095 .notdef
|
||||
!96 U+0096 .notdef
|
||||
!97 U+0097 .notdef
|
||||
!98 U+0098 .notdef
|
||||
!99 U+0099 .notdef
|
||||
!9A U+009A .notdef
|
||||
!9B U+009B .notdef
|
||||
!9C U+009C .notdef
|
||||
!9D U+009D .notdef
|
||||
!9E U+009E .notdef
|
||||
!9F U+009F .notdef
|
||||
!A0 U+00A0 space
|
||||
!A1 U+0104 Aogonek
|
||||
!A2 U+02D8 breve
|
||||
!A3 U+0141 Lslash
|
||||
!A4 U+00A4 currency
|
||||
!A5 U+013D Lcaron
|
||||
!A6 U+015A Sacute
|
||||
!A7 U+00A7 section
|
||||
!A8 U+00A8 dieresis
|
||||
!A9 U+0160 Scaron
|
||||
!AA U+015E Scedilla
|
||||
!AB U+0164 Tcaron
|
||||
!AC U+0179 Zacute
|
||||
!AD U+00AD hyphen
|
||||
!AE U+017D Zcaron
|
||||
!AF U+017B Zdotaccent
|
||||
!B0 U+00B0 degree
|
||||
!B1 U+0105 aogonek
|
||||
!B2 U+02DB ogonek
|
||||
!B3 U+0142 lslash
|
||||
!B4 U+00B4 acute
|
||||
!B5 U+013E lcaron
|
||||
!B6 U+015B sacute
|
||||
!B7 U+02C7 caron
|
||||
!B8 U+00B8 cedilla
|
||||
!B9 U+0161 scaron
|
||||
!BA U+015F scedilla
|
||||
!BB U+0165 tcaron
|
||||
!BC U+017A zacute
|
||||
!BD U+02DD hungarumlaut
|
||||
!BE U+017E zcaron
|
||||
!BF U+017C zdotaccent
|
||||
!C0 U+0154 Racute
|
||||
!C1 U+00C1 Aacute
|
||||
!C2 U+00C2 Acircumflex
|
||||
!C3 U+0102 Abreve
|
||||
!C4 U+00C4 Adieresis
|
||||
!C5 U+0139 Lacute
|
||||
!C6 U+0106 Cacute
|
||||
!C7 U+00C7 Ccedilla
|
||||
!C8 U+010C Ccaron
|
||||
!C9 U+00C9 Eacute
|
||||
!CA U+0118 Eogonek
|
||||
!CB U+00CB Edieresis
|
||||
!CC U+011A Ecaron
|
||||
!CD U+00CD Iacute
|
||||
!CE U+00CE Icircumflex
|
||||
!CF U+010E Dcaron
|
||||
!D0 U+0110 Dcroat
|
||||
!D1 U+0143 Nacute
|
||||
!D2 U+0147 Ncaron
|
||||
!D3 U+00D3 Oacute
|
||||
!D4 U+00D4 Ocircumflex
|
||||
!D5 U+0150 Ohungarumlaut
|
||||
!D6 U+00D6 Odieresis
|
||||
!D7 U+00D7 multiply
|
||||
!D8 U+0158 Rcaron
|
||||
!D9 U+016E Uring
|
||||
!DA U+00DA Uacute
|
||||
!DB U+0170 Uhungarumlaut
|
||||
!DC U+00DC Udieresis
|
||||
!DD U+00DD Yacute
|
||||
!DE U+0162 Tcommaaccent
|
||||
!DF U+00DF germandbls
|
||||
!E0 U+0155 racute
|
||||
!E1 U+00E1 aacute
|
||||
!E2 U+00E2 acircumflex
|
||||
!E3 U+0103 abreve
|
||||
!E4 U+00E4 adieresis
|
||||
!E5 U+013A lacute
|
||||
!E6 U+0107 cacute
|
||||
!E7 U+00E7 ccedilla
|
||||
!E8 U+010D ccaron
|
||||
!E9 U+00E9 eacute
|
||||
!EA U+0119 eogonek
|
||||
!EB U+00EB edieresis
|
||||
!EC U+011B ecaron
|
||||
!ED U+00ED iacute
|
||||
!EE U+00EE icircumflex
|
||||
!EF U+010F dcaron
|
||||
!F0 U+0111 dcroat
|
||||
!F1 U+0144 nacute
|
||||
!F2 U+0148 ncaron
|
||||
!F3 U+00F3 oacute
|
||||
!F4 U+00F4 ocircumflex
|
||||
!F5 U+0151 ohungarumlaut
|
||||
!F6 U+00F6 odieresis
|
||||
!F7 U+00F7 divide
|
||||
!F8 U+0159 rcaron
|
||||
!F9 U+016F uring
|
||||
!FA U+00FA uacute
|
||||
!FB U+0171 uhungarumlaut
|
||||
!FC U+00FC udieresis
|
||||
!FD U+00FD yacute
|
||||
!FE U+0163 tcommaaccent
|
||||
!FF U+02D9 dotaccent
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+0080 .notdef
|
||||
!81 U+0081 .notdef
|
||||
!82 U+0082 .notdef
|
||||
!83 U+0083 .notdef
|
||||
!84 U+0084 .notdef
|
||||
!85 U+0085 .notdef
|
||||
!86 U+0086 .notdef
|
||||
!87 U+0087 .notdef
|
||||
!88 U+0088 .notdef
|
||||
!89 U+0089 .notdef
|
||||
!8A U+008A .notdef
|
||||
!8B U+008B .notdef
|
||||
!8C U+008C .notdef
|
||||
!8D U+008D .notdef
|
||||
!8E U+008E .notdef
|
||||
!8F U+008F .notdef
|
||||
!90 U+0090 .notdef
|
||||
!91 U+0091 .notdef
|
||||
!92 U+0092 .notdef
|
||||
!93 U+0093 .notdef
|
||||
!94 U+0094 .notdef
|
||||
!95 U+0095 .notdef
|
||||
!96 U+0096 .notdef
|
||||
!97 U+0097 .notdef
|
||||
!98 U+0098 .notdef
|
||||
!99 U+0099 .notdef
|
||||
!9A U+009A .notdef
|
||||
!9B U+009B .notdef
|
||||
!9C U+009C .notdef
|
||||
!9D U+009D .notdef
|
||||
!9E U+009E .notdef
|
||||
!9F U+009F .notdef
|
||||
!A0 U+00A0 space
|
||||
!A1 U+0104 Aogonek
|
||||
!A2 U+0138 kgreenlandic
|
||||
!A3 U+0156 Rcommaaccent
|
||||
!A4 U+00A4 currency
|
||||
!A5 U+0128 Itilde
|
||||
!A6 U+013B Lcommaaccent
|
||||
!A7 U+00A7 section
|
||||
!A8 U+00A8 dieresis
|
||||
!A9 U+0160 Scaron
|
||||
!AA U+0112 Emacron
|
||||
!AB U+0122 Gcommaaccent
|
||||
!AC U+0166 Tbar
|
||||
!AD U+00AD hyphen
|
||||
!AE U+017D Zcaron
|
||||
!AF U+00AF macron
|
||||
!B0 U+00B0 degree
|
||||
!B1 U+0105 aogonek
|
||||
!B2 U+02DB ogonek
|
||||
!B3 U+0157 rcommaaccent
|
||||
!B4 U+00B4 acute
|
||||
!B5 U+0129 itilde
|
||||
!B6 U+013C lcommaaccent
|
||||
!B7 U+02C7 caron
|
||||
!B8 U+00B8 cedilla
|
||||
!B9 U+0161 scaron
|
||||
!BA U+0113 emacron
|
||||
!BB U+0123 gcommaaccent
|
||||
!BC U+0167 tbar
|
||||
!BD U+014A Eng
|
||||
!BE U+017E zcaron
|
||||
!BF U+014B eng
|
||||
!C0 U+0100 Amacron
|
||||
!C1 U+00C1 Aacute
|
||||
!C2 U+00C2 Acircumflex
|
||||
!C3 U+00C3 Atilde
|
||||
!C4 U+00C4 Adieresis
|
||||
!C5 U+00C5 Aring
|
||||
!C6 U+00C6 AE
|
||||
!C7 U+012E Iogonek
|
||||
!C8 U+010C Ccaron
|
||||
!C9 U+00C9 Eacute
|
||||
!CA U+0118 Eogonek
|
||||
!CB U+00CB Edieresis
|
||||
!CC U+0116 Edotaccent
|
||||
!CD U+00CD Iacute
|
||||
!CE U+00CE Icircumflex
|
||||
!CF U+012A Imacron
|
||||
!D0 U+0110 Dcroat
|
||||
!D1 U+0145 Ncommaaccent
|
||||
!D2 U+014C Omacron
|
||||
!D3 U+0136 Kcommaaccent
|
||||
!D4 U+00D4 Ocircumflex
|
||||
!D5 U+00D5 Otilde
|
||||
!D6 U+00D6 Odieresis
|
||||
!D7 U+00D7 multiply
|
||||
!D8 U+00D8 Oslash
|
||||
!D9 U+0172 Uogonek
|
||||
!DA U+00DA Uacute
|
||||
!DB U+00DB Ucircumflex
|
||||
!DC U+00DC Udieresis
|
||||
!DD U+0168 Utilde
|
||||
!DE U+016A Umacron
|
||||
!DF U+00DF germandbls
|
||||
!E0 U+0101 amacron
|
||||
!E1 U+00E1 aacute
|
||||
!E2 U+00E2 acircumflex
|
||||
!E3 U+00E3 atilde
|
||||
!E4 U+00E4 adieresis
|
||||
!E5 U+00E5 aring
|
||||
!E6 U+00E6 ae
|
||||
!E7 U+012F iogonek
|
||||
!E8 U+010D ccaron
|
||||
!E9 U+00E9 eacute
|
||||
!EA U+0119 eogonek
|
||||
!EB U+00EB edieresis
|
||||
!EC U+0117 edotaccent
|
||||
!ED U+00ED iacute
|
||||
!EE U+00EE icircumflex
|
||||
!EF U+012B imacron
|
||||
!F0 U+0111 dcroat
|
||||
!F1 U+0146 ncommaaccent
|
||||
!F2 U+014D omacron
|
||||
!F3 U+0137 kcommaaccent
|
||||
!F4 U+00F4 ocircumflex
|
||||
!F5 U+00F5 otilde
|
||||
!F6 U+00F6 odieresis
|
||||
!F7 U+00F7 divide
|
||||
!F8 U+00F8 oslash
|
||||
!F9 U+0173 uogonek
|
||||
!FA U+00FA uacute
|
||||
!FB U+00FB ucircumflex
|
||||
!FC U+00FC udieresis
|
||||
!FD U+0169 utilde
|
||||
!FE U+016B umacron
|
||||
!FF U+02D9 dotaccent
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+0080 .notdef
|
||||
!81 U+0081 .notdef
|
||||
!82 U+0082 .notdef
|
||||
!83 U+0083 .notdef
|
||||
!84 U+0084 .notdef
|
||||
!85 U+0085 .notdef
|
||||
!86 U+0086 .notdef
|
||||
!87 U+0087 .notdef
|
||||
!88 U+0088 .notdef
|
||||
!89 U+0089 .notdef
|
||||
!8A U+008A .notdef
|
||||
!8B U+008B .notdef
|
||||
!8C U+008C .notdef
|
||||
!8D U+008D .notdef
|
||||
!8E U+008E .notdef
|
||||
!8F U+008F .notdef
|
||||
!90 U+0090 .notdef
|
||||
!91 U+0091 .notdef
|
||||
!92 U+0092 .notdef
|
||||
!93 U+0093 .notdef
|
||||
!94 U+0094 .notdef
|
||||
!95 U+0095 .notdef
|
||||
!96 U+0096 .notdef
|
||||
!97 U+0097 .notdef
|
||||
!98 U+0098 .notdef
|
||||
!99 U+0099 .notdef
|
||||
!9A U+009A .notdef
|
||||
!9B U+009B .notdef
|
||||
!9C U+009C .notdef
|
||||
!9D U+009D .notdef
|
||||
!9E U+009E .notdef
|
||||
!9F U+009F .notdef
|
||||
!A0 U+00A0 space
|
||||
!A1 U+0401 afii10023
|
||||
!A2 U+0402 afii10051
|
||||
!A3 U+0403 afii10052
|
||||
!A4 U+0404 afii10053
|
||||
!A5 U+0405 afii10054
|
||||
!A6 U+0406 afii10055
|
||||
!A7 U+0407 afii10056
|
||||
!A8 U+0408 afii10057
|
||||
!A9 U+0409 afii10058
|
||||
!AA U+040A afii10059
|
||||
!AB U+040B afii10060
|
||||
!AC U+040C afii10061
|
||||
!AD U+00AD hyphen
|
||||
!AE U+040E afii10062
|
||||
!AF U+040F afii10145
|
||||
!B0 U+0410 afii10017
|
||||
!B1 U+0411 afii10018
|
||||
!B2 U+0412 afii10019
|
||||
!B3 U+0413 afii10020
|
||||
!B4 U+0414 afii10021
|
||||
!B5 U+0415 afii10022
|
||||
!B6 U+0416 afii10024
|
||||
!B7 U+0417 afii10025
|
||||
!B8 U+0418 afii10026
|
||||
!B9 U+0419 afii10027
|
||||
!BA U+041A afii10028
|
||||
!BB U+041B afii10029
|
||||
!BC U+041C afii10030
|
||||
!BD U+041D afii10031
|
||||
!BE U+041E afii10032
|
||||
!BF U+041F afii10033
|
||||
!C0 U+0420 afii10034
|
||||
!C1 U+0421 afii10035
|
||||
!C2 U+0422 afii10036
|
||||
!C3 U+0423 afii10037
|
||||
!C4 U+0424 afii10038
|
||||
!C5 U+0425 afii10039
|
||||
!C6 U+0426 afii10040
|
||||
!C7 U+0427 afii10041
|
||||
!C8 U+0428 afii10042
|
||||
!C9 U+0429 afii10043
|
||||
!CA U+042A afii10044
|
||||
!CB U+042B afii10045
|
||||
!CC U+042C afii10046
|
||||
!CD U+042D afii10047
|
||||
!CE U+042E afii10048
|
||||
!CF U+042F afii10049
|
||||
!D0 U+0430 afii10065
|
||||
!D1 U+0431 afii10066
|
||||
!D2 U+0432 afii10067
|
||||
!D3 U+0433 afii10068
|
||||
!D4 U+0434 afii10069
|
||||
!D5 U+0435 afii10070
|
||||
!D6 U+0436 afii10072
|
||||
!D7 U+0437 afii10073
|
||||
!D8 U+0438 afii10074
|
||||
!D9 U+0439 afii10075
|
||||
!DA U+043A afii10076
|
||||
!DB U+043B afii10077
|
||||
!DC U+043C afii10078
|
||||
!DD U+043D afii10079
|
||||
!DE U+043E afii10080
|
||||
!DF U+043F afii10081
|
||||
!E0 U+0440 afii10082
|
||||
!E1 U+0441 afii10083
|
||||
!E2 U+0442 afii10084
|
||||
!E3 U+0443 afii10085
|
||||
!E4 U+0444 afii10086
|
||||
!E5 U+0445 afii10087
|
||||
!E6 U+0446 afii10088
|
||||
!E7 U+0447 afii10089
|
||||
!E8 U+0448 afii10090
|
||||
!E9 U+0449 afii10091
|
||||
!EA U+044A afii10092
|
||||
!EB U+044B afii10093
|
||||
!EC U+044C afii10094
|
||||
!ED U+044D afii10095
|
||||
!EE U+044E afii10096
|
||||
!EF U+044F afii10097
|
||||
!F0 U+2116 afii61352
|
||||
!F1 U+0451 afii10071
|
||||
!F2 U+0452 afii10099
|
||||
!F3 U+0453 afii10100
|
||||
!F4 U+0454 afii10101
|
||||
!F5 U+0455 afii10102
|
||||
!F6 U+0456 afii10103
|
||||
!F7 U+0457 afii10104
|
||||
!F8 U+0458 afii10105
|
||||
!F9 U+0459 afii10106
|
||||
!FA U+045A afii10107
|
||||
!FB U+045B afii10108
|
||||
!FC U+045C afii10109
|
||||
!FD U+00A7 section
|
||||
!FE U+045E afii10110
|
||||
!FF U+045F afii10193
|
||||
|
|
@ -1,250 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+0080 .notdef
|
||||
!81 U+0081 .notdef
|
||||
!82 U+0082 .notdef
|
||||
!83 U+0083 .notdef
|
||||
!84 U+0084 .notdef
|
||||
!85 U+0085 .notdef
|
||||
!86 U+0086 .notdef
|
||||
!87 U+0087 .notdef
|
||||
!88 U+0088 .notdef
|
||||
!89 U+0089 .notdef
|
||||
!8A U+008A .notdef
|
||||
!8B U+008B .notdef
|
||||
!8C U+008C .notdef
|
||||
!8D U+008D .notdef
|
||||
!8E U+008E .notdef
|
||||
!8F U+008F .notdef
|
||||
!90 U+0090 .notdef
|
||||
!91 U+0091 .notdef
|
||||
!92 U+0092 .notdef
|
||||
!93 U+0093 .notdef
|
||||
!94 U+0094 .notdef
|
||||
!95 U+0095 .notdef
|
||||
!96 U+0096 .notdef
|
||||
!97 U+0097 .notdef
|
||||
!98 U+0098 .notdef
|
||||
!99 U+0099 .notdef
|
||||
!9A U+009A .notdef
|
||||
!9B U+009B .notdef
|
||||
!9C U+009C .notdef
|
||||
!9D U+009D .notdef
|
||||
!9E U+009E .notdef
|
||||
!9F U+009F .notdef
|
||||
!A0 U+00A0 space
|
||||
!A1 U+2018 quoteleft
|
||||
!A2 U+2019 quoteright
|
||||
!A3 U+00A3 sterling
|
||||
!A6 U+00A6 brokenbar
|
||||
!A7 U+00A7 section
|
||||
!A8 U+00A8 dieresis
|
||||
!A9 U+00A9 copyright
|
||||
!AB U+00AB guillemotleft
|
||||
!AC U+00AC logicalnot
|
||||
!AD U+00AD hyphen
|
||||
!AF U+2015 afii00208
|
||||
!B0 U+00B0 degree
|
||||
!B1 U+00B1 plusminus
|
||||
!B2 U+00B2 twosuperior
|
||||
!B3 U+00B3 threesuperior
|
||||
!B4 U+0384 tonos
|
||||
!B5 U+0385 dieresistonos
|
||||
!B6 U+0386 Alphatonos
|
||||
!B7 U+00B7 periodcentered
|
||||
!B8 U+0388 Epsilontonos
|
||||
!B9 U+0389 Etatonos
|
||||
!BA U+038A Iotatonos
|
||||
!BB U+00BB guillemotright
|
||||
!BC U+038C Omicrontonos
|
||||
!BD U+00BD onehalf
|
||||
!BE U+038E Upsilontonos
|
||||
!BF U+038F Omegatonos
|
||||
!C0 U+0390 iotadieresistonos
|
||||
!C1 U+0391 Alpha
|
||||
!C2 U+0392 Beta
|
||||
!C3 U+0393 Gamma
|
||||
!C4 U+0394 Delta
|
||||
!C5 U+0395 Epsilon
|
||||
!C6 U+0396 Zeta
|
||||
!C7 U+0397 Eta
|
||||
!C8 U+0398 Theta
|
||||
!C9 U+0399 Iota
|
||||
!CA U+039A Kappa
|
||||
!CB U+039B Lambda
|
||||
!CC U+039C Mu
|
||||
!CD U+039D Nu
|
||||
!CE U+039E Xi
|
||||
!CF U+039F Omicron
|
||||
!D0 U+03A0 Pi
|
||||
!D1 U+03A1 Rho
|
||||
!D3 U+03A3 Sigma
|
||||
!D4 U+03A4 Tau
|
||||
!D5 U+03A5 Upsilon
|
||||
!D6 U+03A6 Phi
|
||||
!D7 U+03A7 Chi
|
||||
!D8 U+03A8 Psi
|
||||
!D9 U+03A9 Omega
|
||||
!DA U+03AA Iotadieresis
|
||||
!DB U+03AB Upsilondieresis
|
||||
!DC U+03AC alphatonos
|
||||
!DD U+03AD epsilontonos
|
||||
!DE U+03AE etatonos
|
||||
!DF U+03AF iotatonos
|
||||
!E0 U+03B0 upsilondieresistonos
|
||||
!E1 U+03B1 alpha
|
||||
!E2 U+03B2 beta
|
||||
!E3 U+03B3 gamma
|
||||
!E4 U+03B4 delta
|
||||
!E5 U+03B5 epsilon
|
||||
!E6 U+03B6 zeta
|
||||
!E7 U+03B7 eta
|
||||
!E8 U+03B8 theta
|
||||
!E9 U+03B9 iota
|
||||
!EA U+03BA kappa
|
||||
!EB U+03BB lambda
|
||||
!EC U+03BC mu
|
||||
!ED U+03BD nu
|
||||
!EE U+03BE xi
|
||||
!EF U+03BF omicron
|
||||
!F0 U+03C0 pi
|
||||
!F1 U+03C1 rho
|
||||
!F2 U+03C2 sigma1
|
||||
!F3 U+03C3 sigma
|
||||
!F4 U+03C4 tau
|
||||
!F5 U+03C5 upsilon
|
||||
!F6 U+03C6 phi
|
||||
!F7 U+03C7 chi
|
||||
!F8 U+03C8 psi
|
||||
!F9 U+03C9 omega
|
||||
!FA U+03CA iotadieresis
|
||||
!FB U+03CB upsilondieresis
|
||||
!FC U+03CC omicrontonos
|
||||
!FD U+03CD upsilontonos
|
||||
!FE U+03CE omegatonos
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+0080 .notdef
|
||||
!81 U+0081 .notdef
|
||||
!82 U+0082 .notdef
|
||||
!83 U+0083 .notdef
|
||||
!84 U+0084 .notdef
|
||||
!85 U+0085 .notdef
|
||||
!86 U+0086 .notdef
|
||||
!87 U+0087 .notdef
|
||||
!88 U+0088 .notdef
|
||||
!89 U+0089 .notdef
|
||||
!8A U+008A .notdef
|
||||
!8B U+008B .notdef
|
||||
!8C U+008C .notdef
|
||||
!8D U+008D .notdef
|
||||
!8E U+008E .notdef
|
||||
!8F U+008F .notdef
|
||||
!90 U+0090 .notdef
|
||||
!91 U+0091 .notdef
|
||||
!92 U+0092 .notdef
|
||||
!93 U+0093 .notdef
|
||||
!94 U+0094 .notdef
|
||||
!95 U+0095 .notdef
|
||||
!96 U+0096 .notdef
|
||||
!97 U+0097 .notdef
|
||||
!98 U+0098 .notdef
|
||||
!99 U+0099 .notdef
|
||||
!9A U+009A .notdef
|
||||
!9B U+009B .notdef
|
||||
!9C U+009C .notdef
|
||||
!9D U+009D .notdef
|
||||
!9E U+009E .notdef
|
||||
!9F U+009F .notdef
|
||||
!A0 U+00A0 space
|
||||
!A1 U+00A1 exclamdown
|
||||
!A2 U+00A2 cent
|
||||
!A3 U+00A3 sterling
|
||||
!A4 U+00A4 currency
|
||||
!A5 U+00A5 yen
|
||||
!A6 U+00A6 brokenbar
|
||||
!A7 U+00A7 section
|
||||
!A8 U+00A8 dieresis
|
||||
!A9 U+00A9 copyright
|
||||
!AA U+00AA ordfeminine
|
||||
!AB U+00AB guillemotleft
|
||||
!AC U+00AC logicalnot
|
||||
!AD U+00AD hyphen
|
||||
!AE U+00AE registered
|
||||
!AF U+00AF macron
|
||||
!B0 U+00B0 degree
|
||||
!B1 U+00B1 plusminus
|
||||
!B2 U+00B2 twosuperior
|
||||
!B3 U+00B3 threesuperior
|
||||
!B4 U+00B4 acute
|
||||
!B5 U+00B5 mu
|
||||
!B6 U+00B6 paragraph
|
||||
!B7 U+00B7 periodcentered
|
||||
!B8 U+00B8 cedilla
|
||||
!B9 U+00B9 onesuperior
|
||||
!BA U+00BA ordmasculine
|
||||
!BB U+00BB guillemotright
|
||||
!BC U+00BC onequarter
|
||||
!BD U+00BD onehalf
|
||||
!BE U+00BE threequarters
|
||||
!BF U+00BF questiondown
|
||||
!C0 U+00C0 Agrave
|
||||
!C1 U+00C1 Aacute
|
||||
!C2 U+00C2 Acircumflex
|
||||
!C3 U+00C3 Atilde
|
||||
!C4 U+00C4 Adieresis
|
||||
!C5 U+00C5 Aring
|
||||
!C6 U+00C6 AE
|
||||
!C7 U+00C7 Ccedilla
|
||||
!C8 U+00C8 Egrave
|
||||
!C9 U+00C9 Eacute
|
||||
!CA U+00CA Ecircumflex
|
||||
!CB U+00CB Edieresis
|
||||
!CC U+00CC Igrave
|
||||
!CD U+00CD Iacute
|
||||
!CE U+00CE Icircumflex
|
||||
!CF U+00CF Idieresis
|
||||
!D0 U+011E Gbreve
|
||||
!D1 U+00D1 Ntilde
|
||||
!D2 U+00D2 Ograve
|
||||
!D3 U+00D3 Oacute
|
||||
!D4 U+00D4 Ocircumflex
|
||||
!D5 U+00D5 Otilde
|
||||
!D6 U+00D6 Odieresis
|
||||
!D7 U+00D7 multiply
|
||||
!D8 U+00D8 Oslash
|
||||
!D9 U+00D9 Ugrave
|
||||
!DA U+00DA Uacute
|
||||
!DB U+00DB Ucircumflex
|
||||
!DC U+00DC Udieresis
|
||||
!DD U+0130 Idotaccent
|
||||
!DE U+015E Scedilla
|
||||
!DF U+00DF germandbls
|
||||
!E0 U+00E0 agrave
|
||||
!E1 U+00E1 aacute
|
||||
!E2 U+00E2 acircumflex
|
||||
!E3 U+00E3 atilde
|
||||
!E4 U+00E4 adieresis
|
||||
!E5 U+00E5 aring
|
||||
!E6 U+00E6 ae
|
||||
!E7 U+00E7 ccedilla
|
||||
!E8 U+00E8 egrave
|
||||
!E9 U+00E9 eacute
|
||||
!EA U+00EA ecircumflex
|
||||
!EB U+00EB edieresis
|
||||
!EC U+00EC igrave
|
||||
!ED U+00ED iacute
|
||||
!EE U+00EE icircumflex
|
||||
!EF U+00EF idieresis
|
||||
!F0 U+011F gbreve
|
||||
!F1 U+00F1 ntilde
|
||||
!F2 U+00F2 ograve
|
||||
!F3 U+00F3 oacute
|
||||
!F4 U+00F4 ocircumflex
|
||||
!F5 U+00F5 otilde
|
||||
!F6 U+00F6 odieresis
|
||||
!F7 U+00F7 divide
|
||||
!F8 U+00F8 oslash
|
||||
!F9 U+00F9 ugrave
|
||||
!FA U+00FA uacute
|
||||
!FB U+00FB ucircumflex
|
||||
!FC U+00FC udieresis
|
||||
!FD U+0131 dotlessi
|
||||
!FE U+015F scedilla
|
||||
!FF U+00FF ydieresis
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+2500 SF100000
|
||||
!81 U+2502 SF110000
|
||||
!82 U+250C SF010000
|
||||
!83 U+2510 SF030000
|
||||
!84 U+2514 SF020000
|
||||
!85 U+2518 SF040000
|
||||
!86 U+251C SF080000
|
||||
!87 U+2524 SF090000
|
||||
!88 U+252C SF060000
|
||||
!89 U+2534 SF070000
|
||||
!8A U+253C SF050000
|
||||
!8B U+2580 upblock
|
||||
!8C U+2584 dnblock
|
||||
!8D U+2588 block
|
||||
!8E U+258C lfblock
|
||||
!8F U+2590 rtblock
|
||||
!90 U+2591 ltshade
|
||||
!91 U+2592 shade
|
||||
!92 U+2593 dkshade
|
||||
!93 U+2320 integraltp
|
||||
!94 U+25A0 filledbox
|
||||
!95 U+2219 periodcentered
|
||||
!96 U+221A radical
|
||||
!97 U+2248 approxequal
|
||||
!98 U+2264 lessequal
|
||||
!99 U+2265 greaterequal
|
||||
!9A U+00A0 space
|
||||
!9B U+2321 integralbt
|
||||
!9C U+00B0 degree
|
||||
!9D U+00B2 twosuperior
|
||||
!9E U+00B7 periodcentered
|
||||
!9F U+00F7 divide
|
||||
!A0 U+2550 SF430000
|
||||
!A1 U+2551 SF240000
|
||||
!A2 U+2552 SF510000
|
||||
!A3 U+0451 afii10071
|
||||
!A4 U+2553 SF520000
|
||||
!A5 U+2554 SF390000
|
||||
!A6 U+2555 SF220000
|
||||
!A7 U+2556 SF210000
|
||||
!A8 U+2557 SF250000
|
||||
!A9 U+2558 SF500000
|
||||
!AA U+2559 SF490000
|
||||
!AB U+255A SF380000
|
||||
!AC U+255B SF280000
|
||||
!AD U+255C SF270000
|
||||
!AE U+255D SF260000
|
||||
!AF U+255E SF360000
|
||||
!B0 U+255F SF370000
|
||||
!B1 U+2560 SF420000
|
||||
!B2 U+2561 SF190000
|
||||
!B3 U+0401 afii10023
|
||||
!B4 U+2562 SF200000
|
||||
!B5 U+2563 SF230000
|
||||
!B6 U+2564 SF470000
|
||||
!B7 U+2565 SF480000
|
||||
!B8 U+2566 SF410000
|
||||
!B9 U+2567 SF450000
|
||||
!BA U+2568 SF460000
|
||||
!BB U+2569 SF400000
|
||||
!BC U+256A SF540000
|
||||
!BD U+256B SF530000
|
||||
!BE U+256C SF440000
|
||||
!BF U+00A9 copyright
|
||||
!C0 U+044E afii10096
|
||||
!C1 U+0430 afii10065
|
||||
!C2 U+0431 afii10066
|
||||
!C3 U+0446 afii10088
|
||||
!C4 U+0434 afii10069
|
||||
!C5 U+0435 afii10070
|
||||
!C6 U+0444 afii10086
|
||||
!C7 U+0433 afii10068
|
||||
!C8 U+0445 afii10087
|
||||
!C9 U+0438 afii10074
|
||||
!CA U+0439 afii10075
|
||||
!CB U+043A afii10076
|
||||
!CC U+043B afii10077
|
||||
!CD U+043C afii10078
|
||||
!CE U+043D afii10079
|
||||
!CF U+043E afii10080
|
||||
!D0 U+043F afii10081
|
||||
!D1 U+044F afii10097
|
||||
!D2 U+0440 afii10082
|
||||
!D3 U+0441 afii10083
|
||||
!D4 U+0442 afii10084
|
||||
!D5 U+0443 afii10085
|
||||
!D6 U+0436 afii10072
|
||||
!D7 U+0432 afii10067
|
||||
!D8 U+044C afii10094
|
||||
!D9 U+044B afii10093
|
||||
!DA U+0437 afii10073
|
||||
!DB U+0448 afii10090
|
||||
!DC U+044D afii10095
|
||||
!DD U+0449 afii10091
|
||||
!DE U+0447 afii10089
|
||||
!DF U+044A afii10092
|
||||
!E0 U+042E afii10048
|
||||
!E1 U+0410 afii10017
|
||||
!E2 U+0411 afii10018
|
||||
!E3 U+0426 afii10040
|
||||
!E4 U+0414 afii10021
|
||||
!E5 U+0415 afii10022
|
||||
!E6 U+0424 afii10038
|
||||
!E7 U+0413 afii10020
|
||||
!E8 U+0425 afii10039
|
||||
!E9 U+0418 afii10026
|
||||
!EA U+0419 afii10027
|
||||
!EB U+041A afii10028
|
||||
!EC U+041B afii10029
|
||||
!ED U+041C afii10030
|
||||
!EE U+041D afii10031
|
||||
!EF U+041E afii10032
|
||||
!F0 U+041F afii10033
|
||||
!F1 U+042F afii10049
|
||||
!F2 U+0420 afii10034
|
||||
!F3 U+0421 afii10035
|
||||
!F4 U+0422 afii10036
|
||||
!F5 U+0423 afii10037
|
||||
!F6 U+0416 afii10024
|
||||
!F7 U+0412 afii10019
|
||||
!F8 U+042C afii10046
|
||||
!F9 U+042B afii10045
|
||||
!FA U+0417 afii10025
|
||||
!FB U+0428 afii10042
|
||||
!FC U+042D afii10047
|
||||
!FD U+0429 afii10043
|
||||
!FE U+0427 afii10041
|
||||
!FF U+042A afii10044
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
!00 U+0000 .notdef
|
||||
!01 U+0001 .notdef
|
||||
!02 U+0002 .notdef
|
||||
!03 U+0003 .notdef
|
||||
!04 U+0004 .notdef
|
||||
!05 U+0005 .notdef
|
||||
!06 U+0006 .notdef
|
||||
!07 U+0007 .notdef
|
||||
!08 U+0008 .notdef
|
||||
!09 U+0009 .notdef
|
||||
!0A U+000A .notdef
|
||||
!0B U+000B .notdef
|
||||
!0C U+000C .notdef
|
||||
!0D U+000D .notdef
|
||||
!0E U+000E .notdef
|
||||
!0F U+000F .notdef
|
||||
!10 U+0010 .notdef
|
||||
!11 U+0011 .notdef
|
||||
!12 U+0012 .notdef
|
||||
!13 U+0013 .notdef
|
||||
!14 U+0014 .notdef
|
||||
!15 U+0015 .notdef
|
||||
!16 U+0016 .notdef
|
||||
!17 U+0017 .notdef
|
||||
!18 U+0018 .notdef
|
||||
!19 U+0019 .notdef
|
||||
!1A U+001A .notdef
|
||||
!1B U+001B .notdef
|
||||
!1C U+001C .notdef
|
||||
!1D U+001D .notdef
|
||||
!1E U+001E .notdef
|
||||
!1F U+001F .notdef
|
||||
!20 U+0020 space
|
||||
!21 U+0021 exclam
|
||||
!22 U+0022 quotedbl
|
||||
!23 U+0023 numbersign
|
||||
!24 U+0024 dollar
|
||||
!25 U+0025 percent
|
||||
!26 U+0026 ampersand
|
||||
!27 U+0027 quotesingle
|
||||
!28 U+0028 parenleft
|
||||
!29 U+0029 parenright
|
||||
!2A U+002A asterisk
|
||||
!2B U+002B plus
|
||||
!2C U+002C comma
|
||||
!2D U+002D hyphen
|
||||
!2E U+002E period
|
||||
!2F U+002F slash
|
||||
!30 U+0030 zero
|
||||
!31 U+0031 one
|
||||
!32 U+0032 two
|
||||
!33 U+0033 three
|
||||
!34 U+0034 four
|
||||
!35 U+0035 five
|
||||
!36 U+0036 six
|
||||
!37 U+0037 seven
|
||||
!38 U+0038 eight
|
||||
!39 U+0039 nine
|
||||
!3A U+003A colon
|
||||
!3B U+003B semicolon
|
||||
!3C U+003C less
|
||||
!3D U+003D equal
|
||||
!3E U+003E greater
|
||||
!3F U+003F question
|
||||
!40 U+0040 at
|
||||
!41 U+0041 A
|
||||
!42 U+0042 B
|
||||
!43 U+0043 C
|
||||
!44 U+0044 D
|
||||
!45 U+0045 E
|
||||
!46 U+0046 F
|
||||
!47 U+0047 G
|
||||
!48 U+0048 H
|
||||
!49 U+0049 I
|
||||
!4A U+004A J
|
||||
!4B U+004B K
|
||||
!4C U+004C L
|
||||
!4D U+004D M
|
||||
!4E U+004E N
|
||||
!4F U+004F O
|
||||
!50 U+0050 P
|
||||
!51 U+0051 Q
|
||||
!52 U+0052 R
|
||||
!53 U+0053 S
|
||||
!54 U+0054 T
|
||||
!55 U+0055 U
|
||||
!56 U+0056 V
|
||||
!57 U+0057 W
|
||||
!58 U+0058 X
|
||||
!59 U+0059 Y
|
||||
!5A U+005A Z
|
||||
!5B U+005B bracketleft
|
||||
!5C U+005C backslash
|
||||
!5D U+005D bracketright
|
||||
!5E U+005E asciicircum
|
||||
!5F U+005F underscore
|
||||
!60 U+0060 grave
|
||||
!61 U+0061 a
|
||||
!62 U+0062 b
|
||||
!63 U+0063 c
|
||||
!64 U+0064 d
|
||||
!65 U+0065 e
|
||||
!66 U+0066 f
|
||||
!67 U+0067 g
|
||||
!68 U+0068 h
|
||||
!69 U+0069 i
|
||||
!6A U+006A j
|
||||
!6B U+006B k
|
||||
!6C U+006C l
|
||||
!6D U+006D m
|
||||
!6E U+006E n
|
||||
!6F U+006F o
|
||||
!70 U+0070 p
|
||||
!71 U+0071 q
|
||||
!72 U+0072 r
|
||||
!73 U+0073 s
|
||||
!74 U+0074 t
|
||||
!75 U+0075 u
|
||||
!76 U+0076 v
|
||||
!77 U+0077 w
|
||||
!78 U+0078 x
|
||||
!79 U+0079 y
|
||||
!7A U+007A z
|
||||
!7B U+007B braceleft
|
||||
!7C U+007C bar
|
||||
!7D U+007D braceright
|
||||
!7E U+007E asciitilde
|
||||
!7F U+007F .notdef
|
||||
!80 U+2500 SF100000
|
||||
!81 U+2502 SF110000
|
||||
!82 U+250C SF010000
|
||||
!83 U+2510 SF030000
|
||||
!84 U+2514 SF020000
|
||||
!85 U+2518 SF040000
|
||||
!86 U+251C SF080000
|
||||
!87 U+2524 SF090000
|
||||
!88 U+252C SF060000
|
||||
!89 U+2534 SF070000
|
||||
!8A U+253C SF050000
|
||||
!8B U+2580 upblock
|
||||
!8C U+2584 dnblock
|
||||
!8D U+2588 block
|
||||
!8E U+258C lfblock
|
||||
!8F U+2590 rtblock
|
||||
!90 U+2591 ltshade
|
||||
!91 U+2592 shade
|
||||
!92 U+2593 dkshade
|
||||
!93 U+2320 integraltp
|
||||
!94 U+25A0 filledbox
|
||||
!95 U+2022 bullet
|
||||
!96 U+221A radical
|
||||
!97 U+2248 approxequal
|
||||
!98 U+2264 lessequal
|
||||
!99 U+2265 greaterequal
|
||||
!9A U+00A0 space
|
||||
!9B U+2321 integralbt
|
||||
!9C U+00B0 degree
|
||||
!9D U+00B2 twosuperior
|
||||
!9E U+00B7 periodcentered
|
||||
!9F U+00F7 divide
|
||||
!A0 U+2550 SF430000
|
||||
!A1 U+2551 SF240000
|
||||
!A2 U+2552 SF510000
|
||||
!A3 U+0451 afii10071
|
||||
!A4 U+0454 afii10101
|
||||
!A5 U+2554 SF390000
|
||||
!A6 U+0456 afii10103
|
||||
!A7 U+0457 afii10104
|
||||
!A8 U+2557 SF250000
|
||||
!A9 U+2558 SF500000
|
||||
!AA U+2559 SF490000
|
||||
!AB U+255A SF380000
|
||||
!AC U+255B SF280000
|
||||
!AD U+0491 afii10098
|
||||
!AE U+255D SF260000
|
||||
!AF U+255E SF360000
|
||||
!B0 U+255F SF370000
|
||||
!B1 U+2560 SF420000
|
||||
!B2 U+2561 SF190000
|
||||
!B3 U+0401 afii10023
|
||||
!B4 U+0404 afii10053
|
||||
!B5 U+2563 SF230000
|
||||
!B6 U+0406 afii10055
|
||||
!B7 U+0407 afii10056
|
||||
!B8 U+2566 SF410000
|
||||
!B9 U+2567 SF450000
|
||||
!BA U+2568 SF460000
|
||||
!BB U+2569 SF400000
|
||||
!BC U+256A SF540000
|
||||
!BD U+0490 afii10050
|
||||
!BE U+256C SF440000
|
||||
!BF U+00A9 copyright
|
||||
!C0 U+044E afii10096
|
||||
!C1 U+0430 afii10065
|
||||
!C2 U+0431 afii10066
|
||||
!C3 U+0446 afii10088
|
||||
!C4 U+0434 afii10069
|
||||
!C5 U+0435 afii10070
|
||||
!C6 U+0444 afii10086
|
||||
!C7 U+0433 afii10068
|
||||
!C8 U+0445 afii10087
|
||||
!C9 U+0438 afii10074
|
||||
!CA U+0439 afii10075
|
||||
!CB U+043A afii10076
|
||||
!CC U+043B afii10077
|
||||
!CD U+043C afii10078
|
||||
!CE U+043D afii10079
|
||||
!CF U+043E afii10080
|
||||
!D0 U+043F afii10081
|
||||
!D1 U+044F afii10097
|
||||
!D2 U+0440 afii10082
|
||||
!D3 U+0441 afii10083
|
||||
!D4 U+0442 afii10084
|
||||
!D5 U+0443 afii10085
|
||||
!D6 U+0436 afii10072
|
||||
!D7 U+0432 afii10067
|
||||
!D8 U+044C afii10094
|
||||
!D9 U+044B afii10093
|
||||
!DA U+0437 afii10073
|
||||
!DB U+0448 afii10090
|
||||
!DC U+044D afii10095
|
||||
!DD U+0449 afii10091
|
||||
!DE U+0447 afii10089
|
||||
!DF U+044A afii10092
|
||||
!E0 U+042E afii10048
|
||||
!E1 U+0410 afii10017
|
||||
!E2 U+0411 afii10018
|
||||
!E3 U+0426 afii10040
|
||||
!E4 U+0414 afii10021
|
||||
!E5 U+0415 afii10022
|
||||
!E6 U+0424 afii10038
|
||||
!E7 U+0413 afii10020
|
||||
!E8 U+0425 afii10039
|
||||
!E9 U+0418 afii10026
|
||||
!EA U+0419 afii10027
|
||||
!EB U+041A afii10028
|
||||
!EC U+041B afii10029
|
||||
!ED U+041C afii10030
|
||||
!EE U+041D afii10031
|
||||
!EF U+041E afii10032
|
||||
!F0 U+041F afii10033
|
||||
!F1 U+042F afii10049
|
||||
!F2 U+0420 afii10034
|
||||
!F3 U+0421 afii10035
|
||||
!F4 U+0422 afii10036
|
||||
!F5 U+0423 afii10037
|
||||
!F6 U+0416 afii10024
|
||||
!F7 U+0412 afii10019
|
||||
!F8 U+042C afii10046
|
||||
!F9 U+042B afii10045
|
||||
!FA U+0417 afii10025
|
||||
!FB U+0428 afii10042
|
||||
!FC U+042D afii10047
|
||||
!FD U+0429 afii10043
|
||||
!FE U+0427 afii10041
|
||||
!FF U+042A afii10044
|
||||
|
|
@ -1,253 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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;
|
||||
|
||||
use FontLib\Table\Type\name;
|
||||
use FontLib\TrueType\File;
|
||||
|
||||
/**
|
||||
* Adobe Font Metrics file creation utility class.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class AdobeFontMetrics {
|
||||
private $f;
|
||||
|
||||
/**
|
||||
* @var File
|
||||
*/
|
||||
private $font;
|
||||
|
||||
function __construct(File $font) {
|
||||
$this->font = $font;
|
||||
}
|
||||
|
||||
function write($file, $encoding = null) {
|
||||
$map_data = array();
|
||||
|
||||
if ($encoding) {
|
||||
$encoding = preg_replace("/[^a-z0-9-_]/", "", $encoding);
|
||||
$map_file = dirname(__FILE__) . "/../../maps/$encoding.map";
|
||||
if (!file_exists($map_file)) {
|
||||
throw new \Exception("Unknown encoding ($encoding)");
|
||||
}
|
||||
|
||||
$map = new EncodingMap($map_file);
|
||||
$map_data = $map->parse();
|
||||
}
|
||||
|
||||
$this->f = fopen($file, "w+");
|
||||
|
||||
$font = $this->font;
|
||||
|
||||
$this->startSection("FontMetrics", 4.1);
|
||||
$this->addPair("Notice", "Converted by PHP-font-lib");
|
||||
$this->addPair("Comment", "https://github.com/dompdf/php-font-lib");
|
||||
|
||||
$encoding_scheme = ($encoding ? $encoding : "FontSpecific");
|
||||
$this->addPair("EncodingScheme", $encoding_scheme);
|
||||
|
||||
$records = $font->getData("name", "records");
|
||||
foreach ($records as $id => $record) {
|
||||
if (!isset(name::$nameIdCodes[$id]) || preg_match("/[\r\n]/", $record->string)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->addPair(name::$nameIdCodes[$id], $record->string);
|
||||
}
|
||||
|
||||
$os2 = $font->getData("OS/2");
|
||||
$this->addPair("Weight", ($os2["usWeightClass"] > 400 ? "Bold" : "Medium"));
|
||||
|
||||
$post = $font->getData("post");
|
||||
$this->addPair("ItalicAngle", $post["italicAngle"]);
|
||||
$this->addPair("IsFixedPitch", ($post["isFixedPitch"] ? "true" : "false"));
|
||||
$this->addPair("UnderlineThickness", $font->normalizeFUnit($post["underlineThickness"]));
|
||||
$this->addPair("UnderlinePosition", $font->normalizeFUnit($post["underlinePosition"]));
|
||||
|
||||
$hhea = $font->getData("hhea");
|
||||
|
||||
if (isset($hhea["ascent"])) {
|
||||
$this->addPair("FontHeightOffset", $font->normalizeFUnit($hhea["lineGap"]));
|
||||
}
|
||||
else {
|
||||
$this->addPair("FontHeightOffset", $font->normalizeFUnit($os2["typoLineGap"]));
|
||||
}
|
||||
|
||||
$glyf = $font->getData("glyf");
|
||||
$glyphIndexArray = $font->getUnicodeCharMap();
|
||||
$hasGlyphs = $glyf instanceof glyf && is_array($glyphIndexArray);
|
||||
|
||||
// capHeight is based on capital H
|
||||
if ($hasGlyphs && \array_key_exists(72, $glyphIndexArray)) {
|
||||
$upperH = $glyf[$glyphIndexArray[72]];
|
||||
$upperH->parseData();
|
||||
$this->addPair("CapHeight", $font->normalizeFUnit($upperH->yMax));
|
||||
}
|
||||
|
||||
// xHeight is based on lowercase x
|
||||
if ($hasGlyphs && \array_key_exists(120, $glyphIndexArray)) {
|
||||
$lowerX = $glyf[$glyphIndexArray[120]];
|
||||
$lowerX->parseData();
|
||||
$this->addPair("XHeight", $font->normalizeFUnit($lowerX->yMax));
|
||||
}
|
||||
|
||||
// ascender is based on lowercase d
|
||||
if ($hasGlyphs && \array_key_exists(100, $glyphIndexArray)) {
|
||||
$lowerD = $glyf[$glyphIndexArray[100]];
|
||||
$lowerD->parseData();
|
||||
$this->addPair("Ascender", $font->normalizeFUnit($lowerD->yMax));
|
||||
} elseif (isset($hhea["ascent"])) {
|
||||
$this->addPair("Ascender", $font->normalizeFUnit($hhea["ascent"]));
|
||||
}
|
||||
else {
|
||||
$this->addPair("Ascender", $font->normalizeFUnit($os2["typoAscender"]));
|
||||
}
|
||||
|
||||
// descender is based on lowercase p
|
||||
if ($hasGlyphs && \array_key_exists(112, $glyphIndexArray)) {
|
||||
$lowerP = $glyf[$glyphIndexArray[112]];
|
||||
$lowerP->parseData();
|
||||
$this->addPair("Descender", $font->normalizeFUnit($lowerP->yMin));
|
||||
} elseif (isset($hhea["descent"])) {
|
||||
$this->addPair("Descender", $font->normalizeFUnit($hhea["descent"]));
|
||||
}
|
||||
else {
|
||||
$this->addPair("Descender", -abs($font->normalizeFUnit($os2["typoDescender"])));
|
||||
}
|
||||
|
||||
$head = $font->getData("head");
|
||||
$this->addArray("FontBBox", array(
|
||||
$font->normalizeFUnit($head["xMin"]),
|
||||
$font->normalizeFUnit($head["yMin"]),
|
||||
$font->normalizeFUnit($head["xMax"]),
|
||||
$font->normalizeFUnit($head["yMax"]),
|
||||
));
|
||||
|
||||
if ($glyphIndexArray) {
|
||||
$hmtx = $font->getData("hmtx");
|
||||
$names = $font->getData("post", "names");
|
||||
|
||||
$this->startSection("CharMetrics", count($hmtx));
|
||||
|
||||
if ($encoding) {
|
||||
foreach ($map_data as $code => $value) {
|
||||
list($c, $name) = $value;
|
||||
|
||||
if (!isset($glyphIndexArray[$c])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$g = $glyphIndexArray[$c];
|
||||
|
||||
if (!isset($hmtx[$g])) {
|
||||
$hmtx[$g] = $hmtx[0];
|
||||
}
|
||||
|
||||
$this->addMetric(array(
|
||||
"C" => ($code > 255 ? -1 : $code),
|
||||
"WX" => $font->normalizeFUnit($hmtx[$g][0]),
|
||||
"N" => $name,
|
||||
));
|
||||
}
|
||||
}
|
||||
else {
|
||||
foreach ($glyphIndexArray as $c => $g) {
|
||||
if (!isset($hmtx[$g])) {
|
||||
$hmtx[$g] = $hmtx[0];
|
||||
}
|
||||
|
||||
$this->addMetric(array(
|
||||
"U" => $c,
|
||||
"WX" => $font->normalizeFUnit($hmtx[$g][0]),
|
||||
"N" => (isset($names[$g]) ? $names[$g] : sprintf("uni%04x", $c)),
|
||||
"G" => $g,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
$this->endSection("CharMetrics");
|
||||
|
||||
$kern = $font->getData("kern", "subtable");
|
||||
$tree = is_array($kern) ? $kern["tree"] : null;
|
||||
|
||||
if (!$encoding && is_array($tree)) {
|
||||
$this->startSection("KernData");
|
||||
$this->startSection("KernPairs", count($tree, COUNT_RECURSIVE) - count($tree));
|
||||
|
||||
foreach ($tree as $left => $values) {
|
||||
if (!is_array($values)) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($glyphIndexArray[$left])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$left_gid = $glyphIndexArray[$left];
|
||||
|
||||
if (!isset($names[$left_gid])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$left_name = $names[$left_gid];
|
||||
|
||||
$this->addLine("");
|
||||
|
||||
foreach ($values as $right => $value) {
|
||||
if (!isset($glyphIndexArray[$right])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$right_gid = $glyphIndexArray[$right];
|
||||
|
||||
if (!isset($names[$right_gid])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$right_name = $names[$right_gid];
|
||||
$this->addPair("KPX", "$left_name $right_name $value");
|
||||
}
|
||||
}
|
||||
|
||||
$this->endSection("KernPairs");
|
||||
$this->endSection("KernData");
|
||||
}
|
||||
}
|
||||
|
||||
$this->endSection("FontMetrics");
|
||||
}
|
||||
|
||||
function addLine($line) {
|
||||
fwrite($this->f, "$line\n");
|
||||
}
|
||||
|
||||
function addPair($key, $value) {
|
||||
$this->addLine("$key $value");
|
||||
}
|
||||
|
||||
function addArray($key, $array) {
|
||||
$this->addLine("$key " . implode(" ", $array));
|
||||
}
|
||||
|
||||
function addMetric($data) {
|
||||
$array = array();
|
||||
foreach ($data as $key => $value) {
|
||||
$array[] = "$key $value";
|
||||
}
|
||||
$this->addLine(implode(" ; ", $array));
|
||||
}
|
||||
|
||||
function startSection($name, $value = "") {
|
||||
$this->addLine("Start$name $value");
|
||||
}
|
||||
|
||||
function endSection($name) {
|
||||
$this->addLine("End$name");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,449 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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("Unknown 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $n The number of bytes to read
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function read($n) {
|
||||
if ($n < 1) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return (string) 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 date("Y-m-d H:i: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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\EOT;
|
||||
|
||||
/**
|
||||
* EOT font file.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class File extends \FontLib\TrueType\File {
|
||||
const TTEMBED_SUBSET = 0x00000001;
|
||||
const TTEMBED_TTCOMPRESSED = 0x00000004;
|
||||
const TTEMBED_FAILIFVARIATIONSIMULATED = 0x00000010;
|
||||
const TTMBED_EMBEDEUDC = 0x00000020;
|
||||
const TTEMBED_VALIDATIONTESTS = 0x00000040; // Deprecated
|
||||
const TTEMBED_WEBOBJECT = 0x00000080;
|
||||
const TTEMBED_XORENCRYPTDATA = 0x10000000;
|
||||
|
||||
/**
|
||||
* @var Header
|
||||
*/
|
||||
public $header;
|
||||
|
||||
function parseHeader() {
|
||||
if (!empty($this->header)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->header = new Header($this);
|
||||
$this->header->parse();
|
||||
}
|
||||
|
||||
function parse() {
|
||||
$this->parseHeader();
|
||||
|
||||
$flags = $this->header->data["Flags"];
|
||||
|
||||
if ($flags & self::TTEMBED_TTCOMPRESSED) {
|
||||
$mtx_version = $this->readUInt8();
|
||||
$mtx_copy_limit = $this->readUInt8() << 16 | $this->readUInt8() << 8 | $this->readUInt8();
|
||||
$mtx_offset_1 = $this->readUInt8() << 16 | $this->readUInt8() << 8 | $this->readUInt8();
|
||||
$mtx_offset_2 = $this->readUInt8() << 16 | $this->readUInt8() << 8 | $this->readUInt8();
|
||||
/*
|
||||
var_dump("$mtx_version $mtx_copy_limit $mtx_offset_1 $mtx_offset_2");
|
||||
|
||||
$pos = $this->pos();
|
||||
$size = $mtx_offset_1 - $pos;
|
||||
var_dump("pos: $pos");
|
||||
var_dump("size: $size");*/
|
||||
}
|
||||
|
||||
if ($flags & self::TTEMBED_XORENCRYPTDATA) {
|
||||
// Process XOR
|
||||
}
|
||||
// TODO Read font data ...
|
||||
}
|
||||
|
||||
/**
|
||||
* Little endian version of the read method
|
||||
*
|
||||
* @param int $n The number of bytes to read
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function read($n) {
|
||||
if ($n < 1) {
|
||||
return "";
|
||||
}
|
||||
|
||||
$string = (string) fread($this->f, $n);
|
||||
$chunks = mb_str_split($string, 2, '8bit');
|
||||
$chunks = array_map("strrev", $chunks);
|
||||
return implode("", $chunks);
|
||||
}
|
||||
|
||||
public function readUInt32() {
|
||||
$uint32 = parent::readUInt32();
|
||||
|
||||
return $uint32 >> 16 & 0x0000FFFF | $uint32 << 16 & 0xFFFF0000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font copyright
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontCopyright() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font name
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontName() {
|
||||
return $this->header->data["FamilyName"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font subfamily
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontSubfamily() {
|
||||
return $this->header->data["StyleName"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font subfamily ID
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontSubfamilyID() {
|
||||
return $this->header->data["StyleName"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font full name
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontFullName() {
|
||||
return $this->header->data["FullName"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font version
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontVersion() {
|
||||
return $this->header->data["VersionName"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font weight
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontWeight() {
|
||||
return $this->header->data["Weight"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font Postscript name
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontPostscriptName() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\EOT;
|
||||
|
||||
use Exception;
|
||||
use FontLib\Font;
|
||||
|
||||
/**
|
||||
* TrueType font file header.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*
|
||||
* @property File $font
|
||||
*/
|
||||
class Header extends \FontLib\Header {
|
||||
protected $def = array(
|
||||
"format" => self::uint32,
|
||||
"numTables" => self::uint16,
|
||||
"searchRange" => self::uint16,
|
||||
"entrySelector" => self::uint16,
|
||||
"rangeShift" => self::uint16,
|
||||
);
|
||||
|
||||
public function parse() {
|
||||
$font = $this->font;
|
||||
|
||||
$this->data = $font->unpack(array(
|
||||
"EOTSize" => self::uint32,
|
||||
"FontDataSize" => self::uint32,
|
||||
"Version" => self::uint32,
|
||||
"Flags" => self::uint32,
|
||||
"FontPANOSE" => array(self::uint8, 10),
|
||||
"Charset" => self::uint8,
|
||||
"Italic" => self::uint8,
|
||||
"Weight" => self::uint32,
|
||||
"fsType" => self::uint16,
|
||||
"MagicNumber" => self::uint16,
|
||||
"UnicodeRange1" => self::uint32,
|
||||
"UnicodeRange2" => self::uint32,
|
||||
"UnicodeRange3" => self::uint32,
|
||||
"UnicodeRange4" => self::uint32,
|
||||
"CodePageRange1" => self::uint32,
|
||||
"CodePageRange2" => self::uint32,
|
||||
"CheckSumAdjustment" => self::uint32,
|
||||
"Reserved1" => self::uint32,
|
||||
"Reserved2" => self::uint32,
|
||||
"Reserved3" => self::uint32,
|
||||
"Reserved4" => self::uint32,
|
||||
));
|
||||
|
||||
$this->data["Padding1"] = $font->readUInt16();
|
||||
$this->readString("FamilyName");
|
||||
|
||||
$this->data["Padding2"] = $font->readUInt16();
|
||||
$this->readString("StyleName");
|
||||
|
||||
$this->data["Padding3"] = $font->readUInt16();
|
||||
$this->readString("VersionName");
|
||||
|
||||
$this->data["Padding4"] = $font->readUInt16();
|
||||
$this->readString("FullName");
|
||||
|
||||
switch ($this->data["Version"]) {
|
||||
default:
|
||||
throw new Exception("Unknown EOT version " . $this->data["Version"]);
|
||||
|
||||
case 0x00010000:
|
||||
// Nothing to do more
|
||||
break;
|
||||
|
||||
case 0x00020001:
|
||||
$this->data["Padding5"] = $font->readUInt16();
|
||||
$this->readString("RootString");
|
||||
break;
|
||||
|
||||
case 0x00020002:
|
||||
$this->data["Padding5"] = $font->readUInt16();
|
||||
$this->readString("RootString");
|
||||
|
||||
$this->data["RootStringCheckSum"] = $font->readUInt32();
|
||||
$this->data["EUDCCodePage"] = $font->readUInt32();
|
||||
|
||||
$this->data["Padding6"] = $font->readUInt16();
|
||||
$this->readString("Signature");
|
||||
|
||||
$this->data["EUDCFlags"] = $font->readUInt32();
|
||||
$this->data["EUDCFontSize"] = $font->readUInt32();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!empty($this->data["RootString"])) {
|
||||
$this->data["RootString"] = explode("\0", $this->data["RootString"]);
|
||||
}
|
||||
}
|
||||
|
||||
private function readString($name) {
|
||||
$font = $this->font;
|
||||
$size = $font->readUInt16();
|
||||
|
||||
$this->data["{$name}Size"] = $size;
|
||||
$this->data[$name] = Font::UTF16ToUTF8($font->read($size));
|
||||
}
|
||||
|
||||
public function encode() {
|
||||
//return $this->font->pack($this->def, $this->data);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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;
|
||||
|
||||
/**
|
||||
* Encoding map used to map a code point to a Unicode char.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class EncodingMap {
|
||||
private $f;
|
||||
|
||||
function __construct($file) {
|
||||
$this->f = fopen($file, "r");
|
||||
}
|
||||
|
||||
function parse() {
|
||||
$map = array();
|
||||
|
||||
while ($line = fgets($this->f)) {
|
||||
if (preg_match('/^[\!\=]([0-9A-F]{2,})\s+U\+([0-9A-F]{2})([0-9A-F]{2})\s+([^\s]+)/', $line, $matches)) {
|
||||
$unicode = (hexdec($matches[2]) << 8) + hexdec($matches[3]);
|
||||
$map[hexdec($matches[1])] = array($unicode, $matches[4]);
|
||||
}
|
||||
}
|
||||
|
||||
ksort($map);
|
||||
|
||||
return $map;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace FontLib\Exception;
|
||||
|
||||
class FontNotFoundException extends \Exception
|
||||
{
|
||||
public function __construct($fontPath)
|
||||
{
|
||||
$this->message = 'Font not found in: ' . $fontPath;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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;
|
||||
|
||||
use FontLib\Exception\FontNotFoundException;
|
||||
|
||||
/**
|
||||
* Generic font file.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class Font {
|
||||
static $debug = false;
|
||||
|
||||
/**
|
||||
* @param string $file The font file
|
||||
*
|
||||
* @return TrueType\File|null $file
|
||||
*/
|
||||
public static function load($file) {
|
||||
if(!file_exists($file)){
|
||||
throw new FontNotFoundException($file);
|
||||
}
|
||||
|
||||
$header = file_get_contents($file, false, null, 0, 4);
|
||||
$class = null;
|
||||
|
||||
switch ($header) {
|
||||
case "\x00\x01\x00\x00":
|
||||
case "true":
|
||||
case "typ1":
|
||||
$class = "TrueType\\File";
|
||||
break;
|
||||
|
||||
case "OTTO":
|
||||
$class = "OpenType\\File";
|
||||
break;
|
||||
|
||||
case "wOFF":
|
||||
$class = "WOFF\\File";
|
||||
break;
|
||||
|
||||
case "ttcf":
|
||||
$class = "TrueType\\Collection";
|
||||
break;
|
||||
|
||||
// Unknown type or EOT
|
||||
default:
|
||||
$magicNumber = file_get_contents($file, false, null, 34, 2);
|
||||
|
||||
if ($magicNumber === "LP") {
|
||||
$class = "EOT\\File";
|
||||
}
|
||||
}
|
||||
|
||||
if ($class) {
|
||||
$class = "FontLib\\$class";
|
||||
|
||||
/** @var TrueType\File $obj */
|
||||
$obj = new $class;
|
||||
$obj->load($file);
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static function d($str) {
|
||||
if (!self::$debug) {
|
||||
return;
|
||||
}
|
||||
echo "$str\n";
|
||||
}
|
||||
|
||||
static function UTF16ToUTF8($str) {
|
||||
return mb_convert_encoding($str, "utf-8", "utf-16");
|
||||
}
|
||||
|
||||
static function UTF8ToUTF16($str) {
|
||||
return mb_convert_encoding($str, "utf-16", "utf-8");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/php-font-lib
|
||||
* @author Fabien Ménager <fabien.menager@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||
* @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
|
||||
*/
|
||||
namespace FontLib\Glyph;
|
||||
|
||||
use FontLib\Table\Type\glyf;
|
||||
use FontLib\TrueType\File;
|
||||
use FontLib\BinaryStream;
|
||||
|
||||
/**
|
||||
* `glyf` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class Outline extends BinaryStream {
|
||||
/**
|
||||
* @var \FontLib\Table\Type\glyf
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
protected $offset;
|
||||
protected $size;
|
||||
|
||||
// Data
|
||||
public $numberOfContours;
|
||||
public $xMin;
|
||||
public $yMin;
|
||||
public $xMax;
|
||||
public $yMax;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
public $raw;
|
||||
|
||||
/**
|
||||
* @param glyf $table
|
||||
* @param $offset
|
||||
* @param $size
|
||||
*
|
||||
* @return Outline
|
||||
*/
|
||||
static function init(glyf $table, $offset, $size, BinaryStream $font) {
|
||||
$font->seek($offset);
|
||||
|
||||
if ($size === 0 || $font->readInt16() > -1) {
|
||||
/** @var OutlineSimple $glyph */
|
||||
$glyph = new OutlineSimple($table, $offset, $size);
|
||||
}
|
||||
else {
|
||||
/** @var OutlineComposite $glyph */
|
||||
$glyph = new OutlineComposite($table, $offset, $size);
|
||||
}
|
||||
|
||||
$glyph->parse($font);
|
||||
|
||||
return $glyph;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return File
|
||||
*/
|
||||
function getFont() {
|
||||
return $this->table->getFont();
|
||||
}
|
||||
|
||||
function __construct(glyf $table, $offset = null, $size = null) {
|
||||
$this->table = $table;
|
||||
$this->offset = $offset;
|
||||
$this->size = $size;
|
||||
}
|
||||
|
||||
function parse(BinaryStream $font) {
|
||||
$font->seek($this->offset);
|
||||
|
||||
$this->raw = $font->read($this->size);
|
||||
}
|
||||
|
||||
function parseData() {
|
||||
$font = $this->getFont();
|
||||
$font->seek($this->offset);
|
||||
|
||||
$this->numberOfContours = $font->readInt16();
|
||||
$this->xMin = $font->readFWord();
|
||||
$this->yMin = $font->readFWord();
|
||||
$this->xMax = $font->readFWord();
|
||||
$this->yMax = $font->readFWord();
|
||||
}
|
||||
|
||||
function encode() {
|
||||
$font = $this->getFont();
|
||||
|
||||
return $font->write($this->raw, mb_strlen((string) $this->raw, '8bit'));
|
||||
}
|
||||
|
||||
function getSVGContours() {
|
||||
// Inherit
|
||||
}
|
||||
|
||||
function getGlyphIDs() {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/php-font-lib
|
||||
* @author Fabien Ménager <fabien.menager@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||
* @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
|
||||
*/
|
||||
|
||||
namespace FontLib\Glyph;
|
||||
/**
|
||||
* Glyph outline component
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class OutlineComponent {
|
||||
public $flags;
|
||||
public $glyphIndex;
|
||||
public $a, $b, $c, $d, $e, $f;
|
||||
public $point_compound;
|
||||
public $point_component;
|
||||
public $instructions;
|
||||
|
||||
function getMatrix() {
|
||||
return array(
|
||||
$this->a, $this->b,
|
||||
$this->c, $this->d,
|
||||
$this->e, $this->f,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,253 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/php-font-lib
|
||||
* @author Fabien Ménager <fabien.menager@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||
* @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
|
||||
*/
|
||||
|
||||
namespace FontLib\Glyph;
|
||||
|
||||
/**
|
||||
* Composite glyph outline
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class OutlineComposite extends Outline {
|
||||
const ARG_1_AND_2_ARE_WORDS = 0x0001;
|
||||
const ARGS_ARE_XY_VALUES = 0x0002;
|
||||
const ROUND_XY_TO_GRID = 0x0004;
|
||||
const WE_HAVE_A_SCALE = 0x0008;
|
||||
const MORE_COMPONENTS = 0x0020;
|
||||
const WE_HAVE_AN_X_AND_Y_SCALE = 0x0040;
|
||||
const WE_HAVE_A_TWO_BY_TWO = 0x0080;
|
||||
const WE_HAVE_INSTRUCTIONS = 0x0100;
|
||||
const USE_MY_METRICS = 0x0200;
|
||||
const OVERLAP_COMPOUND = 0x0400;
|
||||
|
||||
/**
|
||||
* @var OutlineComponent[]
|
||||
*/
|
||||
public $components = array();
|
||||
|
||||
function getGlyphIDs() {
|
||||
if (empty($this->components)) {
|
||||
$this->parseData();
|
||||
}
|
||||
|
||||
$glyphIDs = array();
|
||||
foreach ($this->components as $_component) {
|
||||
$glyphIDs[] = $_component->glyphIndex;
|
||||
|
||||
$_glyph = $this->table->data[$_component->glyphIndex];
|
||||
|
||||
if ($_glyph !== $this) {
|
||||
$glyphIDs = array_merge($glyphIDs, $_glyph->getGlyphIDs());
|
||||
}
|
||||
}
|
||||
|
||||
return $glyphIDs;
|
||||
}
|
||||
|
||||
/*function parse() {
|
||||
//$this->parseData();
|
||||
}*/
|
||||
|
||||
function parseData() {
|
||||
parent::parseData();
|
||||
|
||||
$font = $this->getFont();
|
||||
|
||||
do {
|
||||
$flags = $font->readUInt16();
|
||||
$glyphIndex = $font->readUInt16();
|
||||
|
||||
$a = 1.0;
|
||||
$b = 0.0;
|
||||
$c = 0.0;
|
||||
$d = 1.0;
|
||||
$e = 0.0;
|
||||
$f = 0.0;
|
||||
|
||||
$point_compound = null;
|
||||
$point_component = null;
|
||||
|
||||
$instructions = null;
|
||||
|
||||
if ($flags & self::ARG_1_AND_2_ARE_WORDS) {
|
||||
if ($flags & self::ARGS_ARE_XY_VALUES) {
|
||||
$e = $font->readInt16();
|
||||
$f = $font->readInt16();
|
||||
}
|
||||
else {
|
||||
$point_compound = $font->readUInt16();
|
||||
$point_component = $font->readUInt16();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($flags & self::ARGS_ARE_XY_VALUES) {
|
||||
$e = $font->readInt8();
|
||||
$f = $font->readInt8();
|
||||
}
|
||||
else {
|
||||
$point_compound = $font->readUInt8();
|
||||
$point_component = $font->readUInt8();
|
||||
}
|
||||
}
|
||||
|
||||
if ($flags & self::WE_HAVE_A_SCALE) {
|
||||
$a = $d = $font->readInt16();
|
||||
}
|
||||
elseif ($flags & self::WE_HAVE_AN_X_AND_Y_SCALE) {
|
||||
$a = $font->readInt16();
|
||||
$d = $font->readInt16();
|
||||
}
|
||||
elseif ($flags & self::WE_HAVE_A_TWO_BY_TWO) {
|
||||
$a = $font->readInt16();
|
||||
$b = $font->readInt16();
|
||||
$c = $font->readInt16();
|
||||
$d = $font->readInt16();
|
||||
}
|
||||
|
||||
//if ($flags & self::WE_HAVE_INSTRUCTIONS) {
|
||||
//
|
||||
//}
|
||||
|
||||
$component = new OutlineComponent();
|
||||
$component->flags = $flags;
|
||||
$component->glyphIndex = $glyphIndex;
|
||||
$component->a = $a;
|
||||
$component->b = $b;
|
||||
$component->c = $c;
|
||||
$component->d = $d;
|
||||
$component->e = $e;
|
||||
$component->f = $f;
|
||||
$component->point_compound = $point_compound;
|
||||
$component->point_component = $point_component;
|
||||
$component->instructions = $instructions;
|
||||
|
||||
$this->components[] = $component;
|
||||
} while ($flags & self::MORE_COMPONENTS);
|
||||
if ($flags & self::WE_HAVE_INSTRUCTIONS) {
|
||||
$numInstr = $font->readUInt16();
|
||||
$instr = $font->read($numInstr);
|
||||
$this->components[count($this->components) - 1]->instructions = pack('n', $numInstr) . $instr;
|
||||
}
|
||||
}
|
||||
|
||||
function encode() {
|
||||
$font = $this->getFont();
|
||||
|
||||
$gids = $font->getSubset();
|
||||
|
||||
$size = $font->writeInt16(-1);
|
||||
$size += $font->writeFWord($this->xMin);
|
||||
$size += $font->writeFWord($this->yMin);
|
||||
$size += $font->writeFWord($this->xMax);
|
||||
$size += $font->writeFWord($this->yMax);
|
||||
|
||||
foreach ($this->components as $_i => $_component) {
|
||||
$flags = 0;
|
||||
if ($_component->point_component === null && $_component->point_compound === null) {
|
||||
$flags |= self::ARGS_ARE_XY_VALUES;
|
||||
|
||||
if (abs($_component->e) > 0x7F || abs($_component->f) > 0x7F) {
|
||||
$flags |= self::ARG_1_AND_2_ARE_WORDS;
|
||||
}
|
||||
}
|
||||
elseif ($_component->point_component > 0xFF || $_component->point_compound > 0xFF) {
|
||||
$flags |= self::ARG_1_AND_2_ARE_WORDS;
|
||||
}
|
||||
|
||||
if ($_component->b == 0 && $_component->c == 0) {
|
||||
if ($_component->a == $_component->d) {
|
||||
if ($_component->a != 1.0) {
|
||||
$flags |= self::WE_HAVE_A_SCALE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$flags |= self::WE_HAVE_AN_X_AND_Y_SCALE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$flags |= self::WE_HAVE_A_TWO_BY_TWO;
|
||||
}
|
||||
|
||||
if ($_i < count($this->components) - 1) {
|
||||
$flags |= self::MORE_COMPONENTS;
|
||||
} elseif($_component->instructions !== null) {
|
||||
$flags |= self::WE_HAVE_INSTRUCTIONS;
|
||||
}
|
||||
|
||||
$size += $font->writeUInt16($flags);
|
||||
|
||||
$new_gid = array_search($_component->glyphIndex, $gids);
|
||||
$size += $font->writeUInt16($new_gid);
|
||||
|
||||
if ($flags & self::ARG_1_AND_2_ARE_WORDS) {
|
||||
if ($flags & self::ARGS_ARE_XY_VALUES) {
|
||||
$size += $font->writeInt16($_component->e);
|
||||
$size += $font->writeInt16($_component->f);
|
||||
}
|
||||
else {
|
||||
$size += $font->writeUInt16($_component->point_compound);
|
||||
$size += $font->writeUInt16($_component->point_component);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($flags & self::ARGS_ARE_XY_VALUES) {
|
||||
$size += $font->writeInt8($_component->e);
|
||||
$size += $font->writeInt8($_component->f);
|
||||
}
|
||||
else {
|
||||
$size += $font->writeUInt8($_component->point_compound);
|
||||
$size += $font->writeUInt8($_component->point_component);
|
||||
}
|
||||
}
|
||||
|
||||
if ($flags & self::WE_HAVE_A_SCALE) {
|
||||
$size += $font->writeInt16($_component->a);
|
||||
}
|
||||
elseif ($flags & self::WE_HAVE_AN_X_AND_Y_SCALE) {
|
||||
$size += $font->writeInt16($_component->a);
|
||||
$size += $font->writeInt16($_component->d);
|
||||
}
|
||||
elseif ($flags & self::WE_HAVE_A_TWO_BY_TWO) {
|
||||
$size += $font->writeInt16($_component->a);
|
||||
$size += $font->writeInt16($_component->b);
|
||||
$size += $font->writeInt16($_component->c);
|
||||
$size += $font->writeInt16($_component->d);
|
||||
}
|
||||
}
|
||||
|
||||
if($_component->instructions !== null) {
|
||||
$size += $font->write($_component->instructions, strlen($_component->instructions));
|
||||
}
|
||||
|
||||
return $size;
|
||||
}
|
||||
|
||||
public function getSVGContours() {
|
||||
$contours = array();
|
||||
|
||||
/** @var \FontLib\Table\Type\glyf $glyph_data */
|
||||
$glyph_data = $this->getFont()->getTableObject("glyf");
|
||||
|
||||
/** @var Outline[] $glyphs */
|
||||
$glyphs = $glyph_data->data;
|
||||
|
||||
foreach ($this->components as $component) {
|
||||
$_glyph = $glyphs[$component->glyphIndex];
|
||||
|
||||
if ($_glyph !== $this) {
|
||||
$contours[] = array(
|
||||
"contours" => $_glyph->getSVGContours(),
|
||||
"transform" => $component->getMatrix(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $contours;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,335 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/php-font-lib
|
||||
* @author Fabien Ménager <fabien.menager@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||
* @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
|
||||
*/
|
||||
|
||||
namespace FontLib\Glyph;
|
||||
|
||||
/**
|
||||
* `glyf` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class OutlineSimple extends Outline {
|
||||
const ON_CURVE = 0x01;
|
||||
const X_SHORT_VECTOR = 0x02;
|
||||
const Y_SHORT_VECTOR = 0x04;
|
||||
const REPEAT = 0x08;
|
||||
const THIS_X_IS_SAME = 0x10;
|
||||
const THIS_Y_IS_SAME = 0x20;
|
||||
|
||||
public $instructions;
|
||||
public $points;
|
||||
|
||||
function parseData() {
|
||||
parent::parseData();
|
||||
|
||||
if (!$this->size) {
|
||||
return;
|
||||
}
|
||||
|
||||
$font = $this->getFont();
|
||||
|
||||
$noc = $this->numberOfContours;
|
||||
|
||||
if ($noc == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$endPtsOfContours = $font->r(array(self::uint16, $noc));
|
||||
|
||||
$instructionLength = $font->readUInt16();
|
||||
$this->instructions = $font->r(array(self::uint8, $instructionLength));
|
||||
|
||||
$count = $endPtsOfContours[$noc - 1] + 1;
|
||||
|
||||
// Flags
|
||||
$flags = array();
|
||||
for ($index = 0; $index < $count; $index++) {
|
||||
$flags[$index] = $font->readUInt8();
|
||||
|
||||
if ($flags[$index] & self::REPEAT) {
|
||||
$repeats = $font->readUInt8();
|
||||
|
||||
for ($i = 1; $i <= $repeats; $i++) {
|
||||
$flags[$index + $i] = $flags[$index];
|
||||
}
|
||||
|
||||
$index += $repeats;
|
||||
}
|
||||
}
|
||||
|
||||
$points = array();
|
||||
foreach ($flags as $i => $flag) {
|
||||
$points[$i]["onCurve"] = $flag & self::ON_CURVE;
|
||||
$points[$i]["endOfContour"] = in_array($i, $endPtsOfContours);
|
||||
}
|
||||
|
||||
// X Coords
|
||||
$x = 0;
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$flag = $flags[$i];
|
||||
|
||||
if ($flag & self::THIS_X_IS_SAME) {
|
||||
if ($flag & self::X_SHORT_VECTOR) {
|
||||
$x += $font->readUInt8();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($flag & self::X_SHORT_VECTOR) {
|
||||
$x -= $font->readUInt8();
|
||||
}
|
||||
else {
|
||||
$x += $font->readInt16();
|
||||
}
|
||||
}
|
||||
|
||||
$points[$i]["x"] = $x;
|
||||
}
|
||||
|
||||
// Y Coords
|
||||
$y = 0;
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$flag = $flags[$i];
|
||||
|
||||
if ($flag & self::THIS_Y_IS_SAME) {
|
||||
if ($flag & self::Y_SHORT_VECTOR) {
|
||||
$y += $font->readUInt8();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($flag & self::Y_SHORT_VECTOR) {
|
||||
$y -= $font->readUInt8();
|
||||
}
|
||||
else {
|
||||
$y += $font->readInt16();
|
||||
}
|
||||
}
|
||||
|
||||
$points[$i]["y"] = $y;
|
||||
}
|
||||
|
||||
$this->points = $points;
|
||||
}
|
||||
|
||||
public function splitSVGPath($path) {
|
||||
preg_match_all('/([a-z])|(-?\d+(?:\.\d+)?)/i', $path, $matches, PREG_PATTERN_ORDER);
|
||||
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
public function makePoints($path) {
|
||||
$path = $this->splitSVGPath($path);
|
||||
$l = count($path);
|
||||
$i = 0;
|
||||
|
||||
$points = array();
|
||||
|
||||
while ($i < $l) {
|
||||
switch ($path[$i]) {
|
||||
// moveTo
|
||||
case "M":
|
||||
$points[] = array(
|
||||
"onCurve" => true,
|
||||
"x" => $path[++$i],
|
||||
"y" => $path[++$i],
|
||||
"endOfContour" => false,
|
||||
);
|
||||
break;
|
||||
|
||||
// lineTo
|
||||
case "L":
|
||||
$points[] = array(
|
||||
"onCurve" => true,
|
||||
"x" => $path[++$i],
|
||||
"y" => $path[++$i],
|
||||
"endOfContour" => false,
|
||||
);
|
||||
break;
|
||||
|
||||
// quadraticCurveTo
|
||||
case "Q":
|
||||
$points[] = array(
|
||||
"onCurve" => false,
|
||||
"x" => $path[++$i],
|
||||
"y" => $path[++$i],
|
||||
"endOfContour" => false,
|
||||
);
|
||||
$points[] = array(
|
||||
"onCurve" => true,
|
||||
"x" => $path[++$i],
|
||||
"y" => $path[++$i],
|
||||
"endOfContour" => false,
|
||||
);
|
||||
break;
|
||||
|
||||
// closePath
|
||||
/** @noinspection PhpMissingBreakStatementInspection */
|
||||
case "z":
|
||||
$points[count($points) - 1]["endOfContour"] = true;
|
||||
|
||||
default:
|
||||
$i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $points;
|
||||
}
|
||||
|
||||
function encode() {
|
||||
if (empty($this->points)) {
|
||||
return parent::encode();
|
||||
}
|
||||
|
||||
return $this->size = $this->encodePoints($this->points);
|
||||
}
|
||||
|
||||
public function encodePoints($points) {
|
||||
$endPtsOfContours = array();
|
||||
$flags = array();
|
||||
$coords_x = array();
|
||||
$coords_y = array();
|
||||
|
||||
$last_x = 0;
|
||||
$last_y = 0;
|
||||
$xMin = $yMin = 0xFFFF;
|
||||
$xMax = $yMax = -0xFFFF;
|
||||
foreach ($points as $i => $point) {
|
||||
$flag = 0;
|
||||
if ($point["onCurve"]) {
|
||||
$flag |= self::ON_CURVE;
|
||||
}
|
||||
|
||||
if ($point["endOfContour"]) {
|
||||
$endPtsOfContours[] = $i;
|
||||
}
|
||||
|
||||
// Simplified, we could do some optimizations
|
||||
if ($point["x"] == $last_x) {
|
||||
$flag |= self::THIS_X_IS_SAME;
|
||||
}
|
||||
else {
|
||||
$x = intval($point["x"]);
|
||||
$xMin = min($x, $xMin);
|
||||
$xMax = max($x, $xMax);
|
||||
$coords_x[] = $x - $last_x; // int16
|
||||
}
|
||||
|
||||
// Simplified, we could do some optimizations
|
||||
if ($point["y"] == $last_y) {
|
||||
$flag |= self::THIS_Y_IS_SAME;
|
||||
}
|
||||
else {
|
||||
$y = intval($point["y"]);
|
||||
$yMin = min($y, $yMin);
|
||||
$yMax = max($y, $yMax);
|
||||
$coords_y[] = $y - $last_y; // int16
|
||||
}
|
||||
|
||||
$flags[] = $flag;
|
||||
$last_x = $point["x"];
|
||||
$last_y = $point["y"];
|
||||
}
|
||||
|
||||
$font = $this->getFont();
|
||||
|
||||
$l = 0;
|
||||
$l += $font->writeInt16(count($endPtsOfContours)); // endPtsOfContours
|
||||
$l += $font->writeFWord(isset($this->xMin) ? $this->xMin : $xMin); // xMin
|
||||
$l += $font->writeFWord(isset($this->yMin) ? $this->yMin : $yMin); // yMin
|
||||
$l += $font->writeFWord(isset($this->xMax) ? $this->xMax : $xMax); // xMax
|
||||
$l += $font->writeFWord(isset($this->yMax) ? $this->yMax : $yMax); // yMax
|
||||
|
||||
// Simple glyf
|
||||
$l += $font->w(array(self::uint16, count($endPtsOfContours)), $endPtsOfContours); // endPtsOfContours
|
||||
$l += $font->writeUInt16(0); // instructionLength
|
||||
$l += $font->w(array(self::uint8, count($flags)), $flags); // flags
|
||||
$l += $font->w(array(self::int16, count($coords_x)), $coords_x); // xCoordinates
|
||||
$l += $font->w(array(self::int16, count($coords_y)), $coords_y); // yCoordinates
|
||||
return $l;
|
||||
}
|
||||
|
||||
public function getSVGContours($points = null) {
|
||||
$path = "";
|
||||
|
||||
if (!$points) {
|
||||
if (empty($this->points)) {
|
||||
$this->parseData();
|
||||
}
|
||||
|
||||
$points = $this->points;
|
||||
}
|
||||
|
||||
$length = (empty($points) ? 0 : count($points));
|
||||
$firstIndex = 0;
|
||||
$count = 0;
|
||||
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$count++;
|
||||
|
||||
if ($points[$i]["endOfContour"]) {
|
||||
$path .= $this->getSVGPath($points, $firstIndex, $count);
|
||||
$firstIndex = $i + 1;
|
||||
$count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
protected function getSVGPath($points, $startIndex, $count) {
|
||||
$offset = 0;
|
||||
$path = "";
|
||||
|
||||
while ($offset < $count) {
|
||||
$point = $points[$startIndex + $offset % $count];
|
||||
$point_p1 = $points[$startIndex + ($offset + 1) % $count];
|
||||
|
||||
if ($offset == 0) {
|
||||
$path .= "M{$point['x']},{$point['y']} ";
|
||||
}
|
||||
|
||||
if ($point["onCurve"]) {
|
||||
if ($point_p1["onCurve"]) {
|
||||
$path .= "L{$point_p1['x']},{$point_p1['y']} ";
|
||||
$offset++;
|
||||
}
|
||||
else {
|
||||
$point_p2 = $points[$startIndex + ($offset + 2) % $count];
|
||||
|
||||
if ($point_p2["onCurve"]) {
|
||||
$path .= "Q{$point_p1['x']},{$point_p1['y']},{$point_p2['x']},{$point_p2['y']} ";
|
||||
}
|
||||
else {
|
||||
$path .= "Q{$point_p1['x']},{$point_p1['y']}," . $this->midValue($point_p1['x'], $point_p2['x']) . "," . $this->midValue($point_p1['y'], $point_p2['y']) . " ";
|
||||
}
|
||||
|
||||
$offset += 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($point_p1["onCurve"]) {
|
||||
$path .= "Q{$point['x']},{$point['y']},{$point_p1['x']},{$point_p1['y']} ";
|
||||
}
|
||||
else {
|
||||
$path .= "Q{$point['x']},{$point['y']}," . $this->midValue($point['x'], $point_p1['x']) . "," . $this->midValue($point['y'], $point_p1['y']) . " ";
|
||||
}
|
||||
|
||||
$offset++;
|
||||
}
|
||||
}
|
||||
|
||||
$path .= "z ";
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
function midValue($a, $b) {
|
||||
return $a + ($b - $a) / 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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;
|
||||
|
||||
use FontLib\TrueType\File;
|
||||
|
||||
/**
|
||||
* Font header container.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
abstract class Header extends BinaryStream {
|
||||
/**
|
||||
* @var File
|
||||
*/
|
||||
protected $font;
|
||||
protected $def = array();
|
||||
|
||||
public $data;
|
||||
|
||||
public function __construct(File $font) {
|
||||
$this->font = $font;
|
||||
}
|
||||
|
||||
public function encode() {
|
||||
return $this->font->pack($this->def, $this->data);
|
||||
}
|
||||
|
||||
public function parse() {
|
||||
$this->data = $this->font->unpack($this->def);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\OpenType;
|
||||
|
||||
/**
|
||||
* Open Type font, the same as a TrueType one.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class File extends \FontLib\TrueType\File {
|
||||
//
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\OpenType;
|
||||
|
||||
/**
|
||||
* Open Type Table directory entry, the same as a TrueType one.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class TableDirectoryEntry extends \FontLib\TrueType\TableDirectoryEntry {
|
||||
|
||||
}
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\Table;
|
||||
|
||||
use FontLib\TrueType\File;
|
||||
use FontLib\Font;
|
||||
use FontLib\BinaryStream;
|
||||
|
||||
/**
|
||||
* Generic Font table directory entry.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class DirectoryEntry extends BinaryStream {
|
||||
/**
|
||||
* @var File
|
||||
*/
|
||||
protected $font;
|
||||
|
||||
/**
|
||||
* @var Table
|
||||
*/
|
||||
protected $font_table;
|
||||
|
||||
public $entryLength = 4;
|
||||
|
||||
public $tag;
|
||||
public $checksum;
|
||||
public $offset;
|
||||
public $length;
|
||||
|
||||
protected $origF;
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
static function computeChecksum($data) {
|
||||
$len = mb_strlen($data, '8bit');
|
||||
$mod = $len % 4;
|
||||
|
||||
if ($mod) {
|
||||
$data = str_pad($data, $len + (4 - $mod), "\0");
|
||||
}
|
||||
|
||||
$table = unpack("N*", $data);
|
||||
return array_sum($table);
|
||||
}
|
||||
|
||||
function __construct(File $font) {
|
||||
$this->font = $font;
|
||||
$this->f = $font->f;
|
||||
}
|
||||
|
||||
function parse() {
|
||||
$this->tag = $this->font->read(4);
|
||||
}
|
||||
|
||||
function open($filename, $mode = self::modeRead) {
|
||||
// void
|
||||
}
|
||||
|
||||
function setTable(Table $font_table) {
|
||||
$this->font_table = $font_table;
|
||||
}
|
||||
|
||||
function encode($entry_offset) {
|
||||
Font::d("\n==== $this->tag ====");
|
||||
//Font::d("Entry offset = $entry_offset");
|
||||
|
||||
$data = $this->font_table;
|
||||
$font = $this->font;
|
||||
|
||||
$table_offset = $font->pos();
|
||||
$this->offset = $table_offset;
|
||||
$table_length = $data->encode();
|
||||
|
||||
$font->seek($table_offset + $table_length);
|
||||
$pad = 0;
|
||||
$mod = $table_length % 4;
|
||||
if ($mod != 0) {
|
||||
$pad = 4 - $mod;
|
||||
$font->write(str_pad("", $pad, "\0"), $pad);
|
||||
}
|
||||
|
||||
$font->seek($table_offset);
|
||||
$table_data = $font->read($table_length);
|
||||
|
||||
$font->seek($entry_offset);
|
||||
|
||||
$font->write($this->tag, 4);
|
||||
$font->writeUInt32(self::computeChecksum($table_data));
|
||||
$font->writeUInt32($table_offset);
|
||||
$font->writeUInt32($table_length);
|
||||
|
||||
Font::d("Bytes written = $table_length");
|
||||
|
||||
$font->seek($table_offset + $table_length + $pad);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return File
|
||||
*/
|
||||
function getFont() {
|
||||
return $this->font;
|
||||
}
|
||||
|
||||
function startRead() {
|
||||
$this->font->seek($this->offset);
|
||||
}
|
||||
|
||||
function endRead() {
|
||||
//
|
||||
}
|
||||
|
||||
function startWrite() {
|
||||
$this->font->seek($this->offset);
|
||||
}
|
||||
|
||||
function endWrite() {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\Table;
|
||||
|
||||
use FontLib\TrueType\File;
|
||||
use FontLib\Font;
|
||||
use FontLib\BinaryStream;
|
||||
|
||||
/**
|
||||
* Generic font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class Table extends BinaryStream {
|
||||
/**
|
||||
* @var DirectoryEntry
|
||||
*/
|
||||
protected $entry;
|
||||
protected $def = array();
|
||||
|
||||
public $data;
|
||||
|
||||
final public function __construct(DirectoryEntry $entry) {
|
||||
$this->entry = $entry;
|
||||
$entry->setTable($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return File
|
||||
*/
|
||||
public function getFont() {
|
||||
return $this->entry->getFont();
|
||||
}
|
||||
|
||||
protected function _encode() {
|
||||
if (empty($this->data)) {
|
||||
Font::d(" >> Table is empty");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $this->getFont()->pack($this->def, $this->data);
|
||||
}
|
||||
|
||||
protected function _parse() {
|
||||
$this->data = $this->getFont()->unpack($this->def);
|
||||
}
|
||||
|
||||
protected function _parseRaw() {
|
||||
$this->data = $this->getFont()->read($this->entry->length);
|
||||
}
|
||||
|
||||
protected function _encodeRaw() {
|
||||
return $this->getFont()->write($this->data, $this->entry->length);
|
||||
}
|
||||
|
||||
public function toHTML() {
|
||||
return "<pre>" . var_export($this->data, true) . "</pre>";
|
||||
}
|
||||
|
||||
final public function encode() {
|
||||
$this->entry->startWrite();
|
||||
|
||||
if (false && empty($this->def)) {
|
||||
$length = $this->_encodeRaw();
|
||||
}
|
||||
else {
|
||||
$length = $this->_encode();
|
||||
}
|
||||
|
||||
$this->entry->endWrite();
|
||||
|
||||
return $length;
|
||||
}
|
||||
|
||||
final public function parse() {
|
||||
$this->entry->startRead();
|
||||
|
||||
if (false && empty($this->def)) {
|
||||
$this->_parseRaw();
|
||||
}
|
||||
else {
|
||||
$this->_parse();
|
||||
}
|
||||
|
||||
$this->entry->endRead();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,381 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\Table\Type;
|
||||
use FontLib\Table\Table;
|
||||
|
||||
/**
|
||||
* `cmap` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class cmap extends Table {
|
||||
private static $header_format = array(
|
||||
"version" => self::uint16,
|
||||
"numberSubtables" => self::uint16,
|
||||
);
|
||||
|
||||
private static $subtable_header_format = array(
|
||||
"platformID" => self::uint16,
|
||||
"platformSpecificID" => self::uint16,
|
||||
"offset" => self::uint32,
|
||||
);
|
||||
|
||||
private static $subtable_v2_format = array(
|
||||
"length" => self::uint16,
|
||||
"language" => self::uint16
|
||||
);
|
||||
|
||||
private static $subtable_v2_format_subheader = array(
|
||||
"firstCode" => self::uint16,
|
||||
"entryCount" => self::uint16,
|
||||
"idDelta" => self::int16,
|
||||
"idRangeOffset" => self::uint16
|
||||
);
|
||||
|
||||
private static $subtable_v4_format = array(
|
||||
"length" => self::uint16,
|
||||
"language" => self::uint16,
|
||||
"segCountX2" => self::uint16,
|
||||
"searchRange" => self::uint16,
|
||||
"entrySelector" => self::uint16,
|
||||
"rangeShift" => self::uint16,
|
||||
);
|
||||
|
||||
private static $subtable_v12_format = array(
|
||||
"length" => self::uint32,
|
||||
"language" => self::uint32,
|
||||
"ngroups" => self::uint32
|
||||
);
|
||||
|
||||
protected function _parse() {
|
||||
$font = $this->getFont();
|
||||
|
||||
$cmap_offset = $font->pos();
|
||||
|
||||
$data = $font->unpack(self::$header_format);
|
||||
|
||||
$subtables = array();
|
||||
for ($i = 0; $i < $data["numberSubtables"]; $i++) {
|
||||
$subtables[] = $font->unpack(self::$subtable_header_format);
|
||||
}
|
||||
|
||||
$data["subtables"] = $subtables;
|
||||
|
||||
foreach ($data["subtables"] as $i => &$subtable) {
|
||||
$font->seek($cmap_offset + $subtable["offset"]);
|
||||
|
||||
$subtable["format"] = $font->readUInt16();
|
||||
|
||||
switch ($subtable["format"]) {
|
||||
case 0:
|
||||
case 6:
|
||||
case 8:
|
||||
case 10:
|
||||
case 13:
|
||||
case 14:
|
||||
unset($data["subtables"][$i]);
|
||||
$data["numberSubtables"]--;
|
||||
continue 2;
|
||||
|
||||
case 2:
|
||||
$subtable += $font->unpack(self::$subtable_v2_format);
|
||||
|
||||
$subHeaderKeys = array_map(function($val) { return $val / 8; }, $font->readUInt16Many(256));
|
||||
$subHeaders = array();
|
||||
|
||||
$glyphIdArray = array();
|
||||
$maxSubHeaderIndex = max($subHeaderKeys);
|
||||
for ($i = 0; $i <= $maxSubHeaderIndex; $i++) {
|
||||
$subHeader = $font->unpack(self::$subtable_v2_format_subheader);
|
||||
$offset = $font->pos();
|
||||
$subHeader["glyphIdArrayOffset"] = $offset + $subHeader["idRangeOffset"] - 2;
|
||||
$subHeaders[$i] = $subHeader;
|
||||
|
||||
if (!\array_key_exists($subHeader["glyphIdArrayOffset"], $glyphIdArray) || count($glyphIdArray[$subHeader["glyphIdArrayOffset"]]) < $subHeader["entryCount"]) {
|
||||
$font->seek($subHeader["glyphIdArrayOffset"]);
|
||||
$glyphIdArray[$subHeader["glyphIdArrayOffset"]] = $font->readUInt16Many($subHeader["entryCount"]);
|
||||
$font->seek($offset);
|
||||
}
|
||||
}
|
||||
|
||||
$glyphIndexArray = array();
|
||||
foreach ($subHeaderKeys as $highByte => $subHeaderKey) {
|
||||
$subHeader = $subHeaders[$subHeaderKey];
|
||||
if ($subHeaderKey === 0) {
|
||||
$c = $highByte;
|
||||
if ($c < $subHeader["firstCode"] || $c >= ($subHeader["firstCode"] + $subHeader["entryCount"])) {
|
||||
$glyphIndexArray[$c] = 0;
|
||||
continue;
|
||||
}
|
||||
$c = $highByte;
|
||||
$index = $c - $subHeader["firstCode"];
|
||||
$glyphId = $glyphIdArray[$subHeader["glyphIdArrayOffset"]][$index];
|
||||
if ($glyphId === 0) {
|
||||
$glyphIndexArray[$c] = 0;
|
||||
} else {
|
||||
$glyphIndexArray[$c] = ($glyphId + $subHeader["idDelta"]) & 0xFFFF;
|
||||
}
|
||||
} else {
|
||||
for ($index = 0; $index < $subHeader["entryCount"]; $index++) {
|
||||
$c = null;
|
||||
$lowByte = $subHeader["firstCode"] + $index;
|
||||
$c = (($highByte & 0xFF) << 8) | ($lowByte & 0xFF);
|
||||
$glyphId = $glyphIdArray[$subHeader["glyphIdArrayOffset"]][$index];
|
||||
if ($glyphId === 0) {
|
||||
$glyphIndexArray[$c] = 0;
|
||||
} else {
|
||||
$glyphIndexArray[$c] = ($glyphId + $subHeader["idDelta"]) & 0xFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$subtable += array(
|
||||
"subHeaderKeys" => $subHeaderKeys,
|
||||
"subHeaders" => $subHeaders,
|
||||
"glyphIdArray" => $glyphIdArray,
|
||||
"glyphIndexArray" => $glyphIndexArray
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
$subtable += $font->unpack(self::$subtable_v4_format);
|
||||
|
||||
$segCount = $subtable["segCountX2"] / 2;
|
||||
$subtable["segCount"] = $segCount;
|
||||
|
||||
$endCode = $font->readUInt16Many($segCount);
|
||||
|
||||
$font->readUInt16(); // reservedPad
|
||||
|
||||
$startCode = $font->readUInt16Many($segCount);
|
||||
$idDelta = $font->readInt16Many($segCount);
|
||||
|
||||
$ro_start = $font->pos();
|
||||
$idRangeOffset = $font->readUInt16Many($segCount);
|
||||
|
||||
$glyphIndexArray = array();
|
||||
for ($i = 0; $i < $segCount; $i++) {
|
||||
$c1 = $startCode[$i];
|
||||
$c2 = $endCode[$i];
|
||||
$d = $idDelta[$i];
|
||||
$ro = $idRangeOffset[$i];
|
||||
|
||||
if ($ro > 0) {
|
||||
$font->seek($subtable["offset"] + 2 * $i + $ro);
|
||||
}
|
||||
|
||||
for ($c = $c1; $c <= $c2; $c++) {
|
||||
if ($c === 0xFFFF) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($ro == 0) {
|
||||
$gid = ($c + $d) & 0xFFFF;
|
||||
}
|
||||
else {
|
||||
$offset = ($c - $c1) * 2 + $ro;
|
||||
$offset = $ro_start + 2 * $i + $offset;
|
||||
|
||||
$gid = 0;
|
||||
if ($font->seek($offset) === true) {
|
||||
$gid = $font->readUInt16();
|
||||
}
|
||||
|
||||
if ($gid != 0) {
|
||||
$gid = ($gid + $d) & 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
if ($gid >= 0) {
|
||||
$glyphIndexArray[$c] = $gid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$subtable += array(
|
||||
"endCode" => $endCode,
|
||||
"startCode" => $startCode,
|
||||
"idDelta" => $idDelta,
|
||||
"idRangeOffset" => $idRangeOffset,
|
||||
"glyphIndexArray" => $glyphIndexArray
|
||||
);
|
||||
break;
|
||||
|
||||
case 12:
|
||||
$font->readUInt16();
|
||||
|
||||
$subtable += $font->unpack(self::$subtable_v12_format);
|
||||
|
||||
$glyphIndexArray = array();
|
||||
$endCodes = array();
|
||||
$startCodes = array();
|
||||
|
||||
for ($p = 0; $p < $subtable['ngroups']; $p++) {
|
||||
|
||||
$startCode = $startCodes[] = $font->readUInt32();
|
||||
$endCode = $endCodes[] = $font->readUInt32();
|
||||
$startGlyphCode = $font->readUInt32();
|
||||
|
||||
for ($c = $startCode; $c <= $endCode; $c++) {
|
||||
$glyphIndexArray[$c] = $startGlyphCode;
|
||||
$startGlyphCode++;
|
||||
}
|
||||
}
|
||||
|
||||
$subtable += array(
|
||||
"startCode" => $startCodes,
|
||||
"endCode" => $endCodes,
|
||||
"glyphIndexArray" => $glyphIndexArray,
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
function _encode() {
|
||||
$font = $this->getFont();
|
||||
|
||||
$subset = $font->getSubset();
|
||||
$glyphIndexArray = $font->getUnicodeCharMap();
|
||||
|
||||
$newGlyphIndexArray = array();
|
||||
foreach ($glyphIndexArray as $code => $gid) {
|
||||
$new_gid = array_search($gid, $subset);
|
||||
if ($new_gid !== false) {
|
||||
$newGlyphIndexArray[$code] = $new_gid;
|
||||
}
|
||||
}
|
||||
|
||||
ksort($newGlyphIndexArray); // Sort by char code
|
||||
|
||||
$segments = array();
|
||||
|
||||
$i = -1;
|
||||
$prevCode = 0xFFFF;
|
||||
$prevGid = 0xFFFF;
|
||||
|
||||
foreach ($newGlyphIndexArray as $code => $gid) {
|
||||
if (
|
||||
$prevCode + 1 != $code ||
|
||||
$prevGid + 1 != $gid
|
||||
) {
|
||||
$i++;
|
||||
$segments[$i] = array();
|
||||
}
|
||||
|
||||
$segments[$i][] = array($code, $gid);
|
||||
|
||||
$prevCode = $code;
|
||||
$prevGid = $gid;
|
||||
}
|
||||
|
||||
$segments[][] = array(0xFFFF, null);
|
||||
|
||||
$startCode = array();
|
||||
$endCode = array();
|
||||
$idDelta = array();
|
||||
|
||||
foreach ($segments as $codes) {
|
||||
$start = reset($codes);
|
||||
$end = end($codes);
|
||||
|
||||
$startCode[] = $start[0];
|
||||
$endCode[] = $end[0];
|
||||
$idDelta[] = $start[1] - $start[0];
|
||||
}
|
||||
|
||||
$segCount = count($startCode);
|
||||
$idRangeOffset = array_fill(0, $segCount, 0);
|
||||
|
||||
$searchRange = 1;
|
||||
$entrySelector = 0;
|
||||
while ($searchRange * 2 <= $segCount) {
|
||||
$searchRange *= 2;
|
||||
$entrySelector++;
|
||||
}
|
||||
$searchRange *= 2;
|
||||
$rangeShift = $segCount * 2 - $searchRange;
|
||||
|
||||
$subtables = array(
|
||||
array(
|
||||
// header
|
||||
"platformID" => 3, // Unicode
|
||||
"platformSpecificID" => 1,
|
||||
"offset" => null,
|
||||
|
||||
// subtable
|
||||
"format" => 4,
|
||||
"length" => null,
|
||||
"language" => 0,
|
||||
"segCount" => $segCount,
|
||||
"segCountX2" => $segCount * 2,
|
||||
"searchRange" => $searchRange,
|
||||
"entrySelector" => $entrySelector,
|
||||
"rangeShift" => $rangeShift,
|
||||
"startCode" => $startCode,
|
||||
"endCode" => $endCode,
|
||||
"idDelta" => $idDelta,
|
||||
"idRangeOffset" => $idRangeOffset,
|
||||
"glyphIndexArray" => $newGlyphIndexArray,
|
||||
)
|
||||
);
|
||||
|
||||
$data = array(
|
||||
"version" => 0,
|
||||
"numberSubtables" => count($subtables),
|
||||
"subtables" => $subtables,
|
||||
);
|
||||
|
||||
$length = $font->pack(self::$header_format, $data);
|
||||
|
||||
$subtable_headers_size = $data["numberSubtables"] * 8; // size of self::$subtable_header_format
|
||||
$subtable_headers_offset = $font->pos();
|
||||
|
||||
$length += $font->write(str_repeat("\0", $subtable_headers_size), $subtable_headers_size);
|
||||
|
||||
// write subtables data
|
||||
foreach ($data["subtables"] as $i => $subtable) {
|
||||
$length_before = $length;
|
||||
$data["subtables"][$i]["offset"] = $length;
|
||||
|
||||
$length += $font->writeUInt16($subtable["format"]);
|
||||
|
||||
$before_subheader = $font->pos();
|
||||
$length += $font->pack(self::$subtable_v4_format, $subtable);
|
||||
|
||||
$segCount = $subtable["segCount"];
|
||||
$length += $font->w(array(self::uint16, $segCount), $subtable["endCode"]);
|
||||
$length += $font->writeUInt16(0); // reservedPad
|
||||
$length += $font->w(array(self::uint16, $segCount), $subtable["startCode"]);
|
||||
$length += $font->w(array(self::int16, $segCount), $subtable["idDelta"]);
|
||||
$length += $font->w(array(self::uint16, $segCount), $subtable["idRangeOffset"]);
|
||||
$length += $font->w(array(self::uint16, $segCount), array_values($subtable["glyphIndexArray"]));
|
||||
|
||||
$after_subtable = $font->pos();
|
||||
|
||||
$subtable["length"] = $length - $length_before;
|
||||
$font->seek($before_subheader);
|
||||
$font->pack(self::$subtable_v4_format, $subtable);
|
||||
|
||||
$font->seek($after_subtable);
|
||||
}
|
||||
|
||||
// write subtables headers
|
||||
$font->seek($subtable_headers_offset);
|
||||
foreach ($data["subtables"] as $subtable) {
|
||||
$font->pack(self::$subtable_header_format, $subtable);
|
||||
}
|
||||
|
||||
return $length;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
<?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\Table\Type;
|
||||
use FontLib\Table\Table;
|
||||
|
||||
/**
|
||||
* `cvt ` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class cvt extends Table {
|
||||
private $rawData;
|
||||
protected function _parse() {
|
||||
$font = $this->getFont();
|
||||
$font->seek($this->entry->offset);
|
||||
$this->rawData = $font->read($this->entry->length);
|
||||
}
|
||||
function _encode() {
|
||||
return $this->getFont()->write($this->rawData, $this->entry->length);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
<?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\Table\Type;
|
||||
use FontLib\Table\Table;
|
||||
|
||||
/**
|
||||
* `fpgm` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class fpgm extends Table {
|
||||
private $rawData;
|
||||
protected function _parse() {
|
||||
$font = $this->getFont();
|
||||
$font->seek($this->entry->offset);
|
||||
$this->rawData = $font->read($this->entry->length);
|
||||
}
|
||||
function _encode() {
|
||||
return $this->getFont()->write($this->rawData, $this->entry->length);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\Table\Type;
|
||||
|
||||
use FontLib\Table\Table;
|
||||
use FontLib\Glyph\Outline;
|
||||
use FontLib\Glyph\OutlineSimple;
|
||||
|
||||
/**
|
||||
* `glyf` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
* @property Outline[] $data
|
||||
*/
|
||||
class glyf extends Table {
|
||||
protected function _parse() {
|
||||
$font = $this->getFont();
|
||||
$offset = $font->pos();
|
||||
|
||||
$loca = $font->getData("loca");
|
||||
$real_loca = array_slice($loca, 0, -1); // Not the last dummy loca entry
|
||||
|
||||
$data = array();
|
||||
|
||||
foreach ($real_loca as $gid => $location) {
|
||||
$_offset = $offset + $loca[$gid];
|
||||
$_size = $loca[$gid + 1] - $loca[$gid];
|
||||
$data[$gid] = Outline::init($this, $_offset, $_size, $font);
|
||||
}
|
||||
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function getGlyphIDs($gids = array()) {
|
||||
$glyphIDs = array();
|
||||
|
||||
foreach ($gids as $_gid) {
|
||||
$_glyph = $this->data[$_gid];
|
||||
$glyphIDs = array_merge($glyphIDs, $_glyph->getGlyphIDs());
|
||||
}
|
||||
|
||||
return array_unique(array_merge($gids, $glyphIDs));
|
||||
}
|
||||
|
||||
public function toHTML($n = 500) {
|
||||
$max = 160;
|
||||
$font = $this->getFont();
|
||||
|
||||
$head = $font->getData("head");
|
||||
$head_json = json_encode($head);
|
||||
|
||||
$os2 = $font->getData("OS/2");
|
||||
$os2_json = json_encode($os2);
|
||||
|
||||
$hmtx = $font->getData("hmtx");
|
||||
$hmtx_json = json_encode($hmtx);
|
||||
|
||||
$names = $font->getData("post", "names");
|
||||
$glyphIndexArray = array_flip($font->getUnicodeCharMap());
|
||||
|
||||
$width = (abs($head["xMin"]) + $head["xMax"]);
|
||||
$height = (abs($head["yMin"]) + $head["yMax"]);
|
||||
|
||||
$ratio = 1;
|
||||
if ($width > $max || $height > $max) {
|
||||
$ratio = max($width, $height) / $max;
|
||||
$width = round($width / $ratio);
|
||||
$height = round($height / $ratio);
|
||||
}
|
||||
|
||||
$s = "<h3>" . "Only the first $n simple glyphs are shown (" . count($this->data) . " total)
|
||||
<div class='glyph-view simple'>Simple glyph</div>
|
||||
<div class='glyph-view composite'>Composite glyph</div>
|
||||
Zoom: <input type='range' value='100' max='400' onchange='Glyph.resize(this.value)' />
|
||||
</h3>
|
||||
<script>
|
||||
Glyph.ratio = $ratio;
|
||||
Glyph.head = $head_json;
|
||||
Glyph.os2 = $os2_json;
|
||||
Glyph.hmtx = $hmtx_json;
|
||||
Glyph.width = $width;
|
||||
Glyph.height = $height;
|
||||
</script>";
|
||||
|
||||
foreach ($this->data as $g => $glyph) {
|
||||
if ($n-- <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
$glyph->parseData();
|
||||
|
||||
$shape = array(
|
||||
"SVGContours" => $glyph->getSVGContours(),
|
||||
"xMin" => $glyph->xMin,
|
||||
"yMin" => $glyph->yMin,
|
||||
"xMax" => $glyph->xMax,
|
||||
"yMax" => $glyph->yMax,
|
||||
);
|
||||
$shape_json = json_encode($shape);
|
||||
|
||||
$type = ($glyph instanceof OutlineSimple ? "simple" : "composite");
|
||||
$char = isset($glyphIndexArray[$g]) ? $glyphIndexArray[$g] : 0;
|
||||
$name = isset($names[$g]) ? $names[$g] : sprintf("uni%04x", $char);
|
||||
$char = $char ? "&#{$glyphIndexArray[$g]};" : "";
|
||||
|
||||
if ($char === "" && empty($shape["SVGContours"])) {
|
||||
$n++;
|
||||
continue;
|
||||
}
|
||||
|
||||
$s .= "<div class='glyph-view $type' id='glyph-$g'>
|
||||
<span class='glyph-id'>$g</span>
|
||||
<span class='char'>$char</span>
|
||||
<span class='char-name'>$name</span>
|
||||
";
|
||||
|
||||
if ($type == "composite") {
|
||||
foreach ($glyph->getGlyphIDs() as $_id) {
|
||||
$s .= "<a href='#glyph-$_id' class='glyph-component-id'>$_id</a> ";
|
||||
}
|
||||
}
|
||||
|
||||
$s .= "<br />
|
||||
<canvas width='$width' height='$height' id='glyph-canvas-$g'></canvas>
|
||||
</div>
|
||||
<script>Glyph.glyphs.push([$g,$shape_json]);</script>";
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
|
||||
protected function _encode() {
|
||||
$font = $this->getFont();
|
||||
$subset = $font->getSubset();
|
||||
$data = $this->data;
|
||||
|
||||
$loca = array();
|
||||
|
||||
$length = 0;
|
||||
foreach ($subset as $gid) {
|
||||
$loca[] = $length;
|
||||
|
||||
$bytes = $data[$gid]->encode();
|
||||
|
||||
$pad = 0;
|
||||
$mod = $bytes % 4;
|
||||
if ($mod != 0) {
|
||||
$pad = 4 - $mod;
|
||||
$font->write(str_pad("", $pad, "\0"), $pad);
|
||||
}
|
||||
$length += $bytes + $pad;
|
||||
}
|
||||
|
||||
$loca[] = $length; // dummy loca
|
||||
$font->getTableObject("loca")->data = $loca;
|
||||
|
||||
return $length;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\Table\Type;
|
||||
use FontLib\Table\Table;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* `head` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class head extends Table {
|
||||
protected $def = array(
|
||||
"tableVersion" => self::Fixed,
|
||||
"fontRevision" => self::Fixed,
|
||||
"checkSumAdjustment" => self::uint32,
|
||||
"magicNumber" => self::uint32,
|
||||
"flags" => self::uint16,
|
||||
"unitsPerEm" => self::uint16,
|
||||
"created" => self::longDateTime,
|
||||
"modified" => self::longDateTime,
|
||||
"xMin" => self::FWord,
|
||||
"yMin" => self::FWord,
|
||||
"xMax" => self::FWord,
|
||||
"yMax" => self::FWord,
|
||||
"macStyle" => self::uint16,
|
||||
"lowestRecPPEM" => self::uint16,
|
||||
"fontDirectionHint" => self::int16,
|
||||
"indexToLocFormat" => self::int16,
|
||||
"glyphDataFormat" => self::int16,
|
||||
);
|
||||
|
||||
protected function _parse() {
|
||||
parent::_parse();
|
||||
|
||||
if ($this->data["magicNumber"] != 0x5F0F3CF5) {
|
||||
throw new Exception("Incorrect magic number (" . dechex($this->data["magicNumber"]) . ")");
|
||||
}
|
||||
}
|
||||
|
||||
function _encode() {
|
||||
$this->data["checkSumAdjustment"] = 0;
|
||||
return parent::_encode();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\Table\Type;
|
||||
use FontLib\Table\Table;
|
||||
|
||||
/**
|
||||
* `hhea` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class hhea extends Table {
|
||||
protected $def = array(
|
||||
"version" => self::Fixed,
|
||||
"ascent" => self::FWord,
|
||||
"descent" => self::FWord,
|
||||
"lineGap" => self::FWord,
|
||||
"advanceWidthMax" => self::uFWord,
|
||||
"minLeftSideBearing" => self::FWord,
|
||||
"minRightSideBearing" => self::FWord,
|
||||
"xMaxExtent" => self::FWord,
|
||||
"caretSlopeRise" => self::int16,
|
||||
"caretSlopeRun" => self::int16,
|
||||
"caretOffset" => self::FWord,
|
||||
self::int16,
|
||||
self::int16,
|
||||
self::int16,
|
||||
self::int16,
|
||||
"metricDataFormat" => self::int16,
|
||||
"numOfLongHorMetrics" => self::uint16,
|
||||
);
|
||||
|
||||
function _encode() {
|
||||
$font = $this->getFont();
|
||||
$this->data["numOfLongHorMetrics"] = count($font->getSubset());
|
||||
|
||||
return parent::_encode();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\Table\Type;
|
||||
use FontLib\Table\Table;
|
||||
|
||||
/**
|
||||
* `hmtx` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class hmtx extends Table {
|
||||
protected function _parse() {
|
||||
$font = $this->getFont();
|
||||
$offset = $font->pos();
|
||||
|
||||
$numOfLongHorMetrics = $font->getData("hhea", "numOfLongHorMetrics");
|
||||
$numGlyphs = $font->getData("maxp", "numGlyphs");
|
||||
|
||||
$font->seek($offset);
|
||||
|
||||
$data = array();
|
||||
$metrics = $font->readUInt16Many($numOfLongHorMetrics * 2);
|
||||
for ($gid = 0, $mid = 0; $gid < $numOfLongHorMetrics; $gid++) {
|
||||
$advanceWidth = isset($metrics[$mid]) ? $metrics[$mid] : 0;
|
||||
$mid += 1;
|
||||
$leftSideBearing = isset($metrics[$mid]) ? $metrics[$mid] : 0;
|
||||
$mid += 1;
|
||||
$data[$gid] = array($advanceWidth, $leftSideBearing);
|
||||
}
|
||||
|
||||
if ($numOfLongHorMetrics < $numGlyphs) {
|
||||
$lastWidth = end($data)[0];
|
||||
$numLeft = $numGlyphs - $numOfLongHorMetrics;
|
||||
$metrics = $font->readUInt16Many($numLeft);
|
||||
for($i = 0; $i < $numLeft; $i++) {
|
||||
$gid = $numOfLongHorMetrics + $i;
|
||||
$leftSideBearing = isset($metrics[$i]) ? $metrics[$i] : 0;
|
||||
$data[$gid] = array($lastWidth, $leftSideBearing);
|
||||
}
|
||||
}
|
||||
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
protected function _encode() {
|
||||
$font = $this->getFont();
|
||||
$subset = $font->getSubset();
|
||||
$data = $this->data;
|
||||
|
||||
$length = 0;
|
||||
|
||||
foreach ($subset as $gid) {
|
||||
$length += $font->writeUInt16($data[$gid][0]);
|
||||
$length += $font->writeUInt16($data[$gid][1]);
|
||||
}
|
||||
|
||||
return $length;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\Table\Type;
|
||||
use FontLib\Table\Table;
|
||||
|
||||
/**
|
||||
* `kern` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class kern extends Table {
|
||||
protected function _parse() {
|
||||
$font = $this->getFont();
|
||||
|
||||
$data = $font->unpack(array(
|
||||
"version" => self::uint16,
|
||||
"nTables" => self::uint16,
|
||||
|
||||
// only the first subtable will be parsed
|
||||
"subtableVersion" => self::uint16,
|
||||
"length" => self::uint16,
|
||||
"coverage" => self::uint16,
|
||||
));
|
||||
|
||||
$data["format"] = ($data["coverage"] >> 8);
|
||||
|
||||
$subtable = array();
|
||||
|
||||
switch ($data["format"]) {
|
||||
case 0:
|
||||
$subtable = $font->unpack(array(
|
||||
"nPairs" => self::uint16,
|
||||
"searchRange" => self::uint16,
|
||||
"entrySelector" => self::uint16,
|
||||
"rangeShift" => self::uint16,
|
||||
));
|
||||
|
||||
$pairs = array();
|
||||
$tree = array();
|
||||
|
||||
$values = $font->readUInt16Many($subtable["nPairs"] * 3);
|
||||
for ($i = 0, $idx = 0; $i < $subtable["nPairs"]; $i++) {
|
||||
$left = $values[$idx++];
|
||||
$right = $values[$idx++];
|
||||
$value = $values[$idx++];
|
||||
|
||||
if ($value >= 0x8000) {
|
||||
$value -= 0x10000;
|
||||
}
|
||||
|
||||
$pairs[] = array(
|
||||
"left" => $left,
|
||||
"right" => $right,
|
||||
"value" => $value,
|
||||
);
|
||||
|
||||
$tree[$left][$right] = $value;
|
||||
}
|
||||
|
||||
//$subtable["pairs"] = $pairs;
|
||||
$subtable["tree"] = $tree;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
break;
|
||||
}
|
||||
|
||||
$data["subtable"] = $subtable;
|
||||
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\Table\Type;
|
||||
use FontLib\Table\Table;
|
||||
|
||||
/**
|
||||
* `loca` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class loca extends Table {
|
||||
protected function _parse() {
|
||||
$font = $this->getFont();
|
||||
$offset = $font->pos();
|
||||
|
||||
$indexToLocFormat = $font->getData("head", "indexToLocFormat");
|
||||
$numGlyphs = $font->getData("maxp", "numGlyphs");
|
||||
|
||||
$font->seek($offset);
|
||||
|
||||
$data = array();
|
||||
|
||||
// 2 bytes
|
||||
if ($indexToLocFormat == 0) {
|
||||
$d = $font->read(($numGlyphs + 1) * 2);
|
||||
$loc = unpack("n*", $d);
|
||||
|
||||
for ($i = 0; $i <= $numGlyphs; $i++) {
|
||||
$data[] = isset($loc[$i + 1]) ? $loc[$i + 1] * 2 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 4 bytes
|
||||
else {
|
||||
if ($indexToLocFormat == 1) {
|
||||
$d = $font->read(($numGlyphs + 1) * 4);
|
||||
$loc = unpack("N*", $d);
|
||||
|
||||
for ($i = 0; $i <= $numGlyphs; $i++) {
|
||||
$data[] = isset($loc[$i + 1]) ? $loc[$i + 1] : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
function _encode() {
|
||||
$font = $this->getFont();
|
||||
$data = $this->data;
|
||||
|
||||
$indexToLocFormat = $font->getData("head", "indexToLocFormat");
|
||||
$numGlyphs = $font->getData("maxp", "numGlyphs");
|
||||
$length = 0;
|
||||
|
||||
// 2 bytes
|
||||
if ($indexToLocFormat == 0) {
|
||||
for ($i = 0; $i <= $numGlyphs; $i++) {
|
||||
$length += $font->writeUInt16($data[$i] / 2);
|
||||
}
|
||||
}
|
||||
|
||||
// 4 bytes
|
||||
else {
|
||||
if ($indexToLocFormat == 1) {
|
||||
for ($i = 0; $i <= $numGlyphs; $i++) {
|
||||
$length += $font->writeUInt32($data[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $length;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\Table\Type;
|
||||
use FontLib\Table\Table;
|
||||
|
||||
/**
|
||||
* `maxp` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class maxp extends Table {
|
||||
protected $def = array(
|
||||
"version" => self::Fixed,
|
||||
"numGlyphs" => self::uint16,
|
||||
"maxPoints" => self::uint16,
|
||||
"maxContours" => self::uint16,
|
||||
"maxComponentPoints" => self::uint16,
|
||||
"maxComponentContours" => self::uint16,
|
||||
"maxZones" => self::uint16,
|
||||
"maxTwilightPoints" => self::uint16,
|
||||
"maxStorage" => self::uint16,
|
||||
"maxFunctionDefs" => self::uint16,
|
||||
"maxInstructionDefs" => self::uint16,
|
||||
"maxStackElements" => self::uint16,
|
||||
"maxSizeOfInstructions" => self::uint16,
|
||||
"maxComponentElements" => self::uint16,
|
||||
"maxComponentDepth" => self::uint16,
|
||||
);
|
||||
|
||||
function _encode() {
|
||||
$font = $this->getFont();
|
||||
$this->data["numGlyphs"] = count($font->getSubset());
|
||||
|
||||
return parent::_encode();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,242 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\Table\Type;
|
||||
|
||||
use FontLib\Table\Table;
|
||||
use FontLib\Font;
|
||||
|
||||
/**
|
||||
* `name` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class name extends Table {
|
||||
private static $header_format = array(
|
||||
"format" => self::uint16,
|
||||
"count" => self::uint16,
|
||||
"stringOffset" => self::uint16,
|
||||
);
|
||||
|
||||
const NAME_COPYRIGHT = 0;
|
||||
const NAME_NAME = 1;
|
||||
const NAME_SUBFAMILY = 2;
|
||||
const NAME_SUBFAMILY_ID = 3;
|
||||
const NAME_FULL_NAME = 4;
|
||||
const NAME_VERSION = 5;
|
||||
const NAME_POSTSCRIPT_NAME = 6;
|
||||
const NAME_TRADEMARK = 7;
|
||||
const NAME_MANUFACTURER = 8;
|
||||
const NAME_DESIGNER = 9;
|
||||
const NAME_DESCRIPTION = 10;
|
||||
const NAME_VENDOR_URL = 11;
|
||||
const NAME_DESIGNER_URL = 12;
|
||||
const NAME_LICENSE = 13;
|
||||
const NAME_LICENSE_URL = 14;
|
||||
const NAME_PREFERRE_FAMILY = 16;
|
||||
const NAME_PREFERRE_SUBFAMILY = 17;
|
||||
const NAME_COMPAT_FULL_NAME = 18;
|
||||
const NAME_SAMPLE_TEXT = 19;
|
||||
|
||||
static $nameIdCodes = array(
|
||||
0 => "Copyright",
|
||||
1 => "FontName",
|
||||
2 => "FontSubfamily",
|
||||
3 => "UniqueID",
|
||||
4 => "FullName",
|
||||
5 => "Version",
|
||||
6 => "PostScriptName",
|
||||
7 => "Trademark",
|
||||
8 => "Manufacturer",
|
||||
9 => "Designer",
|
||||
10 => "Description",
|
||||
11 => "FontVendorURL",
|
||||
12 => "FontDesignerURL",
|
||||
13 => "LicenseDescription",
|
||||
14 => "LicenseURL",
|
||||
// 15
|
||||
16 => "PreferredFamily",
|
||||
17 => "PreferredSubfamily",
|
||||
18 => "CompatibleFullName",
|
||||
19 => "SampleText",
|
||||
);
|
||||
|
||||
static $platforms = array(
|
||||
0 => "Unicode",
|
||||
1 => "Macintosh",
|
||||
// 2 => Reserved
|
||||
3 => "Microsoft",
|
||||
);
|
||||
|
||||
static $platformSpecific = array(
|
||||
// Unicode
|
||||
0 => array(
|
||||
0 => "Default semantics",
|
||||
1 => "Version 1.1 semantics",
|
||||
2 => "ISO 10646 1993 semantics (deprecated)",
|
||||
3 => "Unicode 2.0 or later semantics",
|
||||
),
|
||||
|
||||
// Macintosh
|
||||
1 => array(
|
||||
0 => "Roman",
|
||||
1 => "Japanese",
|
||||
2 => "Traditional Chinese",
|
||||
3 => "Korean",
|
||||
4 => "Arabic",
|
||||
5 => "Hebrew",
|
||||
6 => "Greek",
|
||||
7 => "Russian",
|
||||
8 => "RSymbol",
|
||||
9 => "Devanagari",
|
||||
10 => "Gurmukhi",
|
||||
11 => "Gujarati",
|
||||
12 => "Oriya",
|
||||
13 => "Bengali",
|
||||
14 => "Tamil",
|
||||
15 => "Telugu",
|
||||
16 => "Kannada",
|
||||
17 => "Malayalam",
|
||||
18 => "Sinhalese",
|
||||
19 => "Burmese",
|
||||
20 => "Khmer",
|
||||
21 => "Thai",
|
||||
22 => "Laotian",
|
||||
23 => "Georgian",
|
||||
24 => "Armenian",
|
||||
25 => "Simplified Chinese",
|
||||
26 => "Tibetan",
|
||||
27 => "Mongolian",
|
||||
28 => "Geez",
|
||||
29 => "Slavic",
|
||||
30 => "Vietnamese",
|
||||
31 => "Sindhi",
|
||||
),
|
||||
|
||||
// Microsoft
|
||||
3 => array(
|
||||
0 => "Symbol",
|
||||
1 => "Unicode BMP (UCS-2)",
|
||||
2 => "ShiftJIS",
|
||||
3 => "PRC",
|
||||
4 => "Big5",
|
||||
5 => "Wansung",
|
||||
6 => "Johab",
|
||||
// 7 => Reserved
|
||||
// 8 => Reserved
|
||||
// 9 => Reserved
|
||||
10 => "Unicode UCS-4",
|
||||
),
|
||||
);
|
||||
|
||||
protected function _parse() {
|
||||
$font = $this->getFont();
|
||||
|
||||
$tableOffset = $font->pos();
|
||||
|
||||
$data = $font->unpack(self::$header_format);
|
||||
|
||||
$records = array();
|
||||
for ($i = 0; $i < $data["count"]; $i++) {
|
||||
$record = new nameRecord();
|
||||
$record_data = $font->unpack(nameRecord::$format);
|
||||
$record->map($record_data);
|
||||
|
||||
$records[] = $record;
|
||||
}
|
||||
|
||||
$system_encodings = mb_list_encodings();
|
||||
$system_encodings = array_change_key_case(array_fill_keys($system_encodings, true), CASE_UPPER);
|
||||
|
||||
$names = array();
|
||||
foreach ($records as $record) {
|
||||
$font->seek($tableOffset + $data["stringOffset"] + $record->offset);
|
||||
$record->stringRaw = $font->read($record->length);
|
||||
|
||||
$encoding = null;
|
||||
switch ($record->platformID) {
|
||||
case 3:
|
||||
switch ($record->platformSpecificID) {
|
||||
case 2:
|
||||
if (\array_key_exists("SJIS", $system_encodings)) {
|
||||
$encoding = "SJIS";
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (\array_key_exists("GB18030", $system_encodings)) {
|
||||
$encoding = "GB18030";
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (\array_key_exists("BIG-5", $system_encodings)) {
|
||||
$encoding = "BIG-5";
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (\array_key_exists("UHC", $system_encodings)) {
|
||||
$encoding = "UHC";
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ($encoding === null) {
|
||||
$encoding = "UTF-16";
|
||||
}
|
||||
|
||||
$record->string = mb_convert_encoding($record->stringRaw, "UTF-8", $encoding);
|
||||
if (strpos($record->string, "\0") !== false) {
|
||||
$record->string = str_replace("\0", "", $record->string);
|
||||
}
|
||||
$names[$record->nameID] = $record;
|
||||
}
|
||||
|
||||
$data["records"] = $names;
|
||||
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
protected function _encode() {
|
||||
$font = $this->getFont();
|
||||
|
||||
/** @var nameRecord[] $records */
|
||||
$records = $this->data["records"];
|
||||
$count_records = \count($records);
|
||||
|
||||
$this->data["count"] = $count_records;
|
||||
$this->data["stringOffset"] = 6 + ($count_records * 12); // 6 => uint16 * 3, 12 => sizeof self::$record_format
|
||||
|
||||
$length = $font->pack(self::$header_format, $this->data);
|
||||
|
||||
$offset = 0;
|
||||
|
||||
/** @var nameRecord[] $records_to_encode */
|
||||
$records_to_encode = array();
|
||||
foreach ($records as $record) {
|
||||
$encoded_record = new nameRecord();
|
||||
$encoded_record->platformID = 3;
|
||||
$encoded_record->platformSpecificID = 1;
|
||||
$encoded_record->languageID = $record->languageID;
|
||||
$encoded_record->nameID = $record->nameID;
|
||||
$encoded_record->offset = $offset;
|
||||
$encoded_record->string = $record->string;
|
||||
$encoded_record->length = mb_strlen($encoded_record->getUTF16(), "8bit");
|
||||
$records_to_encode[] = $encoded_record;
|
||||
|
||||
$offset += $encoded_record->length;
|
||||
$length += $font->pack(nameRecord::$format, (array)$encoded_record);
|
||||
}
|
||||
|
||||
foreach ($records_to_encode as $record) {
|
||||
$str = $record->getUTF16();
|
||||
$length += $font->write($str, mb_strlen($str, "8bit"));
|
||||
}
|
||||
|
||||
return $length;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\Table\Type;
|
||||
|
||||
use FontLib\Font;
|
||||
use FontLib\BinaryStream;
|
||||
|
||||
/**
|
||||
* Font table name record.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class nameRecord extends BinaryStream {
|
||||
public $platformID;
|
||||
public $platformSpecificID;
|
||||
public $languageID;
|
||||
public $nameID;
|
||||
public $length;
|
||||
public $offset;
|
||||
public $string;
|
||||
public $stringRaw;
|
||||
|
||||
public static $format = array(
|
||||
"platformID" => self::uint16,
|
||||
"platformSpecificID" => self::uint16,
|
||||
"languageID" => self::uint16,
|
||||
"nameID" => self::uint16,
|
||||
"length" => self::uint16,
|
||||
"offset" => self::uint16,
|
||||
);
|
||||
|
||||
public function map($data) {
|
||||
foreach ($data as $key => $value) {
|
||||
$this->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function getUTF8() {
|
||||
return $this->string;
|
||||
}
|
||||
|
||||
public function getUTF16() {
|
||||
return Font::UTF8ToUTF16($this->string);
|
||||
}
|
||||
|
||||
function __toString() {
|
||||
return $this->string;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\Table\Type;
|
||||
use FontLib\Table\Table;
|
||||
|
||||
/**
|
||||
* `OS/2` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class os2 extends Table {
|
||||
protected $def = array(
|
||||
"version" => self::uint16,
|
||||
"xAvgCharWidth" => self::int16,
|
||||
"usWeightClass" => self::uint16,
|
||||
"usWidthClass" => self::uint16,
|
||||
"fsType" => self::int16,
|
||||
"ySubscriptXSize" => self::int16,
|
||||
"ySubscriptYSize" => self::int16,
|
||||
"ySubscriptXOffset" => self::int16,
|
||||
"ySubscriptYOffset" => self::int16,
|
||||
"ySuperscriptXSize" => self::int16,
|
||||
"ySuperscriptYSize" => self::int16,
|
||||
"ySuperscriptXOffset" => self::int16,
|
||||
"ySuperscriptYOffset" => self::int16,
|
||||
"yStrikeoutSize" => self::int16,
|
||||
"yStrikeoutPosition" => self::int16,
|
||||
"sFamilyClass" => self::int16,
|
||||
"panose" => array(self::uint8, 10),
|
||||
"ulCharRange" => array(self::uint32, 4),
|
||||
"achVendID" => array(self::char, 4),
|
||||
"fsSelection" => self::uint16,
|
||||
"fsFirstCharIndex" => self::uint16,
|
||||
"fsLastCharIndex" => self::uint16,
|
||||
"typoAscender" => self::int16,
|
||||
"typoDescender" => self::int16,
|
||||
"typoLineGap" => self::int16,
|
||||
"winAscent" => self::int16,
|
||||
"winDescent" => self::int16,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,143 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\Table\Type;
|
||||
use FontLib\Table\Table;
|
||||
use FontLib\TrueType\File;
|
||||
|
||||
/**
|
||||
* `post` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class post extends Table {
|
||||
protected $def = array(
|
||||
"format" => self::Fixed,
|
||||
"italicAngle" => self::Fixed,
|
||||
"underlinePosition" => self::FWord,
|
||||
"underlineThickness" => self::FWord,
|
||||
"isFixedPitch" => self::uint32,
|
||||
"minMemType42" => self::uint32,
|
||||
"maxMemType42" => self::uint32,
|
||||
"minMemType1" => self::uint32,
|
||||
"maxMemType1" => self::uint32,
|
||||
);
|
||||
|
||||
protected function _parse() {
|
||||
$font = $this->getFont();
|
||||
$data = $font->unpack($this->def);
|
||||
|
||||
$names = array();
|
||||
|
||||
switch ($data["format"]) {
|
||||
case 1:
|
||||
$names = File::$macCharNames;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
$data["numberOfGlyphs"] = $font->readUInt16();
|
||||
|
||||
$glyphNameIndex = $font->readUInt16Many($data["numberOfGlyphs"]);
|
||||
|
||||
$data["glyphNameIndex"] = $glyphNameIndex;
|
||||
|
||||
$namesPascal = array();
|
||||
for ($i = 0; $i < $data["numberOfGlyphs"]; $i++) {
|
||||
$len = $font->readUInt8();
|
||||
$namesPascal[] = $font->read($len);
|
||||
}
|
||||
|
||||
foreach ($glyphNameIndex as $g => $index) {
|
||||
if ($index < 258) {
|
||||
$names[$g] = File::$macCharNames[$index];
|
||||
}
|
||||
else {
|
||||
if (array_key_exists($index - 258, $namesPascal)) {
|
||||
$names[$g] = $namesPascal[$index - 258];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 2.5:
|
||||
// TODO
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// nothing
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
|
||||
$data["names"] = $names;
|
||||
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
function _encode() {
|
||||
$font = $this->getFont();
|
||||
$data = $this->data;
|
||||
$data["format"] = 3;
|
||||
|
||||
$length = $font->pack($this->def, $data);
|
||||
|
||||
return $length;
|
||||
/*
|
||||
$subset = $font->getSubset();
|
||||
|
||||
switch($data["format"]) {
|
||||
case 1:
|
||||
// nothing to do
|
||||
break;
|
||||
|
||||
case 2:
|
||||
$old_names = $data["names"];
|
||||
|
||||
$glyphNameIndex = range(0, count($subset));
|
||||
|
||||
$names = array();
|
||||
foreach($subset as $gid) {
|
||||
$names[] = $data["names"][$data["glyphNameIndex"][$gid]];
|
||||
}
|
||||
|
||||
$numberOfGlyphs = count($names);
|
||||
$length += $font->writeUInt16($numberOfGlyphs);
|
||||
|
||||
foreach($glyphNameIndex as $gni) {
|
||||
$length += $font->writeUInt16($gni);
|
||||
}
|
||||
|
||||
//$names = array_slice($names, 257);
|
||||
foreach($names as $name) {
|
||||
$len = strlen($name);
|
||||
$length += $font->writeUInt8($len);
|
||||
$length += $font->write($name, $len);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 2.5:
|
||||
// TODO
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// nothing
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
|
||||
return $length;*/
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
<?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\Table\Type;
|
||||
|
||||
use FontLib\Table\Table;
|
||||
|
||||
/**
|
||||
* `prep` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class prep extends Table
|
||||
{
|
||||
private $rawData;
|
||||
protected function _parse() {
|
||||
$font = $this->getFont();
|
||||
$font->seek($this->entry->offset);
|
||||
$this->rawData = $font->read($this->entry->length);
|
||||
}
|
||||
function _encode() {
|
||||
return $this->getFont()->write($this->rawData, $this->entry->length);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\TrueType;
|
||||
|
||||
use Countable;
|
||||
use FontLib\BinaryStream;
|
||||
use Iterator;
|
||||
use OutOfBoundsException;
|
||||
|
||||
/**
|
||||
* TrueType collection font file.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class Collection extends BinaryStream implements Iterator, Countable {
|
||||
/**
|
||||
* Current iterator position.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $position = 0;
|
||||
|
||||
protected $collectionOffsets = array();
|
||||
protected $collection = array();
|
||||
protected $version;
|
||||
protected $numFonts;
|
||||
|
||||
function parse() {
|
||||
if (isset($this->numFonts)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->read(4); // tag name
|
||||
|
||||
$this->version = $this->readFixed();
|
||||
$this->numFonts = $this->readUInt32();
|
||||
|
||||
for ($i = 0; $i < $this->numFonts; $i++) {
|
||||
$this->collectionOffsets[] = $this->readUInt32();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $fontId
|
||||
*
|
||||
* @throws OutOfBoundsException
|
||||
* @return File
|
||||
*/
|
||||
function getFont($fontId) {
|
||||
$this->parse();
|
||||
|
||||
if (!isset($this->collectionOffsets[$fontId])) {
|
||||
throw new OutOfBoundsException();
|
||||
}
|
||||
|
||||
if (isset($this->collection[$fontId])) {
|
||||
return $this->collection[$fontId];
|
||||
}
|
||||
|
||||
$font = new File();
|
||||
$font->f = $this->f;
|
||||
$font->setTableOffset($this->collectionOffsets[$fontId]);
|
||||
|
||||
return $this->collection[$fontId] = $font;
|
||||
}
|
||||
|
||||
function current() {
|
||||
return $this->getFont($this->position);
|
||||
}
|
||||
|
||||
function key() {
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
function next() {
|
||||
return ++$this->position;
|
||||
}
|
||||
|
||||
function rewind() {
|
||||
$this->position = 0;
|
||||
}
|
||||
|
||||
function valid() {
|
||||
$this->parse();
|
||||
|
||||
return isset($this->collectionOffsets[$this->position]);
|
||||
}
|
||||
|
||||
function count() {
|
||||
$this->parse();
|
||||
|
||||
return $this->numFonts;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,591 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\TrueType;
|
||||
|
||||
use FontLib\AdobeFontMetrics;
|
||||
use FontLib\Font;
|
||||
use FontLib\BinaryStream;
|
||||
use FontLib\Table\Table;
|
||||
use FontLib\Table\DirectoryEntry;
|
||||
use FontLib\Table\Type\glyf;
|
||||
use FontLib\Table\Type\name;
|
||||
use FontLib\Table\Type\nameRecord;
|
||||
|
||||
/**
|
||||
* TrueType font file.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class File extends BinaryStream {
|
||||
/**
|
||||
* @var Header
|
||||
*/
|
||||
public $header = array();
|
||||
|
||||
private $tableOffset = 0; // Used for TTC
|
||||
|
||||
private static $raw = false;
|
||||
|
||||
protected $directory = array();
|
||||
protected $data = array();
|
||||
|
||||
protected $glyph_subset = array();
|
||||
|
||||
public $glyph_all = array();
|
||||
|
||||
static $macCharNames = array(
|
||||
".notdef", ".null", "CR",
|
||||
"space", "exclam", "quotedbl", "numbersign",
|
||||
"dollar", "percent", "ampersand", "quotesingle",
|
||||
"parenleft", "parenright", "asterisk", "plus",
|
||||
"comma", "hyphen", "period", "slash",
|
||||
"zero", "one", "two", "three",
|
||||
"four", "five", "six", "seven",
|
||||
"eight", "nine", "colon", "semicolon",
|
||||
"less", "equal", "greater", "question",
|
||||
"at", "A", "B", "C", "D", "E", "F", "G",
|
||||
"H", "I", "J", "K", "L", "M", "N", "O",
|
||||
"P", "Q", "R", "S", "T", "U", "V", "W",
|
||||
"X", "Y", "Z", "bracketleft",
|
||||
"backslash", "bracketright", "asciicircum", "underscore",
|
||||
"grave", "a", "b", "c", "d", "e", "f", "g",
|
||||
"h", "i", "j", "k", "l", "m", "n", "o",
|
||||
"p", "q", "r", "s", "t", "u", "v", "w",
|
||||
"x", "y", "z", "braceleft",
|
||||
"bar", "braceright", "asciitilde", "Adieresis",
|
||||
"Aring", "Ccedilla", "Eacute", "Ntilde",
|
||||
"Odieresis", "Udieresis", "aacute", "agrave",
|
||||
"acircumflex", "adieresis", "atilde", "aring",
|
||||
"ccedilla", "eacute", "egrave", "ecircumflex",
|
||||
"edieresis", "iacute", "igrave", "icircumflex",
|
||||
"idieresis", "ntilde", "oacute", "ograve",
|
||||
"ocircumflex", "odieresis", "otilde", "uacute",
|
||||
"ugrave", "ucircumflex", "udieresis", "dagger",
|
||||
"degree", "cent", "sterling", "section",
|
||||
"bullet", "paragraph", "germandbls", "registered",
|
||||
"copyright", "trademark", "acute", "dieresis",
|
||||
"notequal", "AE", "Oslash", "infinity",
|
||||
"plusminus", "lessequal", "greaterequal", "yen",
|
||||
"mu", "partialdiff", "summation", "product",
|
||||
"pi", "integral", "ordfeminine", "ordmasculine",
|
||||
"Omega", "ae", "oslash", "questiondown",
|
||||
"exclamdown", "logicalnot", "radical", "florin",
|
||||
"approxequal", "increment", "guillemotleft", "guillemotright",
|
||||
"ellipsis", "nbspace", "Agrave", "Atilde",
|
||||
"Otilde", "OE", "oe", "endash",
|
||||
"emdash", "quotedblleft", "quotedblright", "quoteleft",
|
||||
"quoteright", "divide", "lozenge", "ydieresis",
|
||||
"Ydieresis", "fraction", "currency", "guilsinglleft",
|
||||
"guilsinglright", "fi", "fl", "daggerdbl",
|
||||
"periodcentered", "quotesinglbase", "quotedblbase", "perthousand",
|
||||
"Acircumflex", "Ecircumflex", "Aacute", "Edieresis",
|
||||
"Egrave", "Iacute", "Icircumflex", "Idieresis",
|
||||
"Igrave", "Oacute", "Ocircumflex", "applelogo",
|
||||
"Ograve", "Uacute", "Ucircumflex", "Ugrave",
|
||||
"dotlessi", "circumflex", "tilde", "macron",
|
||||
"breve", "dotaccent", "ring", "cedilla",
|
||||
"hungarumlaut", "ogonek", "caron", "Lslash",
|
||||
"lslash", "Scaron", "scaron", "Zcaron",
|
||||
"zcaron", "brokenbar", "Eth", "eth",
|
||||
"Yacute", "yacute", "Thorn", "thorn",
|
||||
"minus", "multiply", "onesuperior", "twosuperior",
|
||||
"threesuperior", "onehalf", "onequarter", "threequarters",
|
||||
"franc", "Gbreve", "gbreve", "Idot",
|
||||
"Scedilla", "scedilla", "Cacute", "cacute",
|
||||
"Ccaron", "ccaron", "dmacron"
|
||||
);
|
||||
|
||||
private function uniord (string $c, string $encoding = null) {
|
||||
if (function_exists("mb_ord")) {
|
||||
if (PHP_VERSION_ID < 80000 && $encoding === null) {
|
||||
// in PHP < 8 the encoding argument, if supplied, must be a valid encoding
|
||||
$encoding = "UTF-8";
|
||||
}
|
||||
return mb_ord($c, $encoding);
|
||||
}
|
||||
|
||||
if ($encoding != "UTF-8" && $encoding !== null) {
|
||||
$c = mb_convert_encoding($c, "UTF-8", $encoding);
|
||||
}
|
||||
|
||||
$length = mb_strlen(mb_substr($c, 0, 1), '8bit');
|
||||
$ord = false;
|
||||
$bytes = [];
|
||||
$numbytes = 1;
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$o = \ord($c[$i]); // get one string character at time
|
||||
if (\count($bytes) === 0) { // get starting octect
|
||||
if ($o <= 0x7F) {
|
||||
$ord = $o;
|
||||
$numbytes = 1;
|
||||
} elseif (($o >> 0x05) === 0x06) { // 2 bytes character (0x06 = 110 BIN)
|
||||
$bytes[] = ($o - 0xC0) << 0x06;
|
||||
$numbytes = 2;
|
||||
} elseif (($o >> 0x04) === 0x0E) { // 3 bytes character (0x0E = 1110 BIN)
|
||||
$bytes[] = ($o - 0xE0) << 0x0C;
|
||||
$numbytes = 3;
|
||||
} elseif (($o >> 0x03) === 0x1E) { // 4 bytes character (0x1E = 11110 BIN)
|
||||
$bytes[] = ($o - 0xF0) << 0x12;
|
||||
$numbytes = 4;
|
||||
} else {
|
||||
$ord = false;
|
||||
break;
|
||||
}
|
||||
} elseif (($o >> 0x06) === 0x02) { // bytes 2, 3 and 4 must start with 0x02 = 10 BIN
|
||||
$bytes[] = $o - 0x80;
|
||||
if (\count($bytes) === $numbytes) {
|
||||
// compose UTF-8 bytes to a single unicode value
|
||||
$o = $bytes[0];
|
||||
for ($j = 1; $j < $numbytes; $j++) {
|
||||
$o += ($bytes[$j] << (($numbytes - $j - 1) * 0x06));
|
||||
}
|
||||
if ((($o >= 0xD800) and ($o <= 0xDFFF)) or ($o >= 0x10FFFF)) {
|
||||
// The definition of UTF-8 prohibits encoding character numbers between
|
||||
// U+D800 and U+DFFF, which are reserved for use with the UTF-16
|
||||
// encoding form (as surrogate pairs) and do not directly represent
|
||||
// characters.
|
||||
return false;
|
||||
} else {
|
||||
$ord = $o; // add char to array
|
||||
}
|
||||
// reset data for next char
|
||||
$bytes = [];
|
||||
$numbytes = 1;
|
||||
}
|
||||
} else {
|
||||
$ord = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $ord;
|
||||
}
|
||||
|
||||
function getTable() {
|
||||
$this->parseTableEntries();
|
||||
|
||||
return $this->directory;
|
||||
}
|
||||
|
||||
function setTableOffset($offset) {
|
||||
$this->tableOffset = $offset;
|
||||
}
|
||||
|
||||
function parse() {
|
||||
$this->parseTableEntries();
|
||||
|
||||
$this->data = array();
|
||||
|
||||
foreach ($this->directory as $tag => $table) {
|
||||
if (empty($this->data[$tag])) {
|
||||
$this->readTable($tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function utf8toUnicode($str) {
|
||||
$len = mb_strlen($str, '8bit');
|
||||
$out = array();
|
||||
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$uni = -1;
|
||||
$h = ord($str[$i]);
|
||||
|
||||
if ($h <= 0x7F) {
|
||||
$uni = $h;
|
||||
}
|
||||
elseif ($h >= 0xC2) {
|
||||
if (($h <= 0xDF) && ($i < $len - 1)) {
|
||||
$uni = ($h & 0x1F) << 6 | (ord($str[++$i]) & 0x3F);
|
||||
}
|
||||
elseif (($h <= 0xEF) && ($i < $len - 2)) {
|
||||
$uni = ($h & 0x0F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
|
||||
}
|
||||
elseif (($h <= 0xF4) && ($i < $len - 3)) {
|
||||
$uni = ($h & 0x0F) << 18 | (ord($str[++$i]) & 0x3F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
|
||||
}
|
||||
}
|
||||
|
||||
if ($uni >= 0) {
|
||||
$out[] = $uni;
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
function getUnicodeCharMap() {
|
||||
$subtable = null;
|
||||
foreach ($this->getData("cmap", "subtables") as $_subtable) {
|
||||
if ($_subtable["platformID"] == 0 || ($_subtable["platformID"] == 3 && $_subtable["platformSpecificID"] == 1)) {
|
||||
$subtable = $_subtable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($subtable) {
|
||||
return $subtable["glyphIndexArray"];
|
||||
}
|
||||
|
||||
$system_encodings = mb_list_encodings();
|
||||
$system_encodings = array_change_key_case(array_fill_keys($system_encodings, true), CASE_UPPER);
|
||||
foreach ($this->getData("cmap", "subtables") as $_subtable) {
|
||||
$encoding = null;
|
||||
switch ($_subtable["platformID"]) {
|
||||
case 3:
|
||||
switch ($_subtable["platformSpecificID"]) {
|
||||
case 2:
|
||||
if (\array_key_exists("SJIS", $system_encodings)) {
|
||||
$encoding = "SJIS";
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (\array_key_exists("GB18030", $system_encodings)) {
|
||||
$encoding = "GB18030";
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (\array_key_exists("BIG-5", $system_encodings)) {
|
||||
$encoding = "BIG-5";
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (\array_key_exists("UHC", $system_encodings)) {
|
||||
$encoding = "UHC";
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ($encoding) {
|
||||
$glyphIndexArray = array();
|
||||
foreach ($_subtable["glyphIndexArray"] as $c => $gid) {
|
||||
$str = trim(pack("N", $c));
|
||||
if (\strlen($str) > 0) {
|
||||
$ord = $this->uniord($str, $encoding);
|
||||
if ($ord > 0) {
|
||||
$glyphIndexArray[$ord] = $gid;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $glyphIndexArray;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function setSubset($subset) {
|
||||
if (!is_array($subset)) {
|
||||
$subset = $this->utf8toUnicode($subset);
|
||||
}
|
||||
|
||||
$subset = array_unique($subset);
|
||||
|
||||
$glyphIndexArray = $this->getUnicodeCharMap();
|
||||
|
||||
if (!$glyphIndexArray) {
|
||||
return;
|
||||
}
|
||||
|
||||
$gids = array(
|
||||
0, // .notdef
|
||||
1, // .null
|
||||
);
|
||||
|
||||
foreach ($subset as $code) {
|
||||
if (!isset($glyphIndexArray[$code])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$gid = $glyphIndexArray[$code];
|
||||
$gids[$gid] = $gid;
|
||||
}
|
||||
|
||||
/** @var glyf $glyf */
|
||||
$glyf = $this->getTableObject("glyf");
|
||||
if ($glyf) {
|
||||
$gids = $glyf->getGlyphIDs($gids);
|
||||
sort($gids);
|
||||
$this->glyph_subset = $gids;
|
||||
}
|
||||
$this->glyph_all = array_values($glyphIndexArray); // FIXME
|
||||
}
|
||||
|
||||
function getSubset() {
|
||||
if (empty($this->glyph_subset)) {
|
||||
return $this->glyph_all;
|
||||
}
|
||||
|
||||
return $this->glyph_subset;
|
||||
}
|
||||
|
||||
function encode($tags = array()) {
|
||||
if (!self::$raw) {
|
||||
$tags = array_merge(array("head", "hhea", "cmap", "hmtx", "maxp", "glyf", "loca", "name", "post", "cvt ", "fpgm", "prep"), $tags);
|
||||
}
|
||||
else {
|
||||
$tags = array_keys($this->directory);
|
||||
}
|
||||
|
||||
$n = 16; // @todo
|
||||
|
||||
Font::d("Tables : " . implode(", ", $tags));
|
||||
|
||||
/** @var DirectoryEntry[] $entries */
|
||||
$entries = array();
|
||||
foreach ($tags as $tag) {
|
||||
if (!isset($this->directory[$tag])) {
|
||||
Font::d(" >> '$tag' table doesn't exist");
|
||||
continue;
|
||||
}
|
||||
|
||||
$entries[$tag] = $this->directory[$tag];
|
||||
}
|
||||
|
||||
$num_tables = count($entries);
|
||||
$exponent = floor(log($num_tables, 2));
|
||||
$power_of_two = pow(2, $exponent);
|
||||
|
||||
$this->header->data["numTables"] = $num_tables;
|
||||
$this->header->data["searchRange"] = $power_of_two * 16;
|
||||
$this->header->data["entrySelector"] = log($power_of_two, 2);
|
||||
$this->header->data["rangeShift"] = $num_tables * 16 - $this->header->data["searchRange"];
|
||||
$this->header->encode();
|
||||
|
||||
$directory_offset = $this->pos();
|
||||
$offset = $directory_offset + $num_tables * $n;
|
||||
$this->seek($offset);
|
||||
|
||||
$i = 0;
|
||||
foreach ($entries as $entry) {
|
||||
$entry->encode($directory_offset + $i * $n);
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
function parseHeader() {
|
||||
if (!empty($this->header)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->seek($this->tableOffset);
|
||||
|
||||
$this->header = new Header($this);
|
||||
$this->header->parse();
|
||||
}
|
||||
|
||||
function getFontType(){
|
||||
$class_parts = explode("\\", get_class($this));
|
||||
return $class_parts[1];
|
||||
}
|
||||
|
||||
function parseTableEntries() {
|
||||
$this->parseHeader();
|
||||
|
||||
if (!empty($this->directory)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($this->header->data["numTables"])) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$type = $this->getFontType();
|
||||
$class = "FontLib\\$type\\TableDirectoryEntry";
|
||||
|
||||
for ($i = 0; $i < $this->header->data["numTables"]; $i++) {
|
||||
/** @var TableDirectoryEntry $entry */
|
||||
$entry = new $class($this);
|
||||
$entry->parse();
|
||||
|
||||
$this->directory[$entry->tag] = $entry;
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeFUnit($value, $base = 1000) {
|
||||
return round($value * ($base / $this->getData("head", "unitsPerEm")));
|
||||
}
|
||||
|
||||
protected function readTable($tag) {
|
||||
$this->parseTableEntries();
|
||||
|
||||
if (!self::$raw) {
|
||||
$name_canon = preg_replace("/[^a-z0-9]/", "", strtolower($tag));
|
||||
|
||||
$class = "FontLib\\Table\\Type\\$name_canon";
|
||||
|
||||
if (!isset($this->directory[$tag]) || !@class_exists($class)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$class = "FontLib\\Table\\Table";
|
||||
}
|
||||
|
||||
/** @var Table $table */
|
||||
$table = new $class($this->directory[$tag]);
|
||||
$table->parse();
|
||||
|
||||
$this->data[$tag] = $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return Table
|
||||
*/
|
||||
public function getTableObject($name) {
|
||||
if (\array_key_exists($name, $this->data)) {
|
||||
return $this->data[$name];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setTableObject($name, Table $data) {
|
||||
$this->data[$name] = $data;
|
||||
}
|
||||
|
||||
public function getData($name, $key = null) {
|
||||
$this->parseTableEntries();
|
||||
|
||||
if (empty($this->data[$name])) {
|
||||
$this->readTable($name);
|
||||
}
|
||||
|
||||
if (!isset($this->data[$name])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$key) {
|
||||
return $this->data[$name]->data;
|
||||
}
|
||||
else {
|
||||
return $this->data[$name]->data[$key];
|
||||
}
|
||||
}
|
||||
|
||||
function addDirectoryEntry(DirectoryEntry $entry) {
|
||||
$this->directory[$entry->tag] = $entry;
|
||||
}
|
||||
|
||||
function saveAdobeFontMetrics($file, $encoding = null) {
|
||||
$afm = new AdobeFontMetrics($this);
|
||||
$afm->write($file, $encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific name table string value from its ID
|
||||
*
|
||||
* @param int $nameID The name ID
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getNameTableString($nameID) {
|
||||
/** @var nameRecord[] $records */
|
||||
$records = $this->getData("name", "records");
|
||||
|
||||
if (!isset($records[$nameID])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $records[$nameID]->string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font copyright
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontCopyright() {
|
||||
return $this->getNameTableString(name::NAME_COPYRIGHT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font name
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontName() {
|
||||
return $this->getNameTableString(name::NAME_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font subfamily
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontSubfamily() {
|
||||
return $this->getNameTableString(name::NAME_SUBFAMILY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font subfamily ID
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontSubfamilyID() {
|
||||
return $this->getNameTableString(name::NAME_SUBFAMILY_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font full name
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontFullName() {
|
||||
return $this->getNameTableString(name::NAME_FULL_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font version
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontVersion() {
|
||||
return $this->getNameTableString(name::NAME_VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font weight
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontWeight() {
|
||||
return $this->getTableObject("OS/2")->data["usWeightClass"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font Postscript name
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getFontPostscriptName() {
|
||||
return $this->getNameTableString(name::NAME_POSTSCRIPT_NAME);
|
||||
}
|
||||
|
||||
function reduce() {
|
||||
$names_to_keep = array(
|
||||
name::NAME_COPYRIGHT,
|
||||
name::NAME_NAME,
|
||||
name::NAME_SUBFAMILY,
|
||||
name::NAME_SUBFAMILY_ID,
|
||||
name::NAME_FULL_NAME,
|
||||
name::NAME_VERSION,
|
||||
name::NAME_POSTSCRIPT_NAME,
|
||||
);
|
||||
|
||||
foreach ($this->data["name"]->data["records"] as $id => $rec) {
|
||||
if (!in_array($id, $names_to_keep)) {
|
||||
unset($this->data["name"]->data["records"][$id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\TrueType;
|
||||
|
||||
/**
|
||||
* TrueType font file header.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class Header extends \FontLib\Header {
|
||||
protected $def = array(
|
||||
"format" => self::uint32,
|
||||
"numTables" => self::uint16,
|
||||
"searchRange" => self::uint16,
|
||||
"entrySelector" => self::uint16,
|
||||
"rangeShift" => self::uint16,
|
||||
);
|
||||
|
||||
public function parse() {
|
||||
parent::parse();
|
||||
|
||||
$format = $this->data["format"];
|
||||
$this->data["formatText"] = $this->convertUInt32ToStr($format);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/dompdf/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\TrueType;
|
||||
|
||||
use FontLib\Table\DirectoryEntry;
|
||||
|
||||
/**
|
||||
* TrueType table directory entry.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class TableDirectoryEntry extends DirectoryEntry {
|
||||
function __construct(File $font) {
|
||||
parent::__construct($font);
|
||||
}
|
||||
|
||||
function parse() {
|
||||
parent::parse();
|
||||
|
||||
$font = $this->font;
|
||||
$this->checksum = $font->readUInt32();
|
||||
$this->offset = $font->readUInt32();
|
||||
$this->length = $font->readUInt32();
|
||||
$this->entryLength += 12;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue