I18N_Arabic
[ class tree: I18N_Arabic ] [ index: I18N_Arabic ] [ all elements ]

Source for file Glyphs.php

Documentation is available at Glyphs.php

  1. <?php
  2. /**
  3.  * ----------------------------------------------------------------------
  4.  *  
  5.  * Copyright (c) 2006-2016 Khaled Al-Sham'aa.
  6.  *  
  7.  * http://www.ar-php.org
  8.  *  
  9.  * PHP Version 5
  10.  *  
  11.  * ----------------------------------------------------------------------
  12.  *  
  13.  * LICENSE
  14.  *
  15.  * This program is open source product; you can redistribute it and/or
  16.  * modify it under the terms of the GNU Lesser General Public License (LGPL)
  17.  * as published by the Free Software Foundation; either version 3
  18.  * of the License, or (at your option) any later version.
  19.  *  
  20.  * This program is distributed in the hope that it will be useful,
  21.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23.  * GNU Lesser General Public License for more details.
  24.  *  
  25.  * You should have received a copy of the GNU Lesser General Public License
  26.  * along with this program.  If not, see <http://www.gnu.org/licenses/lgpl.txt>.
  27.  *  
  28.  * ----------------------------------------------------------------------
  29.  *  
  30.  * Class Name: Arabic Glyphs is a simple class to render Arabic text
  31.  *  
  32.  * Filename:   Glyphs.php
  33.  *  
  34.  * Original    Author(s): Khaled Al-Sham'aa <khaled@ar-php.org>
  35.  *  
  36.  * Purpose:    This class takes Arabic text (encoded in Windows-1256 character
  37.  *             set) as input and performs Arabic glyph joining on it and outputs
  38.  *             a UTF-8 hexadecimals stream that is no longer logically arranged
  39.  *             but in a visual order which gives readable results when formatted
  40.  *             with a simple Unicode rendering just like GD and UFPDF libraries
  41.  *             that does not handle basic connecting glyphs of Arabic language
  42.  *             yet but simply outputs all stand alone glyphs in left-to-right
  43.  *             order.
  44.  *              
  45.  * ----------------------------------------------------------------------
  46.  *  
  47.  * Arabic Glyphs is class to render Arabic text
  48.  *
  49.  * PHP class to render Arabic text by performs Arabic glyph joining on it,
  50.  * then output a UTF-8 hexadecimals stream gives readable results on PHP
  51.  * libraries supports UTF-8.
  52.  *
  53.  * Example:
  54.  * <code>
  55.  *   include('./I18N/Arabic.php');
  56.  *   $obj = new I18N_Arabic('Glyphs');
  57.  *
  58.  *   $text = $obj->utf8Glyphs($text);
  59.  *      
  60.  *   imagettftext($im, 20, 0, 200, 100, $black, $font, $text);
  61.  * </code>
  62.  *
  63.  * @category  I18N
  64.  * @package   I18N_Arabic
  65.  * @author    Khaled Al-Sham'aa <khaled@ar-php.org>
  66.  * @copyright 2006-2016 Khaled Al-Sham'aa
  67.  *    
  68.  * @license   LGPL <http://www.gnu.org/licenses/lgpl.txt>
  69.  * @link      http://www.ar-php.org
  70.  */
  71.  
  72. /**
  73.  * This PHP class render Arabic text by performs Arabic glyph joining on it
  74.  *  
  75.  * @category  I18N
  76.  * @package   I18N_Arabic
  77.  * @author    Khaled Al-Sham'aa <khaled@ar-php.org>
  78.  * @copyright 2006-2016 Khaled Al-Sham'aa
  79.  *    
  80.  * @license   LGPL <http://www.gnu.org/licenses/lgpl.txt>
  81.  * @link      http://www.ar-php.org
  82.  */ 
  83. {
  84.     private $_glyphs   null;
  85.     private $_hex      null;
  86.     private $_prevLink null;
  87.     private $_nextLink null;
  88.     private $_vowel    null;
  89.  
  90.     /**
  91.      * Loads initialize values
  92.      *
  93.      * @ignore
  94.      */         
  95.     public function __construct()
  96.     {
  97.         $this->_prevLink  '،؟؛ـئبتثجحخسشصضطظعغفقكلمنهي';
  98.         $this->_nextLink  'ـآأؤإائبةتثجحخدذرز';
  99.         $this->_nextLink .= 'سشصضطظعغفقكلمنهوىي';
  100.         $this->_vowel     'ًٌٍَُِّْ';
  101.  
  102.         /*
  103.          $this->_glyphs['ً']  = array('FE70','FE71');
  104.          $this->_glyphs['ٌ']  = array('FE72','FE72');
  105.          $this->_glyphs['ٍ']  = array('FE74','FE74');
  106.          $this->_glyphs['َ']  = array('FE76','FE77');
  107.          $this->_glyphs['ُ']  = array('FE78','FE79');
  108.          $this->_glyphs['ِ']  = array('FE7A','FE7B');
  109.          $this->_glyphs['ّ']  = array('FE7C','FE7D');
  110.          $this->_glyphs['ْ']  = array('FE7E','FE7E');
  111.          */
  112.          
  113.         $this->_glyphs 'ًٌٍَُِّْٰ';
  114.         $this->_hex    '064B064B064B064B064C064C064C064C064D064D064D064D064E064E';
  115.         $this->_hex   .= '064E064E064F064F064F064F06500650065006500651065106510651';
  116.         $this->_hex   .= '06520652065206520670067006700670';
  117.  
  118.         $this->_glyphs .= 'ءآأؤإئاب';
  119.         $this->_hex    .= 'FE80FE80FE80FE80FE81FE82FE81FE82FE83FE84FE83FE84FE85FE86';
  120.         $this->_hex    .= 'FE85FE86FE87FE88FE87FE88FE89FE8AFE8BFE8CFE8DFE8EFE8DFE8E';
  121.         $this->_hex    .= 'FE8FFE90FE91FE92';
  122.  
  123.         $this->_glyphs .= 'ةتثجحخدذ';
  124.         $this->_hex    .= 'FE93FE94FE93FE94FE95FE96FE97FE98FE99FE9AFE9BFE9CFE9DFE9E';
  125.         $this->_hex    .= 'FE9FFEA0FEA1FEA2FEA3FEA4FEA5FEA6FEA7FEA8FEA9FEAAFEA9FEAA';
  126.         $this->_hex    .= 'FEABFEACFEABFEAC';
  127.  
  128.         $this->_glyphs .= 'رزسشصضطظ';
  129.         $this->_hex    .= 'FEADFEAEFEADFEAEFEAFFEB0FEAFFEB0FEB1FEB2FEB3FEB4FEB5FEB6';
  130.         $this->_hex    .= 'FEB7FEB8FEB9FEBAFEBBFEBCFEBDFEBEFEBFFEC0FEC1FEC2FEC3FEC4';
  131.         $this->_hex    .= 'FEC5FEC6FEC7FEC8';
  132.  
  133.         $this->_glyphs .= 'عغفقكلمن';
  134.         $this->_hex    .= 'FEC9FECAFECBFECCFECDFECEFECFFED0FED1FED2FED3FED4FED5FED6';
  135.         $this->_hex    .= 'FED7FED8FED9FEDAFEDBFEDCFEDDFEDEFEDFFEE0FEE1FEE2FEE3FEE4';
  136.         $this->_hex    .= 'FEE5FEE6FEE7FEE8';
  137.  
  138.         $this->_glyphs .= 'هوىيـ،؟؛';
  139.         $this->_hex    .= 'FEE9FEEAFEEBFEECFEEDFEEEFEEDFEEEFEEFFEF0FEEFFEF0FEF1FEF2';
  140.         $this->_hex    .= 'FEF3FEF40640064006400640060C060C060C060C061F061F061F061F';
  141.         $this->_hex    .= '061B061B061B061B';
  142.  
  143.         // Support the extra 4 Persian letters (p), (ch), (zh) and (g)
  144.         // This needs value in getGlyphs function to be 52 instead of 48
  145.         // $this->_glyphs .= chr(129).chr(141).chr(142).chr(144);
  146.         // $this->_hex    .= 'FB56FB57FB58FB59FB7AFB7BFB7CFB7DFB8AFB8BFB8AFB8BFB92';
  147.         // $this->_hex    .= 'FB93FB94FB95';
  148.         //
  149.         // $this->_prevLink .= chr(129).chr(141).chr(142).chr(144);
  150.         // $this->_nextLink .= chr(129).chr(141).chr(142).chr(144);
  151.         //
  152.         // Example:     $text = 'نمونة قلم: لاگچ ژافپ';
  153.         // Email Yossi Beck <yosbeck@gmail.com> ask him to save that example
  154.         // string using ANSI encoding in Notepad
  155.         $this->_glyphs .= '';
  156.         $this->_hex    .= '';
  157.         
  158.         $this->_glyphs .= 'لآلألإلا';
  159.         $this->_hex    .= 'FEF5FEF6FEF5FEF6FEF7FEF8FEF7FEF8FEF9FEFAFEF9FEFAFEFBFEFC';
  160.         $this->_hex    .= 'FEFBFEFC';
  161.     }
  162.     
  163.     /**
  164.      * Get glyphs
  165.      * 
  166.      * @param string  $char Char
  167.      * @param integer $type Type
  168.      * 
  169.      * @return string 
  170.      */                                  
  171.     protected function getGlyphs($char$type)
  172.     {
  173.  
  174.         $pos mb_strpos($this->_glyphs$char);
  175.         
  176.         if ($pos 49{
  177.             $pos ($pos-49)/49;
  178.         }
  179.         
  180.         $pos $pos*16 $type*4;
  181.         
  182.         return substr($this->_hex$pos4);
  183.     }
  184.     
  185.     /**
  186.      * Convert Arabic Windows-1256 charset string into glyph joining in UTF-8
  187.      * hexadecimals stream
  188.      *      
  189.      * @param string $str Arabic string in Windows-1256 charset
  190.      *      
  191.      * @return string Arabic glyph joining in UTF-8 hexadecimals stream
  192.      * @author Khaled Al-Sham'aa <khaled@ar-php.org>
  193.      */
  194.     protected function preConvert($str)
  195.     {
  196.         $crntChar null;
  197.         $prevChar null;
  198.         $nextChar null;
  199.         $output   '';
  200.         
  201.         $_temp mb_strlen($str);
  202.  
  203.         for ($i 0$i $_temp$i++{
  204.             $chars[mb_substr($str$i1);
  205.         }
  206.  
  207.         $max count($chars);
  208.  
  209.         for ($i $max 1$i >= 0$i--{
  210.             $crntChar $chars[$i];
  211.             $prevChar ' ';
  212.             
  213.             if ($i 0{
  214.                 $prevChar $chars[$i 1];
  215.             }
  216.             
  217.             if ($prevChar && mb_strpos($this->_vowel$prevChar!== false{
  218.                 $prevChar $chars[$i 2];
  219.                 if ($prevChar && mb_strpos($this->_vowel$prevChar!== false{
  220.                     $prevChar $chars[$i 3];
  221.                 }
  222.             }
  223.             
  224.             $Reversed    false;
  225.             $flip_arr    ')]>}';
  226.             $ReversedChr '([<{';
  227.             
  228.             if ($crntChar && mb_strpos($flip_arr$crntChar!== false{
  229.                 $crntChar $ReversedChr[mb_strpos($flip_arr$crntChar)];
  230.                 $Reversed true;
  231.             else {
  232.                 $Reversed false;
  233.             }
  234.             
  235.             if ($crntChar && !$Reversed 
  236.                 && (mb_strpos($ReversedChr$crntChar!== false)
  237.             {
  238.                 $crntChar $flip_arr[mb_strpos($ReversedChr$crntChar)];
  239.             }
  240.             
  241.             if (ord($crntChar128{
  242.                 $output  .= $crntChar;
  243.                 $nextChar $crntChar;
  244.                 continue;
  245.             }
  246.             
  247.             if ($crntChar == 'ل' && isset($chars[$i 1]
  248.                 && (mb_strpos('آأإا'$chars[$i 1]!== false)
  249.             {
  250.                 continue;
  251.             }
  252.             
  253.             if ($crntChar && mb_strpos($this->_vowel$crntChar!== false{
  254.                 if (isset($chars[$i 1]
  255.                     && (mb_strpos($this->_nextLink$chars[$i 1]!== false
  256.                     && (mb_strpos($this->_prevLink$prevChar!== false)
  257.                 {
  258.                     $output .= '&#x' $this->getGlyphs($crntChar1';';
  259.                 else {
  260.                     $output .= '&#x' $this->getGlyphs($crntChar0';';
  261.                 }
  262.                 continue;
  263.             }
  264.             
  265.             $form 0;
  266.             
  267.             if (($prevChar == 'لا' || $prevChar == 'لآ' || $prevChar == 'لأ' 
  268.                 || $prevChar == 'لإ' || $prevChar == 'ل'
  269.                 && (mb_strpos('آأإا'$crntChar!== false)
  270.             {
  271.                 if (mb_strpos($this->_prevLink$chars[$i 2]!== false{
  272.                     $form++;
  273.                 }
  274.                 
  275.                 if (mb_strpos($this->_vowel$chars[$i 1])) {
  276.                     $output .= '&#x';
  277.                     $output .= $this->getGlyphs($crntChar$form).';';
  278.                 else {
  279.                     $output .= '&#x';
  280.                     $output .= $this->getGlyphs($prevChar.$crntChar$form).';';
  281.                 }
  282.                 $nextChar $prevChar;
  283.                 continue;
  284.             }
  285.             
  286.             if ($prevChar && mb_strpos($this->_prevLink$prevChar!== false{
  287.                 $form++;
  288.             }
  289.             
  290.             if ($nextChar && mb_strpos($this->_nextLink$nextChar!== false{
  291.                 $form += 2;
  292.             }
  293.             
  294.             $output  .= '&#x' $this->getGlyphs($crntChar$form';';
  295.             $nextChar $crntChar;
  296.         }
  297.         
  298.         // from Arabic Presentation Forms-B, Range: FE70-FEFF, 
  299.         // file "UFE70.pdf" (in reversed order)
  300.         // into Arabic Presentation Forms-A, Range: FB50-FDFF, file "UFB50.pdf"
  301.         // Example: $output = str_replace('&#xFEA0;&#xFEDF;', '&#xFCC9;', $output);
  302.         // Lam Jeem
  303.  
  304.         $output $this->decodeEntities($output$exclude array('&'));
  305.         return $output;
  306.     }
  307.     
  308.     /**
  309.      * Regression analysis calculate roughly the max number of character fit in
  310.      * one A4 page line for a given font size.
  311.      *      
  312.      * @param integer $font Font size
  313.      *      
  314.      * @return integer Maximum number of characters per line
  315.      * @author Khaled Al-Sham'aa <khaled@ar-php.org>
  316.      */
  317.     public function a4MaxChars($font)
  318.     {
  319.         $x 381.6 31.57 $font 1.182 pow($font20.02052 
  320.              pow($font30.0001342 pow($font4);
  321.         return floor($x 2);
  322.     }
  323.     
  324.     /**
  325.      * Calculate the lines number of given Arabic text and font size that will
  326.      * fit in A4 page size
  327.      *      
  328.      * @param string  $str  Arabic string you would like to split it into lines
  329.      * @param integer $font Font size
  330.      *                    
  331.      * @return integer Number of lines for a given Arabic string in A4 page size
  332.      * @author Khaled Al-Sham'aa <khaled@ar-php.org>
  333.      */
  334.     public function a4Lines($str$font)
  335.     {
  336.         $str str_replace(array("\r\n""\n""\r")"\n"$str);
  337.         
  338.         $lines     0;
  339.         $chars     0;
  340.         $words     explode(' '$str);
  341.         $w_count   count($words);
  342.         $max_chars $this->a4MaxChars($font);
  343.         
  344.         for ($i 0$i $w_count$i++{
  345.             $w_len mb_strlen($words[$i]1;
  346.             
  347.             if ($chars $w_len $max_chars{
  348.                 if (mb_strpos($words[$i]"\n"!== false{
  349.                     $words_nl explode("\n"$words[$i]);
  350.                     
  351.                     $nl_num count($words_nl1;
  352.                     for ($j 1$j $nl_num$j++{
  353.                         $lines++;
  354.                     }
  355.                     
  356.                     $chars mb_strlen($words_nl[$nl_num]1;
  357.                 else {
  358.                     $chars += $w_len;
  359.                 }
  360.             else {
  361.                 $lines++;
  362.                 $chars $w_len;
  363.             }
  364.         }
  365.         $lines++;
  366.         
  367.         return $lines;
  368.     }
  369.     
  370.     /**
  371.      * Convert Arabic Windows-1256 charset string into glyph joining in UTF-8
  372.      * hexadecimals stream (take care of whole the document including English
  373.      * sections as well as numbers and arcs etc...)
  374.      *                    
  375.      * @param string  $str       Arabic string in Windows-1256 charset
  376.      * @param integer $max_chars Max number of chars you can fit in one line
  377.      * @param boolean $hindo     If true use Hindo digits else use Arabic digits
  378.      *                    
  379.      * @return string Arabic glyph joining in UTF-8 hexadecimals stream (take
  380.      *                 care of whole document including English sections as well
  381.      *                 as numbers and arcs etc...)
  382.      * @author Khaled Al-Sham'aa <khaled@ar-php.org>
  383.      */
  384.     public function utf8Glyphs($str$max_chars 50$hindo true)
  385.     {
  386.         $str str_replace(array("\r\n""\n""\r")" \n "$str);
  387.         $str str_replace("\t""        "$str);
  388.         
  389.         $lines   array();
  390.         $words   explode(' '$str);
  391.         $w_count count($words);
  392.         $c_chars 0;
  393.         $c_words array();
  394.         
  395.         $english  array();
  396.         $en_index = -1;
  397.         
  398.         $en_words array();
  399.         $en_stack array();
  400.  
  401.         for ($i 0$i $w_count$i++{
  402.             $pattern  '/^(\n?)';
  403.             $pattern .= '[a-z\d\\/\@\#\$\%\^\&\*\(\)\_\~\"\'\[\]\{\}\;\,\|\-\.\:!]*';
  404.             $pattern .= '([\.\:\+\=\-\!،؟]?)$/i';
  405.             
  406.             if (preg_match($pattern$words[$i]$matches)) {
  407.                 if ($matches[1]{
  408.                     $words[$imb_substr($words[$i]1).$matches[1];
  409.                 }
  410.                 if ($matches[2]{
  411.                     $words[$i$matches[2].mb_substr($words[$i]0-1);
  412.                 }
  413.                 $words[$istrrev($words[$i]);
  414.                 array_push($english$words[$i]);
  415.                 if ($en_index == -1{
  416.                     $en_index $i;
  417.                 }
  418.                 $en_words[true;
  419.             elseif ($en_index != -1{
  420.                 $en_count count($english);
  421.                 
  422.                 for ($j 0$j $en_count$j++{
  423.                     $words[$en_index $j$english[$en_count $j];
  424.                 }
  425.                 
  426.                 $en_index = -1;
  427.                 $english  array();
  428.                 
  429.                 $en_words[false;
  430.             else {
  431.                 $en_words[false;
  432.             }
  433.         }
  434.  
  435.         if ($en_index != -1{
  436.             $en_count count($english);
  437.             
  438.             for ($j 0$j $en_count$j++{
  439.                 $words[$en_index $j$english[$en_count $j];
  440.             }
  441.         }
  442.  
  443.         // need more work to fix lines starts by English words
  444.         if (isset($en_start)) {
  445.             $last true;
  446.             $from 0;
  447.             
  448.             foreach ($en_words as $key => $value{
  449.                 if ($last !== $value{
  450.                     $to $key 1;
  451.                     array_push($en_stackarray($from$to));
  452.                     $from $key;
  453.                 }
  454.                 $last $value;
  455.             }
  456.             
  457.             array_push($en_stackarray($from$key));
  458.             
  459.             $new_words array();
  460.             
  461.             while (list($from$toarray_pop($en_stack)) {
  462.                 for ($i $from$i <= $to$i++{
  463.                     $new_words[$words[$i];
  464.                 }
  465.             }
  466.             
  467.             $words $new_words;
  468.         }
  469.  
  470.         for ($i 0$i $w_count$i++{
  471.             $w_len mb_strlen($words[$i]1;
  472.             
  473.             if ($c_chars $w_len $max_chars{
  474.                 if (mb_strpos($words[$i]"\n"!== false{
  475.                     $words_nl explode("\n"$words[$i]);
  476.                     
  477.                     array_push($c_words$words_nl[0]);
  478.                     array_push($linesimplode(' '$c_words));
  479.                     
  480.                     $nl_num count($words_nl1;
  481.                     for ($j 1$j $nl_num$j++{
  482.                         array_push($lines$words_nl[$j]);
  483.                     }
  484.                     
  485.                     $c_words array($words_nl[$nl_num]);
  486.                     $c_chars mb_strlen($words_nl[$nl_num]1;
  487.                 else {
  488.                     array_push($c_words$words[$i]);
  489.                     $c_chars += $w_len;
  490.                 }
  491.             else {
  492.                 array_push($linesimplode(' '$c_words));
  493.                 $c_words array($words[$i]);
  494.                 $c_chars $w_len;
  495.             }
  496.         }
  497.         array_push($linesimplode(' '$c_words));
  498.         
  499.         $maxLine count($lines);
  500.         $output  '';
  501.         
  502.         for ($j $maxLine 1$j >= 0$j--{
  503.             $output .= $lines[$j"\n";
  504.         }
  505.         
  506.         $output rtrim($output);
  507.         
  508.         $output $this->preConvert($output);
  509.         if ($hindo{
  510.             $nums   array(
  511.                 '0''1''2''3''4'
  512.                 '5''6''7''8''9'
  513.             );
  514.             $arNums array(
  515.                 '٠''١''٢''٣''٤',
  516.                 '٥''٦''٧''٨''٩'
  517.             );
  518.             
  519.             foreach ($nums as $k => $v{
  520.                 $p_nums[$k'/'.$v.'/ui';
  521.             }
  522.             $output preg_replace($p_nums$arNums$output);
  523.             
  524.             foreach ($arNums as $k => $v{
  525.                 $p_arNums[$k'/([a-z-\d]+)'.$v.'/ui';
  526.             }
  527.             foreach ($nums as $k => $v{
  528.                 $r_nums[$k'${1}'.$v;
  529.             }
  530.             $output preg_replace($p_arNums$r_nums$output);
  531.             
  532.             foreach ($arNums as $k => $v{
  533.                 $p_arNums[$k'/'.$v.'([a-z-\d]+)/ui';
  534.             }
  535.             foreach ($nums as $k => $v{
  536.                 $r_nums[$k$v.'${1}';
  537.             }
  538.             $output preg_replace($p_arNums$r_nums$output);
  539.         }
  540.  
  541.         return $output;
  542.     }
  543.     
  544.     /**
  545.      * Decode all HTML entities (including numerical ones) to regular UTF-8 bytes.
  546.      * Double-escaped entities will only be decoded once
  547.      * ("&amp;lt;" becomes "&lt;", not "<").
  548.      *                   
  549.      * @param string $text    The text to decode entities in.
  550.      * @param array  $exclude An array of characters which should not be decoded.
  551.      *                         For example, array('<', '&', '"'). This affects
  552.      *                         both named and numerical entities.
  553.      *                        
  554.      * @return string 
  555.      */
  556.     protected function decodeEntities($text$exclude array())
  557.     {
  558.         static $table;
  559.         
  560.         // We store named entities in a table for quick processing.
  561.         if (!isset($table)) {
  562.             // Get all named HTML entities.
  563.             $table array_flip(get_html_translation_table(HTML_ENTITIES));
  564.             
  565.             // PHP gives us ISO-8859-1 data, we need UTF-8.
  566.             $table array_map('utf8_encode'$table);
  567.             
  568.             // Add apostrophe (XML)
  569.             $table['&apos;'"'";
  570.         }
  571.         $newtable array_diff($table$exclude);
  572.         
  573.         // Use a regexp to select all entities in one pass, to avoid decoding 
  574.         // double-escaped entities twice.
  575.         //return preg_replace('/&(#x?)?([A-Za-z0-9]+);/e', 
  576.         //                    '$this->decodeEntities2("$1", "$2", "$0", $newtable, 
  577.         //                                             $exclude)', $text);
  578.  
  579.         $pieces explode('&'$text);
  580.         $text   array_shift($pieces);
  581.         foreach ($pieces as $piece{
  582.             if ($piece[0== '#'{
  583.                 if ($piece[1== 'x'{
  584.                     $one '#x';
  585.                 else {
  586.                     $one '#';
  587.                 }
  588.             else {
  589.                 $one '';
  590.             }
  591.             $end   mb_strpos($piece';');
  592.             $start mb_strlen($one);
  593.             
  594.             $two   mb_substr($piece$start$end $start);
  595.             $zero  '&'.$one.$two.';';
  596.             $text .= $this->decodeEntities2($one$two$zero$newtable$exclude).
  597.                      mb_substr($piece$end+1);
  598.         }
  599.         return $text;
  600.     }
  601.     
  602.     /**
  603.      * Helper function for decodeEntities
  604.      * 
  605.      * @param string $prefix    Prefix
  606.      * @param string $codepoint Codepoint
  607.      * @param string $original  Original
  608.      * @param array  &$table    Store named entities in a table
  609.      * @param array  &$exclude  An array of characters which should not be decoded
  610.      * 
  611.      * @return string 
  612.      */
  613.     protected function decodeEntities2(
  614.         $prefix$codepoint$original&$table&$exclude
  615.     {
  616.         // Named entity
  617.         if (!$prefix{
  618.             if (isset($table[$original])) {
  619.                 return $table[$original];
  620.             else {
  621.                 return $original;
  622.             }
  623.         }
  624.         
  625.         // Hexadecimal numerical entity
  626.         if ($prefix == '#x'{
  627.             $codepoint base_convert($codepoint1610);
  628.         }
  629.         
  630.         // Encode codepoint as UTF-8 bytes
  631.         if ($codepoint 0x80{
  632.             $str chr($codepoint);
  633.         elseif ($codepoint 0x800{
  634.             $str chr(0xC0 ($codepoint >> 6)) 
  635.                    chr(0x80 ($codepoint 0x3F));
  636.         elseif ($codepoint 0x10000{
  637.             $str chr(0xE0 ($codepoint >> 12)) 
  638.                    chr(0x80 (($codepoint >> 60x3F)) 
  639.                    chr(0x80 ($codepoint 0x3F));
  640.         elseif ($codepoint 0x200000{
  641.             $str chr(0xF0 ($codepoint >> 18)) 
  642.                    chr(0x80 (($codepoint >> 120x3F)) 
  643.                    chr(0x80 (($codepoint >> 60x3F)) 
  644.                    chr(0x80 ($codepoint 0x3F));
  645.         }
  646.         
  647.         // Check for excluded characters
  648.         if (in_array($str$exclude)) {
  649.             return $original;
  650.         else {
  651.             return $str;
  652.         }
  653.     }
  654. }

Documentation generated on Fri, 01 Jan 2016 10:26:02 +0200 by phpDocumentor 1.4.0