-
-
Save dtinth/716814 to your computer and use it in GitHub Desktop.
<?php | |
function thai($x) { | |
$back = array( | |
"\xE0\xB9\x88" => "\xEF\x9C\x85", | |
"\xE0\xB9\x89" => "\xEF\x9C\x86", | |
"\xE0\xB9\x8A" => "\xEF\x9C\x87", | |
"\xE0\xB9\x8B" => "\xEF\x9C\x88", | |
"\xE0\xB9\x8C" => "\xEF\x9C\x89" | |
); | |
$cross = array(); | |
foreach (array("\xE0\xB8\xB4", "\xE0\xB8\xB5", "\xE0\xB8\xB6", "\xE0\xB8\xB7") as $p) { | |
for ($i = 0x85; $i <= 0x89; $i ++) { | |
$from = $p . "\xEF\x9C" . chr($i); | |
$to = $p . "\xE0\xB9" . chr($i + 3); | |
$cross[$from] = $to; | |
} | |
} | |
$x = strtr($x, $back); | |
$x = strtr($x, $cross); | |
return $x; | |
} |
ปรับให้วรรณยุกต์ที่ซ้อนอยู่บน อิ อี อึ อือ และไม้หันอากาศ อยู่ชิดขวาของตัวอักษร ให้เป็นธรรมชาติมากขึ้น
function thai($x)
{
$back = array(
"\xE0\xB9\x88" => "\xEF\x9C\x8A", // ไม้เอก
"\xE0\xB9\x89" => "\xEF\x9C\x8B", // ไม้โท
"\xE0\xB9\x8A" => "\xEF\x9C\x8C", // ไม้ตรี
"\xE0\xB9\x8B" => "\xEF\x9C\x8D", // ไม้จัตวา
"\xE0\xB9\x8C" => "\xEF\x9C\x8E" // ตัวการันต์
);
$cross = array();
$vowels = array(
"\xE0\xB8\xB4", // สระอิ
"\xE0\xB8\xB5", // สระอี
"\xE0\xB8\xB6", // สระอึ
"\xE0\xB8\xB7", // สระอือ
"\xE0\xB8\xB1", // ไม้หันอากาศ
"ำ" //สระอำ \xE0\xB8\xB3
);
//http://www.endmemo.com/unicode/thai.php อ้างอิง unicode
foreach ($vowels as $p) {
if ($p != 'ำ') {
for ($i = 0x8A; $i <= 0x8E; $i++) {
$from = $p . "\xEF\x9C" . chr($i);
$to = $p . "\xE0\xB9" . chr($i - 2);
$cross[$from] = $to;
}
} else {
for ($i = 0x8A; $i <= 0x8E; $i++) {
$from = "\xEF\x9C" . chr($i) . $p;
$to = "\xE0\xB9" . chr($i - 2) . $p;
$cross[$from] = $to;
}
}
}
$x = strtr($x, $back);
$x = strtr($x, $cross);
return $x;
}
สำหรับผู้ที่สงสัยว่า \xEF\x9C\x...
ทั้งหลายมันคืออะไร เพราะไปหาในหน้าอักขระไทย unicode ก็ไม่พบ
เฉลย: มันคือตัวอักษรไทยในตำแหน่งต่างๆหรือตัดเอาบางส่วนออกไป อยู่ใน private area ซึ่งปกติแสดงผลผ่านเบราว์เซอร์มักจะไม่ปรากฏ เป็นสัญญลักษณ์อะไรก็ไม่รู้ดูไม่รู้เรื่อง. ต้องทำผ่านโปรแกรมสร้าง pdf อย่างเช่น mpdf มันจึงจะแสดงออกมารู้เรื่อง.
เอาโค้ดต่อไปนี้ไปเพื่อดูว่ามันมีอะไรกันบ้าง แล้วจะเข้าใจเองครับ.
<?php
/**
* Get default Mpdf fonts.
*
* @return array Return associative array with keys: `fontDirs`, `fontData`.
*/
function mpdfGetDefaultFonts(): array
{
$defaultConfig = (new \Mpdf\Config\ConfigVariables())->getDefaults();
$fontDirs = $defaultConfig['fontDir'];
$defaultFontConfig = (new \Mpdf\Config\FontVariables())->getDefaults();
$fontData = $defaultFontConfig['fontdata'];
// remove not exists font.
unset($fontData['eeyekunicode']);
unset($defaultConfig, $defaultFontConfig);
return [
'fontDirs' => $fontDirs,
'fontData' => $fontData,
];
}// mpdfGetDefaultFonts
.mpdf-functions.php
<?php
require 'vendor/autoload.php';
ini_set('memory_limit', '64M');
include_once '.mpdf-functions.php';
list('fontDirs' => $fontDirs, 'fontData' => $fontData) = mpdfGetDefaultFonts();
$config = [
'default_font' => 'sans-serif',
'default_font_size' => 22,
'fontdata' => $fontData,
'fontDir' => $fontDirs,
];
unset($fontDirs);
$mpdf = new \Mpdf\Mpdf($config);
$fontsToTest = ['garuda', 'zawgyi-one'];
/**
* Private use area of unicode block.
* @link https://utf8-chartable.de/unicode-utf8-table.pl?start=63168&utf8=string-literal&unicodeinhtml=hex Reference.
*/
$html = '<!DOCTYPE html><html>' . PHP_EOL;
$html .= '<head><meta charset="utf-8"></head>' . PHP_EOL;
$html .= '<body>' . PHP_EOL;
$html .= '<h1><a href="https://utf8-chartable.de/unicode-utf8-table.pl?start=63168&utf8=string-literal&unicodeinhtml=hex" target="_blank">Private use area of unicode block.</a></h1>' . PHP_EOL;
foreach ($fontsToTest as $index => $font) {
$html .= '<h3>' . $font . '</h3>' . PHP_EOL;
$html .= '<p style="font-family:' . $font . ';">' . PHP_EOL;
for ($i = 0x80; $i <= 0xBF; ++$i) {
$html .= "อ\xEF\x9B" . chr($i) . 'า (\xEF\x9B\x' . dechex($i) . ')<br>';
}
for ($i = 0x80; $i <= 0xBF; ++$i) {
$html .= "อ\xEF\x9C" . chr($i) . 'า (\xEF\x9C\x' . dechex($i) . ')<br>';
}
for ($i = 0x80; $i <= 0xBF; ++$i) {
$html .= "อ\xEF\x9D" . chr($i) . 'า (\xEF\x9D\x' . dechex($i) . ')<br>';
}
$html .= '</p>' . PHP_EOL;
if (array_key_last($fontsToTest) !== $index) {
$html .= '<pagebreak>';
}
}// endforeach;
unset($font, $index);
unset($fontsToTest);
$html .= '</body>' . PHP_EOL;
$html .= '</html>' . PHP_EOL;
// Write some HTML code:
$mpdf->WriteHTML($html);
unset($html);
// Output a PDF file directly to the browser
$mpdf->Output();
test.php
ตัวอย่าง
\xEF\x9C\x85
จะได้ไม้เอกที่อยู่ตรงกลางๆ
\xEF\x9C\x8a
จะได้ไม้เอกที่เยื้องอยู่ข้างหลัง
\xEF\x9C\x93
จะได้ไม้เอกที่ลอยๆ
อัปเดทใหม่ นอกจากจะแก้เสียงวรรณยุกต์ลอยแล้ว (ไม้เอก เป็นต้น) ยังแก้เรื่องสระด้านล่างไปชนกับตัวอักษรที่ลากยาวลงมาด้านล่างด้วย เช่น ญ, ฎ เป็นต้น.
function fixThaiVowels(string $text): string
{
// เสียงวรรณยุกต์ และทัณฑฆาต (การันต์)
$back = [
"\xE0\xB9\x88" => "\xEF\x9C\x8A", //่(ไม้เอก)
"\xE0\xB9\x89" => "\xEF\x9C\x8B", //(ไม้โท)
"\xE0\xB9\x8A" => "\xEF\x9C\x8C", //(ไม้ตรี)
"\xE0\xB9\x8B" => "\xEF\x9C\x8D", //(ไม้จัตวา)
"\xE0\xB9\x8C" => "\xEF\x9C\x8E" //(ตัวการันต์)
];
$bottomVowels = [
"\xE0\xB8\xB8" => "\xEF\x9C\x98", // สระอุ
"\xE0\xB8\xB9" => "\xEF\x9C\x99", // สระอู
"\xE0\xB8\xBA" => "\xEF\x9C\x9A", // พินธุ
];
$replaces = [];
// ตัวอักษรที่มีความสูงที่จะต้องไม่ให้ชนกับเสียงวรรณยุกต์
$highChars = [
"ิ", // สระอิ
"ี", // สระอี
"ึ", // สระอึ
"ื", // สระอือ
"ั", // ไม้หันอากาศ
"ำ", // สระอำ
"ํ", // สระอำ ที่ไม่มีสระอา
"ป",
"ฝ",
"ฟ",
"ฬ",
];
// ตัวอักษรที่ลากลงด้านล่าง
$lowChars = [
"ฎ",
"ฏ",
"ฤ",
"ฦ",
];
$lowReplaceChars = [
'ญ' => "\xEF\x9C\x8F",
'ฐ' => "\xEF\x9C\x80",
];
// loop กำหนดค่าคืนกลับ (replace) เสียงวรรณยุกต์ที่จะต้องลอยสูง
foreach ($highChars as $p) {
if ($p !== 'ำ' && $p !== 'ํ') {
for ($i = 0x8A; $i <= 0x8E; ++$i) {
$from = $p . "\xEF\x9C" . chr($i);
$to = $p . "\xE0\xB9" . chr($i - 2);
$replaces[$from] = $to;
}// endfor;
unset($i);
} else {
for ($i = 0x8A; $i <= 0x8E; ++$i) {
$from = "\xEF\x9C" . chr($i) . $p;
$to = "\xE0\xB9" . chr($i - 2) . $p;
$replaces[$from] = $to;
}// endfor;
unset($i);
}// endif;
}// endforeach;
unset($highChars, $p);
// loop กำหนดค่าสระด้านล่าง ที่จะต้องเปลี่ยน (replace) เมื่อเจอตัวอักษรที่ลากลงด้านล่าง
foreach ($lowChars as $p) {
foreach ($bottomVowels as $orig => $replace) {
$from = $p . $orig;
$to = $p . $replace;
$replaces[$from] = $to;
}// endforeach;
unset($orig, $replace);
}// endforeach;
unset($lowChars, $p);
// loop กำหนดตัวอักษรที่มีฐานด้านล่าง ที่จะต้องเปลี่ยน (replace) เมื่อมีสระด้านล่างตามมาด้วย
foreach ($lowReplaceChars as $origChar => $replaceChar) {
foreach ($bottomVowels as $orig => $replace) {
$from = $origChar . $orig;
$to = $replaceChar . $orig;
$replaces[$from] = $to;
}// endforeach;
unset($orig, $replace);
}// endforeach;
unset($lowReplaceChars, $origChar, $replaceChar);
$text = strtr($text, $back);
$text = strtr($text, $replaces);
unset($back, $replaces);
return $text;
}// fixThaiVowels
ทำสอบโดยใช้โค้ดสร้าง PDF ใดๆก็ได้แล้วแก้ไขชื่อฟอนต์เอาให้ถูกต้อง
$font = 'sarabunnew';// ตย. กำหนดชื่อฟอนต์ให้ถูกต้องเอาเองนะครับ
$html .= '<h3>' . $font . '</h3>' . PHP_EOL;
$html .= '<p style="font-family:' . $font . ';">orig: อ่า อิ่ อี่ อึ่ อื่ อ้า อิ้ อี้ อึ้ อื้ อ๊า อิ๊ อี๊ อึ๊ อื๊ อ๋า อิ๋ อี๋ อึ๋ อื๋<br>' . PHP_EOL;
$html .= ' อ์ อิ์ อี์ อึ์ อื์ อั่น อั้น อั๊น อั๋น อ่ำ อ้ำ อ๊ำ อ๋ำ อ่ํ อ้ํ อ๊ํ อ๋ํ<br>' . PHP_EOL;
$html .= ' ป่า ป้า ป๊า ป๋า ปิ่ ปิ้ ปิ๊ ปิ๋ ปื่ ปื้ ปื๊ ปื๋ ปั่น ป่ำ ป่ํ<br>';
$html .= ' ฝ่า ฝ้า ฝ๊า ฝ๋า ฝิ่ ฝิ้ ฝิ๊ ฝิ๋ ฝื่ ฝื้ ฝื๊ ฝื๋ ฝั่น ฝ่ำ ฝ่ํ<br>';
$html .= ' ฟ่า ฟ้า ฟ๊า ฟ๋า ฟิ่ ฟิ้ ฟิ๊ ฟิ๋ ฟื่ ฟื้ ฟื๊ ฟื๋ ฟั่น ฟ่ำ ฟ่ํ<br>';
$html .= ' ฬ่า ฬ้า ฬ๊า ฬ๋า ฬิ่ ฬิ้ ฬิ๊ ฬิ๋ ฬื่ ฬื้ ฬื๊ ฬื๋ ฬั่น ฬ่ำ ฬ่ํ<br>';
$html .= ' อุ อู อฺ ฎุ ฎู ฎฺ ฏุ ฏู ฏฺ ฤุ ฤู ฤฺ ฦุ ฦู ฦฺ<br>';
$html .= ' ญุ ญู ญฺ ฐุ ฐู ฐฺ<br>';
$html .= "custom: อ\xEF\x9C\x8Aา อิ\xEF\x9C\x93 อี\xEF\x9C\x93 อึ\xEF\x9C\x93 อื\xEF\x9C\x93 ";
$html .= "อ\xEF\x9C\x8Bา อิ\xEF\x9C\x94 อี\xEF\x9C\x94 อึ\xEF\x9C\x94 อื\xEF\x9C\x94 ";
$html .= "อ\xEF\x9C\x8Cา อิ\xEF\x9C\x95 อี\xEF\x9C\x95 อึ\xEF\x9C\x95 อื\xEF\x9C\x95 ";
$html .= "อ\xEF\x9C\x8Dา อิ\xEF\x9C\x96 อี\xEF\x9C\x96 อึ\xEF\x9C\x96 อื\xEF\x9C\x96 ";
$html .= '<br>' . PHP_EOL;
$html .= " อ\xEF\x9C\x8E อิ\xEF\x9C\x97 อี\xEF\x9C\x97 อึ\xEF\x9C\x97 อื\xEF\x9C\x97 ";
$html .= "อั\xEF\x9C\x93น อั\xEF\x9C\x94น อั\xEF\x9C\x95น อั\xEF\x9C\x96น ";
$html .= "อ\xEF\x9C\x93ำ อ\xEF\x9C\x94ำ อ\xEF\x9C\x95ำ อ\xEF\x9C\x96ำ ";
$html .= "อ\xEF\x9C\x93ํ อ\xEF\x9C\x94ํ อ\xEF\x9C\x95ํ อ\xEF\x9C\x96ํ";
$html .= '<br>' . PHP_EOL;
$html .= " ป\xEF\x9C\x93า ป\xEF\x9C\x94า ป\xEF\x9C\x95า ป\xEF\x9C\x96า ";
$html .= "ปิ\xEF\x9C\x93 ปิ\xEF\x9C\x94 ปิ\xEF\x9C\x95 ปิ\xEF\x9C\x96 ";
$html .= "ปื\xEF\x9C\x93 ปื\xEF\x9C\x94 ปื\xEF\x9C\x95 ปื\xEF\x9C\x96 ";
$html .= "ปั\xEF\x9C\x93น ป\xEF\x9C\x93ำ ป\xEF\x9C\x93ํ";
$html .= '<br>' . PHP_EOL;
$html .= " ฝ\xEF\x9C\x93า ฝ\xEF\x9C\x94า ฝ\xEF\x9C\x95า ฝ\xEF\x9C\x96า ";
$html .= "ฝิ\xEF\x9C\x93 ฝิ\xEF\x9C\x94 ฝิ\xEF\x9C\x95 ฝิ\xEF\x9C\x96 ";
$html .= "ฝื\xEF\x9C\x93 ฝื\xEF\x9C\x94 ฝื\xEF\x9C\x95 ฝื\xEF\x9C\x96 ";
$html .= "ฝั\xEF\x9C\x93น ฝ\xEF\x9C\x93ำ ฝ\xEF\x9C\x93ํ";
$html .= '<br>' . PHP_EOL;
$html .= " ฟ\xEF\x9C\x93า ฟ\xEF\x9C\x94า ฟ\xEF\x9C\x95า ฟ\xEF\x9C\x96า ";
$html .= "ฟิ\xEF\x9C\x93 ฟิ\xEF\x9C\x94 ฟิ\xEF\x9C\x95 ฟิ\xEF\x9C\x96 ";
$html .= "ฟื\xEF\x9C\x93 ฟื\xEF\x9C\x94 ฟื\xEF\x9C\x95 ฟื\xEF\x9C\x96 ";
$html .= "ฟั\xEF\x9C\x93น ฟ\xEF\x9C\x93ำ ฟ\xEF\x9C\x93ํ";
$html .= '<br>' . PHP_EOL;
$html .= " ฬ\xEF\x9C\x93า ฬ\xEF\x9C\x94า ฬ\xEF\x9C\x95า ฬ\xEF\x9C\x96า ";
$html .= "ฬิ\xEF\x9C\x93 ฬิ\xEF\x9C\x94 ฬิ\xEF\x9C\x95 ฬิ\xEF\x9C\x96 ";
$html .= "ฬื\xEF\x9C\x93 ฬื\xEF\x9C\x94 ฬื\xEF\x9C\x95 ฬื\xEF\x9C\x96 ";
$html .= "ฬั\xEF\x9C\x93น ฬ\xEF\x9C\x93ำ ฬ\xEF\x9C\x93ํ";
$html .= '<br>' . PHP_EOL;
$html .= " อุ อู อฺ ฎ\xEF\x9C\x98 ฎ\xEF\x9C\x99 ฎ\xEF\x9C\x9A ";
$html .= "ฏ\xEF\x9C\x98 ฏ\xEF\x9C\x99 ฏ\xEF\x9C\x9A ";
$html .= "ฦ\xEF\x9C\x98 ฦ\xEF\x9C\x99 ฦ\xEF\x9C\x9A ";
$html .= '<br>' . PHP_EOL;
$html .= " \xEF\x9C\x8Fุ \xEF\x9C\x8Fู \xEF\x9C\x8Fฺ \xEF\x9C\x80ุ \xEF\x9C\x80ู \xEF\x9C\x80ฺ";
$html .= '<br>' . PHP_EOL;
$html .= 'test function: ' . fixThaiVowels('อ่า อิ่ อี่ อึ่ อื่ อ้า อิ้ อี้ อึ้ อื้ อ๊า อิ๊ อี๊ อึ๊ อื๊ อ๋า อิ๋ อี๋ อึ๋ อื๋');
$html .= '<br>' . PHP_EOL;
$html .= ' ' . fixThaiVowels('อ์ อิ์ อี์ อึ์ อื์ อั่น อั้น อั๊น อั๋น อ่ำ อ้ำ อ๊ำ อ๋ำ อ่ํ อ้ํ อ๊ํ อ๋ํ');
$html .= '<br>' . PHP_EOL;
$html .= ' ' . fixThaiVowels('ป่า ป้า ป๊า ป๋า ปิ่ ปิ้ ปิ๊ ปิ๋ ปื่ ปื้ ปื๊ ปื๋ ปั่น ป่ำ ป่ํ');
$html .= '<br>' . PHP_EOL;
$html .= ' ' . fixThaiVowels('ฝ่า ฝ้า ฝ๊า ฝ๋า ฝิ่ ฝิ้ ฝิ๊ ฝิ๋ ฝื่ ฝื้ ฝื๊ ฝื๋ ฝั่น ฝ่ำ ฝ่ํ');
$html .= '<br>' . PHP_EOL;
$html .= ' ' . fixThaiVowels('ฟ่า ฟ้า ฟ๊า ฟ๋า ฟิ่ ฟิ้ ฟิ๊ ฟิ๋ ฟื่ ฟื้ ฟื๊ ฟื๋ ฟั่น ฟ่ำ ฟ่ํ');
$html .= '<br>' . PHP_EOL;
$html .= ' ' . fixThaiVowels('ฬ่า ฬ้า ฬ๊า ฬ๋า ฬิ่ ฬิ้ ฬิ๊ ฬิ๋ ฬื่ ฬื้ ฬื๊ ฬื๋ ฬั่น ฬ่ำ ฬ่ํ');
$html .= '<br>' . PHP_EOL;
$html .= ' ' . fixThaiVowels('อุ อู อฺ ฎุ ฎู ฎฺ ฏุ ฏู ฏฺ ฤุ ฤู ฤฺ ฦุ ฦู ฦฺ');
$html .= '<br>' . PHP_EOL;
$html .= ' ' . fixThaiVowels('ญุ ญู ญฺ ฐุ ฐู ฐฺ');
$html .= '</p>' . PHP_EOL;
หมายเหตุ: ไม่สามารถแก้ไขได้กับทุกฟอนต์ บางฟอนต์ที่เสียงวรรณยุกต์จม (สระจม, ไม้เอกจม เป็นต้น) จะไม่สามารถแก้ได้เลย เนื่องจากเขาทำมาไม่ครบ. ดังนั้นตรวจสอบกับฟอนต์ที่จะใช้ให้ดีก่อนใช้จริง.
function thai($x) {
$back = array(
"\xE0\xB9\x88" => "\xEF\x9C\x85", //่(ไม้เอก)=>
"\xE0\xB9\x89" => "\xEF\x9C\x86", //้(ไม้โทร)=>
"\xE0\xB9\x8A" => "\xEF\x9C\x87", //๊(ไม้ตรี)=>
"\xE0\xB9\x8B" => "\xEF\x9C\x88", //+(ไม้จัตวา)=>
"\xE0\xB9\x8C" => "\xEF\x9C\x89" //์(ตัวการัน)=>
);
$cross = array();
$payanchana=array(
"\xE0\xB8\xB4", //สระอิ
"\xE0\xB8\xB5", //สระอี
"\xE0\xB8\xB6", //สระอึ
"\xE0\xB8\xB7", //สระอือ
"\xE0\xB8\xB1", //ไม้หันอากาศ
"ำ" //สระอำ \xE0\xB8\xB3
);
//http://www.endmemo.com/unicode/thai.php อ้างอิง unicode
foreach ($payanchana as $p) {
}