00001 <?php
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00136 require_once(dirname(__FILE__).'/config/tcpdf_config.php');
00137 
00138 
00139 
00143 require_once(dirname(__FILE__).'/unicode_data.php');
00144 
00148 require_once(dirname(__FILE__).'/htmlcolors.php');
00149 
00150 if (!class_exists('TCPDF', false)) {
00154     define('PDF_PRODUCER', 'TCPDF 4.8.007 (http://www.tcpdf.org)');
00155     
00165     class TCPDF {
00166         
00167         
00168 
00173         protected $page;
00174         
00179         protected $n;
00180 
00185         protected $offsets;
00186 
00191         protected $buffer;
00192 
00197         protected $pages = array();
00198 
00203         protected $state;
00204 
00209         protected $compress;
00210         
00215         protected $CurOrientation;
00216 
00221         protected $pagedim = array();
00222 
00227         protected $k;
00228 
00233         protected $fwPt;
00234 
00239         protected $fhPt;
00240 
00245         protected $wPt;
00246 
00251         protected $hPt;
00252 
00257         protected $w;
00258 
00263         protected $h;
00264 
00269         protected $lMargin;
00270 
00275         protected $tMargin;
00276 
00281         protected $rMargin;
00282 
00287         protected $bMargin;
00288 
00293         
00294         public $cMargin;
00295         
00300         protected $oldcMargin;
00301 
00306         protected $x;
00307 
00312         protected $y;
00313 
00318         protected $lasth;
00319 
00324         protected $LineWidth;
00325 
00330         protected $CoreFonts;
00331 
00336         protected $fonts = array();
00337 
00342         protected $FontFiles = array();
00343 
00348         protected $diffs = array();
00349 
00354         protected $images = array();
00355 
00360         protected $PageAnnots = array();
00361 
00366         protected $links = array();
00367 
00372         protected $FontFamily;
00373 
00378         protected $FontStyle;
00379         
00385         protected $FontAscent;
00386         
00392         protected $FontDescent;
00393 
00398         protected $underline;
00399 
00404         protected $CurrentFont;
00405 
00410         protected $FontSizePt;
00411 
00416         protected $FontSize;
00417 
00422         protected $DrawColor;
00423 
00428         protected $FillColor;
00429 
00434         protected $TextColor;
00435 
00440         protected $ColorFlag;
00441 
00446         protected $AutoPageBreak;
00447 
00452         protected $PageBreakTrigger;
00453 
00458         protected $InFooter = false;
00459 
00464         protected $ZoomMode;
00465 
00470         protected $LayoutMode;
00471 
00476         protected $title = '';
00477 
00482         protected $subject = '';
00483 
00488         protected $author = '';
00489 
00494         protected $keywords = '';
00495 
00500         protected $creator = '';
00501 
00506         protected $AliasNbPages = '{nb}';
00507         
00512         protected $AliasNumPage = '{pnb}';
00513         
00520         protected $img_rb_x;
00521 
00528         protected $img_rb_y;
00529 
00536         protected $imgscale = 1;
00537 
00544         protected $isunicode = false;
00545 
00551         protected $PDFVersion = '1.7';
00552         
00553         
00554         
00555         
00560         protected $header_margin;
00561         
00566         protected $footer_margin;
00567         
00573         protected $original_lMargin;
00574         
00580         protected $original_rMargin;
00581             
00586         protected $header_font;
00587         
00592         protected $footer_font;
00593         
00598         protected $l;
00599         
00604         protected $barcode = false;
00605         
00610         protected $print_header = true;
00611         
00616         protected $print_footer = true;
00617             
00622         protected $header_logo = '';
00623         
00628         protected $header_logo_width = 30;
00629         
00634         protected $header_title = '';
00635         
00640         protected $header_string = '';
00641         
00646         protected $default_table_columns = 4;
00647         
00648         
00649         
00650         
00655         protected $HREF = array();
00656         
00661         protected $fontlist = array();
00662         
00667         protected $fgcolor;
00668                         
00673         protected $listordered = array();
00674         
00679         protected $listcount = array();
00680         
00685         protected $listnum = 0;
00686         
00691         protected $listindent;
00692         
00697         protected $bgcolor;
00698         
00703         protected $tempfontsize = 10;
00704         
00709         protected $lispacer = '';
00710         
00716         protected $encoding = 'UTF-8';
00717         
00723         protected $internal_encoding;
00724         
00730         protected $rtl = false;
00731         
00737         protected $tmprtl = false;
00738         
00739         
00740         
00746         protected $encrypted;
00747         
00753         protected $Uvalue;
00754         
00760         protected $Ovalue;
00761         
00767         protected $Pvalue;
00768         
00774         protected $enc_obj_id;
00775         
00781         protected $last_rc4_key;
00782         
00788         protected $last_rc4_key_c;
00789         
00794         protected $padding = "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A";
00795         
00800         protected $encryption_key;
00801         
00802         
00803         
00809         protected $outlines = array();
00810         
00816         protected $OutlineRoot;
00817         
00818         
00819         
00820         
00826         protected $javascript = '';
00827         
00833         protected $n_js;
00834 
00840         protected $linethrough;
00841 
00842         
00843         
00844 
00850         protected $ur;
00851 
00857         protected $ur_document;
00858 
00864         protected $ur_annots;
00865 
00871         protected $ur_form;
00872 
00878         protected $ur_signature;
00879 
00885         protected $dpi = 72;
00886         
00892         protected $newpagegroup = array();
00893         
00899         protected $pagegroups;
00900         
00906         protected $currpagegroup; 
00907         
00913         protected $visibility = 'all';
00914         
00920         protected $n_ocg_print;
00921         
00927         protected $n_ocg_view;
00928         
00934         protected $extgstates;
00935         
00941         protected $jpeg_quality;
00942         
00948         protected $cell_height_ratio = K_CELL_HEIGHT_RATIO;
00949         
00955         protected $viewer_preferences;
00956         
00962         protected $PageMode;
00963         
00969         protected $gradients = array();
00970         
00977         protected $intmrk = array();
00978         
00985         protected $cntmrk = array();
00986         
00992         protected $footerpos = array();
00993         
00994         
01000         protected $footerlen = array();
01001         
01007         protected $newline = true;
01008         
01014         protected $endlinex = 0;
01015         
01021         protected $linestyleWidth = '';
01022         
01028         protected $linestyleCap = '0 J';
01029         
01035         protected $linestyleJoin = '0 j';
01036         
01042         protected $linestyleDash = '[] 0 d';
01043         
01049         protected $openMarkedContent = false;
01050         
01056         protected $htmlvspace = 0;
01057         
01063         protected $spot_colors = array();
01064         
01070         protected $lisymbol = '';
01071         
01077         protected $epsmarker = 'x#!#EPS#!#x';
01078         
01084         protected $transfmatrix = array();
01085 
01091         protected $transfmatrix_key = 0;
01092 
01098         protected $booklet = false;
01099         
01105         protected $feps = 0.005;
01106         
01112         protected $tagvspaces = array();
01113         
01120         protected $customlistindent = -1;
01121         
01127         protected $opencell = true;
01128 
01134         protected $embeddedfiles = array();
01135 
01141         protected $premode = false;
01142 
01149         protected $transfmrk = array();
01150 
01156         protected $htmlLinkColorArray = array(0, 0, 255);
01157 
01163         protected $htmlLinkFontStyle = 'U';
01164 
01170         protected $numpages = 0;
01171 
01177         protected $pagelen = array();
01178 
01184         protected $numimages = 0;
01185 
01191         protected $imagekeys = array();
01192 
01198         protected $bufferlen = 0;
01199 
01205         protected $diskcache = false;
01206 
01212         protected $numfonts = 0;
01213 
01219         protected $fontkeys = array();
01220         
01226         protected $font_obj_ids = array();
01227 
01233         protected $pageopen = array();
01234         
01240         protected $default_monospaced_font = 'courier';
01241 
01247         protected $objcopy;
01248 
01254         protected $cache_file_lenght = array();
01255 
01261         protected $thead = '';
01262 
01268         protected $theadMargins = array();
01269 
01275         protected $cache_UTF8StringToArray = array();
01276 
01282         protected $cache_maxsize_UTF8StringToArray = 8;
01283 
01289         protected $cache_size_UTF8StringToArray = 0;
01290 
01296         protected $sign = false;
01297 
01303         protected $signature_data = array();
01304 
01310         protected $signature_max_lenght = 11742;
01311 
01317         protected $re_spaces = '/[\s]/';
01318 
01324         protected $sig_obj_id = 0;
01325 
01331         protected $byterange_string = '/ByteRange[0 ********** ********** **********]';
01332 
01338         protected $sig_annot_ref = '***SIGANNREF*** 0 R';
01339 
01345         protected $page_obj_id = array();
01346 
01352         protected $embedded_start_obj_id = 100000;
01353 
01359         protected $annots_start_obj_id = 200000;
01360         
01366         protected $annot_obj_id = 200000;
01367         
01373         protected $curr_annot_obj_id = 200000;
01374         
01380         protected $form_obj_id = array();
01381         
01382         
01383 
01384 
01385 
01386 
01387         protected $default_form_prop = array('lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>array(255, 255, 255), 'strokeColor'=>array(128, 128, 128));
01388 
01394         protected $js_objects = array();
01395 
01401         protected $js_start_obj_id = 300000;
01402         
01408         protected $js_obj_id = 300000;
01409         
01415         protected $form_action = '';
01416 
01422         protected $form_enctype = 'application/x-www-form-urlencoded';
01423 
01429         protected $form_mode = 'post';
01430 
01436         protected $apxo_start_obj_id = 400000;
01437         
01443         protected $apxo_obj_id = 400000;
01444         
01450         protected $annotation_fonts = array();
01451         
01457         protected $radiobutton_groups = array();
01458         
01464         protected $radio_groups = array();
01465         
01471         protected $textindent = 0;
01472         
01478         protected $start_transaction_page = 0;
01479         
01480         
01481         
01482         
01483 
01497         public function __construct($orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding='UTF-8', $diskcache=false) {
01498             
01499             if (function_exists('mb_internal_encoding') AND mb_internal_encoding()) {
01500                 $this->internal_encoding = mb_internal_encoding();
01501                 mb_internal_encoding('ASCII');
01502             }
01503             
01504             $this->diskcache = $diskcache ? true : false;
01505             
01506             $this->rtl = false;
01507             $this->tmprtl = false;
01508             
01509             $this->_dochecks();
01510             
01511             $this->isunicode = $unicode;
01512             $this->page = 0;
01513             $this->transfmrk[0] = array();
01514             $this->pagedim = array();
01515             $this->n = 2;
01516             $this->buffer = '';
01517             $this->pages = array();
01518             $this->state = 0;
01519             $this->fonts = array();
01520             $this->FontFiles = array();
01521             $this->diffs = array();
01522             $this->images = array();
01523             $this->links = array();
01524             $this->gradients = array();
01525             $this->InFooter = false;
01526             $this->lasth = 0;
01527             $this->FontFamily = 'helvetica';
01528             $this->FontStyle = '';
01529             $this->FontSizePt = 12;
01530             $this->underline = false;
01531             $this->linethrough = false;
01532             $this->DrawColor = '0 G';
01533             $this->FillColor = '0 g';
01534             $this->TextColor = '0 g';
01535             $this->ColorFlag = false;
01536             
01537             $this->encrypted = false;
01538             $this->last_rc4_key = '';
01539             $this->padding = "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A";
01540             
01541             $this->CoreFonts = array(
01542                 'courier'=>'Courier',
01543                 'courierB'=>'Courier-Bold',
01544                 'courierI'=>'Courier-Oblique',
01545                 'courierBI'=>'Courier-BoldOblique',
01546                 'helvetica'=>'Helvetica',
01547                 'helveticaB'=>'Helvetica-Bold',
01548                 'helveticaI'=>'Helvetica-Oblique',
01549                 'helveticaBI'=>'Helvetica-BoldOblique',
01550                 'times'=>'Times-Roman',
01551                 'timesB'=>'Times-Bold',
01552                 'timesI'=>'Times-Italic',
01553                 'timesBI'=>'Times-BoldItalic',
01554                 'symbol'=>'Symbol',
01555                 'zapfdingbats'=>'ZapfDingbats'
01556             );
01557             
01558             $this->setPageUnit($unit);
01559             
01560             $this->setPageFormat($format, $orientation);
01561             
01562             $margin = 28.35 / $this->k;
01563             $this->SetMargins($margin, $margin);
01564             
01565             $this->cMargin = $margin / 10;
01566             
01567             $this->LineWidth = 0.57 / $this->k;
01568             $this->linestyleWidth = sprintf('%.2F w', ($this->LineWidth * $this->k));
01569             $this->linestyleCap = '0 J';
01570             $this->linestyleJoin = '0 j';
01571             $this->linestyleDash = '[] 0 d';
01572             
01573             $this->SetAutoPageBreak(true, (2 * $margin));
01574             
01575             $this->SetDisplayMode('fullwidth');
01576             
01577             $this->SetCompression(true);
01578             
01579             $this->PDFVersion = '1.7';
01580             $this->encoding = $encoding;
01581             $this->HREF = array();
01582             $this->getFontsList();
01583             $this->fgcolor = array('R' => 0, 'G' => 0, 'B' => 0);
01584             $this->bgcolor = array('R' => 255, 'G' => 255, 'B' => 255);
01585             $this->extgstates = array();
01586             
01587             $this->sign = false;
01588             $this->ur = false;
01589             $this->ur_document = '/FullSave';
01590             $this->ur_annots = '/Create/Delete/Modify/Copy/Import/Export';
01591             $this->ur_form = '/Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate';
01592             $this->ur_signature = '/Modify';            
01593             
01594             $this->jpeg_quality = 75;
01595             
01596             $this->utf8Bidi(array(''), '');
01597             
01598             $this->SetFont($this->FontFamily, $this->FontStyle, $this->FontSizePt);
01599             
01600             if ($this->isunicode AND (@preg_match('/\pL/u', 'a') == 1)) {
01601                 
01602                 
01603                 
01604                 
01605                 
01606                 $this->re_spaces = '/[\s\p{Z}]/u';
01607             } else {
01608                 
01609                 $this->re_spaces = '/[\s]/';
01610             }
01611             $this->annot_obj_id = $this->annots_start_obj_id;
01612             $this->curr_annot_obj_id = $this->annots_start_obj_id;
01613             $this->apxo_obj_id = $this->apxo_start_obj_id;
01614             $this->js_obj_id = $this->js_start_obj_id;
01615             $this->default_form_prop = array('lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>array(255, 255, 255), 'strokeColor'=>array(128, 128, 128));
01616         }
01617         
01623         public function __destruct() {
01624             
01625             if (isset($this->internal_encoding) AND !empty($this->internal_encoding)) {
01626                 mb_internal_encoding($this->internal_encoding);
01627             }
01628             
01629             $this->_destroy(true);
01630         }
01631         
01638         public function setPageUnit($unit) {
01639         
01640             switch (strtolower($unit)) {
01641                 
01642                 case 'px':
01643                 case 'pt': {
01644                     $this->k = 1;
01645                     break;
01646                 }
01647                 
01648                 case 'mm': {
01649                     $this->k = $this->dpi / 25.4;
01650                     break;
01651                 }
01652                 
01653                 case 'cm': {
01654                     $this->k = $this->dpi / 2.54;
01655                     break;
01656                 }
01657                 
01658                 case 'in': {
01659                     $this->k = $this->dpi;
01660                     break;
01661                 }
01662                 
01663                 default : {
01664                     $this->Error('Incorrect unit: '.$unit);
01665                     break;
01666                 }
01667             }
01668             if (isset($this->CurOrientation)) {
01669                     $this->setPageOrientation($this->CurOrientation);
01670             }
01671         }
01672         
01680         public function setPageFormat($format, $orientation='P') {
01681             
01682             if (is_string($format)) {
01683                 
01684                 
01685                 switch (strtoupper($format)) {
01686                     case '4A0': {$format = array(4767.87,6740.79); break;}
01687                     case '2A0': {$format = array(3370.39,4767.87); break;}
01688                     case 'A0': {$format = array(2383.94,3370.39); break;}
01689                     case 'A1': {$format = array(1683.78,2383.94); break;}
01690                     case 'A2': {$format = array(1190.55,1683.78); break;}
01691                     case 'A3': {$format = array(841.89,1190.55); break;}
01692                     case 'A4': default: {$format = array(595.28,841.89); break;}
01693                     case 'A5': {$format = array(419.53,595.28); break;}
01694                     case 'A6': {$format = array(297.64,419.53); break;}
01695                     case 'A7': {$format = array(209.76,297.64); break;}
01696                     case 'A8': {$format = array(147.40,209.76); break;}
01697                     case 'A9': {$format = array(104.88,147.40); break;}
01698                     case 'A10': {$format = array(73.70,104.88); break;}
01699                     case 'B0': {$format = array(2834.65,4008.19); break;}
01700                     case 'B1': {$format = array(2004.09,2834.65); break;}
01701                     case 'B2': {$format = array(1417.32,2004.09); break;}
01702                     case 'B3': {$format = array(1000.63,1417.32); break;}
01703                     case 'B4': {$format = array(708.66,1000.63); break;}
01704                     case 'B5': {$format = array(498.90,708.66); break;}
01705                     case 'B6': {$format = array(354.33,498.90); break;}
01706                     case 'B7': {$format = array(249.45,354.33); break;}
01707                     case 'B8': {$format = array(175.75,249.45); break;}
01708                     case 'B9': {$format = array(124.72,175.75); break;}
01709                     case 'B10': {$format = array(87.87,124.72); break;}
01710                     case 'C0': {$format = array(2599.37,3676.54); break;}
01711                     case 'C1': {$format = array(1836.85,2599.37); break;}
01712                     case 'C2': {$format = array(1298.27,1836.85); break;}
01713                     case 'C3': {$format = array(918.43,1298.27); break;}
01714                     case 'C4': {$format = array(649.13,918.43); break;}
01715                     case 'C5': {$format = array(459.21,649.13); break;}
01716                     case 'C6': {$format = array(323.15,459.21); break;}
01717                     case 'C7': {$format = array(229.61,323.15); break;}
01718                     case 'C8': {$format = array(161.57,229.61); break;}
01719                     case 'C9': {$format = array(113.39,161.57); break;}
01720                     case 'C10': {$format = array(79.37,113.39); break;}
01721                     case 'RA0': {$format = array(2437.80,3458.27); break;}
01722                     case 'RA1': {$format = array(1729.13,2437.80); break;}
01723                     case 'RA2': {$format = array(1218.90,1729.13); break;}
01724                     case 'RA3': {$format = array(864.57,1218.90); break;}
01725                     case 'RA4': {$format = array(609.45,864.57); break;}
01726                     case 'SRA0': {$format = array(2551.18,3628.35); break;}
01727                     case 'SRA1': {$format = array(1814.17,2551.18); break;}
01728                     case 'SRA2': {$format = array(1275.59,1814.17); break;}
01729                     case 'SRA3': {$format = array(907.09,1275.59); break;}
01730                     case 'SRA4': {$format = array(637.80,907.09); break;}
01731                     case 'LETTER': {$format = array(612.00,792.00); break;}
01732                     case 'LEGAL': {$format = array(612.00,1008.00); break;}
01733                     case 'EXECUTIVE': {$format = array(521.86,756.00); break;}
01734                     case 'FOLIO': {$format = array(612.00,936.00); break;}
01735                 }
01736                 $this->fwPt = $format[0];
01737                 $this->fhPt = $format[1];
01738             } else {
01739                 $this->fwPt = $format[0] * $this->k;
01740                 $this->fhPt = $format[1] * $this->k;
01741             }
01742             $this->setPageOrientation($orientation);
01743         }
01744         
01753         public function setPageOrientation($orientation, $autopagebreak='', $bottommargin='') {
01754             $orientation = strtoupper($orientation);
01755             if (($orientation == 'P') OR ($orientation == 'PORTRAIT')) {
01756                 $this->CurOrientation = 'P';
01757                 $this->wPt = $this->fwPt;
01758                 $this->hPt = $this->fhPt;
01759             } elseif (($orientation == 'L') OR ($orientation == 'LANDSCAPE')) {
01760                 $this->CurOrientation = 'L';
01761                 $this->wPt = $this->fhPt;
01762                 $this->hPt = $this->fwPt;
01763             } else {
01764                 $this->Error('Incorrect orientation: '.$orientation);
01765             }
01766             $this->w = $this->wPt / $this->k;
01767             $this->h = $this->hPt / $this->k;
01768             if ($this->empty_string($autopagebreak)) {
01769                 if (isset($this->AutoPageBreak)) {
01770                     $autopagebreak = $this->AutoPageBreak;
01771                 } else {
01772                     $autopagebreak = true;
01773                 }
01774             }
01775             if ($this->empty_string($bottommargin)) {
01776                 if (isset($this->bMargin)) {
01777                     $bottommargin = $this->bMargin;
01778                 } else {
01779                     
01780                     $bottommargin = 2 * 28.35 / $this->k;
01781                 }
01782             }
01783             $this->SetAutoPageBreak($autopagebreak, $bottommargin);
01784             
01785             $this->pagedim[$this->page] = array('w' => $this->wPt, 'h' => $this->hPt, 'wk' => $this->w, 'hk' => $this->h, 'tm' => $this->tMargin, 'bm' => $bottommargin, 'lm' => $this->lMargin, 'rm' => $this->rMargin, 'pb' => $autopagebreak, 'or' => $this->CurOrientation, 'olm' => $this->original_lMargin, 'orm' => $this->original_rMargin);
01786         }
01787         
01794         public function setSpacesRE($re='/[\s]/') {
01795             
01796             
01797             
01798             
01799             $this->re_spaces = $re;
01800         }
01801             
01809         public function setRTL($enable, $resetx=true) {
01810             $enable = $enable ? true : false;
01811             $resetx = ($resetx AND ($enable != $this->rtl));
01812             $this->rtl = $enable;
01813             $this->tmprtl = false;
01814             if ($resetx) {
01815                 $this->Ln(0);
01816             }
01817         }
01818         
01825         public function getRTL() {
01826             return $this->rtl;
01827         }
01828         
01835         public function setTempRTL($mode) {
01836             switch ($mode) {
01837                 case false:
01838                 case 'L':
01839                 case 'R': {
01840                     $this->tmprtl = $mode;
01841                 }
01842             }
01843         }
01844         
01852         public function setLastH($h) {
01853             $this->lasth = $h;
01854         }
01855         
01862         public function getLastH() {
01863             return $this->lasth;
01864         }
01865         
01873         public function setImageScale($scale) {
01874             $this->imgscale = $scale;
01875         }
01876 
01884         public function getImageScale() {
01885             return $this->imgscale;
01886         }
01887                 
01897         public function getPageDimensions($pagenum='') {
01898             if (empty($pagenum)) {
01899                 $pagenum = $this->page;
01900             }
01901             return $this->pagedim[$pagenum];
01902         }
01903         
01913         public function getPageWidth($pagenum='') {
01914             if (empty($pagenum)) {
01915                 return $this->w;
01916             }
01917             return $this->pagedim[$pagenum]['w'];
01918         }
01919 
01929         public function getPageHeight($pagenum='') {
01930             if (empty($pagenum)) {
01931                 return $this->h;
01932             }
01933             return $this->pagedim[$pagenum]['h'];
01934         }
01935 
01945         public function getBreakMargin($pagenum='') {
01946             if (empty($pagenum)) {
01947                 return $this->bMargin;
01948             }
01949             return $this->pagedim[$pagenum]['bm'];
01950         }
01951 
01959         public function getScaleFactor() {
01960             return $this->k;
01961         }
01962 
01972         public function SetMargins($left, $top, $right=-1) {
01973             
01974             $this->lMargin = $left;
01975             $this->tMargin = $top;
01976             if ($right == -1) {
01977                 $right = $left;
01978             }
01979             $this->rMargin = $right;
01980         }
01981 
01989         public function SetLeftMargin($margin) {
01990             
01991             $this->lMargin=$margin;
01992             if (($this->page > 0) AND ($this->x < $margin)) {
01993                 $this->x = $margin;
01994             }
01995         }
01996 
02004         public function SetTopMargin($margin) {
02005             
02006             $this->tMargin=$margin;
02007             if (($this->page > 0) AND ($this->y < $margin)) {
02008                 $this->y = $margin;
02009             }
02010         }
02011 
02019         public function SetRightMargin($margin) {
02020             $this->rMargin=$margin;
02021             if (($this->page > 0) AND ($this->x > ($this->w - $margin))) {
02022                 $this->x = $this->w - $margin;
02023             }
02024         }
02025 
02033         public function SetCellPadding($pad) {
02034             $this->cMargin = $pad;
02035         }
02036 
02045         public function SetAutoPageBreak($auto, $margin=0) {
02046             
02047             $this->AutoPageBreak = $auto;
02048             $this->bMargin = $margin;
02049             $this->PageBreakTrigger = $this->h - $margin;
02050         }
02051 
02060         public function SetDisplayMode($zoom, $layout='SinglePage', $mode='UseNone') {
02061             
02062             if (($zoom == 'fullpage') OR ($zoom == 'fullwidth') OR ($zoom == 'real') OR ($zoom == 'default') OR (!is_string($zoom))) {
02063                 $this->ZoomMode = $zoom;
02064             } else {
02065                 $this->Error('Incorrect zoom display mode: '.$zoom);
02066             }
02067             switch ($layout) {
02068                 case 'default':
02069                 case 'single':
02070                 case 'SinglePage': {
02071                     $this->LayoutMode = 'SinglePage';
02072                     break;
02073                 }
02074                 case 'continuous':
02075                 case 'OneColumn': {
02076                     $this->LayoutMode = 'OneColumn';
02077                     break;
02078                 }
02079                 case 'two':
02080                 case 'TwoColumnLeft': {
02081                     $this->LayoutMode = 'TwoColumnLeft';
02082                     break;
02083                 }
02084                 case 'TwoColumnRight': {
02085                     $this->LayoutMode = 'TwoColumnRight';
02086                     break;
02087                 }
02088                 case 'TwoPageLeft': {
02089                     $this->LayoutMode = 'TwoPageLeft';
02090                     break;
02091                 }
02092                 case 'TwoPageRight': {
02093                     $this->LayoutMode = 'TwoPageRight';
02094                     break;
02095                 }
02096                 default: {
02097                     $this->LayoutMode = 'SinglePage';
02098                 }
02099             }
02100             switch ($mode) {
02101                 case 'UseNone': {
02102                     $this->PageMode = 'UseNone';
02103                     break;
02104                 }
02105                 case 'UseOutlines': {
02106                     $this->PageMode = 'UseOutlines';
02107                     break;
02108                 }
02109                 case 'UseThumbs': {
02110                     $this->PageMode = 'UseThumbs';
02111                     break;
02112                 }
02113                 case 'FullScreen': {
02114                     $this->PageMode = 'FullScreen';
02115                     break;
02116                 }
02117                 case 'UseOC': {
02118                     $this->PageMode = 'UseOC';
02119                     break;
02120                 }
02121                 case '': {
02122                     $this->PageMode = 'UseAttachments';
02123                     break;
02124                 }
02125                 default: {
02126                     $this->PageMode = 'UseNone';
02127                 }
02128             }
02129         }
02130 
02138         public function SetCompression($compress) {
02139             
02140             if (function_exists('gzcompress')) {
02141                 $this->compress = $compress;
02142             } else {
02143                 $this->compress = false;
02144             }
02145         }
02146 
02154         public function SetTitle($title) {
02155             
02156             $this->title = $title;
02157         }
02158 
02166         public function SetSubject($subject) {
02167             
02168             $this->subject = $subject;
02169         }
02170 
02178         public function SetAuthor($author) {
02179             
02180             $this->author = $author;
02181         }
02182 
02190         public function SetKeywords($keywords) {
02191             
02192             $this->keywords = $keywords;
02193         }
02194 
02202         public function SetCreator($creator) {
02203             
02204             $this->creator = $creator;
02205         }
02206         
02214         public function Error($msg) {
02215             
02216             $this->_destroy(true);
02217             
02218             die('<strong>TCPDF ERROR: </strong>'.$msg);
02219         }
02220 
02229         public function Open() {
02230             
02231             $this->state = 1;
02232         }
02233 
02242         public function Close() {
02243             if ($this->state == 3) {
02244                 return;
02245             }
02246             if ($this->page == 0) {
02247                 $this->AddPage();
02248             }
02249             
02250             $this->endPage();
02251             
02252             $this->_enddoc();
02253             
02254             $this->_destroy(false);
02255         }
02256         
02265         public function setPage($pnum, $resetmargins=false) {
02266             if ($pnum == $this->page) {
02267                 return;
02268             }
02269             if (($pnum > 0) AND ($pnum <= $this->numpages)) {
02270                 $this->state = 2;
02271                 
02272                 
02273                 $oldpage = $this->page;
02274                 $this->page = $pnum;
02275                 $this->wPt = $this->pagedim[$this->page]['w'];
02276                 $this->hPt = $this->pagedim[$this->page]['h'];
02277                 $this->w = $this->wPt / $this->k;
02278                 $this->h = $this->hPt / $this->k;
02279                 $this->tMargin = $this->pagedim[$this->page]['tm'];
02280                 $this->bMargin = $this->pagedim[$this->page]['bm'];
02281                 $this->original_lMargin = $this->pagedim[$this->page]['olm'];
02282                 $this->original_rMargin = $this->pagedim[$this->page]['orm'];
02283                 $this->AutoPageBreak = $this->pagedim[$this->page]['pb'];
02284                 $this->CurOrientation = $this->pagedim[$this->page]['or'];
02285                 $this->SetAutoPageBreak($this->AutoPageBreak, $this->bMargin);
02286                 
02287                 
02288                 if ($resetmargins) {
02289                     $this->lMargin = $this->pagedim[$this->page]['olm'];
02290                     $this->rMargin = $this->pagedim[$this->page]['orm'];
02291                     $this->SetY($this->tMargin);
02292                 } else {
02293                     
02294                     if ($this->pagedim[$this->page]['olm'] != $this->pagedim[$oldpage]['olm']) {
02295                         $deltam = $this->pagedim[$this->page]['olm'] - $this->pagedim[$this->page]['orm'];
02296                         $this->lMargin += $deltam;
02297                         $this->rMargin -= $deltam;
02298                     }
02299                 }
02300             } else {
02301                 $this->Error('Wrong page number on setPage() function.');
02302             }
02303         }
02304         
02312         public function lastPage($resetmargins=false) {
02313             $this->setPage($this->getNumPages(), $resetmargins);
02314         }
02315         
02323         public function getPage() {
02324             return $this->page;
02325         }
02326         
02327         
02335         public function getNumPages() {
02336             return $this->numpages;
02337         }
02338 
02348         public function AddPage($orientation='', $format='') {
02349             if (!isset($this->original_lMargin)) {
02350                 $this->original_lMargin = $this->lMargin;
02351             }
02352             if (!isset($this->original_rMargin)) {
02353                 $this->original_rMargin = $this->rMargin;
02354             }
02355             
02356             $this->endPage();
02357             
02358             $this->startPage($orientation, $format);
02359         }
02360 
02367         protected function endPage() {
02368             
02369             if (($this->page == 0) OR ($this->numpages > $this->page) OR (!$this->pageopen[$this->page])) {
02370                 return;
02371             }
02372             $this->InFooter = true;
02373             
02374             $this->setFooter();
02375             
02376             $this->_endpage();
02377             
02378             $this->pageopen[$this->page] = false;
02379             $this->InFooter = false;
02380         }
02381 
02391         protected function startPage($orientation='', $format='') {
02392             if ($this->numpages > $this->page) {
02393                 
02394                 $this->setPage($this->page + 1);
02395                 $this->SetY($this->tMargin);
02396                 return;
02397             }
02398             
02399             if ($this->state == 0) {
02400                 $this->Open();
02401             }
02402             ++$this->numpages;
02403             $this->swapMargins($this->booklet);
02404             
02405             $gvars = $this->getGraphicVars();
02406             
02407             $this->_beginpage($orientation, $format);
02408             
02409             $this->pageopen[$this->page] = true;
02410             
02411             $this->setGraphicVars($gvars);
02412             
02413             $this->setPageMark();
02414             
02415             $this->setHeader();
02416             
02417             $this->setGraphicVars($gvars);
02418             
02419             $this->setPageMark();
02420             
02421             $this->setTableHeader();
02422         }
02423             
02431         public function setPageMark() {
02432             $this->intmrk[$this->page] = $this->pagelen[$this->page];
02433             $this->setContentMark();
02434         }
02435         
02442         protected function setContentMark($page=0) {
02443             if ($page <= 0) {
02444                 $page = $this->page;
02445             }
02446             if (isset($this->footerlen[$page])) {
02447                 $this->cntmrk[$page] = $this->pagelen[$page] - $this->footerlen[$page];
02448             } else {
02449                 $this->cntmrk[$page] = $this->pagelen[$page];
02450             }
02451         }
02452         
02461         public function setHeaderData($ln='', $lw=0, $ht='', $hs='') {
02462             $this->header_logo = $ln;
02463             $this->header_logo_width = $lw;
02464             $this->header_title = $ht;
02465             $this->header_string = $hs;
02466         }
02467         
02475         public function getHeaderData() {
02476             $ret = array();
02477             $ret['logo'] = $this->header_logo;
02478             $ret['logo_width'] = $this->header_logo_width;
02479             $ret['title'] = $this->header_title;
02480             $ret['string'] = $this->header_string;
02481             return $ret;
02482         }
02483         
02490         public function setHeaderMargin($hm=10) {
02491             $this->header_margin = $hm;
02492         }
02493         
02500         public function getHeaderMargin() {
02501             return $this->header_margin;
02502         }
02503         
02510         public function setFooterMargin($fm=10) {
02511             $this->footer_margin = $fm;
02512         }
02513         
02520         public function getFooterMargin() {
02521             return $this->footer_margin;
02522         }
02528         public function setPrintHeader($val=true) {
02529             $this->print_header = $val;
02530         }
02531         
02537         public function setPrintFooter($val=true) {
02538             $this->print_footer = $val;
02539         }
02540         
02546         public function getImageRBX() {
02547             return $this->img_rb_x;
02548         }
02549         
02555         public function getImageRBY() {
02556             return $this->img_rb_y;
02557         }
02558         
02564         public function Header() {
02565             $ormargins = $this->getOriginalMargins();
02566             $headerfont = $this->getHeaderFont();
02567             $headerdata = $this->getHeaderData();
02568             if (($headerdata['logo']) AND ($headerdata['logo'] != K_BLANK_IMAGE)) {
02569                 $this->Image(K_PATH_IMAGES.$headerdata['logo'], $this->GetX(), $this->getHeaderMargin(), $headerdata['logo_width']);
02570                 $imgy = $this->getImageRBY();
02571             } else {
02572                 $imgy = $this->GetY();
02573             }
02574             $cell_height = round(($this->getCellHeightRatio() * $headerfont[2]) / $this->getScaleFactor(), 2);
02575             
02576             if ($this->getRTL()) {
02577                 $header_x = $ormargins['right'] + ($headerdata['logo_width'] * 1.1);
02578             } else {
02579                 $header_x = $ormargins['left'] + ($headerdata['logo_width'] * 1.1);
02580             }
02581             $this->SetTextColor(0, 0, 0);
02582             
02583             $this->SetFont($headerfont[0], 'B', $headerfont[2] + 1);
02584             $this->SetX($header_x);         
02585             $this->Cell(0, $cell_height, $headerdata['title'], 0, 1, '', 0, '', 0);
02586             
02587             $this->SetFont($headerfont[0], $headerfont[1], $headerfont[2]);
02588             $this->SetX($header_x);
02589             $this->MultiCell(0, $cell_height, $headerdata['string'], 0, '', 0, 1, '', '', true, 0, false);
02590             
02591             $this->SetLineStyle(array('width' => 0.85 / $this->getScaleFactor(), 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0)));
02592             $this->SetY((2.835 / $this->getScaleFactor()) + max($imgy, $this->GetY()));
02593             if ($this->getRTL()) {
02594                 $this->SetX($ormargins['right']);
02595             } else {
02596                 $this->SetX($ormargins['left']);
02597             }
02598             $this->Cell(0, 0, '', 'T', 0, 'C');
02599         }
02600         
02606         public function Footer() {              
02607             $cur_y = $this->GetY();
02608             $ormargins = $this->getOriginalMargins();
02609             $this->SetTextColor(0, 0, 0);           
02610             
02611             $line_width = 0.85 / $this->getScaleFactor();
02612             $this->SetLineStyle(array('width' => $line_width, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0)));
02613             
02614             $barcode = $this->getBarcode();
02615             if (!empty($barcode)) {
02616                 $this->Ln($line_width);
02617                 $barcode_width = round(($this->getPageWidth() - $ormargins['left'] - $ormargins['right'])/3);
02618                 $this->write1DBarcode($barcode, 'C128B', $this->GetX(), $cur_y + $line_width, $barcode_width, (($this->getFooterMargin() / 3) - $line_width), 0.3, '', ''); 
02619             }
02620             if (empty($this->pagegroups)) {
02621                 $pagenumtxt = $this->l['w_page'].' '.$this->getAliasNumPage().' / '.$this->getAliasNbPages();
02622             } else {
02623                 $pagenumtxt = $this->l['w_page'].' '.$this->getPageNumGroupAlias().' / '.$this->getPageGroupAlias();
02624             }       
02625             $this->SetY($cur_y);
02626             
02627             if ($this->getRTL()) {
02628                 $this->SetX($ormargins['right']);
02629                 $this->Cell(0, 0, $pagenumtxt, 'T', 0, 'L');
02630             } else {
02631                 $this->SetX($ormargins['left']);
02632                 $this->Cell(0, 0, $pagenumtxt, 'T', 0, 'R');
02633             }
02634         }
02635         
02641         protected function setHeader() {
02642             if ($this->print_header) {
02643                 $lasth = $this->lasth;
02644                 $this->_out('q');
02645                 $this->rMargin = $this->original_rMargin;
02646                 $this->lMargin = $this->original_lMargin;
02647                 $this->cMargin = 0;
02648                 
02649                 if ($this->rtl) {
02650                     $this->SetXY($this->original_rMargin, $this->header_margin);
02651                 } else {
02652                     $this->SetXY($this->original_lMargin, $this->header_margin);
02653                 }
02654                 $this->SetFont($this->header_font[0], $this->header_font[1], $this->header_font[2]);
02655                 $this->Header();
02656                 
02657                 if ($this->rtl) {
02658                     $this->SetXY($this->original_rMargin, $this->tMargin);
02659                 } else {
02660                     $this->SetXY($this->original_lMargin, $this->tMargin);
02661                 }
02662                 $this->_out('Q');
02663                 $this->lasth = $lasth;
02664             }
02665         }
02666         
02672         protected function setFooter() {
02673             
02674             
02675             $gvars = $this->getGraphicVars();
02676             
02677             $this->footerpos[$this->page] = $this->pagelen[$this->page];
02678             $this->_out("\n");
02679             if ($this->print_footer) {
02680                 $lasth = $this->lasth;
02681                 $this->_out('q');
02682                 $this->rMargin = $this->original_rMargin;
02683                 $this->lMargin = $this->original_lMargin;
02684                 $this->cMargin = 0;
02685                 
02686                 $footer_y = $this->h - $this->footer_margin;
02687                 if ($this->rtl) {
02688                     $this->SetXY($this->original_rMargin, $footer_y);
02689                 } else {
02690                     $this->SetXY($this->original_lMargin, $footer_y);
02691                 }
02692                 $this->SetFont($this->footer_font[0], $this->footer_font[1], $this->footer_font[2]);
02693                 $this->Footer();
02694                 
02695                 if ($this->rtl) {
02696                     $this->SetXY($this->original_rMargin, $this->tMargin);
02697                 } else {
02698                     $this->SetXY($this->original_lMargin, $this->tMargin);
02699                 }
02700                 $this->_out('Q');
02701                 $this->lasth = $lasth;
02702             }
02703             
02704             $this->setGraphicVars($gvars);
02705             
02706             $this->footerlen[$this->page] = $this->pagelen[$this->page] - $this->footerpos[$this->page] + 1;
02707         }
02708 
02714         protected function setTableHeader() {
02715             if (isset($this->theadMargins['top'])) {
02716                 
02717                 $this->tMargin = $this->theadMargins['top'];
02718                 $this->pagedim[$this->page]['tm'] = $this->tMargin;
02719                 $this->y = $this->tMargin;
02720             }
02721             if (!$this->empty_string($this->thead)) {
02722                 
02723                 $prev_lMargin = $this->lMargin;
02724                 $prev_rMargin = $this->rMargin;
02725                 $this->lMargin = $this->pagedim[$this->page]['olm'];
02726                 $this->rMargin = $this->pagedim[$this->page]['orm'];
02727                 $this->cMargin = $this->theadMargins['cmargin'];
02728                 
02729                 $this->writeHTML($this->thead, false, false, false, false, '');
02730                 
02731                 if (!isset($this->theadMargins['top'])) {
02732                     $this->theadMargins['top'] = $this->tMargin;
02733                 }
02734                 $this->tMargin = $this->y;
02735                 $this->pagedim[$this->page]['tm'] = $this->tMargin;
02736                 $this->lasth = 0;
02737                 $this->lMargin = $prev_lMargin;
02738                 $this->rMargin = $prev_rMargin;
02739             }
02740         }
02741         
02749         public function PageNo() {
02750             return $this->page;
02751         }
02752 
02765         public function AddSpotColor($name, $c, $m, $y, $k) {
02766             if (!isset($this->spot_colors[$name])) {
02767                 $i = 1 + count($this->spot_colors);
02768                 $this->spot_colors[$name] = array('i' => $i, 'c' => $c, 'm' => $m, 'y' => $y, 'k' => $k);
02769             }
02770         }
02771 
02781         public function SetDrawColorArray($color) {
02782             if (isset($color)) {
02783                 $color = array_values($color);
02784                 $r = isset($color[0]) ? $color[0] : -1;
02785                 $g = isset($color[1]) ? $color[1] : -1;
02786                 $b = isset($color[2]) ? $color[2] : -1;
02787                 $k = isset($color[3]) ? $color[3] : -1;
02788                 if ($r >= 0) {
02789                     $this->SetDrawColor($r, $g, $b, $k);
02790                 }
02791             }
02792         }
02793 
02804         public function SetDrawColor($col1=0, $col2=-1, $col3=-1, $col4=-1) {
02805             
02806             if (!is_numeric($col1)) {
02807                 $col1 = 0;
02808             }
02809             if (!is_numeric($col2)) {
02810                 $col2 = -1;
02811             }
02812             if (!is_numeric($col3)) {
02813                 $col3 = -1;
02814             }
02815             if (!is_numeric($col4)) {
02816                 $col4 = -1;
02817             }
02818             
02819             if (($col2 == -1) AND ($col3 == -1) AND ($col4 == -1)) {
02820                 
02821                 $this->DrawColor = sprintf('%.3F G', $col1/255);
02822             } elseif ($col4 == -1) {
02823                 
02824                 $this->DrawColor = sprintf('%.3F %.3F %.3F RG', $col1/255, $col2/255, $col3/255);
02825             } else {
02826                 
02827                 $this->DrawColor = sprintf('%.3F %.3F %.3F %.3F K', $col1/100, $col2/100, $col3/100, $col4/100);
02828             }
02829             if ($this->page > 0) {
02830                 $this->_out($this->DrawColor);
02831             }
02832         }
02833         
02842         public function SetDrawSpotColor($name, $tint=100) {
02843             if (!isset($this->spot_colors[$name])) {
02844                 $this->Error('Undefined spot color: '.$name);
02845             }
02846             $this->DrawColor = sprintf('/CS%d CS %.3F SCN', $this->spot_colors[$name]['i'], $tint/100);
02847             if ($this->page > 0) {
02848                 $this->_out($this->DrawColor);
02849             }
02850         }
02851         
02861         public function SetFillColorArray($color) {
02862             if (isset($color)) {
02863                 $color = array_values($color);
02864                 $r = isset($color[0]) ? $color[0] : -1;
02865                 $g = isset($color[1]) ? $color[1] : -1;
02866                 $b = isset($color[2]) ? $color[2] : -1;
02867                 $k = isset($color[3]) ? $color[3] : -1;
02868                 if ($r >= 0) {
02869                     $this->SetFillColor($r, $g, $b, $k);
02870                 }
02871             }
02872         }
02873         
02884         public function SetFillColor($col1=0, $col2=-1, $col3=-1, $col4=-1) {
02885             
02886             if (!is_numeric($col1)) {
02887                 $col1 = 0;
02888             }
02889             if (!is_numeric($col2)) {
02890                 $col2 = -1;
02891             }
02892             if (!is_numeric($col3)) {
02893                 $col3 = -1;
02894             }
02895             if (!is_numeric($col4)) {
02896                 $col4 = -1;
02897             }
02898             
02899             if (($col2 == -1) AND ($col3 == -1) AND ($col4 == -1)) {
02900                 
02901                 $this->FillColor = sprintf('%.3F g', $col1/255);
02902                 $this->bgcolor = array('G' => $col1);
02903             } elseif ($col4 == -1) {
02904                 
02905                 $this->FillColor = sprintf('%.3F %.3F %.3F rg', $col1/255, $col2/255, $col3/255);
02906                 $this->bgcolor = array('R' => $col1, 'G' => $col2, 'B' => $col3);
02907             } else {
02908                 
02909                 $this->FillColor = sprintf('%.3F %.3F %.3F %.3F k', $col1/100, $col2/100, $col3/100, $col4/100);
02910                 $this->bgcolor = array('C' => $col1, 'M' => $col2, 'Y' => $col3, 'K' => $col4);
02911             }
02912             $this->ColorFlag = ($this->FillColor != $this->TextColor);
02913             if ($this->page > 0) {
02914                 $this->_out($this->FillColor);
02915             }
02916         }
02917         
02926         public function SetFillSpotColor($name, $tint=100) {
02927             if (!isset($this->spot_colors[$name])) {
02928                 $this->Error('Undefined spot color: '.$name);
02929             }
02930             $this->FillColor = sprintf('/CS%d cs %.3F scn', $this->spot_colors[$name]['i'], $tint/100);
02931             $this->ColorFlag = ($this->FillColor != $this->TextColor);
02932             if ($this->page > 0) {
02933                 $this->_out($this->FillColor);
02934             }
02935         }
02936         
02945         public function SetTextColorArray($color) {
02946             if (isset($color)) {
02947                 $color = array_values($color);
02948                 $r = isset($color[0]) ? $color[0] : -1;
02949                 $g = isset($color[1]) ? $color[1] : -1;
02950                 $b = isset($color[2]) ? $color[2] : -1;
02951                 $k = isset($color[3]) ? $color[3] : -1;
02952                 if ($r >= 0) {
02953                     $this->SetTextColor($r, $g, $b, $k);
02954                 }
02955             }
02956         }
02957 
02968         public function SetTextColor($col1=0, $col2=-1, $col3=-1, $col4=-1) {
02969             
02970             if (!is_numeric($col1)) {
02971                 $col1 = 0;
02972             }
02973             if (!is_numeric($col2)) {
02974                 $col2 = -1;
02975             }
02976             if (!is_numeric($col3)) {
02977                 $col3 = -1;
02978             }
02979             if (!is_numeric($col4)) {
02980                 $col4 = -1;
02981             }
02982             
02983             if (($col2 == -1) AND ($col3 == -1) AND ($col4 == -1)) {
02984                 
02985                 $this->TextColor = sprintf('%.3F g', $col1/255);
02986                 $this->fgcolor = array('G' => $col1);
02987             } elseif ($col4 == -1) {
02988                 
02989                 $this->TextColor = sprintf('%.3F %.3F %.3F rg', $col1/255, $col2/255, $col3/255);
02990                 $this->fgcolor = array('R' => $col1, 'G' => $col2, 'B' => $col3);
02991             } else {
02992                 
02993                 $this->TextColor = sprintf('%.3F %.3F %.3F %.3F k', $col1/100, $col2/100, $col3/100, $col4/100);
02994                 $this->fgcolor = array('C' => $col1, 'M' => $col2, 'Y' => $col3, 'K' => $col4);
02995             }
02996             $this->ColorFlag = ($this->FillColor != $this->TextColor);
02997         }
02998         
03007         public function SetTextSpotColor($name, $tint=100) {
03008             if (!isset($this->spot_colors[$name])) {
03009                 $this->Error('Undefined spot color: '.$name);
03010             }
03011             $this->TextColor = sprintf('/CS%d cs %.3F scn', $this->spot_colors[$name]['i'], $tint/100);
03012             $this->ColorFlag = ($this->FillColor != $this->TextColor);
03013             if ($this->page > 0) {
03014                 $this->_out($this->TextColor);
03015             }
03016         }
03017 
03029         public function GetStringWidth($s, $fontname='', $fontstyle='', $fontsize=0) {
03030             return $this->GetArrStringWidth($this->utf8Bidi($this->UTF8StringToArray($s), $s, $this->tmprtl), $fontname, $fontstyle, $fontsize);
03031         }
03032         
03044         public function GetArrStringWidth($sa, $fontname='', $fontstyle='', $fontsize=0) {
03045             
03046             if (!$this->empty_string($fontname)) {
03047                 $prev_FontFamily = $this->FontFamily;
03048                 $prev_FontStyle = $this->FontStyle;
03049                 $prev_FontSizePt = $this->FontSizePt;
03050                 $this->SetFont($fontname, $fontstyle, $fontsize);
03051             }
03052             $w = 0;
03053             foreach ($sa as $char) {
03054                 $w += $this->GetCharWidth($char);
03055             }
03056             
03057             if (!$this->empty_string($fontname)) {
03058                 $this->SetFont($prev_FontFamily, $prev_FontStyle, $prev_FontSizePt);
03059             }
03060             return $w;
03061         }
03062         
03071         public function GetCharWidth($char) {
03072             if ($char == 173) {
03073                 
03074                 return (0);
03075             }
03076             $cw = &$this->CurrentFont['cw'];
03077             if (isset($cw[$char])) {
03078                 $w = $cw[$char];
03079             } elseif (isset($this->CurrentFont['dw'])) {
03080                 
03081                 $w = $this->CurrentFont['dw'];
03082             } elseif (isset($cw[32])) {
03083                 
03084                 $dw = $cw[32];
03085             } else {
03086                 $w = 600;
03087             }
03088             return ($w * $this->FontSize / 1000);
03089         }
03090         
03098         public function GetNumChars($s) {
03099             if (($this->CurrentFont['type'] == 'TrueTypeUnicode') OR ($this->CurrentFont['type'] == 'cidfont0')) {
03100                 return count($this->UTF8StringToArray($s));
03101             } 
03102             return strlen($s);
03103         }
03104             
03110         protected function getFontsList() {
03111             $fontsdir = opendir($this->_getfontpath());
03112             while (($file = readdir($fontsdir)) !== false) {
03113                 if (substr($file, -4) == '.php') {
03114                     array_push($this->fontlist, strtolower(basename($file, '.php')));
03115                 }
03116             }
03117             closedir($fontsdir);
03118         }
03119         
03132         public function AddFont($family, $style='', $fontfile='') {
03133             if ($this->empty_string($family)) {
03134                 if (!$this->empty_string($this->FontFamily)) {
03135                     $family = $this->FontFamily;
03136                 } else {
03137                     $this->Error('Empty font family');
03138                 }
03139             }
03140             $family = strtolower($family);
03141             if ((!$this->isunicode) AND ($family == 'arial')) {
03142                 $family = 'helvetica';
03143             }
03144             if (($family == 'symbol') OR ($family == 'zapfdingbats')) {
03145                 $style = '';
03146             }
03147             $tempstyle = strtoupper($style);
03148             $style = '';
03149             
03150             if (strpos($tempstyle, 'U') !== false) {
03151                 $this->underline = true;
03152             } else {
03153                 $this->underline = false;
03154             }
03155             
03156             if (strpos($tempstyle, 'D') !== false) {
03157                 $this->linethrough = true;
03158             } else {
03159                 $this->linethrough = false;
03160             }
03161             
03162             if (strpos($tempstyle, 'B') !== false) {
03163                 $style .= 'B';
03164             }
03165             
03166             if (strpos($tempstyle, 'I') !== false) {
03167                 $style .= 'I';
03168             }
03169             $bistyle = $style;
03170             $fontkey = $family.$style;
03171             $font_style = $style.($this->underline ? 'U' : '').($this->linethrough ? 'D' : '');
03172             $fontdata = array('fontkey' => $fontkey, 'family' => $family, 'style' => $font_style);
03173             
03174             if ($this->getFontBuffer($fontkey) !== false) {
03175                 return $fontdata;
03176             }
03177             if (isset($type)) {
03178                 unset($type); 
03179             }
03180             if (isset($cw)) {
03181                 unset($cw); 
03182             }
03183             
03184             $fontdir = '';
03185             if (!$this->empty_string($fontfile)) {
03186                 $fontdir = dirname($fontfile);
03187                 if ($this->empty_string($fontdir) OR ($fontdir == '.')) {
03188                     $fontdir = '';
03189                 } else {
03190                     $fontdir .= '/';
03191                 }
03192             }
03193             
03194             if ($this->empty_string($fontfile) OR (!file_exists($fontfile))) {
03195                 
03196                 $fontfile1 = str_replace(' ', '', $family).strtolower($style).'.php';
03197                 $fontfile2 = str_replace(' ', '', $family).'.php';
03198                 
03199                 if (file_exists($fontdir.$fontfile1)) {
03200                     $fontfile = $fontdir.$fontfile1;
03201                 } elseif (file_exists($this->_getfontpath().$fontfile1)) {
03202                     $fontfile = $this->_getfontpath().$fontfile1;
03203                 } elseif (file_exists($fontfile1)) {
03204                     $fontfile = $fontfile1;
03205                 } elseif (file_exists($fontdir.$fontfile2)) {
03206                     $fontfile = $fontdir.$fontfile2;
03207                 } elseif (file_exists($this->_getfontpath().$fontfile2)) {
03208                     $fontfile = $this->_getfontpath().$fontfile2;
03209                 } else {
03210                     $fontfile = $fontfile2;
03211                 }
03212             }
03213             
03214             if (file_exists($fontfile)) {
03215                 include($fontfile);
03216             } else {
03217                 $this->Error('Could not include font definition file: '.$family.'');
03218             }
03219             
03220             if ((!isset($type)) OR (!isset($cw))) {
03221                 $this->Error('The font definition file has a bad format: '.$fontfile.'');
03222             }
03223             
03224             if (!isset($file) OR $this->empty_string($file)) {
03225                 $file = '';
03226             }
03227             if (!isset($enc) OR $this->empty_string($enc)) {
03228                 $enc = '';
03229             }
03230             if (!isset($cidinfo) OR $this->empty_string($cidinfo)) {
03231                 $cidinfo = array('Registry'=>'Adobe','Ordering'=>'Identity','Supplement'=>0);
03232                 $cidinfo['uni2cid'] = array();
03233             }
03234             if (!isset($ctg) OR $this->empty_string($ctg)) {
03235                 $ctg = '';
03236             }
03237             if (!isset($desc) OR $this->empty_string($desc)) {
03238                 $desc = array();
03239             }
03240             if (!isset($up) OR $this->empty_string($up)) {
03241                 $up = -100;
03242             }
03243             if (!isset($ut) OR $this->empty_string($ut)) {
03244                 $ut = 50;
03245             }
03246             if (!isset($cw) OR $this->empty_string($cw)) {
03247                 $cw = array();
03248             }
03249             if (!isset($dw) OR $this->empty_string($dw)) {
03250                 
03251                 if (isset($desc['MissingWidth']) AND ($desc['MissingWidth'] > 0)) {
03252                     $dw = $desc['MissingWidth'];
03253                 } elseif (isset($cw[32])) {
03254                     $dw = $cw[32];
03255                 } else {
03256                     $dw = 600;
03257                 }
03258             }
03259             ++$this->numfonts;          
03260             if ($type == 'cidfont0') {
03261                 
03262                 $styles = array('' => '', 'B' => ',Bold', 'I' => ',Italic', 'BI' => ',BoldItalic');
03263                 $sname = $name.$styles[$bistyle];
03264                 if ((strpos($bistyle, 'B') !== false) AND (isset($desc['StemV'])) AND ($desc['StemV'] == 70)) {
03265                     $desc['StemV'] = 120;
03266                 }
03267             } elseif ($type == 'core') {
03268                 $name = $this->CoreFonts[$fontkey];
03269             } elseif (($type == 'TrueType') OR ($type == 'Type1')) {
03270                 
03271             } elseif ($type == 'TrueTypeUnicode') {
03272                 $enc = 'Identity-H';
03273             } else {
03274                 $this->Error('Unknow font type: '.$type.'');
03275             }
03276             $this->setFontBuffer($fontkey, array('i' => $this->numfonts, 'type' => $type, 'name' => $name, 'desc' => $desc, 'up' => $up, 'ut' => $ut, 'cw' => $cw, 'dw' => $dw, 'enc' => $enc, 'cidinfo' => $cidinfo, 'file' => $file, 'ctg' => $ctg));
03277             if (isset($diff) AND (!empty($diff))) {
03278                 
03279                 $d = 0;
03280                 $nb = count($this->diffs);
03281                 for ($i=1; $i <= $nb; ++$i) {
03282                     if ($this->diffs[$i] == $diff) {
03283                         $d = $i;
03284                         break;
03285                     }
03286                 }
03287                 if ($d == 0) {
03288                     $d = $nb + 1;
03289                     $this->diffs[$d] = $diff;
03290                 }
03291                 $this->setFontSubBuffer($fontkey, 'diff', $d);
03292             }
03293             if (!$this->empty_string($file)) {
03294                 if ((strcasecmp($type,'TrueType') == 0) OR (strcasecmp($type, 'TrueTypeUnicode') == 0)) {
03295                     $this->FontFiles[$file] = array('length1' => $originalsize, 'fontdir' => $fontdir);
03296                 } elseif ($type != 'core') {
03297                     $this->FontFiles[$file] = array('length1' => $size1, 'length2' => $size2, 'fontdir' => $fontdir);
03298                 }
03299             }
03300             return $fontdata;
03301         }
03302 
03317         public function SetFont($family, $style='', $size=0, $fontfile='') {
03318             
03319             if ($size == 0) {
03320                 $size = $this->FontSizePt;
03321             }
03322             
03323             $fontdata = $this->AddFont($family, $style, $fontfile);
03324             $this->FontFamily = $fontdata['family'];
03325             $this->FontStyle = $fontdata['style'];
03326             $this->CurrentFont = $this->getFontBuffer($fontdata['fontkey']);
03327             $this->SetFontSize($size);
03328         }
03329 
03337         public function SetFontSize($size) {
03338             
03339             $this->FontSizePt = $size;
03340             $this->FontSize = $size / $this->k;
03341             if (isset($this->CurrentFont['desc']['Ascent']) AND ($this->CurrentFont['desc']['Ascent'] > 0)) {
03342                 $this->FontAscent = $this->CurrentFont['desc']['Ascent'] * $this->FontSize / 1000;
03343             } else {
03344                 $this->FontAscent = 0.8 * $this->FontSize;
03345             }
03346             if (isset($this->CurrentFont['desc']['Descent']) AND ($this->CurrentFont['desc']['Descent'] > 0)) {
03347                 $this->FontDescent = - $this->CurrentFont['desc']['Descent'] * $this->FontSize / 1000;
03348             } else {
03349                 $this->FontDescent = 0.2 * $this->FontSize;
03350             }
03351             if (($this->page > 0) AND (isset($this->CurrentFont['i']))) {
03352                 $this->_out(sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
03353             }
03354         }
03355 
03362         public function SetDefaultMonospacedFont($font) {
03363             $this->default_monospaced_font = $font;
03364         }
03365         
03373         public function AddLink() {
03374             
03375             $n = count($this->links) + 1;
03376             $this->links[$n] = array(0, 0);
03377             return $n;
03378         }
03379 
03389         public function SetLink($link, $y=0, $page=-1) {
03390             if ($y == -1) {
03391                 $y = $this->y;
03392             }
03393             if ($page == -1) {
03394                 $page = $this->page;
03395             }
03396             $this->links[$link] = array($page, $y);
03397         }
03398 
03412         public function Link($x, $y, $w, $h, $link, $spaces=0) {
03413             $this->Annotation($x, $y, $w, $h, $link, array('Subtype'=>'Link'), $spaces);
03414         }
03415         
03429         public function Annotation($x='', $y='', $w, $h, $text, $opt=array('Subtype'=>'Text'), $spaces=0) {
03430             if ($x === '') {
03431                 $x = $this->x;
03432             }
03433             if ($y === '') {
03434                 $y = $this->y;
03435             }
03436             
03437             if (isset($this->transfmatrix)) {
03438                 for ($i=$this->transfmatrix_key; $i > 0; --$i) {
03439                     $maxid = count($this->transfmatrix[$i]) - 1;
03440                     for ($j=$maxid; $j >= 0; --$j) {
03441                         $ctm = $this->transfmatrix[$i][$j];
03442                         if (isset($ctm['a'])) {
03443                             $x = $x * $this->k;
03444                             $y = ($this->h - $y) * $this->k;
03445                             $w = $w * $this->k;
03446                             $h = $h * $this->k;
03447                             
03448                             $xt = $x;
03449                             $yt = $y;
03450                             $x1 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
03451                             $y1 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
03452                             
03453                             $xt = $x + $w;
03454                             $yt = $y;
03455                             $x2 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
03456                             $y2 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
03457                             
03458                             $xt = $x;
03459                             $yt = $y - $h;
03460                             $x3 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
03461                             $y3 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
03462                             
03463                             $xt = $x + $w;
03464                             $yt = $y - $h;
03465                             $x4 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
03466                             $y4 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
03467                             
03468                             $x = min($x1, $x2, $x3, $x4);
03469                             $y = max($y1, $y2, $y3, $y4);
03470                             $w = (max($x1, $x2, $x3, $x4) - $x) / $this->k;
03471                             $h = ($y - min($y1, $y2, $y3, $y4)) / $this->k;
03472                             $x = $x / $this->k;
03473                             $y = $this->h - ($y / $this->k);
03474                         }
03475                     }
03476                 }
03477             }
03478             if ($this->page <= 0) {
03479                 $page = 1;
03480             } else {
03481                 $page = $this->page;
03482             }
03483             if (!isset($this->PageAnnots[$page])) {
03484                 $this->PageAnnots[$page] = array();
03485             }
03486             $this->PageAnnots[$page][] = array('x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'txt' => $text, 'opt' => $opt, 'numspaces' => $spaces);
03487             if (($opt['Subtype'] == 'FileAttachment') AND (!$this->empty_string($opt['FS'])) AND file_exists($opt['FS']) AND (!isset($this->embeddedfiles[basename($opt['FS'])]))) {
03488                 $this->embeddedfiles[basename($opt['FS'])] = array('file' => $opt['FS'], 'n' => (count($this->embeddedfiles) + $this->embedded_start_obj_id));
03489             }
03490             
03491             if (isset($opt['mk']['i']) AND file_exists($opt['mk']['i'])) {
03492                 $this->Image($opt['mk']['i'], '', '', 10, 10, '', '', '', false, 300, '', false, false, 0, false, true);
03493             }
03494             if (isset($opt['mk']['ri']) AND file_exists($opt['mk']['ri'])) {
03495                 $this->Image($opt['mk']['ri'], '', '', 0, 0, '', '', '', false, 300, '', false, false, 0, false, true);
03496             }
03497             if (isset($opt['mk']['ix']) AND file_exists($opt['mk']['ix'])) {
03498                 $this->Image($opt['mk']['ix'], '', '', 0, 0, '', '', '', false, 300, '', false, false, 0, false, true);
03499             }
03500             ++$this->annot_obj_id;
03501         }
03502 
03509         protected function _putEmbeddedFiles() {
03510             reset($this->embeddedfiles);
03511             foreach ($this->embeddedfiles as $filename => $filedata) {
03512                 $data = file_get_contents($filedata['file']);
03513                 $filter = '';
03514                 if ($this->compress) {
03515                     $data = gzcompress($data);
03516                     $filter = ' /Filter /FlateDecode';
03517                 }
03518                 $this->offsets[$filedata['n']] = $this->bufferlen;
03519                 $this->_out($filedata['n'].' 0 obj');
03520                 $this->_out('<</Type /EmbeddedFile'.$filter.' /Length '.strlen($data).' >>');
03521                 $this->_putstream($data);
03522                 $this->_out('endobj');
03523             }
03524         }
03525         
03540         public function Text($x, $y, $txt, $stroke=0, $clip=false) {
03541             
03542             if ($this->rtl) {
03543                 
03544                 $s = $this->utf8Bidi($this->UTF8StringToArray($txt), $txt, $this->tmprtl);
03545                 $l = $this->GetArrStringWidth($s);
03546                 $xr = $this->w - $x - $this->GetArrStringWidth($s);
03547             } else {
03548                 $xr = $x;
03549             }
03550             $opt = '';
03551             if (($stroke > 0) AND (!$clip)) {
03552                 $opt .= '1 Tr '.intval($stroke).' w ';
03553             } elseif (($stroke > 0) AND $clip) {
03554                 $opt .= '5 Tr '.intval($stroke).' w ';
03555             } elseif ($clip) {
03556                 $opt .= '7 Tr ';
03557             }
03558             $s = sprintf('BT %.2F %.2F Td %s(%s) Tj ET 0 Tr', $xr * $this->k, ($this->h-$y) * $this->k, $opt, $this->_escapetext($txt));
03559             if ($this->underline AND ($txt!='')) {
03560                 $s .= ' '.$this->_dounderline($xr, $y, $txt);
03561             }
03562             if ($this->linethrough AND ($txt!='')) { 
03563                 $s .= ' '.$this->_dolinethrough($xr, $y, $txt); 
03564             }
03565             if ($this->ColorFlag AND (!$clip)) {
03566                 $s='q '.$this->TextColor.' '.$s.' Q';
03567             }
03568             $this->_out($s);
03569         }
03570 
03580         public function AcceptPageBreak() {
03581             return $this->AutoPageBreak;
03582         }
03583         
03593         protected function checkPageBreak($h=0, $y='', $addpage=true) {
03594             if ($this->empty_string($y)) {
03595                 $y = $this->y;
03596             }
03597             if ((($y + $h) > $this->PageBreakTrigger) AND (!$this->InFooter) AND ($this->AcceptPageBreak())) {
03598                 if ($addpage) {
03599                     
03600                     $x = $this->x;
03601                     $this->AddPage($this->CurOrientation);
03602                     $this->y = $this->tMargin;
03603                     $oldpage = $this->page - 1;
03604                     if ($this->rtl) {
03605                         if ($this->pagedim[$this->page]['orm'] != $this->pagedim[$oldpage]['orm']) {
03606                             $this->x = $x - ($this->pagedim[$this->page]['orm'] - $this->pagedim[$oldpage]['orm']);
03607                         } else {
03608                             $this->x = $x;
03609                         }
03610                     } else {
03611                         if ($this->pagedim[$this->page]['olm'] != $this->pagedim[$oldpage]['olm']) {
03612                             $this->x = $x + ($this->pagedim[$this->page]['olm'] - $this->pagedim[$oldpage]['olm']);
03613                         } else {
03614                             $this->x = $x;
03615                         }
03616                     }
03617                 }
03618                 return true;
03619             }
03620             return false;
03621         }
03622 
03641         public function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=0, $link='', $stretch=0, $ignore_min_height=false) {
03642             
03643             $min_cell_height = $this->FontSize * $this->cell_height_ratio;
03644             if ($h < $min_cell_height) {
03645                 $h = $min_cell_height;
03646             }
03647             $this->checkPageBreak($h);
03648             $this->_out($this->getCellCode($w, $h, $txt, $border, $ln, $align, $fill, $link, $stretch, $ignore_min_height));
03649         }
03650 
03658         public function removeSHY($txt='') {
03659             
03660 
03661 
03662 
03663 
03664 
03665 
03666 
03667 
03668 
03669             $txt = preg_replace('/([\\xc2]{1}[\\xad]{1})/', '', $txt);
03670             if (!$this->isunicode) {
03671                 $txt = preg_replace('/([\\xad]{1})/', '', $txt);
03672             }
03673             return $txt;
03674         }
03675         
03693         protected function getCellCode($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=0, $link='', $stretch=0, $ignore_min_height=false) {
03694             $txt = $this->removeSHY($txt);
03695             $rs = ''; 
03696             if (!$ignore_min_height) {
03697                 $min_cell_height = $this->FontSize * $this->cell_height_ratio;
03698                 if ($h < $min_cell_height) {
03699                     $h = $min_cell_height;
03700                 }
03701             }
03702             $k = $this->k;
03703             if ($this->empty_string($w) OR ($w <= 0)) {
03704                 if ($this->rtl) {
03705                     $w = $this->x - $this->lMargin;
03706                 } else {
03707                     $w = $this->w - $this->rMargin - $this->x;
03708                 }
03709             }
03710             $s = '';            
03711             if (($fill == 1) OR ($border == 1)) {
03712                 if ($fill == 1) {
03713                     $op = ($border == 1) ? 'B' : 'f';
03714                 } else {
03715                     $op = 'S';
03716                 }
03717                 if ($this->rtl) {
03718                     $xk = (($this->x  - $w) * $k);
03719                 } else {
03720                     $xk = ($this->x * $k);
03721                 }
03722                 $s .= sprintf('%.2F %.2F %.2F %.2F re %s ', $xk, (($this->h - $this->y) * $k), ($w * $k), (-$h * $k), $op);
03723             }
03724             if (is_string($border)) {
03725                 $lm = ($this->LineWidth / 2);
03726                 $x = $this->x;
03727                 $y = $this->y;
03728                 if (strpos($border,'L') !== false) {
03729                     if ($this->rtl) {
03730                         $xk = ($x - $w) * $k;
03731                     } else {
03732                         $xk = $x * $k;
03733                     }
03734                     $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $xk, (($this->h - $y + $lm) * $k), $xk, (($this->h - ($y + $h + $lm)) * $k));
03735                 }
03736                 if (strpos($border,'T') !== false) {
03737                     if ($this->rtl) {
03738                         $xk = ($x - $w + $lm) * $k;
03739                         $xwk = ($x - $lm) * $k;
03740                     } else {
03741                         $xk = ($x - $lm) * $k;
03742                         $xwk = ($x + $w + $lm) * $k;
03743                     }
03744                     $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $xk, (($this->h - $y) * $k), $xwk, (($this->h - $y) * $k));
03745                 }
03746                 if (strpos($border,'R') !== false) {
03747                     if ($this->rtl) {
03748                         $xk = $x * $k;
03749                     } else {
03750                         $xk = ($x + $w) * $k;
03751                     }
03752                     $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $xk, (($this->h - $y + $lm) * $k), $xk, (($this->h - ($y + $h + $lm))* $k));
03753                 }
03754                 if (strpos($border,'B') !== false) {
03755                     if ($this->rtl) {
03756                         $xk = ($x - $w + $lm) * $k;
03757                         $xwk = ($x - $lm) * $k;
03758                     } else {
03759                         $xk = ($x - $lm) * $k;
03760                         $xwk = ($x + $w + $lm) * $k;
03761                     }
03762                     $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $xk, (($this->h - ($y + $h)) * $k), $xwk, (($this->h - ($y + $h)) * $k));
03763                 }
03764             }
03765             if ($txt != '') {
03766                 
03767                 $width = $this->GetStringWidth($txt);
03768                 
03769                 if ($width <= 0) {
03770                     $ratio = 1;
03771                 } else {
03772                     $ratio = ($w - (2 * $this->cMargin)) / $width;
03773                 }
03774                 
03775                 if (($stretch > 0) AND (($ratio < 1) OR (($ratio > 1) AND (($stretch % 2) == 0)))) {
03776                     if ($stretch > 2) {
03777                         
03778                         
03779                         $char_space = (($w - $width - (2 * $this->cMargin)) * $this->k) / max($this->GetNumChars($txt)-1,1);
03780                         
03781                         $rs .= sprintf('BT %.2F Tc ET ', $char_space);
03782                     } else {
03783                         
03784                         
03785                         $horiz_scale = $ratio * 100.0;
03786                         
03787                         $rs .= sprintf('BT %.2F Tz ET ', $horiz_scale);
03788                     }
03789                     $align = '';
03790                     $width = $w - (2 * $this->cMargin);
03791                 } else {
03792                     $stretch == 0;
03793                 }
03794                 if ($align == 'L') {
03795                     if ($this->rtl) {
03796                         $dx = $w - $width - $this->cMargin;
03797                     } else {
03798                         $dx = $this->cMargin;
03799                     }
03800                 } elseif ($align == 'R') {
03801                     if ($this->rtl) {
03802                         $dx = $this->cMargin;
03803                     } else {
03804                         $dx = $w - $width - $this->cMargin;
03805                     }
03806                 } elseif ($align == 'C') {
03807                     $dx = ($w - $width) / 2;
03808                 } elseif ($align == 'J') {
03809                     if ($this->rtl) {
03810                         $dx = $w - $width - $this->cMargin;
03811                     } else {
03812                         $dx = $this->cMargin;
03813                     }
03814                 } else {
03815                     $dx = $this->cMargin;
03816                 }
03817                 if ($this->ColorFlag) {
03818                     $s .= 'q '.$this->TextColor.' ';
03819                 }
03820                 $txt2 = $this->_escapetext($txt);
03821                 if ($this->rtl) {
03822                     $xdk = ($this->x - $dx - $width) * $k;
03823                 } else {
03824                     $xdk = ($this->x + $dx) * $k;
03825                 }
03826                 
03827                 if ($align == 'J') {
03828                     
03829                     $ns = substr_count($txt, ' ');
03830                     if (($this->CurrentFont['type'] == 'TrueTypeUnicode') OR ($this->CurrentFont['type'] == 'cidfont0')) {
03831                         
03832                         $width = $this->GetStringWidth(str_replace(' ', '', $txt));
03833                         
03834                         $spacewidth = -1000 * ($w - $width - (2 * $this->cMargin)) / ($ns?$ns:1) / $this->FontSize;
03835                         
03836                         $txt2 = str_replace(chr(0).' ', ') '.($spacewidth).' (', $txt2);
03837                     } else {
03838                         
03839                         $width = $this->GetStringWidth($txt);
03840                         $spacewidth = (($w - $width - (2 * $this->cMargin)) / ($ns?$ns:1)) * $this->k;
03841                         $rs .= sprintf('BT %.3F Tw ET ', $spacewidth);
03842                     }
03843                 }
03844                 
03845                 
03846                 $basefonty = $this->y + ($h/2) + ($this->FontSize/3);
03847                 
03848                 $s .= sprintf('BT %.2F %.2F Td [(%s)] TJ ET', $xdk, (($this->h - $basefonty) * $k), $txt2);
03849                 if ($this->rtl) {
03850                     $xdx = $this->x - $dx - $width;
03851                 } else {
03852                     $xdx = $this->x + $dx;
03853                 }
03854                 if ($this->underline)  {
03855                     $s .= ' '.$this->_dounderline($xdx, $basefonty, $txt);
03856                 }
03857                 if ($this->linethrough) { 
03858                     $s .= ' '.$this->_dolinethrough($xdx, $basefonty, $txt);
03859                 }
03860                 if ($this->ColorFlag) {
03861                     $s .= ' Q';
03862                 }
03863                 if ($link) {
03864                     $this->Link($xdx, $this->y + (($h - $this->FontSize)/2), $width, $this->FontSize, $link, substr_count($txt, chr(32)));
03865                 }
03866             }
03867             
03868             if ($s) {
03869                 
03870                 $rs .= $s;
03871                 
03872                 if ($stretch > 2) {
03873                     
03874                     $rs .= ' BT 0 Tc ET';
03875                 } elseif ($stretch > 0) {
03876                     
03877                     $rs .= ' BT 100 Tz ET';
03878                 }
03879             }
03880             
03881             if (!(($this->CurrentFont['type'] == 'TrueTypeUnicode') OR ($this->CurrentFont['type'] == 'cidfont0')) AND ($align == 'J')) {
03882                 $rs .= ' BT 0 Tw ET';
03883             }
03884             $this->lasth = $h;
03885             if ($ln > 0) {
03886                 
03887                 $this->y += $h;
03888                 if ($ln == 1) {
03889                     if ($this->rtl) {
03890                         $this->x = $this->w - $this->rMargin;
03891                     } else {
03892                         $this->x = $this->lMargin;
03893                     }
03894                 }
03895             } else {
03896                 
03897                 if ($this->rtl) {
03898                     $this->x -= $w;
03899                 } else {
03900                     $this->x += $w;
03901                 }
03902             }
03903             $gstyles = ''.$this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor.' '.$this->FillColor."\n";
03904             $rs = $gstyles.$rs;
03905             return $rs;
03906         }
03907 
03931         public function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=0, $ln=1, $x='', $y='', $reseth=true, $stretch=0, $ishtml=false, $autopadding=true, $maxh=0) { 
03932             if ($this->empty_string($this->lasth) OR $reseth) {
03933                 
03934                 $this->lasth = $this->FontSize * $this->cell_height_ratio;
03935             }
03936             if (!$this->empty_string($y)) {
03937                 $this->SetY($y);
03938             } else {
03939                 $y = $this->GetY();
03940             }
03941             
03942             $this->checkPageBreak($h);
03943             $y = $this->GetY();
03944             
03945             $startpage = $this->page;
03946             if (!$this->empty_string($x)) {
03947                 $this->SetX($x);
03948             } else {
03949                 $x = $this->GetX();
03950             }
03951             if ($this->empty_string($w) OR ($w <= 0)) {
03952                 if ($this->rtl) {
03953                     $w = $this->x - $this->lMargin;
03954                 } else {
03955                     $w = $this->w - $this->rMargin - $this->x;
03956                 }
03957             }
03958             
03959             $lMargin = $this->lMargin;
03960             $rMargin = $this->rMargin;
03961             if ($this->rtl) {
03962                 $this->SetRightMargin($this->w - $this->x);
03963                 $this->SetLeftMargin($this->x - $w);
03964             } else {
03965                 $this->SetLeftMargin($this->x);
03966                 $this->SetRightMargin($this->w - $this->x - $w);
03967             }
03968             $starty = $this->y;
03969             if ($autopadding) {
03970                 
03971                 if ($this->cMargin < ($this->LineWidth / 2)) {
03972                     $this->cMargin = ($this->LineWidth / 2);
03973                 }
03974                 
03975                 if (($this->lasth - $this->FontSize) < $this->LineWidth) {
03976                     $this->y += $this->LineWidth / 2;
03977                 }
03978                 
03979                 $this->y += $this->cMargin;
03980             }
03981             if ($ishtml) {
03982                 
03983                 $this->writeHTML($txt, true, 0, $reseth, true, $align);
03984                 $nl = 1;
03985             } else {
03986                 
03987                 $nl = $this->Write($this->lasth, $txt, '', 0, $align, true, $stretch, false, false, $maxh);
03988             }
03989             if ($autopadding) {
03990                 
03991                 $this->y += $this->cMargin;
03992                 
03993                 if (($this->lasth - $this->FontSize) < $this->LineWidth) {
03994                     $this->y += $this->LineWidth / 2;
03995                 }
03996             }
03997             
03998             $currentY = $this->y;
03999             
04000             $endpage = $this->page;
04001             
04002             if ($endpage > $startpage) {
04003                 
04004                 for ($page=$startpage; $page <= $endpage; ++$page) {
04005                     $this->setPage($page);
04006                     if ($page == $startpage) {
04007                         $this->y = $starty; 
04008                         $h = $this->getPageHeight() - $starty - $this->getBreakMargin();
04009                         $cborder = $this->getBorderMode($border, $position='start');
04010                     } elseif ($page == $endpage) {
04011                         $this->y = $this->tMargin; 
04012                         $h = $currentY - $this->tMargin;
04013                         $cborder = $this->getBorderMode($border, $position='end');
04014                     } else {
04015                         $this->y = $this->tMargin; 
04016                         $h = $this->getPageHeight() - $this->tMargin - $this->getBreakMargin();
04017                         $cborder = $this->getBorderMode($border, $position='middle');
04018                     }
04019                     $nx = $x;
04020                     
04021                     if ($page > $startpage) {
04022                         if (($this->rtl) AND ($this->pagedim[$page]['orm'] != $this->pagedim[$startpage]['orm'])) {
04023                             $nx = $x + ($this->pagedim[$page]['orm'] - $this->pagedim[$startpage]['orm']);
04024                         } elseif ((!$this->rtl) AND ($this->pagedim[$page]['olm'] != $this->pagedim[$startpage]['olm'])) {
04025                             $nx = $x + ($this->pagedim[$page]['olm'] - $this->pagedim[$startpage]['olm']);
04026                         }
04027                     }
04028                     $this->SetX($nx);
04029                     $ccode = $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, false);
04030                     if ($cborder OR $fill) {
04031                         $pagebuff = $this->getPageBuffer($this->page);
04032                         $pstart = substr($pagebuff, 0, $this->intmrk[$this->page]);
04033                         $pend = substr($pagebuff, $this->intmrk[$this->page]);
04034                         $this->setPageBuffer($this->page, $pstart.$ccode."\n".$pend);
04035                         $this->intmrk[$this->page] += strlen($ccode."\n");
04036                     }
04037                 }
04038             } else {
04039                 $h = max($h, ($currentY - $y));
04040                 
04041                 $this->SetY($y); 
04042                 $this->SetX($x);
04043                 
04044                 $ccode = $this->getCellCode($w, $h, '', $border, 1, '', $fill, '', 0, true);
04045                 if ($border OR $fill) {
04046                     if (end($this->transfmrk[$this->page]) !== false) {
04047                         $pagemarkkey = key($this->transfmrk[$this->page]);
04048                         $pagemark = &$this->transfmrk[$this->page][$pagemarkkey];
04049                     } elseif ($this->InFooter) {
04050                         $pagemark = &$this->footerpos[$this->page];
04051                     } else {
04052                         $pagemark = &$this->intmrk[$this->page];
04053                     }
04054                     $pagebuff = $this->getPageBuffer($this->page);
04055                     $pstart = substr($pagebuff, 0, $pagemark);
04056                     $pend = substr($pagebuff, $pagemark);
04057                     $this->setPageBuffer($this->page, $pstart.$ccode."\n".$pend);
04058                     $pagemark += strlen($ccode."\n");
04059                 }
04060             }
04061             
04062             $currentY = $this->GetY();
04063             
04064             $this->SetLeftMargin($lMargin);
04065             $this->SetRightMargin($rMargin);
04066             if ($ln > 0) {
04067                 
04068                 $this->SetY($currentY);
04069                 if ($ln == 2) {
04070                     $this->SetX($x + $w);
04071                 }
04072             } else {
04073                 
04074                 $this->setPage($startpage);
04075                 $this->y = $y;
04076                 $this->SetX($x + $w);
04077             }
04078             $this->setContentMark();
04079             return $nl;
04080         }
04081 
04090         protected function getBorderMode($border, $position='start') {
04091             if ((!$this->opencell) AND ($border == 1)) {
04092                 return 1;
04093             }
04094             $cborder = '';
04095             switch ($position) {
04096                 case 'start': {
04097                     if ($border == 1) {
04098                         $cborder = 'LTR';
04099                     } else {
04100                         if (!(false === strpos($border, 'L'))) {
04101                             $cborder .= 'L';
04102                         }
04103                         if (!(false === strpos($border, 'T'))) {
04104                             $cborder .= 'T';
04105                         }
04106                         if (!(false === strpos($border, 'R'))) {
04107                             $cborder .= 'R';
04108                         }
04109                         if ((!$this->opencell) AND (!(false === strpos($border, 'B')))) {
04110                             $cborder .= 'B';
04111                         }
04112                     }
04113                     break;
04114                 }
04115                 case 'middle': {
04116                     if ($border == 1) {
04117                         $cborder = 'LR';
04118                     } else {
04119                         if (!(false === strpos($border, 'L'))) {
04120                             $cborder .= 'L';
04121                         }
04122                         if ((!$this->opencell) AND (!(false === strpos($border, 'T')))) {
04123                             $cborder .= 'T';
04124                         }
04125                         if (!(false === strpos($border, 'R'))) {
04126                             $cborder .= 'R';
04127                         }
04128                         if ((!$this->opencell) AND (!(false === strpos($border, 'B')))) {
04129                             $cborder .= 'B';
04130                         }
04131                     }
04132                     break;
04133                 }
04134                 case 'end': {
04135                     if ($border == 1) {
04136                         $cborder = 'LRB';
04137                     } else {
04138                         if (!(false === strpos($border, 'L'))) {
04139                             $cborder .= 'L';
04140                         }
04141                         if ((!$this->opencell) AND (!(false === strpos($border, 'T')))) {
04142                             $cborder .= 'T';
04143                         }
04144                         if (!(false === strpos($border, 'R'))) {
04145                             $cborder .= 'R';
04146                         }
04147                         if (!(false === strpos($border, 'B'))) {
04148                             $cborder .= 'B';
04149                         }
04150                     }
04151                     break;
04152                 }
04153                 default: {
04154                     $cborder = $border;
04155                     break;
04156                 }
04157             }
04158             return $cborder;
04159         }
04160 
04169         public function getNumLines($txt, $w=0) {
04170             $lines = 0;
04171             if ($this->empty_string($w) OR ($w <= 0)) {
04172                 if ($this->rtl) {
04173                     $w = $this->x - $this->lMargin;
04174                 } else {
04175                     $w = $this->w - $this->rMargin - $this->x;
04176                 }
04177             }
04178             
04179             $wmax = $w - (2 * $this->cMargin);
04180             
04181             $txt = str_replace("\r", '', $txt);
04182             
04183             if (substr($txt,-1) == "\n") {
04184                 $txt = substr($txt, 0, -1);
04185             }
04186             
04187             $txtblocks = explode("\n", $txt);
04188             
04189             foreach ($txtblocks as $block) {
04190                 
04191                 $lines += $this->empty_string($block) ? 1 : (ceil($this->GetStringWidth($block) / $wmax));
04192             }
04193             return $lines;
04194         }
04195             
04212         public function Write($h, $txt, $link='', $fill=0, $align='', $ln=false, $stretch=0, $firstline=false, $firstblock=false, $maxh=0) {
04213             if (strlen($txt) == 0) {
04214                 $txt = ' ';
04215             }
04216             
04217             $s = str_replace("\r", '', $txt);
04218             
04219             if (preg_match(K_RE_PATTERN_ARABIC, $s)) {
04220                 $arabic = true;
04221             } else {
04222                 $arabic = false;
04223             }
04224             
04225             if ($arabic OR $this->tmprtl OR preg_match(K_RE_PATTERN_RTL, $txt)) {
04226                 $rtlmode = true;
04227             } else {
04228                 $rtlmode = false;
04229             }
04230             
04231             $chrwidth = $this->GetCharWidth('.');
04232             
04233             $chars = $this->UTF8StringToArray($s);
04234             
04235             $uchars = $this->UTF8ArrayToUniArray($chars);
04236             
04237             $nb = count($chars);
04238             
04239             $shy_replacement = 45;
04240             $shy_replacement_char = $this->unichr($shy_replacement);
04241             
04242             $shy_replacement_width = $this->GetCharWidth($shy_replacement);
04243             
04244             $prevx = $this->x;
04245             $prevy = $this->y;
04246             
04247             $maxy = $this->y + $maxh - $h - (2 * $this->cMargin);
04248             
04249             if ($this->rtl) {
04250                 $w = $this->x - $this->lMargin;
04251             } else {
04252                 $w = $this->w - $this->rMargin - $this->x;
04253             }
04254             
04255             $wmax = $w - (2 * $this->cMargin);
04256             if ((!$firstline) AND (($chrwidth > $wmax) OR ($this->GetCharWidth($chars[0]) > $wmax))) {
04257                 
04258                 return '';
04259             }
04260             $i = 0; 
04261             $j = 0; 
04262             $sep = -1; 
04263             $shy = false; 
04264             $l = 0; 
04265             $nl = 0; 
04266             $linebreak = false;
04267             
04268             while ($i < $nb) {
04269                 if (($maxh > 0) AND ($this->y >= $maxy) ) {
04270                     $firstline = true;
04271                 }
04272                 
04273                 $c = $chars[$i];
04274                 if ($c == 10) { 
04275                     
04276                     if ($align == 'J') {
04277                         if ($this->rtl) {
04278                             $talign = 'R';
04279                         } else {
04280                             $talign = 'L';
04281                         }
04282                     } else {
04283                         $talign = $align;
04284                     }
04285                     $tmpstr = $this->UniArrSubString($uchars, $j, $i);
04286                     if ($firstline) {
04287                         $startx = $this->x;
04288                         $tmparr = array_slice($chars, $j, $i);
04289                         if ($rtlmode) {
04290                             $tmparr = $this->utf8Bidi($tmparr, $tmpstr, $this->tmprtl);
04291                         }
04292                         $linew = $this->GetArrStringWidth($tmparr);
04293                         unset($tmparr);
04294                         if ($this->rtl) {
04295                             $this->endlinex = $startx - $linew;
04296                         } else {
04297                             $this->endlinex = $startx + $linew;
04298                         }
04299                         $w = $linew;
04300                         $tmpcmargin = $this->cMargin;
04301                         if ($maxh == 0) {
04302                             $this->cMargin = 0;
04303                         }
04304                     }
04305                     $this->Cell($w, $h, $tmpstr, 0, 1, $talign, $fill, $link, $stretch);
04306                     unset($tmpstr);
04307                     if ($firstline) {
04308                         $this->cMargin = $tmpcmargin;
04309                         return ($this->UniArrSubString($uchars, $i));
04310                     }
04311                     ++$nl;
04312                     $j = $i + 1;
04313                     $l = 0;
04314                     $sep = -1;
04315                     $shy = false;
04316                     
04317                     if ((($this->y + $this->lasth) > $this->PageBreakTrigger) AND (!$this->InFooter)) {
04318                         
04319                         $this->AcceptPageBreak();
04320                     }
04321                     $w = $this->getRemainingWidth();
04322                     $wmax = $w - (2 * $this->cMargin);
04323                 } else {
04324                     
04325                     
04326                     
04327                     
04328                     
04329                     if (($c != 160) AND (($c == 173) OR preg_match($this->re_spaces, $this->unichr($c)))) {
04330                         
04331                         $sep = $i;
04332                         
04333                         if ($c == 173) {
04334                             $shy = true;
04335                         } else {
04336                             $shy = false;
04337                         }
04338                     }
04339                     
04340                     if ((($this->CurrentFont['type'] == 'TrueTypeUnicode') OR ($this->CurrentFont['type'] == 'cidfont0')) AND ($arabic)) {
04341                         
04342                         
04343                         $l = $this->GetArrStringWidth($this->utf8Bidi(array_slice($chars, $j, $i-$j+1), '', $this->tmprtl));
04344                     } else {
04345                         $l += $this->GetCharWidth($c);
04346                     }
04347                     if (($l > $wmax) OR ($shy AND (($l + $shy_replacement_width) > $wmax)) ) {
04348                         
04349                         if ($sep == -1) {
04350                             
04351                             if (($this->rtl AND ($this->x <= ($this->w - $this->rMargin - $chrwidth)))
04352                                 OR ((!$this->rtl) AND ($this->x >= ($this->lMargin + $chrwidth)))) {
04353                                 
04354                                 $this->Cell($w, $h, '', 0, 1);
04355                                 $linebreak = true;
04356                                 if ($firstline) {
04357                                     return ($this->UniArrSubString($uchars, $j));
04358                                 }
04359                             } else {
04360                                 
04361                                 $tmpstr = $this->UniArrSubString($uchars, $j, $i);
04362                                 if ($firstline) {
04363                                     $startx = $this->x;
04364                                     $tmparr = array_slice($chars, $j, $i);
04365                                     if ($rtlmode) {
04366                                         $tmparr = $this->utf8Bidi($tmparr, $tmpstr, $this->tmprtl);
04367                                     }
04368                                     $linew = $this->GetArrStringWidth($tmparr);
04369                                     unset($tmparr);
04370                                     if ($this->rtl) {
04371                                         $this->endlinex = $startx - $linew;
04372                                     } else {
04373                                         $this->endlinex = $startx + $linew;
04374                                     }
04375                                     $w = $linew;
04376                                     $tmpcmargin = $this->cMargin;
04377                                     if ($maxh == 0) {
04378                                         $this->cMargin = 0;
04379                                     }
04380                                 }
04381                                 $this->Cell($w, $h, $tmpstr, 0, 1, $align, $fill, $link, $stretch);
04382                                 unset($tmpstr);
04383                                 if ($firstline) {
04384                                     $this->cMargin = $tmpcmargin;
04385                                     return ($this->UniArrSubString($uchars, $i));
04386                                 }
04387                                 $j = $i;
04388                                 --$i;
04389                             }   
04390                         } else {
04391                             
04392                             if ($this->rtl AND (!$firstblock)) {
04393                                 $endspace = 1;
04394                             } else {
04395                                 $endspace = 0;
04396                             }
04397                             if ($shy) {
04398                                 
04399                                 $shy_width = $shy_replacement_width;
04400                                 if ($this->rtl) {
04401                                     $shy_char_left = $shy_replacement_char;
04402                                     $shy_char_right = '';
04403                                 } else {
04404                                     $shy_char_left = '';
04405                                     $shy_char_right = $shy_replacement_char;
04406                                 }
04407                             } else {
04408                                 $shy_width = 0;
04409                                 $shy_char_left = '';
04410                                 $shy_char_right = '';
04411                             }
04412                             $tmpstr = $this->UniArrSubString($uchars, $j, ($sep + $endspace));
04413                             if ($firstline) {
04414                                 $startx = $this->x;
04415                                 $tmparr = array_slice($chars, $j, ($sep + $endspace));
04416                                 if ($rtlmode) {
04417                                     $tmparr = $this->utf8Bidi($tmparr, $tmpstr, $this->tmprtl);
04418                                 }
04419                                 $linew = $this->GetArrStringWidth($tmparr);
04420                                 unset($tmparr);
04421                                 if ($this->rtl) {
04422                                     $this->endlinex = $startx - $linew - $shy_width;
04423                                 } else {
04424                                     $this->endlinex = $startx + $linew + $shy_width;
04425                                 }
04426                                 $w = $linew;
04427                                 $tmpcmargin = $this->cMargin;
04428                                 if ($maxh == 0) {
04429                                     $this->cMargin = 0;
04430                                 }
04431                             }
04432                             
04433                             $this->Cell($w, $h, $shy_char_left.$tmpstr.$shy_char_right, 0, 1, $align, $fill, $link, $stretch);
04434                             unset($tmpstr);
04435                             if ($firstline) {
04436                                 
04437                                 $this->cMargin = $tmpcmargin;
04438                                 return ($this->UniArrSubString($uchars, ($sep + $endspace)));
04439                             }
04440                             $i = $sep;
04441                             $sep = -1;
04442                             $shy = false;
04443                             $j = ($i+1);
04444                         }
04445                         
04446                         if ((($this->y + $this->lasth) > $this->PageBreakTrigger) AND (!$this->InFooter)) {
04447                             
04448                             $this->AcceptPageBreak();
04449                         }
04450                         $w = $this->getRemainingWidth();
04451                         $wmax = $w - (2 * $this->cMargin);
04452                         if ($linebreak) {
04453                             $linebreak = false;
04454                         } else {
04455                             ++$nl;
04456                             $l = 0;
04457                         }
04458                     }
04459                 }
04460                 ++$i;
04461             } 
04462             
04463             if ($l > 0) {
04464                 switch ($align) {
04465                     case 'J':
04466                     case 'C': {
04467                         $w = $w;
04468                         break;
04469                     }
04470                     case 'L': {
04471                         if ($this->rtl) {
04472                             $w = $w;
04473                         } else {
04474                             $w = $l;
04475                         }
04476                         break;
04477                     }
04478                     case 'R': {
04479                         if ($this->rtl) {
04480                             $w = $l;
04481                         } else {
04482                             $w = $w;
04483                         }
04484                         break;
04485                     }
04486                     default: {
04487                         $w = $l;
04488                         break;
04489                     }
04490                 }
04491                 $tmpstr = $this->UniArrSubString($uchars, $j, $nb);
04492                 if ($firstline) {
04493                     $startx = $this->x;
04494                     $tmparr = array_slice($chars, $j, $nb);
04495                     if ($rtlmode) {
04496                         $tmparr = $this->utf8Bidi($tmparr, $tmpstr, $this->tmprtl);
04497                     }
04498                     $linew = $this->GetArrStringWidth($tmparr);
04499                     unset($tmparr);
04500                     if ($this->rtl) {
04501                         $this->endlinex = $startx - $linew;
04502                     } else {
04503                         $this->endlinex = $startx + $linew;
04504                     }
04505                     $w = $linew;
04506                     $tmpcmargin = $this->cMargin;
04507                     if ($maxh == 0) {
04508                         $this->cMargin = 0;
04509                     }
04510                 }
04511                 $this->Cell($w, $h, $tmpstr, 0, $ln, $align, $fill, $link, $stretch);
04512                 unset($tmpstr);
04513                 if ($firstline) {
04514                     $this->cMargin = $tmpcmargin;
04515                     return ($this->UniArrSubString($uchars, $nb));
04516                 }
04517                 ++$nl;
04518             }
04519             if ($firstline) {
04520                 return '';
04521             }
04522             return $nl;
04523         }
04524                 
04530         protected function getRemainingWidth() {
04531             if ($this->rtl) {
04532                 return ($this->x - $this->lMargin);
04533             } else {
04534                 return ($this->w - $this->rMargin - $this->x);
04535             }
04536         }
04537 
04546         public function UTF8ArrSubString($strarr, $start='', $end='') {
04547             if (strlen($start) == 0) {
04548                 $start = 0;
04549             }
04550             if (strlen($end) == 0) {
04551                 $end = count($strarr);
04552             }
04553             $string = '';
04554             for ($i=$start; $i < $end; ++$i) {
04555                 $string .= $this->unichr($strarr[$i]);
04556             }
04557             return $string;
04558         }
04559 
04569         public function UniArrSubString($uniarr, $start='', $end='') {
04570             if (strlen($start) == 0) {
04571                 $start = 0;
04572             }
04573             if (strlen($end) == 0) {
04574                 $end = count($uniarr);
04575             }
04576             $string = '';
04577             for ($i=$start; $i < $end; ++$i) {
04578                 $string .= $uniarr[$i];
04579             }
04580             return $string;
04581         }
04582 
04590         public function UTF8ArrayToUniArray($ta) {
04591             return array_map(array($this, 'unichr'), $ta);
04592         }
04593         
04602         public function unichr($c) {
04603             if (!$this->isunicode) {
04604                 return chr($c);
04605             } elseif ($c <= 0x7F) {
04606                 
04607                 return chr($c);
04608             } elseif ($c <= 0x7FF) {
04609                 
04610                 return chr(0xC0 | $c >> 6).chr(0x80 | $c & 0x3F);
04611             } elseif ($c <= 0xFFFF) {
04612                 
04613                 return chr(0xE0 | $c >> 12).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F);
04614             } elseif ($c <= 0x10FFFF) {
04615                 
04616                 return chr(0xF0 | $c >> 18).chr(0x80 | $c >> 12 & 0x3F).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F);
04617             } else {
04618                 return '';
04619             }
04620         }
04621         
04653         public function Image($file, $x='', $y='', $w=0, $h=0, $type='', $link='', $align='', $resize=false, $dpi=300, $palign='', $ismask=false, $imgmask=false, $border=0, $fitbox=false, $hidden=false) {
04654             if ($x === '') {
04655                 $x = $this->x;
04656             }
04657             if ($y === '') {
04658                 $y = $this->y;
04659             }
04660             
04661             $imsize = @getimagesize($file);
04662             if ($imsize === FALSE) {
04663                 
04664                 $file = str_replace(' ', '%20', $file);
04665                 $imsize = @getimagesize($file);
04666                 if ($imsize === FALSE) {
04667                     $this->Error('[Image] No such file or directory in '.$file);
04668                 }
04669             }
04670             
04671             list($pixw, $pixh) = $imsize;
04672             
04673             if (($w <= 0) AND ($h <= 0)) {
04674                 
04675                 $w = $this->pixelsToUnits($pixw);
04676                 $h = $this->pixelsToUnits($pixh);
04677             } elseif ($w <= 0) {
04678                 $w = $h * $pixw / $pixh;
04679             } elseif ($h <= 0) {
04680                 $h = $w * $pixh / $pixw;
04681             } elseif ($fitbox AND ($w > 0) AND ($h > 0)) {
04682                 
04683                 if ((($w * $pixh) / ($h * $pixw)) < 1) {
04684                     $h = $w * $pixh / $pixw;
04685                 } else {
04686                     $w = $h * $pixw / $pixh;
04687                 }
04688             }
04689             
04690             $neww = round($w * $this->k * $dpi / $this->dpi);
04691             $newh = round($h * $this->k * $dpi / $this->dpi);
04692             
04693             if (($neww * $newh) >= ($pixw * $pixh)) {
04694                 $resize = false;
04695             }
04696             
04697             if (!in_array($file, $this->imagekeys)) {
04698                 
04699                 if ($type == '') {
04700                     $fileinfo = pathinfo($file);
04701                     if (isset($fileinfo['extension']) AND (!$this->empty_string($fileinfo['extension']))) {
04702                         $type = $fileinfo['extension'];
04703                     } else {
04704                         $this->Error('Image file has no extension and no type was specified: '.$file);
04705                     }
04706                 }
04707                 $type = strtolower($type);
04708                 if ($type == 'jpg') {
04709                     $type = 'jpeg';
04710                 }
04711                 $mqr = $this->get_mqr();
04712                 $this->set_mqr(false);
04713                 
04714                 $mtd = '_parse'.$type;
04715                 
04716                 $gdfunction = 'imagecreatefrom'.$type;
04717                 $info = false;
04718                 if ((method_exists($this, $mtd)) AND (!($resize AND function_exists($gdfunction)))) {
04719                     
04720                     $info = $this->$mtd($file);
04721                     if ($info == 'pngalpha') {
04722                         return $this->ImagePngAlpha($file, $x, $y, $w, $h, 'PNG', $link, $align, $resize, $dpi, $palign);
04723                     }
04724                 } 
04725                 if (!$info) {
04726                     if (function_exists($gdfunction)) {
04727                         
04728                         $img = $gdfunction($file);
04729                         if ($resize) {
04730                             $imgr = imagecreatetruecolor($neww, $newh);
04731                             imagecopyresampled($imgr, $img, 0, 0, 0, 0, $neww, $newh, $pixw, $pixh); 
04732                             $info = $this->_toJPEG($imgr);
04733                         } else {
04734                             $info = $this->_toJPEG($img);
04735                         }
04736                     } elseif (extension_loaded('imagick')) {
04737                         
04738                         $img = new Imagick();
04739                         $img->readImage($file);
04740                         if ($resize) {
04741                             $img->resizeImage($neww, $newh, 10, 1, false);
04742                         }
04743                         $img->setCompressionQuality($this->jpeg_quality);
04744                         $img->setImageFormat('jpeg');
04745                         $tempname = tempnam(K_PATH_CACHE, 'jpg_');
04746                         $img->writeImage($tempname);
04747                         $info = $this->_parsejpeg($tempname);
04748                         unlink($tempname);
04749                         $img->destroy();
04750                     } else {
04751                         return;
04752                     }
04753                 }
04754                 if ($info === false) {
04755                     
04756                     return;
04757                 }
04758                 $this->set_mqr($mqr);
04759                 if ($ismask) {
04760                     
04761                     $info['cs'] = 'DeviceGray';
04762                 }
04763                 $info['i'] = $this->numimages + 1;
04764                 if ($imgmask !== false) {
04765                     $info['masked'] = $imgmask;
04766                 }
04767                 
04768                 $this->setImageBuffer($file, $info);
04769             } else {
04770                 $info = $this->getImageBuffer($file);
04771             }
04772             
04773             if ($this->checkPageBreak($h, $y)) {
04774                 $y = $this->GetY() + $this->cMargin;
04775             }
04776             
04777             $this->img_rb_y = $y + $h;
04778             
04779             if ($this->rtl) {
04780                 if ($palign == 'L') {
04781                     $ximg = $this->lMargin;
04782                     
04783                     $this->img_rb_x = $ximg + $w;
04784                 } elseif ($palign == 'C') {
04785                     $ximg = ($this->w - $x - $w) / 2;
04786                     
04787                     $this->img_rb_x = $ximg + $w;
04788                 } else {
04789                     $ximg = $this->w - $x - $w;
04790                     
04791                     $this->img_rb_x = $ximg;
04792                 }
04793             } else {
04794                 if ($palign == 'R') {
04795                     $ximg = $this->w - $this->rMargin - $w;
04796                     
04797                     $this->img_rb_x = $ximg;
04798                 } elseif ($palign == 'C') {
04799                     $ximg = ($this->w - $x - $w) / 2;
04800                     
04801                     $this->img_rb_x = $ximg + $w;
04802                 } else {
04803                     $ximg = $x;
04804                     
04805                     $this->img_rb_x = $ximg + $w;
04806                 }
04807             }
04808             if ($ismask OR $hidden) {
04809                 
04810                 return $info['i'];
04811             }
04812             $xkimg = $ximg * $this->k;
04813             $this->_out(sprintf('q %.2F 0 0 %.2F %.2F %.2F cm /I%d Do Q', ($w * $this->k), ($h * $this->k), $xkimg, (($this->h - ($y + $h)) * $this->k), $info['i']));
04814             if (!empty($border)) {
04815                 $bx = $x;
04816                 $by = $y;
04817                 $this->x = $ximg;
04818                 $this->y = $y;
04819                 $this->Cell($w, $h, '', $border, 0, '', 0, '', 0);
04820                 $this->x = $bx;
04821                 $this->y = $by;
04822             }
04823             if ($link) {
04824                 $this->Link($ximg, $y, $w, $h, $link, 0);
04825             }
04826             
04827             switch($align) {
04828                 case 'T': {
04829                     $this->y = $y;
04830                     $this->x = $this->img_rb_x;
04831                     break;
04832                 }
04833                 case 'M': {
04834                     $this->y = $y + round($h/2);
04835                     $this->x = $this->img_rb_x;
04836                     break;
04837                 }
04838                 case 'B': {
04839                     $this->y = $this->img_rb_y;
04840                     $this->x = $this->img_rb_x;
04841                     break;
04842                 }
04843                 case 'N': {
04844                     $this->SetY($this->img_rb_y);
04845                     break;
04846                 }
04847                 default:{
04848                     break;
04849                 }
04850             }
04851             $this->endlinex = $this->img_rb_x;
04852             return $info['i'];
04853         }
04854         
04860         public function set_mqr($mqr) {
04861             if (function_exists('set_magic_quotes_runtime')) {
04862                 @set_magic_quotes_runtime($mqr);
04863             }
04864         }
04865         
04871         public function get_mqr() {
04872             if (function_exists('get_magic_quotes_runtime')) {
04873                 return @get_magic_quotes_runtime();
04874             }
04875             return 0;
04876         }
04877                         
04886         protected function _toJPEG($image) {
04887             $tempname = tempnam(K_PATH_CACHE, 'jpg_');
04888             imagejpeg($image, $tempname, $this->jpeg_quality);
04889             imagedestroy($image);
04890             $retvars = $this->_parsejpeg($tempname);
04891             
04892             unlink($tempname);
04893             return $retvars;
04894         }
04895         
04902         protected function _parsejpeg($file) {
04903             $a = getimagesize($file);
04904             if (empty($a)) {
04905                 $this->Error('Missing or incorrect image file: '.$file);
04906             }
04907             if ($a[2] != 2) {
04908                 $this->Error('Not a JPEG file: '.$file);
04909             }
04910             if ((!isset($a['channels'])) OR ($a['channels'] == 3)) {
04911                 $colspace = 'DeviceRGB';
04912             } elseif ($a['channels'] == 4) {
04913                 $colspace = 'DeviceCMYK';
04914             } else {
04915                 $colspace = 'DeviceGray';
04916             }
04917             $bpc = isset($a['bits']) ? $a['bits'] : 8;
04918             $data = file_get_contents($file);
04919             return array('w' => $a[0], 'h' => $a[1], 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'DCTDecode', 'data' => $data);
04920         }
04921 
04928         protected function _parsepng($file) {
04929             $f = fopen($file, 'rb');
04930             if ($f === false) {
04931                 $this->Error('Can\'t open image file: '.$file);
04932             }
04933             
04934             if (fread($f, 8) != chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
04935                 $this->Error('Not a PNG file: '.$file);
04936             }
04937             
04938             fread($f, 4);
04939             if (fread($f, 4) != 'IHDR') {
04940                 $this->Error('Incorrect PNG file: '.$file);
04941             }
04942             $w = $this->_freadint($f);
04943             $h = $this->_freadint($f);
04944             $bpc = ord(fread($f, 1));
04945             if ($bpc > 8) {
04946                 
04947                 fclose($f);
04948                 return false;
04949             }
04950             $ct = ord(fread($f, 1));
04951             if ($ct == 0) {
04952                 $colspace = 'DeviceGray';
04953             } elseif ($ct == 2) {
04954                 $colspace = 'DeviceRGB';
04955             } elseif ($ct == 3) {
04956                 $colspace = 'Indexed';
04957             } else {
04958                 
04959                 fclose($f);
04960                 return 'pngalpha';
04961             }
04962             if (ord(fread($f, 1)) != 0) {
04963                 
04964                 fclose($f);
04965                 return false;
04966             }
04967             if (ord(fread($f, 1)) != 0) {
04968                 
04969                 fclose($f);
04970                 return false;
04971             }
04972             if (ord(fread($f, 1)) != 0) {
04973                 
04974                 fclose($f);
04975                 return false;
04976             }
04977             fread($f, 4);
04978             $parms = '/DecodeParms <</Predictor 15 /Colors '.($ct==2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>';
04979             
04980             $pal = '';
04981             $trns = '';
04982             $data = '';
04983             do {
04984                 $n = $this->_freadint($f);
04985                 $type = fread($f, 4);
04986                 if ($type == 'PLTE') {
04987                     
04988                     $pal = $this->rfread($f, $n);
04989                     fread($f, 4);
04990                 } elseif ($type == 'tRNS') {
04991                     
04992                     $t = $this->rfread($f, $n);
04993                     if ($ct == 0) {
04994                         $trns = array(ord(substr($t, 1, 1)));
04995                     } elseif ($ct == 2) {
04996                         $trns = array(ord(substr($t, 1, 1)), ord(substr($t, 3, 1)), ord(substr($t, 5, 1)));
04997                     } else {
04998                         $pos = strpos($t, chr(0));
04999                         if ($pos !== false) {
05000                             $trns = array($pos);
05001                         }
05002                     }
05003                     fread($f, 4);
05004                 } elseif ($type == 'IDAT') {
05005                     
05006                     $data .= $this->rfread($f, $n);
05007                     fread($f, 4);
05008                 } elseif ($type == 'IEND') {
05009                     break;
05010                 } else {
05011                     $this->rfread($f, $n + 4);
05012                 }
05013             } while ($n);
05014             if (($colspace == 'Indexed') AND (empty($pal))) {
05015                 
05016                 fclose($f);
05017                 return false;
05018             }
05019             fclose($f);
05020             return array('w' => $w, 'h' => $h, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'FlateDecode', 'parms' => $parms, 'pal' => $pal, 'trns' => $trns, 'data' => $data);
05021         }
05022 
05033         protected function rfread($handle, $length) {
05034             $data = fread($handle, $length);
05035             if ($data === false) {
05036                 return false;
05037             }
05038             $rest = $length - strlen($data);
05039             if ($rest > 0) {
05040                 $data .= $this->rfread($handle, $rest);
05041             }
05042             return $data;
05043         }
05044 
05063         protected function ImagePngAlpha($file, $x='', $y='', $w=0, $h=0, $type='', $link='', $align='', $resize=false, $dpi=300, $palign='') {
05064             
05065             list($wpx, $hpx) = getimagesize($file);
05066             
05067             $img = imagecreatefrompng($file);
05068             $imgalpha = imagecreate($wpx, $hpx);
05069             
05070             for ($c = 0; $c < 256; ++$c) {
05071                 ImageColorAllocate($imgalpha, $c, $c, $c);
05072             }
05073             
05074             for ($xpx = 0; $xpx < $wpx; ++$xpx) {
05075                 for ($ypx = 0; $ypx < $hpx; ++$ypx) {
05076                     $colorindex = imagecolorat($img, $xpx, $ypx);
05077                     $col = imagecolorsforindex($img, $colorindex);
05078                     imagesetpixel($imgalpha, $xpx, $ypx, $this->getGDgamma((127 - $col['alpha']) * 255 / 127));
05079                 }
05080             }
05081             
05082             $tempfile_alpha = tempnam(K_PATH_CACHE, 'mska_');
05083             imagepng($imgalpha, $tempfile_alpha);
05084             imagedestroy($imgalpha);
05085             
05086             $imgplain = imagecreatetruecolor($wpx, $hpx);
05087             imagecopy($imgplain, $img, 0, 0, 0, 0, $wpx, $hpx);
05088             
05089             $tempfile_plain = tempnam(K_PATH_CACHE, 'mskp_');
05090             imagepng($imgplain, $tempfile_plain);
05091             imagedestroy($imgplain);
05092             
05093             $imgmask = $this->Image($tempfile_alpha, $x, $y, $w, $h, 'PNG', '', '', $resize, $dpi, '', true, false);
05094             
05095             $this->Image($tempfile_plain, $x, $y, $w, $h, $type, $link, $align, $resize, $dpi, $palign, false, $imgmask);
05096             
05097             unlink($tempfile_alpha);
05098             unlink($tempfile_plain);
05099         }
05100 
05107         protected function getGDgamma($v) {
05108             return (pow(($v / 255), 2.2) * 255);
05109         } 
05110         
05120         public function Ln($h='', $cell=false) {
05121             
05122             if ($cell) {
05123                 $cellmargin = $this->cMargin;
05124             } else {
05125                 $cellmargin = 0;
05126             }
05127             if ($this->rtl) {
05128                 $this->x = $this->w - $this->rMargin - $cellmargin;
05129             } else {
05130                 $this->x = $this->lMargin + $cellmargin;
05131             }
05132             if (is_string($h)) {
05133                 $this->y += $this->lasth;
05134             } else {
05135                 $this->y += $h;
05136             }
05137             $this->newline = true;
05138         }
05139 
05148         public function GetX() {
05149             
05150             if ($this->rtl) {
05151                 return ($this->w - $this->x);
05152             } else {
05153                 return $this->x;
05154             }
05155         }
05156         
05164         public function GetAbsX() {
05165             return $this->x;
05166         }
05167         
05175         public function GetY() {
05176             
05177             return $this->y;
05178         }
05179         
05188         public function SetX($x) {
05189             
05190             if ($this->rtl) {
05191                 if ($x >= 0) {
05192                     $this->x = $this->w - $x;
05193                 } else {
05194                     $this->x = abs($x);
05195                 }
05196             } else {
05197                 if ($x >= 0) {
05198                     $this->x = $x;
05199                 } else {
05200                     $this->x = $this->w + $x;
05201                 }
05202             }
05203             if ($this->x < 0) {
05204                 $this->x = 0;
05205             }
05206             if ($this->x > $this->w) {
05207                 $this->x = $this->w;
05208             }
05209         }
05210         
05220         public function SetY($y, $resetx=true) {
05221             if ($resetx) {
05222                 
05223                 if ($this->rtl) {
05224                     $this->x = $this->w - $this->rMargin;
05225                 } else {
05226                     $this->x = $this->lMargin;
05227                 }
05228             }
05229             if ($y >= 0) {
05230                 $this->y = $y;
05231             } else {
05232                 $this->y = $this->h + $y;
05233             }
05234             if ($this->y < 0) {
05235                 $this->y = 0;
05236             }
05237             if ($this->y > $this->h) {
05238                 $this->y = $this->h;
05239             }
05240         }
05241         
05251         public function SetXY($x, $y) {
05252             
05253             $this->SetY($y);
05254             $this->SetX($x);
05255         }
05256 
05267         public function Output($name='doc.pdf', $dest='I') {
05268             
05269             
05270             if ($this->state < 3) {
05271                 $this->Close();
05272             }
05273             
05274             if (is_bool($dest)) {
05275                 $dest = $dest ? 'D' : 'F';
05276             }
05277             $dest = strtoupper($dest);
05278             if ($dest != 'F') {
05279                 $name = preg_replace('/[\s]+/', '_', $name);
05280                 $name = preg_replace('/[^a-zA-Z0-9_\.-]/', '', $name);
05281             }
05282             if ($this->sign) {
05283                 
05284                 
05285                 $pdfdoc = $this->getBuffer();
05286                 
05287                 $pdfdoc = substr($pdfdoc, 0, -1);
05288                 
05289                 if (isset($this->diskcache) AND $this->diskcache) {
05290                     
05291                     unlink($this->buffer);
05292                 }
05293                 unset($this->buffer);
05294                 
05295                 $byterange_string_len = strlen($this->byterange_string);
05296                 
05297                 $byte_range = array();
05298                 $byte_range[0] = 0;
05299                 $byte_range[1] = strpos($pdfdoc, $this->byterange_string) + $byterange_string_len + 10;
05300                 $byte_range[2] = $byte_range[1] + $this->signature_max_lenght + 2;
05301                 $byte_range[3] = strlen($pdfdoc) - $byte_range[2];
05302                 $pdfdoc = substr($pdfdoc, 0, $byte_range[1]).substr($pdfdoc, $byte_range[2]);
05303                 
05304                 $byterange = sprintf('/ByteRange[0 %u %u %u]', $byte_range[1], $byte_range[2], $byte_range[3]);
05305                 $byterange .= str_repeat(' ', ($byterange_string_len - strlen($byterange)));
05306                 $pdfdoc = str_replace($this->byterange_string, $byterange, $pdfdoc);
05307                 
05308                 $tempdoc = tempnam(K_PATH_CACHE, 'tmppdf_');
05309                 $f = fopen($tempdoc, 'wb');
05310                 if (!$f) {
05311                     $this->Error('Unable to create temporary file: '.$tempdoc);
05312                 }
05313                 $pdfdoc_lenght = strlen($pdfdoc);
05314                 fwrite($f, $pdfdoc, $pdfdoc_lenght);
05315                 fclose($f);
05316                 
05317                 $tempsign = tempnam(K_PATH_CACHE, 'tmpsig_');
05318                 if (empty($this->signature_data['extracerts'])) {
05319                     openssl_pkcs7_sign($tempdoc, $tempsign, $this->signature_data['signcert'], array($this->signature_data['privkey'], $this->signature_data['password']), array(), PKCS7_BINARY | PKCS7_DETACHED);
05320                 } else {
05321                     openssl_pkcs7_sign($tempdoc, $tempsign, $this->signature_data['signcert'], array($this->signature_data['privkey'], $this->signature_data['password']), array(), PKCS7_BINARY | PKCS7_DETACHED, $this->signature_data['extracerts']);
05322                 }   
05323                 unlink($tempdoc);
05324                 
05325                 $signature = file_get_contents($tempsign, false, null, $pdfdoc_lenght);
05326                 unlink($tempsign);
05327                 
05328                 $signature = substr($signature, (strpos($signature, "%%EOF\n\n------") + 13));
05329                 $tmparr = explode("\n\n", $signature);
05330                 $signature = $tmparr[1];
05331                 unset($tmparr);
05332                 
05333                 $signature = base64_decode(trim($signature));
05334                 
05335                 $signature = current(unpack('H*', $signature));
05336                 $signature = str_pad($signature, $this->signature_max_lenght, '0');
05337                 
05338                 $pdfdoc = substr($pdfdoc, 0, $byte_range[1]).'<'.$signature.'>'.substr($pdfdoc, ($byte_range[1]));
05339                 $this->diskcache = false;
05340                 $this->buffer = &$pdfdoc;
05341                 $this->bufferlen = strlen($pdfdoc);
05342             }
05343             switch($dest) {
05344                 case 'I': {
05345                     
05346                     if (ob_get_contents()) {
05347                         $this->Error('Some data has already been output, can\'t send PDF file');
05348                     }
05349                     if (php_sapi_name() != 'cli') {
05350                         
05351                         header('Content-Type: application/pdf');
05352                         if (headers_sent()) {
05353                             $this->Error('Some data has already been output to browser, can\'t send PDF file');
05354                         }
05355                         header('Cache-Control: public, must-revalidate, max-age=0'); 
05356                         header('Pragma: public');
05357                         header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); 
05358                         header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');  
05359                         header('Content-Length: '.$this->bufferlen);
05360                         header('Content-Disposition: inline; filename="'.basename($name).'";');
05361                     }
05362                     echo $this->getBuffer();
05363                     break;
05364                 }
05365                 case 'D': {
05366                     
05367                     if (ob_get_contents()) {
05368                         $this->Error('Some data has already been output, can\'t send PDF file');
05369                     }
05370                     header('Content-Description: File Transfer');
05371                     if (headers_sent()) {
05372                         $this->Error('Some data has already been output to browser, can\'t send PDF file');
05373                     }
05374                     header('Cache-Control: public, must-revalidate, max-age=0'); 
05375                     header('Pragma: public');
05376                     header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); 
05377                     header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
05378                     
05379                     header('Content-Type: application/force-download');
05380                     header('Content-Type: application/octet-stream', false);
05381                     header('Content-Type: application/download', false);
05382                     header('Content-Type: application/pdf', false);
05383                     
05384                     header('Content-Disposition: attachment; filename="'.basename($name).'";');
05385                     header('Content-Transfer-Encoding: binary');
05386                     header('Content-Length: '.$this->bufferlen);
05387                     echo $this->getBuffer();
05388                     break;
05389                 }
05390                 case 'F': {
05391                     
05392                     if ($this->diskcache) {
05393                         copy($this->buffer, $name);
05394                     } else {
05395                         $f = fopen($name, 'wb');
05396                         if (!$f) {
05397                             $this->Error('Unable to create output file: '.$name);
05398                         }
05399                         fwrite($f, $this->getBuffer(), $this->bufferlen);
05400                         fclose($f);
05401                     }
05402                     break;
05403                 }
05404                 case 'S': {
05405                     
05406                     return $this->getBuffer();
05407                 }
05408                 default: {
05409                     $this->Error('Incorrect output destination: '.$dest);
05410                 }
05411             }
05412             return '';
05413         }
05414 
05422         public function _destroy($destroyall=false, $preserve_objcopy=false) {
05423             if ($destroyall AND isset($this->diskcache) AND $this->diskcache AND (!$preserve_objcopy) AND (!$this->empty_string($this->buffer))) {
05424                 
05425                 unlink($this->buffer);
05426             }
05427             foreach (array_keys(get_object_vars($this)) as $val) {
05428                 if ($destroyall OR (
05429                     ($val != 'internal_encoding') 
05430                     AND ($val != 'state') 
05431                     AND ($val != 'bufferlen') 
05432                     AND ($val != 'buffer') 
05433                     AND ($val != 'diskcache')
05434                     AND ($val != 'sign')
05435                     AND ($val != 'signature_data')
05436                     AND ($val != 'signature_max_lenght')
05437                     AND ($val != 'byterange_string')
05438                     )) {
05439                     if (!$preserve_objcopy OR ($val != 'objcopy')) {
05440                         unset($this->$val);
05441                     }
05442                 }
05443             }
05444         }
05445         
05450         protected function _dochecks() {
05451             
05452             if (1.1 == 1) {
05453                 $this->Error('Don\'t alter the locale before including class file');
05454             }
05455             
05456             if (sprintf('%.1F', 1.0) != '1.0') {
05457                 setlocale(LC_NUMERIC, 'C');
05458             }
05459         }
05460 
05466         protected function _getfontpath() {
05467             if (!defined('K_PATH_FONTS') AND is_dir(dirname(__FILE__).'/fonts')) {
05468                 define('K_PATH_FONTS', dirname(__FILE__).'/fonts/');
05469             }
05470             return defined('K_PATH_FONTS') ? K_PATH_FONTS : '';
05471         }
05472         
05477         protected function _putpages() {
05478             $nb = $this->numpages;
05479             if (!empty($this->AliasNbPages)) {
05480                 $nbs = $this->formatPageNumber($nb);
05481                 $nbu = $this->UTF8ToUTF16BE($nbs, false); 
05482                 $alias_a = $this->_escape($this->AliasNbPages);
05483                 $alias_au = $this->_escape('{'.$this->AliasNbPages.'}');
05484                 if ($this->isunicode) {
05485                     $alias_b = $this->_escape($this->UTF8ToLatin1($this->AliasNbPages));
05486                     $alias_bu = $this->_escape($this->UTF8ToLatin1('{'.$this->AliasNbPages.'}'));
05487                     $alias_c = $this->_escape($this->utf8StrRev($this->AliasNbPages, false, $this->tmprtl));
05488                     $alias_cu = $this->_escape($this->utf8StrRev('{'.$this->AliasNbPages.'}', false, $this->tmprtl));
05489                 }
05490             }
05491             if (!empty($this->AliasNumPage)) {
05492                 $alias_pa = $this->_escape($this->AliasNumPage);
05493                 $alias_pau = $this->_escape('{'.$this->AliasNumPage.'}');
05494                 if ($this->isunicode) {
05495                     $alias_pb = $this->_escape($this->UTF8ToLatin1($this->AliasNumPage));
05496                     $alias_pbu = $this->_escape($this->UTF8ToLatin1('{'.$this->AliasNumPage.'}'));
05497                     $alias_pc = $this->_escape($this->utf8StrRev($this->AliasNumPage, false, $this->tmprtl));
05498                     $alias_pcu = $this->_escape($this->utf8StrRev('{'.$this->AliasNumPage.'}', false, $this->tmprtl));
05499                 }
05500             }
05501             $pagegroupnum = 0;
05502             $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
05503             for ($n=1; $n <= $nb; ++$n) {
05504                 $temppage = $this->getPageBuffer($n);
05505                 if (!empty($this->pagegroups)) {
05506                     if(isset($this->newpagegroup[$n])) {
05507                         $pagegroupnum = 0;
05508                     }
05509                     ++$pagegroupnum;
05510                     foreach ($this->pagegroups as $k => $v) {
05511                         
05512                         $vs = $this->formatPageNumber($v);
05513                         $vu = $this->UTF8ToUTF16BE($vs, false);
05514                         $alias_ga = $this->_escape($k);
05515                         $alias_gau = $this->_escape('{'.$k.'}');
05516                         if ($this->isunicode) {
05517                             $alias_gb = $this->_escape($this->UTF8ToLatin1($k));
05518                             $alias_gbu = $this->_escape($this->UTF8ToLatin1('{'.$k.'}'));
05519                             $alias_gc = $this->_escape($this->utf8StrRev($k, false, $this->tmprtl));
05520                             $alias_gcu = $this->_escape($this->utf8StrRev('{'.$k.'}', false, $this->tmprtl));
05521                         }
05522                         $temppage = str_replace($alias_gau, $vu, $temppage);
05523                         if ($this->isunicode) {
05524                             $temppage = str_replace($alias_gbu, $vu, $temppage);
05525                             $temppage = str_replace($alias_gcu, $vu, $temppage);
05526                             $temppage = str_replace($alias_gb, $vs, $temppage);
05527                             $temppage = str_replace($alias_gc, $vs, $temppage);
05528                         }
05529                         $temppage = str_replace($alias_ga, $vs, $temppage);
05530                         
05531                         $pvs = $this->formatPageNumber($pagegroupnum);
05532                         $pvu = $this->UTF8ToUTF16BE($pvs, false);
05533                         $pk = str_replace('{nb', '{pnb', $k);
05534                         $alias_pga = $this->_escape($pk);
05535                         $alias_pgau = $this->_escape('{'.$pk.'}');
05536                         if ($this->isunicode) {
05537                             $alias_pgb = $this->_escape($this->UTF8ToLatin1($pk));
05538                             $alias_pgbu = $this->_escape($this->UTF8ToLatin1('{'.$pk.'}'));
05539                             $alias_pgc = $this->_escape($this->utf8StrRev($pk, false, $this->tmprtl));
05540                             $alias_pgcu = $this->_escape($this->utf8StrRev('{'.$pk.'}', false, $this->tmprtl));
05541                         }
05542                         $temppage = str_replace($alias_pgau, $pvu, $temppage);
05543                         if ($this->isunicode) {
05544                             $temppage = str_replace($alias_pgbu, $pvu, $temppage);
05545                             $temppage = str_replace($alias_pgcu, $pvu, $temppage);
05546                             $temppage = str_replace($alias_pgb, $pvs, $temppage);
05547                             $temppage = str_replace($alias_pgc, $pvs, $temppage);
05548                         }
05549                         $temppage = str_replace($alias_pga, $pvs, $temppage);
05550                     }
05551                 }
05552                 if (!empty($this->AliasNbPages)) {
05553                     
05554                     $temppage = str_replace($alias_au, $nbu, $temppage);
05555                     if ($this->isunicode) {
05556                         $temppage = str_replace($alias_bu, $nbu, $temppage);
05557                         $temppage = str_replace($alias_cu, $nbu, $temppage);
05558                         $temppage = str_replace($alias_b, $nbs, $temppage);
05559                         $temppage = str_replace($alias_c, $nbs, $temppage);
05560                     }
05561                     $temppage = str_replace($alias_a, $nbs, $temppage);
05562                 }
05563                 if (!empty($this->AliasNumPage)) {
05564                     
05565                     $pnbs = $this->formatPageNumber($n);
05566                     $pnbu = $this->UTF8ToUTF16BE($pnbs, false); 
05567                     $temppage = str_replace($alias_pau, $pnbu, $temppage);
05568                     if ($this->isunicode) {
05569                         $temppage = str_replace($alias_pbu, $pnbu, $temppage);
05570                         $temppage = str_replace($alias_pcu, $pnbu, $temppage);
05571                         $temppage = str_replace($alias_pb, $pnbs, $temppage);
05572                         $temppage = str_replace($alias_pc, $pnbs, $temppage);
05573                     }
05574                     $temppage = str_replace($alias_pa, $pnbs, $temppage);
05575                 }
05576                 $temppage = str_replace($this->epsmarker, '', $temppage);
05577                 
05578                 $this->page_obj_id[$n] = $this->_newobj();
05579                 $this->_out('<</Type /Page');
05580                 $this->_out('/Parent 1 0 R');
05581                 $this->_out(sprintf('/MediaBox [0 0 %.2F %.2F]', $this->pagedim[$n]['w'], $this->pagedim[$n]['h']));
05582                 $this->_out('/Resources 2 0 R');
05583                 $this->_putannotsrefs($n);
05584                 $this->_out('/Contents '.($this->n + 1).' 0 R>>');
05585                 $this->_out('endobj');
05586                 
05587                 $p = ($this->compress) ? gzcompress($temppage) : $temppage;
05588                 $this->_newobj();
05589                 $this->_out('<<'.$filter.'/Length '.strlen($p).'>>');
05590                 $this->_putstream($p);
05591                 $this->_out('endobj');
05592                 if ($this->diskcache) {
05593                     
05594                     unlink($this->pages[$n]);
05595                 }
05596             }
05597             
05598             $this->offsets[1] = $this->bufferlen;
05599             $this->_out('1 0 obj');
05600             $this->_out('<</Type /Pages');
05601             $this->_out('/Kids [');
05602             foreach($this->page_obj_id as $page_obj) {
05603                 $this->_out($page_obj.' 0 R');
05604             }
05605             $this->_out(']');
05606             $this->_out('/Count '.$nb);
05607             $this->_out('>>');
05608             $this->_out('endobj');
05609         }
05610 
05618         protected function _putannotsrefs($n) {
05619             if (!(isset($this->PageAnnots[$n]) OR ($this->sign AND isset($this->signature_data['cert_type'])))) {
05620                 return;
05621             }
05622             $this->_out('/Annots [');
05623             if (isset($this->PageAnnots[$n])) {
05624                 $num_annots = count($this->PageAnnots[$n]);
05625                 for ($i = 0; $i < $num_annots; ++$i) {
05626                     ++$this->curr_annot_obj_id;
05627                     if (!in_array($this->curr_annot_obj_id, $this->radio_groups)) {
05628                         $this->_out($this->curr_annot_obj_id.' 0 R');
05629                     } else {
05630                         ++$num_annots;
05631                     }
05632                 }
05633             }
05634             if (($n==1) AND $this->sign AND isset($this->signature_data['cert_type'])) {
05635                 
05636                 $this->_out($this->sig_annot_ref);
05637             }
05638             $this->_out(']');
05639         }
05640 
05649         protected function _putannotsobjs() {
05650             
05651             $this->annot_obj_id = $this->annots_start_obj_id;
05652             for ($n=1; $n <= $this->numpages; ++$n) {
05653                 if (isset($this->PageAnnots[$n])) {
05654                     
05655                     foreach ($this->PageAnnots[$n] as $key => $pl) {
05656                         
05657                         if (isset($this->radiobutton_groups[$n][$pl['txt']]) AND is_array($this->radiobutton_groups[$n][$pl['txt']])) {
05658                             $annots = '<<';
05659                             $annots .= ' /Type /Annot';
05660                             $annots .= ' /Subtype /Widget';
05661                             $annots .= ' /T '.$this->_datastring($pl['txt']);
05662                             $annots .= ' /FT /Btn';
05663                             $annots .= ' /Ff 49152';
05664                             $annots .= ' /Kids [';
05665                             foreach ($this->radiobutton_groups[$n][$pl['txt']] as $data) {
05666                                 $annots .= ' '.$data['kid'].' 0 R';
05667                                 if ($data['def'] !== 'Off') {
05668                                     $defval = $data['def'];
05669                                 }
05670                             }
05671                             $annots .= ' ]';
05672                             if (isset($defval)) {
05673                                 $annots .= ' /V /'.$defval;
05674                             }
05675                             $annots .= ' >>';
05676                             ++$this->annot_obj_id;
05677                             $this->offsets[$this->annot_obj_id] = $this->bufferlen;
05678                             $this->_out($this->annot_obj_id.' 0 obj');
05679                             $this->_out($annots);
05680                             $this->_out('endobj');
05681                             $this->form_obj_id[] = $this->annot_obj_id;
05682                             
05683                             $this->radiobutton_groups[$n][$pl['txt']] = $this->annot_obj_id;
05684                         }
05685                         $formfield = false;
05686                         $pl['opt'] = array_change_key_case($pl['opt'], CASE_LOWER);
05687                         $a = $pl['x'] * $this->k;
05688                         $b = $this->pagedim[$n]['h'] - (($pl['y'] + $pl['h'])  * $this->k);
05689                         $c = $pl['w'] * $this->k;
05690                         $d = $pl['h'] * $this->k;
05691                         $rect = sprintf('%.2F %.2F %.2F %.2F', $a, $b, $a+$c, $b+$d);
05692                         
05693                         $annots = '<</Type /Annot';
05694                         $annots .= ' /Subtype /'.$pl['opt']['subtype'];
05695                         $annots .= ' /Rect ['.$rect.']';
05696                         $ft = array('Btn', 'Tx', 'Ch', 'Sig');
05697                         if (isset($pl['opt']['ft']) AND in_array($pl['opt']['ft'], $ft)) {
05698                             $annots .= ' /FT /'.$pl['opt']['ft'];
05699                             $formfield = true;
05700                         }
05701                         $annots .= ' /Contents '.$this->_textstring($pl['txt']);
05702                         $annots .= ' /P '.$this->page_obj_id[$n].' 0 R';
05703                         $annots .= ' /NM '.$this->_datastring(sprintf('%04u-%04u', $n, $key));
05704                         $annots .= ' /M '.$this->_datestring();
05705                         if (isset($pl['opt']['f'])) {
05706                             $val = 0;
05707                             if (is_array($pl['opt']['f'])) {
05708                                 foreach ($pl['opt']['f'] as $f) {
05709                                     switch (strtolower($f)) {
05710                                         case 'invisible': {
05711                                             $val += 1 << 0;
05712                                             break;
05713                                         }
05714                                         case 'hidden': {
05715                                             $val += 1 << 1;
05716                                             break;
05717                                         }
05718                                         case 'print': {
05719                                             $val += 1 << 2;
05720                                             break;
05721                                         }
05722                                         case 'nozoom': {
05723                                             $val += 1 << 3;
05724                                             break;
05725                                         }
05726                                         case 'norotate': {
05727                                             $val += 1 << 4;
05728                                             break;
05729                                         }
05730                                         case 'noview': {
05731                                             $val += 1 << 5;
05732                                             break;
05733                                         }
05734                                         case 'readonly': {
05735                                             $val += 1 << 6;
05736                                             break;
05737                                         }
05738                                         case 'locked': {
05739                                             $val += 1 << 8;
05740                                             break;
05741                                         }
05742                                         case 'togglenoview': {
05743                                             $val += 1 << 9;
05744                                             break;
05745                                         }
05746                                         case 'lockedcontents': {
05747                                             $val += 1 << 10;
05748                                             break;
05749                                         }
05750                                         default: {
05751                                             break;
05752                                         }
05753                                     }
05754                                 }
05755                             } else {
05756                                 $val = intval($pl['opt']['f']);
05757                             }
05758                             $annots .= ' /F '.intval($val);
05759                         }
05760                         if (isset($pl['opt']['as']) AND is_string($pl['opt']['as'])) {
05761                             $annots .= ' /AS /'.$pl['opt']['as'];
05762                         }
05763                         if (isset($pl['opt']['ap'])) {
05764                             
05765                             $annots .= ' /AP <<';
05766                             if (is_array($pl['opt']['ap'])) {
05767                                 foreach ($pl['opt']['ap'] as $apmode => $apdef) {
05768                                     
05769                                     $annots .= ' /'.strtoupper($apmode);
05770                                     if (is_array($apdef)) {
05771                                         $annots .= ' <<';
05772                                         foreach ($apdef as $apstate => $stream) {
05773                                             
05774                                             $apsobjid = $this->_putAPXObject($c, $d, $stream);
05775                                             $annots .= ' /'.$apstate.' '.$apsobjid.' 0 R';
05776                                         }
05777                                         $annots .= ' >>';
05778                                     } else {
05779                                         
05780                                         $apsobjid = $this->_putAPXObject($c, $d, $apdef);
05781                                         $annots .= ' '.$apsobjid.' 0 R';
05782                                     }
05783                                 }
05784                             } else {
05785                                 $annots .= $pl['opt']['ap'];
05786                             }
05787                             $annots .= ' >>';
05788                         }
05789                         if (isset($pl['opt']['bs']) AND (is_array($pl['opt']['bs']))) {
05790                             $annots .= ' /BS <<';
05791                             $annots .= ' /Type /Border';
05792                             if (isset($pl['opt']['bs']['w'])) {
05793                                 $annots .= ' /W '.intval($pl['opt']['bs']['w']);
05794                             }
05795                             $bstyles = array('S', 'D', 'B', 'I', 'U');
05796                             if (isset($pl['opt']['bs']['s']) AND in_array($pl['opt']['bs']['s'], $bstyles)) {
05797                                 $annots .= ' /S /'.$pl['opt']['bs']['s'];
05798                             }
05799                             if (isset($pl['opt']['bs']['d']) AND (is_array($pl['opt']['bs']['d']))) {
05800                                 $annots .= ' /D [';
05801                                 foreach ($pl['opt']['bs']['d'] as $cord) {
05802                                     $annots .= ' '.intval($cord);
05803                                 }
05804                                 $annots .= ']';
05805                             }
05806                             $annots .= ' >>';
05807                         } else {
05808                             $annots .= ' /Border [';
05809                             if (isset($pl['opt']['border']) AND (count($pl['opt']['border']) >= 3)) {
05810                                 $annots .= intval($pl['opt']['border'][0]).' ';
05811                                 $annots .= intval($pl['opt']['border'][1]).' ';
05812                                 $annots .= intval($pl['opt']['border'][2]);
05813                                 if (isset($pl['opt']['border'][3]) AND is_array($pl['opt']['border'][3])) {
05814                                     $annots .= ' [';
05815                                     foreach ($pl['opt']['border'][3] as $dash) {
05816                                         $annots .= intval($dash).' ';
05817                                     }
05818                                     $annots .= ']';
05819                                 }
05820                             } else {
05821                                 $annots .= '0 0 0';
05822                             }
05823                             $annots .= ']';
05824                         }
05825                         if (isset($pl['opt']['be']) AND (is_array($pl['opt']['be']))) {
05826                             $annots .= ' /BE <<';
05827                             $bstyles = array('S', 'C');
05828                             if (isset($pl['opt']['be']['s']) AND in_array($pl['opt']['be']['s'], $markups)) {
05829                                 $annots .= ' /S /'.$pl['opt']['bs']['s'];
05830                             } else {
05831                                 $annots .= ' /S /S';
05832                             }
05833                             if (isset($pl['opt']['be']['i']) AND ($pl['opt']['be']['i'] >= 0) AND ($pl['opt']['be']['i'] <= 2)) {
05834                                 $annots .= ' /I '.sprintf(" %.4F", $pl['opt']['be']['i']);
05835                             }
05836                             $annots .= '>>';
05837                         }
05838                         if (isset($pl['opt']['c']) AND (is_array($pl['opt']['c'])) AND !empty($pl['opt']['c'])) {
05839                             $annots .= ' /C [';
05840                             foreach ($pl['opt']['c'] as $col) {
05841                                 $col = intval($col);
05842                                 $color = $col <= 0 ? 0 : ($col >= 255 ? 1 : $col / 255);
05843                                 $annots .= sprintf(" %.4F", $color);
05844                             }
05845                             $annots .= ']';
05846                         }
05847                         
05848                         
05849                         $markups = array('text', 'freetext', 'line', 'square', 'circle', 'polygon', 'polyline', 'highlight',  'underline', 'squiggly', 'strikeout', 'stamp', 'caret', 'ink', 'fileattachment', 'sound');
05850                         if (in_array(strtolower($pl['opt']['subtype']), $markups)) {
05851                             
05852                             if (isset($pl['opt']['t']) AND is_string($pl['opt']['t'])) {
05853                                 $annots .= ' /T '.$this->_textstring($pl['opt']['t']);
05854                             }
05855                             
05856                             if (isset($pl['opt']['ca'])) {
05857                                 $annots .= ' /CA '.sprintf("%.4F", floatval($pl['opt']['ca']));
05858                             }
05859                             if (isset($pl['opt']['rc'])) {
05860                                 $annots .= ' /RC '.$this->_textstring($pl['opt']['rc']);
05861                             }
05862                             $annots .= ' /CreationDate '.$this->_datestring();
05863                             
05864                             if (isset($pl['opt']['subj'])) {
05865                                 $annots .= ' /Subj '.$this->_textstring($pl['opt']['subj']);
05866                             }
05867                             
05868                             
05869                             
05870                         }
05871                         $lineendings = array('Square', 'Circle', 'Diamond', 'OpenArrow', 'ClosedArrow', 'None', 'Butt', 'ROpenArrow', 'RClosedArrow', 'Slash');
05872                         switch (strtolower($pl['opt']['subtype'])) {
05873                             case 'text': {
05874                                 if (isset($pl['opt']['open'])) {
05875                                     $annots .= ' /Open '. (strtolower($pl['opt']['open']) == 'true' ? 'true' : 'false');
05876                                 }
05877                                 $iconsapp = array('Comment', 'Help', 'Insert', 'Key', 'NewParagraph', 'Note', 'Paragraph');
05878                                 if (isset($pl['opt']['name']) AND in_array($pl['opt']['name'], $iconsapp)) {
05879                                     $annots .= ' /Name /'.$pl['opt']['name'];
05880                                 } else {
05881                                     $annots .= ' /Name /Note';
05882                                 }
05883                                 $statemodels = array('Marked', 'Review');
05884                                 if (isset($pl['opt']['statemodel']) AND in_array($pl['opt']['statemodel'], $statemodels)) {
05885                                     $annots .= ' /StateModel /'.$pl['opt']['statemodel'];
05886                                 } else {
05887                                     $pl['opt']['statemodel'] = 'Marked';
05888                                     $annots .= ' /StateModel /'.$pl['opt']['statemodel'];
05889                                 }
05890                                 if ($pl['opt']['statemodel'] == 'Marked') {
05891                                     $states = array('Accepted', 'Unmarked');
05892                                 } else {
05893                                     $states = array('Accepted', 'Rejected', 'Cancelled', 'Completed', 'None');
05894                                 }
05895                                 if (isset($pl['opt']['state']) AND in_array($pl['opt']['state'], $states)) {
05896                                     $annots .= ' /State /'.$pl['opt']['state'];
05897                                 } else {
05898                                     if ($pl['opt']['statemodel'] == 'Marked') {
05899                                         $annots .= ' /State /Unmarked';
05900                                     } else {
05901                                         $annots .= ' /State /None';
05902                                     }
05903                                 }
05904                                 break;
05905                             }
05906                             case 'link': {
05907                                 if(is_string($pl['txt'])) {
05908                                     
05909                                     $annots .= ' /A <</S /URI /URI '.$this->_datastring($this->unhtmlentities($pl['txt'])).'>>';
05910                                 } else {
05911                                     
05912                                     $l = $this->links[$pl['txt']];
05913                                     $annots .= sprintf(' /Dest [%d 0 R /XYZ 0 %.2F null]', (1 + (2 * $l[0])), ($this->pagedim[$l[0]]['h'] - ($l[1] * $this->k)));
05914                                 }
05915                                 $hmodes = array('N', 'I', 'O', 'P');
05916                                 if (isset($pl['opt']['h']) AND in_array($pl['opt']['h'], $hmodes)) {
05917                                     $annots .= ' /H /'.$pl['opt']['h'];
05918                                 } else {
05919                                     $annots .= ' /H /I';
05920                                 }
05921                                 
05922                                 
05923                                 break;
05924                             }
05925                             case 'freetext': {
05926                                 if (isset($pl['opt']['da']) AND !empty($pl['opt']['da'])) {
05927                                     $annots .= ' /DA ('.$pl['opt']['da'].')';
05928                                 }
05929                                 if (isset($pl['opt']['q']) AND ($pl['opt']['q'] >= 0) AND ($pl['opt']['q'] <= 2)) {
05930                                     $annots .= ' /Q '.intval($pl['opt']['q']);
05931                                 }
05932                                 if (isset($pl['opt']['rc'])) {
05933                                     $annots .= ' /RC '.$this->_textstring($pl['opt']['rc']);
05934                                 }
05935                                 if (isset($pl['opt']['ds'])) {
05936                                     $annots .= ' /DS '.$this->_textstring($pl['opt']['ds']);
05937                                 }
05938                                 if (isset($pl['opt']['cl']) AND is_array($pl['opt']['cl'])) {
05939                                     $annots .= ' /CL [';
05940                                     foreach ($pl['opt']['cl'] as $cl) {
05941                                         $annots .= sprintf("%.4F ", $cl * $this->k);
05942                                     }
05943                                     $annots .= ']';
05944                                 }
05945                                 $tfit = array('FreeText', 'FreeTextCallout', 'FreeTextTypeWriter');
05946                                 if (isset($pl['opt']['it']) AND in_array($pl['opt']['it'], $tfit)) {
05947                                     $annots .= ' /IT '.$pl['opt']['it'];
05948                                 }
05949                                 if (isset($pl['opt']['rd']) AND is_array($pl['opt']['rd'])) {
05950                                     $l = $pl['opt']['rd'][0] * $this->k;
05951                                     $r = $pl['opt']['rd'][1] * $this->k;
05952                                     $t = $pl['opt']['rd'][2] * $this->k;
05953                                     $b = $pl['opt']['rd'][3] * $this->k;
05954                                     $annots .= ' /RD ['.sprintf('%.2F %.2F %.2F %.2F', $l, $r, $t, $b).']';
05955                                 }
05956                                 if (isset($pl['opt']['le']) AND in_array($pl['opt']['le'], $lineendings)) {
05957                                     $annots .= ' /LE /'.$pl['opt']['le'];
05958                                 }
05959                                 break;
05960                             }
05961                             case 'line': {
05962                                 break;
05963                             }
05964                             case 'square': {
05965                                 break;
05966                             }
05967                             case 'circle': {
05968                                 break;
05969                             }
05970                             case 'polygon': {
05971                                 break;
05972                             }
05973                             case 'polyline': {
05974                                 break;
05975                             }
05976                             case 'highlight': {
05977                                 break;
05978                             }
05979                             case 'underline': {
05980                                 break;
05981                             }
05982                             case 'squiggly': {
05983                                 break;
05984                             }
05985                             case 'strikeout': {
05986                                 break;
05987                             }
05988                             case 'stamp': {
05989                                 break;
05990                             }
05991                             case 'caret': {
05992                                 break;
05993                             }
05994                             case 'ink': {
05995                                 break;
05996                             }
05997                             case 'popup': {
05998                                 break;
05999                             }
06000                             case 'fileattachment': {
06001                                 if (!isset($pl['opt']['fs'])) {
06002                                     break;
06003                                 }
06004                                 $filename = basename($pl['opt']['fs']);
06005                                 if (isset($this->embeddedfiles[$filename]['n'])) {
06006                                     $annots .= ' /FS <</Type /Filespec /F '.$this->_datastring($filename).' /EF <</F '.$this->embeddedfiles[$filename]['n'].' 0 R>> >>';
06007                                     $iconsapp = array('Graph', 'Paperclip', 'PushPin', 'Tag');
06008                                     if (isset($pl['opt']['name']) AND in_array($pl['opt']['name'], $iconsapp)) {
06009                                         $annots .= ' /Name /'.$pl['opt']['name'];
06010                                     } else {
06011                                         $annots .= ' /Name /PushPin';
06012                                     }
06013                                 }
06014                                 break;
06015                             }
06016                             case 'sound': {
06017                                 if (!isset($pl['opt']['sound'])) {
06018                                     break;
06019                                 }
06020                                 $filename = basename($pl['opt']['sound']);
06021                                 if (isset($this->embeddedfiles[$filename]['n'])) {
06022                                     $annots .= ' /Sound <</Type /Sound';
06023                                     
06024                                     
06025                                     
06026                                     $iconsapp = array('Speaker', 'Mic');
06027                                     if (isset($pl['opt']['name']) AND in_array($pl['opt']['name'], $iconsapp)) {
06028                                         $annots .= ' /Name /'.$pl['opt']['name'];
06029                                     } else {
06030                                         $annots .= ' /Name /Speaker';
06031                                     }
06032                                 }
06033                                 break;
06034                             }
06035                             case 'movie': {
06036                                 break;
06037                             }
06038                             case 'widget': {
06039                                 $hmode = array('N', 'I', 'O', 'P', 'T');
06040                                 if (isset($pl['opt']['h']) AND in_array($pl['opt']['h'], $hmode)) {
06041                                     $annots .= ' /H /'.$pl['opt']['h'];
06042                                 }
06043                                 if (isset($pl['opt']['mk']) AND (is_array($pl['opt']['mk'])) AND !empty($pl['opt']['mk'])) {
06044                                     $annots .= ' /MK <<';
06045                                     if (isset($pl['opt']['mk']['r'])) {
06046                                         $annots .= ' /R '.$pl['opt']['mk']['r'];
06047                                     }
06048                                     if (isset($pl['opt']['mk']['bc']) AND (is_array($pl['opt']['mk']['bc']))) {
06049                                         $annots .= ' /BC [';
06050                                         foreach($pl['opt']['mk']['bc'] AS $col) {
06051                                             $col = intval($col);
06052                                             $color = $col <= 0 ? 0 : ($col >= 255 ? 1 : $col / 255);
06053                                             $annots .= ' '.$color;
06054                                         }
06055                                         $annots .= ']';
06056                                     }
06057                                     if (isset($pl['opt']['mk']['bg']) AND (is_array($pl['opt']['mk']['bg']))) {
06058                                         $annots .= ' /BG [';
06059                                         foreach($pl['opt']['mk']['bg'] AS $col) {
06060                                             $col = intval($col);
06061                                             $color = $col <= 0 ? 0 : ($col >= 255 ? 1 : $col / 255);
06062                                             $annots .= ' '.$color;
06063                                         }
06064                                         $annots .= ']';
06065                                     }
06066                                     if (isset($pl['opt']['mk']['ca'])) {
06067                                         $annots .= ' /CA '.$pl['opt']['mk']['ca'].'';
06068                                     }
06069                                     if (isset($pl['opt']['mk']['rc'])) {
06070                                         $annots .= ' /RC '.$pl['opt']['mk']['ca'].'';
06071                                     }
06072                                     if (isset($pl['opt']['mk']['ac'])) {
06073                                         $annots .= ' /AC '.$pl['opt']['mk']['ca'].'';
06074                                     }                                                                   
06075                                     if (isset($pl['opt']['mk']['i'])) {
06076                                         $info = $this->getImageBuffer($pl['opt']['mk']['i']);
06077                                         if ($info !== false) {
06078                                             $annots .= ' /I '.$info['n'].' 0 R';
06079                                         }
06080                                     }
06081                                     if (isset($pl['opt']['mk']['ri'])) {
06082                                         $info = $this->getImageBuffer($pl['opt']['mk']['ri']);
06083                                         if ($info !== false) {
06084                                             $annots .= ' /RI '.$info['n'].' 0 R';
06085                                         }
06086                                     }
06087                                     if (isset($pl['opt']['mk']['ix'])) {
06088                                         $info = $this->getImageBuffer($pl['opt']['mk']['ix']);
06089                                         if ($info !== false) {
06090                                             $annots .= ' /IX '.$info['n'].' 0 R';
06091                                         }
06092                                     }                                   
06093                                     if (isset($pl['opt']['mk']['if']) AND (is_array($pl['opt']['mk']['if'])) AND !empty($pl['opt']['mk']['if'])) {
06094                                         $annots .= ' /IF <<';
06095                                         $if_sw = array('A', 'B', 'S', 'N');
06096                                         if (isset($pl['opt']['mk']['if']['sw']) AND in_array($pl['opt']['mk']['if']['sw'], $if_sw)) {
06097                                             $annots .= ' /SW /'.$pl['opt']['mk']['if']['sw'];
06098                                         }
06099                                         $if_s = array('A', 'P');
06100                                         if (isset($pl['opt']['mk']['if']['s']) AND in_array($pl['opt']['mk']['if']['s'], $if_s)) {
06101                                             $annots .= ' /S /'.$pl['opt']['mk']['if']['s'];
06102                                         }
06103                                         if (isset($pl['opt']['mk']['if']['a']) AND (is_array($pl['opt']['mk']['if']['a'])) AND !empty($pl['opt']['mk']['if']['a'])) {
06104                                             $annots .= ' /A ['.$pl['opt']['mk']['if']['a'][0].' '.$pl['opt']['mk']['if']['a'][1].']';
06105                                         }
06106                                         if (isset($pl['opt']['mk']['if']['fb']) AND ($pl['opt']['mk']['if']['fb'])) {
06107                                             $annots .= ' /FB true';
06108                                         }
06109                                         $annots .= '>>';
06110                                     }
06111                                     if (isset($pl['opt']['mk']['tp']) AND ($pl['opt']['mk']['tp'] >= 0) AND ($pl['opt']['mk']['tp'] <= 6)) {
06112                                         $annots .= ' /TP '.$pl['opt']['mk']['tp'];
06113                                     } else {
06114                                         $annots .= ' /TP 0';
06115                                     }
06116                                     $annots .= '>>';
06117                                 } 
06118                                 
06119                                 if (isset($this->radiobutton_groups[$n][$pl['txt']])) {
06120                                     
06121                                     $annots .= ' /Parent '.$this->radiobutton_groups[$n][$pl['txt']].' 0 R';
06122                                 }
06123                                 if (isset($pl['opt']['t']) AND is_string($pl['opt']['t'])) {
06124                                     $annots .= ' /T '.$this->_datastring($pl['opt']['t']);
06125                                 }
06126                                 if (isset($pl['opt']['tu']) AND is_string($pl['opt']['tu'])) {
06127                                     $annots .= ' /TU '.$this->_datastring($pl['opt']['tu']);
06128                                 }
06129                                 if (isset($pl['opt']['tm']) AND is_string($pl['opt']['tm'])) {
06130                                     $annots .= ' /TM '.$this->_datastring($pl['opt']['tm']);
06131                                 }
06132                                 if (isset($pl['opt']['ff'])) {
06133                                     if (is_array($pl['opt']['ff'])) {
06134                                         
06135                                         $flag = 0;
06136                                         foreach($pl['opt']['ff'] as $val) {
06137                                             $flag += 1 << ($val - 1);
06138                                         }
06139                                     } else {
06140                                         $flag = intval($pl['opt']['ff']);
06141                                     }
06142                                     $annots .= ' /Ff '.$flag;
06143                                 }
06144                                 if (isset($pl['opt']['maxlen'])) {
06145                                     $annots .= ' /MaxLen '.intval($pl['opt']['maxlen']);
06146                                 }
06147                                 if (isset($pl['opt']['v'])) {
06148                                     $annots .= ' /V';
06149                                     if (is_array($pl['opt']['v'])) {
06150                                         foreach ($pl['opt']['v'] AS $optval) {
06151                                             $annots .= ' '.$optval;
06152                                         }
06153                                     } else {
06154                                         $annots .= ' '.$this->_textstring($pl['opt']['v']);
06155                                     }
06156                                 }
06157                                 if (isset($pl['opt']['dv']) AND is_string($pl['opt']['dv'])) {
06158                                     $annots .= ' /DV';
06159                                     if (is_array($pl['opt']['dv'])) {
06160                                         foreach ($pl['opt']['dv'] AS $optval) {
06161                                             $annots .= ' '.$optval;
06162                                         }
06163                                     } else {
06164                                         $annots .= ' '.$this->_textstring($pl['opt']['dv']);
06165                                     }
06166                                 }
06167                                 if (isset($pl['opt']['rv']) AND is_string($pl['opt']['rv'])) {
06168                                     $annots .= ' /RV';
06169                                     if (is_array($pl['opt']['rv'])) {
06170                                         foreach ($pl['opt']['rv'] AS $optval) {
06171                                             $annots .= ' '.$optval;
06172                                         }
06173                                     } else {
06174                                         $annots .= ' '.$this->_textstring($pl['opt']['rv']);
06175                                     }
06176                                 }
06177                                 if (isset($pl['opt']['a']) AND !empty($pl['opt']['a'])) {
06178                                     $annots .= ' /A << '.$pl['opt']['a'].' >>';
06179                                 }
06180                                 if (isset($pl['opt']['aa']) AND !empty($pl['opt']['aa'])) {
06181                                     $annots .= ' /AA << '.$pl['opt']['aa'].' >>';
06182                                 }
06183                                 if (isset($pl['opt']['da']) AND !empty($pl['opt']['da'])) {
06184                                     $annots .= ' /DA ('.$pl['opt']['da'].')';
06185                                 }
06186                                 if (isset($pl['opt']['q']) AND ($pl['opt']['q'] >= 0) AND ($pl['opt']['q'] <= 2)) {
06187                                     $annots .= ' /Q '.intval($pl['opt']['q']);
06188                                 }
06189                                 if (isset($pl['opt']['opt']) AND (is_array($pl['opt']['opt'])) AND !empty($pl['opt']['opt'])) {
06190                                     $annots .= ' /Opt [';
06191                                     foreach($pl['opt']['opt'] AS $copt) {
06192                                         if (is_array($copt)) {
06193                                             $annots .= ' ['.$this->_textstring($copt[0]).' '.$this->_textstring($copt[1]).']';
06194                                         } else {
06195                                             $annots .= ' '.$this->_textstring($copt);
06196                                         }
06197                                     }
06198                                     $annots .= ']';
06199                                 }
06200                                 if (isset($pl['opt']['ti'])) {
06201                                     $annots .= ' /TI '.intval($pl['opt']['ti']);
06202                                 }
06203                                 if (isset($pl['opt']['i']) AND (is_array($pl['opt']['i'])) AND !empty($pl['opt']['i'])) {
06204                                     $annots .= ' /I [';
06205                                     foreach($pl['opt']['i'] AS $copt) {
06206                                         $annots .= intval($copt).' ';
06207                                     }
06208                                     $annots .= ']';
06209                                 }
06210                                 break;
06211                             }
06212                             case 'screen': {
06213                                 break;
06214                             }
06215                             case 'printermark': {
06216                                 break;
06217                             }
06218                             case 'trapnet': {
06219                                 break;
06220                             }
06221                             case 'watermark': {
06222                                 break;
06223                             }
06224                             case '3d': {
06225                                 break;
06226                             }
06227                             default: {
06228                                 break;
06229                             }
06230                         }
06231                         $annots .= '>>';
06232                         
06233                         ++$this->annot_obj_id;
06234                         $this->offsets[$this->annot_obj_id] = $this->bufferlen;
06235                         $this->_out($this->annot_obj_id.' 0 obj');
06236                         $this->_out($annots);
06237                         $this->_out('endobj');
06238                         if ($formfield AND ! isset($this->radiobutton_groups[$n][$pl['txt']])) {
06239                             
06240                             $this->form_obj_id[] = $this->annot_obj_id;
06241                         }
06242                     }
06243                 }
06244             } 
06245         }
06246 
06256         protected function _putAPXObject($w=0, $h=0, $stream='') {
06257             $stream = trim($stream);
06258             ++$this->apxo_obj_id;
06259             $this->offsets[$this->apxo_obj_id] = $this->bufferlen;
06260             $this->_out($this->apxo_obj_id.' 0 obj');
06261             $this->_out('<<');
06262             $this->_out('/Type /XObject');
06263             $this->_out('/Subtype /Form');
06264             $this->_out('/FormType 1');
06265             if ($this->compress) {
06266                 $stream = gzcompress($stream);
06267                 $this->_out('/Filter /FlateDecode');
06268             }
06269             $rect = sprintf('%.2F %.2F', $w, $h);
06270             $this->_out('/BBox [0 0 '.$rect.']');
06271             $this->_out('/Matrix [1 0 0 1 0 0]');
06272             $this->_out('/Resources <</ProcSet [/PDF]>>');
06273             $this->_out('/Length '.strlen($stream));
06274             $this->_out('>>');
06275             $this->_putstream($stream);
06276             $this->_out('endobj');
06277             return $this->apxo_obj_id;
06278         }
06279 
06284         protected function _putfonts() {
06285             $nf = $this->n;
06286             foreach ($this->diffs as $diff) {
06287                 
06288                 $this->_newobj();
06289                 $this->_out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.']>>');
06290                 $this->_out('endobj');
06291             }
06292             $mqr = $this->get_mqr();
06293             $this->set_mqr(false);
06294             foreach ($this->FontFiles as $file => $info) {
06295                 
06296                 $fontdir = $info['fontdir'];
06297                 $file = strtolower($file);
06298                 $fontfile = '';
06299                 
06300                 if (file_exists($fontdir.$file)) {
06301                     $fontfile = $fontdir.$file;
06302                 } elseif (file_exists($this->_getfontpath().$file)) {
06303                     $fontfile = $this->_getfontpath().$file;
06304                 } elseif (file_exists($file)) {
06305                     $fontfile = $file;
06306                 }
06307                 if (!$this->empty_string($fontfile)) {
06308                     $font = file_get_contents($fontfile);
06309                     $compressed = (substr($file, -2) == '.z');
06310                     if ((!$compressed) AND (isset($info['length2']))) {
06311                         $header = (ord($font{0}) == 128);
06312                         if ($header) {
06313                             
06314                             $font = substr($font, 6);
06315                         }
06316                         if ($header AND (ord($font{$info['length1']}) == 128)) {
06317                             
06318                             $font = substr($font, 0, $info['length1']).substr($font, ($info['length1'] + 6));
06319                         }
06320                     }
06321                     $this->_newobj();
06322                     $this->FontFiles[$file]['n'] = $this->n;
06323                     $this->_out('<</Length '.strlen($font));
06324                     if ($compressed) {
06325                         $this->_out('/Filter /FlateDecode');
06326                     }
06327                     $this->_out('/Length1 '.$info['length1']);
06328                     if (isset($info['length2'])) {
06329                         $this->_out('/Length2 '.$info['length2'].' /Length3 0');
06330                     }
06331                     $this->_out('>>');
06332                     $this->_putstream($font);
06333                     $this->_out('endobj');
06334                 }
06335             }
06336             $this->set_mqr($mqr);
06337             foreach ($this->fontkeys as $k) {
06338                 
06339                 $this->setFontSubBuffer($k, 'n', $this->n + 1);
06340                 $font = $this->getFontBuffer($k);
06341                 $type = $font['type'];
06342                 $name = $font['name'];
06343                 if ($type == 'core') {
06344                     
06345                     $obj_id = $this->_newobj();
06346                     $this->_out('<</Type /Font');
06347                     $this->_out('/Subtype /Type1');
06348                     $this->_out('/BaseFont /'.$name);
06349                     $this->_out('/Name /F'.$font['i']);
06350                     if ((strtolower($name) != 'symbol') AND (strtolower($name) != 'zapfdingbats')) {
06351                         $this->_out('/Encoding /WinAnsiEncoding');
06352                     }
06353                     if (strtolower($name) == 'helvetica') {
06354                         
06355                         $this->annotation_fonts['helvetica'] = $k;
06356                     }
06357                     $this->_out('>>');
06358                     $this->_out('endobj');
06359                 } elseif (($type == 'Type1') OR ($type == 'TrueType')) {
06360                     
06361                     $obj_id = $this->_newobj();
06362                     $this->_out('<</Type /Font');
06363                     $this->_out('/Subtype /'.$type);
06364                     $this->_out('/BaseFont /'.$name);
06365                     $this->_out('/Name /F'.$font['i']);
06366                     $this->_out('/FirstChar 32 /LastChar 255');
06367                     $this->_out('/Widths '.($this->n + 1).' 0 R');
06368                     $this->_out('/FontDescriptor '.($this->n + 2).' 0 R');
06369                     if ($font['enc']) {
06370                         if (isset($font['diff'])) {
06371                             $this->_out('/Encoding '.($nf + $font['diff']).' 0 R');
06372                         } else {
06373                             $this->_out('/Encoding /WinAnsiEncoding');
06374                         }
06375                     }
06376                     $this->_out('>>');
06377                     $this->_out('endobj');
06378                     
06379                     $this->_newobj();
06380                     $cw = &$font['cw'];
06381                     $s = '[';
06382                     for ($i = 32; $i < 256; ++$i) {
06383                         $s .= $cw[$i].' ';
06384                     }
06385                     $this->_out($s.']');
06386                     $this->_out('endobj');
06387                     
06388                     $this->_newobj();
06389                     $s = '<</Type /FontDescriptor /FontName /'.$name;
06390                     foreach ($font['desc'] as $fdk => $fdv) {
06391                         $s .= ' /'.$fdk.' '.$fdv.'';
06392                     }
06393                     if (!$this->empty_string($font['file'])) {
06394                         $s .= ' /FontFile'.($type == 'Type1' ? '' : '2').' '.$this->FontFiles[$font['file']]['n'].' 0 R';
06395                     }
06396                     $this->_out($s.'>>');
06397                     $this->_out('endobj');
06398                 } else {
06399                     
06400                     $mtd = '_put'.strtolower($type);
06401                     if (!method_exists($this, $mtd)) {
06402                         $this->Error('Unsupported font type: '.$type);
06403                     }
06404                     $obj_id = $this->$mtd($font);
06405                 }
06406                 
06407                 $this->font_obj_ids[$k] = $obj_id;
06408             }
06409         }
06410         
06419         protected function _putfontwidths($font, $cidoffset=0) {
06420             ksort($font['cw']);
06421             $rangeid = 0;
06422             $range = array();
06423             $prevcid = -2;
06424             $prevwidth = -1;
06425             $interval = false;
06426             
06427             foreach ($font['cw'] as $cid => $width) {
06428                 $cid -= $cidoffset;
06429                 if ($width != $font['dw']) {
06430                     if ($cid == ($prevcid + 1)) {
06431                         
06432                         if ($width == $prevwidth) {
06433                             if ($width == $range[$rangeid][0]) {
06434                                 $range[$rangeid][] = $width;
06435                             } else {
06436                                 array_pop($range[$rangeid]);
06437                                 
06438                                 $rangeid = $prevcid;
06439                                 $range[$rangeid] = array();
06440                                 $range[$rangeid][] = $prevwidth;
06441                                 $range[$rangeid][] = $width;
06442                             }
06443                             $interval = true;
06444                             $range[$rangeid]['interval'] = true;
06445                         } else {
06446                             if ($interval) {
06447                                 
06448                                 $rangeid = $cid;
06449                                 $range[$rangeid] = array();
06450                                 $range[$rangeid][] = $width;
06451                             } else {
06452                                 $range[$rangeid][] = $width;
06453                             }
06454                             $interval = false;
06455                         }
06456                     } else {
06457                         
06458                         $rangeid = $cid;
06459                         $range[$rangeid] = array();
06460                         $range[$rangeid][] = $width;
06461                         $interval = false;
06462                     }
06463                     $prevcid = $cid;
06464                     $prevwidth = $width;
06465                 }
06466             }
06467             
06468             $prevk = -1;
06469             $nextk = -1;
06470             $prevint = false;
06471             foreach ($range as $k => $ws) {
06472                 $cws = count($ws);
06473                 if (($k == $nextk) AND (!$prevint) AND ((!isset($ws['interval'])) OR ($cws < 4))) {
06474                     if (isset($range[$k]['interval'])) {
06475                         unset($range[$k]['interval']);
06476                     }
06477                     $range[$prevk] = array_merge($range[$prevk], $range[$k]);
06478                     unset($range[$k]);
06479                 } else {
06480                     $prevk = $k;
06481                 }
06482                 $nextk = $k + $cws;
06483                 if (isset($ws['interval'])) {
06484                     if ($cws > 3) {
06485                         $prevint = true;
06486                     } else {
06487                         $prevint = false;
06488                     }
06489                     unset($range[$k]['interval']);
06490                     --$nextk;
06491                 } else {
06492                     $prevint = false;
06493                 }
06494             }
06495             
06496             $w = '';
06497             foreach ($range as $k => $ws) {
06498                 if (count(array_count_values($ws)) == 1) {
06499                     
06500                     $w .= ' '.$k.' '.($k + count($ws) - 1).' '.$ws[0];
06501                 } else {
06502                     
06503                     $w .= ' '.$k.' [ '.implode(' ', $ws).' ]';
06504                 }
06505             }
06506             $this->_out('/W ['.$w.' ]');
06507         }
06508         
06518         protected function _puttruetypeunicode($font) {
06519             
06520             
06521             $obj_id = $this->_newobj();
06522             $this->_out('<</Type /Font');
06523             $this->_out('/Subtype /Type0');
06524             $this->_out('/BaseFont /'.$font['name'].'');
06525             $this->_out('/Name /F'.$font['i']);
06526             $this->_out('/Encoding /'.$font['enc']);
06527             $this->_out('/ToUnicode /Identity-H');
06528             $this->_out('/DescendantFonts ['.($this->n + 1).' 0 R]');
06529             $this->_out('>>');
06530             $this->_out('endobj');
06531             
06532             
06533             $this->_newobj();
06534             $this->_out('<</Type /Font');
06535             $this->_out('/Subtype /CIDFontType2');
06536             $this->_out('/BaseFont /'.$font['name'].'');
06537             
06538             $cidinfo = '/Registry '.$this->_datastring($font['cidinfo']['Registry']);
06539             $cidinfo .= ' /Ordering '.$this->_datastring($font['cidinfo']['Ordering']);
06540             $cidinfo .= ' /Supplement '.$font['cidinfo']['Supplement'];
06541             $this->_out('/CIDSystemInfo <<'.$cidinfo.'>>');
06542             $this->_out('/FontDescriptor '.($this->n + 1).' 0 R');
06543             $this->_out('/DW '.$font['dw'].''); 
06544             $this->_putfontwidths($font, 0);
06545             $this->_out('/CIDToGIDMap '.($this->n + 2).' 0 R');
06546             $this->_out('>>');
06547             $this->_out('endobj');          
06548             
06549             
06550             $this->_newobj();
06551             $this->_out('<</Type /FontDescriptor');
06552             $this->_out('/FontName /'.$font['name']);
06553             foreach ($font['desc'] as $key => $value) {
06554                 $this->_out('/'.$key.' '.$value);
06555             }
06556             $fontdir = '';
06557             if (!$this->empty_string($font['file'])) {
06558                 
06559                 $this->_out('/FontFile2 '.$this->FontFiles[$font['file']]['n'].' 0 R');
06560                 $fontdir = $this->FontFiles[$font['file']]['fontdir'];
06561             }
06562             $this->_out('>>');
06563             $this->_out('endobj');
06564             $this->_newobj();
06565             if (isset($font['ctg']) AND (!$this->empty_string($font['ctg']))) {
06566                 
06567                 
06568                 
06569                 $ctgfile = strtolower($font['ctg']);
06570                 
06571                 $fontfile = '';
06572                 
06573                 if (file_exists($fontdir.$ctgfile)) {
06574                     $fontfile = $fontdir.$ctgfile;
06575                 } elseif (file_exists($this->_getfontpath().$ctgfile)) {
06576                     $fontfile = $this->_getfontpath().$ctgfile;
06577                 } elseif (file_exists($ctgfile)) {
06578                     $fontfile = $ctgfile;
06579                 }
06580                 if ($this->empty_string($fontfile)) {
06581                     $this->Error('Font file not found: '.$ctgfile);
06582                 }
06583                 $size = filesize($fontfile);
06584                 $this->_out('<</Length '.$size.'');
06585                 if (substr($fontfile, -2) == '.z') { 
06586                     
06587                     
06588                     
06589                     $this->_out('/Filter /FlateDecode');
06590                 }
06591                 $this->_out('>>');
06592                 $this->_putstream(file_get_contents($fontfile));
06593             }
06594             $this->_out('endobj');
06595             return $obj_id;
06596         }
06597         
06607         protected function _putcidfont0($font) {
06608             $cidoffset = 0;
06609             if (!isset($font['cw'][1])) {
06610                 $cidoffset = 31;
06611             }
06612             if (isset($font['cidinfo']['uni2cid'])) {
06613                 
06614                 $uni2cid = $font['cidinfo']['uni2cid'];
06615                 $cw = array();
06616                 foreach ($font['cw'] as $uni => $width) {
06617                     if (isset($uni2cid[$uni])) {
06618                         $cw[($uni2cid[$uni] + $cidoffset)] = $width;
06619                     } elseif ($uni < 256) {
06620                         $cw[$uni] = $width;
06621                     } 
06622                 }
06623                 $font = array_merge($font, array('cw' => $cw));
06624             }
06625             $name = $font['name'];
06626             $enc = $font['enc'];
06627             if ($enc) {
06628                 $longname = $name.'-'.$enc;
06629             } else {
06630                 $longname = $name;
06631             }
06632             $obj_id = $this->_newobj();
06633             $this->_out('<</Type /Font');
06634             $this->_out('/Subtype /Type0');
06635             $this->_out('/BaseFont /'.$longname);
06636             $this->_out('/Name /F'.$font['i']);
06637             if ($enc) {
06638                 $this->_out('/Encoding /'.$enc);
06639             }
06640             $this->_out('/DescendantFonts ['.($this->n + 1).' 0 R]');
06641             $this->_out('>>');
06642             $this->_out('endobj');
06643             $this->_newobj();
06644             $this->_out('<</Type /Font');
06645             $this->_out('/Subtype /CIDFontType0');
06646             $this->_out('/BaseFont /'.$name);
06647             $cidinfo = '/Registry '.$this->_datastring($font['cidinfo']['Registry']);
06648             $cidinfo .= ' /Ordering '.$this->_datastring($font['cidinfo']['Ordering']);
06649             $cidinfo .= ' /Supplement '.$font['cidinfo']['Supplement'];
06650             $this->_out('/CIDSystemInfo <<'.$cidinfo.'>>');
06651             $this->_out('/FontDescriptor '.($this->n + 1).' 0 R');
06652             $this->_out('/DW '.$font['dw']);
06653             $this->_putfontwidths($font, $cidoffset);
06654             $this->_out('>>');
06655             $this->_out('endobj');
06656             $this->_newobj();
06657             $s = '<</Type /FontDescriptor /FontName /'.$name;
06658             foreach ($font['desc'] as $k => $v) {
06659                 if ($k != 'Style') {
06660                     $s .= ' /'.$k.' '.$v.'';
06661                 }
06662             }
06663             $this->_out($s.'>>');
06664             $this->_out('endobj');
06665             return $obj_id;
06666         }
06667 
06672         protected function _putimages() {
06673             $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
06674             foreach ($this->imagekeys as $file) {
06675                 $info = $this->getImageBuffer($file);
06676                 $this->_newobj();
06677                 $this->setImageSubBuffer($file, 'n', $this->n);
06678                 $this->_out('<</Type /XObject');
06679                 $this->_out('/Subtype /Image');
06680                 $this->_out('/Width '.$info['w']);
06681                 $this->_out('/Height '.$info['h']);
06682                 if (isset($info['masked'])) {
06683                     $this->_out('/SMask '.($this->n - 1).' 0 R');
06684                 }
06685                 if ($info['cs'] == 'Indexed') {
06686                     $this->_out('/ColorSpace [/Indexed /DeviceRGB '.((strlen($info['pal']) / 3) - 1).' '.($this->n + 1).' 0 R]');
06687                 } else {
06688                     $this->_out('/ColorSpace /'.$info['cs']);
06689                     if ($info['cs'] == 'DeviceCMYK') {
06690                         $this->_out('/Decode [1 0 1 0 1 0 1 0]');
06691                     }
06692                 }
06693                 $this->_out('/BitsPerComponent '.$info['bpc']);
06694                 if (isset($info['f'])) {
06695                     $this->_out('/Filter /'.$info['f']);
06696                 }
06697                 if (isset($info['parms'])) {
06698                     $this->_out($info['parms']);
06699                 }
06700                 if (isset($info['trns']) AND is_array($info['trns'])) {
06701                     $trns='';
06702                     $count_info = count($info['trns']);
06703                     for ($i=0; $i < $count_info; ++$i) {
06704                         $trns .= $info['trns'][$i].' '.$info['trns'][$i].' ';
06705                     }
06706                     $this->_out('/Mask ['.$trns.']');
06707                 }
06708                 $this->_out('/Length '.strlen($info['data']).'>>');
06709                 $this->_putstream($info['data']);
06710                 $this->_out('endobj');
06711                 
06712                 if ($info['cs'] == 'Indexed') {
06713                     $this->_newobj();
06714                     $pal = ($this->compress) ? gzcompress($info['pal']) : $info['pal'];
06715                     $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
06716                     $this->_putstream($pal);
06717                     $this->_out('endobj');
06718                 }
06719             }
06720         }
06721 
06727         protected function _putspotcolors() {
06728             foreach ($this->spot_colors as $name => $color) {
06729                 $this->_newobj();
06730                 $this->spot_colors[$name]['n'] = $this->n;
06731                 $this->_out('[/Separation /'.str_replace(' ', '#20', $name));
06732                 $this->_out('/DeviceCMYK <<');
06733                 $this->_out('/Range [0 1 0 1 0 1 0 1] /C0 [0 0 0 0] ');
06734                 $this->_out(sprintf('/C1 [%.4F %.4F %.4F %.4F] ', $color['c']/100, $color['m']/100, $color['y']/100, $color['k']/100));
06735                 $this->_out('/FunctionType 2 /Domain [0 1] /N 1>>]');
06736                 $this->_out('endobj');
06737             }
06738         }
06739 
06744         protected function _putxobjectdict() {
06745             foreach ($this->imagekeys as $file) {
06746                 $info = $this->getImageBuffer($file);
06747                 $this->_out('/I'.$info['i'].' '.$info['n'].' 0 R');
06748             }
06749         }
06750 
06755         protected function _putresourcedict() {
06756             $this->_out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
06757             $this->_out('/Font <<');
06758             foreach ($this->fontkeys as $fontkey) {
06759                 $font = $this->getFontBuffer($fontkey);
06760                 $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R');
06761             }
06762             $this->_out('>>');
06763             $this->_out('/XObject <<');
06764             $this->_putxobjectdict();
06765             $this->_out('>>');
06766             
06767             $this->_out('/Properties <</OC1 '.$this->n_ocg_print.' 0 R /OC2 '.$this->n_ocg_view.' 0 R>>');
06768             
06769             $this->_out('/ExtGState <<');
06770             foreach ($this->extgstates as $k => $extgstate) {
06771                 $this->_out('/GS'.$k.' '.$extgstate['n'].' 0 R');
06772             }
06773             $this->_out('>>');
06774             
06775             if (isset($this->gradients) AND (count($this->gradients) > 0)) {
06776                 $this->_out('/Shading <<');
06777                 foreach ($this->gradients as $id => $grad) {
06778                     $this->_out('/Sh'.$id.' '.$grad['id'].' 0 R');
06779                 }
06780                 $this->_out('>>');
06781             }
06782             
06783             if (isset($this->spot_colors) AND (count($this->spot_colors) > 0)) {
06784                 $this->_out('/ColorSpace <<');
06785                 foreach ($this->spot_colors as $color) {
06786                     $this->_out('/CS'.$color['i'].' '.$color['n'].' 0 R');
06787                 }
06788                 $this->_out('>>');
06789             }
06790         }
06791         
06796         protected function _putresources() {
06797             $this->_putextgstates();
06798             $this->_putocg();
06799             $this->_putfonts();
06800             $this->_putimages();
06801             $this->_putspotcolors();
06802             $this->_putshaders();
06803             
06804             $this->offsets[2] = $this->bufferlen;
06805             $this->_out('2 0 obj');
06806             $this->_out('<<');
06807             $this->_putresourcedict();
06808             $this->_out('>>');
06809             $this->_out('endobj');
06810             $this->_putbookmarks();
06811             $this->_putEmbeddedFiles();
06812             $this->_putannotsobjs();
06813             $this->_putjavascript();
06814             
06815             if ($this->encrypted) {
06816                 $this->_newobj();
06817                 $this->enc_obj_id = $this->n;
06818                 $this->_out('<<');
06819                 $this->_putencryption();
06820                 $this->_out('>>');
06821                 $this->_out('endobj');
06822             }
06823         }
06824         
06830         protected function _putinfo() {
06831             if ($this->empty_string($this->title)) {
06832                 $this->title = '?';
06833             }
06834             $this->_out('/Title '.$this->_textstring($this->title));
06835             if ($this->empty_string($this->author)) {
06836                 $this->author = '?';
06837             }
06838             $this->_out('/Author '.$this->_textstring($this->author));
06839             if ($this->empty_string($this->subject)) {
06840                 $this->subject = '?';
06841             }
06842             $this->_out('/Subject '.$this->_textstring($this->subject));
06843             if ($this->empty_string($this->keywords)) {
06844                 $this->keywords = '?';
06845             }
06846             $this->_out('/Keywords '.$this->_textstring($this->keywords));
06847             if ($this->empty_string($this->creator)) {
06848                 $this->creator = '?';
06849             }
06850             $this->_out('/Creator '.$this->_textstring($this->creator));
06851             if (defined('PDF_PRODUCER')) {
06852                 $this->_out('/Producer '.$this->_textstring(PDF_PRODUCER));
06853             } else {
06854                 $this->_out('/Producer '.$this->_textstring('TCPDF'));
06855             }
06856             $this->_out('/CreationDate '.$this->_datestring());
06857             $this->_out('/ModDate '.$this->_datestring());  
06858         }
06859         
06864         protected function _putcatalog() {
06865             $this->_out('/Type /Catalog');
06866             $this->_out('/Pages 1 0 R');
06867             if ($this->ZoomMode == 'fullpage') {
06868                 $this->_out('/OpenAction [3 0 R /Fit]');
06869             } elseif ($this->ZoomMode == 'fullwidth') {
06870                 $this->_out('/OpenAction [3 0 R /FitH null]');
06871             } elseif ($this->ZoomMode == 'real') {
06872                 $this->_out('/OpenAction [3 0 R /XYZ null null 1]');
06873             } elseif (!is_string($this->ZoomMode)) {
06874                 $this->_out('/OpenAction [3 0 R /XYZ null null '.($this->ZoomMode / 100).']');
06875             }           
06876             if (isset($this->LayoutMode) AND (!$this->empty_string($this->LayoutMode))) {
06877                 $this->_out('/PageLayout /'.$this->LayoutMode.'');
06878             }
06879             if (isset($this->PageMode) AND (!$this->empty_string($this->PageMode))) {
06880                 $this->_out('/PageMode /'.$this->PageMode);
06881             }
06882             if (isset($this->l['a_meta_language'])) {
06883                 $this->_out('/Lang /'.$this->l['a_meta_language']);
06884             }
06885             $this->_out('/Names <<');
06886             if ((!empty($this->javascript)) OR (!empty($this->js_objects))) {
06887                 $this->_out('/JavaScript '.($this->n_js).' 0 R');
06888             }
06889             $this->_out('>>');          
06890             if (count($this->outlines) > 0) {
06891                 $this->_out('/Outlines '.$this->OutlineRoot.' 0 R');
06892                 $this->_out('/PageMode /UseOutlines');
06893             }
06894             $this->_putviewerpreferences();
06895             $p = $this->n_ocg_print.' 0 R';
06896             $v = $this->n_ocg_view.' 0 R';
06897             $as = '<</Event /Print /OCGs ['.$p.' '.$v.'] /Category [/Print]>> <</Event /View /OCGs ['.$p.' '.$v.'] /Category [/View]>>';
06898             $this->_out('/OCProperties <</OCGs ['.$p.' '.$v.'] /D <</ON ['.$p.'] /OFF ['.$v.'] /AS ['.$as.']>>>>');
06899             
06900             if (!empty($this->form_obj_id) OR ($this->sign AND isset($this->signature_data['cert_type']))) {
06901                 $this->_out('/AcroForm<<');
06902                 $objrefs = '';
06903                 if ($this->sign AND isset($this->signature_data['cert_type'])) {
06904                     $objrefs .= $this->sig_obj_id.' 0 R';
06905                 }
06906                 if (!empty($this->form_obj_id)) {
06907                     foreach($this->form_obj_id as $objid) {
06908                         $objrefs .= ' '.$objid.' 0 R';
06909                     }
06910                 }
06911                 $this->_out('/Fields ['.$objrefs.']');
06912                 $this->_out('/NeedAppearances '.(empty($this->form_obj_id)?'false':'true'));
06913                 if ($this->sign AND isset($this->signature_data['cert_type'])) {
06914                     $this->_out('/SigFlags 3');
06915                 }
06916                 
06917                 if (isset($this->annotation_fonts) AND !empty($this->annotation_fonts)) {
06918                     $this->_out('/DR <<');
06919                     $this->_out('/Font <<');
06920                     foreach ($this->annotation_fonts as $font => $fontkey) {
06921                         $this->_out('/F'.($fontkey + 1).' '.$this->font_obj_ids[$font].' 0 R');
06922                     }
06923                     $this->_out('>>');
06924                     $this->_out('>>');
06925                 }
06926                 $this->_out('/DA (/F'.(array_search('helvetica', $this->fontkeys) + 1).' 0 Tf 0 g)');
06927                 $this->_out('/Q '.(($this->rtl)?'2':'0'));
06928                 
06929                 $this->_out('>>');
06930                 
06931                 if ($this->sign AND isset($this->signature_data['cert_type'])) {
06932                     if ($this->signature_data['cert_type'] > 0) {
06933                         $this->_out('/Perms<</DocMDP '.($this->sig_obj_id + 1).' 0 R>>');
06934                     } else {
06935                         $this->_out('/Perms<</UR3 '.($this->sig_obj_id + 1).' 0 R>>');
06936                     }
06937                 }
06938             }
06939         }
06940         
06947         protected function _putviewerpreferences() {
06948             $this->_out('/ViewerPreferences<<');
06949             if ($this->rtl) {
06950                 $this->_out('/Direction /R2L');
06951             } else {
06952                 $this->_out('/Direction /L2R');
06953             }
06954             if (isset($this->viewer_preferences['HideToolbar']) AND ($this->viewer_preferences['HideToolbar'])) {
06955                 $this->_out('/HideToolbar true');
06956             }
06957             if (isset($this->viewer_preferences['HideMenubar']) AND ($this->viewer_preferences['HideMenubar'])) {
06958                 $this->_out('/HideMenubar true');
06959             }
06960             if (isset($this->viewer_preferences['HideWindowUI']) AND ($this->viewer_preferences['HideWindowUI'])) {
06961                 $this->_out('/HideWindowUI true');
06962             }
06963             if (isset($this->viewer_preferences['FitWindow']) AND ($this->viewer_preferences['FitWindow'])) {
06964                 $this->_out('/FitWindow true');
06965             }
06966             if (isset($this->viewer_preferences['CenterWindow']) AND ($this->viewer_preferences['CenterWindow'])) {
06967                 $this->_out('/CenterWindow true');
06968             }
06969             if (isset($this->viewer_preferences['DisplayDocTitle']) AND ($this->viewer_preferences['DisplayDocTitle'])) {
06970                 $this->_out('/DisplayDocTitle true');
06971             }
06972             if (isset($this->viewer_preferences['NonFullScreenPageMode'])) {
06973                 $this->_out('/NonFullScreenPageMode /'.$this->viewer_preferences['NonFullScreenPageMode'].'');
06974             }
06975             if (isset($this->viewer_preferences['ViewArea'])) {
06976                 $this->_out('/ViewArea /'.$this->viewer_preferences['ViewArea']);
06977             }
06978             if (isset($this->viewer_preferences['ViewClip'])) {
06979                 $this->_out('/ViewClip /'.$this->viewer_preferences['ViewClip']);
06980             }
06981             if (isset($this->viewer_preferences['PrintArea'])) {
06982                 $this->_out('/PrintArea /'.$this->viewer_preferences['PrintArea']);
06983             }
06984             if (isset($this->viewer_preferences['PrintClip'])) {
06985                 $this->_out('/PrintClip /'.$this->viewer_preferences['PrintClip']);
06986             }
06987             if (isset($this->viewer_preferences['PrintScaling'])) {
06988                 $this->_out('/PrintScaling /'.$this->viewer_preferences['PrintScaling']);
06989             }
06990             if (isset($this->viewer_preferences['Duplex']) AND (!$this->empty_string($this->viewer_preferences['Duplex']))) {
06991                 $this->_out('/Duplex /'.$this->viewer_preferences['Duplex']);
06992             }
06993             if (isset($this->viewer_preferences['PickTrayByPDFSize'])) {
06994                 if ($this->viewer_preferences['PickTrayByPDFSize']) {
06995                     $this->_out('/PickTrayByPDFSize true');
06996                 } else {
06997                     $this->_out('/PickTrayByPDFSize false');
06998                 }
06999             }
07000             if (isset($this->viewer_preferences['PrintPageRange'])) {
07001                 $PrintPageRangeNum = '';
07002                 foreach ($this->viewer_preferences['PrintPageRange'] as $k => $v) {
07003                     $PrintPageRangeNum .= ' '.($v - 1).'';
07004                 }
07005                 $this->_out('/PrintPageRange ['.substr($PrintPageRangeNum,1).']');
07006             }
07007             if (isset($this->viewer_preferences['NumCopies'])) {
07008                 $this->_out('/NumCopies '.intval($this->viewer_preferences['NumCopies']));
07009             }
07010             $this->_out('>>');
07011         }
07012         
07017         protected function _puttrailer() {
07018             $this->_out('/Size '.($this->n + 1));
07019             $this->_out('/Root '.$this->n.' 0 R');
07020             $this->_out('/Info '.($this->n - 1).' 0 R');
07021             if ($this->encrypted) {
07022                 $this->_out('/Encrypt '.$this->enc_obj_id.' 0 R');
07023                 $this->_out('/ID [()()]');
07024             }
07025         }
07026 
07031         protected function _putheader() {
07032             $this->_out('%PDF-'.$this->PDFVersion);
07033         }
07034 
07039         protected function _enddoc() {
07040             $this->state = 1;
07041             $this->_putheader();            
07042             $this->_putpages();
07043             $this->_putresources();
07044             
07045             if ($this->sign AND isset($this->signature_data['cert_type'])) {
07046                 
07047                 $this->sig_obj_id = $this->_newobj();
07048                 
07049                 
07050                 $pdfdoc = $this->getBuffer();
07051                 
07052                 if (isset($this->diskcache) AND $this->diskcache) {
07053                     
07054                     unlink($this->buffer);
07055                 }
07056                 unset($this->buffer);
07057                 $signature_widget_ref = sprintf('%u 0 R', $this->sig_obj_id);
07058                 $signature_widget_ref .= str_repeat(' ', (strlen($this->sig_annot_ref) - strlen($signature_widget_ref)));
07059                 $pdfdoc = str_replace($this->sig_annot_ref, $signature_widget_ref, $pdfdoc);
07060                 $this->diskcache = false;
07061                 $this->buffer = &$pdfdoc;
07062                 $this->bufferlen = strlen($pdfdoc);
07063                 
07064                 $this->_out('<<');
07065                 $this->_out('/Type /Annot /Subtype /Widget /Rect [0 0 0 0]');
07066                 $this->_out('/P 3 0 R'); 
07067                 $this->_out('/FT /Sig');
07068                 $this->_out('/T '.$this->_textstring('Signature'));
07069                 $this->_out('/Ff 0');
07070                 $this->_out('/V '.($this->sig_obj_id + 1).' 0 R');
07071                 $this->_out('>>');
07072                 $this->_out('endobj');
07073                 
07074                 $this->_newobj();
07075                 $this->_out('<<');
07076                 $this->_putsignature();
07077                 $this->_out('>>');
07078                 $this->_out('endobj');
07079             }
07080             
07081             $this->_newobj();
07082             $this->_out('<<');
07083             $this->_putinfo();
07084             $this->_out('>>');
07085             $this->_out('endobj');
07086             
07087             $this->_newobj();
07088             $this->_out('<<');
07089             $this->_putcatalog();
07090             $this->_out('>>');
07091             $this->_out('endobj');
07092             
07093             $o = $this->bufferlen;
07094             $this->_out('xref');
07095             $this->_out('0 '.($this->n + 1));
07096             $this->_out('0000000000 65535 f ');
07097             for ($i=1; $i <= $this->n; ++$i) {
07098                 $this->_out(sprintf('%010d 00000 n ', $this->offsets[$i]));
07099             }
07100             
07101             if (isset($this->embeddedfiles) AND count($this->embeddedfiles) > 0) {
07102                 $this->_out($this->embedded_start_obj_id.' '.count($this->embeddedfiles));
07103                 foreach ($this->embeddedfiles as $filename => $filedata) {
07104                     $this->_out(sprintf('%010d 00000 n ', $this->offsets[$filedata['n']]));
07105                 }
07106             }
07107             
07108             if ($this->annot_obj_id > $this->annots_start_obj_id) {
07109                 $this->_out(($this->annots_start_obj_id + 1).' '.($this->annot_obj_id - $this->annots_start_obj_id));
07110                 for ($i = ($this->annots_start_obj_id + 1); $i <= $this->annot_obj_id; ++$i) {
07111                     $this->_out(sprintf('%010d 00000 n ', $this->offsets[$i]));
07112                 }
07113             }
07114             
07115             if ($this->js_obj_id > $this->js_start_obj_id) {
07116                 $this->_out(($this->js_start_obj_id + 1).' '.($this->js_obj_id - $this->js_start_obj_id));
07117                 for ($i = ($this->js_start_obj_id + 1); $i <= $this->js_obj_id; ++$i) {
07118                     $this->_out(sprintf('%010d 00000 n ', $this->offsets[$i]));
07119                 }
07120             }
07121             
07122             if ($this->apxo_obj_id > $this->apxo_start_obj_id) {
07123                 $this->_out(($this->apxo_start_obj_id + 1).' '.($this->apxo_obj_id - $this->apxo_start_obj_id));
07124                 for ($i = ($this->apxo_start_obj_id + 1); $i <= $this->apxo_obj_id; ++$i) {
07125                     $this->_out(sprintf('%010d 00000 n ', $this->offsets[$i]));
07126                 }
07127             }
07128             
07129             $this->_out('trailer');
07130             $this->_out('<<');
07131             $this->_puttrailer();
07132             $this->_out('>>');
07133             $this->_out('startxref');
07134             $this->_out($o);
07135             $this->_out('%%EOF');
07136             $this->state = 3; 
07137             if ($this->diskcache) {
07138                 
07139                 foreach ($this->imagekeys as $key) {
07140                     
07141                     unlink($this->images[$key]);
07142                 }
07143                 foreach ($this->fontkeys as $key) {
07144                     
07145                     unlink($this->fonts[$key]);
07146                 }
07147             }
07148         }
07149 
07156         protected function _beginpage($orientation='', $format='') {
07157             ++$this->page;
07158             $this->setPageBuffer($this->page, '');
07159             
07160             $this->transfmrk[$this->page] = array();
07161             $this->state = 2;
07162             if ($this->empty_string($orientation)) {
07163                 if (isset($this->CurOrientation)) {
07164                     $orientation = $this->CurOrientation;
07165                 } else {
07166                     $orientation = 'P';
07167                 }
07168             }
07169             if ($this->empty_string($format)) {
07170                 $this->setPageOrientation($orientation);
07171             } else {
07172                 $this->setPageFormat($format, $orientation);
07173             }
07174             if ($this->rtl) {
07175                 $this->x = $this->w - $this->rMargin;
07176             } else {
07177                 $this->x = $this->lMargin;
07178             }
07179             $this->y = $this->tMargin;
07180             if (isset($this->newpagegroup[$this->page])) {
07181                 
07182                 $n = sizeof($this->pagegroups) + 1;
07183                 $alias = '{nb'.$n.'}';
07184                 $this->pagegroups[$alias] = 1;
07185                 $this->currpagegroup = $alias;
07186             } elseif ($this->currpagegroup) {
07187                 ++$this->pagegroups[$this->currpagegroup];
07188             }
07189         }
07190 
07195         protected function _endpage() {
07196             $this->setVisibility('all');
07197             $this->state = 1;
07198         }
07199 
07205         protected function _newobj() {
07206             ++$this->n;
07207             $this->offsets[$this->n] = $this->bufferlen;
07208             $this->_out($this->n.' 0 obj');
07209             return $this->n;
07210         }
07211 
07219         protected function _dounderline($x, $y, $txt) {
07220             $up = $this->CurrentFont['up'];
07221             $ut = $this->CurrentFont['ut'];
07222             $w = $this->GetStringWidth($txt);
07223             return sprintf('%.2F %.2F %.2F %.2F re f', $x * $this->k, ($this->h - ($y - $up / 1000 * $this->FontSize)) * $this->k, $w * $this->k, -$ut / 1000 * $this->FontSizePt);
07224         }
07225         
07233         protected function _dolinethrough($x, $y, $txt) {
07234             $up = $this->CurrentFont['up'];
07235             $ut = $this->CurrentFont['ut'];
07236             $w = $this->GetStringWidth($txt);
07237             return sprintf('%.2F %.2F %.2F %.2F re f', $x * $this->k, ($this->h - ($y - ($this->FontSize/2) - $up / 1000 * $this->FontSize)) * $this->k, $w * $this->k, -$ut / 1000 * $this->FontSizePt);
07238         }
07239         
07246         protected function _freadint($f) {
07247             $a = unpack('Ni', fread($f, 4));
07248             return $a['i'];
07249         }
07250         
07257         protected function _escape($s) {
07258             
07259             return strtr($s, array(')' => '\\)', '(' => '\\(', '\\' => '\\\\', chr(13) => '\r'));
07260         }
07261         
07268         protected function _datastring($s) {
07269             if ($this->encrypted) {
07270                 $s = $this->_RC4($this->_objectkey($this->n), $s);
07271             }
07272             return '('. $this->_escape($s).')';
07273         }
07274 
07281         protected function _datestring() {
07282             $current_time = substr_replace(date('YmdHisO'), '\'', (0 - 2), 0).'\'';
07283             return $this->_datastring('D:'.$current_time);
07284         }
07285 
07292         protected function _textstring($s) {
07293             if ($this->isunicode) {
07294                 
07295                 $s = $this->UTF8ToUTF16BE($s, true);
07296             }
07297             return $this->_datastring($s);
07298         }
07299                 
07306         protected function _escapetext($s) {
07307             if ($this->isunicode) {
07308                 if (($this->CurrentFont['type'] == 'core') OR ($this->CurrentFont['type'] == 'TrueType') OR ($this->CurrentFont['type'] == 'Type1')) {
07309                     $s = $this->UTF8ToLatin1($s);
07310                 } else {
07311                     
07312                     $s = $this->utf8StrRev($s, false, $this->tmprtl);
07313                 }
07314             }
07315             return $this->_escape($s);
07316         }
07317         
07323         protected function _putstream($s) {
07324             if ($this->encrypted) {
07325                 $s = $this->_RC4($this->_objectkey($this->n), $s);
07326             }
07327             $this->_out('stream');
07328             $this->_out($s);
07329             $this->_out('endstream');
07330         }
07331         
07337         protected function _out($s) {
07338             if ($this->state == 2) {
07339                 if ((!$this->InFooter) AND isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) {
07340                     
07341                     $pagebuff = $this->getPageBuffer($this->page);
07342                     $page = substr($pagebuff, 0, -$this->footerlen[$this->page]);
07343                     $footer = substr($pagebuff, -$this->footerlen[$this->page]);
07344                     $this->setPageBuffer($this->page, $page.$s."\n".$footer);
07345                     
07346                     $this->footerpos[$this->page] += strlen($s."\n");   
07347                 } else {
07348                     $this->setPageBuffer($this->page, $s."\n", true);
07349                 }
07350             } else {
07351                 $this->setBuffer($s."\n");
07352             }
07353         }
07354         
07389         protected function UTF8StringToArray($str) {
07390             if (isset($this->cache_UTF8StringToArray['_'.$str])) {
07391                 
07392                 return($this->cache_UTF8StringToArray['_'.$str]);
07393             }
07394             
07395             if ($this->cache_size_UTF8StringToArray >= $this->cache_maxsize_UTF8StringToArray) {
07396                 
07397                 array_shift($this->cache_UTF8StringToArray);
07398             }
07399             ++$this->cache_size_UTF8StringToArray;
07400             if (!$this->isunicode) {
07401                 
07402                 $strarr = array();
07403                 $strlen = strlen($str);
07404                 for ($i=0; $i < $strlen; ++$i) {
07405                     $strarr[] = ord($str{$i});
07406                 }
07407                 
07408                 $this->cache_UTF8StringToArray['_'.$str] = $strarr;
07409                 return $strarr;
07410             }
07411             $unicode = array(); 
07412             $bytes  = array(); 
07413             $numbytes  = 1; 
07414             $str .= ''; 
07415             $length = strlen($str);
07416             for ($i = 0; $i < $length; ++$i) {
07417                 $char = ord($str{$i}); 
07418                 if (count($bytes) == 0) { 
07419                     if ($char <= 0x7F) {
07420                         $unicode[] = $char; 
07421                         $numbytes = 1;
07422                     } elseif (($char >> 0x05) == 0x06) { 
07423                         $bytes[] = ($char - 0xC0) << 0x06; 
07424                         $numbytes = 2;
07425                     } elseif (($char >> 0x04) == 0x0E) { 
07426                         $bytes[] = ($char - 0xE0) << 0x0C; 
07427                         $numbytes = 3;
07428                     } elseif (($char >> 0x03) == 0x1E) { 
07429                         $bytes[] = ($char - 0xF0) << 0x12; 
07430                         $numbytes = 4;
07431                     } else {
07432                         
07433                         $unicode[] = 0xFFFD;
07434                         $bytes = array();
07435                         $numbytes = 1;
07436                     }
07437                 } elseif (($char >> 0x06) == 0x02) { 
07438                     $bytes[] = $char - 0x80;
07439                     if (count($bytes) == $numbytes) {
07440                         
07441                         $char = $bytes[0];
07442                         for ($j = 1; $j < $numbytes; ++$j) {
07443                             $char += ($bytes[$j] << (($numbytes - $j - 1) * 0x06));
07444                         }
07445                         if ((($char >= 0xD800) AND ($char <= 0xDFFF)) OR ($char >= 0x10FFFF)) {
07446                             
07447 
07448 
07449 
07450                             $unicode[] = 0xFFFD; 
07451                         } else {
07452                             $unicode[] = $char; 
07453                         }
07454                         
07455                         $bytes = array(); 
07456                         $numbytes = 1;
07457                     }
07458                 } else {
07459                     
07460                     $unicode[] = 0xFFFD;
07461                     $bytes = array();
07462                     $numbytes = 1;
07463                 }
07464             }
07465             
07466             $this->cache_UTF8StringToArray['_'.$str] = $unicode;
07467             return $unicode;
07468         }
07469         
07480         protected function UTF8ToUTF16BE($str, $setbom=true) {
07481             if (!$this->isunicode) {
07482                 return $str; 
07483             }
07484             $unicode = $this->UTF8StringToArray($str); 
07485             return $this->arrUTF8ToUTF16BE($unicode, $setbom);
07486         }
07487         
07496         protected function UTF8ToLatin1($str) {
07497             global $utf8tolatin;
07498             if (!$this->isunicode) {
07499                 return $str; 
07500             }
07501             $outstr = ''; 
07502             $unicode = $this->UTF8StringToArray($str); 
07503             foreach ($unicode as $char) {
07504                 if ($char < 256) {
07505                     $outstr .= chr($char);
07506                 } elseif (array_key_exists($char, $utf8tolatin)) {
07507                     
07508                     $outstr .= chr($utf8tolatin[$char]);
07509                 } elseif ($char == 0xFFFD) {
07510                     
07511                 } else {
07512                     $outstr .= '?';
07513                 }
07514             }
07515             return $outstr;
07516         }
07517 
07556         protected function arrUTF8ToUTF16BE($unicode, $setbom=true) {
07557             $outstr = ''; 
07558             if ($setbom) {
07559                 $outstr .= "\xFE\xFF"; 
07560             }
07561             foreach ($unicode as $char) {
07562                 if ($char == 0xFFFD) {
07563                     $outstr .= "\xFF\xFD"; 
07564                 } elseif ($char < 0x10000) {
07565                     $outstr .= chr($char >> 0x08);
07566                     $outstr .= chr($char & 0xFF);
07567                 } else {
07568                     $char -= 0x10000;
07569                     $w1 = 0xD800 | ($char >> 0x10);
07570                     $w2 = 0xDC00 | ($char & 0x3FF); 
07571                     $outstr .= chr($w1 >> 0x08);
07572                     $outstr .= chr($w1 & 0xFF);
07573                     $outstr .= chr($w2 >> 0x08);
07574                     $outstr .= chr($w2 & 0xFF);
07575                 }
07576             }
07577             return $outstr;
07578         }
07579         
07580         
07587         public function setHeaderFont($font) {
07588             $this->header_font = $font;
07589         }
07590         
07597         public function getHeaderFont() {
07598             return $this->header_font;
07599         }
07600         
07607         public function setFooterFont($font) {
07608             $this->footer_font = $font;
07609         }
07610         
07617         public function getFooterFont() {
07618             return $this->footer_font;
07619         }
07620         
07627         public function setLanguageArray($language) {
07628             $this->l = $language;
07629             if (isset($this->l['a_meta_dir'])) {
07630                 $this->rtl = $this->l['a_meta_dir']=='rtl' ? true : false;
07631             } else {
07632                 $this->rtl = false;
07633             }
07634         }
07635         
07640         public function getPDFData() {
07641             if ($this->state < 3) {
07642                 $this->Close();
07643             }
07644             return $this->buffer;
07645         }
07646                 
07658         public function addHtmlLink($url, $name, $fill=0, $firstline=false, $color='', $style=-1) {
07659             if (!$this->empty_string($url) AND ($url{0} == '#')) {
07660                 
07661                 $page = intval(substr($url, 1));
07662                 $url = $this->AddLink();
07663                 $this->SetLink($url, 0, $page);
07664             }
07665             
07666             $prevcolor = $this->fgcolor;
07667             $prevstyle = $this->FontStyle;
07668             if (empty($color)) {
07669                 $this->SetTextColorArray($this->htmlLinkColorArray);
07670             } else {
07671                 $this->SetTextColorArray($color);
07672             }
07673             if ($style == -1) {
07674                 $this->SetFont('', $this->FontStyle.$this->htmlLinkFontStyle);
07675             } else {
07676                 $this->SetFont('', $this->FontStyle.$style);
07677             }
07678             $ret = $this->Write($this->lasth, $name, $url, $fill, '', false, 0, $firstline);
07679             
07680             $this->SetFont('', $prevstyle);
07681             $this->SetTextColorArray($prevcolor);
07682             return $ret;
07683         }
07684         
07691         public function convertHTMLColorToDec($color='#FFFFFF') {
07692             global $webcolor;
07693             $returncolor = false;
07694             $color = preg_replace('/[\s]*/', '', $color); 
07695             $color = strtolower($color);
07696             if (($dotpos = strpos($color, '.')) !== false) {
07697                 
07698                 $color = substr($color, ($dotpos + 1));
07699             }
07700             if (strlen($color) == 0) {
07701                 return false;
07702             }
07703             if (substr($color, 0, 3) == 'rgb') {
07704                 $codes = substr($color, 4);
07705                 $codes = str_replace(')', '', $codes);
07706                 $returncolor = explode(',', $codes, 3);
07707                 return $returncolor;
07708             }
07709             if (substr($color, 0, 1) != '#') {
07710                 
07711                 if (isset($webcolor[$color])) {
07712                     $color_code = $webcolor[$color];
07713                 } else {
07714                     return false;
07715                 }
07716             } else {
07717                 $color_code = substr($color, 1);
07718             }
07719             switch (strlen($color_code)) {
07720                 case 3: {
07721                     
07722                     $r = substr($color_code, 0, 1);
07723                     $g = substr($color_code, 1, 1);
07724                     $b = substr($color_code, 2, 1);
07725                     $returncolor['R'] = hexdec($r.$r);
07726                     $returncolor['G'] = hexdec($g.$g);
07727                     $returncolor['B'] = hexdec($b.$b);
07728                     break;
07729                 }
07730                 case 6: {
07731                     
07732                     $returncolor['R'] = hexdec(substr($color_code, 0, 2));
07733                     $returncolor['G'] = hexdec(substr($color_code, 2, 2));
07734                     $returncolor['B'] = hexdec(substr($color_code, 4, 2));
07735                     break;
07736                 }
07737             }
07738             return $returncolor;
07739         }
07740         
07748         public function pixelsToUnits($px) {
07749             return ($px / ($this->imgscale * $this->k));
07750         }
07751             
07759         public function unhtmlentities($text_to_convert) {
07760             return html_entity_decode($text_to_convert, ENT_QUOTES, $this->encoding);
07761         }
07762         
07763         
07764         
07765         
07772         protected function _objectkey($n) {
07773             return substr($this->_md5_16($this->encryption_key.pack('VXxx', $n)), 0, 10);
07774         }
07775         
07781         protected function _putencryption() {
07782             $this->_out('/Filter /Standard');
07783             $this->_out('/V 1');
07784             $this->_out('/R 2');
07785             $this->_out('/O ('.$this->_escape($this->Ovalue).')');
07786             $this->_out('/U ('.$this->_escape($this->Uvalue).')');
07787             $this->_out('/P '.$this->Pvalue);
07788         }
07789         
07800         protected function _RC4($key, $text) {
07801             if ($this->last_rc4_key != $key) {
07802                 $k = str_repeat($key, ((256 / strlen($key)) + 1));
07803                 $rc4 = range(0, 255);
07804                 $j = 0;
07805                 for ($i = 0; $i < 256; ++$i) {
07806                     $t = $rc4[$i];
07807                     $j = ($j + $t + ord($k{$i})) % 256;
07808                     $rc4[$i] = $rc4[$j];
07809                     $rc4[$j] = $t;
07810                 }
07811                 $this->last_rc4_key = $key;
07812                 $this->last_rc4_key_c = $rc4;
07813             } else {
07814                 $rc4 = $this->last_rc4_key_c;
07815             }
07816             $len = strlen($text);
07817             $a = 0;
07818             $b = 0;
07819             $out = '';
07820             for ($i = 0; $i < $len; ++$i) {
07821                 $a = ($a + 1) % 256;
07822                 $t = $rc4[$a];
07823                 $b = ($b + $t) % 256;
07824                 $rc4[$a] = $rc4[$b];
07825                 $rc4[$b] = $t;
07826                 $k = $rc4[($rc4[$a] + $rc4[$b]) % 256];
07827                 $out .= chr(ord($text{$i}) ^ $k);
07828             }
07829             return $out;
07830         }
07831         
07840         protected function _md5_16($str) {
07841             return pack('H*', md5($str));
07842         }
07843         
07853         protected function _Ovalue($user_pass, $owner_pass) {
07854             $tmp = $this->_md5_16($owner_pass);
07855             $owner_RC4_key = substr($tmp, 0, 5);
07856             return $this->_RC4($owner_RC4_key, $user_pass);
07857         }
07858         
07866         protected function _Uvalue() {
07867             return $this->_RC4($this->encryption_key, $this->padding);
07868         }
07869         
07879         protected function _generateencryptionkey($user_pass, $owner_pass, $protection) {
07880             
07881             $user_pass = substr($user_pass.$this->padding, 0, 32);
07882             $owner_pass = substr($owner_pass.$this->padding, 0, 32);
07883             
07884             $this->Ovalue = $this->_Ovalue($user_pass, $owner_pass);
07885             
07886             $tmp = $this->_md5_16($user_pass.$this->Ovalue.chr($protection)."\xFF\xFF\xFF");
07887             $this->encryption_key = substr($tmp, 0, 5);
07888             
07889             $this->Uvalue = $this->_Uvalue();
07890             
07891             $this->Pvalue = -(($protection^255) + 1);
07892         }
07893         
07911         public function SetProtection($permissions=array(), $user_pass='', $owner_pass=null) {
07912             $options = array('print' => 4, 'modify' => 8, 'copy' => 16, 'annot-forms' => 32);
07913             $protection = 192;
07914             foreach ($permissions as $permission) {
07915                 if (!isset($options[$permission])) {
07916                     $this->Error('Incorrect permission: '.$permission);
07917                 }
07918                 $protection += $options[$permission];
07919             }
07920             if ($owner_pass === null) {
07921                 $owner_pass = uniqid(rand());
07922             }
07923             $this->encrypted = true;
07924             $this->_generateencryptionkey($user_pass, $owner_pass, $protection);
07925         }
07926         
07927         
07928         
07929         
07930         
07939         public function StartTransform() {
07940             $this->_out('q');
07941             $this->transfmrk[$this->page][] = $this->pagelen[$this->page];
07942             ++$this->transfmatrix_key;
07943             $this->transfmatrix[$this->transfmatrix_key] = array();
07944         }
07945         
07954         public function StopTransform() {
07955             $this->_out('Q');
07956             if (isset($this->transfmatrix[$this->transfmatrix_key])) {
07957                 array_pop($this->transfmatrix[$this->transfmatrix_key]);
07958                 --$this->transfmatrix_key;
07959             }
07960             array_pop($this->transfmrk[$this->page]);
07961         }
07971         public function ScaleX($s_x, $x='', $y='') {
07972             $this->Scale($s_x, 100, $x, $y);
07973         }
07974         
07984         public function ScaleY($s_y, $x='', $y='') {
07985             $this->Scale(100, $s_y, $x, $y);
07986         }
07987         
07997         public function ScaleXY($s, $x='', $y='') {
07998             $this->Scale($s, $s, $x, $y);
07999         }
08000         
08011         public function Scale($s_x, $s_y, $x='', $y='') {
08012             if ($x === '') {
08013                 $x = $this->x;
08014             }
08015             if ($y === '') {
08016                 $y = $this->y;
08017             }
08018             if ($this->rtl) {
08019                 $x = $this->w - $x;
08020             }
08021             if (($s_x == 0) OR ($s_y == 0)) {
08022                 $this->Error('Please do not use values equal to zero for scaling');
08023             }
08024             $y = ($this->h - $y) * $this->k;
08025             $x *= $this->k;
08026             
08027             $s_x /= 100;
08028             $s_y /= 100;
08029             $tm[0] = $s_x;
08030             $tm[1] = 0;
08031             $tm[2] = 0;
08032             $tm[3] = $s_y;
08033             $tm[4] = $x * (1 - $s_x);
08034             $tm[5] = $y * (1 - $s_y);
08035             
08036             $this->Transform($tm);
08037         }
08038         
08046         public function MirrorH($x='') {
08047             $this->Scale(-100, 100, $x);
08048         }
08049         
08057         public function MirrorV($y='') {
08058             $this->Scale(100, -100, '', $y);
08059         }
08060         
08069         public function MirrorP($x='',$y='') {
08070             $this->Scale(-100, -100, $x, $y);
08071         }
08072         
08082         public function MirrorL($angle=0, $x='',$y='') {
08083             $this->Scale(-100, 100, $x, $y);
08084             $this->Rotate(-2*($angle-90), $x, $y);
08085         }
08086         
08094         public function TranslateX($t_x) {
08095             $this->Translate($t_x, 0);
08096         }
08097         
08105         public function TranslateY($t_y) {
08106             $this->Translate(0, $t_y);
08107         }
08108         
08117         public function Translate($t_x, $t_y) {
08118             if ($this->rtl) {
08119                 $t_x = -$t_x;
08120             }
08121             
08122             $tm[0] = 1;
08123             $tm[1] = 0;
08124             $tm[2] = 0;
08125             $tm[3] = 1;
08126             $tm[4] = $t_x * $this->k;
08127             $tm[5] = -$t_y * $this->k;
08128             
08129             $this->Transform($tm);
08130         }
08131         
08141         public function Rotate($angle, $x='', $y='') {
08142             if ($x === '') {
08143                 $x = $this->x;
08144             }
08145             if ($y === '') {
08146                 $y = $this->y;
08147             }
08148             if ($this->rtl) {
08149                 $x = $this->w - $x;
08150                 $angle = -$angle;
08151             }
08152             $y = ($this->h - $y) * $this->k;
08153             $x *= $this->k;
08154             
08155             $tm[0] = cos(deg2rad($angle));
08156             $tm[1] = sin(deg2rad($angle));
08157             $tm[2] = -$tm[1];
08158             $tm[3] = $tm[0];
08159             $tm[4] = $x + ($tm[1] * $y) - ($tm[0] * $x);
08160             $tm[5] = $y - ($tm[0] * $y) - ($tm[1] * $x);
08161             
08162             $this->Transform($tm);
08163         }
08164         
08174         public function SkewX($angle_x, $x='', $y='') {
08175             $this->Skew($angle_x, 0, $x, $y);
08176         }
08177         
08187         public function SkewY($angle_y, $x='', $y='') {
08188             $this->Skew(0, $angle_y, $x, $y);
08189         }
08190         
08201         public function Skew($angle_x, $angle_y, $x='', $y='') {
08202             if ($x === '') {
08203                 $x = $this->x;
08204             }
08205             if ($y === '') {
08206                 $y = $this->y;
08207             }
08208             if ($this->rtl) {
08209                 $x = $this->w - $x;
08210                 $angle_x = -$angle_x;
08211             }
08212             if (($angle_x <= -90) OR ($angle_x >= 90) OR ($angle_y <= -90) OR ($angle_y >= 90)) {
08213                 $this->Error('Please use values between -90 and +90 degrees for Skewing.');
08214             }
08215             $x *= $this->k;
08216             $y = ($this->h - $y) * $this->k;
08217             
08218             $tm[0] = 1;
08219             $tm[1] = tan(deg2rad($angle_y));
08220             $tm[2] = tan(deg2rad($angle_x));
08221             $tm[3] = 1;
08222             $tm[4] = -$tm[2] * $y;
08223             $tm[5] = -$tm[1] * $x;
08224             
08225             $this->Transform($tm);
08226         }
08227         
08234         protected function Transform($tm) {
08235             $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F cm', $tm[0], $tm[1], $tm[2], $tm[3], $tm[4], $tm[5]));
08236             
08237             $this->transfmatrix[$this->transfmatrix_key][] = array('a' => $tm[0], 'b' => $tm[1], 'c' => $tm[2], 'd' => $tm[3], 'e' => $tm[4], 'f' => $tm[5]);
08238             
08239             if (end($this->transfmrk[$this->page]) !== false) {
08240                 $key = key($this->transfmrk[$this->page]);
08241                 $this->transfmrk[$this->page][$key] = $this->pagelen[$this->page];
08242             }
08243         }
08244         
08245         
08246         
08247         
08248         
08249         
08250         
08258         public function SetLineWidth($width) {
08259             
08260             $this->LineWidth = $width;
08261             $this->linestyleWidth = sprintf('%.2F w', ($width * $this->k));
08262             if ($this->page > 0) {
08263                 $this->_out($this->linestyleWidth);
08264             }
08265         }
08266         
08274         public function GetLineWidth() {
08275             return $this->LineWidth;
08276         }
08277         
08299         public function SetLineStyle($style) {
08300             if (!is_array($style)) {
08301                 return;
08302             }
08303             extract($style);
08304             if (isset($width)) {
08305                 $width_prev = $this->LineWidth;
08306                 $this->SetLineWidth($width);
08307                 $this->LineWidth = $width_prev;
08308             }
08309             if (isset($cap)) {
08310                 $ca = array('butt' => 0, 'round'=> 1, 'square' => 2);
08311                 if (isset($ca[$cap])) {
08312                     $this->linestyleCap = $ca[$cap].' J';
08313                     $this->_out($this->linestyleCap);
08314                 }
08315             }
08316             if (isset($join)) {
08317                 $ja = array('miter' => 0, 'round' => 1, 'bevel' => 2);
08318                 if (isset($ja[$join])) {
08319                     $this->linestyleJoin = $ja[$join].' j';
08320                     $this->_out($this->linestyleJoin);
08321                 }
08322             }
08323             if (isset($dash)) {
08324                 $dash_string = '';
08325                 if ($dash) {
08326                     if (preg_match('/^.+,/', $dash) > 0) {
08327                         $tab = explode(',', $dash);
08328                     } else {
08329                         $tab = array($dash);
08330                     }
08331                     $dash_string = '';
08332                     foreach ($tab as $i => $v) {
08333                         if ($i) {
08334                             $dash_string .= ' ';
08335                         }
08336                         $dash_string .= sprintf("%.2F", $v);
08337                     }
08338                 }
08339                 if (!isset($phase) OR !$dash) {
08340                     $phase = 0;
08341                 }
08342                 $this->linestyleDash = sprintf("[%s] %.2F d", $dash_string, $phase);
08343                 $this->_out($this->linestyleDash);
08344             }
08345             if (isset($color)) {
08346                 $this->SetDrawColorArray($color);
08347             }
08348         }
08349         
08350         
08351 
08352 
08353 
08354 
08355 
08356 
08357         protected function _outPoint($x, $y) {
08358             if ($this->rtl) {
08359                 $x = $this->w - $x;
08360             }
08361             $this->_out(sprintf("%.2F %.2F m", $x * $this->k, ($this->h - $y) * $this->k));
08362         }
08363         
08364         
08365 
08366 
08367 
08368 
08369 
08370 
08371         protected function _outLine($x, $y) {
08372             if ($this->rtl) {
08373                 $x = $this->w - $x;
08374             }
08375             $this->_out(sprintf("%.2F %.2F l", $x * $this->k, ($this->h - $y) * $this->k));
08376         }
08377         
08388         protected function _outRect($x, $y, $w, $h, $op) {
08389             if ($this->rtl) {
08390                 $x = $this->w - $x - $w;
08391             }
08392             $this->_out(sprintf('%.2F %.2F %.2F %.2F re %s', $x*$this->k, ($this->h-$y)*$this->k, $w*$this->k, -$h*$this->k, $op));
08393         }
08394         
08395         
08396 
08397 
08398 
08399 
08400 
08401 
08402 
08403 
08404 
08405 
08406 
08407         protected function _outCurve($x1, $y1, $x2, $y2, $x3, $y3) {
08408             if ($this->rtl) {
08409                 $x1 = $this->w - $x1;
08410                 $x2 = $this->w - $x2;
08411                 $x3 = $this->w - $x3;
08412             }
08413             $this->_out(sprintf("%.2F %.2F %.2F %.2F %.2F %.2F c", $x1 * $this->k, ($this->h - $y1) * $this->k, $x2 * $this->k, ($this->h - $y2) * $this->k, $x3 * $this->k, ($this->h - $y3) * $this->k));
08414         }
08415         
08427         public function Line($x1, $y1, $x2, $y2, $style=array()) {
08428             if (is_array($style)) {
08429                 $this->SetLineStyle($style);
08430             }
08431             $this->_outPoint($x1, $y1);
08432             $this->_outLine($x2, $y2);
08433             $this->_out(' S');
08434         }
08435         
08462         public function Rect($x, $y, $w, $h, $style='', $border_style=array(), $fill_color=array()) {
08463             if (!(false === strpos($style, 'F')) AND isset($fill_color)) {
08464                 $this->SetFillColorArray($fill_color);
08465             }
08466             switch ($style) {
08467                 case 'F': {
08468                     $op = 'f';
08469                     $border_style = array();
08470                     $this->_outRect($x, $y, $w, $h, $op);
08471                     break;
08472                 }
08473                 case 'DF':
08474                 case 'FD': {
08475                     if ((!$border_style) OR (isset($border_style['all']))) {
08476                         $op = 'B';
08477                         if (isset($border_style['all'])) {
08478                             $this->SetLineStyle($border_style['all']);
08479                             $border_style = array();
08480                         }
08481                     } else {
08482                         $op = 'f';
08483                     }
08484                     $this->_outRect($x, $y, $w, $h, $op);
08485                     break;
08486                 }
08487                 case 'CNZ': {
08488                     $op = 'W n';
08489                     $this->_outRect($x, $y, $w, $h, $op);
08490                     break;
08491                 }
08492                 case 'CEO': {
08493                     $op = 'W* n';
08494                     $this->_outRect($x, $y, $w, $h, $op);
08495                     break;
08496                 }
08497                 default: {
08498                     $op = 'S';
08499                     if ((!$border_style) OR (isset($border_style['all']))) {
08500                         if (isset($border_style['all']) AND $border_style['all']) {
08501                             $this->SetLineStyle($border_style['all']);
08502                             $border_style = array();
08503                         }
08504                         $this->_outRect($x, $y, $w, $h, $op);
08505                     }
08506                     break;
08507                 }
08508             }
08509             if ($border_style) {
08510                 $border_style2 = array();
08511                 foreach ($border_style as $line => $value) {
08512                     $lenght = strlen($line);
08513                     for ($i = 0; $i < $lenght; ++$i) {
08514                         $border_style2[$line[$i]] = $value;
08515                     }
08516                 }
08517                 $border_style = $border_style2;
08518                 if (isset($border_style['L']) AND $border_style['L']) {
08519                     $this->Line($x, $y, $x, $y + $h, $border_style['L']);
08520                 }
08521                 if (isset($border_style['T']) AND $border_style['T']) {
08522                     $this->Line($x, $y, $x + $w, $y, $border_style['T']);
08523                 }
08524                 if (isset($border_style['R']) AND $border_style['R']) {
08525                     $this->Line($x + $w, $y, $x + $w, $y + $h, $border_style['R']);
08526                 }
08527                 if (isset($border_style['B']) AND $border_style['B']) {
08528                     $this->Line($x, $y + $h, $x + $w, $y + $h, $border_style['B']);
08529                 }
08530             }
08531         }
08532         
08533         
08560         public function Curve($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3, $style='', $line_style=array(), $fill_color=array()) {
08561             if (!(false === strpos($style, 'F')) AND isset($fill_color)) {
08562                 $this->SetFillColorArray($fill_color);
08563             }
08564             switch ($style) {
08565                 case 'F': {
08566                     $op = 'f';
08567                     $line_style = array();
08568                     break;
08569                 }
08570                 case 'FD': 
08571                 case 'DF': {
08572                     $op = 'B';
08573                     break;
08574                 }
08575                 case 'CNZ': {
08576                     $op = 'W n';
08577                     break;
08578                 }
08579                 case 'CEO': {
08580                     $op = 'W* n';
08581                     break;
08582                 }
08583                 default: {
08584                     $op = 'S';
08585                     break;
08586                 }
08587             }
08588             if ($line_style) {
08589                 $this->SetLineStyle($line_style);
08590             }
08591             $this->_outPoint($x0, $y0);
08592             $this->_outCurve($x1, $y1, $x2, $y2, $x3, $y3);
08593             $this->_out($op);
08594         }
08595         
08617         public function Polycurve($x0, $y0, $segments, $style='', $line_style=array(), $fill_color=array()) {
08618             if (!(false === strpos($style, 'F')) AND isset($fill_color)) {
08619                 $this->SetFillColorArray($fill_color);
08620             }
08621             switch ($style) {
08622                 case 'F': {
08623                     $op = 'f';
08624                     $line_style = array();
08625                     break;
08626                 }
08627                 case 'FD':
08628                 case 'DF': {
08629                     $op = 'B';
08630                     break;
08631                 }
08632                 case 'CNZ': {
08633                     $op = 'W n';
08634                     break;
08635                 }
08636                 case 'CEO': {
08637                     $op = 'W* n';
08638                     break;
08639                 }
08640                 default: {
08641                     $op = 'S';
08642                     break;
08643                 }
08644             }
08645             if ($line_style) {
08646                 $this->SetLineStyle($line_style);
08647             }
08648             $this->_outPoint($x0, $y0);
08649             foreach ($segments as $segment) {
08650                 list($x1, $y1, $x2, $y2, $x3, $y3) = $segment;
08651                 $this->_outCurve($x1, $y1, $x2, $y2, $x3, $y3);
08652             }   
08653             $this->_out($op);
08654         }
08655         
08681         public function Ellipse($x0, $y0, $rx, $ry=0, $angle=0, $astart=0, $afinish=360, $style='', $line_style=array(), $fill_color=array(), $nc=8) {
08682             if ($angle) {
08683                 $this->StartTransform();
08684                 $this->Rotate($angle, $x0, $y0);
08685                 $this->Ellipse($x0, $y0, $rx, $ry, 0, $astart, $afinish, $style, $line_style, $fill_color, $nc);
08686                 $this->StopTransform();
08687                 return;
08688             }
08689             if ($rx) {
08690                 if (!(false === strpos($style, 'F')) AND isset($fill_color)) {
08691                     $this->SetFillColorArray($fill_color);
08692                 }
08693                 switch ($style) {
08694                     case 'F': {
08695                         $op = 'f';
08696                         $line_style = array();
08697                         break;
08698                     }
08699                     case 'FD': 
08700                     case 'DF': {
08701                         $op = 'B';
08702                         break;
08703                     }
08704                     case 'C': {
08705                         $op = 's'; 
08706                         break;
08707                     }
08708                     case 'CNZ': {
08709                         $op = 'W n';
08710                         break;
08711                     }
08712                     case 'CEO': {
08713                         $op = 'W* n';
08714                         break;
08715                     }
08716                     default: {
08717                         $op = 'S';
08718                         break;
08719                     }
08720                 }
08721                 if ($line_style) {
08722                     $this->SetLineStyle($line_style);
08723                 }
08724                 if (!$ry) {
08725                     $ry = $rx;
08726                 }
08727                 $rx *= $this->k;
08728                 $ry *= $this->k;
08729                 if ($nc < 2) {
08730                     $nc = 2;
08731                 }
08732                 $astart = deg2rad((float) $astart);
08733                 $afinish = deg2rad((float) $afinish);
08734                 $total_angle = $afinish - $astart;
08735                 $dt = $total_angle / $nc;
08736                 $dtm = $dt / 3;
08737                 $x0 *= $this->k;
08738                 $y0 = ($this->h - $y0) * $this->k;
08739                 $t1 = $astart;
08740                 $a0 = $x0 + ($rx * cos($t1));
08741                 $b0 = $y0 + ($ry * sin($t1));
08742                 $c0 = -$rx * sin($t1);
08743                 $d0 = $ry * cos($t1);
08744                 $this->_outPoint($a0 / $this->k, $this->h - ($b0 / $this->k));
08745                 for ($i = 1; $i <= $nc; ++$i) {
08746                     
08747                     $t1 = ($i * $dt) + $astart;
08748                     $a1 = $x0 + ($rx * cos($t1));
08749                     $b1 = $y0 + ($ry * sin($t1));
08750                     $c1 = -$rx * sin($t1);
08751                     $d1 = $ry * cos($t1);
08752                     $this->_outCurve(($a0 + ($c0 * $dtm)) / $this->k, $this->h - (($b0 + ($d0 * $dtm)) / $this->k), ($a1 - ($c1 * $dtm)) / $this->k, $this->h - (($b1 - ($d1 * $dtm)) / $this->k), $a1 / $this->k, $this->h - ($b1 / $this->k));
08753                     $a0 = $a1;
08754                     $b0 = $b1;
08755                     $c0 = $c1;
08756                     $d0 = $d1;
08757                 }
08758                 $this->_out($op);
08759             }
08760         }
08761         
08785         public function Circle($x0, $y0, $r, $astart=0, $afinish=360, $style='', $line_style=array(), $fill_color=array(), $nc=8) {
08786             $this->Ellipse($x0, $y0, $r, 0, 0, $astart, $afinish, $style, $line_style, $fill_color, $nc);
08787         }
08788 
08811         public function PolyLine($p, $style='', $line_style=array(), $fill_color=array()) {
08812             $this->Polygon($p, $style, $line_style, $fill_color, false);
08813         }
08814 
08837         public function Polygon($p, $style='', $line_style=array(), $fill_color=array(), $closed=true) {
08838             $nc = count($p); 
08839             $np = $nc / 2; 
08840             if ($closed) {
08841                 
08842                 for ($i = 0; $i < 4; ++$i) {
08843                     $p[$nc + $i] = $p[$i];
08844                 }
08845                 
08846                 if (isset($line_style[0])) {
08847                     $line_style[$np] = $line_style[0];
08848                 }           
08849                 $nc += 4;
08850             }
08851             if (!(false === strpos($style, 'F')) AND isset($fill_color)) {
08852                 $this->SetFillColorArray($fill_color);
08853             }
08854             switch ($style) {
08855                 case 'F': {
08856                     $line_style = array();
08857                     $op = 'f';
08858                     break;
08859                 }
08860                 case 'FD': 
08861                 case 'DF': {
08862                     $op = 'B';
08863                     break;
08864                 }
08865                 case 'CNZ': {
08866                     $op = 'W n';
08867                     break;
08868                 }
08869                 case 'CEO': {
08870                     $op = 'W* n';
08871                     break;
08872                 }               
08873                 default: {
08874                     $op = 'S';
08875                     break;
08876                 }
08877             }
08878             $draw = true;
08879             if ($line_style) {
08880                 if (isset($line_style['all'])) {
08881                     $this->SetLineStyle($line_style['all']);
08882                 } else {
08883                     $draw = false;
08884                     if ($op == 'B') {
08885                         
08886                         $op = 'f';
08887                         $this->_outPoint($p[0], $p[1]);
08888                         for ($i = 2; $i < $nc; $i = $i + 2) {
08889                             $this->_outLine($p[$i], $p[$i + 1]);
08890                         }
08891                         $this->_out($op);
08892                     }
08893                     
08894                     $this->_outPoint($p[0], $p[1]);
08895                     for ($i = 2; $i < $nc; $i = $i + 2) {
08896                         $line_num = ($i / 2) - 1;
08897                         if (isset($line_style[$line_num])) {
08898                             if ($line_style[$line_num] != 0) {
08899                                 if (is_array($line_style[$line_num])) {
08900                                     $this->_out('S');
08901                                     $this->SetLineStyle($line_style[$line_num]);
08902                                     $this->_outPoint($p[$i - 2], $p[$i - 1]);
08903                                     $this->_outLine($p[$i], $p[$i + 1]);
08904                                     $this->_out('S');
08905                                     $this->_outPoint($p[$i], $p[$i + 1]);
08906                                 } else {
08907                                     $this->_outLine($p[$i], $p[$i + 1]);
08908                                 }
08909                             }
08910                         } else {
08911                             $this->_outLine($p[$i], $p[$i + 1]);
08912                         }
08913                     }
08914                     $this->_out($op);
08915                 }
08916             }
08917             if ($draw) {
08918                 $this->_outPoint($p[0], $p[1]);
08919                 for ($i = 2; $i < $nc; $i = $i + 2) {
08920                     $this->_outLine($p[$i], $p[$i + 1]);
08921                 }
08922                 $this->_out($op);
08923             }
08924         }
08925         
08962         public function RegularPolygon($x0, $y0, $r, $ns, $angle=0, $draw_circle=false, $style='', $line_style=array(), $fill_color=array(), $circle_style='', $circle_outLine_style=array(), $circle_fill_color=array()) {
08963             if (3 > $ns) {
08964                 $ns = 3;
08965             }
08966             if ($draw_circle) {
08967                 $this->Circle($x0, $y0, $r, 0, 360, $circle_style, $circle_outLine_style, $circle_fill_color);
08968             }
08969             $p = array();
08970             for ($i = 0; $i < $ns; ++$i) {
08971                 $a = $angle + ($i * 360 / $ns);
08972                 $a_rad = deg2rad((float) $a);
08973                 $p[] = $x0 + ($r * sin($a_rad));
08974                 $p[] = $y0 + ($r * cos($a_rad));
08975             }
08976             $this->Polygon($p, $style, $line_style, $fill_color);
08977         }
08978         
09017         public function StarPolygon($x0, $y0, $r, $nv, $ng, $angle=0, $draw_circle=false, $style='', $line_style=array(), $fill_color=array(), $circle_style='', $circle_outLine_style=array(), $circle_fill_color=array()) {
09018             if ($nv < 2) {
09019                 $nv = 2;
09020             }
09021             if ($draw_circle) {
09022                 $this->Circle($x0, $y0, $r, 0, 360, $circle_style, $circle_outLine_style, $circle_fill_color);
09023             }
09024             $p2 = array();
09025             $visited = array();
09026             for ($i = 0; $i < $nv; ++$i) {
09027                 $a = $angle + ($i * 360 / $nv);
09028                 $a_rad = deg2rad((float) $a);
09029                 $p2[] = $x0 + ($r * sin($a_rad));
09030                 $p2[] = $y0 + ($r * cos($a_rad));
09031                 $visited[] = false;
09032             }
09033             $p = array();
09034             $i = 0;
09035             do {
09036                 $p[] = $p2[$i * 2];
09037                 $p[] = $p2[($i * 2) + 1];
09038                 $visited[$i] = true;
09039                 $i += $ng;
09040                 $i %= $nv;
09041             } while (!$visited[$i]);
09042             $this->Polygon($p, $style, $line_style, $fill_color);
09043         }
09044         
09066         public function RoundedRect($x, $y, $w, $h, $r, $round_corner='1111', $style='', $border_style=array(), $fill_color=array()) {
09067             if ('0000' == $round_corner) { 
09068                 $this->Rect($x, $y, $w, $h, $style, $border_style, $fill_color);
09069             } else { 
09070                 if (!(false === strpos($style, 'F')) AND isset($fill_color)) {
09071                     $this->SetFillColorArray($fill_color);
09072                 }
09073                 switch ($style) {
09074                     case 'F': {
09075                         $border_style = array();
09076                         $op = 'f';
09077                         break;
09078                     }
09079                     case 'FD': 
09080                     case 'DF': {
09081                         $op = 'B';
09082                         break;
09083                     }
09084                     case 'CNZ': {
09085                         $op = 'W n';
09086                         break;
09087                     }
09088                     case 'CEO': {
09089                         $op = 'W* n';
09090                         break;
09091                     }
09092                     default: {
09093                         $op = 'S';
09094                         break;
09095                     }
09096                 }
09097                 if ($border_style) {
09098                     $this->SetLineStyle($border_style);
09099                 }
09100                 $MyArc = 4 / 3 * (sqrt(2) - 1);
09101                 $this->_outPoint($x + $r, $y);
09102                 $xc = $x + $w - $r;
09103                 $yc = $y + $r;
09104                 $this->_outLine($xc, $y);
09105                 if ($round_corner[0]) {
09106                     $this->_outCurve($xc + ($r * $MyArc), $yc - $r, $xc + $r, $yc - ($r * $MyArc), $xc + $r, $yc);
09107                 } else {
09108                     $this->_outLine($x + $w, $y);
09109                 }
09110                 $xc = $x + $w - $r;
09111                 $yc = $y + $h - $r;
09112                 $this->_outLine($x + $w, $yc);
09113                 if ($round_corner[1]) {
09114                     $this->_outCurve($xc + $r, $yc + ($r * $MyArc), $xc + ($r * $MyArc), $yc + $r, $xc, $yc + $r);
09115                 } else {
09116                     $this->_outLine($x + $w, $y + $h);
09117                 }
09118                 $xc = $x + $r;
09119                 $yc = $y + $h - $r;
09120                 $this->_outLine($xc, $y + $h);
09121                 if ($round_corner[2]) {
09122                     $this->_outCurve($xc - ($r * $MyArc), $yc + $r, $xc - $r, $yc + ($r * $MyArc), $xc - $r, $yc);
09123                 } else {
09124                     $this->_outLine($x, $y + $h);
09125                 }
09126                 $xc = $x + $r;
09127                 $yc = $y + $r;
09128                 $this->_outLine($x, $yc);
09129                 if ($round_corner[3]) {
09130                     $this->_outCurve($xc - $r, $yc - ($r * $MyArc), $xc - ($r * $MyArc), $yc - $r, $xc, $yc - $r);
09131                 } else {
09132                     $this->_outLine($x, $y);
09133                     $this->_outLine($x + $r, $y);
09134                 }
09135                 $this->_out($op);
09136             }
09137         }
09138         
09151         public function Arrow($x0, $y0, $x1, $y1, $head_style=0, $arm_size=5, $arm_angle=15) {
09152             
09153             
09154             $dir_angle = rad2deg(atan2(($y0 - $y1), ($x0 - $x1)));
09155             $sx1 = $x1;
09156             $sy1 = $y1;
09157             if ($head_style > 0) {
09158                 
09159                 $sx1 = $x1 + (($arm_size - $this->LineWidth) * cos(deg2rad($dir_angle)));
09160                 $sy1 = $y1 + (($arm_size - $this->LineWidth) * sin(deg2rad($dir_angle)));
09161             } 
09162             
09163             $this->Line($x0, $y0, $sx1, $sy1);
09164             
09165             $x2L = $x1 + ($arm_size * cos(deg2rad($dir_angle + $arm_angle)));
09166             $y2L = $y1 + ($arm_size * sin(deg2rad($dir_angle + $arm_angle)));
09167             
09168             $x2R = $x1 + ($arm_size * cos(deg2rad($dir_angle - $arm_angle)));
09169             $y2R = $y1 + ($arm_size * sin(deg2rad($dir_angle - $arm_angle)));
09170             $mode = 'D';
09171             $style = array();
09172             switch ($head_style) {
09173                 case 0: {
09174                     
09175                     $mode = 'D';
09176                     $style = array(1, 1, 0);
09177                     break;
09178                 }
09179                 case 1: {
09180                     
09181                     $mode = 'D';
09182                     break;
09183                 }
09184                 case 2: {
09185                     
09186                     $mode = 'DF';
09187                     break;
09188                 }
09189                 case 3: {
09190                     
09191                     $mode = 'F';
09192                     break;
09193                 }
09194             }
09195             $this->Polygon(array($x2L, $y2L, $x1, $y1, $x2R, $y2R), $mode, $style, array());
09196         }
09197         
09198         
09199         
09200         
09210         protected function utf8StrRev($str, $setbom=false, $forcertl=false) {
09211             return $this->arrUTF8ToUTF16BE($this->utf8Bidi($this->UTF8StringToArray($str), $str, $forcertl), $setbom);
09212         }
09213         
09224         protected function utf8Bidi($ta, $str='', $forcertl=false) {
09225             global $unicode, $unicode_mirror, $unicode_arlet, $laa_array, $diacritics;
09226             
09227             $pel = 0;
09228             
09229             $maxlevel = 0;
09230             if ($this->empty_string($str)) {
09231                 
09232                 $str = $this->UTF8ArrSubString($ta);
09233             }
09234             
09235             if (preg_match(K_RE_PATTERN_ARABIC, $str)) {
09236                 $arabic = true;
09237             } else {
09238                 $arabic = false;
09239             }
09240             
09241             if (!($forcertl OR $arabic OR preg_match(K_RE_PATTERN_RTL, $str))) {
09242                 return $ta;
09243             }
09244             
09245             
09246             $numchars = count($ta);
09247             
09248             if ($forcertl == 'R') {
09249                     $pel = 1;
09250             } elseif ($forcertl == 'L') {
09251                     $pel = 0;
09252             } else {
09253                 
09254                 
09255                 for ($i=0; $i < $numchars; ++$i) {
09256                     $type = $unicode[$ta[$i]];
09257                     if ($type == 'L') {
09258                         $pel = 0;
09259                         break;
09260                     } elseif (($type == 'AL') OR ($type == 'R')) {
09261                         $pel = 1;
09262                         break;
09263                     }
09264                 }
09265             }
09266             
09267             
09268             $cel = $pel;
09269             
09270             $dos = 'N';
09271             $remember = array();
09272             
09273             $sor = $pel % 2 ? 'R' : 'L';
09274             $eor = $sor;
09275             
09276             
09277             $chardata = Array();
09278             
09279             
09280             
09281             for ($i=0; $i < $numchars; ++$i) {
09282                 if ($ta[$i] == K_RLE) {
09283                     
09284                     
09285                     
09286                     $next_level = $cel + ($cel % 2) + 1;
09287                     if ($next_level < 62) {
09288                         $remember[] = array('num' => K_RLE, 'cel' => $cel, 'dos' => $dos);
09289                         $cel = $next_level;
09290                         $dos = 'N';
09291                         $sor = $eor;
09292                         $eor = $cel % 2 ? 'R' : 'L';
09293                     }
09294                 } elseif ($ta[$i] == K_LRE) {
09295                     
09296                     
09297                     
09298                     $next_level = $cel + 2 - ($cel % 2);
09299                     if ( $next_level < 62 ) {
09300                         $remember[] = array('num' => K_LRE, 'cel' => $cel, 'dos' => $dos);
09301                         $cel = $next_level;
09302                         $dos = 'N';
09303                         $sor = $eor;
09304                         $eor = $cel % 2 ? 'R' : 'L';
09305                     }
09306                 } elseif ($ta[$i] == K_RLO) {
09307                     
09308                     
09309                     
09310                     $next_level = $cel + ($cel % 2) + 1;
09311                     if ($next_level < 62) {
09312                         $remember[] = array('num' => K_RLO, 'cel' => $cel, 'dos' => $dos);
09313                         $cel = $next_level;
09314                         $dos = 'R';
09315                         $sor = $eor;
09316                         $eor = $cel % 2 ? 'R' : 'L';
09317                     }
09318                 } elseif ($ta[$i] == K_LRO) {
09319                     
09320                     
09321                     
09322                     $next_level = $cel + 2 - ($cel % 2);
09323                     if ( $next_level < 62 ) {
09324                         $remember[] = array('num' => K_LRO, 'cel' => $cel, 'dos' => $dos);
09325                         $cel = $next_level;
09326                         $dos = 'L';
09327                         $sor = $eor;
09328                         $eor = $cel % 2 ? 'R' : 'L';
09329                     }
09330                 } elseif ($ta[$i] == K_PDF) {
09331                     
09332                     if (count($remember)) {
09333                         $last = count($remember ) - 1;
09334                         if (($remember[$last]['num'] == K_RLE) OR 
09335                               ($remember[$last]['num'] == K_LRE) OR 
09336                               ($remember[$last]['num'] == K_RLO) OR 
09337                               ($remember[$last]['num'] == K_LRO)) {
09338                             $match = array_pop($remember);
09339                             $cel = $match['cel'];
09340                             $dos = $match['dos'];
09341                             $sor = $eor;
09342                             $eor = ($cel > $match['cel'] ? $cel : $match['cel']) % 2 ? 'R' : 'L';
09343                         }
09344                     }
09345                 } elseif (($ta[$i] != K_RLE) AND
09346                                  ($ta[$i] != K_LRE) AND
09347                                  ($ta[$i] != K_RLO) AND
09348                                  ($ta[$i] != K_LRO) AND
09349                                  ($ta[$i] != K_PDF)) {
09350                     
09351                     
09352                     
09353                     if ($dos != 'N') {
09354                         $chardir = $dos;
09355                     } else {
09356                         if (isset($unicode[$ta[$i]])) {
09357                             $chardir = $unicode[$ta[$i]];
09358                         } else {
09359                             $chardir = 'L';
09360                         }
09361                     }
09362                     
09363                     $chardata[] = array('char' => $ta[$i], 'level' => $cel, 'type' => $chardir, 'sor' => $sor, 'eor' => $eor);
09364                 }
09365             } 
09366             
09367             
09368             
09369             
09370             
09371             
09372             
09373             
09374             $numchars = count($chardata);
09375             
09376             
09377             $prevlevel = -1; 
09378             $levcount = 0; 
09379             for ($i=0; $i < $numchars; ++$i) {
09380                 if ($chardata[$i]['type'] == 'NSM') {
09381                     if ($levcount) {
09382                         $chardata[$i]['type'] = $chardata[$i]['sor'];
09383                     } elseif ($i > 0) {
09384                         $chardata[$i]['type'] = $chardata[($i-1)]['type'];
09385                     }
09386                 }
09387                 if ($chardata[$i]['level'] != $prevlevel) {
09388                     $levcount = 0;
09389                 } else {
09390                     ++$levcount;
09391                 }
09392                 $prevlevel = $chardata[$i]['level'];
09393             }
09394             
09395             
09396             $prevlevel = -1;
09397             $levcount = 0;
09398             for ($i=0; $i < $numchars; ++$i) {
09399                 if ($chardata[$i]['char'] == 'EN') {
09400                     for ($j=$levcount; $j >= 0; $j--) {
09401                         if ($chardata[$j]['type'] == 'AL') {
09402                             $chardata[$i]['type'] = 'AN';
09403                         } elseif (($chardata[$j]['type'] == 'L') OR ($chardata[$j]['type'] == 'R')) {
09404                             break;
09405                         }
09406                     }
09407                 }
09408                 if ($chardata[$i]['level'] != $prevlevel) {
09409                     $levcount = 0;
09410                 } else {
09411                     ++$levcount;
09412                 }
09413                 $prevlevel = $chardata[$i]['level'];
09414             }
09415             
09416             
09417             for ($i=0; $i < $numchars; ++$i) {
09418                 if ($chardata[$i]['type'] == 'AL') {
09419                     $chardata[$i]['type'] = 'R';
09420                 } 
09421             }
09422             
09423             
09424             $prevlevel = -1;
09425             $levcount = 0;
09426             for ($i=0; $i < $numchars; ++$i) {
09427                 if (($levcount > 0) AND (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] == $prevlevel)) {
09428                     if (($chardata[$i]['type'] == 'ES') AND ($chardata[($i-1)]['type'] == 'EN') AND ($chardata[($i+1)]['type'] == 'EN')) {
09429                         $chardata[$i]['type'] = 'EN';
09430                     } elseif (($chardata[$i]['type'] == 'CS') AND ($chardata[($i-1)]['type'] == 'EN') AND ($chardata[($i+1)]['type'] == 'EN')) {
09431                         $chardata[$i]['type'] = 'EN';
09432                     } elseif (($chardata[$i]['type'] == 'CS') AND ($chardata[($i-1)]['type'] == 'AN') AND ($chardata[($i+1)]['type'] == 'AN')) {
09433                         $chardata[$i]['type'] = 'AN';
09434                     }
09435                 }
09436                 if ($chardata[$i]['level'] != $prevlevel) {
09437                     $levcount = 0;
09438                 } else {
09439                     ++$levcount;
09440                 }
09441                 $prevlevel = $chardata[$i]['level'];
09442             }
09443             
09444             
09445             $prevlevel = -1;
09446             $levcount = 0;
09447             for ($i=0; $i < $numchars; ++$i) {
09448                 if ($chardata[$i]['type'] == 'ET') {
09449                     if (($levcount > 0) AND ($chardata[($i-1)]['type'] == 'EN')) {
09450                         $chardata[$i]['type'] = 'EN';
09451                     } else {
09452                         $j = $i+1;
09453                         while (($j < $numchars) AND ($chardata[$j]['level'] == $prevlevel)) {
09454                             if ($chardata[$j]['type'] == 'EN') {
09455                                 $chardata[$i]['type'] = 'EN';
09456                                 break;
09457                             } elseif ($chardata[$j]['type'] != 'ET') {
09458                                 break;
09459                             }
09460                             ++$j;
09461                         }
09462                     }
09463                 }
09464                 if ($chardata[$i]['level'] != $prevlevel) {
09465                     $levcount = 0;
09466                 } else {
09467                     ++$levcount;
09468                 }
09469                 $prevlevel = $chardata[$i]['level'];
09470             }
09471             
09472             
09473             $prevlevel = -1;
09474             $levcount = 0;
09475             for ($i=0; $i < $numchars; ++$i) {
09476                 if (($chardata[$i]['type'] == 'ET') OR ($chardata[$i]['type'] == 'ES') OR ($chardata[$i]['type'] == 'CS')) {
09477                     $chardata[$i]['type'] = 'ON';
09478                 }
09479                 if ($chardata[$i]['level'] != $prevlevel) {
09480                     $levcount = 0;
09481                 } else {
09482                     ++$levcount;
09483                 }
09484                 $prevlevel = $chardata[$i]['level'];
09485             }
09486             
09487             
09488             $prevlevel = -1;
09489             $levcount = 0;
09490             for ($i=0; $i < $numchars; ++$i) {
09491                 if ($chardata[$i]['char'] == 'EN') {
09492                     for ($j=$levcount; $j >= 0; $j--) {
09493                         if ($chardata[$j]['type'] == 'L') {
09494                             $chardata[$i]['type'] = 'L';
09495                         } elseif ($chardata[$j]['type'] == 'R') {
09496                             break;
09497                         }
09498                     }
09499                 }
09500                 if ($chardata[$i]['level'] != $prevlevel) {
09501                     $levcount = 0;
09502                 } else {
09503                     ++$levcount;
09504                 }
09505                 $prevlevel = $chardata[$i]['level'];
09506             }
09507             
09508             
09509             $prevlevel = -1;
09510             $levcount = 0;
09511             for ($i=0; $i < $numchars; ++$i) {
09512                 if (($levcount > 0) AND (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] == $prevlevel)) {
09513                     if (($chardata[$i]['type'] == 'N') AND ($chardata[($i-1)]['type'] == 'L') AND ($chardata[($i+1)]['type'] == 'L')) {
09514                         $chardata[$i]['type'] = 'L';
09515                     } elseif (($chardata[$i]['type'] == 'N') AND
09516                      (($chardata[($i-1)]['type'] == 'R') OR ($chardata[($i-1)]['type'] == 'EN') OR ($chardata[($i-1)]['type'] == 'AN')) AND
09517                      (($chardata[($i+1)]['type'] == 'R') OR ($chardata[($i+1)]['type'] == 'EN') OR ($chardata[($i+1)]['type'] == 'AN'))) {
09518                         $chardata[$i]['type'] = 'R';
09519                     } elseif ($chardata[$i]['type'] == 'N') {
09520                         
09521                         $chardata[$i]['type'] = $chardata[$i]['sor'];
09522                     }
09523                 } elseif (($levcount == 0) AND (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] == $prevlevel)) {
09524                     
09525                     if (($chardata[$i]['type'] == 'N') AND ($chardata[$i]['sor'] == 'L') AND ($chardata[($i+1)]['type'] == 'L')) {
09526                         $chardata[$i]['type'] = 'L';
09527                     } elseif (($chardata[$i]['type'] == 'N') AND
09528                      (($chardata[$i]['sor'] == 'R') OR ($chardata[$i]['sor'] == 'EN') OR ($chardata[$i]['sor'] == 'AN')) AND
09529                      (($chardata[($i+1)]['type'] == 'R') OR ($chardata[($i+1)]['type'] == 'EN') OR ($chardata[($i+1)]['type'] == 'AN'))) {
09530                         $chardata[$i]['type'] = 'R';
09531                     } elseif ($chardata[$i]['type'] == 'N') {
09532                         
09533                         $chardata[$i]['type'] = $chardata[$i]['sor'];
09534                     }
09535                 } elseif (($levcount > 0) AND ((($i+1) == $numchars) OR (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] != $prevlevel))) {
09536                     
09537                     if (($chardata[$i]['type'] == 'N') AND ($chardata[($i-1)]['type'] == 'L') AND ($chardata[$i]['eor'] == 'L')) {
09538                         $chardata[$i]['type'] = 'L';
09539                     } elseif (($chardata[$i]['type'] == 'N') AND
09540                      (($chardata[($i-1)]['type'] == 'R') OR ($chardata[($i-1)]['type'] == 'EN') OR ($chardata[($i-1)]['type'] == 'AN')) AND
09541                      (($chardata[$i]['eor'] == 'R') OR ($chardata[$i]['eor'] == 'EN') OR ($chardata[$i]['eor'] == 'AN'))) {
09542                         $chardata[$i]['type'] = 'R';
09543                     } elseif ($chardata[$i]['type'] == 'N') {
09544                         
09545                         $chardata[$i]['type'] = $chardata[$i]['sor'];
09546                     }
09547                 } elseif ($chardata[$i]['type'] == 'N') {
09548                     
09549                     $chardata[$i]['type'] = $chardata[$i]['sor'];
09550                 }
09551                 if ($chardata[$i]['level'] != $prevlevel) {
09552                     $levcount = 0;
09553                 } else {
09554                     ++$levcount;
09555                 }
09556                 $prevlevel = $chardata[$i]['level'];
09557             }
09558             
09559             
09560             
09561             for ($i=0; $i < $numchars; ++$i) {
09562                 $odd = $chardata[$i]['level'] % 2;
09563                 if ($odd) {
09564                     if (($chardata[$i]['type'] == 'L') OR ($chardata[$i]['type'] == 'AN') OR ($chardata[$i]['type'] == 'EN')) {
09565                         $chardata[$i]['level'] += 1;
09566                     }
09567                 } else {
09568                     if ($chardata[$i]['type'] == 'R') {
09569                         $chardata[$i]['level'] += 1;
09570                     } elseif (($chardata[$i]['type'] == 'AN') OR ($chardata[$i]['type'] == 'EN')) {
09571                         $chardata[$i]['level'] += 2;
09572                     }
09573                 }
09574                 $maxlevel = max($chardata[$i]['level'],$maxlevel);
09575             }
09576             
09577             
09578             
09579             
09580             
09581             
09582             for ($i=0; $i < $numchars; ++$i) {
09583                 if (($chardata[$i]['type'] == 'B') OR ($chardata[$i]['type'] == 'S')) {
09584                     $chardata[$i]['level'] = $pel;
09585                 } elseif ($chardata[$i]['type'] == 'WS') {
09586                     $j = $i+1;
09587                     while ($j < $numchars) {
09588                         if ((($chardata[$j]['type'] == 'B') OR ($chardata[$j]['type'] == 'S')) OR
09589                             (($j == ($numchars-1)) AND ($chardata[$j]['type'] == 'WS'))) {
09590                             $chardata[$i]['level'] = $pel;
09591                             break;
09592                         } elseif ($chardata[$j]['type'] != 'WS') {
09593                             break;
09594                         }
09595                         ++$j;
09596                     }
09597                 }
09598             }
09599             
09600             
09601             
09602             if ($arabic) {
09603                 $endedletter = array(1569,1570,1571,1572,1573,1575,1577,1583,1584,1585,1586,1608,1688);
09604                 $alfletter = array(1570,1571,1573,1575);
09605                 $chardata2 = $chardata;
09606                 $laaletter = false;
09607                 $charAL = array();
09608                 $x = 0;
09609                 for ($i=0; $i < $numchars; ++$i) {
09610                     if (($unicode[$chardata[$i]['char']] == 'AL') OR ($chardata[$i]['char'] == 32) OR ($chardata[$i]['char'] == 8204)) {
09611                         $charAL[$x] = $chardata[$i];
09612                         $charAL[$x]['i'] = $i;
09613                         $chardata[$i]['x'] = $x;
09614                         ++$x;
09615                     }
09616                 }
09617                 $numAL = $x;
09618                 for ($i=0; $i < $numchars; ++$i) {
09619                     $thischar = $chardata[$i];
09620                     if ($i > 0) {
09621                         $prevchar = $chardata[($i-1)];
09622                     } else {
09623                         $prevchar = false;
09624                     }
09625                     if (($i+1) < $numchars) {
09626                         $nextchar = $chardata[($i+1)];
09627                     } else {
09628                         $nextchar = false;
09629                     }
09630                     if ($unicode[$thischar['char']] == 'AL') {
09631                         $x = $thischar['x'];
09632                         if ($x > 0) {
09633                             $prevchar = $charAL[($x-1)];
09634                         } else {
09635                             $prevchar = false;
09636                         }
09637                         if (($x+1) < $numAL) {
09638                             $nextchar = $charAL[($x+1)];
09639                         } else {
09640                             $nextchar = false;
09641                         }
09642                         
09643                         if (($prevchar !== false) AND ($prevchar['char'] == 1604) AND (in_array($thischar['char'], $alfletter))) {
09644                             $arabicarr = $laa_array;
09645                             $laaletter = true;
09646                             if ($x > 1) {
09647                                 $prevchar = $charAL[($x-2)];
09648                             } else {
09649                                 $prevchar = false;
09650                             }
09651                         } else {
09652                             $arabicarr = $unicode_arlet;
09653                             $laaletter = false;
09654                         }
09655                         if (($prevchar !== false) AND ($nextchar !== false) AND
09656                             (($unicode[$prevchar['char']] == 'AL') OR ($unicode[$prevchar['char']] == 'NSM')) AND
09657                             (($unicode[$nextchar['char']] == 'AL') OR ($unicode[$nextchar['char']] == 'NSM')) AND
09658                             ($prevchar['type'] == $thischar['type']) AND
09659                             ($nextchar['type'] == $thischar['type']) AND
09660                             ($nextchar['char'] != 1567)) {
09661                             if (in_array($prevchar['char'], $endedletter)) {
09662                                 if (isset($arabicarr[$thischar['char']][2])) {
09663                                     
09664                                     $chardata2[$i]['char'] = $arabicarr[$thischar['char']][2];
09665                                 }
09666                             } else {
09667                                 if (isset($arabicarr[$thischar['char']][3])) {
09668                                     
09669                                     $chardata2[$i]['char'] = $arabicarr[$thischar['char']][3];
09670                                 }
09671                             }
09672                         } elseif (($nextchar !== false) AND
09673                             (($unicode[$nextchar['char']] == 'AL') OR ($unicode[$nextchar['char']] == 'NSM')) AND
09674                             ($nextchar['type'] == $thischar['type']) AND
09675                             ($nextchar['char'] != 1567)) {
09676                             if (isset($arabicarr[$chardata[$i]['char']][2])) {
09677                                 
09678                                 $chardata2[$i]['char'] = $arabicarr[$thischar['char']][2];
09679                             }
09680                         } elseif ((($prevchar !== false) AND
09681                             (($unicode[$prevchar['char']] == 'AL') OR ($unicode[$prevchar['char']] == 'NSM')) AND
09682                             ($prevchar['type'] == $thischar['type'])) OR
09683                             (($nextchar !== false) AND ($nextchar['char'] == 1567))) {
09684                             
09685                             if (($i > 1) AND ($thischar['char'] == 1607) AND
09686                                 ($chardata[$i-1]['char'] == 1604) AND
09687                                 ($chardata[$i-2]['char'] == 1604)) {
09688                                 
09689                                 
09690                                 $chardata2[$i-2]['char'] = false;
09691                                 $chardata2[$i-1]['char'] = false; 
09692                                 $chardata2[$i]['char'] = 65010;
09693                             } else {
09694                                 if (($prevchar !== false) AND in_array($prevchar['char'], $endedletter)) {
09695                                     if (isset($arabicarr[$thischar['char']][0])) {
09696                                         
09697                                         $chardata2[$i]['char'] = $arabicarr[$thischar['char']][0];
09698                                     }
09699                                 } else {
09700                                     if (isset($arabicarr[$thischar['char']][1])) {
09701                                         
09702                                         $chardata2[$i]['char'] = $arabicarr[$thischar['char']][1];
09703                                     }
09704                                 }
09705                             }
09706                         } elseif (isset($arabicarr[$thischar['char']][0])) {
09707                             
09708                             $chardata2[$i]['char'] = $arabicarr[$thischar['char']][0];
09709                         }
09710                         
09711                         if ($laaletter) {
09712                             
09713                             $chardata2[($charAL[($x-1)]['i'])]['char'] = false;
09714                         }
09715                     } 
09716                 } 
09717                 
09718 
09719 
09720 
09721                 $cw = &$this->CurrentFont['cw'];
09722                 for ($i = 0; $i < ($numchars-1); ++$i) {
09723                     if (($chardata2[$i]['char'] == 1617) AND (isset($diacritics[($chardata2[$i+1]['char'])]))) {
09724                         
09725                         if (isset($cw[($diacritics[($chardata2[$i+1]['char'])])])) {
09726                             $chardata2[$i]['char'] = false;
09727                             $chardata2[$i+1]['char'] = $diacritics[($chardata2[$i+1]['char'])];
09728                         }
09729                     }
09730                 }
09731                 
09732                 foreach ($chardata2 as $key => $value) {
09733                     if ($value['char'] === false) {
09734                         unset($chardata2[$key]);
09735                     }
09736                 }
09737                 $chardata = array_values($chardata2);
09738                 $numchars = count($chardata);
09739                 unset($chardata2);
09740                 unset($arabicarr);
09741                 unset($laaletter);
09742                 unset($charAL);
09743             }
09744             
09745             
09746             for ($j=$maxlevel; $j > 0; $j--) {
09747                 $ordarray = Array();
09748                 $revarr = Array();
09749                 $onlevel = false;
09750                 for ($i=0; $i < $numchars; ++$i) {
09751                     if ($chardata[$i]['level'] >= $j) {
09752                         $onlevel = true;
09753                         if (isset($unicode_mirror[$chardata[$i]['char']])) {
09754                             
09755                             $chardata[$i]['char'] = $unicode_mirror[$chardata[$i]['char']];
09756                         }
09757                         $revarr[] = $chardata[$i];
09758                     } else {
09759                         if ($onlevel) {
09760                             $revarr = array_reverse($revarr);
09761                             $ordarray = array_merge($ordarray, $revarr);
09762                             $revarr = Array();
09763                             $onlevel = false;
09764                         }
09765                         $ordarray[] = $chardata[$i];
09766                     }
09767                 }
09768                 if ($onlevel) {
09769                     $revarr = array_reverse($revarr);
09770                     $ordarray = array_merge($ordarray, $revarr);
09771                 }
09772                 $chardata = $ordarray;
09773             }
09774             
09775             $ordarray = array();
09776             for ($i=0; $i < $numchars; ++$i) {
09777                 $ordarray[] = $chardata[$i]['char'];
09778             }
09779             
09780             return $ordarray;
09781         }
09782         
09783         
09784         
09785         
09786 
09787 
09788 
09789 
09790 
09791 
09792 
09793 
09794 
09795         public function Bookmark($txt, $level=0, $y=-1, $page='') {
09796             if ($level < 0) {
09797                 $level = 0;
09798             }
09799             if (isset($this->outlines[0])) {
09800                 $lastoutline = end($this->outlines);
09801                 $maxlevel = $lastoutline['l'] + 1;
09802             } else {
09803                 $maxlevel = 0;
09804             }
09805             if ($level > $maxlevel) {
09806                 $level = $maxlevel;
09807             }
09808             if ($y == -1) {
09809                 $y = $this->GetY();
09810             }
09811             if (empty($page)) {
09812                 $page = $this->PageNo();
09813             }
09814             $this->outlines[] = array('t' => $txt, 'l' => $level, 'y' => $y, 'p' => $page);
09815         }
09816         
09817         
09818 
09819 
09820 
09821 
09822 
09823         protected function _putbookmarks() {
09824             $nb = count($this->outlines);
09825             if ($nb == 0) {
09826                 return;
09827             }
09828             $lru = array();
09829             $level = 0;
09830             foreach ($this->outlines as $i => $o) {
09831                 if ($o['l'] > 0) {
09832                     $parent = $lru[($o['l'] - 1)];
09833                     
09834                     $this->outlines[$i]['parent'] = $parent;
09835                     $this->outlines[$parent]['last'] = $i;
09836                     if ($o['l'] > $level) {
09837                         
09838                         $this->outlines[$parent]['first'] = $i;
09839                     }
09840                 } else {
09841                     $this->outlines[$i]['parent'] = $nb;
09842                 }
09843                 if (($o['l'] <= $level) AND ($i > 0)) {
09844                     
09845                     $prev = $lru[$o['l']];
09846                     $this->outlines[$prev]['next'] = $i;
09847                     $this->outlines[$i]['prev'] = $prev;
09848                 }
09849                 $lru[$o['l']] = $i;
09850                 $level = $o['l'];
09851             }
09852             
09853             $n = $this->n + 1;
09854             foreach ($this->outlines as $i => $o) {
09855                 $this->_newobj();
09856                 $this->_out('<</Title '.$this->_textstring($o['t']));
09857                 $this->_out('/Parent '.($n + $o['parent']).' 0 R');
09858                 if (isset($o['prev']))
09859                 $this->_out('/Prev '.($n + $o['prev']).' 0 R');
09860                 if (isset($o['next']))
09861                 $this->_out('/Next '.($n + $o['next']).' 0 R');
09862                 if (isset($o['first']))
09863                 $this->_out('/First '.($n + $o['first']).' 0 R');
09864                 if (isset($o['last']))
09865                 $this->_out('/Last '.($n + $o['last']).' 0 R');
09866                 $this->_out(sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]', (1 + (2 * $o['p'])), ($this->pagedim[$o['p']]['h'] - ($o['y'] * $this->k))));
09867                 $this->_out('/Count 0>>');
09868                 $this->_out('endobj');
09869             }
09870             
09871             $this->_newobj();
09872             $this->OutlineRoot = $this->n;
09873             $this->_out('<</Type /Outlines /First '.$n.' 0 R');
09874             $this->_out('/Last '.($n + $lru[0]).' 0 R>>');
09875             $this->_out('endobj');
09876         }
09877         
09878         
09879         
09880         
09881         
09882 
09883 
09884 
09885 
09886 
09887 
09888         public function IncludeJS($script) {
09889             $this->javascript .= $script;
09890         }
09891 
09892         
09893 
09894 
09895 
09896 
09897 
09898 
09899 
09900 
09901         public function addJavascriptObject($script, $onload=false) {
09902             ++$this->js_obj_id;
09903             $this->js_objects[$this->js_obj_id] = array('js' => $script, 'onload' => $onload);
09904             return $this->js_obj_id;
09905         }
09906 
09907         
09908 
09909 
09910 
09911 
09912 
09913         protected function _putjavascript() {
09914             if (empty($this->javascript) AND empty($this->js_objects)) {
09915                 return;
09916             }
09917             if (strpos($this->javascript, 'this.addField') > 0) {
09918                 if (!$this->ur) {
09919                     
09920                 }
09921                 
09922                 
09923                 $jsa = sprintf("ftcpdfdocsaved=this.addField('%s','%s',%d,[%.2F,%.2F,%.2F,%.2F]);", 'tcpdfdocsaved', 'text', 0, 0, 1, 0, 1);
09924                 $jsb = "getField('tcpdfdocsaved').value='saved';";
09925                 $this->javascript = $jsa."\n".$this->javascript."\n".$jsb;
09926             }
09927             $this->n_js = $this->_newobj();
09928             $this->_out('<<');
09929             $this->_out('/Names [');
09930             if (!empty($this->javascript)) {
09931                 $this->_out('(EmbeddedJS) '.($this->n + 1).' 0 R');
09932             }
09933             if (!empty($this->js_objects)) {
09934                 foreach ($this->js_objects as $key => $val) {
09935                     if ($val['onload']) {
09936                         $this->_out('(JS'.$key.') '.$key.' 0 R');
09937                     }
09938                 }
09939             }
09940             $this->_out(']');
09941             $this->_out('>>');
09942             $this->_out('endobj');
09943             
09944             if (!empty($this->javascript)) {
09945                 $this->_newobj();
09946                 $this->_out('<<');
09947                 $this->_out('/S /JavaScript');
09948                 $this->_out('/JS '.$this->_textstring($this->javascript));
09949                 $this->_out('>>');
09950                 $this->_out('endobj');
09951             }
09952             
09953             if (!empty($this->js_objects)) {
09954                 foreach ($this->js_objects as $key => $val) {
09955                     $this->offsets[$key] = $this->bufferlen;
09956                     $this->_out($key.' 0 obj');
09957                     $this->_out('<<');
09958                     $this->_out('/S /JavaScript');
09959                     $this->_out('/JS '.$this->_textstring($val['js']));
09960                     $this->_out('>>');
09961                     $this->_out('endobj');
09962                 }
09963             }           
09964         }
09965         
09966         
09967 
09968 
09969 
09970 
09971 
09972 
09973         protected function _JScolor($color) {
09974             static $aColors = array('transparent', 'black', 'white', 'red', 'green', 'blue', 'cyan', 'magenta', 'yellow', 'dkGray', 'gray', 'ltGray');
09975             if (substr($color,0,1) == '#') {
09976                 return sprintf("['RGB',%.3F,%.3F,%.3F]", hexdec(substr($color,1,2))/255, hexdec(substr($color,3,2))/255, hexdec(substr($color,5,2))/255);
09977             }
09978             if (!in_array($color,$aColors)) {
09979                 $this->Error('Invalid color: '.$color);
09980             }
09981             return 'color.'.$color;
09982         }
09983         
09984         
09985 
09986 
09987 
09988 
09989 
09990 
09991 
09992 
09993 
09994 
09995 
09996 
09997         protected function _addfield($type, $name, $x, $y, $w, $h, $prop) {
09998             if ($this->rtl) {
09999                 $x = $x - $w;
10000             }
10001             
10002             $this->javascript .= "if(getField('tcpdfdocsaved').value != 'saved') {";
10003             $k = $this->k;
10004             $this->javascript .= sprintf("f".$name."=this.addField('%s','%s',%d,[%.2F,%.2F,%.2F,%.2F]);", $name, $type, $this->PageNo()-1, $x*$k, ($this->h-$y)*$k+1, ($x+$w)*$k, ($this->h-$y-$h)*$k+1)."\n";
10005             $this->javascript .= 'f'.$name.'.textSize='.$this->FontSizePt.";\n";
10006             while (list($key, $val) = each($prop)) {
10007                 if (strcmp(substr($key, -5), 'Color') == 0) {
10008                     $val = $this->_JScolor($val);
10009                 } else {
10010                     $val = "'".$val."'";
10011                 }
10012                 $this->javascript .= 'f'.$name.'.'.$key.'='.$val.";\n";
10013             }
10014             if ($this->rtl) {
10015                 $this->x -= $w;
10016             } else {
10017                 $this->x += $w;
10018             }
10019             $this->javascript .= '}';
10020         }
10021 
10022         
10023 
10024         
10025 
10026 
10027 
10028 
10029 
10030 
10031 
10032         protected function getAnnotOptFromJSProp($prop) {
10033             if (isset($prop['aopt']) AND is_array($prop['aopt'])) {
10034                 
10035                 return $prop['aopt'];
10036             }
10037             $opt = array(); 
10038             
10039             if (isset($prop['alignment'])) {
10040                 switch ($prop['alignment']) {
10041                     case 'left': {
10042                         $opt['q'] = 0;
10043                         break;
10044                     }
10045                     case 'center': {
10046                         $opt['q'] = 1;
10047                         break;
10048                     }
10049                     case 'right': {
10050                         $opt['q'] = 2;
10051                         break;
10052                     }
10053                     default: {
10054                         $opt['q'] = ($this->rtl)?2:0;
10055                         break;
10056                     }
10057                 }
10058             }
10059             
10060             if (isset($prop['lineWidth'])) {
10061                 $linewidth = intval($prop['lineWidth']);
10062             } else {
10063                 $linewidth = 1;
10064             }
10065             
10066             if (isset($prop['borderStyle'])) {
10067                 switch ($prop['borderStyle']) {
10068                     case 'border.d':
10069                     case 'dashed': {
10070                         $opt['border'] = array(0, 0, $linewidth, array(3, 2));
10071                         $opt['bs'] = array('w'=>$linewidth, 's'=>'D', 'd'=>array(3, 2));
10072                         break;
10073                     }
10074                     case 'border.b':
10075                     case 'beveled': {
10076                         $opt['border'] = array(0, 0, $linewidth);
10077                         $opt['bs'] = array('w'=>$linewidth, 's'=>'B');
10078                         break;
10079                     }
10080                     case 'border.i':
10081                     case 'inset': {
10082                         $opt['border'] = array(0, 0, $linewidth);
10083                         $opt['bs'] = array('w'=>$linewidth, 's'=>'I');
10084                         break;
10085                     }
10086                     case 'border.u':
10087                     case 'underline': {
10088                         $opt['border'] = array(0, 0, $linewidth);
10089                         $opt['bs'] = array('w'=>$linewidth, 's'=>'U');
10090                         break;
10091                     }
10092                     default:
10093                     case 'border.s':
10094                     case 'solid': {
10095                         $opt['border'] = array(0, 0, $linewidth);
10096                         $opt['bs'] = array('w'=>$linewidth, 's'=>'S');
10097                         break;
10098                     }
10099                 }
10100             }
10101             if (isset($prop['border']) AND is_array($prop['border'])) {
10102                 $opt['border'] = $prop['border'];
10103             }
10104             if (!isset($opt['mk'])) {
10105                 $opt['mk'] = array();
10106             }
10107             if (!isset($opt['mk']['if'])) {
10108                 $opt['mk']['if'] = array();
10109             }
10110             $opt['mk']['if']['a'] = array(0.5, 0.5);
10111             
10112             if (isset($prop['buttonAlignX'])) {
10113                 $opt['mk']['if']['a'][0] = $prop['buttonAlignX'];
10114             }
10115             
10116             if (isset($prop['buttonAlignY'])) {
10117                 $opt['mk']['if']['a'][1] = $prop['buttonAlignY'];
10118             }
10119             
10120             if (isset($prop['buttonFitBounds']) AND ($prop['buttonFitBounds'] == 'true')) {
10121                 $opt['mk']['if']['fb'] = true;
10122             }           
10123             
10124             if (isset($prop['buttonScaleHow'])) {
10125                 switch ($prop['buttonScaleHow']) {
10126                     case 'scaleHow.proportional': {
10127                         $opt['mk']['if']['s'] = 'P';
10128                         break;
10129                     }
10130                     case 'scaleHow.anamorphic': {
10131                         $opt['mk']['if']['s'] = 'A';
10132                         break;
10133                     }
10134                 }
10135             }
10136             
10137             if (isset($prop['buttonScaleWhen'])) {
10138                 switch ($prop['buttonScaleWhen']) {
10139                     case 'scaleWhen.always': {
10140                         $opt['mk']['if']['sw'] = 'A';
10141                         break;
10142                     }
10143                     case 'scaleWhen.never': {
10144                         $opt['mk']['if']['sw'] = 'N';
10145                         break;
10146                     }
10147                     case 'scaleWhen.tooBig': {
10148                         $opt['mk']['if']['sw'] = 'B';
10149                         break;
10150                     }
10151                     case 'scaleWhen.tooSmall': {
10152                         $opt['mk']['if']['sw'] = 'S';
10153                         break;
10154                     }
10155                 }
10156             }
10157             
10158             if (isset($prop['buttonPosition'])) {
10159                 switch ($prop['buttonPosition']) {
10160                     case 0:
10161                     case 'position.textOnly': {
10162                         $opt['mk']['tp'] = 0;
10163                         break;
10164                     }
10165                     case 1:
10166                     case 'position.iconOnly': {
10167                         $opt['mk']['tp'] = 1;
10168                         break;
10169                     }
10170                     case 2:
10171                     case 'position.iconTextV': {
10172                         $opt['mk']['tp'] = 2;
10173                         break;
10174                     }
10175                     case 3:
10176                     case 'position.textIconV': {
10177                         $opt['mk']['tp'] = 3;
10178                         break;
10179                     }
10180                     case 4:
10181                     case 'position.iconTextH': {
10182                         $opt['mk']['tp'] = 4;
10183                         break;
10184                     }
10185                     case 5:
10186                     case 'position.textIconH': {
10187                         $opt['mk']['tp'] = 5;
10188                         break;
10189                     }
10190                     case 6:
10191                     case 'position.overlay': {
10192                         $opt['mk']['tp'] = 6;
10193                         break;
10194                     }
10195                 }               
10196             }
10197             
10198             if (isset($prop['fillColor'])) {
10199                 if (is_array($prop['fillColor'])) {
10200                     $opt['mk']['bg'] = $prop['fillColor'];
10201                 } else {
10202                     $opt['mk']['bg'] = $this->convertHTMLColorToDec($prop['fillColor']);
10203                 }
10204             }
10205             
10206             if (isset($prop['strokeColor'])) {
10207                 if (is_array($prop['strokeColor'])) {
10208                     $opt['mk']['bc'] = $prop['strokeColor'];
10209                 } else {
10210                     $opt['mk']['bc'] = $this->convertHTMLColorToDec($prop['strokeColor']);
10211                 }
10212             }
10213             
10214             if (isset($prop['rotation'])) {
10215                 $opt['mk']['r'] = $prop['rotation'];
10216             }
10217             
10218             if (isset($prop['charLimit'])) {
10219                 $opt['maxlen'] = intval($prop['charLimit']);
10220             }
10221             if (!isset($ff)) {
10222                 $ff = 0;
10223             }
10224             
10225             if (isset($prop['readonly']) AND ($prop['readonly'] == 'true')) {
10226                 $ff += 1 << 0;
10227             }
10228             
10229             if (isset($prop['required']) AND ($prop['required'] == 'true')) {
10230                 $ff += 1 << 1;
10231             }
10232             
10233             if (isset($prop['multiline']) AND ($prop['multiline'] == 'true')) {
10234                 $ff += 1 << 12;
10235             }
10236             
10237             if (isset($prop['password']) AND ($prop['password'] == 'true')) {
10238                 $ff += 1 << 13;
10239             }
10240             
10241             if (isset($prop['NoToggleToOff']) AND ($prop['NoToggleToOff'] == 'true')) {
10242                 $ff += 1 << 14;
10243             }
10244             
10245             if (isset($prop['Radio']) AND ($prop['Radio'] == 'true')) {
10246                 $ff += 1 << 15;
10247             }
10248             
10249             if (isset($prop['Pushbutton']) AND ($prop['Pushbutton'] == 'true')) {
10250                 $ff += 1 << 16;
10251             }
10252             
10253             if (isset($prop['Combo']) AND ($prop['Combo'] == 'true')) {
10254                 $ff += 1 << 17;
10255             }
10256             
10257             if (isset($prop['editable']) AND ($prop['editable'] == 'true')) {
10258                 $ff += 1 << 18;
10259             }
10260             
10261             if (isset($prop['Sort']) AND ($prop['Sort'] == 'true')) {
10262                 $ff += 1 << 19;
10263             }
10264             
10265             if (isset($prop['fileSelect']) AND ($prop['fileSelect'] == 'true')) {
10266                 $ff += 1 << 20;
10267             }
10268             
10269             if (isset($prop['multipleSelection']) AND ($prop['multipleSelection'] == 'true')) {
10270                 $ff += 1 << 21;
10271             }
10272             
10273             if (isset($prop['doNotSpellCheck']) AND ($prop['doNotSpellCheck'] == 'true')) {
10274                 $ff += 1 << 22;
10275             }
10276             
10277             if (isset($prop['doNotScroll']) AND ($prop['doNotScroll'] == 'true')) {
10278                 $ff += 1 << 23;
10279             }
10280             
10281             if (isset($prop['comb']) AND ($prop['comb'] == 'true')) {
10282                 $ff += 1 << 24;
10283             }
10284             
10285             if (isset($prop['radiosInUnison']) AND ($prop['radiosInUnison'] == 'true')) {
10286                 $ff += 1 << 25;
10287             }
10288             
10289             if (isset($prop['richText']) AND ($prop['richText'] == 'true')) {
10290                 $ff += 1 << 25;
10291             }
10292             
10293             if (isset($prop['commitOnSelChange']) AND ($prop['commitOnSelChange'] == 'true')) {
10294                 $ff += 1 << 26;
10295             }
10296             $opt['ff'] = $ff;
10297             
10298             if (isset($prop['defaultValue'])) {
10299                 $opt['dv'] = $prop['defaultValue'];
10300             }
10301             $f = 4; 
10302             
10303             if (isset($prop['readonly']) AND ($prop['readonly'] == 'true')) {
10304                 $f += 1 << 6;
10305             }
10306             
10307             if (isset($prop['display'])) {
10308                 if ($prop['display'] == 'display.visible') {
10309                     
10310                 } elseif ($prop['display'] == 'display.hidden') {
10311                     $f += 1 << 1;
10312                 } elseif ($prop['display'] == 'display.noPrint') {
10313                     $f -= 1 << 2;
10314                 } elseif ($prop['display'] == 'display.noView') {
10315                     $f += 1 << 5;
10316                 }
10317             }
10318             $opt['f'] = $f;
10319             
10320             if (isset($prop['currentValueIndices']) AND is_array($prop['currentValueIndices'])) {
10321                 $opt['i'] = $prop['currentValueIndices'];
10322             }
10323             
10324             if (isset($prop['value'])) {
10325                 if (is_array($prop['value'])) {
10326                     $opt['opt'] = array();
10327                     foreach ($prop['value'] AS $key => $optval) {
10328                         
10329                         if (isset($prop['exportValues'][$key])) {
10330                             $opt['opt'][$key] = array($prop['exportValues'][$key], $prop['value'][$key]);
10331                         } else {
10332                             $opt['opt'][$key] = $prop['value'][$key];
10333                         }
10334                     }
10335                 } else {
10336                     $opt['v'] = $prop['value'];
10337                 }
10338             }
10339             
10340             if (isset($prop['richValue'])) {
10341                 $opt['rv'] = $prop['richValue'];
10342             }
10343             
10344             if (isset($prop['submitName'])) {
10345                 $opt['tm'] = $prop['submitName'];
10346             }
10347             
10348             if (isset($prop['name'])) {
10349                 $opt['t'] = $prop['name'];
10350             }
10351             
10352             if (isset($prop['userName'])) {
10353                 $opt['tu'] = $prop['userName'];
10354             }
10355             
10356             if (isset($prop['highlight'])) {
10357                 switch ($prop['highlight']) {
10358                     case 'none':
10359                     case 'highlight.n': {
10360                         $opt['h'] = 'N';
10361                         break;
10362                     }
10363                     case 'invert':
10364                     case 'highlight.i': {
10365                         $opt['h'] = 'i';
10366                         break;
10367                     }
10368                     case 'push':
10369                     case 'highlight.p': {
10370                         $opt['h'] = 'P';
10371                         break;
10372                     }
10373                     case 'outline':
10374                     case 'highlight.o': {
10375                         $opt['h'] = 'O';
10376                         break;
10377                     }
10378                 }               
10379             }
10380             
10381             
10382             
10383             
10384             
10385             
10386             return $opt;
10387         }
10388         
10389         
10390 
10391 
10392 
10393 
10394 
10395 
10396         public function setFormDefaultProp($prop=array()) {
10397             $this->default_form_prop = $prop;
10398         }
10399         
10400         
10401 
10402 
10403 
10404 
10405 
10406 
10407         public function getFormDefaultProp() {
10408             return $this->default_form_prop;
10409         }
10410         
10411         
10412 
10413 
10414 
10415 
10416 
10417 
10418 
10419 
10420 
10421 
10422 
10423 
10424 
10425         public function TextField($name, $w, $h, $prop=array(), $opt=array(), $x='', $y='', $js=false) {
10426             if ($x === '') {
10427                 $x = $this->x;
10428             }
10429             if ($y === '') {
10430                 $y = $this->y;
10431             }
10432             if ($js) {
10433                 $this->_addfield('text', $name, $x, $y, $w, $h, $prop);
10434                 return;
10435             }
10436             
10437             $prop = array_merge($this->getFormDefaultProp(), $prop);
10438             
10439             $popt = $this->getAnnotOptFromJSProp($prop);
10440             
10441             $font = $this->FontFamily;
10442             $fontkey = array_search($font, $this->fontkeys);
10443             if (!in_array($fontkey, $this->annotation_fonts)) {
10444                 $this->annotation_fonts[$font] = $fontkey;
10445             }
10446             $fontstyle = sprintf('/F%d %.2F Tf %s', ($fontkey + 1), $this->FontSizePt, $this->TextColor);
10447             $popt['da'] = $fontstyle;
10448             $popt['ap'] = array();
10449             $popt['ap']['n'] = 'q BT '.$fontstyle.' ET Q';
10450             
10451             $opt = array_merge($popt, $opt);
10452             
10453             unset($opt['bs']);
10454             
10455             $opt['Subtype'] = 'Widget';
10456             $opt['ft'] = 'Tx';
10457             $opt['t'] = $name;
10458             
10459 
10460 
10461 
10462 
10463 
10464 
10465 
10466 
10467 
10468 
10469 
10470 
10471 
10472 
10473 
10474 
10475 
10476 
10477 
10478 
10479 
10480 
10481 
10482 
10483 
10484 
10485 
10486 
10487 
10488 
10489 
10490 
10491 
10492 
10493             $this->Annotation($x, $y, $w, $h, $name, $opt, 0);
10494             if ($this->rtl) {
10495                 $this->x -= $w;
10496             } else {
10497                 $this->x += $w;
10498             }
10499         }
10500 
10501         
10502 
10503 
10504 
10505 
10506 
10507 
10508 
10509 
10510 
10511 
10512 
10513 
10514 
10515 
10516         public function RadioButton($name, $w, $prop=array(), $opt=array(), $onvalue='On', $checked=false, $x='', $y='', $js=false) {
10517             if ($x === '') {
10518                 $x = $this->x;
10519             }
10520             if ($y === '') {
10521                 $y = $this->y;
10522             }
10523             if ($js) {
10524                 $this->_addfield('radiobutton', $name, $x, $y, $w, $w, $prop);
10525                 return;
10526             }
10527             if ($this->empty_string($onvalue)) {
10528                 $onvalue = 'On';
10529             }
10530             if ($checked) {
10531                 $defval = $onvalue;
10532             } else {
10533                 $defval = 'Off';
10534             }
10535             
10536             if (!isset($this->radiobutton_groups[$this->page])) {
10537                 $this->radiobutton_groups[$this->page] = array();
10538             }
10539             if (!isset($this->radiobutton_groups[$this->page][$name])) {
10540                 $this->radiobutton_groups[$this->page][$name] = array();
10541                 ++$this->annot_obj_id;
10542                 $this->radio_groups[] = $this->annot_obj_id;
10543             }
10544             
10545             $this->radiobutton_groups[$this->page][$name][] = array('kid' => ($this->annot_obj_id + 1), 'def' => $defval);
10546             
10547             $prop = array_merge($this->getFormDefaultProp(), $prop);
10548             $prop['NoToggleToOff'] = 'true';
10549             $prop['Radio'] = 'true';
10550             $prop['borderStyle'] = 'inset';
10551             
10552             $popt = $this->getAnnotOptFromJSProp($prop);
10553             
10554             $font = 'zapfdingbats';
10555             $this->AddFont($font);
10556             $fontkey = array_search($font, $this->fontkeys);
10557             if (!in_array($fontkey, $this->annotation_fonts)) {
10558                 $this->annotation_fonts[$font] = $fontkey;
10559             }
10560             $fontstyle = sprintf('/F%d %.2F Tf %s', ($fontkey + 1), $this->FontSizePt, $this->TextColor);
10561             $popt['da'] = $fontstyle;
10562             $popt['ap'] = array();
10563             $popt['ap']['n'] = array();
10564             $popt['ap']['n'][$onvalue] = 'q BT '.$fontstyle.' 0 0 Td (8) Tj ET Q';
10565             $popt['ap']['n']['Off'] = 'q BT '.$fontstyle.' 0 0 Td (8) Tj ET Q';
10566             if (!isset($popt['mk'])) {
10567                 $popt['mk'] = array();
10568             }
10569             $popt['mk']['ca'] = '(l)';
10570             
10571             $opt = array_merge($popt, $opt);
10572             
10573             $opt['Subtype'] = 'Widget';
10574             $opt['ft'] = 'Btn';
10575             if ($checked) {
10576                 $opt['v'] = array('/'.$onvalue);
10577                 $opt['as'] = $onvalue;
10578             } else {
10579                 $opt['as'] = 'Off';
10580             }
10581             $this->Annotation($x, $y, $w, $w, $name, $opt, 0);
10582             if ($this->rtl) {
10583                 $this->x -= $w;
10584             } else {
10585                 $this->x += $w;
10586             }
10587         }
10588         
10589         
10590 
10591 
10592 
10593 
10594 
10595 
10596 
10597 
10598 
10599 
10600 
10601 
10602 
10603 
10604         public function ListBox($name, $w, $h, $values, $prop=array(), $opt=array(), $x='', $y='', $js=false) {
10605             if ($x === '') {
10606                 $x = $this->x;
10607             }
10608             if ($y === '') {
10609                 $y = $this->y;
10610             }
10611             if ($js) {
10612                 $this->_addfield('listbox', $name, $x, $y, $w, $h, $prop);
10613                 $s = '';
10614                 foreach ($values as $value) {
10615                     $s .= "'".addslashes($value)."',";
10616                 }
10617                 $this->javascript .= 'f'.$name.'.setItems(['.substr($s, 0, -1)."]);\n";
10618                 return;
10619             }
10620             
10621             $prop = array_merge($this->getFormDefaultProp(), $prop);
10622             
10623             $popt = $this->getAnnotOptFromJSProp($prop);
10624             
10625             $font = $this->FontFamily;
10626             $fontkey = array_search($font, $this->fontkeys);
10627             if (!in_array($fontkey, $this->annotation_fonts)) {
10628                 $this->annotation_fonts[$font] = $fontkey;
10629             }
10630             $fontstyle = sprintf('/F%d %.2F Tf %s', ($fontkey + 1), $this->FontSizePt, $this->TextColor);
10631             $popt['da'] = $fontstyle;
10632             $popt['ap'] = array();
10633             $popt['ap']['n'] = 'q BT '.$fontstyle.' ET Q';
10634             
10635             $opt = array_merge($popt, $opt);
10636             
10637             $opt['Subtype'] = 'Widget';
10638             $opt['ft'] = 'Ch';
10639             $opt['t'] = $name;
10640             $opt['opt'] = $values;
10641             $this->Annotation($x, $y, $w, $h, $name, $opt, 0);
10642             if ($this->rtl) {
10643                 $this->x -= $w;
10644             } else {
10645                 $this->x += $w;
10646             }
10647         }
10648         
10649         
10650 
10651 
10652 
10653 
10654 
10655 
10656 
10657 
10658 
10659 
10660 
10661 
10662 
10663 
10664         public function ComboBox($name, $w, $h, $values, $prop=array(), $opt=array(), $x='', $y='', $js=false) {
10665             if ($x === '') {
10666                 $x = $this->x;
10667             }
10668             if ($y === '') {
10669                 $y = $this->y;
10670             }
10671             if ($js) {
10672                 $this->_addfield('combobox', $name, $x, $y, $w, $h, $prop);
10673                 $s = '';
10674                 foreach ($values as $value) {
10675                     $s .= "'".addslashes($value)."',";
10676                 }
10677                 $this->javascript .= 'f'.$name.'.setItems(['.substr($s, 0, -1)."]);\n";
10678                 return;
10679             }
10680             
10681             $prop = array_merge($this->getFormDefaultProp(), $prop);
10682             $prop['Combo'] = true;
10683             
10684             $popt = $this->getAnnotOptFromJSProp($prop);
10685             
10686             $font = $this->FontFamily;
10687             $fontkey = array_search($font, $this->fontkeys);
10688             if (!in_array($fontkey, $this->annotation_fonts)) {
10689                 $this->annotation_fonts[$font] = $fontkey;
10690             }
10691             $fontstyle = sprintf('/F%d %.2F Tf %s', ($fontkey + 1), $this->FontSizePt, $this->TextColor);
10692             $popt['da'] = $fontstyle;
10693             $popt['ap'] = array();
10694             $popt['ap']['n'] = 'q BT '.$fontstyle.' ET Q';
10695             
10696             $opt = array_merge($popt, $opt);
10697             
10698             $opt['Subtype'] = 'Widget';
10699             $opt['ft'] = 'Ch';
10700             $opt['t'] = $name;
10701             $opt['opt'] = $values;
10702             $this->Annotation($x, $y, $w, $h, $name, $opt, 0);
10703             if ($this->rtl) {
10704                 $this->x -= $w;
10705             } else {
10706                 $this->x += $w;
10707             }
10708         }
10709         
10710         
10711 
10712 
10713 
10714 
10715 
10716 
10717 
10718 
10719 
10720 
10721 
10722 
10723 
10724 
10725         public function CheckBox($name, $w, $checked=false, $prop=array(), $opt=array(), $onvalue='Yes', $x='', $y='', $js=false) {
10726             if ($x === '') {
10727                 $x = $this->x;
10728             }
10729             if ($y === '') {
10730                 $y = $this->y;
10731             }
10732             if ($js) {
10733                 $this->_addfield('checkbox', $name, $x, $y, $w, $w, $prop);
10734                 return;
10735             }
10736             if (!isset($prop['value'])) {
10737                 $prop['value'] = array('Yes');
10738             }
10739             
10740             $prop = array_merge($this->getFormDefaultProp(), $prop);
10741             $prop['borderStyle'] = 'inset';
10742             
10743             $popt = $this->getAnnotOptFromJSProp($prop);
10744             
10745             $font = 'zapfdingbats';
10746             $this->AddFont($font);
10747             $fontkey = array_search($font, $this->fontkeys);
10748             if (!in_array($fontkey, $this->annotation_fonts)) {
10749                 $this->annotation_fonts[$font] = $fontkey;
10750             }
10751             $fontstyle = sprintf('/F%d %.2F Tf %s', ($fontkey + 1), $this->FontSizePt, $this->TextColor);
10752             $popt['da'] = $fontstyle;
10753             $popt['ap'] = array();
10754             $popt['ap']['n'] = array();
10755             $popt['ap']['n']['Yes'] = 'q BT '.$fontstyle.' 0 0 Td (8) Tj ET Q';
10756             $popt['ap']['n']['Off'] = 'q BT '.$fontstyle.' 0 0 Td (8) Tj ET Q';
10757             
10758             $opt = array_merge($popt, $opt);
10759             
10760             $opt['Subtype'] = 'Widget';
10761             $opt['ft'] = 'Btn';
10762             $opt['t'] = $name;
10763             $opt['opt'] = array($onvalue);
10764             if ($checked) {
10765                 $opt['v'] = array('/0');
10766                 $opt['as'] = 'Yes';
10767             } else {
10768                 $opt['v'] = array('/Off');
10769                 $opt['as'] = 'Off';
10770             }
10771             $this->Annotation($x, $y, $w, $w, $name, $opt, 0);
10772             if ($this->rtl) {
10773                 $this->x -= $w;
10774             } else {
10775                 $this->x += $w;
10776             }
10777         }
10778         
10779         
10780 
10781 
10782 
10783 
10784 
10785 
10786 
10787 
10788 
10789 
10790 
10791 
10792 
10793 
10794 
10795         public function Button($name, $w, $h, $caption, $action, $prop=array(), $opt=array(), $x='', $y='', $js=false) {
10796             if ($x === '') {
10797                 $x = $this->x;
10798             }
10799             if ($y === '') {
10800                 $y = $this->y;
10801             }
10802             if ($js) {
10803                 $this->_addfield('button', $name, $this->x, $this->y, $w, $h, $prop);
10804                 $this->javascript .= 'f'.$name.".buttonSetCaption('".addslashes($caption)."');\n";
10805                 $this->javascript .= 'f'.$name.".setAction('MouseUp','".addslashes($action)."');\n";
10806                 $this->javascript .= 'f'.$name.".highlight='push';\n";
10807                 $this->javascript .= 'f'.$name.".print=false;\n";
10808                 return;
10809             }
10810             
10811             $prop = array_merge($this->getFormDefaultProp(), $prop);
10812             $prop['Pushbutton'] = 'true';
10813             $prop['highlight'] = 'push';
10814             $prop['display'] = 'display.noPrint';
10815             
10816             $popt = $this->getAnnotOptFromJSProp($prop);
10817             
10818             if (!isset($popt['mk'])) {
10819                 $popt['mk'] = array();
10820             }
10821             $popt['mk']['ca'] = $this->_textstring($caption);
10822             $popt['mk']['rc'] = $this->_textstring($caption);
10823             $popt['mk']['ac'] = $this->_textstring($caption);
10824             $font = $this->FontFamily;
10825             $fontkey = array_search($font, $this->fontkeys);
10826             if (!in_array($fontkey, $this->annotation_fonts)) {
10827                 $this->annotation_fonts[$font] = $fontkey;
10828             }
10829             $fontstyle = sprintf('/F%d %.2F Tf %s', ($fontkey + 1), $this->FontSizePt, $this->TextColor);
10830             $popt['da'] = $fontstyle;
10831             $popt['ap'] = array();
10832             $popt['ap']['n'] = 'q BT '.$fontstyle.' ET Q';
10833             
10834             $opt = array_merge($popt, $opt);
10835             
10836             $opt['Subtype'] = 'Widget';
10837             $opt['ft'] = 'Btn';
10838             $opt['t'] = $caption;
10839             $opt['v'] = $name;
10840             if (!empty($action)) {
10841                 if (is_array($action)) {
10842                     
10843                     $opt['aa'] = '/D <<';
10844                     $bmode = array('SubmitForm', 'ResetForm', 'ImportData');
10845                     foreach ($action AS $key => $val) {
10846                         if (($key == 'S') AND in_array($val, $bmode)) {
10847                             $opt['aa'] .= ' /S /'.$val;
10848                         } elseif (($key == 'F') AND (!empty($val))) {
10849                             $opt['aa'] .= ' /F '.$this->_datastring($val);
10850                         } elseif (($key == 'Fields') AND is_array($val) AND !empty($val)) {
10851                             $opt['aa'] .= ' /Fields [';
10852                             foreach ($val AS $field) {
10853                                 $opt['aa'] .= ' '.$this->_textstring($field);
10854                             }
10855                             $opt['aa'] .= ']';
10856                         } elseif (($key == 'Flags')) {
10857                             $ff = 0;
10858                             if (is_array($val)) {
10859                                 foreach ($val AS $flag) {
10860                                     switch ($flag) {
10861                                         case 'Include/Exclude': {
10862                                             $ff += 1 << 0;
10863                                             break;
10864                                         }
10865                                         case 'IncludeNoValueFields': {
10866                                             $ff += 1 << 1;
10867                                             break;
10868                                         }
10869                                         case 'ExportFormat': {
10870                                             $ff += 1 << 2;
10871                                             break;
10872                                         }
10873                                         case 'GetMethod': {
10874                                             $ff += 1 << 3;
10875                                             break;
10876                                         }
10877                                         case 'SubmitCoordinates': {
10878                                             $ff += 1 << 4;
10879                                             break;
10880                                         }
10881                                         case 'XFDF': {
10882                                             $ff += 1 << 5;
10883                                             break;
10884                                         }
10885                                         case 'IncludeAppendSaves': {
10886                                             $ff += 1 << 6;
10887                                             break;
10888                                         }
10889                                         case 'IncludeAnnotations': {
10890                                             $ff += 1 << 7;
10891                                             break;
10892                                         }
10893                                         case 'SubmitPDF': {
10894                                             $ff += 1 << 8;
10895                                             break;
10896                                         }
10897                                         case 'CanonicalFormat': {
10898                                             $ff += 1 << 9;
10899                                             break;
10900                                         }
10901                                         case 'ExclNonUserAnnots': {
10902                                             $ff += 1 << 10;
10903                                             break;
10904                                         }
10905                                         case 'ExclFKey': {
10906                                             $ff += 1 << 11;
10907                                             break;
10908                                         }
10909                                         case 'EmbedForm': {
10910                                             $ff += 1 << 13;
10911                                             break;
10912                                         }
10913                                     }
10914                                 }
10915                             } else {
10916                                 $ff = intval($val);
10917                             }
10918                             $opt['aa'] .= ' /Flags '.$ff;
10919                         }
10920                     }
10921                     $opt['aa'] .= ' >>';
10922                 } else {
10923                     
10924                     $js_obj_id = $this->addJavascriptObject($action);
10925                     $opt['aa'] = '/D '.$js_obj_id.' 0 R';
10926                 }
10927             }
10928             $this->Annotation($x, $y, $w, $h, $name, $opt, 0);
10929             if ($this->rtl) {
10930                 $this->x -= $w;
10931             } else {
10932                 $this->x += $w;
10933             }
10934         }
10935         
10936         
10937         
10938         
10939 
10940 
10941 
10942 
10943 
10944 
10945         protected function _putsignature() {
10946             if ((!$this->sign) OR (!isset($this->signature_data['cert_type']))) {
10947                 return;
10948             }
10949             $this->_out('/Type /Sig');
10950             $this->_out('/Filter /Adobe.PPKLite');
10951             $this->_out('/SubFilter /adbe.pkcs7.detached');
10952             $this->_out($this->byterange_string);
10953             $this->_out('/Contents<>'.str_repeat(' ', $this->signature_max_lenght));
10954             $this->_out('/Reference');
10955             $this->_out('[');
10956             $this->_out('<<');
10957             $this->_out('/Type /SigRef');
10958             if ($this->signature_data['cert_type'] > 0) {
10959                 $this->_out('/TransformMethod /DocMDP');
10960                 $this->_out('/TransformParams');
10961                 $this->_out('<<');
10962                 $this->_out('/Type /TransformParams');
10963                 $this->_out('/V /1.2');
10964                 $this->_out('/P '.$this->signature_data['cert_type'].'');
10965             } else {
10966                 $this->_out('/TransformMethod /UR3');
10967                 $this->_out('/TransformParams');
10968                 $this->_out('<<');
10969                 $this->_out('/Type /TransformParams');
10970                 $this->_out('/V /2.2');
10971                 if (!$this->empty_string($this->ur_document)) {
10972                     $this->_out('/Document['.$this->ur_document.']');
10973                 }
10974                 if (!$this->empty_string($this->ur_annots)) {
10975                     $this->_out('/Annots['.$this->ur_annots.']');
10976                 }
10977                 if (!$this->empty_string($this->ur_form)) {
10978                     $this->_out('/Form['.$this->ur_form.']');
10979                 }
10980                 if (!$this->empty_string($this->ur_signature)) {
10981                     $this->_out('/Signature['.$this->ur_signature.']');
10982                 }
10983             }
10984             $this->_out('>>');
10985             $this->_out('>>');
10986             $this->_out(']');
10987             if (isset($this->signature_data['info']['Name']) AND !$this->empty_string($this->signature_data['info']['Name'])) {
10988                 $this->_out('/Name '.$this->_textstring($this->signature_data['info']['Name']).'');
10989             }
10990             if (isset($this->signature_data['info']['Location']) AND !$this->empty_string($this->signature_data['info']['Location'])) {
10991                 $this->_out('/Location '.$this->_textstring($this->signature_data['info']['Location']).'');
10992             }
10993             if (isset($this->signature_data['info']['Reason']) AND !$this->empty_string($this->signature_data['info']['Reason'])) {
10994                 $this->_out('/Reason '.$this->_textstring($this->signature_data['info']['Reason']).'');
10995             }
10996             if (isset($this->signature_data['info']['ContactInfo']) AND !$this->empty_string($this->signature_data['info']['ContactInfo'])) {
10997                 $this->_out('/ContactInfo '.$this->_textstring($this->signature_data['info']['ContactInfo']).'');
10998             }
10999             $this->_out('/M '.$this->_datestring());
11000         }
11001         
11002         
11003 
11004 
11005 
11006 
11007 
11008 
11009 
11010 
11011 
11012 
11013 
11014 
11015 
11016         public function setUserRights(
11017                 $enable=true, 
11018                 $document='/FullSave',
11019                 $annots='/Create/Delete/Modify/Copy/Import/Export',
11020                 $form='/Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate',
11021                 $signature='/Modify') {
11022             $this->ur = $enable;
11023             $this->ur_document = $document;
11024             $this->ur_annots = $annots;
11025             $this->ur_form = $form;
11026             $this->ur_signature = $signature;
11027             if (!$this->sign) {
11028                 
11029                 $this->setSignature('', '', '', '', 0, array());
11030             }
11031         }
11032         
11033         
11034 
11035 
11036 
11037 
11038 
11039 
11040 
11041 
11042 
11043 
11044 
11045 
11046         public function setSignature($signing_cert='', $private_key='', $private_key_password='', $extracerts='', $cert_type=2, $info=array()) {
11047             
11048             
11049             
11050             $this->sign = true;
11051             $this->signature_data = array();
11052             if (strlen($signing_cert) == 0) {
11053                 $signing_cert = 'file://'.dirname(__FILE__).'/tcpdf.crt';
11054                 $private_key_password = 'tcpdfdemo';
11055             }
11056             if (strlen($private_key) == 0) {
11057                 $private_key = $signing_cert;
11058             }
11059             $this->signature_data['signcert'] = $signing_cert;
11060             $this->signature_data['privkey'] = $private_key;
11061             $this->signature_data['password'] = $private_key_password;
11062             $this->signature_data['extracerts'] = $extracerts;
11063             $this->signature_data['cert_type'] = $cert_type;
11064             $this->signature_data['info'] = $info;
11065         }
11066         
11067         
11068 
11069 
11070 
11071 
11072 
11073 
11074         public function startPageGroup($page='') {
11075             if (empty($page)) {
11076                 $page = $this->page + 1;
11077             }
11078             $this->newpagegroup[$page] = true;
11079         }
11080 
11089         public function AliasNbPages($alias='{nb}') {
11090             $this->AliasNbPages = $alias;
11091         }
11092         
11101         public function getAliasNbPages() {
11102             if (($this->CurrentFont['type'] == 'TrueTypeUnicode') OR ($this->CurrentFont['type'] == 'cidfont0')) {
11103                 return '{'.$this->AliasNbPages.'}';
11104             }
11105             return $this->AliasNbPages;
11106         }
11107 
11116         public function AliasNumPage($alias='{pnb}') {
11117             
11118             $this->AliasNumPage = $alias;
11119         }
11120         
11129         public function getAliasNumPage() {
11130             if (($this->CurrentFont['type'] == 'TrueTypeUnicode') OR ($this->CurrentFont['type'] == 'cidfont0')) {
11131                 return '{'.$this->AliasNumPage.'}';
11132             }
11133             return $this->AliasNumPage;
11134         }
11135         
11136         
11137 
11138 
11139 
11140 
11141 
11142         public function getGroupPageNo() {
11143             return $this->pagegroups[$this->currpagegroup];
11144         }
11145 
11152         public function getGroupPageNoFormatted() {
11153             return $this->formatPageNumber($this->getGroupPageNo());
11154         }
11155         
11156         
11157 
11158 
11159 
11160 
11161 
11162 
11163 
11164         public function getPageGroupAlias() {
11165             if (($this->CurrentFont['type'] == 'TrueTypeUnicode') OR ($this->CurrentFont['type'] == 'cidfont0')) {
11166                 return '{'.$this->currpagegroup.'}';
11167             }
11168             return $this->currpagegroup;
11169         }
11170         
11171         
11172 
11173 
11174 
11175 
11176 
11177 
11178 
11179         public function getPageNumGroupAlias() {
11180             if (($this->CurrentFont['type'] == 'TrueTypeUnicode') OR ($this->CurrentFont['type'] == 'cidfont0')) {
11181                 return '{'.str_replace('{nb', '{pnb', $this->currpagegroup).'}';
11182             }
11183             return str_replace('{nb', '{pnb', $this->currpagegroup);
11184         }
11185 
11193         protected function formatPageNumber($num) {
11194             return number_format((float)$num, 0, '', '.');
11195         }
11196 
11205         protected function formatTOCPageNumber($num) {
11206             return number_format((float)$num, 0, '', '.');
11207         }
11208 
11215         public function PageNoFormatted() {
11216             return $this->formatPageNumber($this->PageNo());
11217         }
11218 
11219         
11220 
11221 
11222 
11223 
11224         protected function _putocg() {
11225             $this->_newobj();
11226             $this->n_ocg_print = $this->n;
11227             $this->_out('<</Type /OCG /Name '.$this->_textstring('print'));
11228             $this->_out('/Usage <</Print <</PrintState /ON>> /View <</ViewState /OFF>>>>>>');
11229             $this->_out('endobj');
11230             $this->_newobj();
11231             $this->n_ocg_view = $this->n;
11232             $this->_out('<</Type /OCG /Name '.$this->_textstring('view'));
11233             $this->_out('/Usage <</Print <</PrintState /OFF>> /View <</ViewState /ON>>>>>>');
11234             $this->_out('endobj');
11235         }
11236         
11237         
11238 
11239 
11240 
11241 
11242 
11243 
11244 
11245         public function setVisibility($v) {
11246             if ($this->openMarkedContent) {
11247                 
11248                 $this->_out('EMC');
11249                 $this->openMarkedContent = false;
11250             }
11251             switch($v) {
11252                 case 'print': {
11253                     $this->_out('/OC /OC1 BDC');
11254                     $this->openMarkedContent = true;
11255                     break;
11256                 }
11257                 case 'screen': {
11258                     $this->_out('/OC /OC2 BDC');
11259                     $this->openMarkedContent = true;
11260                     break;
11261                 }
11262                 case 'all': {
11263                     $this->_out('');
11264                     break;
11265                 }
11266                 default: {
11267                     $this->Error('Incorrect visibility: '.$v);
11268                     break;
11269                 }
11270             }
11271             $this->visibility = $v;
11272         }
11273         
11274         
11275 
11276 
11277 
11278 
11279 
11280 
11281         protected function addExtGState($parms) {
11282             $n = count($this->extgstates) + 1;
11283             $this->extgstates[$n]['parms'] = $parms;
11284             return $n;
11285         }
11286         
11287         
11288 
11289 
11290 
11291 
11292 
11293         protected function setExtGState($gs) {
11294             $this->_out(sprintf('/GS%d gs', $gs));
11295         }
11296         
11297         
11298 
11299 
11300 
11301 
11302 
11303         protected function _putextgstates() {
11304             $ne = count($this->extgstates);
11305             for ($i = 1; $i <= $ne; ++$i) {
11306                 $this->_newobj();
11307                 $this->extgstates[$i]['n'] = $this->n;
11308                 $this->_out('<</Type /ExtGState');
11309                 foreach ($this->extgstates[$i]['parms'] as $k => $v) {
11310                     $this->_out('/'.$k.' '.$v);
11311                 }
11312                 $this->_out('>>');
11313                 $this->_out('endobj');
11314             }
11315         }
11316         
11317         
11318 
11319 
11320 
11321 
11322 
11323 
11324         public function setAlpha($alpha, $bm='Normal') {
11325             $gs = $this->addExtGState(array('ca' => $alpha, 'CA' => $alpha, 'BM' => '/'.$bm));
11326             $this->setExtGState($gs);
11327         }
11328 
11329         
11330 
11331 
11332 
11333 
11334 
11335         public function setJPEGQuality($quality) {
11336             if (($quality < 1) OR ($quality > 100)) {
11337                 $quality = 75;
11338             }
11339             $this->jpeg_quality = intval($quality);
11340         }
11341         
11342         
11343 
11344 
11345 
11346 
11347 
11348         public function setDefaultTableColumns($cols=4) { 
11349             $this->default_table_columns = intval($cols); 
11350         }
11351         
11352         
11353 
11354 
11355 
11356 
11357 
11358         public function setCellHeightRatio($h) { 
11359             $this->cell_height_ratio = $h; 
11360         }
11361         
11362         
11363 
11364 
11365 
11366 
11367         public function getCellHeightRatio() { 
11368             return $this->cell_height_ratio; 
11369         }
11370         
11371         
11372 
11373 
11374 
11375 
11376 
11377         public function setPDFVersion($version='1.7') { 
11378             $this->PDFVersion = $version;
11379         }
11380         
11381         
11382 
11383 
11384 
11385 
11386 
11387 
11388 
11389 
11390 
11391 
11392 
11393 
11394 
11395 
11396 
11397 
11398 
11399 
11400 
11401 
11402 
11403 
11404 
11405 
11406 
11407         public function setViewerPreferences($preferences) { 
11408             $this->viewer_preferences = $preferences;
11409         }
11410         
11424         public function LinearGradient($x, $y, $w, $h, $col1=array(), $col2=array(), $coords=array(0,0,1,0)) {
11425             $this->Clip($x, $y, $w, $h);
11426             $this->Gradient(2, $col1, $col2, $coords);
11427         }
11428         
11442         public function RadialGradient($x, $y, $w, $h, $col1=array(), $col2=array(), $coords=array(0.5,0.5,0.5,0.5,1)) {
11443             $this->Clip($x, $y, $w, $h);
11444             $this->Gradient(3, $col1, $col2, $coords);
11445         }
11446         
11464         public function CoonsPatchMesh($x, $y, $w, $h, $col1=array(), $col2=array(), $col3=array(), $col4=array(), $coords=array(0.00,0.0,0.33,0.00,0.67,0.00,1.00,0.00,1.00,0.33,1.00,0.67,1.00,1.00,0.67,1.00,0.33,1.00,0.00,1.00,0.00,0.67,0.00,0.33), $coords_min=0, $coords_max=1) {
11465             $this->Clip($x, $y, $w, $h);        
11466             $n = count($this->gradients) + 1;
11467             $this->gradients[$n]['type'] = 6; 
11468             
11469             if (!isset($coords[0]['f'])) {
11470                 
11471                 if (!isset($col1[1])) {
11472                     $col1[1] = $col1[2] = $col1[0];
11473                 }
11474                 if (!isset($col2[1])) {
11475                     $col2[1] = $col2[2] = $col2[0];
11476                 }
11477                 if (!isset($col3[1])) {
11478                     $col3[1] = $col3[2] = $col3[0];
11479                 }
11480                 if (!isset($col4[1])) {
11481                     $col4[1] = $col4[2] = $col4[0];
11482                 }
11483                 $patch_array[0]['f'] = 0;
11484                 $patch_array[0]['points'] = $coords;
11485                 $patch_array[0]['colors'][0]['r'] = $col1[0];
11486                 $patch_array[0]['colors'][0]['g'] = $col1[1];
11487                 $patch_array[0]['colors'][0]['b'] = $col1[2];
11488                 $patch_array[0]['colors'][1]['r'] = $col2[0];
11489                 $patch_array[0]['colors'][1]['g'] = $col2[1];
11490                 $patch_array[0]['colors'][1]['b'] = $col2[2];
11491                 $patch_array[0]['colors'][2]['r'] = $col3[0];
11492                 $patch_array[0]['colors'][2]['g'] = $col3[1];
11493                 $patch_array[0]['colors'][2]['b'] = $col3[2];
11494                 $patch_array[0]['colors'][3]['r'] = $col4[0];
11495                 $patch_array[0]['colors'][3]['g'] = $col4[1];
11496                 $patch_array[0]['colors'][3]['b'] = $col4[2];
11497             } else {
11498                 
11499                 $patch_array = $coords;
11500             }
11501             $bpcd = 65535; 
11502             
11503             $this->gradients[$n]['stream'] = '';
11504             $count_patch = count($patch_array);
11505             for ($i=0; $i < $count_patch; ++$i) {
11506                 $this->gradients[$n]['stream'] .= chr($patch_array[$i]['f']); 
11507                 $count_points = count($patch_array[$i]['points']);
11508                 for ($j=0; $j < $count_points; ++$j) {
11509                     
11510                     $patch_array[$i]['points'][$j] = (($patch_array[$i]['points'][$j] - $coords_min) / ($coords_max - $coords_min)) * $bpcd;
11511                     if ($patch_array[$i]['points'][$j] < 0) {
11512                         $patch_array[$i]['points'][$j] = 0;
11513                     }
11514                     if ($patch_array[$i]['points'][$j] > $bpcd) {
11515                         $patch_array[$i]['points'][$j] = $bpcd;
11516                     }
11517                     $this->gradients[$n]['stream'] .= chr(floor($patch_array[$i]['points'][$j] / 256));
11518                     $this->gradients[$n]['stream'] .= chr(floor($patch_array[$i]['points'][$j] % 256));
11519                 }
11520                 $count_cols = count($patch_array[$i]['colors']);
11521                 for ($j=0; $j < $count_cols; ++$j) {
11522                     
11523                     $this->gradients[$n]['stream'] .= chr($patch_array[$i]['colors'][$j]['r']);
11524                     $this->gradients[$n]['stream'] .= chr($patch_array[$i]['colors'][$j]['g']);
11525                     $this->gradients[$n]['stream'] .= chr($patch_array[$i]['colors'][$j]['b']);
11526                 }
11527             }
11528             
11529             $this->_out('/Sh'.$n.' sh');
11530             
11531             $this->_out('Q');
11532         }
11533         
11544         protected function Clip($x, $y, $w, $h) {
11545             if ($this->rtl) {
11546                 $x = $this->w - $x - $w;
11547             }
11548             
11549             $s = 'q';
11550             
11551             $s .= sprintf(' %.2F %.2F %.2F %.2F re W n', $x*$this->k, ($this->h-$y)*$this->k, $w*$this->k, -$h*$this->k);
11552             
11553             $s .= sprintf(' %.3F 0 0 %.3F %.3F %.3F cm', $w*$this->k, $h*$this->k, $x*$this->k, ($this->h-($y+$h))*$this->k);
11554             $this->_out($s);
11555         }
11556                 
11567         protected function Gradient($type, $col1, $col2, $coords) {
11568             $n = count($this->gradients) + 1;
11569             $this->gradients[$n]['type'] = $type;
11570             if (!isset($col1[1])) {
11571                 $col1[1]=$col1[2]=$col1[0];
11572             }
11573             $this->gradients[$n]['col1'] = sprintf('%.3F %.3F %.3F', ($col1[0]/255), ($col1[1]/255), ($col1[2]/255));
11574             if (!isset($col2[1])) {
11575                 $col2[1] = $col2[2] = $col2[0];
11576             }
11577             $this->gradients[$n]['col2'] = sprintf('%.3F %.3F %.3F', ($col2[0]/255), ($col2[1]/255), ($col2[2]/255));
11578             $this->gradients[$n]['coords'] = $coords;
11579             
11580             $this->_out('/Sh'.$n.' sh');
11581             
11582             $this->_out('Q');
11583         }
11584         
11591         function _putshaders() {
11592             foreach ($this->gradients as $id => $grad) {  
11593                 if (($grad['type'] == 2) OR ($grad['type'] == 3)) {
11594                     $this->_newobj();
11595                     $this->_out('<<');
11596                     $this->_out('/FunctionType 2');
11597                     $this->_out('/Domain [0.0 1.0]');
11598                     $this->_out('/C0 ['.$grad['col1'].']');
11599                     $this->_out('/C1 ['.$grad['col2'].']');
11600                     $this->_out('/N 1');
11601                     $this->_out('>>');
11602                     $this->_out('endobj');
11603                     $f1 = $this->n;
11604                 }
11605                 $this->_newobj();
11606                 $this->_out('<<');
11607                 $this->_out('/ShadingType '.$grad['type']);
11608                 $this->_out('/ColorSpace /DeviceRGB');
11609                 if ($grad['type'] == 2) {
11610                     $this->_out(sprintf('/Coords [%.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3]));
11611                     $this->_out('/Function '.$f1.' 0 R');
11612                     $this->_out('/Extend [true true] ');
11613                     $this->_out('>>');
11614                 } elseif ($grad['type'] == 3) {
11615                     
11616                     
11617                     $this->_out(sprintf('/Coords [%.3F %.3F 0 %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3], $grad['coords'][4]));
11618                     $this->_out('/Function '.$f1.' 0 R');
11619                     $this->_out('/Extend [true true] ');
11620                     $this->_out('>>');
11621                 } elseif ($grad['type'] == 6) {
11622                     $this->_out('/BitsPerCoordinate 16');
11623                     $this->_out('/BitsPerComponent 8');
11624                     $this->_out('/Decode[0 1 0 1 0 1 0 1 0 1]');
11625                     $this->_out('/BitsPerFlag 8');
11626                     $this->_out('/Length '.strlen($grad['stream']));
11627                     $this->_out('>>');
11628                     $this->_putstream($grad['stream']);
11629                 }
11630                 $this->_out('endobj');
11631                 $this->gradients[$id]['id'] = $this->n;
11632             }
11633         }
11634 
11641         protected function _outarc($x1, $y1, $x2, $y2, $x3, $y3 ) {
11642             $h = $this->h;
11643             $this->_out(sprintf('%.2F %.2F %.2F %.2F %.2F %.2F c', $x1*$this->k, ($h-$y1)*$this->k, $x2*$this->k, ($h-$y2)*$this->k, $x3*$this->k, ($h-$y3)*$this->k));
11644         }
11645         
11661         public function PieSector($xc, $yc, $r, $a, $b, $style='FD', $cw=true, $o=90) {
11662             if ($this->rtl) {
11663                 $xc = $this->w - $xc;
11664             }
11665             if ($cw) {
11666                 $d = $b;
11667                 $b = $o - $a;
11668                 $a = $o - $d;
11669             } else {
11670                 $b += $o;
11671                 $a += $o;
11672             }
11673             $a = ($a % 360) + 360;
11674             $b = ($b % 360) + 360;
11675             if ($a > $b) {
11676                 $b +=360;
11677             }
11678             $b = $b / 360 * 2 * M_PI;
11679             $a = $a / 360 * 2 * M_PI;
11680             $d = $b - $a;
11681             if ($d == 0 ) {
11682                 $d = 2 * M_PI;
11683             }
11684             $k = $this->k;
11685             $hp = $this->h;
11686             if ($style=='F') {
11687                 $op = 'f';
11688             } elseif ($style=='FD' or $style=='DF') {
11689                 $op = 'b';
11690             } else {
11691                 $op = 's';
11692             }
11693             if (sin($d/2)) {
11694                 $MyArc = 4/3 * (1 - cos($d/2)) / sin($d/2) * $r;
11695             }
11696             
11697             $this->_out(sprintf('%.2F %.2F m', ($xc)*$k, ($hp-$yc)*$k));
11698             
11699             $this->_out(sprintf('%.2F %.2F l', ($xc+$r*cos($a))*$k, (($hp-($yc-$r*sin($a)))*$k)));
11700             
11701             if ($d < (M_PI/2)) {
11702                 $this->_outarc($xc+$r*cos($a)+$MyArc*cos(M_PI/2+$a), $yc-$r*sin($a)-$MyArc*sin(M_PI/2+$a), $xc+$r*cos($b)+$MyArc*cos($b-M_PI/2), $yc-$r*sin($b)-$MyArc*sin($b-M_PI/2), $xc+$r*cos($b), $yc-$r*sin($b));
11703             } else {
11704                 $b = $a + $d/4;
11705                 $MyArc = 4/3*(1-cos($d/8))/sin($d/8)*$r;
11706                 $this->_outarc($xc+$r*cos($a)+$MyArc*cos(M_PI/2+$a), $yc-$r*sin($a)-$MyArc*sin(M_PI/2+$a), $xc+$r*cos($b)+$MyArc*cos($b-M_PI/2), $yc-$r*sin($b)-$MyArc*sin($b-M_PI/2), $xc+$r*cos($b), $yc-$r*sin($b));
11707                 $a = $b;
11708                 $b = $a + $d/4;
11709                 $this->_outarc($xc+$r*cos($a)+$MyArc*cos(M_PI/2+$a), $yc-$r*sin($a)-$MyArc*sin(M_PI/2+$a), $xc+$r*cos($b)+$MyArc*cos($b-M_PI/2), $yc-$r*sin($b)-$MyArc*sin($b-M_PI/2), $xc+$r*cos($b), $yc-$r*sin($b));
11710                 $a = $b;
11711                 $b = $a + $d/4;
11712                 $this->_outarc($xc+$r*cos($a)+$MyArc*cos(M_PI/2+$a), $yc-$r*sin($a)-$MyArc*sin(M_PI/2+$a), $xc+$r*cos($b)+$MyArc*cos($b-M_PI/2), $yc-$r*sin($b)-$MyArc*sin($b-M_PI/2), $xc+$r*cos($b), $yc-$r*sin($b) );
11713                 $a = $b;
11714                 $b = $a + $d/4;
11715                 $this->_outarc($xc+$r*cos($a)+$MyArc*cos(M_PI/2+$a), $yc-$r*sin($a)-$MyArc*sin(M_PI/2+$a), $xc+$r*cos($b)+$MyArc*cos($b-M_PI/2), $yc-$r*sin($b)-$MyArc*sin($b-M_PI/2), $xc+$r*cos($b), $yc-$r*sin($b));
11716             }
11717             
11718             $this->_out($op);
11719         }
11720         
11739         public function ImageEps($file, $x='', $y='', $w=0, $h=0, $link='', $useBoundingBox=true, $align='', $palign='', $border=0) {
11740             if ($x === '') {
11741                 $x = $this->x;
11742             }
11743             if ($y === '') {
11744                 $y = $this->y;
11745             }
11746             $k = $this->k;
11747             $data = file_get_contents($file);
11748             if ($data === false) {
11749                 $this->Error('EPS file not found: '.$file);
11750             }
11751             $regs = array();
11752             
11753             preg_match("/%%Creator:([^\r\n]+)/", $data, $regs); # find Creator
11754             if (count($regs) > 1) {
11755                 $version_str = trim($regs[1]); # e.g. "Adobe Illustrator(R) 8.0"
11756                 if (strpos($version_str, 'Adobe Illustrator') !== false) {
11757                     $versexp = explode(' ', $version_str);
11758                     $version = (float)array_pop($versexp);
11759                     if ($version >= 9) {
11760                         $this->Error('This version of Adobe Illustrator file is not supported: '.$file);
11761                     }
11762                 }
11763             }
11764             
11765             $start = strpos($data, '%!PS-Adobe');
11766             if ($start > 0) {
11767                 $data = substr($data, $start);
11768             }
11769             
11770             preg_match("/%%BoundingBox:([^\r\n]+)/", $data, $regs);
11771             if (count($regs) > 1) {
11772                 list($x1, $y1, $x2, $y2) = explode(' ', trim($regs[1]));
11773             } else {
11774                 $this->Error('No BoundingBox found in EPS file: '.$file);
11775             }
11776             $start = strpos($data, '%%EndSetup');
11777             if ($start === false) {
11778                 $start = strpos($data, '%%EndProlog');
11779             }
11780             if ($start === false) {
11781                 $start = strpos($data, '%%BoundingBox');
11782             }
11783             $data = substr($data, $start);
11784             $end = strpos($data, '%%PageTrailer');
11785             if ($end===false) {
11786                 $end = strpos($data, 'showpage');
11787             }
11788             if ($end) {
11789                 $data = substr($data, 0, $end);
11790             }
11791             if ($w > 0) {
11792                 $scale_x = $w / (($x2 - $x1) / $k);
11793                 if ($h > 0) {
11794                     $scale_y = $h / (($y2 - $y1) / $k);
11795                 } else {
11796                     $scale_y = $scale_x;
11797                     $h = ($y2 - $y1) / $k * $scale_y;
11798                 }
11799             } else {
11800                 if ($h > 0) {
11801                     $scale_y = $h / (($y2 - $y1) / $k);
11802                     $scale_x = $scale_y;
11803                     $w = ($x2-$x1) / $k * $scale_x;
11804                 } else {
11805                     $w = ($x2 - $x1) / $k;
11806                     $h = ($y2 - $y1) / $k;
11807                 }
11808             }
11809             
11810             if ($this->checkPageBreak($h, $y)) {
11811                 $y = $this->GetY() + $this->cMargin;
11812             }
11813             
11814             $this->img_rb_y = $y + $h;
11815             
11816             if ($this->rtl) {
11817                 if ($palign == 'L') {
11818                     $ximg = $this->lMargin;
11819                     
11820                     $this->img_rb_x = $ximg + $w;
11821                 } elseif ($palign == 'C') {
11822                     $ximg = ($this->w - $x - $w) / 2;
11823                     
11824                     $this->img_rb_x = $ximg + $w;
11825                 } else {
11826                     $ximg = $this->w - $x - $w;
11827                     
11828                     $this->img_rb_x = $ximg;
11829                 }
11830             } else {
11831                 if ($palign == 'R') {
11832                     $ximg = $this->w - $this->rMargin - $w;
11833                     
11834                     $this->img_rb_x = $ximg;
11835                 } elseif ($palign == 'C') {
11836                     $ximg = ($this->w - $x - $w) / 2;
11837                     
11838                     $this->img_rb_x = $ximg + $w;
11839                 } else {
11840                     $ximg = $x;
11841                     
11842                     $this->img_rb_x = $ximg + $w;
11843                 }
11844             }
11845             if ($useBoundingBox) {
11846                 $dx = $ximg * $k - $x1;
11847                 $dy = $y * $k - $y1;
11848             } else {
11849                 $dx = $ximg * $k;
11850                 $dy = $y * $k;
11851             }
11852             
11853             $this->_out('q'.$this->epsmarker);
11854             
11855             $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F cm', 1, 0, 0, 1, $dx, $dy + ($this->hPt - (2 * $y * $k) - ($y2 - $y1))));
11856             
11857             if (isset($scale_x)) {
11858                 $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F cm', $scale_x, 0, 0, $scale_y, $x1 * (1 - $scale_x), $y2 * (1 - $scale_y)));
11859             }
11860             
11861             preg_match('/[\r\n]+/s', $data, $regs);
11862             $lines = explode($regs[0], $data);
11863             $u=0;
11864             $cnt = count($lines);
11865             for ($i=0; $i < $cnt; ++$i) {
11866                 $line = $lines[$i];
11867                 if (($line == '') OR ($line{0} == '%')) {
11868                     continue;
11869                 }
11870                 $len = strlen($line);
11871                 $chunks = explode(' ', $line);
11872                 $cmd = array_pop($chunks);
11873                 
11874                 if (($cmd == 'Xa') OR ($cmd == 'XA')) {
11875                     $b = array_pop($chunks); 
11876                     $g = array_pop($chunks); 
11877                     $r = array_pop($chunks);
11878                     $this->_out(''.$r.' '.$g.' '.$b.' '.($cmd=='Xa'?'rg':'RG')); 
11879                     continue;
11880                 }
11881                 switch ($cmd) {
11882                     case 'm':
11883                     case 'l':
11884                     case 'v':
11885                     case 'y':
11886                     case 'c':
11887                     case 'k':
11888                     case 'K':
11889                     case 'g':
11890                     case 'G':
11891                     case 's':
11892                     case 'S':
11893                     case 'J':
11894                     case 'j':
11895                     case 'w':
11896                     case 'M':
11897                     case 'd':
11898                     case 'n':
11899                     case 'v': {
11900                         $this->_out($line);
11901                         break;
11902                     }
11903                     case 'x': {
11904                         list($c,$m,$y,$k) = $chunks;
11905                         $this->_out(''.$c.' '.$m.' '.$y.' '.$k.' k');
11906                         break;
11907                     }
11908                     case 'X': { 
11909                         list($c,$m,$y,$k) = $chunks;
11910                         $this->_out(''.$c.' '.$m.' '.$y.' '.$k.' K');
11911                         break;
11912                     }
11913                     case 'Y':
11914                     case 'N':
11915                     case 'V':
11916                     case 'L':
11917                     case 'C': {
11918                         $line{$len-1} = strtolower($cmd);
11919                         $this->_out($line);
11920                         break;
11921                     }
11922                     case 'b':
11923                     case 'B': {
11924                         $this->_out($cmd . '*');
11925                         break;
11926                     }
11927                     case 'f':
11928                     case 'F': {
11929                         if ($u > 0) {
11930                             $isU = false;
11931                             $max = min($i+5, $cnt);
11932                             for ($j=$i+1; $j < $max; ++$j)
11933                               $isU = ($isU OR (($lines[$j] == 'U') OR ($lines[$j] == '*U')));
11934                             if ($isU) {
11935                                 $this->_out('f*');
11936                             }
11937                         } else {
11938                             $this->_out('f*');
11939                         }
11940                         break;
11941                     }
11942                     case '*u': {
11943                         ++$u;
11944                         break;
11945                     }
11946                     case '*U': {
11947                         --$u;
11948                         break;
11949                     }
11950                 }
11951             }
11952             
11953             $this->_out($this->epsmarker.'Q');
11954             if (!empty($border)) {
11955                 $bx = $x;
11956                 $by = $y;
11957                 $this->x = $x;
11958                 $this->y = $y;
11959                 $this->Cell($w, $h, '', $border, 0, '', 0, '', 0);
11960                 $this->x = $bx;
11961                 $this->y = $by;
11962             }
11963             if ($link) {
11964                 $this->Link($ximg, $y, $w, $h, $link, 0);
11965             }
11966             
11967             switch($align) {
11968                 case 'T':{
11969                     $this->y = $y;
11970                     $this->x = $this->img_rb_x;
11971                     break;
11972                 }
11973                 case 'M':{
11974                     $this->y = $y + round($h/2);
11975                     $this->x = $this->img_rb_x;
11976                     break;
11977                 }
11978                 case 'B':{
11979                     $this->y = $this->img_rb_y;
11980                     $this->x = $this->img_rb_x;
11981                     break;
11982                 }
11983                 case 'N':{
11984                     $this->SetY($this->img_rb_y);
11985                     break;
11986                 }
11987                 default:{
11988                     break;
11989                 }
11990             }
11991             $this->endlinex = $this->img_rb_x;
11992         }
11993         
11999         public function setBarcode($bc='') {
12000             $this->barcode = $bc;
12001         }
12002         
12009         public function getBarcode() {
12010             return $this->barcode;
12011         }
12012         
12028         public function write1DBarcode($code, $type, $x='', $y='', $w='', $h='', $xres=0.4, $style='', $align='') {
12029             if ($this->empty_string($code)) {
12030                 return;
12031             }
12032             require_once(dirname(__FILE__).'/barcodes.php');
12033             
12034             $gvars = $this->getGraphicVars();
12035             
12036             $barcodeobj = new TCPDFBarcode($code, $type);
12037             $arrcode = $barcodeobj->getBarcodeArray();
12038             if ($arrcode === false) {
12039                 $this->Error('Error in 1D barcode string');
12040             }
12041             
12042             if (!isset($style['position'])) {
12043                 if ($this->rtl) {
12044                     $style['position'] = 'R';
12045                 } else {
12046                     $style['position'] = 'L';
12047                 }
12048             }
12049             if (!isset($style['padding'])) {
12050                 $style['padding'] = 0;
12051             }
12052             if (!isset($style['fgcolor'])) {
12053                 $style['fgcolor'] = array(0,0,0); 
12054             }
12055             if (!isset($style['bgcolor'])) {
12056                 $style['bgcolor'] = false; 
12057             }
12058             if (!isset($style['border'])) {
12059                 $style['border'] = false;
12060             }
12061             $fontsize = 0;
12062             if (!isset($style['text'])) {
12063                 $style['text'] = false;
12064             }
12065             if ($style['text'] AND isset($style['font'])) {
12066                 if (isset($style['fontsize'])) {
12067                     $fontsize = $style['fontsize'];
12068                 }
12069                 $this->SetFont($style['font'], '', $fontsize);
12070             }
12071             if (!isset($style['stretchtext'])) {
12072                 $style['stretchtext'] = 4;
12073             }
12074             
12075             $this->SetDrawColorArray($style['fgcolor']);
12076             $this->SetTextColorArray($style['fgcolor']);
12077             if ($this->empty_string($w) OR ($w <= 0)) {
12078                 if ($this->rtl) {
12079                     $w = $this->x - $this->lMargin;
12080                 } else {
12081                     $w = $this->w - $this->rMargin - $this->x;
12082                 }
12083             }
12084             if ($this->empty_string($x)) {
12085                 $x = $this->GetX();
12086             }
12087             if ($this->rtl) {
12088                 $x = $this->w - $x;
12089             }
12090             if ($this->empty_string($y)) {
12091                 $y = $this->GetY();
12092             }
12093             if ($this->empty_string($xres)) {
12094                 $xres = 0.4;
12095             }
12096             $fbw = ($arrcode['maxw'] * $xres) + (2 * $style['padding']);
12097             $extraspace = ($this->cell_height_ratio * $fontsize / $this->k) + (2 * $style['padding']);
12098             if ($this->empty_string($h) OR ($h <= 0)) {
12099                 $h = 10 + $extraspace;
12100             }
12101             if ($this->checkPageBreak($h)) {
12102                 $y = $this->y;
12103             }
12104             
12105             $barh = $h - $extraspace;
12106             switch ($style['position']) {
12107                 case 'L': { 
12108                     if ($this->rtl) {
12109                         $xpos = $x - $w;
12110                     } else {
12111                         $xpos = $x;
12112                     }
12113                     break;
12114                 }
12115                 case 'C': { 
12116                     $xdiff = (($w - $fbw) / 2);
12117                     if ($this->rtl) {
12118                         $xpos = $x - $w + $xdiff;
12119                     } else {
12120                         $xpos = $x + $xdiff;
12121                     }
12122                     break;
12123                 }
12124                 case 'R': { 
12125                     if ($this->rtl) {
12126                         $xpos = $x - $fbw;
12127                     } else {
12128                         $xpos = $x + $w - $fbw;
12129                     }
12130                     break;
12131                 }
12132                 case 'S': { 
12133                     $fbw = $w;
12134                     $xres = ($w - (2 * $style['padding'])) / $arrcode['maxw'];
12135                     if ($this->rtl) {
12136                         $xpos = $x - $w;
12137                     } else {
12138                         $xpos = $x;
12139                     }
12140                     break;
12141                 }
12142             }
12143             $xpos_rect = $xpos;
12144             $xpos = $xpos_rect + $style['padding'];
12145             $xpos_text = $xpos;
12146             
12147             $tempRTL = $this->rtl;
12148             $this->rtl = false;
12149             
12150             if ($style['bgcolor']) {
12151                 $this->Rect($xpos_rect, $y, $fbw, $h, $style['border'] ? 'DF' : 'F', '', $style['bgcolor']);
12152             } elseif ($style['border']) {
12153                 $this->Rect($xpos_rect, $y, $fbw, $h, 'D');
12154             }
12155             
12156             if ($arrcode !== false) {
12157                 foreach ($arrcode['bcode'] as $k => $v) {
12158                     $bw = ($v['w'] * $xres);
12159                     if ($v['t']) {
12160                         
12161                         $ypos = $y + $style['padding'] + ($v['p'] * $barh / $arrcode['maxh']);
12162                         $this->Rect($xpos, $ypos, $bw, ($v['h'] * $barh  / $arrcode['maxh']), 'F', array(), $style['fgcolor']);
12163                     }
12164                     $xpos += $bw;
12165                 }
12166             }
12167             
12168             if ($style['text']) {
12169                 
12170                 $this->x = $xpos_text;
12171                 $this->y = $y + $style['padding'] + $barh; 
12172                 $this->Cell(($arrcode['maxw'] * $xres), ($this->cell_height_ratio * $fontsize / $this->k), $code, 0, 0, 'C', 0, '', $style['stretchtext']);
12173             }
12174             
12175             $this->rtl = $tempRTL;
12176             
12177             $this->setGraphicVars($gvars);
12178             
12179             $this->img_rb_y = $y + $h;
12180             if ($this->rtl) {
12181                 
12182                 $this->img_rb_x = ($this->w - $x - $w);
12183             } else {
12184                 
12185                 $this->img_rb_x = $x + $w;
12186             }
12187             
12188             switch($align) {
12189                 case 'T':{
12190                     $this->y = $y;
12191                     $this->x = $this->img_rb_x;
12192                     break;
12193                 }
12194                 case 'M':{
12195                     $this->y = $y + round($h/2);
12196                     $this->x = $this->img_rb_x;
12197                     break;
12198                 }
12199                 case 'B':{
12200                     $this->y = $this->img_rb_y;
12201                     $this->x = $this->img_rb_x;
12202                     break;
12203                 }
12204                 case 'N':{
12205                     $this->SetY($this->img_rb_y);
12206                     break;
12207                 }
12208                 default:{
12209                     break;
12210                 }
12211             }
12212         }
12213         
12229         public function writeBarcode($x, $y, $w, $h, $type, $style, $font, $xres, $code) {
12230             
12231             $xres = 1 / $xres;
12232             $newstyle = array(
12233                 'position' => 'L',
12234                 'border' => false,
12235                 'padding' => 0,
12236                 'fgcolor' => array(0,0,0),
12237                 'bgcolor' => false,
12238                 'text' => true,
12239                 'font' => $font,
12240                 'fontsize' => 8,
12241                 'stretchtext' => 4
12242             );
12243             if ($style & 1) {
12244                 $newstyle['border'] = true;
12245             }
12246             if ($style & 2) {
12247                 $newstyle['bgcolor'] = false;
12248             }
12249             if ($style & 4) {
12250                 $newstyle['position'] = 'C';
12251             } elseif ($style & 8) {
12252                 $newstyle['position'] = 'L';
12253             } elseif ($style & 16) {
12254                 $newstyle['position'] = 'R';
12255             }
12256             if ($style & 128) {
12257                 $newstyle['text'] = true;
12258             }
12259             if ($style & 256) {
12260                 $newstyle['stretchtext'] = 4;
12261             }
12262             $this->write1DBarcode($code, $type, $x, $y, $w, $h, $xres, $newstyle, '');
12263         }
12264         
12279         public function write2DBarcode($code, $type, $x='', $y='', $w='', $h='', $style='', $align='') {
12280             if ($this->empty_string($code)) {
12281                 return;
12282             }
12283             require_once(dirname(__FILE__).'/2dbarcodes.php');
12284             
12285             $gvars = $this->getGraphicVars();
12286             
12287             $barcodeobj = new TCPDF2DBarcode($code, $type);
12288             $arrcode = $barcodeobj->getBarcodeArray();
12289             if ($arrcode === false) {
12290                 $this->Error('Error in 2D barcode string');
12291             }
12292             
12293             if (!isset($style['padding'])) {
12294                 $style['padding'] = 0;
12295             }
12296             if (!isset($style['fgcolor'])) {
12297                 $style['fgcolor'] = array(0,0,0); 
12298             }
12299             if (!isset($style['bgcolor'])) {
12300                 $style['bgcolor'] = false; 
12301             }
12302             if (!isset($style['border'])) {
12303                 $style['border'] = false;
12304             }
12305             
12306             $this->SetDrawColorArray($style['fgcolor']);
12307             if ($this->empty_string($x)) {
12308                 $x = $this->GetX();
12309             }
12310             if ($this->rtl) {
12311                 $x = $this->w - $x;
12312             }
12313             if ($this->empty_string($y)) {
12314                 $y = $this->GetY();
12315             }
12316             if ($this->empty_string($w) OR ($w <= 0)) {
12317                 if ($this->rtl) {
12318                     $w = $x - $this->lMargin;
12319                 } else {
12320                     $w = $this->w - $this->rMargin - $x;
12321                 }
12322             }
12323             if ($this->empty_string($h) OR ($h <= 0)) {
12324                 
12325                 $h = $w;
12326             }
12327             if ($this->checkPageBreak($h)) {
12328                 $y = $this->y;
12329             }
12330             
12331             $bw = $w - (2 * $style['padding']);
12332             $bh = $h - (2 * $style['padding']);
12333             
12334             if ($this->rtl) {
12335                 $xpos = $x - $w;
12336             } else {
12337                 $xpos = $x;
12338             }
12339             $xpos += $style['padding'];
12340             $ypos = $y + $style['padding'];
12341             
12342             $tempRTL = $this->rtl;
12343             $this->rtl = false;
12344             
12345             if ($style['bgcolor']) {
12346                 $this->Rect($x, $y, $w, $h, $style['border'] ? 'DF' : 'F', '', $style['bgcolor']);
12347             } elseif ($style['border']) {
12348                 $this->Rect($x, $y, $w, $h, 'D');
12349             }
12350             
12351             if ($arrcode !== false) {
12352                 $rows = $arrcode['num_rows'];
12353                 $cols = $arrcode['num_cols'];
12354                 
12355                 $cw = $bw / $cols;
12356                 $ch = $bh / $rows;
12357                 
12358                 for ($r = 0; $r < $rows; ++$r) {
12359                     $xr = $xpos;
12360                     
12361                     for ($c = 0; $c < $cols; ++$c) {
12362                         if ($arrcode['bcode'][$r][$c] == 1) {
12363                             
12364                             $this->Rect($xr, $ypos, $cw, $ch, 'F', array(), $style['fgcolor']);
12365                         }
12366                         $xr += $cw;
12367                     }
12368                     $ypos += $ch;
12369                 }
12370             }
12371             
12372             $this->rtl = $tempRTL;
12373             
12374             $this->setGraphicVars($gvars);
12375             
12376             $this->img_rb_y = $y + $h;
12377             if ($this->rtl) {
12378                 
12379                 $this->img_rb_x = ($this->w - $x - $w);
12380             } else {
12381                 
12382                 $this->img_rb_x = $x + $w;
12383             }
12384             
12385             switch($align) {
12386                 case 'T':{
12387                     $this->y = $y;
12388                     $this->x = $this->img_rb_x;
12389                     break;
12390                 }
12391                 case 'M':{
12392                     $this->y = $y + round($h/2);
12393                     $this->x = $this->img_rb_x;
12394                     break;
12395                 }
12396                 case 'B':{
12397                     $this->y = $this->img_rb_y;
12398                     $this->x = $this->img_rb_x;
12399                     break;
12400                 }
12401                 case 'N':{
12402                     $this->SetY($this->img_rb_y);
12403                     break;
12404                 }
12405                 default:{
12406                     break;
12407                 }
12408             }
12409         }
12410         
12426         public function getMargins() {
12427             $ret = array(
12428                 'left' => $this->lMargin,
12429                 'right' => $this->rMargin,
12430                 'top' => $this->tMargin,
12431                 'bottom' => $this->bMargin,
12432                 'header' => $this->header_margin,
12433                 'footer' => $this->footer_margin,
12434                 'cell' => $this->cMargin,
12435             );
12436             return $ret;
12437         }
12438         
12449         public function getOriginalMargins() {
12450             $ret = array(
12451                 'left' => $this->original_lMargin,
12452                 'right' => $this->original_rMargin
12453             );
12454             return $ret;
12455         }
12456         
12463         public function getFontSize() {
12464             return $this->FontSize;
12465         }
12466         
12473         public function getFontSizePt() {
12474             return $this->FontSizePt;
12475         }
12476 
12483         public function getFontFamily() {
12484             return $this->FontFamily;
12485         }
12486 
12493         public function getFontStyle() {
12494             return $this->FontStyle;
12495         }
12496         
12517         public function writeHTMLCell($w, $h, $x, $y, $html='', $border=0, $ln=0, $fill=0, $reseth=true, $align='', $autopadding=true) {
12518             return $this->MultiCell($w, $h, $html, $border, $align, $fill, $ln, $x, $y, $reseth, 0, true, $autopadding, 0);
12519         }
12520         
12529         protected function getHtmlDomArray($html) {
12530             
12531             $html = strip_tags($html, '<marker/><a><b><blockquote><br><br/><dd><del><div><dl><dt><em><font><form><h1><h2><h3><h4><h5><h6><hr><i><img><input><label><li><ol><option><p><pre><select><small><span><strong><sub><sup><table><tablehead><tcpdf><td><textarea><th><thead><tr><tt><u><ul>');
12532             
12533             $html = preg_replace('/<pre/', '<xre', $html); 
12534             $html = preg_replace('/<(table|tr|td|th|tcpdf|blockquote|dd|div|dt|form|h1|h2|h3|h4|h5|h6|br|hr|li|ol|ul|p)([^>]*)>[\n\r\t]+/', '<\\1\\2>', $html);
12535             $html = preg_replace('@(\r\n|\r)@', "\n", $html);
12536             $repTable = array("\t" => ' ', "\0" => ' ', "\x0B" => ' ', "\\" => "\\\\");
12537             $html = strtr($html, $repTable);
12538             $offset = 0;
12539             while (($offset < strlen($html)) AND ($pos = strpos($html, '</pre>', $offset)) !== false) {
12540                 $html_a = substr($html, 0, $offset);
12541                 $html_b = substr($html, $offset, ($pos - $offset + 6));
12542                 while (preg_match("'<xre([^>]*)>(.*?)\n(.*?)</pre>'si", $html_b)) {
12543                     
12544                     $html_b = preg_replace("'<xre([^>]*)>(.*?)\n(.*?)</pre>'si", "<xre\\1>\\2<br />\\3</pre>", $html_b);
12545                 }
12546                 $html = $html_a.$html_b.substr($html, $pos + 6);
12547                 $offset = strlen($html_a.$html_b);
12548             }
12549             $offset = 0;
12550             while (($offset < strlen($html)) AND ($pos = strpos($html, '</textarea>', $offset)) !== false) {
12551                 $html_a = substr($html, 0, $offset);
12552                 $html_b = substr($html, $offset, ($pos - $offset + 11));
12553                 while (preg_match("'<textarea([^>]*)>(.*?)\n(.*?)</textarea>'si", $html_b)) {
12554                     
12555                     $html_b = preg_replace("'<textarea([^>]*)>(.*?)\n(.*?)</textarea>'si", "<textarea\\1>\\2<TBR>\\3</textarea>", $html_b);
12556                     $html_b = preg_replace("'<textarea([^>]*)>(.*?)[\"](.*?)</textarea>'si", "<textarea\\1>\\2''\\3</textarea>", $html_b);
12557                 }
12558                 $html = $html_a.$html_b.substr($html, $pos + 11);
12559                 $offset = strlen($html_a.$html_b);
12560             }
12561             $html = preg_replace("'([\s]*)<option'si", "<option", $html);
12562             $html = preg_replace("'</option>([\s]*)'si", "</option>", $html);
12563             $offset = 0;
12564             while (($offset < strlen($html)) AND ($pos = strpos($html, '</option>', $offset)) !== false) {
12565                 $html_a = substr($html, 0, $offset);
12566                 $html_b = substr($html, $offset, ($pos - $offset + 9));
12567                 while (preg_match("'<option([^>]*)>(.*?)</option>'si", $html_b)) {
12568                     $html_b = preg_replace("'<option([\s]+)value=\"([^\"]*)\"([^>]*)>(.*?)</option>'si", "\\2\t\\4\r", $html_b);
12569                     $html_b = preg_replace("'<option([^>]*)>(.*?)</option>'si", "\\2\r", $html_b);
12570                 }
12571                 $html = $html_a.$html_b.substr($html, $pos + 9);
12572                 $offset = strlen($html_a.$html_b);
12573             }
12574             $html = preg_replace("'<select([^>]*)>'si", "<select\\1 opt=\"", $html);
12575             $html = preg_replace("'([\s]+)</select>'si", "\" />", $html);
12576             $html = str_replace("\n", ' ', $html);
12577             
12578             $html = str_replace('<TBR>', "\n", $html);
12579             
12580             $html = preg_replace('/[\s]+<\/(table|tr|td|th|ul|ol|li)>/', '</\\1>', $html);
12581             $html = preg_replace('/[\s]+<(tr|td|th|ul|ol|li|br)/', '<\\1', $html);
12582             $html = preg_replace('/<\/(table|tr|td|th|blockquote|dd|div|dt|h1|h2|h3|h4|h5|h6|hr|li|ol|ul|p)>[\s]+</', '</\\1><', $html);
12583             $html = preg_replace('/<\/(td|th)>/', '<marker style="font-size:0"/></\\1>', $html);
12584             $html = preg_replace('/<\/table>([\s]*)<marker style="font-size:0"\/>/', '</table>', $html);
12585             $html = preg_replace('/<img/', ' <img', $html);
12586             $html = preg_replace('/<img([^>]*)>/xi', '<img\\1><span></span>', $html);
12587             $html = preg_replace('/<xre/', '<pre', $html); 
12588             $html = preg_replace('/<textarea([^>]*)>/xi', '<textarea\\1 value="', $html);
12589             $html = preg_replace('/<\/textarea>/', '" />', $html);
12590             
12591             $html = preg_replace('/^[\s]+/', '', $html);
12592             $html = preg_replace('/[\s]+$/', '', $html);
12593             
12594             $tagpattern = '/(<[^>]+>)/';
12595             
12596             $a = preg_split($tagpattern, $html, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
12597             
12598             $maxel = count($a);
12599             $elkey = 0;
12600             $key = 0;
12601             
12602             $dom = array();
12603             $dom[$key] = array();
12604             
12605             $dom[$key]['tag'] = false;
12606             $dom[$key]['value'] = '';
12607             $dom[$key]['parent'] = 0;
12608             $dom[$key]['fontname'] = $this->FontFamily;
12609             $dom[$key]['fontstyle'] = $this->FontStyle;
12610             $dom[$key]['fontsize'] = $this->FontSizePt;
12611             $dom[$key]['bgcolor'] = false;
12612             $dom[$key]['fgcolor'] = $this->fgcolor;
12613             $dom[$key]['align'] = '';
12614             $dom[$key]['listtype'] = '';
12615             $dom[$key]['text-indent'] = 0;
12616             $thead = false; 
12617             ++$key;
12618             $level = array();
12619             array_push($level, 0); 
12620             while ($elkey < $maxel) {
12621                 $dom[$key] = array();
12622                 $element = $a[$elkey];
12623                 $dom[$key]['elkey'] = $elkey;
12624                 if (preg_match($tagpattern, $element)) {
12625                     
12626                     $element = substr($element, 1, -1);
12627                     
12628                     preg_match('/[\/]?([a-zA-Z0-9]*)/', $element, $tag);
12629                     $tagname = strtolower($tag[1]);
12630                     
12631                     if ($tagname == 'thead') {
12632                         if ($element{0} == '/') {
12633                             $thead = false;
12634                         } else {
12635                             $thead = true;
12636                         }
12637                         ++$elkey;
12638                         continue;
12639                     }
12640                     $dom[$key]['tag'] = true;
12641                     $dom[$key]['value'] = $tagname;
12642                     if ($element{0} == '/') {
12643                         
12644                         $dom[$key]['opening'] = false;
12645                         $dom[$key]['parent'] = end($level);
12646                         array_pop($level);
12647                         $dom[$key]['fontname'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fontname'];
12648                         $dom[$key]['fontstyle'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fontstyle'];
12649                         $dom[$key]['fontsize'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fontsize'];
12650                         $dom[$key]['bgcolor'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['bgcolor'];
12651                         $dom[$key]['fgcolor'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fgcolor'];
12652                         $dom[$key]['align'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['align'];
12653                         if (isset($dom[($dom[($dom[$key]['parent'])]['parent'])]['listtype'])) {
12654                             $dom[$key]['listtype'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['listtype'];
12655                         }
12656                         
12657                         if (($dom[$key]['value'] == 'tr') AND (!isset($dom[($dom[($dom[$key]['parent'])]['parent'])]['cols']))) {
12658                             $dom[($dom[($dom[$key]['parent'])]['parent'])]['cols'] = $dom[($dom[$key]['parent'])]['cols'];
12659                         }
12660                         if (($dom[$key]['value'] == 'td') OR ($dom[$key]['value'] == 'th')) {
12661                             $dom[($dom[$key]['parent'])]['content'] = '';
12662                             for ($i = ($dom[$key]['parent'] + 1); $i < $key; ++$i) {
12663                                 $dom[($dom[$key]['parent'])]['content'] .= $a[$dom[$i]['elkey']];
12664                             }
12665                             $key = $i;
12666                         }
12667                         
12668                         if (($dom[$key]['value'] == 'tr') AND ($dom[($dom[$key]['parent'])]['thead'] === true)) {
12669                             if ($this->empty_string($dom[($dom[($dom[$key]['parent'])]['parent'])]['thead'])) {
12670                                 $dom[($dom[($dom[$key]['parent'])]['parent'])]['thead'] = $a[$dom[($dom[($dom[$key]['parent'])]['parent'])]['elkey']];
12671                             }
12672                             for ($i = $dom[$key]['parent']; $i <= $key; ++$i) {
12673                                 $dom[($dom[($dom[$key]['parent'])]['parent'])]['thead'] .= $a[$dom[$i]['elkey']];
12674                             }
12675                         }
12676                         if (($dom[$key]['value'] == 'table') AND (!$this->empty_string($dom[($dom[$key]['parent'])]['thead']))) {
12677                             $dom[($dom[$key]['parent'])]['thead'] .= '</tablehead>';
12678                         }
12679                     } else {
12680                         
12681                         $dom[$key]['opening'] = true;
12682                         $dom[$key]['parent'] = end($level);
12683                         if (substr($element, -1, 1) != '/') {
12684                             
12685                             array_push($level, $key);
12686                             $dom[$key]['self'] = false;
12687                         } else {
12688                             $dom[$key]['self'] = true;
12689                         }
12690                         
12691                         $parentkey = 0;
12692                         if ($key > 0) {
12693                             $parentkey = $dom[$key]['parent'];
12694                             $dom[$key]['fontname'] = $dom[$parentkey]['fontname'];
12695                             $dom[$key]['fontstyle'] = $dom[$parentkey]['fontstyle'];
12696                             $dom[$key]['fontsize'] = $dom[$parentkey]['fontsize'];
12697                             $dom[$key]['bgcolor'] = $dom[$parentkey]['bgcolor'];
12698                             $dom[$key]['fgcolor'] = $dom[$parentkey]['fgcolor'];
12699                             $dom[$key]['align'] = $dom[$parentkey]['align'];
12700                             $dom[$key]['listtype'] = $dom[$parentkey]['listtype'];
12701                             $dom[$key]['text-indent'] = $dom[$parentkey]['text-indent'];
12702                         }
12703                         
12704                         preg_match_all('/([^=\s]*)=["]?([^"]*)["]?/', $element, $attr_array, PREG_PATTERN_ORDER);
12705                         $dom[$key]['attribute'] = array(); 
12706                         while (list($id, $name) = each($attr_array[1])) {
12707                             $dom[$key]['attribute'][strtolower($name)] = $attr_array[2][$id];
12708                         }
12709                         
12710                         if (isset($dom[$key]['attribute']['style'])) {
12711                             
12712                             preg_match_all('/([^;:\s]*):([^;]*)/', $dom[$key]['attribute']['style'], $style_array, PREG_PATTERN_ORDER);
12713                             $dom[$key]['style'] = array(); 
12714                             while (list($id, $name) = each($style_array[1])) {
12715                                 $dom[$key]['style'][strtolower($name)] = trim($style_array[2][$id]);
12716                             }
12717                             
12718                             if (isset($dom[$key]['style']['font-family'])) {
12719                                 
12720                                 if (isset($dom[$key]['style']['font-family'])) {
12721                                     $fontslist = preg_split('/[,]/', strtolower($dom[$key]['style']['font-family']));
12722                                     foreach ($fontslist as $font) {
12723                                         $font = trim(strtolower($font));
12724                                         if (in_array($font, $this->fontlist) OR in_array($font, $this->fontkeys)) {
12725                                             $dom[$key]['fontname'] = $font;
12726                                             break;
12727                                         }
12728                                     }
12729                                 }
12730                             }
12731                             
12732                             if (isset($dom[$key]['style']['list-style-type'])) {
12733                                 $dom[$key]['listtype'] = trim(strtolower($dom[$key]['style']['list-style-type']));
12734                                 if ($dom[$key]['listtype'] == 'inherit') {
12735                                     $dom[$key]['listtype'] = $dom[$parentkey]['listtype'];
12736                                 }
12737                             }
12738                             
12739                             if (isset($dom[$key]['style']['text-indent'])) {
12740                                 $dom[$key]['text-indent'] = $this->getHTMLUnitToUnits($dom[$key]['style']['text-indent']);
12741                                 if ($dom[$key]['text-indent'] == 'inherit') {
12742                                     $dom[$key]['text-indent'] = $dom[$parentkey]['text-indent'];
12743                                 }
12744                             }
12745                             
12746                             if (isset($dom[$key]['style']['font-size'])) {
12747                                 $fsize = trim($dom[$key]['style']['font-size']);
12748                                 switch ($fsize) {
12749                                     
12750                                     case 'xx-small': {
12751                                         $dom[$key]['fontsize'] = $dom[0]['fontsize'] - 4;
12752                                         break;
12753                                     }
12754                                     case 'x-small': {
12755                                         $dom[$key]['fontsize'] = $dom[0]['fontsize'] - 3;
12756                                         break;
12757                                     }
12758                                     case 'small': {
12759                                         $dom[$key]['fontsize'] = $dom[0]['fontsize'] - 2;
12760                                         break;
12761                                     }
12762                                     case 'medium': {
12763                                         $dom[$key]['fontsize'] = $dom[0]['fontsize'];
12764                                         break;
12765                                     }
12766                                     case 'large': {
12767                                         $dom[$key]['fontsize'] = $dom[0]['fontsize'] + 2;
12768                                         break;
12769                                     }
12770                                     case 'x-large': {
12771                                         $dom[$key]['fontsize'] = $dom[0]['fontsize'] + 4;
12772                                         break;
12773                                     }
12774                                     case 'xx-large': {
12775                                         $dom[$key]['fontsize'] = $dom[0]['fontsize'] + 6;
12776                                         break;
12777                                     }
12778                                     
12779                                     case 'smaller': {
12780                                         $dom[$key]['fontsize'] = $dom[$parentkey]['fontsize'] - 3;
12781                                         break;
12782                                     }
12783                                     case 'larger': {
12784                                         $dom[$key]['fontsize'] = $dom[$parentkey]['fontsize'] + 3;
12785                                         break;
12786                                     }
12787                                     default: {
12788                                         $dom[$key]['fontsize'] = $this->getHTMLUnitToUnits($fsize, $dom[$parentkey]['fontsize'], 'pt', true);
12789                                     }
12790                                 }
12791                             }
12792                             
12793                             if (isset($dom[$key]['style']['font-weight']) AND (strtolower($dom[$key]['style']['font-weight']{0}) == 'b')) {
12794                                 $dom[$key]['fontstyle'] .= 'B';
12795                             }
12796                             if (isset($dom[$key]['style']['font-style']) AND (strtolower($dom[$key]['style']['font-style']{0}) == 'i')) {
12797                                 $dom[$key]['fontstyle'] .= '"I';
12798                             }
12799                             
12800                             if (isset($dom[$key]['style']['color']) AND (!$this->empty_string($dom[$key]['style']['color']))) {
12801                                 $dom[$key]['fgcolor'] = $this->convertHTMLColorToDec($dom[$key]['style']['color']);
12802                             }
12803                             
12804                             if (isset($dom[$key]['style']['background-color']) AND (!$this->empty_string($dom[$key]['style']['background-color']))) {
12805                                 $dom[$key]['bgcolor'] = $this->convertHTMLColorToDec($dom[$key]['style']['background-color']);
12806                             }
12807                             
12808                             if (isset($dom[$key]['style']['text-decoration'])) {
12809                                 $decors = explode(' ', strtolower($dom[$key]['style']['text-decoration']));
12810                                 foreach ($decors as $dec) {
12811                                     $dec = trim($dec);
12812                                     if (!$this->empty_string($dec)) {
12813                                         if ($dec{0} == 'u') {
12814                                             $dom[$key]['fontstyle'] .= 'U';
12815                                         } elseif ($dec{0} == 'l') {
12816                                             $dom[$key]['fontstyle'] .= 'D';
12817                                         }
12818                                     }
12819                                 }
12820                             }
12821                             
12822                             if (isset($dom[$key]['style']['width'])) {
12823                                 $dom[$key]['width'] = $dom[$key]['style']['width'];
12824                             }
12825                             
12826                             if (isset($dom[$key]['style']['height'])) {
12827                                 $dom[$key]['height'] = $dom[$key]['style']['height'];
12828                             }
12829                             
12830                             if (isset($dom[$key]['style']['text-align'])) {
12831                                 $dom[$key]['align'] = strtoupper($dom[$key]['style']['text-align']{0});
12832                             }
12833                             
12834                             if (isset($dom[$key]['style']['border'])) {
12835                                 $dom[$key]['attribute']['border'] = $dom[$key]['style']['border'];
12836                             }
12837                         }
12838                         
12839                         if ($dom[$key]['value'] == 'font') {
12840                             
12841                             if (isset($dom[$key]['attribute']['face'])) {
12842                                 $fontslist = preg_split('/[,]/', strtolower($dom[$key]['attribute']['face']));
12843                                 foreach ($fontslist as $font) {
12844                                     $font = trim(strtolower($font));
12845                                     if (in_array($font, $this->fontlist) OR in_array($font, $this->fontkeys)) {
12846                                         $dom[$key]['fontname'] = $font;
12847                                         break;
12848                                     }
12849                                 }
12850                             }
12851                             
12852                             if (isset($dom[$key]['attribute']['size'])) {
12853                                 if ($key > 0) {
12854                                     if ($dom[$key]['attribute']['size']{0} == '+') {
12855                                         $dom[$key]['fontsize'] = $dom[($dom[$key]['parent'])]['fontsize'] + intval(substr($dom[$key]['attribute']['size'], 1));
12856                                     } elseif ($dom[$key]['attribute']['size']{0} == '-') {
12857                                         $dom[$key]['fontsize'] = $dom[($dom[$key]['parent'])]['fontsize'] - intval(substr($dom[$key]['attribute']['size'], 1));
12858                                     } else {
12859                                         $dom[$key]['fontsize'] = intval($dom[$key]['attribute']['size']);
12860                                     }
12861                                 } else {
12862                                     $dom[$key]['fontsize'] = intval($dom[$key]['attribute']['size']);
12863                                 }
12864                             }
12865                         }
12866                         
12867                         if ((($dom[$key]['value'] == 'ul') OR ($dom[$key]['value'] == 'ol') OR ($dom[$key]['value'] == 'dl'))
12868                             AND (!isset($dom[$key]['align']) OR $this->empty_string($dom[$key]['align']) OR ($dom[$key]['align'] != 'J'))) {
12869                             if ($this->rtl) {
12870                                 $dom[$key]['align'] = 'R';
12871                             } else {
12872                                 $dom[$key]['align'] = 'L';
12873                             }
12874                         }
12875                         if (($dom[$key]['value'] == 'small') OR ($dom[$key]['value'] == 'sup') OR ($dom[$key]['value'] == 'sub')) {
12876                             $dom[$key]['fontsize'] = $dom[$key]['fontsize'] * K_SMALL_RATIO;
12877                         }
12878                         if (($dom[$key]['value'] == 'strong') OR ($dom[$key]['value'] == 'b')) {
12879                             $dom[$key]['fontstyle'] .= 'B';
12880                         }
12881                         if (($dom[$key]['value'] == 'em') OR ($dom[$key]['value'] == 'i')) {
12882                             $dom[$key]['fontstyle'] .= 'I';
12883                         }
12884                         if ($dom[$key]['value'] == 'u') {
12885                             $dom[$key]['fontstyle'] .= 'U';
12886                         }
12887                         if ($dom[$key]['value'] == 'del') {
12888                             $dom[$key]['fontstyle'] .= 'D';
12889                         }
12890                         if (($dom[$key]['value'] == 'pre') OR ($dom[$key]['value'] == 'tt')) {
12891                             $dom[$key]['fontname'] = $this->default_monospaced_font;
12892                         }
12893                         if (($dom[$key]['value']{0} == 'h') AND (intval($dom[$key]['value']{1}) > 0) AND (intval($dom[$key]['value']{1}) < 7)) {
12894                             $headsize = (4 - intval($dom[$key]['value']{1})) * 2;
12895                             $dom[$key]['fontsize'] = $dom[0]['fontsize'] + $headsize;
12896                             $dom[$key]['fontstyle'] .= 'B';
12897                         }
12898                         if (($dom[$key]['value'] == 'table')) {
12899                             $dom[$key]['rows'] = 0; 
12900                             $dom[$key]['trids'] = array(); 
12901                             $dom[$key]['thead'] = ''; 
12902                         }
12903                         if (($dom[$key]['value'] == 'tr')) {
12904                             $dom[$key]['cols'] = 0;
12905                             
12906                             ++$dom[($dom[$key]['parent'])]['rows'];
12907                             
12908                             array_push($dom[($dom[$key]['parent'])]['trids'], $key);
12909                             if ($thead) {
12910                                 $dom[$key]['thead'] = true;
12911                             } else {
12912                                 $dom[$key]['thead'] = false;
12913                             }
12914                         }
12915                         if (($dom[$key]['value'] == 'th') OR ($dom[$key]['value'] == 'td')) {
12916                             if (isset($dom[$key]['attribute']['colspan'])) {
12917                                 $colspan = intval($dom[$key]['attribute']['colspan']);
12918                             } else {
12919                                 $colspan = 1;
12920                             }
12921                             $dom[$key]['attribute']['colspan'] = $colspan;
12922                             $dom[($dom[$key]['parent'])]['cols'] += $colspan;
12923                         }
12924                         
12925                         if (isset($dom[$key]['attribute']['color']) AND (!$this->empty_string($dom[$key]['attribute']['color']))) {
12926                             $dom[$key]['fgcolor'] = $this->convertHTMLColorToDec($dom[$key]['attribute']['color']);
12927                         }
12928                         
12929                         if (isset($dom[$key]['attribute']['bgcolor']) AND (!$this->empty_string($dom[$key]['attribute']['bgcolor']))) {
12930                             $dom[$key]['bgcolor'] = $this->convertHTMLColorToDec($dom[$key]['attribute']['bgcolor']);
12931                         }
12932                         
12933                         if (isset($dom[$key]['attribute']['width'])) {
12934                             $dom[$key]['width'] = $dom[$key]['attribute']['width'];
12935                         }
12936                         
12937                         if (isset($dom[$key]['attribute']['height'])) {
12938                             $dom[$key]['height'] = $dom[$key]['attribute']['height'];
12939                         }
12940                         
12941                         if (isset($dom[$key]['attribute']['align']) AND (!$this->empty_string($dom[$key]['attribute']['align'])) AND ($dom[$key]['value'] !== 'img')) {
12942                             $dom[$key]['align'] = strtoupper($dom[$key]['attribute']['align']{0});
12943                         }
12944                     } 
12945                 } else {
12946                     
12947                     $dom[$key]['tag'] = false;
12948                     $dom[$key]['value'] = stripslashes($this->unhtmlentities($element));
12949                     $dom[$key]['parent'] = end($level);
12950                 }
12951                 ++$elkey;
12952                 ++$key;
12953             }
12954             return $dom;
12955         }
12956         
12969         public function writeHTML($html, $ln=true, $fill=false, $reseth=false, $cell=false, $align='') {
12970             $gvars = $this->getGraphicVars();
12971             
12972             $prevPage = $this->page;
12973             $prevlMargin = $this->lMargin;
12974             $prevrMargin = $this->rMargin;
12975             $curfontname = $this->FontFamily;
12976             $curfontstyle = $this->FontStyle;
12977             $curfontsize = $this->FontSizePt;   
12978             $this->newline = true;
12979             $startlinepage = $this->page;
12980             $minstartliney = $this->y;
12981             $startlinex = $this->x;
12982             $startliney = $this->y;
12983             $yshift = 0;
12984             $newline = true;
12985             $loop = 0;
12986             $curpos = 0;
12987             $this_method_vars = array();
12988             $undo = false;
12989             $blocktags = array('blockquote','br','dd','div','dt','h1','h2','h3','h4','h5','h6','hr','li','ol','p','ul','tcpdf');
12990             $this->premode = false;
12991             if (isset($this->PageAnnots[$this->page])) {
12992                 $pask = count($this->PageAnnots[$this->page]);
12993             } else {
12994                 $pask = 0;
12995             }
12996             if (isset($this->footerlen[$this->page])) {
12997                 $this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page];
12998             } else {
12999                 $this->footerpos[$this->page] = $this->pagelen[$this->page];
13000             }
13001             $startlinepos = $this->footerpos[$this->page];
13002             $lalign = $align;
13003             $plalign = $align;
13004             if ($this->rtl) {
13005                 $w = $this->x - $this->lMargin;
13006             } else {
13007                 $w = $this->w - $this->rMargin - $this->x;
13008             }
13009             $w -= (2 * $this->cMargin);
13010             if ($cell) {
13011                 if ($this->rtl) {
13012                     $this->x -= $this->cMargin;
13013                 } else {
13014                     $this->x += $this->cMargin;
13015                 }
13016             }
13017             if ($this->customlistindent >= 0) {
13018                 $this->listindent = $this->customlistindent;
13019             } else {
13020                 $this->listindent = $this->GetStringWidth('0000');
13021             }
13022             
13023             $prev_listnum = $this->listnum;
13024             $prev_listordered = $this->listordered;
13025             $prev_listcount = $this->listcount;
13026             $prev_lispacer = $this->lispacer;
13027             $this->listnum = 0;
13028             $this->listordered = array();
13029             $this->listcount = array();
13030             $this->lispacer = '';
13031             if (($this->empty_string($this->lasth)) OR ($reseth)) {
13032                 
13033                 $this->lasth = $this->FontSize * $this->cell_height_ratio; 
13034             }
13035             $dom = $this->getHtmlDomArray($html);
13036             $maxel = count($dom);
13037             $key = 0;
13038             while ($key < $maxel) {
13039                 if ($dom[$key]['tag'] AND $dom[$key]['opening'] AND isset($dom[$key]['attribute']['nobr']) AND ($dom[$key]['attribute']['nobr'] == 'true')) {
13040                     if (isset($dom[($dom[$key]['parent'])]['attribute']['nobr']) AND ($dom[($dom[$key]['parent'])]['attribute']['nobr'] == 'true')) {
13041                         $dom[$key]['attribute']['nobr'] = false;
13042                     } else {
13043                         
13044                         $this->startTransaction();
13045                         
13046                         $this_method_vars['html'] = $html;
13047                         $this_method_vars['ln'] = $ln;
13048                         $this_method_vars['fill'] = $fill;
13049                         $this_method_vars['reseth'] = $reseth;
13050                         $this_method_vars['cell'] = $cell;
13051                         $this_method_vars['align'] = $align;
13052                         $this_method_vars['gvars'] = $gvars;
13053                         $this_method_vars['prevPage'] = $prevPage;
13054                         $this_method_vars['prevlMargin'] = $prevlMargin;
13055                         $this_method_vars['prevrMargin'] = $prevrMargin;
13056                         $this_method_vars['curfontname'] = $curfontname;
13057                         $this_method_vars['curfontstyle'] = $curfontstyle;
13058                         $this_method_vars['curfontsize'] = $curfontsize;
13059                         $this_method_vars['minstartliney'] = $minstartliney;
13060                         $this_method_vars['yshift'] = $yshift;
13061                         $this_method_vars['startlinepage'] = $startlinepage;
13062                         $this_method_vars['startlinepos'] = $startlinepos;
13063                         $this_method_vars['startlinex'] = $startlinex;
13064                         $this_method_vars['startliney'] = $startliney;
13065                         $this_method_vars['newline'] = $newline;
13066                         $this_method_vars['loop'] = $loop;
13067                         $this_method_vars['curpos'] = $curpos;
13068                         $this_method_vars['pask'] = $pask;
13069                         $this_method_vars['lalign'] = $lalign;
13070                         $this_method_vars['plalign'] = $plalign;
13071                         $this_method_vars['w'] = $w;
13072                         $this_method_vars['prev_listnum'] = $prev_listnum;
13073                         $this_method_vars['prev_listordered'] = $prev_listordered;
13074                         $this_method_vars['prev_listcount'] = $prev_listcount;
13075                         $this_method_vars['prev_lispacer'] = $prev_lispacer;
13076                         $this_method_vars['key'] = $key;
13077                         $this_method_vars['dom'] = $dom;
13078                     }
13079                 }
13080                 if ($dom[$key]['tag'] OR ($key == 0)) {
13081                     if ((($dom[$key]['value'] == 'table') OR ($dom[$key]['value'] == 'tr')) AND (isset($dom[$key]['align']))) {
13082                         $dom[$key]['align'] = ($this->rtl) ? 'R' : 'L';
13083                     }
13084                     
13085                     if ((!$this->newline)
13086                         AND ($dom[$key]['value'] == 'img')
13087                         AND (isset($dom[$key]['attribute']['height']))
13088                         AND ($dom[$key]['attribute']['height'] > 0)) {
13089                         
13090                         
13091                         $imgh = $this->getHTMLUnitToUnits($dom[$key]['attribute']['height'], $this->lasth, 'px');
13092                         if (!$this->InFooter) {
13093                             
13094                             $this->checkPageBreak($imgh);
13095                         }
13096                         if ($this->page > $startlinepage) {
13097                             
13098                             if (isset($this->footerlen[$startlinepage])) {
13099                                 $curpos = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
13100                             }
13101                             
13102                             $pagebuff = $this->getPageBuffer($startlinepage);
13103                             $linebeg = substr($pagebuff, $startlinepos, ($curpos - $startlinepos));
13104                             $tstart = substr($pagebuff, 0, $startlinepos);
13105                             $tend = substr($this->getPageBuffer($startlinepage), $curpos);
13106                             
13107                             $this->setPageBuffer($startlinepage, $tstart.''.$tend);
13108                             $pagebuff = $this->getPageBuffer($this->page);
13109                             $tstart = substr($pagebuff, 0, $this->cntmrk[$this->page]);
13110                             $tend = substr($pagebuff, $this->cntmrk[$this->page]);
13111                             
13112                             $yshift = $minstartliney - $this->y;
13113                             $try = sprintf('1 0 0 1 0 %.3F cm', ($yshift * $this->k));
13114                             $this->setPageBuffer($this->page, $tstart."\nq\n".$try."\n".$linebeg."\nQ\n".$tend);
13115                             
13116                             if (isset($this->PageAnnots[$this->page])) {
13117                                 $next_pask = count($this->PageAnnots[$this->page]);
13118                             } else {
13119                                 $next_pask = 0;
13120                             }
13121                             if (isset($this->PageAnnots[$startlinepage])) {
13122                                 foreach ($this->PageAnnots[$startlinepage] as $pak => $pac) {
13123                                     if ($pak >= $pask) {
13124                                         $this->PageAnnots[$this->page][] = $pac;
13125                                         unset($this->PageAnnots[$startlinepage][$pak]);
13126                                         $npak = count($this->PageAnnots[$this->page]) - 1;
13127                                         $this->PageAnnots[$this->page][$npak]['y'] -= $yshift;                                      
13128                                     }
13129                                 }
13130                                 
13131                             }
13132                             $pask = $next_pask;
13133                             $startlinepos = $this->cntmrk[$this->page];
13134                             $startlinepage = $this->page;
13135                             $startliney = $this->y;
13136                         }
13137                         $this->y += (($curfontsize / $this->k) - $imgh);
13138                         $minstartliney = min($this->y, $minstartliney); 
13139                     } elseif (isset($dom[$key]['fontname']) OR isset($dom[$key]['fontstyle']) OR isset($dom[$key]['fontsize'])) {
13140                         
13141                         $pfontname = $curfontname;
13142                         $pfontstyle = $curfontstyle;
13143                         $pfontsize = $curfontsize;
13144                         $fontname = isset($dom[$key]['fontname']) ? $dom[$key]['fontname'] : $curfontname;
13145                         $fontstyle = isset($dom[$key]['fontstyle']) ? $dom[$key]['fontstyle'] : $curfontstyle;
13146                         $fontsize = isset($dom[$key]['fontsize']) ? $dom[$key]['fontsize'] : $curfontsize;
13147                         if (($fontname != $curfontname) OR ($fontstyle != $curfontstyle) OR ($fontsize != $curfontsize)) {
13148                             $this->SetFont($fontname, $fontstyle, $fontsize);
13149                             $this->lasth = $this->FontSize * $this->cell_height_ratio;
13150                             if (is_numeric($fontsize) AND ($fontsize > 0)
13151                                 AND is_numeric($curfontsize) AND ($curfontsize > 0)
13152                                 AND ($fontsize != $curfontsize) AND (!$this->newline)
13153                                 AND ($key < ($maxel - 1))
13154                                 ) {
13155                                 if ((!$this->newline) AND ($this->page > $startlinepage)) {
13156                                     
13157                                     if (isset($this->footerlen[$startlinepage])) {
13158                                         $curpos = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
13159                                     }
13160                                     
13161                                     $pagebuff = $this->getPageBuffer($startlinepage);
13162                                     $linebeg = substr($pagebuff, $startlinepos, ($curpos - $startlinepos));
13163                                     $tstart = substr($pagebuff, 0, $startlinepos);
13164                                     $tend = substr($this->getPageBuffer($startlinepage), $curpos);
13165                                     
13166                                     $this->setPageBuffer($startlinepage, $tstart.''.$tend);
13167                                     $pagebuff = $this->getPageBuffer($this->page);
13168                                     $tstart = substr($pagebuff, 0, $this->cntmrk[$this->page]);
13169                                     $tend = substr($pagebuff, $this->cntmrk[$this->page]);
13170                                     
13171                                     $yshift = $minstartliney - $this->y;
13172                                     $try = sprintf('1 0 0 1 0 %.3F cm', ($yshift * $this->k));
13173                                     $this->setPageBuffer($this->page, $tstart."\nq\n".$try."\n".$linebeg."\nQ\n".$tend);
13174                                     
13175                                     if (isset($this->PageAnnots[$this->page])) {
13176                                         $next_pask = count($this->PageAnnots[$this->page]);
13177                                     } else {
13178                                         $next_pask = 0;
13179                                     }
13180                                     if (isset($this->PageAnnots[$startlinepage])) {
13181                                         foreach ($this->PageAnnots[$startlinepage] as $pak => $pac) {
13182                                             if ($pak >= $pask) {
13183                                                 $this->PageAnnots[$this->page][] = $pac;
13184                                                 unset($this->PageAnnots[$startlinepage][$pak]);
13185                                                 $npak = count($this->PageAnnots[$this->page]) - 1;
13186                                                 $this->PageAnnots[$this->page][$npak]['y'] -= $yshift;
13187                                             }
13188                                         }
13189                                     }
13190                                     $pask = $next_pask;
13191                                 }
13192                                 if (($dom[$key]['value'] != 'td') AND ($dom[$key]['value'] != 'th')) {
13193                                     $this->y += (($curfontsize - $fontsize) / $this->k);
13194                                 }
13195                                 $minstartliney = min($this->y, $minstartliney);
13196                             }
13197                             $curfontname = $fontname;
13198                             $curfontstyle = $fontstyle;
13199                             $curfontsize = $fontsize;
13200                         }
13201                     }
13202                     if (($plalign == 'J') AND (in_array($dom[$key]['value'], $blocktags))) {
13203                         $plalign = '';
13204                     }
13205                     
13206                     $curpos = $this->pagelen[$startlinepage];
13207                     if (isset($dom[$key]['bgcolor']) AND ($dom[$key]['bgcolor'] !== false)) {
13208                         $this->SetFillColorArray($dom[$key]['bgcolor']);
13209                         $wfill = true;
13210                     } else {
13211                         $wfill = $fill | false;
13212                     }
13213                     if (isset($dom[$key]['fgcolor']) AND ($dom[$key]['fgcolor'] !== false)) {
13214                         $this->SetTextColorArray($dom[$key]['fgcolor']);
13215                     }
13216                     if (isset($dom[$key]['align'])) {
13217                         $lalign = $dom[$key]['align'];
13218                     }
13219                     if ($this->empty_string($lalign)) {
13220                         $lalign = $align;
13221                     }
13222                 }
13223                 
13224                 if ($this->newline AND (strlen($dom[$key]['value']) > 0) AND ($dom[$key]['value'] != 'td') AND ($dom[$key]['value'] != 'th')) {
13225                     $newline = true;
13226                     
13227                     if (isset($startlinex)) {
13228                         $yshift = $minstartliney - $startliney;
13229                         if (($yshift > 0) OR ($this->page > $startlinepage)) {
13230                             $yshift = 0;
13231                         }
13232                         if ((isset($plalign) AND ((($plalign == 'C') OR ($plalign == 'J') OR (($plalign == 'R') AND (!$this->rtl)) OR (($plalign == 'L') AND ($this->rtl))))) OR ($yshift < 0)) {
13233                             
13234                             $linew = abs($this->endlinex - $startlinex);
13235                             $pstart = substr($this->getPageBuffer($startlinepage), 0, $startlinepos);
13236                             if (isset($opentagpos) AND isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) {
13237                                 $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
13238                                 $midpos = min($opentagpos, $this->footerpos[$startlinepage]);
13239                             } elseif (isset($opentagpos)) {
13240                                 $midpos = $opentagpos;
13241                             } elseif (isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) {
13242                                 $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
13243                                 $midpos = $this->footerpos[$startlinepage];
13244                             } else {
13245                                 $midpos = 0;
13246                             }
13247                             if ($midpos > 0) {
13248                                 $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos, ($midpos - $startlinepos));
13249                                 $pend = substr($this->getPageBuffer($startlinepage), $midpos);
13250                             } else {
13251                                 $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos);
13252                                 $pend = '';
13253                             }
13254                             
13255                             $tw = $w;
13256                             if ($this->lMargin != $prevlMargin) {
13257                                 $tw += ($prevlMargin - $this->lMargin);
13258                             }
13259                             if ($this->rMargin != $prevrMargin) {
13260                                 $tw += ($prevrMargin - $this->rMargin);
13261                             }
13262                             $mdiff = abs($tw - $linew);
13263                             $t_x = 0;
13264                             if ($plalign == 'C') {
13265                                 if ($this->rtl) {
13266                                     $t_x = -($mdiff / 2);
13267                                 } else {
13268                                     $t_x = ($mdiff / 2);
13269                                 }
13270                             } elseif (($plalign == 'R') AND (!$this->rtl)) {
13271                                 
13272                                 $t_x = $mdiff;  
13273                             } elseif (($plalign == 'L') AND ($this->rtl)) {
13274                                 
13275                                 $t_x = -$mdiff;
13276                             } elseif (($plalign == 'J') AND ($plalign == $lalign)) {
13277                                 
13278                                 if ($this->rtl OR $this->tmprtl) {
13279                                     $t_x = $this->lMargin - $this->endlinex;
13280                                 }
13281                                 $no = 0;
13282                                 $ns = 0;
13283                                 $pmidtemp = $pmid;
13284                                 
13285                                 $pmidtemp = preg_replace('/[\\\][\(]/x', '\\#!#OP#!#', $pmidtemp);
13286                                 $pmidtemp = preg_replace('/[\\\][\)]/x', '\\#!#CP#!#', $pmidtemp);
13287                                 
13288                                 if (preg_match_all('/\[\(([^\)]*)\)\]/x', $pmidtemp, $lnstring, PREG_PATTERN_ORDER)) {
13289                                     $maxkk = count($lnstring[1]) - 1;
13290                                     for ($kk=0; $kk <= $maxkk; ++$kk) {
13291                                         
13292                                         $lnstring[1][$kk] = str_replace('#!#OP#!#', '(', $lnstring[1][$kk]);
13293                                         $lnstring[1][$kk] = str_replace('#!#CP#!#', ')', $lnstring[1][$kk]);
13294                                         if ($kk == $maxkk) {
13295                                             if ($this->rtl OR $this->tmprtl) {
13296                                                 $tvalue = ltrim($lnstring[1][$kk]);
13297                                             } else {
13298                                                 $tvalue = rtrim($lnstring[1][$kk]);
13299                                             }
13300                                         } else {
13301                                             $tvalue = $lnstring[1][$kk];
13302                                         }
13303                                         
13304                                         $no += substr_count($lnstring[1][$kk], chr(32));
13305                                         $ns += substr_count($tvalue, chr(32));
13306                                     }
13307                                     if ($this->rtl OR $this->tmprtl) {
13308                                         $t_x = $this->lMargin - $this->endlinex - (($no - $ns - 1) * $this->GetStringWidth(chr(32)));
13309                                     }
13310                                     
13311                                     $spacelen = $this->GetStringWidth(chr(32));
13312                                     $spacewidth = (($tw - $linew + (($no - $ns) * $spacelen)) / ($ns?$ns:1)) * $this->k;
13313                                     $spacewidthu = -1000 * ($tw - $linew + ($no * $spacelen)) / ($ns?$ns:1) / $this->FontSize;
13314                                     $nsmax = $ns;
13315                                     $ns = 0;
13316                                     reset($lnstring);
13317                                     $offset = 0;
13318                                     $strcount = 0;
13319                                     $prev_epsposbeg = 0;
13320                                     global $spacew;
13321                                     while (preg_match('/([0-9\.\+\-]*)[\s](Td|cm|m|l|c|re)[\s]/x', $pmid, $strpiece, PREG_OFFSET_CAPTURE, $offset) == 1) {
13322                                         
13323                                         $stroffset = strpos($pmid, '[(', $offset);
13324                                         if (($stroffset !== false) AND ($stroffset <= $strpiece[2][1])) {
13325                                             
13326                                             $offset = strpos($pmid, ')]', $stroffset);
13327                                             while (($offset !== false) AND ($pmid{($offset - 1)} == '\\')) {
13328                                                 $offset = strpos($pmid, ')]', ($offset + 1));
13329                                             }
13330                                             if ($offset === false) {
13331                                                 $this->Error('HTML Justification: malformed PDF code.');
13332                                             }
13333                                             continue;
13334                                         }
13335                                         if ($this->rtl OR $this->tmprtl) {
13336                                             $spacew = ($spacewidth * ($nsmax - $ns));
13337                                         } else {
13338                                             $spacew = ($spacewidth * $ns);
13339                                         }
13340                                         $offset = $strpiece[2][1] + strlen($strpiece[2][0]);
13341                                         $epsposbeg = strpos($pmid, 'q'.$this->epsmarker, $offset);
13342                                         $epsposend = strpos($pmid, $this->epsmarker.'Q', $offset) + strlen($this->epsmarker.'Q');
13343                                         if ((($epsposbeg > 0) AND ($epsposend > 0) AND ($offset > $epsposbeg) AND ($offset < $epsposend))
13344                                             OR (($epsposbeg === false) AND ($epsposend > 0) AND ($offset < $epsposend))) {
13345                                             
13346                                             $trx = sprintf('1 0 0 1 %.3F 0 cm', $spacew);
13347                                             $epsposbeg = strpos($pmid, 'q'.$this->epsmarker, ($prev_epsposbeg - 6));
13348                                             $pmid_b = substr($pmid, 0, $epsposbeg);
13349                                             $pmid_m = substr($pmid, $epsposbeg, ($epsposend - $epsposbeg));
13350                                             $pmid_e = substr($pmid, $epsposend);
13351                                             $pmid = $pmid_b."\nq\n".$trx."\n".$pmid_m."\nQ\n".$pmid_e;
13352                                             $offset = $epsposend;
13353                                             continue;
13354                                         }
13355                                         $prev_epsposbeg = $epsposbeg;
13356                                         $currentxpos = 0;
13357                                         
13358                                         switch ($strpiece[2][0]) {
13359                                             case 'Td':
13360                                             case 'cm':
13361                                             case 'm':
13362                                             case 'l': {
13363                                                 
13364                                                 preg_match('/([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s]('.$strpiece[2][0].')([\s]*)/x', $pmid, $xmatches);
13365                                                 $currentxpos = $xmatches[1];
13366                                                 if (($strcount <= $maxkk) AND ($strpiece[2][0] == 'Td')) {
13367                                                     if ($strcount == $maxkk) {
13368                                                         if ($this->rtl OR $this->tmprtl) {
13369                                                             $tvalue = $lnstring[1][$strcount];
13370                                                         } else {
13371                                                             $tvalue = rtrim($lnstring[1][$strcount]);
13372                                                         }
13373                                                     } else {
13374                                                         $tvalue = $lnstring[1][$strcount];
13375                                                     }
13376                                                     $ns += substr_count($tvalue, chr(32));
13377                                                     ++$strcount;
13378                                                 }
13379                                                 if ($this->rtl OR $this->tmprtl) {
13380                                                     $spacew = ($spacewidth * ($nsmax - $ns));
13381                                                 }
13382                                                 
13383                                                 $pmid = preg_replace_callback('/([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s]('.$strpiece[2][0].')([\s]*)/x',
13384                                                     create_function('$matches', 'global $spacew;
13385                                                     $newx = sprintf("%.2F",(floatval($matches[1]) + $spacew));
13386                                                     return "".$newx." ".$matches[2]." x*#!#*x".$matches[3].$matches[4];'), $pmid, 1);
13387                                                 break;
13388                                             }
13389                                             case 're': {
13390                                                 
13391                                                 preg_match('/([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s]('.$strpiece[2][0].')([\s]*)/x', $pmid, $xmatches);
13392                                                 $currentxpos = $xmatches[1];
13393                                                 
13394                                                 $pmid = preg_replace_callback('/([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s]('.$strpiece[2][0].')([\s]*)/x',
13395                                                     create_function('$matches', 'global $spacew;
13396                                                     $newx = sprintf("%.2F",(floatval($matches[1]) + $spacew));
13397                                                     return "".$newx." ".$matches[2]." ".$matches[3]." ".$matches[4]." x*#!#*x".$matches[5].$matches[6];'), $pmid, 1);
13398                                                 break;
13399                                             }
13400                                             case 'c': {
13401                                                 
13402                                                 preg_match('/([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s]('.$strpiece[2][0].')([\s]*)/x', $pmid, $xmatches);
13403                                                 $currentxpos = $xmatches[1];
13404                                                 
13405                                                 $pmid = preg_replace_callback('/([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s]('.$strpiece[2][0].')([\s]*)/x',
13406                                                     create_function('$matches', 'global $spacew;
13407                                                     $newx1 = sprintf("%.3F",(floatval($matches[1]) + $spacew));
13408                                                     $newx2 = sprintf("%.3F",(floatval($matches[3]) + $spacew));
13409                                                     $newx3 = sprintf("%.3F",(floatval($matches[5]) + $spacew));
13410                                                     return "".$newx1." ".$matches[2]." ".$newx2." ".$matches[4]." ".$newx3." ".$matches[6]." x*#!#*x".$matches[7].$matches[8];'), $pmid, 1);
13411                                                 break;
13412                                             }
13413                                         }
13414                                         
13415                                         if (isset($this->PageAnnots[$this->page])) {
13416                                             foreach ($this->PageAnnots[$this->page] as $pak => $pac) {
13417                                                 if (($pac['y'] >= $minstartliney) AND (($pac['x'] * $this->k) >= ($currentxpos - $this->feps)) AND (($pac['x'] * $this->k) <= ($currentxpos + $this->feps))) {
13418                                                     $this->PageAnnots[$this->page][$pak]['x'] += ($spacew / $this->k);
13419                                                     $this->PageAnnots[$this->page][$pak]['w'] += (($spacewidth * $pac['numspaces']) / $this->k);
13420                                                     break;
13421                                                 }
13422                                             }
13423                                         }
13424                                     } 
13425                                     
13426                                     $pmid = str_replace('x*#!#*x', '', $pmid);
13427                                     if (($this->CurrentFont['type'] == 'TrueTypeUnicode') OR ($this->CurrentFont['type'] == 'cidfont0')) {
13428                                         
13429                                         $spacew = $spacewidthu;
13430                                         $pmidtemp = $pmid;
13431                                         
13432                                         $pmidtemp = preg_replace('/[\\\][\(]/x', '\\#!#OP#!#', $pmidtemp);
13433                                         $pmidtemp = preg_replace('/[\\\][\)]/x', '\\#!#CP#!#', $pmidtemp);
13434                                         $pmid = preg_replace_callback("/\[\(([^\)]*)\)\]/x",
13435                                                     create_function('$matches', 'global $spacew;
13436                                                     $matches[1] = str_replace("#!#OP#!#", "(", $matches[1]);
13437                                                     $matches[1] = str_replace("#!#CP#!#", ")", $matches[1]);
13438                                                     return "[(".str_replace(chr(0).chr(32), ") ".($spacew)." (", $matches[1]).")]";'), $pmidtemp);
13439                                         $this->setPageBuffer($startlinepage, $pstart."\n".$pmid."\n".$pend);
13440                                         $endlinepos = strlen($pstart."\n".$pmid."\n");
13441                                     } else {
13442                                         
13443                                         $rs = sprintf("%.3F Tw", $spacewidth);
13444                                         $pmid = preg_replace("/\[\(/x", $rs.' [(', $pmid);
13445                                         $this->setPageBuffer($startlinepage, $pstart."\n".$pmid."\nBT 0 Tw ET\n".$pend);
13446                                         $endlinepos = strlen($pstart."\n".$pmid."\nBT 0 Tw ET\n");
13447                                     }
13448                                 }
13449                             } 
13450                             if (($t_x != 0) OR ($yshift < 0)) {
13451                                 
13452                                 $trx = sprintf('1 0 0 1 %.3F %.3F cm', ($t_x * $this->k), ($yshift * $this->k));
13453                                 $this->setPageBuffer($startlinepage, $pstart."\nq\n".$trx."\n".$pmid."\nQ\n".$pend);
13454                                 $endlinepos = strlen($pstart."\nq\n".$trx."\n".$pmid."\nQ\n");
13455                                 
13456                                 if (isset($this->PageAnnots[$this->page])) {
13457                                     foreach ($this->PageAnnots[$this->page] as $pak => $pac) {
13458                                         if ($pak >= $pask) {
13459                                             $this->PageAnnots[$this->page][$pak]['x'] += $t_x;
13460                                             $this->PageAnnots[$this->page][$pak]['y'] -= $yshift;
13461                                         }
13462                                     }
13463                                 }
13464                                 $this->y -= $yshift;
13465                             }
13466                         }
13467                     }
13468                     $this->newline = false;
13469                     $pbrk = $this->checkPageBreak($this->lasth);
13470                     $this->SetFont($fontname, $fontstyle, $fontsize);
13471                     if ($wfill) {
13472                         $this->SetFillColorArray($this->bgcolor);
13473                     }
13474                     $startlinex = $this->x;
13475                     $startliney = $this->y;
13476                     $minstartliney = $this->y;
13477                     $startlinepage = $this->page;
13478                     if (isset($endlinepos) AND (!$pbrk)) {
13479                         $startlinepos = $endlinepos;
13480                         unset($endlinepos);
13481                     } else {
13482                         if (isset($this->footerlen[$this->page])) {
13483                             $this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page];
13484                         } else {
13485                             $this->footerpos[$this->page] = $this->pagelen[$this->page];
13486                         }
13487                         $startlinepos = $this->footerpos[$this->page];
13488                     }
13489                     $plalign = $lalign;
13490                     if (isset($this->PageAnnots[$this->page])) {
13491                         $pask = count($this->PageAnnots[$this->page]);
13492                     } else {
13493                         $pask = 0;
13494                     }
13495                 }
13496                 if (isset($opentagpos)) {
13497                     unset($opentagpos);
13498                 }
13499                 if ($dom[$key]['tag']) {
13500                     if ($dom[$key]['opening']) {
13501                         
13502                         if (isset($dom[$key]['text-indent']) AND in_array($dom[$key]['value'], array('blockquote','dd','div','dt','h1','h2','h3','h4','h5','h6','li','ol','p','ul','table','tr','td'))) {
13503                             $this->textindent = $dom[$key]['text-indent'];
13504                         }
13505                         if ($dom[$key]['value'] == 'table') {
13506                             if ($this->rtl) {
13507                                 $wtmp = $this->x - $this->lMargin;
13508                             } else {
13509                                 $wtmp = $this->w - $this->rMargin - $this->x;
13510                             }
13511                             $wtmp -= (2 * $this->cMargin);
13512                             
13513                             if (isset($dom[$key]['width'])) {
13514                                 $table_width = $this->getHTMLUnitToUnits($dom[$key]['width'], $wtmp, 'px');
13515                             } else {
13516                                 $table_width = $wtmp;
13517                             }
13518                         }
13519                         
13520                         if (($dom[$key]['value'] == 'td') OR ($dom[$key]['value'] == 'th')) {
13521                             $trid = $dom[$key]['parent'];
13522                             $table_el = $dom[$trid]['parent'];
13523                             if (!isset($dom[$table_el]['cols'])) {
13524                                 $dom[$table_el]['cols'] = $trid['cols'];
13525                             }
13526                             $oldmargin = $this->cMargin;
13527                             if (isset($dom[($dom[$trid]['parent'])]['attribute']['cellpadding'])) {
13528                                 $currentcmargin = $this->getHTMLUnitToUnits($dom[($dom[$trid]['parent'])]['attribute']['cellpadding'], 1, 'px');
13529                             } else {
13530                                 $currentcmargin = 0;        
13531                             }
13532                             $this->cMargin = $currentcmargin;
13533                             if (isset($dom[($dom[$trid]['parent'])]['attribute']['cellspacing'])) {
13534                                 $cellspacing = $this->getHTMLUnitToUnits($dom[($dom[$trid]['parent'])]['attribute']['cellspacing'], 1, 'px');
13535                             } else {
13536                                 $cellspacing = 0;
13537                             }
13538                             if ($this->rtl) {
13539                                 $cellspacingx = -$cellspacing;
13540                             } else {
13541                                 $cellspacingx = $cellspacing;
13542                             }
13543                             $colspan = $dom[$key]['attribute']['colspan'];
13544                             $wtmp = ($colspan * ($table_width / $dom[$table_el]['cols']));
13545                             if (isset($dom[$key]['width'])) {
13546                                 $cellw = $this->getHTMLUnitToUnits($dom[$key]['width'], $table_width, 'px');
13547                             } else {
13548                                 $cellw = $wtmp;
13549                             }
13550                             if (isset($dom[$key]['height'])) {
13551                                 
13552                                 $cellh = $this->getHTMLUnitToUnits($dom[$key]['height'], 0, 'px');
13553                             } else {
13554                                 $cellh = 0;
13555                             }
13556                             $cellw -= $cellspacing;
13557                             if (isset($dom[$key]['content'])) {
13558                                 $cell_content = $dom[$key]['content'];
13559                             } else {
13560                                 $cell_content = ' ';
13561                             }
13562                             $tagtype = $dom[$key]['value'];
13563                             $parentid = $key;
13564                             while (($key < $maxel) AND (!(($dom[$key]['tag']) AND (!$dom[$key]['opening']) AND ($dom[$key]['value'] == $tagtype) AND ($dom[$key]['parent'] == $parentid)))) {
13565                                 
13566                                 ++$key;
13567                             }
13568                             if (!isset($dom[$trid]['startpage'])) {
13569                                 $dom[$trid]['startpage'] = $this->page;
13570                             } else {
13571                                 $this->setPage($dom[$trid]['startpage']);
13572                             }
13573                             if (!isset($dom[$trid]['starty'])) {
13574                                 $dom[$trid]['starty'] = $this->y;
13575                             } else {
13576                                 $this->y = $dom[$trid]['starty'];
13577                             }
13578                             if (!isset($dom[$trid]['startx'])) {
13579                                 $dom[$trid]['startx'] = $this->x;
13580                             }
13581                             $this->x += ($cellspacingx / 2);                        
13582                             if (isset($dom[$parentid]['attribute']['rowspan'])) {
13583                                 $rowspan = intval($dom[$parentid]['attribute']['rowspan']);
13584                             } else {
13585                                 $rowspan = 1;
13586                             }
13587                             
13588                             if (isset($dom[$table_el]['rowspans'])) {
13589                                 $rsk = 0;
13590                                 $rskmax = count($dom[$table_el]['rowspans']);
13591                                 while ($rsk < $rskmax) {
13592                                     $trwsp = $dom[$table_el]['rowspans'][$rsk];
13593                                     $rsstartx = $trwsp['startx'];
13594                                     $rsendx = $trwsp['endx'];
13595                                     
13596                                     if ($trwsp['startpage'] < $this->page) {
13597                                         if (($this->rtl) AND ($this->pagedim[$this->page]['orm'] != $this->pagedim[$trwsp['startpage']]['orm'])) {
13598                                             $dl = ($this->pagedim[$this->page]['orm'] - $this->pagedim[$trwsp['startpage']]['orm']);
13599                                             $rsstartx -= $dl;
13600                                             $rsendx -= $dl;
13601                                         } elseif ((!$this->rtl) AND ($this->pagedim[$this->page]['olm'] != $this->pagedim[$trwsp['startpage']]['olm'])) {
13602                                             $dl = ($this->pagedim[$this->page]['olm'] - $this->pagedim[$trwsp['startpage']]['olm']);
13603                                             $rsstartx += $dl;
13604                                             $rsendx += $dl;
13605                                         }
13606                                     }
13607                                     if  (($trwsp['rowspan'] > 0)
13608                                         AND ($rsstartx > ($this->x - $cellspacing - $currentcmargin - $this->feps))
13609                                         AND ($rsstartx < ($this->x + $cellspacing + $currentcmargin + $this->feps))
13610                                         AND (($trwsp['starty'] < ($this->y - $this->feps)) OR ($trwsp['startpage'] < $this->page))) {
13611                                         
13612                                         $this->x = $rsendx + $cellspacingx;
13613                                         if (($trwsp['rowspan'] == 1)
13614                                             AND (isset($dom[$trid]['endy']))
13615                                             AND (isset($dom[$trid]['endpage']))
13616                                             AND ($trwsp['endpage'] == $dom[$trid]['endpage'])) {
13617                                             
13618                                             $dom[$table_el]['rowspans'][$rsk]['endy'] = max($dom[$trid]['endy'], $trwsp['endy']);
13619                                             $dom[$trid]['endy'] = $dom[$table_el]['rowspans'][$rsk]['endy'];
13620                                         }
13621                                         $rsk = 0;
13622                                     } else {
13623                                         ++$rsk;
13624                                     }
13625                                 }
13626                             }
13627                             
13628                             if ($rowspan > 1) {
13629                                 if (isset($this->footerlen[$this->page])) {
13630                                     $this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page];
13631                                 } else {
13632                                     $this->footerpos[$this->page] = $this->pagelen[$this->page];
13633                                 }
13634                                 $trintmrkpos = $this->footerpos[$this->page];
13635                                 $trsid = array_push($dom[$table_el]['rowspans'], array('trid' => $trid, 'rowspan' => $rowspan, 'mrowspan' => $rowspan, 'colspan' => $colspan, 'startpage' => $this->page, 'startx' => $this->x, 'starty' => $this->y, 'intmrkpos' => $trintmrkpos));
13636                             }
13637                             $cellid = array_push($dom[$trid]['cellpos'], array('startx' => $this->x));
13638                             if ($rowspan > 1) {
13639                                 $dom[$trid]['cellpos'][($cellid - 1)]['rowspanid'] = ($trsid - 1);
13640                             }
13641                             
13642                             if (isset($dom[$parentid]['bgcolor']) AND ($dom[$parentid]['bgcolor'] !== false)) {
13643                                 $dom[$trid]['cellpos'][($cellid - 1)]['bgcolor'] = $dom[$parentid]['bgcolor'];
13644                             }
13645                             $prevLastH = $this->lasth;
13646                             
13647                             $this->MultiCell($cellw, $cellh, $cell_content, false, $lalign, false, 2, '', '', true, 0, true);
13648                             $this->lasth = $prevLastH;
13649                             $this->cMargin = $oldmargin;
13650                             $dom[$trid]['cellpos'][($cellid - 1)]['endx'] = $this->x;
13651                             
13652                             if ($rowspan <= 1) {
13653                                 if (isset($dom[$trid]['endy'])) {
13654                                     if ($this->page == $dom[$trid]['endpage']) {
13655                                         $dom[$trid]['endy'] = max($this->y, $dom[$trid]['endy']);
13656                                     } elseif ($this->page > $dom[$trid]['endpage']) {
13657                                         $dom[$trid]['endy'] = $this->y;
13658                                     }
13659                                 } else {
13660                                     $dom[$trid]['endy'] = $this->y;
13661                                 }
13662                                 if (isset($dom[$trid]['endpage'])) {
13663                                     $dom[$trid]['endpage'] = max($this->page, $dom[$trid]['endpage']);
13664                                 } else {
13665                                     $dom[$trid]['endpage'] = $this->page;
13666                                 }                               
13667                             } else {
13668                                 
13669                                 $dom[$table_el]['rowspans'][($trsid - 1)]['endx'] = $this->x;
13670                                 $dom[$table_el]['rowspans'][($trsid - 1)]['endy'] = $this->y;
13671                                 $dom[$table_el]['rowspans'][($trsid - 1)]['endpage'] = $this->page;
13672                             }
13673                             if (isset($dom[$table_el]['rowspans'])) {
13674                                 
13675                                 foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) {
13676                                     if ($trwsp['rowspan'] > 0) {
13677                                         if (isset($dom[$trid]['endpage'])) {
13678                                             if ($trwsp['endpage'] == $dom[$trid]['endpage']) {
13679                                                 $dom[$table_el]['rowspans'][$k]['endy'] = max($dom[$trid]['endy'], $trwsp['endy']);
13680                                             } elseif ($trwsp['endpage'] < $dom[$trid]['endpage']) {
13681                                                 $dom[$table_el]['rowspans'][$k]['endy'] = $dom[$trid]['endy'];
13682                                                 $dom[$table_el]['rowspans'][$k]['endpage'] = $dom[$trid]['endpage'];
13683                                             } else {
13684                                                 $dom[$trid]['endy'] = $this->pagedim[$dom[$trid]['endpage']]['hk'] - $this->pagedim[$dom[$trid]['endpage']]['bm'];
13685                                             }
13686                                         }
13687                                     }
13688                                 }
13689                             }
13690                             $this->x += ($cellspacingx / 2);
13691                         } else {
13692                             
13693                             if (!isset($opentagpos)) {
13694                                 if (!$this->InFooter) {
13695                                     if (isset($this->footerlen[$this->page])) {
13696                                         $this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page];
13697                                     } else {
13698                                         $this->footerpos[$this->page] = $this->pagelen[$this->page];
13699                                     }
13700                                     $opentagpos = $this->footerpos[$this->page];
13701                                 }
13702                             }
13703                             $this->openHTMLTagHandler($dom, $key, $cell);
13704                         }
13705                     } else {
13706                         
13707                         $this->closeHTMLTagHandler($dom, $key, $cell);
13708                     }
13709                 } elseif (strlen($dom[$key]['value']) > 0) {
13710                     
13711                     if (!$this->empty_string($this->lispacer)) {
13712                         $this->SetFont($pfontname, $pfontstyle, $pfontsize);
13713                         $this->lasth = $this->FontSize * $this->cell_height_ratio;
13714                         $minstartliney = $this->y;
13715                         $this->putHtmlListBullet($this->listnum, $this->lispacer, $pfontsize);
13716                         $this->SetFont($curfontname, $curfontstyle, $curfontsize);
13717                         $this->lasth = $this->FontSize * $this->cell_height_ratio;
13718                         if (is_numeric($pfontsize) AND ($pfontsize > 0) AND is_numeric($curfontsize) AND ($curfontsize > 0) AND ($pfontsize != $curfontsize)) {
13719                             $this->y += (($pfontsize - $curfontsize) / $this->k);
13720                             $minstartliney = min($this->y, $minstartliney);
13721                         }
13722                     }
13723                     
13724                     $this->htmlvspace = 0;
13725                     if ((!$this->premode) AND ($this->rtl OR $this->tmprtl)) {
13726                         
13727                         $len1 = strlen($dom[$key]['value']);
13728                         $lsp = $len1 - strlen(ltrim($dom[$key]['value']));
13729                         $rsp = $len1 - strlen(rtrim($dom[$key]['value']));
13730                         $tmpstr = '';
13731                         if ($rsp > 0) {
13732                             $tmpstr .= substr($dom[$key]['value'], -$rsp);
13733                         }
13734                         $tmpstr .= trim($dom[$key]['value']);
13735                         if ($lsp > 0) {
13736                             $tmpstr .= substr($dom[$key]['value'], 0, $lsp);
13737                         }
13738                         $dom[$key]['value'] = $tmpstr;
13739                     }
13740                     if ($newline) {
13741                         if (!$this->premode) {
13742                             if (($this->rtl OR $this->tmprtl)) {
13743                                 $dom[$key]['value'] = rtrim($dom[$key]['value']);
13744                             } else {
13745                                 $dom[$key]['value'] = ltrim($dom[$key]['value']);
13746                             }
13747                         }
13748                         $newline = false;
13749                         $firstblock = true;
13750                     } else {
13751                         $firstblock = false;
13752                     }
13753                     $strrest = '';
13754                     if (!empty($this->HREF) AND (isset($this->HREF['url']))) {
13755                         
13756                         $strrest = $this->addHtmlLink($this->HREF['url'], $dom[$key]['value'], $wfill, true, $this->HREF['color'], $this->HREF['style']);
13757                     } else {
13758                         $ctmpmargin = $this->cMargin;
13759                         $this->cMargin = 0;
13760                         if ($this->rtl) {
13761                             $this->x -= $this->textindent;
13762                         } else {
13763                             $this->x += $this->textindent;
13764                         }
13765                         
13766                         $strrest = $this->Write($this->lasth, $dom[$key]['value'], '', $wfill, '', false, 0, true, $firstblock);
13767                         $this->textindent = 0;
13768                         $this->cMargin = $ctmpmargin;
13769                     }
13770                     if (strlen($strrest) > 0) {
13771                         
13772                         $this->newline = true;
13773                         if ($cell) {
13774                             if ($this->rtl) {
13775                                 $this->x -= $this->cMargin;
13776                             } else {
13777                                 $this->x += $this->cMargin;
13778                             }
13779                         }
13780                         if ($strrest == $dom[$key]['value']) {
13781                             
13782                             ++$loop;
13783                         } else {
13784                             $loop = 0;
13785                         }
13786                         $dom[$key]['value'] = ltrim($strrest);
13787                         if ($loop < 3) {
13788                             --$key;
13789                         }
13790                     } else {
13791                         $loop = 0;
13792                     }
13793                 }
13794                 ++$key;
13795                 if (isset($dom[$key]['tag']) AND $dom[$key]['tag'] AND (!isset($dom[$key]['opening']) OR !$dom[$key]['opening']) AND isset($dom[($dom[$key]['parent'])]['attribute']['nobr']) AND ($dom[($dom[$key]['parent'])]['attribute']['nobr'] == 'true')) {
13796                     if ((!$undo) AND ($this->start_transaction_page == ($this->numpages - 1))) {
13797                         
13798                         $this->rollbackTransaction(true);
13799                         
13800                         foreach ($this_method_vars as $vkey => $vval) {
13801                             $$vkey = $vval;
13802                         }
13803                         
13804                         $this->AddPage();
13805                         $undo = true; 
13806                     } else {
13807                         $undo = false;
13808                     }
13809                 }
13810             } 
13811             
13812             if (isset($startlinex)) {
13813                 $yshift = $minstartliney - $startliney;
13814                 if (($yshift > 0) OR ($this->page > $startlinepage)) {
13815                     $yshift = 0;
13816                 }
13817                 if ((isset($plalign) AND ((($plalign == 'C') OR ($plalign == 'J') OR (($plalign == 'R') AND (!$this->rtl)) OR (($plalign == 'L') AND ($this->rtl))))) OR ($yshift < 0)) {
13818                     
13819                     $linew = abs($this->endlinex - $startlinex);
13820                     $pstart = substr($this->getPageBuffer($startlinepage), 0, $startlinepos);
13821                     if (isset($opentagpos) AND isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) {
13822                         $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
13823                         $midpos = min($opentagpos, $this->footerpos[$startlinepage]);
13824                     } elseif (isset($opentagpos)) {
13825                         $midpos = $opentagpos;
13826                     } elseif (isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) {
13827                         $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
13828                         $midpos = $this->footerpos[$startlinepage];
13829                     } else {
13830                         $midpos = 0;
13831                     }
13832                     if ($midpos > 0) {
13833                         $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos, ($midpos - $startlinepos));
13834                         $pend = substr($this->getPageBuffer($startlinepage), $midpos);
13835                     } else {
13836                         $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos);
13837                         $pend = '';
13838                     }   
13839                     
13840                     $tw = $w;
13841                     if ($this->lMargin != $prevlMargin) {
13842                         $tw += ($prevlMargin - $this->lMargin);
13843                     }
13844                     if ($this->rMargin != $prevrMargin) {
13845                         $tw += ($prevrMargin - $this->rMargin);
13846                     }
13847                     $mdiff = abs($tw - $linew);
13848                     if ($plalign == 'C') {
13849                         if ($this->rtl) {
13850                             $t_x = -($mdiff / 2);
13851                         } else {
13852                             $t_x = ($mdiff / 2);
13853                         }
13854                     } elseif (($plalign == 'R') AND (!$this->rtl)) {
13855                         
13856                         $t_x = $mdiff;
13857                     } elseif (($plalign == 'L') AND ($this->rtl)) {
13858                         
13859                         $t_x = -$mdiff;
13860                     } else {
13861                         $t_x = 0;
13862                     }
13863                     if (($t_x != 0) OR ($yshift < 0)) {
13864                         
13865                         $trx = sprintf('1 0 0 1 %.3F %.3F cm', ($t_x * $this->k), ($yshift * $this->k));
13866                         $this->setPageBuffer($startlinepage, $pstart."\nq\n".$trx."\n".$pmid."\nQ\n".$pend);
13867                         $endlinepos = strlen($pstart."\nq\n".$trx."\n".$pmid."\nQ\n");
13868                         
13869                         if (isset($this->PageAnnots[$this->page])) {
13870                             foreach ($this->PageAnnots[$this->page] as $pak => $pac) {
13871                                 if ($pak >= $pask) {
13872                                     $this->PageAnnots[$this->page][$pak]['x'] += $t_x;
13873                                     $this->PageAnnots[$this->page][$pak]['y'] -= $yshift;
13874                                 }
13875                             }
13876                         }
13877                         $this->y -= $yshift;
13878                     }
13879                 }
13880             }
13881             if ($ln AND (!($cell AND ($dom[$key-1]['value'] == 'table')))) {
13882                 $this->Ln($this->lasth);
13883             }
13884             
13885             $this->setGraphicVars($gvars);
13886             if ($this->page > $prevPage) {
13887                 $this->lMargin = $this->pagedim[$this->page]['olm'];
13888                 $this->rMargin = $this->pagedim[$this->page]['orm'];
13889             }
13890             
13891             $this->listnum = $prev_listnum;
13892             $this->listordered = $prev_listordered;
13893             $this->listcount = $prev_listcount;
13894             $this->lispacer = $prev_lispacer;
13895             unset($dom);
13896         }
13897         
13905         protected function openHTMLTagHandler(&$dom, $key, $cell=false) {
13906             $tag = $dom[$key];
13907             $parent = $dom[($dom[$key]['parent'])];
13908             $firstorlast = ($key == 1);
13909             
13910             if (isset($tag['attribute']['dir'])) {
13911                 $this->tmprtl = $tag['attribute']['dir'] == 'rtl' ? 'R' : 'L';
13912             } else {
13913                 $this->tmprtl = false;
13914             }
13915             
13916             switch($tag['value']) {
13917                 case 'table': {
13918                     $cp = 0;
13919                     $cs = 0;
13920                     $dom[$key]['rowspans'] = array();
13921                     if (!$this->empty_string($dom[$key]['thead'])) {
13922                         
13923                         $this->thead = $dom[$key]['thead'];
13924                         if (!isset($this->theadMargins) OR (empty($this->theadMargins))) {
13925                             $this->theadMargins = array();
13926                             $this->theadMargins['cmargin'] = $this->cMargin;
13927                         }
13928                     }
13929                     if (isset($tag['attribute']['cellpadding'])) {
13930                         $cp = $this->getHTMLUnitToUnits($tag['attribute']['cellpadding'], 1, 'px');
13931                         $this->oldcMargin = $this->cMargin;
13932                         $this->cMargin = $cp;
13933                     }
13934                     if (isset($tag['attribute']['cellspacing'])) {
13935                         $cs = $this->getHTMLUnitToUnits($tag['attribute']['cellspacing'], 1, 'px');
13936                     }
13937                     $this->checkPageBreak((2 * $cp) + (2 * $cs) + $this->lasth);
13938                     break;
13939                 }
13940                 case 'tr': {
13941                     
13942                     $dom[$key]['cellpos'] = array();
13943                     break;
13944                 }
13945                 case 'hr': {
13946                     $this->addHTMLVertSpace(1, $cell, '', $firstorlast, $tag['value'], false);
13947                     $this->htmlvspace = 0;
13948                     $wtmp = $this->w - $this->lMargin - $this->rMargin;
13949                     if ((isset($tag['attribute']['width'])) AND ($tag['attribute']['width'] != '')) {
13950                         $hrWidth = $this->getHTMLUnitToUnits($tag['attribute']['width'], $wtmp, 'px');
13951                     } else {
13952                         $hrWidth = $wtmp;
13953                     }
13954                     $x = $this->GetX();
13955                     $y = $this->GetY();
13956                     $prevlinewidth = $this->GetLineWidth();
13957                     $this->Line($x, $y, $x + $hrWidth, $y);
13958                     $this->SetLineWidth($prevlinewidth);
13959                     $this->addHTMLVertSpace(1, $cell, '', !isset($dom[($key + 1)]), $tag['value'], false);
13960                     break;
13961                 }
13962                 case 'a': {
13963                     if (array_key_exists('href', $tag['attribute'])) {
13964                         $this->HREF['url'] = $tag['attribute']['href'];
13965                     }
13966                     $this->HREF['color'] = $this->htmlLinkColorArray;
13967                     $this->HREF['style'] = $this->htmlLinkFontStyle;
13968                     if (array_key_exists('style', $tag['attribute'])) {
13969                         
13970                         preg_match_all('/([^;:\s]*):([^;]*)/', $tag['attribute']['style'], $style_array, PREG_PATTERN_ORDER);
13971                         $astyle = array();
13972                         while (list($id, $name) = each($style_array[1])) {
13973                             $name = strtolower($name);
13974                             $astyle[$name] = trim($style_array[2][$id]);
13975                         }
13976                         if (isset($astyle['color'])) {
13977                             $this->HREF['color'] = $this->convertHTMLColorToDec($astyle['color']);
13978                         }
13979                         if (isset($astyle['text-decoration'])) {
13980                             $this->HREF['style'] = '';
13981                             $decors = explode(' ', strtolower($astyle['text-decoration']));
13982                             foreach ($decors as $dec) {
13983                                 $dec = trim($dec);
13984                                 if (!$this->empty_string($dec)) {
13985                                     if ($dec{0} == 'u') {
13986                                         $this->HREF['style'] .= 'U';
13987                                     } elseif ($dec{0} == 'l') {
13988                                         $this->HREF['style'] .= 'D';
13989                                     }
13990                                 }
13991                             }
13992                         }
13993                     }       
13994                     break;
13995                 }
13996                 case 'img': {
13997                     if (isset($tag['attribute']['src'])) {
13998                         
13999                         if (($tag['attribute']['src'][0] == '/') AND ($_SERVER['DOCUMENT_ROOT'] != '/')) {
14000                             $tag['attribute']['src'] = $_SERVER['DOCUMENT_ROOT'].$tag['attribute']['src'];
14001                         }
14002                         $tag['attribute']['src'] = urldecode($tag['attribute']['src']);
14003                         $tag['attribute']['src'] = str_replace(K_PATH_URL, K_PATH_MAIN, $tag['attribute']['src']);
14004                         if (!isset($tag['attribute']['width'])) {
14005                             $tag['attribute']['width'] = 0;
14006                         }
14007                         if (!isset($tag['attribute']['height'])) {
14008                             $tag['attribute']['height'] = 0;
14009                         }
14010                         
14011                             
14012                             
14013                             $tag['attribute']['align'] = 'bottom';
14014                         
14015                         switch($tag['attribute']['align']) {
14016                             case 'top': {
14017                                 $align = 'T';
14018                                 break;
14019                             }
14020                             case 'middle': {
14021                                 $align = 'M';
14022                                 break;
14023                             }
14024                             case 'bottom': {
14025                                 $align = 'B';
14026                                 break;
14027                             }
14028                             default: {
14029                                 $align = 'B';
14030                                 break;
14031                             }
14032                         }
14033                         $fileinfo = pathinfo($tag['attribute']['src']);
14034                         if (isset($fileinfo['extension']) AND (!$this->empty_string($fileinfo['extension']))) {
14035                             $type = strtolower($fileinfo['extension']);
14036                         }
14037                         $prevy = $this->y;
14038                         $xpos = $this->GetX();
14039                         if (isset($dom[($key - 1)]) AND ($dom[($key - 1)]['value'] == ' ')) {
14040                             if ($this->rtl) {
14041                                 $xpos += $this->GetStringWidth(' ');
14042                             } else {
14043                                 $xpos -= $this->GetStringWidth(' ');
14044                             }
14045                         }
14046                         $imglink = '';
14047                         if (isset($this->HREF['url']) AND !$this->empty_string($this->HREF['url'])) {
14048                             $imglink = $this->HREF['url'];
14049                             if ($imglink{0} == '#') {
14050                                 
14051                                 $page = intval(substr($imglink, 1));
14052                                 $imglink = $this->AddLink();
14053                                 $this->SetLink($imglink, 0, $page);
14054                             }
14055                         }
14056                         $border = 0;
14057                         if (isset($tag['attribute']['border']) AND !empty($tag['attribute']['border'])) {
14058                             
14059                             $border = $tag['attribute']['border'];
14060                         }
14061                         $iw = '';
14062                         if (isset($tag['attribute']['width'])) {
14063                             $iw = $this->getHTMLUnitToUnits($tag['attribute']['width'], 1, 'px', false);
14064                         }
14065                         $ih = '';
14066                         if (isset($tag['attribute']['height'])) {
14067                             $ih = $this->getHTMLUnitToUnits($tag['attribute']['height'], 1, 'px', false);
14068                         }
14069                         if (($type == 'eps') OR ($type == 'ai')) {
14070                             $this->ImageEps($tag['attribute']['src'], $xpos, $this->GetY(), $iw, $ih, $imglink, true, $align, '', $border);
14071                         } else {
14072                             $this->Image($tag['attribute']['src'], $xpos, $this->GetY(), $iw, $ih, '', $imglink, $align, false, 300, '', false, false, $border);
14073                         }
14074                         switch($align) {
14075                             case 'T': {
14076                                 $this->y = $prevy;
14077                                 break;
14078                             }
14079                             case 'M': {
14080                                 $this->y = (($this->img_rb_y + $prevy - ($tag['fontsize'] / $this->k)) / 2) ;
14081                                 break;
14082                             }
14083                             case 'B': {
14084                                 $this->y = $this->img_rb_y - ($tag['fontsize'] / $this->k);
14085                                 break;
14086                             }
14087                         }
14088                     }
14089                     break;
14090                 }
14091                 case 'dl': {
14092                     ++$this->listnum;
14093                     $this->addHTMLVertSpace(0, $cell, '', $firstorlast, $tag['value'], false);
14094                     break;
14095                 }
14096                 case 'dt': {
14097                     $this->addHTMLVertSpace(1, $cell, '', $firstorlast, $tag['value'], false);
14098                     break;
14099                 }
14100                 case 'dd': {
14101                     if ($this->rtl) {
14102                         $this->rMargin += $this->listindent;
14103                     } else {
14104                         $this->lMargin += $this->listindent;
14105                     }
14106                     $this->addHTMLVertSpace(1, $cell, '', $firstorlast, $tag['value'], false);
14107                     break;
14108                 }
14109                 case 'ul':
14110                 case 'ol': {
14111                     $this->addHTMLVertSpace(0, $cell, '', $firstorlast, $tag['value'], false);
14112                     $this->htmlvspace = 0;
14113                     ++$this->listnum;
14114                     if ($tag['value'] == 'ol') {
14115                         $this->listordered[$this->listnum] = true;
14116                     } else {
14117                         $this->listordered[$this->listnum] = false;
14118                     }
14119                     if (isset($tag['attribute']['start'])) {
14120                         $this->listcount[$this->listnum] = intval($tag['attribute']['start']) - 1;
14121                     } else {
14122                         $this->listcount[$this->listnum] = 0;
14123                     }
14124                     if ($this->rtl) {
14125                         $this->rMargin += $this->listindent;
14126                     } else {
14127                         $this->lMargin += $this->listindent;
14128                     }
14129                     $this->addHTMLVertSpace(0, $cell, '', $firstorlast, $tag['value'], false);
14130                     $this->htmlvspace = 0;
14131                     break;
14132                 }
14133                 case 'li': {
14134                     $this->addHTMLVertSpace(1, $cell, '', $firstorlast, $tag['value'], false);
14135                     if ($this->listordered[$this->listnum]) {
14136                         
14137                         if (isset($parent['attribute']['type']) AND !$this->empty_string($parent['attribute']['type'])) {
14138                             $this->lispacer = $parent['attribute']['type'];
14139                         } elseif (isset($parent['listtype']) AND !$this->empty_string($parent['listtype'])) {
14140                             $this->lispacer = $parent['listtype'];
14141                         } elseif (isset($this->lisymbol) AND !$this->empty_string($this->lisymbol)) {
14142                             $this->lispacer = $this->lisymbol;
14143                         } else {
14144                             $this->lispacer = '#';
14145                         }
14146                         ++$this->listcount[$this->listnum];
14147                         if (isset($tag['attribute']['value'])) {
14148                             $this->listcount[$this->listnum] = intval($tag['attribute']['value']);
14149                         }
14150                     } else {
14151                         
14152                         if (isset($parent['attribute']['type']) AND !$this->empty_string($parent['attribute']['type'])) {
14153                             $this->lispacer = $parent['attribute']['type'];
14154                         } elseif (isset($parent['listtype']) AND !$this->empty_string($parent['listtype'])) {
14155                             $this->lispacer = $parent['listtype'];
14156                         } elseif (isset($this->lisymbol) AND !$this->empty_string($this->lisymbol)) {
14157                             $this->lispacer = $this->lisymbol;
14158                         } else {
14159                             $this->lispacer = '!';
14160                         }
14161                     }
14162                     break;
14163                 }
14164                 case 'blockquote': {
14165                     if ($this->rtl) {
14166                         $this->rMargin += $this->listindent;
14167                     } else {
14168                         $this->lMargin += $this->listindent;
14169                     }
14170                     $this->addHTMLVertSpace(2, $cell, '', $firstorlast, $tag['value'], false);
14171                     break;
14172                 }
14173                 case 'br': {
14174                     $this->Ln('', $cell);
14175                     break;
14176                 }
14177                 case 'div': {
14178                     $this->addHTMLVertSpace(1, $cell, '', $firstorlast, $tag['value'], false);
14179                     break;
14180                 }
14181                 case 'p': {
14182                     $this->addHTMLVertSpace(2, $cell, '', $firstorlast, $tag['value'], false);
14183                     break;
14184                 }
14185                 case 'pre': {
14186                     $this->addHTMLVertSpace(1, $cell, '', $firstorlast, $tag['value'], false);
14187                     $this->premode = true;
14188                     break;
14189                 }
14190                 case 'sup': {
14191                     $this->SetXY($this->GetX(), $this->GetY() - ((0.7 * $this->FontSizePt) / $this->k));
14192                     break;
14193                 }
14194                 case 'sub': {
14195                     $this->SetXY($this->GetX(), $this->GetY() + ((0.3 * $this->FontSizePt) / $this->k));
14196                     break;
14197                 }
14198                 case 'h1': 
14199                 case 'h2': 
14200                 case 'h3': 
14201                 case 'h4': 
14202                 case 'h5': 
14203                 case 'h6': {
14204                     $this->addHTMLVertSpace(1, $cell, ($tag['fontsize'] * 1.5) / $this->k, $firstorlast, $tag['value'], false);
14205                     break;
14206                 }
14207                 
14208                 case 'form': {
14209                     if (isset($tag['attribute']['action'])) {
14210                         $this->form_action = $tag['attribute']['action'];
14211                     } else {
14212                         $this->form_action = K_PATH_URL.$_SERVER['SCRIPT_NAME'];
14213                     }
14214                     if (isset($tag['attribute']['enctype'])) {
14215                         $this->form_enctype = $tag['attribute']['enctype'];
14216                     } else {
14217                         $this->form_enctype = 'application/x-www-form-urlencoded';
14218                     }
14219                     if (isset($tag['attribute']['method'])) {
14220                         $this->form_mode = $tag['attribute']['method'];
14221                     } else {
14222                         $this->form_mode = 'post';
14223                     }
14224                     break;
14225                 }
14226                 case 'input': {
14227                     if (isset($tag['attribute']['name']) AND !$this->empty_string($tag['attribute']['name'])) {
14228                         $name = $tag['attribute']['name'];
14229                     } else {
14230                         break;
14231                     }
14232                     $prop = array();
14233                     $opt = array();
14234                     if (isset($tag['attribute']['value']) AND !$this->empty_string($tag['attribute']['value'])) {
14235                         $value = $tag['attribute']['value'];
14236                     }
14237                     if (isset($tag['attribute']['maxlength']) AND !$this->empty_string($tag['attribute']['maxlength'])) {
14238                         $opt['maxlen'] = intval($tag['attribute']['value']);
14239                     }
14240                     $h = $this->FontSize * $this->cell_height_ratio;
14241                     if (isset($tag['attribute']['size']) AND !$this->empty_string($tag['attribute']['size'])) {
14242                         $w = intval($tag['attribute']['size']) * $this->GetStringWidth(chr(32)) * 2;
14243                     } else {
14244                         $w = $h;
14245                     }
14246                     if (isset($tag['attribute']['checked']) AND (($tag['attribute']['checked'] == 'checked') OR ($tag['attribute']['checked'] == 'true'))) {
14247                         $checked = true;
14248                     } else {
14249                         $checked = false;
14250                     }
14251                     switch ($tag['attribute']['type']) {
14252                         case 'text': {
14253                             if (isset($value)) {
14254                                 $opt['v'] = $value;
14255                             }
14256                             $this->TextField($name, $w, $h, $prop, $opt, '', '', false);
14257                             break;
14258                         }
14259                         case 'password': {
14260                             if (isset($value)) {
14261                                 $opt['v'] = $value;
14262                             }
14263                             $prop['password'] = 'true';
14264                             $this->TextField($name, $w, $h, $prop, $opt, '', '', false);
14265                             break;
14266                         }
14267                         case 'checkbox': {
14268                             $this->CheckBox($name, $w, $checked, $prop, $opt, $value, '', '', false);
14269                             break;
14270                         }
14271                         case 'radio': {
14272                             $this->RadioButton($name, $w, $prop, $opt, $value, $checked, '', '', false);
14273                             break;
14274                         }
14275                         case 'submit': {
14276                             $w = $this->GetStringWidth($value) * 1.5;
14277                             $h *= 1.6;
14278                             $prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255));
14279                             $action = array();
14280                             $action['S'] = 'SubmitForm';
14281                             $action['F'] = $this->form_action;
14282                             if ($this->form_enctype != 'FDF') {
14283                                 $action['Flags'] = array('ExportFormat');
14284                             }
14285                             if ($this->form_mode == 'get') {
14286                                 $action['Flags'] = array('GetMethod');
14287                             }
14288                             $this->Button($name, $w, $h, $value, $action, $prop, $opt, '', '', false);
14289                             break;
14290                         }
14291                         case 'reset': {
14292                             $w = $this->GetStringWidth($value) * 1.5;
14293                             $h *= 1.6;
14294                             $prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255));
14295                             $this->Button($name, $w, $h, $value, array('S'=>'ResetForm'), $prop, $opt, '', '', false);
14296                             break;
14297                         }
14298                         case 'file': {
14299                             $prop['fileSelect'] = 'true';
14300                             $this->TextField($name, $w, $h, $prop, $opt, '', '', false);
14301                             if (!isset($value)) {
14302                                 $value = '*';
14303                             }
14304                             $w = $this->GetStringWidth($value) * 2;
14305                             $h *= 1.2;
14306                             $prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255));
14307                             $jsaction = 'var f=this.getField(\''.$name.'\'); f.browseForFileToSubmit();';
14308                             $this->Button('FB_'.$name, $w, $h, $value, $jsaction, $prop, $opt, '', '', false);
14309                             break;
14310                         }
14311                         case 'hidden': {
14312                             if (isset($value)) {
14313                                 $opt['v'] = $value;
14314                             }
14315                             $opt['f'] = array('invisible', 'hidden');
14316                             $this->TextField($name, 0, 0, $prop, $opt, '', '', false);
14317                             break;
14318                         }
14319                         case 'image': {
14320                             // THIS TYPE MUST BE FIXED
14321                             if (isset($tag['attribute']['src']) AND !$this->empty_string($tag['attribute']['src'])) {
14322                                 $img = $tag['attribute']['src'];
14323                             } else {
14324                                 break;
14325                             }
14326                             $value = 'img';
14327                             //$opt['mk'] = array('i'=>$img, 'tp'=>1, 'if'=>array('sw'=>'A', 's'=>'A', 'fb'=>false));
14328                             if (isset($tag['attribute']['onclick']) AND !empty($tag['attribute']['onclick'])) {
14329                                 $jsaction = $tag['attribute']['onclick'];
14330                             } else {
14331                                 $jsaction = '';
14332                             }
14333                             $this->Button($name, $w, $h, $value, $jsaction, $prop, $opt, '', '', false);
14334                             break;
14335                         }
14336                         case 'button': {
14337                             $w = $this->GetStringWidth($value) * 1.5;
14338                             $h *= 1.6;
14339                             $prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255));
14340                             if (isset($tag['attribute']['onclick']) AND !empty($tag['attribute']['onclick'])) {
14341                                 $jsaction = $tag['attribute']['onclick'];
14342                             } else {
14343                                 $jsaction = '';
14344                             }
14345                             $this->Button($name, $w, $h, $value, $jsaction, $prop, $opt, '', '', false);
14346                             break;
14347                         }
14348                     }
14349                     break;
14350                 }
14351                 case 'textarea': {
14352                     $prop = array();
14353                     $opt = array();
14354                     if (isset($tag['attribute']['name']) AND !$this->empty_string($tag['attribute']['name'])) {
14355                         $name = $tag['attribute']['name'];
14356                     } else {
14357                         break;
14358                     }
14359                     if (isset($tag['attribute']['value']) AND !$this->empty_string($tag['attribute']['value'])) {
14360                         $opt['v'] = $tag['attribute']['value'];
14361                     }
14362                     if (isset($tag['attribute']['cols']) AND !$this->empty_string($tag['attribute']['cols'])) {
14363                         $w = intval($tag['attribute']['cols']) * $this->GetStringWidth(chr(32)) * 2;
14364                     } else {
14365                         $w = 40;
14366                     }
14367                     if (isset($tag['attribute']['rows']) AND !$this->empty_string($tag['attribute']['rows'])) {
14368                         $h = intval($tag['attribute']['rows']) * $this->FontSize * $this->cell_height_ratio;
14369                     } else {
14370                         $h = 10;
14371                     }
14372                     $prop['multiline'] = 'true';
14373                     $this->TextField($name, $w, $h, $prop, $opt, '', '', false);
14374                     break;
14375                 }
14376                 case 'select': {
14377                     $h = $this->FontSize * $this->cell_height_ratio;
14378                     if (isset($tag['attribute']['size']) AND !$this->empty_string($tag['attribute']['size'])) {
14379                         $h *= ($tag['attribute']['size'] + 1);
14380                     }
14381                     $prop = array();
14382                     $opt = array();
14383                     if (isset($tag['attribute']['name']) AND !$this->empty_string($tag['attribute']['name'])) {
14384                         $name = $tag['attribute']['name'];
14385                     } else {
14386                         break;
14387                     }
14388                     $w = 0;
14389                     if (isset($tag['attribute']['opt']) AND !$this->empty_string($tag['attribute']['opt'])) {
14390                         $options = explode ("\r", $tag['attribute']['opt']);
14391                         $values = array();
14392                         foreach ($options as $val) {
14393                             if (strpos($val, "\t") !== false) {
14394                                 $opts = explode("\t", $val);
14395                                 $values[] = $opts;
14396                                 $w = max($w, $this->GetStringWidth($opts[1]));
14397                             } else {
14398                                 $values[] = $val;
14399                                 $w = max($w, $this->GetStringWidth($val));
14400                             }
14401                         }
14402                     } else {
14403                         break;
14404                     }
14405                     $w *= 2;
14406                     if (isset($tag['attribute']['multiple']) AND ($tag['attribute']['multiple']='multiple')) {
14407                         $prop['multipleSelection'] = 'true';
14408                         $this->ListBox($name, $w, $h, $values, $prop, $opt, '', '', false);
14409                     } else {
14410                         $this->ComboBox($name, $w, $h, $values, $prop, $opt, '', '', false);
14411                     }
14412                     break;
14413                 }
14414                 case 'tcpdf': {
14415                     // NOT HTML: used to call TCPDF methods
14416                     if (isset($tag['attribute']['method'])) {
14417                         $tcpdf_method = $tag['attribute']['method'];
14418                         if (method_exists($this, $tcpdf_method)) {
14419                             if (isset($tag['attribute']['params']) AND (!empty($tag['attribute']['params']))) {
14420                                 eval('$params = array('.$this->unhtmlentities($tag['attribute']['params']).');');
14421                                 call_user_func_array(array($this, $tcpdf_method), $params);
14422                             } else {
14423                                 $this->$tcpdf_method();
14424                             }
14425                             $this->newline = true;
14426                         }
14427                     }
14428                 }
14429                 default: {
14430                     break;
14431                 }
14432             }
14433         }
14434         
14442         protected function closeHTMLTagHandler(&$dom, $key, $cell=false) {
14443             $tag = $dom[$key];
14444             $parent = $dom[($dom[$key]['parent'])];
14445             $firstorlast = ((!isset($dom[($key + 1)])) OR ((!isset($dom[($key + 2)])) AND ($dom[($key + 1)]['value'] == 'marker')));
14446             $in_table_head = false;
14447             //Closing tag
14448             switch($tag['value']) {
14449                 case 'tr': {
14450                     $table_el = $dom[($dom[$key]['parent'])]['parent'];
14451                     if(!isset($parent['endy'])) {
14452                         $dom[($dom[$key]['parent'])]['endy'] = $this->y;
14453                         $parent['endy'] = $this->y;
14454                     }
14455                     if(!isset($parent['endpage'])) {
14456                         $dom[($dom[$key]['parent'])]['endpage'] = $this->page;
14457                         $parent['endpage'] = $this->page;
14458                     }
14459                     // update row-spanned cells
14460                     if (isset($dom[$table_el]['rowspans'])) {
14461                         foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) {
14462                             $dom[$table_el]['rowspans'][$k]['rowspan'] -= 1;
14463                             if ($dom[$table_el]['rowspans'][$k]['rowspan'] == 0) {
14464                                 if ($dom[$table_el]['rowspans'][$k]['endpage'] == $parent['endpage']) {
14465                                     $dom[($dom[$key]['parent'])]['endy'] = max($dom[$table_el]['rowspans'][$k]['endy'], $parent['endy']);
14466                                 } elseif ($dom[$table_el]['rowspans'][$k]['endpage'] > $parent['endpage']) {
14467                                     $dom[($dom[$key]['parent'])]['endy'] = $dom[$table_el]['rowspans'][$k]['endy'];
14468                                     $dom[($dom[$key]['parent'])]['endpage'] = $dom[$table_el]['rowspans'][$k]['endpage'];
14469                                 }
14470                             }
14471                         }
14472                         // report new endy and endpage to the rowspanned cells
14473                         foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) {
14474                             if ($dom[$table_el]['rowspans'][$k]['rowspan'] == 0) {
14475                                 $dom[$table_el]['rowspans'][$k]['endpage'] = max($dom[$table_el]['rowspans'][$k]['endpage'], $dom[($dom[$key]['parent'])]['endpage']);
14476                                 $dom[($dom[$key]['parent'])]['endpage'] = $dom[$table_el]['rowspans'][$k]['endpage'];
14477                                 $dom[$table_el]['rowspans'][$k]['endy'] = max($dom[$table_el]['rowspans'][$k]['endy'], $dom[($dom[$key]['parent'])]['endy']);
14478                                 $dom[($dom[$key]['parent'])]['endy'] = $dom[$table_el]['rowspans'][$k]['endy'];
14479                             }
14480                         }
14481                         // update remaining rowspanned cells
14482                         foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) {
14483                             if ($dom[$table_el]['rowspans'][$k]['rowspan'] == 0) {
14484                                 $dom[$table_el]['rowspans'][$k]['endpage'] = $dom[($dom[$key]['parent'])]['endpage'];
14485                                 $dom[$table_el]['rowspans'][$k]['endy'] = $dom[($dom[$key]['parent'])]['endy'];
14486                             }
14487                         }
14488                     }
14489                     $this->setPage($dom[($dom[$key]['parent'])]['endpage']);
14490                     $this->y = $dom[($dom[$key]['parent'])]['endy'];
14491                     if (isset($dom[$table_el]['attribute']['cellspacing'])) {
14492                         $cellspacing = $this->getHTMLUnitToUnits($dom[$table_el]['attribute']['cellspacing'], 1, 'px');
14493                         $this->y += $cellspacing;
14494                     }               
14495                     $this->Ln(0, $cell);
14496                     $this->x = $parent['startx'];
14497                     // account for booklet mode
14498                     if ($this->page > $parent['startpage']) {
14499                         if (($this->rtl) AND ($this->pagedim[$this->page]['orm'] != $this->pagedim[$parent['startpage']]['orm'])) {
14500                             $this->x += ($this->pagedim[$this->page]['orm'] - $this->pagedim[$parent['startpage']]['orm']);
14501                         } elseif ((!$this->rtl) AND ($this->pagedim[$this->page]['olm'] != $this->pagedim[$parent['startpage']]['olm'])) {
14502                             $this->x += ($this->pagedim[$this->page]['olm'] - $this->pagedim[$parent['startpage']]['olm']);
14503                         }
14504                     }
14505                     break;
14506                 }
14507                 case 'tablehead':
14508                     // closing tag used for the thead part
14509                     $in_table_head = true;
14510                 case 'table': {
14511                     // draw borders
14512                     $table_el = $parent;
14513                     if ((isset($table_el['attribute']['border']) AND ($table_el['attribute']['border'] > 0)) 
14514                         OR (isset($table_el['style']['border']) AND ($table_el['style']['border'] > 0))) {
14515                             $border = 1;
14516                     } else {
14517                         $border = 0;
14518                     }
14519                     // fix bottom line alignment of last line before page break
14520                     foreach ($dom[($dom[$key]['parent'])]['trids'] as $j => $trkey) {
14521                         // update row-spanned cells
14522                         if (isset($dom[($dom[$key]['parent'])]['rowspans'])) {
14523                             foreach ($dom[($dom[$key]['parent'])]['rowspans'] as $k => $trwsp) {
14524                                 if ($trwsp['trid'] == $trkey) {
14525                                     $dom[($dom[$key]['parent'])]['rowspans'][$k]['mrowspan'] -= 1;
14526                                 }
14527                                 if (isset($prevtrkey) AND ($trwsp['trid'] == $prevtrkey) AND ($trwsp['mrowspan'] >= 0)) {
14528                                     $dom[($dom[$key]['parent'])]['rowspans'][$k]['trid'] = $trkey;
14529                                 }
14530                             }
14531                         }
14532                         if (isset($prevtrkey) AND ($dom[$trkey]['startpage'] > $dom[$prevtrkey]['endpage'])) {
14533                             $pgendy = $this->pagedim[$dom[$prevtrkey]['endpage']]['hk'] - $this->pagedim[$dom[$prevtrkey]['endpage']]['bm'];
14534                             $dom[$prevtrkey]['endy'] = $pgendy;
14535                             // update row-spanned cells
14536                             if (isset($dom[($dom[$key]['parent'])]['rowspans'])) {
14537                                 foreach ($dom[($dom[$key]['parent'])]['rowspans'] as $k => $trwsp) {
14538                                     if (($trwsp['trid'] == $trkey) AND ($trwsp['mrowspan'] == 1) AND ($trwsp['endpage'] == $dom[$prevtrkey]['endpage'])) {
14539                                         $dom[($dom[$key]['parent'])]['rowspans'][$k]['endy'] = $pgendy;
14540                                         $dom[($dom[$key]['parent'])]['rowspans'][$k]['mrowspan'] = -1;
14541                                     }
14542                                 }
14543                             }
14544                         }
14545                         $prevtrkey = $trkey;
14546                         $table_el = $dom[($dom[$key]['parent'])];
14547                     }
14548                     // for each row
14549                     foreach ($table_el['trids'] as $j => $trkey) {
14550                         $parent = $dom[$trkey];
14551                         // for each cell on the row
14552                         foreach ($parent['cellpos'] as $k => $cellpos) {
14553                             if (isset($cellpos['rowspanid']) AND ($cellpos['rowspanid'] >= 0)) {
14554                                 $cellpos['startx'] = $table_el['rowspans'][($cellpos['rowspanid'])]['startx'];
14555                                 $cellpos['endx'] = $table_el['rowspans'][($cellpos['rowspanid'])]['endx'];
14556                                 $endy = $table_el['rowspans'][($cellpos['rowspanid'])]['endy'];
14557                                 $startpage = $table_el['rowspans'][($cellpos['rowspanid'])]['startpage'];
14558                                 $endpage = $table_el['rowspans'][($cellpos['rowspanid'])]['endpage'];
14559                             } else {
14560                                 $endy = $parent['endy'];
14561                                 $startpage = $parent['startpage'];
14562                                 $endpage = $parent['endpage'];
14563                             }
14564                             if ($endpage > $startpage) {
14565                                 // design borders around HTML cells.
14566                                 for ($page=$startpage; $page <= $endpage; ++$page) {
14567                                     $this->setPage($page);
14568                                     if ($page == $startpage) {
14569                                         $this->y = $parent['starty']; // put cursor at the beginning of row on the first page
14570                                         $ch = $this->getPageHeight() - $parent['starty'] - $this->getBreakMargin();
14571                                         $cborder = $this->getBorderMode($border, $position='start');
14572                                     } elseif ($page == $endpage) {
14573                                         $this->y = $this->tMargin; // put cursor at the beginning of last page
14574                                         $ch = $endy - $this->tMargin;
14575                                         $cborder = $this->getBorderMode($border, $position='end');
14576                                     } else {
14577                                         $this->y = $this->tMargin; // put cursor at the beginning of the current page
14578                                         $ch = $this->getPageHeight() - $this->tMargin - $this->getBreakMargin();
14579                                         $cborder = $this->getBorderMode($border, $position='middle');
14580                                     }
14581                                     if (isset($cellpos['bgcolor']) AND ($cellpos['bgcolor']) !== false) {
14582                                         $this->SetFillColorArray($cellpos['bgcolor']);
14583                                         $fill = true;
14584                                     } else {
14585                                         $fill = false;
14586                                     }
14587                                     $cw = abs($cellpos['endx'] - $cellpos['startx']);
14588                                     $this->x = $cellpos['startx'];
14589                                     // account for margin changes
14590                                     if ($page > $startpage) {
14591                                         if (($this->rtl) AND ($this->pagedim[$page]['orm'] != $this->pagedim[$startpage]['orm'])) {
14592                                             $this->x -= ($this->pagedim[$page]['orm'] - $this->pagedim[$startpage]['orm']);
14593                                         } elseif ((!$this->rtl) AND ($this->pagedim[$page]['lm'] != $this->pagedim[$startpage]['olm'])) {
14594                                             $this->x += ($this->pagedim[$page]['olm'] - $this->pagedim[$startpage]['olm']);
14595                                         }
14596                                     }
14597                                     // design a cell around the text
14598                                     $ccode = $this->FillColor."\n".$this->getCellCode($cw, $ch, '', $cborder, 1, '', $fill, '', 0, true);
14599                                     if ($cborder OR $fill) {
14600                                         $pagebuff = $this->getPageBuffer($this->page);
14601                                         $pstart = substr($pagebuff, 0, $this->intmrk[$this->page]);
14602                                         $pend = substr($pagebuff, $this->intmrk[$this->page]);
14603                                         $this->setPageBuffer($this->page, $pstart.$ccode."\n".$pend);
14604                                         $this->intmrk[$this->page] += strlen($ccode."\n");
14605                                     }
14606                                 }
14607                             } else {
14608                                 $this->setPage($startpage);
14609                                 if (isset($cellpos['bgcolor']) AND ($cellpos['bgcolor']) !== false) {
14610                                     $this->SetFillColorArray($cellpos['bgcolor']);
14611                                     $fill = true;
14612                                 } else {
14613                                     $fill = false;
14614                                 }
14615                                 $this->x = $cellpos['startx'];
14616                                 $this->y = $parent['starty'];
14617                                 $cw = abs($cellpos['endx'] - $cellpos['startx']);
14618                                 $ch = $endy - $parent['starty'];
14619                                 // design a cell around the text
14620                                 $ccode = $this->FillColor."\n".$this->getCellCode($cw, $ch, '', $border, 1, '', $fill, '', 0, true);
14621                                 if ($border OR $fill) {
14622                                     if (end($this->transfmrk[$this->page]) !== false) {
14623                                         $pagemarkkey = key($this->transfmrk[$this->page]);
14624                                         $pagemark = &$this->transfmrk[$this->page][$pagemarkkey];
14625                                     } elseif ($this->InFooter) {
14626                                         $pagemark = &$this->footerpos[$this->page];
14627                                     } else {
14628                                         $pagemark = &$this->intmrk[$this->page];
14629                                     }
14630                                     $pagebuff = $this->getPageBuffer($this->page);
14631                                     $pstart = substr($pagebuff, 0, $pagemark);
14632                                     $pend = substr($pagebuff, $pagemark);
14633                                     $this->setPageBuffer($this->page, $pstart.$ccode."\n".$pend);
14634                                     $pagemark += strlen($ccode."\n");
14635                                 }                   
14636                             }
14637                         }                   
14638                         if (isset($table_el['attribute']['cellspacing'])) {
14639                             $cellspacing = $this->getHTMLUnitToUnits($table_el['attribute']['cellspacing'], 1, 'px');
14640                             $this->y += $cellspacing;
14641                         }               
14642                         $this->Ln(0, $cell);
14643                         $this->x = $parent['startx'];
14644                         if ($endpage > $startpage) {
14645                             if (($this->rtl) AND ($this->pagedim[$endpage]['orm'] != $this->pagedim[$startpage]['orm'])) {
14646                                 $this->x += ($this->pagedim[$endpage]['orm'] - $this->pagedim[$startpage]['orm']);
14647                             } elseif ((!$this->rtl) AND ($this->pagedim[$endpage]['olm'] != $this->pagedim[$startpage]['olm'])) {
14648                                 $this->x += ($this->pagedim[$endpage]['olm'] - $this->pagedim[$startpage]['olm']);
14649                             }
14650                         }
14651                     }
14652                     if (!$in_table_head) {
14653                         // we are not inside a thead section
14654                         if (isset($parent['cellpadding'])) {
14655                             $this->cMargin = $this->oldcMargin;
14656                         }
14657                         $this->lasth = $this->FontSize * $this->cell_height_ratio;
14658                         if (isset($this->theadMargins['top'])) {
14659                             // restore top margin
14660                             $this->tMargin = $this->theadMargins['top'];
14661                             $this->pagedim[$this->page]['tm'] = $this->tMargin;
14662                         }
14663                         // reset table header
14664                         $this->thead = '';
14665                         $this->theadMargins = array();
14666                     }
14667                     break;
14668                 }
14669                 case 'a': {
14670                     $this->HREF = '';
14671                     break;
14672                 }
14673                 case 'sup': {
14674                     $this->SetXY($this->GetX(), $this->GetY() + ((0.7 * $parent['fontsize']) / $this->k));
14675                     break;
14676                 }
14677                 case 'sub': {
14678                     $this->SetXY($this->GetX(), $this->GetY() - ((0.3 * $parent['fontsize'])/$this->k));
14679                     break;
14680                 }
14681                 case 'div': {
14682                     $this->addHTMLVertSpace(1, $cell, '', $firstorlast, $tag['value'], true);
14683                     break;
14684                 }
14685                 case 'blockquote': {
14686                     if ($this->rtl) {
14687                         $this->rMargin -= $this->listindent;
14688                     } else {
14689                         $this->lMargin -= $this->listindent;
14690                     }
14691                     $this->addHTMLVertSpace(2, $cell, '', $firstorlast, $tag['value'], true);
14692                     break;
14693                 }
14694                 case 'p': {
14695                     $this->addHTMLVertSpace(2, $cell, '', $firstorlast, $tag['value'], true);
14696                     break;
14697                 }
14698                 case 'pre': {
14699                     $this->addHTMLVertSpace(1, $cell, '', $firstorlast, $tag['value'], true);
14700                     $this->premode = false;
14701                     break;
14702                 }
14703                 case 'dl': {
14704                     --$this->listnum;
14705                     if ($this->listnum <= 0) {
14706                         $this->listnum = 0;
14707                         $this->addHTMLVertSpace(2, $cell, '', $firstorlast, $tag['value'], true);
14708                     }
14709                     break;
14710                 }
14711                 case 'dt': {
14712                     $this->lispacer = '';
14713                     $this->addHTMLVertSpace(0, $cell, '', $firstorlast, $tag['value'], true);
14714                     break;
14715                 }
14716                 case 'dd': {
14717                     $this->lispacer = '';
14718                     if ($this->rtl) {
14719                         $this->rMargin -= $this->listindent;
14720                     } else {
14721                         $this->lMargin -= $this->listindent;
14722                     }
14723                     $this->addHTMLVertSpace(0, $cell, '', $firstorlast, $tag['value'], true);
14724                     break;
14725                 }
14726                 case 'ul':
14727                 case 'ol': {
14728                     --$this->listnum;
14729                     $this->lispacer = '';
14730                     if ($this->rtl) {
14731                         $this->rMargin -= $this->listindent;
14732                     } else {
14733                         $this->lMargin -= $this->listindent;
14734                     }
14735                     if ($this->listnum <= 0) {
14736                         $this->listnum = 0;
14737                         $this->addHTMLVertSpace(2, $cell, '', $firstorlast, $tag['value'], true);
14738                     }
14739                     $this->lasth = $this->FontSize * $this->cell_height_ratio;
14740                     break;
14741                 }
14742                 case 'li': {
14743                     $this->lispacer = '';
14744                     $this->addHTMLVertSpace(0, $cell, '', $firstorlast, $tag['value'], true);
14745                     break;
14746                 }
14747                 case 'h1': 
14748                 case 'h2': 
14749                 case 'h3': 
14750                 case 'h4': 
14751                 case 'h5': 
14752                 case 'h6': {
14753                     $this->addHTMLVertSpace(1, $cell, ($parent['fontsize'] * 1.5) / $this->k, $firstorlast, $tag['value'], true);
14754                     break;
14755                 }
14756                 // Form fields (since 4.8.000 - 2009-09-07)
14757                 case 'form': {
14758                     $this->form_action = '';
14759                     $this->form_enctype = 'application/x-www-form-urlencoded';
14760                     break;
14761                 }
14762                 default : {
14763                     break;
14764                 }
14765             }
14766             $this->tmprtl = false;
14767         }
14768         
14779         protected function addHTMLVertSpace($n, $cell=false, $h='', $firstorlast=false, $tag='', $closing=false) {
14780             if ($firstorlast) {
14781                 $this->Ln(0, $cell);
14782                 $this->htmlvspace = 0;
14783                 return;
14784             }
14785             if (isset($this->tagvspaces[$tag][intval($closing)]['n'])) {
14786                 $n = $this->tagvspaces[$tag][intval($closing)]['n'];
14787             }
14788             if (isset($this->tagvspaces[$tag][intval($closing)]['h'])) {
14789                 $h = $this->tagvspaces[$tag][intval($closing)]['h'];
14790             }
14791             if (is_string($h)) {
14792                 $vsize = $n * $this->lasth;
14793             } else {
14794                 $vsize = $n * $h;
14795             }
14796             if ($vsize > $this->htmlvspace) {
14797                 $this->Ln(($vsize - $this->htmlvspace), $cell);
14798                 $this->htmlvspace = $vsize;
14799             }
14800         }
14801         
14808         public function setLIsymbol($symbol='!') {
14809             $symbol = strtolower($symbol);
14810             switch ($symbol) {
14811                 case '!' :
14812                 case '#' :
14813                 case 'disc' :
14814                 case 'disc' :
14815                 case 'circle' :
14816                 case 'square' :
14817                 case '1':
14818                 case 'decimal':
14819                 case 'decimal-leading-zero':
14820                 case 'i':
14821                 case 'lower-roman':
14822                 case 'I':
14823                 case 'upper-roman':
14824                 case 'a':
14825                 case 'lower-alpha':
14826                 case 'lower-latin':
14827                 case 'A':
14828                 case 'upper-alpha':
14829                 case 'upper-latin':
14830                 case 'lower-greek': {
14831                     $this->lisymbol = $symbol;
14832                     break;
14833                 }
14834                 default : {
14835                     $this->lisymbol = '';
14836                 }
14837             }
14838         }
14839         
14848         public function SetBooklet($booklet=true, $inner=-1, $outer=-1) {
14849             $this->booklet = $booklet;
14850             if ($inner >= 0) {
14851                 $this->lMargin = $inner;
14852             }
14853             if ($outer >= 0) {
14854                 $this->rMargin = $outer;
14855             }
14856         }
14857         
14864         protected function swapMargins($reverse=true) {
14865             if ($reverse) {
14866                 // swap left and right margins
14867                 $mtemp = $this->original_lMargin;
14868                 $this->original_lMargin = $this->original_rMargin;
14869                 $this->original_rMargin = $mtemp;
14870                 $deltam = $this->original_lMargin - $this->original_rMargin;
14871                 $this->lMargin += $deltam;
14872                 $this->rMargin -= $deltam;
14873             }
14874         }
14875 
14888         public function setHtmlVSpace($tagvs) {
14889             $this->tagvspaces = $tagvs;
14890         }
14891 
14898         public function setListIndentWidth($width) {
14899             return $this->customlistindent = floatval($width);
14900         }
14901 
14908         public function setOpenCell($isopen) {
14909             $this->opencell = $isopen;
14910         }
14911 
14919         public function setHtmlLinksStyle($color=array(0,0,255), $fontstyle='U') {
14920             $this->htmlLinkColorArray = $color;
14921             $this->htmlLinkFontStyle = $fontstyle;
14922         }
14923 
14934         public function getHTMLUnitToUnits($htmlval, $refsize=1, $defaultunit='px', $points=false) {
14935             $supportedunits = array('%', 'em', 'ex', 'px', 'in', 'cm', 'mm', 'pc', 'pt');
14936             $retval = 0;
14937             $value = 0;
14938             $unit = 'px';
14939             $k = $this->k;
14940             if ($points) {
14941                 $k = 1;
14942             }
14943             if (in_array($defaultunit, $supportedunits)) {
14944                 $unit = $defaultunit;
14945             }
14946             if (is_numeric($htmlval)) {
14947                 $value = floatval($htmlval);
14948             } elseif (preg_match('/([0-9\.]+)/', $htmlval, $mnum)) {
14949                 $value = floatval($mnum[1]);
14950                 if (preg_match('/([a-z%]+)/', $htmlval, $munit)) {
14951                     if (in_array($munit[1], $supportedunits)) {
14952                         $unit = $munit[1];
14953                     }
14954                 }
14955             }
14956             switch ($unit) {
14957                 // percentage
14958                 case '%': {
14959                     $retval = (($value * $refsize) / 100);
14960                     break;
14961                 }
14962                 // relative-size
14963                 case 'em': {
14964                     $retval = ($value * $refsize);
14965                     break;
14966                 }
14967                 case 'ex': {
14968                     $retval = $value * ($refsize / 2);
14969                     break;
14970                 }
14971                 // absolute-size
14972                 case 'in': {
14973                     $retval = ($value * $this->dpi) / $k;
14974                     break;
14975                 }
14976                 case 'cm': {
14977                     $retval = ($value / 2.54 * $this->dpi) / $k;
14978                     break;
14979                 }
14980                 case 'mm': {
14981                     $retval = ($value / 25.4 * $this->dpi) / $k;
14982                     break;
14983                 }
14984                 case 'pc': {
14985                     // one pica is 12 points
14986                     $retval = ($value * 12) / $k;
14987                     break;
14988                 }
14989                 case 'pt': {
14990                     $retval = $value / $k;
14991                     break;
14992                 }
14993                 case 'px': {
14994                     $retval = $this->pixelsToUnits($value);
14995                     break;
14996                 }
14997             }
14998             return $retval;
14999         }
15000 
15008         public function intToRoman($number) {
15009             $roman = '';
15010             while ($number >= 1000) {
15011                 $roman .= 'M';
15012                 $number -= 1000;
15013             }
15014             while ($number >= 900) {
15015                 $roman .= 'CM';
15016                 $number -= 900;
15017             }
15018             while ($number >= 500) {
15019                 $roman .= 'D';
15020                 $number -= 500;
15021             }
15022             while ($number >= 400) {
15023                 $roman .= 'CD';
15024                 $number -= 400;
15025             }
15026             while ($number >= 100) {
15027                 $roman .= 'C';
15028                 $number -= 100;
15029             }
15030             while ($number >= 90) {
15031             $roman .= 'XC';
15032             $number -= 90;
15033             }
15034             while ($number >= 50) {
15035                 $roman .= 'L';
15036                 $number -= 50;
15037             }
15038             while ($number >= 40) {
15039                 $roman .= 'XL';
15040                 $number -= 40;
15041             }
15042             while ($number >= 10) {
15043             $roman .= 'X';
15044             $number -= 10;
15045             }
15046             while ($number >= 9) {
15047                 $roman .= 'IX';
15048                 $number -= 9;
15049             }
15050             while ($number >= 5) {
15051                 $roman .= 'V';
15052                 $number -= 5;
15053             }
15054             while ($number >= 4) {
15055             $roman .= 'IV';
15056             $number -= 4;
15057             }
15058             while ($number >= 1) {
15059                 $roman .= 'I';
15060                 --$number;
15061             }
15062             return $roman;
15063         }
15064 
15073         protected function putHtmlListBullet($listdepth, $listtype='', $size=10) {
15074             $size /= $this->k;
15075             $fill = '';
15076             $color = $this->fgcolor;
15077             $width = 0;
15078             $textitem = '';
15079             $tmpx = $this->x;       
15080             $lspace = $this->GetStringWidth('  ');
15081             if ($listtype == '!') {
15082                 // set default list type for unordered list
15083                 $deftypes = array('disc', 'circle', 'square');
15084                 $listtype = $deftypes[($listdepth - 1) % 3];
15085             } elseif ($listtype == '#') {
15086                 // set default list type for ordered list
15087                 $listtype = 'decimal';
15088             }
15089             switch ($listtype) {
15090                 // unordered types
15091                 case 'none': {
15092                     break;
15093                 }
15094                 case 'disc': {
15095                     $fill = 'F';
15096                 }
15097                 case 'circle': {
15098                     $fill .= 'D';
15099                     $r = $size / 6;
15100                     $lspace += (2 * $r);
15101                     if ($this->rtl) {
15102                         $this->x = $this->w - $this->x - $lspace;
15103                     } else {
15104                         $this->x -= $lspace;
15105                     }
15106                     $this->Circle(($this->x + $r), ($this->y + ($this->lasth / 2)), $r, 0, 360, $fill, array('color'=>$color), $color, 8);
15107                     break;
15108                 }
15109                 case 'square': {
15110                     $l = $size / 3;
15111                     $lspace += $l;
15112                     if ($this->rtl) {
15113                         $this->x = $this->w - $this->x - $lspace;
15114                     } else {
15115                         $this->x -= $lspace;
15116                     }
15117                     $this->Rect($this->x, ($this->y + (($this->lasth - $l)/ 2)), $l, $l, 'F', array(), $color);
15118                     break;
15119                 }
15120                 // ordered types
15121 
15122                 // $this->listcount[$this->listnum];
15123                 // $textitem
15124                 case '1':
15125                 case 'decimal': {
15126                     $textitem = $this->listcount[$this->listnum];
15127                     break;
15128                 }
15129                 case 'decimal-leading-zero': {
15130                     $textitem = sprintf("%02d", $this->listcount[$this->listnum]);
15131                     break;
15132                 }
15133                 case 'i':
15134                 case 'lower-roman': {
15135                     $textitem = strtolower($this->intToRoman($this->listcount[$this->listnum]));
15136                     break;
15137                 }
15138                 case 'I':
15139                 case 'upper-roman': {
15140                     $textitem = $this->intToRoman($this->listcount[$this->listnum]);
15141                     break;
15142                 }
15143                 case 'a':
15144                 case 'lower-alpha':
15145                 case 'lower-latin': {
15146                     $textitem = chr(97 + $this->listcount[$this->listnum] - 1);
15147                     break;
15148                 }
15149                 case 'A':
15150                 case 'upper-alpha':
15151                 case 'upper-latin': {
15152                     $textitem = chr(65 + $this->listcount[$this->listnum] - 1);
15153                     break;
15154                 }
15155                 case 'lower-greek': {
15156                     $textitem = $this->unichr(945 + $this->listcount[$this->listnum] - 1);
15157                     break;
15158                 }
15159                 /*
15160                 // Types to be implemented (special handling)
15161                 case 'hebrew': {
15162                     break;
15163                 }
15164                 case 'armenian': {
15165                     break;
15166                 }
15167                 case 'georgian': {
15168                     break;
15169                 }
15170                 case 'cjk-ideographic': {
15171                     break;
15172                 }
15173                 case 'hiragana': {
15174                     break;
15175                 }
15176                 case 'katakana': {
15177                     break;
15178                 }
15179                 case 'hiragana-iroha': {
15180                     break;
15181                 }
15182                 case 'katakana-iroha': {
15183                     break;
15184                 }
15185                 */
15186                 default: {
15187                     $textitem = $this->listcount[$this->listnum];
15188                 }
15189             }
15190             if (!$this->empty_string($textitem)) {
15191                 // print ordered item
15192                 if ($this->rtl) {
15193                     $textitem = '.'.$textitem;
15194                 } else {
15195                     $textitem = $textitem.'.';
15196                 }
15197                 $lspace += $this->GetStringWidth($textitem);
15198                 if ($this->rtl) {
15199                     $this->x += $lspace;
15200                 } else {
15201                     $this->x -= $lspace;
15202                 }
15203                 $this->Write($this->lasth, $textitem, '', false, '', false, 0, false);
15204             }
15205             $this->x = $tmpx;
15206             $this->lispacer = '';
15207         }
15208 
15215         protected function getGraphicVars() {
15216             $grapvars = array(
15217                 'FontFamily' => $this->FontFamily,
15218                 'FontStyle' => $this->FontStyle,
15219                 'FontSizePt' => $this->FontSizePt,
15220                 'rMargin' => $this->rMargin,
15221                 'lMargin' => $this->lMargin,
15222                 'cMargin' => $this->cMargin,
15223                 'LineWidth' => $this->LineWidth,
15224                 'linestyleWidth' => $this->linestyleWidth,
15225                 'linestyleCap' => $this->linestyleCap,
15226                 'linestyleJoin' => $this->linestyleJoin,
15227                 'linestyleDash' => $this->linestyleDash,
15228                 'DrawColor' => $this->DrawColor,
15229                 'FillColor' => $this->FillColor,
15230                 'TextColor' => $this->TextColor,
15231                 'ColorFlag' => $this->ColorFlag,
15232                 'bgcolor' => $this->bgcolor,
15233                 'fgcolor' => $this->fgcolor,
15234                 'htmlvspace' => $this->htmlvspace,
15235                 'lasth' => $this->lasth
15236                 );
15237             return $grapvars;
15238         }
15239 
15246         protected function setGraphicVars($gvars) {
15247             $this->FontFamily = $gvars['FontFamily'];
15248             $this->FontStyle = $gvars['FontStyle'];
15249             $this->FontSizePt = $gvars['FontSizePt'];
15250             $this->rMargin = $gvars['rMargin'];
15251             $this->lMargin = $gvars['lMargin'];
15252             $this->cMargin = $gvars['cMargin'];
15253             $this->LineWidth = $gvars['LineWidth'];
15254             $this->linestyleWidth = $gvars['linestyleWidth'];
15255             $this->linestyleCap = $gvars['linestyleCap'];
15256             $this->linestyleJoin = $gvars['linestyleJoin'];
15257             $this->linestyleDash = $gvars['linestyleDash'];
15258             $this->DrawColor = $gvars['DrawColor'];
15259             $this->FillColor = $gvars['FillColor'];
15260             $this->TextColor = $gvars['TextColor'];
15261             $this->ColorFlag = $gvars['ColorFlag'];
15262             $this->bgcolor = $gvars['bgcolor'];
15263             $this->fgcolor = $gvars['fgcolor'];
15264             $this->htmlvspace = $gvars['htmlvspace'];
15265             //$this->lasth = $gvars['lasth'];
15266             $this->_out(''.$this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor.' '.$this->FillColor.'');
15267             if (!$this->empty_string($this->FontFamily)) {
15268                 $this->SetFont($this->FontFamily, $this->FontStyle, $this->FontSizePt);
15269             }
15270         }
15271 
15279         protected function getObjFilename($name) {
15280             return tempnam(K_PATH_CACHE, $name.'_');
15281         }
15282 
15291         protected function writeDiskCache($filename, $data, $append=false) {
15292             if ($append) {
15293                 $fmode = 'ab+';
15294             } else {
15295                 $fmode = 'wb+';
15296             }
15297             $f = @fopen($filename, $fmode);
15298             if (!$f) {
15299                 $this->Error('Unable to write cache file: '.$filename);
15300             } else {
15301                 fwrite($f, $data);
15302                 fclose($f);
15303             }
15304             // update file lenght (needed for transactions)
15305             if (!isset($this->cache_file_lenght['_'.$filename])) {
15306                 $this->cache_file_lenght['_'.$filename] = strlen($data);
15307             } else {
15308                 $this->cache_file_lenght['_'.$filename] += strlen($data);
15309             }
15310         }
15311 
15319         protected function readDiskCache($filename) {
15320             return file_get_contents($filename);
15321         }
15322 
15329         protected function setBuffer($data) {
15330             $this->bufferlen += strlen($data);
15331             if ($this->diskcache) {
15332                 if (!isset($this->buffer) OR $this->empty_string($this->buffer)) {
15333                     $this->buffer = $this->getObjFilename('buffer');
15334                 }
15335                 $this->writeDiskCache($this->buffer, $data, true);
15336             } else {
15337                 $this->buffer .= $data;
15338             }
15339         }
15340 
15347         protected function getBuffer() {
15348             if ($this->diskcache) {
15349                 return $this->readDiskCache($this->buffer);
15350             } else {
15351                 return $this->buffer;
15352             }
15353         }
15354 
15363         protected function setPageBuffer($page, $data, $append=false) {
15364             if ($this->diskcache) {
15365                 if (!isset($this->pages[$page])) {
15366                     $this->pages[$page] = $this->getObjFilename('page'.$page);
15367                 }
15368                 $this->writeDiskCache($this->pages[$page], $data, $append);
15369             } else {
15370                 if ($append) {
15371                     $this->pages[$page] .= $data;
15372                 } else {
15373                     $this->pages[$page] = $data;
15374                 }
15375             }
15376             if ($append AND isset($this->pagelen[$page])) {
15377                 $this->pagelen[$page] += strlen($data);
15378             } else {
15379                 $this->pagelen[$page] = strlen($data);
15380             }
15381         }
15382 
15390         protected function getPageBuffer($page) {
15391             if ($this->diskcache) {
15392                 return $this->readDiskCache($this->pages[$page]);
15393             } elseif (isset($this->pages[$page])) {
15394                 return $this->pages[$page];
15395             }
15396             return false;
15397         }
15398 
15406         protected function setImageBuffer($image, $data) {
15407             if ($this->diskcache) {
15408                 if (!isset($this->images[$image])) {
15409                     $this->images[$image] = $this->getObjFilename('image'.$image);
15410                 }
15411                 $this->writeDiskCache($this->images[$image], serialize($data));
15412             } else {
15413                 $this->images[$image] = $data;
15414             }
15415             if (!in_array($image, $this->imagekeys)) {
15416                 $this->imagekeys[] = $image;
15417             }
15418             ++$this->numimages;
15419         }
15420 
15429         protected function setImageSubBuffer($image, $key, $data) {
15430             if (!isset($this->images[$image])) {
15431                 $this->setImageBuffer($image, array());
15432             }
15433             if ($this->diskcache) {
15434                 $tmpimg = $this->getImageBuffer($image);
15435                 $tmpimg[$key] = $data;
15436                 $this->writeDiskCache($this->images[$image], serialize($tmpimg));
15437             } else {
15438                 $this->images[$image][$key] = $data;
15439             }
15440         }
15441 
15449         protected function getImageBuffer($image) {
15450             if ($this->diskcache AND isset($this->images[$image])) {
15451                 return unserialize($this->readDiskCache($this->images[$image]));
15452             } elseif (isset($this->images[$image])) {
15453                 return $this->images[$image];
15454             }
15455             return false;
15456         }
15457 
15465         protected function setFontBuffer($font, $data) {
15466             if ($this->diskcache) {
15467                 if (!isset($this->fonts[$font])) {
15468                     $this->fonts[$font] = $this->getObjFilename('font');
15469                 }
15470                 $this->writeDiskCache($this->fonts[$font], serialize($data));
15471             } else {
15472                 $this->fonts[$font] = $data;
15473             }
15474             if (!in_array($font, $this->fontkeys)) {
15475                 $this->fontkeys[] = $font;
15476             }
15477         }
15478 
15487         protected function setFontSubBuffer($font, $key, $data) {
15488             if (!isset($this->fonts[$font])) {
15489                 $this->setFontBuffer($font, array());
15490             }
15491             if ($this->diskcache) {
15492                 $tmpfont = $this->getFontBuffer($font);
15493                 $tmpfont[$key] = $data;
15494                 $this->writeDiskCache($this->fonts[$font], serialize($tmpfont));
15495             } else {
15496                 $this->fonts[$font][$key] = $data;
15497             }
15498         }
15499 
15507         protected function getFontBuffer($font) {
15508             if ($this->diskcache AND isset($this->fonts[$font])) {
15509                 return unserialize($this->readDiskCache($this->fonts[$font]));
15510             } elseif (isset($this->fonts[$font])) {
15511                 return $this->fonts[$font];
15512             }
15513             return false;
15514         }
15515 
15524         public function movePage($frompage, $topage) {
15525             if (($frompage > $this->numpages) OR ($frompage <= $topage)) {
15526                 return false;
15527             }
15528             if ($frompage == $this->page) {
15529                 // close the page before moving it
15530                 $this->endPage();
15531             }
15532             // move all page-related states
15533             $tmppage = $this->pages[$frompage];
15534             $tmppagedim = $this->pagedim[$frompage];
15535             $tmppagelen = $this->pagelen[$frompage];
15536             $tmpintmrk = $this->intmrk[$frompage];
15537             if (isset($this->footerpos[$frompage])) {
15538                 $tmpfooterpos = $this->footerpos[$frompage];
15539             }
15540             if (isset($this->footerlen[$frompage])) {
15541                 $tmpfooterlen = $this->footerlen[$frompage];
15542             }
15543             if (isset($this->transfmrk[$frompage])) {
15544                 $tmptransfmrk = $this->transfmrk[$frompage];
15545             }
15546             if (isset($this->PageAnnots[$frompage])) {
15547                 $tmpannots = $this->PageAnnots[$frompage];
15548             }
15549             if (isset($this->newpagegroup[$frompage])) {
15550                 $tmpnewpagegroup = $this->newpagegroup[$frompage];
15551             }
15552             for ($i = $frompage; $i > $topage; --$i) {
15553                 $j = $i - 1;
15554                 // shift pages down
15555                 $this->pages[$i] = $this->pages[$j];
15556                 $this->pagedim[$i] = $this->pagedim[$j];
15557                 $this->pagelen[$i] = $this->pagelen[$j];
15558                 $this->intmrk[$i] = $this->intmrk[$j];
15559                 if (isset($this->footerpos[$j])) {
15560                     $this->footerpos[$i] = $this->footerpos[$j];
15561                 } elseif (isset($this->footerpos[$i])) {
15562                     unset($this->footerpos[$i]);
15563                 }
15564                 if (isset($this->footerlen[$j])) {
15565                     $this->footerlen[$i] = $this->footerlen[$j];
15566                 } elseif (isset($this->footerlen[$i])) {
15567                     unset($this->footerlen[$i]);
15568                 }
15569                 if (isset($this->transfmrk[$j])) {
15570                     $this->transfmrk[$i] = $this->transfmrk[$j];
15571                 } elseif (isset($this->transfmrk[$i])) {
15572                     unset($this->transfmrk[$i]);
15573                 }
15574                 if (isset($this->PageAnnots[$j])) {
15575                     $this->PageAnnots[$i] = $this->PageAnnots[$j];
15576                 } elseif (isset($this->PageAnnots[$i])) {
15577                     unset($this->PageAnnots[$i]);
15578                 }
15579                 if (isset($this->newpagegroup[$j])) {
15580                     $this->newpagegroup[$i] = $this->newpagegroup[$j];
15581                 } elseif (isset($this->newpagegroup[$i])) {
15582                     unset($this->newpagegroup[$i]);
15583                 }
15584             }
15585             $this->pages[$topage] = $tmppage;
15586             $this->pagedim[$topage] = $tmppagedim;
15587             $this->pagelen[$topage] = $tmppagelen;
15588             $this->intmrk[$topage] = $tmpintmrk;
15589             if (isset($tmpfooterpos)) {
15590                 $this->footerpos[$topage] = $tmpfooterpos;
15591             } elseif (isset($this->footerpos[$topage])) {
15592                 unset($this->footerpos[$topage]);
15593             }
15594             if (isset($tmpfooterlen)) {
15595                 $this->footerlen[$topage] = $tmpfooterlen;
15596             } elseif (isset($this->footerlen[$topage])) {
15597                 unset($this->footerlen[$topage]);
15598             }
15599             if (isset($tmptransfmrk)) {
15600                 $this->transfmrk[$topage] = $tmptransfmrk;
15601             } elseif (isset($this->transfmrk[$topage])) {
15602                 unset($this->transfmrk[$topage]);
15603             }
15604             if (isset($tmpannots)) {
15605                 $this->PageAnnots[$topage] = $tmpannots;
15606             } elseif (isset($this->PageAnnots[$topage])) {
15607                 unset($this->PageAnnots[$topage]);
15608             }
15609             if (isset($tmpnewpagegroup)) {
15610                 $this->newpagegroup[$topage] = $tmpnewpagegroup;
15611             } elseif (isset($this->newpagegroup[$topage])) {
15612                 unset($this->newpagegroup[$topage]);
15613             }
15614             // adjust outlines
15615             $tmpoutlines = $this->outlines;
15616             foreach ($tmpoutlines as $key => $outline) {
15617                 if (($outline['p'] >= $topage) AND ($outline['p'] < $frompage)) {
15618                     $this->outlines[$key]['p'] = $outline['p'] + 1;
15619                 } elseif ($outline['p'] == $frompage) {
15620                     $this->outlines[$key]['p'] = $topage;
15621                 }
15622             }
15623             // adjust links
15624             $tmplinks = $this->links;
15625             foreach ($tmplinks as $key => $link) {
15626                 if (($link[0] >= $topage) AND ($link[0] < $frompage)) {
15627                     $this->links[$key][0] = $link[0] + 1;
15628                 } elseif ($link[0] == $frompage) {
15629                     $this->links[$key][0] = $topage;
15630                 }
15631             }
15632             // adjust javascript
15633             $tmpjavascript = $this->javascript;
15634             global $jfrompage, $jtopage;
15635             $jfrompage = $frompage;
15636             $jtopage = $topage;
15637             $this->javascript = preg_replace_callback('/this\.addField\(\'([^\']*)\',\'([^\']*)\',([0-9]+)/',
15638                 create_function('$matches', 'global $jfrompage, $jtopage;
15639                 $pagenum = intval($matches[3]) + 1;
15640                 if (($pagenum >= $jtopage) AND ($pagenum < $jfrompage)) {
15641                     $newpage = ($pagenum + 1);
15642                 } elseif ($pagenum == $jfrompage) {
15643                     $newpage = $jtopage;
15644                 } else {
15645                     $newpage = $pagenum;
15646                 }
15647                 --$newpage;
15648                 return "this.addField(\'".$matches[1]."\',\'".$matches[2]."\',".$newpage."";'), $tmpjavascript);
15649             
15650             $this->lastPage(true);
15651             return true;
15652         }
15653 
15661         public function deletePage($page) {
15662             if ($page > $this->numpages) {
15663                 return false;
15664             }
15665             
15666             unset($this->pages[$page]);
15667             unset($this->pagedim[$page]);
15668             unset($this->pagelen[$page]);
15669             unset($this->intmrk[$page]);
15670             if (isset($this->footerpos[$page])) {
15671                 unset($this->footerpos[$page]);
15672             }
15673             if (isset($this->footerlen[$page])) {
15674                 unset($this->footerlen[$page]);
15675             }
15676             if (isset($this->transfmrk[$page])) {
15677                 unset($this->transfmrk[$page]);
15678             }
15679             if (isset($this->PageAnnots[$page])) {
15680                 unset($this->PageAnnots[$page]);
15681             }
15682             if (isset($this->newpagegroup[$page])) {
15683                 unset($this->newpagegroup[$page]);
15684             }
15685             if (isset($this->pageopen[$page])) {
15686                 unset($this->pageopen[$page]);
15687             }
15688             
15689             for ($i = $page; $i < $this->numpages; ++$i) {
15690                 $j = $i + 1;
15691                 
15692                 $this->pages[$i] = $this->pages[$j];
15693                 $this->pagedim[$i] = $this->pagedim[$j];
15694                 $this->pagelen[$i] = $this->pagelen[$j];
15695                 $this->intmrk[$i] = $this->intmrk[$j];
15696                 if (isset($this->footerpos[$j])) {
15697                     $this->footerpos[$i] = $this->footerpos[$j];
15698                 } elseif (isset($this->footerpos[$i])) {
15699                     unset($this->footerpos[$i]);
15700                 }
15701                 if (isset($this->footerlen[$j])) {
15702                     $this->footerlen[$i] = $this->footerlen[$j];
15703                 } elseif (isset($this->footerlen[$i])) {
15704                     unset($this->footerlen[$i]);
15705                 }
15706                 if (isset($this->transfmrk[$j])) {
15707                     $this->transfmrk[$i] = $this->transfmrk[$j];
15708                 } elseif (isset($this->transfmrk[$i])) {
15709                     unset($this->transfmrk[$i]);
15710                 }
15711                 if (isset($this->PageAnnots[$j])) {
15712                     $this->PageAnnots[$i] = $this->PageAnnots[$j];
15713                 } elseif (isset($this->PageAnnots[$i])) {
15714                     unset($this->PageAnnots[$i]);
15715                 }
15716                 if (isset($this->newpagegroup[$j])) {
15717                     $this->newpagegroup[$i] = $this->newpagegroup[$j];
15718                 } elseif (isset($this->newpagegroup[$i])) {
15719                     unset($this->newpagegroup[$i]);
15720                 }
15721                 if (isset($this->pageopen[$j])) {
15722                     $this->pageopen[$i] = $this->pageopen[$j];
15723                 } elseif (isset($this->pageopen[$i])) {
15724                     unset($this->pageopen[$i]);
15725                 }
15726             }
15727             
15728             unset($this->pages[$this->numpages]);
15729             unset($this->pagedim[$this->numpages]);
15730             unset($this->pagelen[$this->numpages]);
15731             unset($this->intmrk[$this->numpages]);
15732             if (isset($this->footerpos[$this->numpages])) {
15733                 unset($this->footerpos[$this->numpages]);
15734             }
15735             if (isset($this->footerlen[$this->numpages])) {
15736                 unset($this->footerlen[$this->numpages]);
15737             }
15738             if (isset($this->transfmrk[$this->numpages])) {
15739                 unset($this->transfmrk[$this->numpages]);
15740             }
15741             if (isset($this->PageAnnots[$this->numpages])) {
15742                 unset($this->PageAnnots[$this->numpages]);
15743             }
15744             if (isset($this->newpagegroup[$this->numpages])) {
15745                 unset($this->newpagegroup[$this->numpages]);
15746             }
15747             if (isset($this->pageopen[$this->numpages])) {
15748                 unset($this->pageopen[$this->numpages]);
15749             }
15750             --$this->numpages;
15751             $this->page = $this->numpages;
15752             
15753             $tmpoutlines = $this->outlines;
15754             foreach ($tmpoutlines as $key => $outline) {
15755                 if ($outline['p'] > $page) {
15756                     $this->outlines[$key]['p'] = $outline['p'] - 1;
15757                 } elseif ($outline['p'] == $page) {
15758                     unset($this->outlines[$key]);
15759                 }
15760             }
15761             
15762             $tmplinks = $this->links;
15763             foreach ($tmplinks as $key => $link) {
15764                 if ($link[0] > $page) {
15765                     $this->links[$key][0] = $link[0] - 1;
15766                 } elseif ($link[0] == $page) {
15767                     unset($this->links[$key]);
15768                 }
15769             }
15770             
15771             $tmpjavascript = $this->javascript;
15772             global $jpage;
15773             $jpage = $page;
15774             $this->javascript = preg_replace_callback('/this\.addField\(\'([^\']*)\',\'([^\']*)\',([0-9]+)/',
15775                 create_function('$matches', 'global $jpage;
15776                 $pagenum = intval($matches[3]) + 1;
15777                 if ($pagenum >= $jpage) {
15778                     $newpage = ($pagenum - 1);
15779                 } elseif ($pagenum == $jpage) {
15780                     $newpage = 1;
15781                 } else {
15782                     $newpage = $pagenum;
15783                 }
15784                 --$newpage;
15785                 return "this.addField(\'".$matches[1]."\',\'".$matches[2]."\',".$newpage."";'), $tmpjavascript);
15786             
15787             $this->lastPage(true);
15788             return true;
15789         }
15790 
15801         public function addTOC($page='', $numbersfont='', $filler='.') {
15802             $fontsize = $this->FontSizePt;
15803             $fontfamily = $this->FontFamily;
15804             $fontstyle = $this->FontStyle;
15805             $w = $this->w - $this->lMargin - $this->rMargin;
15806             $spacer = $this->GetStringWidth(' ') * 4;
15807             $page_first = $this->getPage();
15808             $lmargin = $this->lMargin;
15809             $rmargin = $this->rMargin;
15810             $x_start = $this->GetX();
15811             if ($this->empty_string($numbersfont)) {
15812                 $numbersfont = $this->default_monospaced_font;
15813             }
15814             if ($this->empty_string($filler)) {
15815                 $filler = ' ';
15816             }
15817             if ($this->empty_string($page)) {
15818                 $gap = ' ';
15819             } else {
15820                 $gap = '';
15821             }
15822             foreach ($this->outlines as $key => $outline) {
15823                 if ($this->rtl) {
15824                     $aligntext = 'R';
15825                     $alignnum = 'L';
15826                 } else {
15827                     $aligntext = 'L';
15828                     $alignnum = 'R';
15829                 }
15830                 if ($outline['l'] == 0) {
15831                     $this->SetFont($fontfamily, $fontstyle.'B', $fontsize);
15832                 } else {
15833                     $this->SetFont($fontfamily, $fontstyle, $fontsize - $outline['l']);
15834                 }
15835                 $indent = ($spacer * $outline['l']);
15836                 if ($this->rtl) {
15837                     $this->rMargin += $indent;
15838                     $this->x -= $indent;
15839                 } else {
15840                     $this->lMargin += $indent;
15841                     $this->x += $indent;
15842                 }
15843                 $link = $this->AddLink();
15844                 $this->SetLink($link, 0, $outline['p']);
15845                 
15846                 $this->Write(0, $outline['t'], $link, 0, $aligntext, false, 0, false, false, 0);
15847                 $this->SetFont($numbersfont, $fontstyle, $fontsize);
15848                 if ($this->empty_string($page)) {
15849                     $pagenum = $outline['p'];
15850                 } else {
15851                     
15852                     $pagenum = '{#'.($outline['p']).'}';
15853                     if (($this->CurrentFont['type'] == 'TrueTypeUnicode') OR ($this->CurrentFont['type'] == 'cidfont0')) {
15854                         $pagenum = '{'.$pagenum.'}';
15855                     }
15856                 }
15857                 $numwidth = $this->GetStringWidth($pagenum);
15858                 if ($this->rtl) {
15859                     $tw = $this->x - $this->lMargin;
15860                 } else {
15861                     $tw = $this->w - $this->rMargin - $this->x;
15862                 }
15863                 $fw = $tw - $numwidth - $this->GetStringWidth(' ');
15864                 $numfills = floor($fw / $this->GetStringWidth($filler));
15865                 if ($numfills > 0) {
15866                     $rowfill = str_repeat($filler, $numfills);
15867                 } else {
15868                     $rowfill = '';
15869                 }
15870                 if ($this->rtl) {
15871                     $pagenum = $pagenum.$gap.$rowfill.' ';
15872                 } else {
15873                     $pagenum = ' '.$rowfill.$gap.$pagenum;
15874                 }
15875                 
15876                 
15877                 $this->Cell($tw, 0, $pagenum, 0, 1, $alignnum, 0, $link, 0);
15878                 $this->SetX($x_start);
15879                 $this->lMargin = $lmargin;
15880                 $this->rMargin = $rmargin;
15881             }
15882             $page_last = $this->getPage();
15883             $numpages = $page_last - $page_first + 1;
15884             if (!$this->empty_string($page)) {
15885                 for ($p = $page_first; $p <= $page_last; ++$p) {
15886                     
15887                     $temppage = $this->getPageBuffer($p);
15888                     for ($n = 1; $n <= $this->numpages; ++$n) {
15889                         
15890                         $k = '{#'.$n.'}';
15891                         $ku = '{'.$k.'}';
15892                         $alias_a = $this->_escape($k);
15893                         $alias_au = $this->_escape('{'.$k.'}');
15894                         if ($this->isunicode) {
15895                             $alias_b = $this->_escape($this->UTF8ToLatin1($k));
15896                             $alias_bu = $this->_escape($this->UTF8ToLatin1($ku));
15897                             $alias_c = $this->_escape($this->utf8StrRev($k, false, $this->tmprtl));
15898                             $alias_cu = $this->_escape($this->utf8StrRev($ku, false, $this->tmprtl));
15899                         }
15900                         if ($n >= $page) {
15901                             $np = $n + $numpages;
15902                         } else {
15903                             $np = $n;
15904                         }
15905                         $ns = $this->formatTOCPageNumber($np);
15906                         $nu = $ns;
15907                         $sdiff = strlen($k) - strlen($ns) - 1;
15908                         $sdiffu = strlen($ku) - strlen($ns) - 1;
15909                         $sfill = str_repeat($filler, $sdiff);
15910                         $sfillu = str_repeat($filler, $sdiffu);
15911                         if ($this->rtl) {
15912                             $ns = $ns.' '.$sfill;
15913                             $nu = $nu.' '.$sfillu;
15914                         } else {
15915                             $ns = $sfill.' '.$ns;
15916                             $nu = $sfillu.' '.$nu;
15917                         }
15918                         $nu = $this->UTF8ToUTF16BE($nu, false);
15919                         $temppage = str_replace($alias_au, $nu, $temppage);
15920                         if ($this->isunicode) {
15921                             $temppage = str_replace($alias_bu, $nu, $temppage);
15922                             $temppage = str_replace($alias_cu, $nu, $temppage);
15923                             $temppage = str_replace($alias_b, $ns, $temppage);
15924                             $temppage = str_replace($alias_c, $ns, $temppage);
15925                         }
15926                         $temppage = str_replace($alias_a, $ns, $temppage);
15927                     }
15928                     
15929                     $this->setPageBuffer($p, $temppage);
15930                 }
15931                 
15932                 for ($i = 0; $i < $numpages; ++$i) {
15933                     $this->movePage($page_last, $page);
15934                 }
15935             }
15936             $this->SetFont($fontfamily, $fontstyle, $fontsize);
15937         }
15938 
15944         public function startTransaction() {
15945             if (isset($this->objcopy)) {
15946                 
15947                 $this->commitTransaction();
15948             }
15949             
15950             $this->start_transaction_page = $this->page;
15951             
15952             $this->objcopy = $this->objclone($this);
15953         }
15954 
15960         public function commitTransaction() {
15961             if (isset($this->objcopy)) {
15962                 $this->objcopy->_destroy(true, true);
15963                 unset($this->objcopy);
15964             }
15965         }
15966 
15974         public function rollbackTransaction($self=false) {
15975             if (isset($this->objcopy)) {
15976                 if (isset($this->objcopy->diskcache) AND $this->objcopy->diskcache) {
15977                     
15978                     foreach ($this->objcopy->cache_file_lenght as $file => $lenght) {
15979                         $file = substr($file, 1);
15980                         $handle = fopen($file, 'r+');
15981                         ftruncate($handle, $lenght);
15982                     }
15983                 }
15984                 $this->_destroy(true, true);
15985                 if ($self) {
15986                     $objvars = get_object_vars($this->objcopy);
15987                     foreach ($objvars as $key => $value) {
15988                         $this->$key = $value;
15989                     }
15990                 }
15991                 return $this->objcopy;
15992             }
15993             return $this;
15994         }
15995 
16003         public function objclone($object) {
16004             return @clone($object);
16005         }
16006 
16014         public function empty_string($str) {
16015             return (is_null($str) OR (is_string($str) AND (strlen($str) == 0)));
16016         }
16017         
16018     } 
16019 }
16020 
16021 
16022 
16023 ?>