Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
80.00% |
4 / 5 |
CRAP | |
95.83% |
46 / 48 |
| Encoding | |
0.00% |
0 / 1 |
|
80.00% |
4 / 5 |
32 | |
95.83% |
46 / 48 |
| decodeSymbol | |
100.00% |
1 / 1 |
7 | |
100.00% |
7 / 7 |
|||
| getCodePoint | |
0.00% |
0 / 1 |
5.27 | |
77.78% |
7 / 9 |
|||
| decodeUTF16 | |
100.00% |
1 / 1 |
9 | |
100.00% |
15 / 15 |
|||
| decodeANSI | |
100.00% |
1 / 1 |
5 | |
100.00% |
8 / 8 |
|||
| encodeUTF8 | |
100.00% |
1 / 1 |
6 | |
100.00% |
9 / 9 |
|||
| <?php | |
| declare(strict_types=1); | |
| namespace PhpOffice\WMF\Renderer; | |
| /** | |
| * Conversion of the strings of metafiles to UTF-8 | |
| */ | |
| class Encoding | |
| { | |
| /** | |
| * Characters of Windows-1252 from 0x80 to 0x9F | |
| */ | |
| protected const WINDOWS_1252 = [ | |
| 0x20AC, 0x81, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x8D, 0x017D, 0x8F, | |
| 0x90, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x9D, 0x017E, 0x0178, | |
| ]; | |
| /** | |
| * Characters of the Symbol font (from 0x20 to 0xFF) which are not ASCII characters | |
| */ | |
| protected const SYMBOL = [ | |
| 0x22 => 0x2200, 0x24 => 0x2203, 0x27 => 0x220B, 0x2A => 0x2217, 0x2D => 0x2212, 0x40 => 0x2245, 0x41 => 0x0391, 0x42 => 0x0392, | |
| 0x43 => 0x03A7, 0x44 => 0x0394, 0x45 => 0x0395, 0x46 => 0x03A6, 0x47 => 0x0393, 0x48 => 0x0397, 0x49 => 0x0399, 0x4A => 0x03D1, | |
| 0x4B => 0x039A, 0x4C => 0x039B, 0x4D => 0x039C, 0x4E => 0x039D, 0x4F => 0x039F, 0x50 => 0x03A0, 0x51 => 0x0398, 0x52 => 0x03A1, | |
| 0x53 => 0x03A3, 0x54 => 0x03A4, 0x55 => 0x03A5, 0x56 => 0x03C2, 0x57 => 0x03A9, 0x58 => 0x039E, 0x59 => 0x03A8, 0x5A => 0x0396, | |
| 0x5C => 0x2234, 0x5E => 0x22A5, 0x60 => 0x203E, 0x61 => 0x03B1, 0x62 => 0x03B2, 0x63 => 0x03C7, 0x64 => 0x03B4, 0x65 => 0x03B5, | |
| 0x66 => 0x03C6, 0x67 => 0x03B3, 0x68 => 0x03B7, 0x69 => 0x03B9, 0x6A => 0x03D5, 0x6B => 0x03BA, 0x6C => 0x03BB, 0x6D => 0x03BC, | |
| 0x6E => 0x03BD, 0x6F => 0x03BF, 0x70 => 0x03C0, 0x71 => 0x03B8, 0x72 => 0x03C1, 0x73 => 0x03C3, 0x74 => 0x03C4, 0x75 => 0x03C5, | |
| 0x76 => 0x03D6, 0x77 => 0x03C9, 0x78 => 0x03BE, 0x79 => 0x03C8, 0x7A => 0x03B6, 0x7E => 0x223C, 0xA0 => 0x20AC, 0xA1 => 0x03D2, | |
| 0xA2 => 0x2032, 0xA3 => 0x2264, 0xA4 => 0x2044, 0xA5 => 0x221E, 0xA6 => 0x0192, 0xA7 => 0x2663, 0xA8 => 0x2666, 0xA9 => 0x2665, | |
| 0xAA => 0x2660, 0xAB => 0x2194, 0xAC => 0x2190, 0xAD => 0x2191, 0xAE => 0x2192, 0xAF => 0x2193, 0xB0 => 0x00B0, 0xB1 => 0x00B1, | |
| 0xB2 => 0x2033, 0xB3 => 0x2265, 0xB4 => 0x00D7, 0xB5 => 0x221D, 0xB6 => 0x2202, 0xB7 => 0x2022, 0xB8 => 0x00F7, 0xB9 => 0x2260, | |
| 0xBA => 0x2261, 0xBB => 0x2248, 0xBC => 0x2026, 0xBD => 0x23D0, 0xBE => 0x23AF, 0xBF => 0x21B5, 0xC0 => 0x2135, 0xC1 => 0x2111, | |
| 0xC2 => 0x211C, 0xC3 => 0x2118, 0xC4 => 0x2297, 0xC5 => 0x2295, 0xC6 => 0x2205, 0xC7 => 0x2229, 0xC8 => 0x222A, 0xC9 => 0x2283, | |
| 0xCA => 0x2287, 0xCB => 0x2284, 0xCC => 0x2282, 0xCD => 0x2286, 0xCE => 0x2208, 0xCF => 0x2209, 0xD0 => 0x2220, 0xD1 => 0x2207, | |
| 0xD2 => 0x00AE, 0xD3 => 0x00A9, 0xD4 => 0x2122, 0xD5 => 0x220F, 0xD6 => 0x221A, 0xD7 => 0x22C5, 0xD8 => 0x00AC, 0xD9 => 0x2227, | |
| 0xDA => 0x2228, 0xDB => 0x21D4, 0xDC => 0x21D0, 0xDD => 0x21D1, 0xDE => 0x21D2, 0xDF => 0x21D3, 0xE0 => 0x25CA, 0xE1 => 0x2329, | |
| 0xE2 => 0x00AE, 0xE3 => 0x00A9, 0xE4 => 0x2122, 0xE5 => 0x2211, 0xE6 => 0x239B, 0xE7 => 0x239C, 0xE8 => 0x239D, 0xE9 => 0x23A1, | |
| 0xEA => 0x23A2, 0xEB => 0x23A3, 0xEC => 0x23A7, 0xED => 0x23A8, 0xEE => 0x23A9, 0xEF => 0x23AA, 0xF1 => 0x232A, 0xF2 => 0x222B, | |
| 0xF3 => 0x2320, 0xF4 => 0x23AE, 0xF5 => 0x2321, 0xF6 => 0x239E, 0xF7 => 0x239F, 0xF8 => 0x23A0, 0xF9 => 0x23A4, 0xFA => 0x23A5, | |
| 0xFB => 0x23A6, 0xFC => 0x23AB, 0xFD => 0x23AC, 0xFE => 0x23AD, | |
| ]; | |
| /** | |
| * Converts a text drawn with the Symbol font to Unicode (Greek letters, mathematical symbols...) | |
| * | |
| * The characters of the Symbol font are ASCII characters (0x20 to 0xFF) or private characters (U+F020 to U+F0FF) | |
| */ | |
| public static function decodeSymbol(string $text): string | |
| { | |
| $result = ''; | |
| foreach (preg_split('//u', $text, -1, PREG_SPLIT_NO_EMPTY) ?: [] as $character) { | |
| $codePoint = self::getCodePoint($character); | |
| if ($codePoint >= 0xF020 && $codePoint <= 0xF0FF) { | |
| $codePoint -= 0xF000; | |
| } | |
| $result .= isset(self::SYMBOL[$codePoint]) ? self::encodeUTF8(self::SYMBOL[$codePoint]) : ($codePoint < 0x100 ? self::encodeUTF8($codePoint) : $character); | |
| } | |
| return $result; | |
| } | |
| /** | |
| * Returns the code point of a UTF-8 character | |
| */ | |
| protected static function getCodePoint(string $character): int | |
| { | |
| $bytes = array_values(unpack('C*', $character) ?: [0]); | |
| switch (count($bytes)) { | |
| case 1: | |
| return $bytes[0]; | |
| case 2: | |
| return (($bytes[0] & 0x1F) << 6) | ($bytes[1] & 0x3F); | |
| case 3: | |
| return (($bytes[0] & 0x0F) << 12) | (($bytes[1] & 0x3F) << 6) | ($bytes[2] & 0x3F); | |
| default: | |
| return (($bytes[0] & 0x07) << 18) | (($bytes[1] & 0x3F) << 12) | (($bytes[2] & 0x3F) << 6) | ($bytes[3] & 0x3F); | |
| } | |
| } | |
| /** | |
| * Decodes a UTF-16LE string (stopping at the first NUL character) to UTF-8 | |
| */ | |
| public static function decodeUTF16(string $data): string | |
| { | |
| $data = (string) substr($data, 0, strlen($data) - strlen($data) % 2); | |
| if ($data === '') { | |
| return ''; | |
| } | |
| $units = array_values(unpack('v*', $data)); | |
| $count = count($units); | |
| $result = ''; | |
| for ($i = 0; $i < $count; ++$i) { | |
| $codePoint = $units[$i]; | |
| if ($codePoint == 0) { | |
| break; | |
| } | |
| if ($codePoint >= 0xD800 && $codePoint < 0xDC00 && $i + 1 < $count && $units[$i + 1] >= 0xDC00 && $units[$i + 1] < 0xE000) { | |
| $codePoint = 0x10000 + (($codePoint - 0xD800) << 10) + ($units[$i + 1] - 0xDC00); | |
| ++$i; | |
| } | |
| $result .= self::encodeUTF8($codePoint); | |
| } | |
| return $result; | |
| } | |
| /** | |
| * Decodes a Windows-1252 string (stopping at the first NUL character) to UTF-8 | |
| */ | |
| public static function decodeANSI(string $data): string | |
| { | |
| $result = ''; | |
| $length = strlen($data); | |
| for ($i = 0; $i < $length; ++$i) { | |
| $byte = ord($data[$i]); | |
| if ($byte == 0) { | |
| break; | |
| } | |
| $result .= self::encodeUTF8($byte >= 0x80 && $byte < 0xA0 ? self::WINDOWS_1252[$byte - 0x80] : $byte); | |
| } | |
| return $result; | |
| } | |
| public static function encodeUTF8(int $codePoint): string | |
| { | |
| if ($codePoint >= 0xD800 && $codePoint < 0xE000) { | |
| // Lone surrogate | |
| $codePoint = 0xFFFD; | |
| } | |
| if ($codePoint < 0x80) { | |
| return chr($codePoint); | |
| } | |
| if ($codePoint < 0x800) { | |
| return chr(0xC0 | ($codePoint >> 6)) . chr(0x80 | ($codePoint & 0x3F)); | |
| } | |
| if ($codePoint < 0x10000) { | |
| return chr(0xE0 | ($codePoint >> 12)) . chr(0x80 | (($codePoint >> 6) & 0x3F)) . chr(0x80 | ($codePoint & 0x3F)); | |
| } | |
| return chr(0xF0 | ($codePoint >> 18)) . chr(0x80 | (($codePoint >> 12) & 0x3F)) . chr(0x80 | (($codePoint >> 6) & 0x3F)) . chr(0x80 | ($codePoint & 0x3F)); | |
| } | |
| } |