MIOLO20
Carregando...
Procurando...
Nenhuma entrada encontrada
class.pdf.php
Ir para a documentação deste ficheiro.
1<?php
2function __sprintf($fmt, $value)
3{
4 $r = sprintf($fmt, $value);
5 return str_replace(',', '.', $r);
6}
7
29class Cpdf
30{
31
35 var $numObj = 0;
39 var $objects = array(
40 );
49 var $fonts = array(
50 );
54 var $currentFont = '';
78 var $numFonts = 0;
82 var $currentColour = array('r' => -1, 'g' => -1, 'b' => -1);
86 var $currentStrokeColour = array('r' => -1, 'g' => -1, 'b' => -1);
95 var $stateStack = array(
96 );
104 var $numPages = 0;
108 var $stack = array(
109 );
113 var $nStack = 0;
118 var $looseObjects = array(
119 );
123 var $addLooseObjects = array(
124 );
129 var $infoObject = 0;
133 var $numImages = 0;
138 var $options = array('compression' => 1);
157 var $fontFamilies = array(
158 );
166 var $messages = '';
170 var $arc4 = '';
182 var $encrypted = 0;
190 var $callback = array(
191 );
195 var $nCallback = 0;
200 var $destinations = array(
201 );
207 var $checkpoint = '';
215
216 function Cpdf($pageSize = array(0, 0, 612, 792))
217 {
218 self::__construct($pageSize);
219 }
220
221 function __construct($pageSize = array(0, 0, 612, 792))
222 {
223 $this->newDocument($pageSize);
224
225 $this->SetFontsPath('./fonts');
226 // also initialize the font families that are known about already
227 $this->setFontFamily('init');
228 // $this->fileIdentifier = md5('xxxxxxxx'.time());
229
230 }
231
250 function o_destination($id, $action, $options = '')
251 {
252 if ($action != 'new')
253 {
254 $o = &$this->objects[$id];
255 }
256
257 switch ($action)
258 {
259 case 'new':
260 $this->objects[$id] = array
261 (
262 't' => 'destination',
263 'info' => array(
264 )
265 );
266
267 $tmp = '';
268
269 switch ($options['type'])
270 {
271 case 'XYZ':
272 case 'FitR': $tmp = ' ' . $options['p3'] . $tmp;
273
274 case 'FitH':
275 case 'FitV':
276 case 'FitBH':
277 case 'FitBV': $tmp = ' ' . $options['p1'] . ' ' . $options['p2'] . $tmp;
278
279 case 'Fit':
280 case 'FitB':
281 $tmp = $options['type'] . $tmp;
282
283 $this->objects[$id]['info']['string'] = $tmp;
284 $this->objects[$id]['info']['page'] = $options['page'];
285 }
286
287 break;
288
289 case 'out':
290 $tmp = $o['info'];
291
292 $res = "\n" . $id . " 0 obj\n" . '[' . $tmp['page'] . ' 0 R /' . $tmp['string'] . "]\nendobj\n";
293 return $res;
294 break;
295 }
296 }
297
301 function o_viewerPreferences($id, $action, $options = '')
302 {
303 if ($action != 'new')
304 {
305 $o = &$this->objects[$id];
306 }
307
308 switch ($action)
309 {
310 case 'new':
311 $this->objects[$id] = array
312 (
313 't' => 'viewerPreferences',
314 'info' => array(
315 )
316 );
317
318 break;
319
320 case 'add':
321 foreach ($options as $k => $v)
322 {
323 switch ($k)
324 {
325 case 'HideToolbar':
326 case 'HideMenubar':
327 case 'HideWindowUI':
328 case 'FitWindow':
329 case 'CenterWindow':
330 case 'NonFullScreenPageMode':
331 case 'Direction':
332 $o['info'][$k] = $v;
333
334 break;
335 }
336 }
337
338 break;
339
340 case 'out':
341 $res = "\n" . $id . " 0 obj\n" . '<< ';
342
343 foreach ($o['info'] as $k => $v)
344 {
345 $res .= "\n/" . $k . ' ' . $v;
346 }
347
348 $res .= "\n>>\n";
349 return $res;
350 break;
351 }
352 }
353
357 function o_catalog($id, $action, $options = '')
358 {
359 if ($action != 'new')
360 {
361 $o = &$this->objects[$id];
362 }
363
364 switch ($action)
365 {
366 case 'new':
367 $this->objects[$id] = array
368 (
369 't' => 'catalog',
370 'info' => array(
371 )
372 );
373
374 $this->catalogId = $id;
375 break;
376
377 case 'outlines':
378 case 'pages':
379 case 'openHere':
380 $o['info'][$action] = $options;
381
382 break;
383
384 case 'viewerPreferences':
385 if (!isset($o['info']['viewerPreferences']))
386 {
387 $this->numObj++;
388 $this->o_viewerPreferences($this->numObj, 'new');
389 $o['info']['viewerPreferences'] = $this->numObj;
390 }
391
392 $vp = $o['info']['viewerPreferences'];
393 $this->o_viewerPreferences($vp, 'add', $options);
394 break;
395
396 case 'out':
397 $res = "\n" . $id . " 0 obj\n" . '<< /Type /Catalog';
398
399 foreach ($o['info'] as $k => $v)
400 {
401 switch ($k)
402 {
403 case 'outlines':
404 $res .= "\n" . '/Outlines ' . $v . ' 0 R';
405
406 break;
407
408 case 'pages':
409 $res .= "\n" . '/Pages ' . $v . ' 0 R';
410
411 break;
412
413 case 'viewerPreferences':
414 $res .= "\n" . '/ViewerPreferences ' . $o['info']['viewerPreferences'] . ' 0 R';
415
416 break;
417
418 case 'openHere':
419 $res .= "\n" . '/OpenAction ' . $o['info']['openHere'] . ' 0 R';
420
421 break;
422 }
423 }
424
425 $res .= " >>\nendobj";
426 return $res;
427 break;
428 }
429 }
430
434 function o_pages($id, $action, $options = '')
435 {
436 if ($action != 'new')
437 {
438 $o = &$this->objects[$id];
439 }
440
441 switch ($action)
442 {
443 case 'new':
444 $this->objects[$id] = array
445 (
446 't' => 'pages',
447 'info' => array(
448 )
449 );
450
451 $this->o_catalog($this->catalogId, 'pages', $id);
452 break;
453
454 case 'page':
455 if (!is_array($options))
456 {
457 // then it will just be the id of the new page
458 $o['info']['pages'][] = $options;
459 }
460 else
461 {
462 // then it should be an array having 'id','rid','pos', where rid=the page to which this one will be placed relative
463 // and pos is either 'before' or 'after', saying where this page will fit.
464 if (isset($options['id']) && isset($options['rid']) && isset($options['pos']))
465 {
466 $i = array_search($options['rid'], $o['info']['pages']);
467
468 if (isset($o['info']['pages'][$i]) && $o['info']['pages'][$i] == $options['rid'])
469 {
470 // then there is a match
471 // make a space
472 switch ($options['pos'])
473 {
474 case 'before':
475 $k = $i;
476
477 break;
478
479 case 'after':
480 $k = $i + 1;
481
482 break;
483
484 default:
485 $k = -1;
486
487 break;
488 }
489
490 if ($k >= 0)
491 {
492 for ($j = count($o['info']['pages']) - 1; $j >= $k; $j--)
493 {
494 $o['info']['pages'][$j + 1] = $o['info']['pages'][$j];
495 }
496
497 $o['info']['pages'][$k] = $options['id'];
498 }
499 }
500 }
501 }
502
503 break;
504
505 case 'procset':
506 $o['info']['procset'] = $options;
507
508 break;
509
510 case 'mediaBox':
511 $o['info']['mediaBox'] = $options; // which should be an array of 4 numbers
512
513 break;
514
515 case 'font':
516 $o['info']['fonts'][] = array
517 (
518 'objNum' => $options['objNum'],
519 'fontNum' => $options['fontNum']
520 );
521
522 break;
523
524 case 'xObject':
525 $o['info']['xObjects'][] = array
526 (
527 'objNum' => $options['objNum'],
528 'label' => $options['label']
529 );
530
531 break;
532
533 case 'out':
534 if (count($o['info']['pages']))
535 {
536 $res = "\n" . $id . " 0 obj\n<< /Type /Pages\n/Kids [";
537
538 foreach ($o['info']['pages'] as $k => $v)
539 {
540 $res .= $v . " 0 R\n";
541 }
542
543 $res .= "]\n/Count " . count($this->objects[$id]['info']['pages']);
544
545 if ((isset($o['info']['fonts']) && count($o['info']['fonts'])) || isset($o['info']['procset']))
546 {
547 $res .= "\n/Resources <<";
548
549 if (isset($o['info']['procset']))
550 {
551 $res .= "\n/ProcSet " . $o['info']['procset'] . " 0 R";
552 }
553
554 if (isset($o['info']['fonts']) && count($o['info']['fonts']))
555 {
556 $res .= "\n/Font << ";
557
558 foreach ($o['info']['fonts'] as $finfo)
559 {
560 $res .= "\n/F" . $finfo['fontNum'] . " " . $finfo['objNum'] . " 0 R";
561 }
562
563 $res .= " >>";
564 }
565
566 if (isset($o['info']['xObjects']) && count($o['info']['xObjects']))
567 {
568 $res .= "\n/XObject << ";
569
570 foreach ($o['info']['xObjects'] as $finfo)
571 {
572 $res .= "\n/" . $finfo['label'] . " " . $finfo['objNum'] . " 0 R";
573 }
574
575 $res .= " >>";
576 }
577
578 $res .= "\n>>";
579
580 if (isset($o['info']['mediaBox']))
581 {
582 $tmp = $o['info']['mediaBox'];
583 $res .= "\n/MediaBox [" . __sprintf('%.3f',
584 $tmp[0]) . ' ' . __sprintf('%.3f',
585 $tmp[1]) . ' '
586 . __sprintf('%.3f', $tmp[2]) . ' ' . __sprintf('%.3f', $tmp[3]) . ']';
587 }
588 }
589
590 $res .= "\n >>\nendobj";
591 }
592 else
593 {
594 $res = "\n" . $id . " 0 obj\n<< /Type /Pages\n/Count 0\n>>\nendobj";
595 }
596
597 return $res;
598 break;
599 }
600 }
601
605 function o_outlines($id, $action, $options = '')
606 {
607 if ($action != 'new')
608 {
609 $o = &$this->objects[$id];
610 }
611
612 switch ($action)
613 {
614 case 'new':
615 $this->objects[$id] = array
616 (
617 't' => 'outlines',
618 'info' => array('outlines' => array(
619 ))
620 );
621
622 $this->o_catalog($this->catalogId, 'outlines', $id);
623 break;
624
625 case 'outline':
626 $o['info']['outlines'][] = $options;
627
628 break;
629
630 case 'out':
631 if (count($o['info']['outlines']))
632 {
633 $res = "\n" . $id . " 0 obj\n<< /Type /Outlines /Kids [";
634
635 foreach ($o['info']['outlines'] as $k => $v)
636 {
637 $res .= $v . " 0 R ";
638 }
639
640 $res .= "] /Count " . count($o['info']['outlines']) . " >>\nendobj";
641 }
642 else
643 {
644 $res = "\n" . $id . " 0 obj\n<< /Type /Outlines /Count 0 >>\nendobj";
645 }
646
647 return $res;
648 break;
649 }
650 }
651
655 function o_font($id, $action, $options = '')
656 {
657 if ($action != 'new')
658 {
659 $o = &$this->objects[$id];
660 }
661
662 switch ($action)
663 {
664 case 'new':
665 $this->objects[$id] = array
666 (
667 't' => 'font',
668 'info' => array('name' => $options['name'], 'SubType' => 'Type1')
669 );
670
671 $fontNum = $this->numFonts;
672 $this->objects[$id]['info']['fontNum'] = $fontNum;
673
674 // deal with the encoding and the differences
675 if (isset($options['differences']))
676 {
677 // then we'll need an encoding dictionary
678 $this->numObj++;
679 $this->o_fontEncoding($this->numObj, 'new', $options);
680 $this->objects[$id]['info']['encodingDictionary'] = $this->numObj;
681 }
682 else if (isset($options['encoding']))
683 {
684 // we can specify encoding here
685 switch ($options['encoding'])
686 {
687 case 'WinAnsiEncoding':
688 case 'MacRomanEncoding':
689 case 'MacExpertEncoding':
690 $this->objects[$id]['info']['encoding'] = $options['encoding'];
691
692 break;
693
694 case 'none': break;
695
696 default:
697 $this->objects[$id]['info']['encoding'] = 'WinAnsiEncoding';
698
699 break;
700 }
701 }
702 else
703 {
704 $this->objects[$id]['info']['encoding'] = 'WinAnsiEncoding';
705 }
706
707 // also tell the pages node about the new font
708 $this->o_pages($this->currentNode, 'font', array('fontNum' => $fontNum, 'objNum' => $id));
709 break;
710
711 case 'add':
712 foreach ($options as $k => $v)
713 {
714 switch ($k)
715 {
716 case 'BaseFont':
717 $o['info']['name'] = $v;
718
719 break;
720
721 case 'FirstChar':
722 case 'LastChar':
723 case 'Widths':
724 case 'FontDescriptor':
725 case 'SubType':
726 $this->addMessage('o_font ' . $k . " : " . $v);
727
728 $o['info'][$k] = $v;
729 break;
730 }
731 }
732
733 break;
734
735 case 'out':
736 $res = "\n" . $id . " 0 obj\n<< /Type /Font\n/Subtype /" . $o['info']['SubType'] . "\n";
737
738 $res .= "/Name /F" . $o['info']['fontNum'] . "\n";
739 $res .= "/BaseFont /" . $o['info']['name'] . "\n";
740
741 if (isset($o['info']['encodingDictionary']))
742 {
743 // then place a reference to the dictionary
744 $res .= "/Encoding " . $o['info']['encodingDictionary'] . " 0 R\n";
745 }
746 else if (isset($o['info']['encoding']))
747 {
748 // use the specified encoding
749 $res .= "/Encoding /" . $o['info']['encoding'] . "\n";
750 }
751
752 if (isset($o['info']['FirstChar']))
753 {
754 $res .= "/FirstChar " . $o['info']['FirstChar'] . "\n";
755 }
756
757 if (isset($o['info']['LastChar']))
758 {
759 $res .= "/LastChar " . $o['info']['LastChar'] . "\n";
760 }
761
762 if (isset($o['info']['Widths']))
763 {
764 $res .= "/Widths " . $o['info']['Widths'] . " 0 R\n";
765 }
766
767 if (isset($o['info']['FontDescriptor']))
768 {
769 $res .= "/FontDescriptor " . $o['info']['FontDescriptor'] . " 0 R\n";
770 }
771
772 $res .= ">>\nendobj";
773 return $res;
774 break;
775 }
776 }
777
781 function o_fontDescriptor($id, $action, $options = '')
782 {
783 if ($action != 'new')
784 {
785 $o = &$this->objects[$id];
786 }
787
788 switch ($action)
789 {
790 case 'new':
791 $this->objects[$id] = array
792 (
793 't' => 'fontDescriptor',
794 'info' => $options
795 );
796
797 break;
798
799 case 'out':
800 $res = "\n" . $id . " 0 obj\n<< /Type /FontDescriptor\n";
801
802 foreach ($o['info'] as $label => $value)
803 {
804 switch ($label)
805 {
806 case 'Ascent':
807 case 'CapHeight':
808 case 'Descent':
809 case 'Flags':
810 case 'ItalicAngle':
811 case 'StemV':
812 case 'AvgWidth':
813 case 'Leading':
814 case 'MaxWidth':
815 case 'MissingWidth':
816 case 'StemH':
817 case 'XHeight':
818 case 'CharSet':
819 if (strlen($value))
820 {
821 $res .= '/' . $label . ' ' . $value . "\n";
822 }
823
824 break;
825
826 case 'FontFile':
827 case 'FontFile2':
828 case 'FontFile3':
829 $res .= '/' . $label . ' ' . $value . " 0 R\n";
830
831 break;
832
833 case 'FontBBox':
834 $res
835 .= '/' . $label . ' [' . $value[0] . ' ' . $value[1] . ' ' . $value[2] . ' ' . $value[3]
836 . "]\n";
837
838 break;
839
840 case 'FontName':
841 $res .= '/' . $label . ' /' . $value . "\n";
842
843 break;
844 }
845 }
846
847 $res .= ">>\nendobj";
848 return $res;
849 break;
850 }
851 }
852
856 function o_fontEncoding($id, $action, $options = '')
857 {
858 if ($action != 'new')
859 {
860 $o = &$this->objects[$id];
861 }
862
863 switch ($action)
864 {
865 case 'new':
866 // the options array should contain 'differences' and maybe 'encoding'
867 $this->objects[$id] = array
868 (
869 't' => 'fontEncoding',
870 'info' => $options
871 );
872
873 break;
874
875 case 'out':
876 $res = "\n" . $id . " 0 obj\n<< /Type /Encoding\n";
877
878 if (!isset($o['info']['encoding']))
879 {
880 $o['info']['encoding'] = 'WinAnsiEncoding';
881 }
882
883 if ($o['info']['encoding'] != 'none')
884 {
885 $res .= "/BaseEncoding /" . $o['info']['encoding'] . "\n";
886 }
887
888 $res .= "/Differences \n[";
889 $onum = -100;
890
891 foreach ($o['info']['differences'] as $num => $label)
892 {
893 if ($num != $onum + 1)
894 {
895 // we cannot make use of consecutive numbering
896 $res .= "\n" . $num . " /" . $label;
897 }
898 else
899 {
900 $res .= " /" . $label;
901 }
902
903 $onum = $num;
904 }
905
906 $res .= "\n]\n>>\nendobj";
907 return $res;
908 break;
909 }
910 }
911
915 function o_procset($id, $action, $options = '')
916 {
917 if ($action != 'new')
918 {
919 $o = &$this->objects[$id];
920 }
921
922 switch ($action)
923 {
924 case 'new':
925 $this->objects[$id] = array
926 (
927 't' => 'procset',
928 'info' => array('PDF' => 1, 'Text' => 1)
929 );
930
931 $this->o_pages($this->currentNode, 'procset', $id);
932 $this->procsetObjectId = $id;
933 break;
934
935 case 'add':
936 // this is to add new items to the procset list, despite the fact that this is considered
937 // obselete, the items are required for printing to some postscript printers
938 switch ($options)
939 {
940 case 'ImageB':
941 case 'ImageC':
942 case 'ImageI':
943 $o['info'][$options] = 1;
944
945 break;
946 }
947
948 break;
949
950 case 'out':
951 $res = "\n" . $id . " 0 obj\n[";
952
953 foreach ($o['info'] as $label => $val)
954 {
955 $res .= '/' . $label . ' ';
956 }
957
958 $res .= "]\nendobj";
959 return $res;
960 break;
961 }
962 }
963
967 function o_info($id, $action, $options = '')
968 {
969 if ($action != 'new')
970 {
971 $o = &$this->objects[$id];
972 }
973
974 switch ($action)
975 {
976 case 'new':
977 $this->infoObject = $id;
978
979 $date = 'D:' . date('Ymd');
980 $this->objects[$id] = array
981 (
982 't' => 'info',
983 'info' =>
984 array('Creator' => 'R and OS php pdf writer, http://www.ros.co.nz', 'CreationDate' => $date)
985 );
986
987 break;
988
989 case 'Title':
990 case 'Author':
991 case 'Subject':
992 case 'Keywords':
993 case 'Creator':
994 case 'Producer':
995 case 'CreationDate':
996 case 'ModDate':
997 case 'Trapped':
998 $o['info'][$action] = $options;
999
1000 break;
1001
1002 case 'out':
1003 if ($this->encrypted)
1004 {
1005 $this->encryptInit($id);
1006 }
1007
1008 $res = "\n" . $id . " 0 obj\n<<\n";
1009
1010 foreach ($o['info'] as $k => $v)
1011 {
1012 $res .= '/' . $k . ' (';
1013
1014 if ($this->encrypted)
1015 {
1016 $res .= $this->filterText($this->ARC4($v));
1017 }
1018 else
1019 {
1020 $res .= $this->filterText($v);
1021 }
1022
1023 $res .= ")\n";
1024 }
1025
1026 $res .= ">>\nendobj";
1027 return $res;
1028 break;
1029 }
1030 }
1031
1035 function o_action($id, $action, $options = '')
1036 {
1037 if ($action != 'new')
1038 {
1039 $o = &$this->objects[$id];
1040 }
1041
1042 switch ($action)
1043 {
1044 case 'new':
1045 if (is_array($options))
1046 {
1047 $this->objects[$id] = array
1048 (
1049 't' => 'action',
1050 'info' => $options,
1051 'type' => $options['type']
1052 );
1053 }
1054 else
1055 {
1056 // then assume a URI action
1057 $this->objects[$id] = array
1058 (
1059 't' => 'action',
1060 'info' => $options,
1061 'type' => 'URI'
1062 );
1063 }
1064
1065 break;
1066
1067 case 'out':
1068 if ($this->encrypted)
1069 {
1070 $this->encryptInit($id);
1071 }
1072
1073 $res = "\n" . $id . " 0 obj\n<< /Type /Action";
1074
1075 switch ($o['type'])
1076 {
1077 case 'ilink':
1078 // there will be an 'label' setting, this is the name of the destination
1079 $res .= "\n/S /GoTo\n/D " . $this->destinations[(string)$o['info']['label']] . " 0 R";
1080
1081 break;
1082
1083 case 'URI':
1084 $res .= "\n/S /URI\n/URI (";
1085
1086 if ($this->encrypted)
1087 {
1088 $res .= $this->filterText($this->ARC4($o['info']));
1089 }
1090 else
1091 {
1092 $res .= $this->filterText($o['info']);
1093 }
1094
1095 $res .= ")";
1096 break;
1097 }
1098
1099 $res .= "\n>>\nendobj";
1100 return $res;
1101 break;
1102 }
1103 }
1104
1109 function o_annotation($id, $action, $options = '')
1110 {
1111 if ($action != 'new')
1112 {
1113 $o = &$this->objects[$id];
1114 }
1115
1116 switch ($action)
1117 {
1118 case 'new':
1119 // add the annotation to the current page
1120 $pageId = $this->currentPage;
1121
1122 $this->o_page($pageId, 'annot', $id);
1123
1124 // and add the action object which is going to be required
1125 switch ($options['type'])
1126 {
1127 case 'link':
1128 $this->objects[$id] = array
1129 (
1130 't' => 'annotation',
1131 'info' => $options
1132 );
1133
1134 $this->numObj++;
1135 $this->o_action($this->numObj, 'new', $options['url']);
1136 $this->objects[$id]['info']['actionId'] = $this->numObj;
1137 break;
1138
1139 case 'ilink':
1140 // this is to a named internal link
1141 $label = $options['label'];
1142
1143 $this->objects[$id] = array
1144 (
1145 't' => 'annotation',
1146 'info' => $options
1147 );
1148
1149 $this->numObj++;
1150 $this->o_action($this->numObj, 'new', array('type' => 'ilink', 'label' => $label));
1151 $this->objects[$id]['info']['actionId'] = $this->numObj;
1152 break;
1153 }
1154
1155 break;
1156
1157 case 'out':
1158 $res = "\n" . $id . " 0 obj\n<< /Type /Annot";
1159
1160 switch ($o['info']['type'])
1161 {
1162 case 'link':
1163 case 'ilink':
1164 $res .= "\n/Subtype /Link";
1165
1166 break;
1167 }
1168
1169 $res .= "\n/A " . $o['info']['actionId'] . " 0 R";
1170 $res .= "\n/Border [0 0 0]";
1171 $res .= "\n/H /I";
1172 $res .= "\n/Rect [ ";
1173
1174 foreach ($o['info']['rect'] as $v)
1175 {
1176 $res .= __sprintf("%.4f ", $v);
1177 }
1178
1179 $res .= "]";
1180 $res .= "\n>>\nendobj";
1181 return $res;
1182 break;
1183 }
1184 }
1185
1189 function o_page($id, $action, $options = '')
1190 {
1191 if ($action != 'new')
1192 {
1193 $o = &$this->objects[$id];
1194 }
1195
1196 switch ($action)
1197 {
1198 case 'new':
1199 $this->numPages++;
1200
1201 $this->objects[$id] = array
1202 (
1203 't' => 'page',
1204 'info' => array('parent' => $this->currentNode, 'pageNum' => $this->numPages)
1205 );
1206
1207 if (is_array($options))
1208 {
1209 // then this must be a page insertion, array shoudl contain 'rid','pos'=[before|after]
1210 $options['id'] = $id;
1211 $this->o_pages($this->currentNode, 'page', $options);
1212 }
1213 else
1214 {
1215 $this->o_pages($this->currentNode, 'page', $id);
1216 }
1217
1218 $this->currentPage = $id;
1219 //make a contents object to go with this page
1220 $this->numObj++;
1221 $this->o_contents($this->numObj, 'new', $id);
1222 $this->currentContents = $this->numObj;
1223 $this->objects[$id]['info']['contents'] = array(
1224 );
1225
1226 $this->objects[$id]['info']['contents'][] = $this->numObj;
1227 $match = ($this->numPages % 2 ? 'odd' : 'even');
1228
1229 foreach ($this->addLooseObjects as $oId => $target)
1230 {
1231 if ($target == 'all' || $match == $target)
1232 {
1233 $this->objects[$id]['info']['contents'][] = $oId;
1234 }
1235 }
1236
1237 break;
1238
1239 case 'content':
1240 $o['info']['contents'][] = $options;
1241
1242 break;
1243
1244 case 'annot':
1245 // add an annotation to this page
1246 if (!isset($o['info']['annot']))
1247 {
1248 $o['info']['annot'] = array(
1249 );
1250 }
1251
1252 // $options should contain the id of the annotation dictionary
1253 $o['info']['annot'][] = $options;
1254 break;
1255
1256 case 'out':
1257 $res = "\n" . $id . " 0 obj\n<< /Type /Page";
1258
1259 $res .= "\n/Parent " . $o['info']['parent'] . " 0 R";
1260
1261 if (isset($o['info']['annot']))
1262 {
1263 $res .= "\n/Annots [";
1264
1265 foreach ($o['info']['annot'] as $aId)
1266 {
1267 $res .= " " . $aId . " 0 R";
1268 }
1269
1270 $res .= " ]";
1271 }
1272
1273 $count = count($o['info']['contents']);
1274
1275 if ($count == 1)
1276 {
1277 $res .= "\n/Contents " . $o['info']['contents'][0] . " 0 R";
1278 }
1279 else if ($count > 1)
1280 {
1281 $res .= "\n/Contents [\n";
1282
1283 foreach ($o['info']['contents'] as $cId)
1284 {
1285 $res .= $cId . " 0 R\n";
1286 }
1287
1288 $res .= "]";
1289 }
1290
1291 $res .= "\n>>\nendobj";
1292 return $res;
1293 break;
1294 }
1295 }
1296
1300 function o_contents($id, $action, $options = '')
1301 {
1302 if ($action != 'new')
1303 {
1304 $o = &$this->objects[$id];
1305 }
1306
1307 switch ($action)
1308 {
1309 case 'new':
1310 $this->objects[$id] = array
1311 (
1312 't' => 'contents',
1313 'c' => '',
1314 'info' => array(
1315 )
1316 );
1317
1318 if (strlen($options) && intval($options))
1319 {
1320 // then this contents is the primary for a page
1321 $this->objects[$id]['onPage'] = $options;
1322 }
1323 else if ($options == 'raw')
1324 {
1325 // then this page contains some other type of system object
1326 $this->objects[$id]['raw'] = 1;
1327 }
1328
1329 break;
1330
1331 case 'add':
1332 // add more options to the decleration
1333 foreach ($options as $k => $v)
1334 {
1335 $o['info'][$k] = $v;
1336 }
1337
1338 case 'out':
1339 $tmp = $o['c'];
1340
1341 $res = "\n" . $id . " 0 obj\n";
1342
1343 if (isset($this->objects[$id]['raw']))
1344 {
1345 $res .= $tmp;
1346 }
1347 else
1348 {
1349 $res .= "<<";
1350
1351 if (function_exists('gzcompress') && $this->options['compression'])
1352 {
1353 // then implement ZLIB based compression on this content stream
1354 $res .= " /Filter /FlateDecode";
1355 $tmp = gzcompress($tmp);
1356 }
1357
1358 if ($this->encrypted)
1359 {
1360 $this->encryptInit($id);
1361 $tmp = $this->ARC4($tmp);
1362 }
1363
1364 foreach ($o['info'] as $k => $v)
1365 {
1366 $res .= "\n/" . $k . ' ' . $v;
1367 }
1368
1369 $res .= "\n/Length " . strlen($tmp) . " >>\nstream\n" . $tmp . "\nendstream";
1370 }
1371
1372 $res .= "\nendobj\n";
1373 return $res;
1374 break;
1375 }
1376 }
1377
1381 function o_image($id, $action, $options = '')
1382 {
1383 if ($action != 'new')
1384 {
1385 $o = &$this->objects[$id];
1386 }
1387
1388 switch ($action)
1389 {
1390 case 'new':
1391 // make the new object
1392 $this->objects[$id] = array
1393 (
1394 't' => 'image',
1395 'data' => $options['data'],
1396 'info' => array(
1397 )
1398 );
1399
1400 $this->objects[$id]['info']['Type'] = '/XObject';
1401 $this->objects[$id]['info']['Subtype'] = '/Image';
1402 $this->objects[$id]['info']['Width'] = $options['iw'];
1403 $this->objects[$id]['info']['Height'] = $options['ih'];
1404
1405 if (!isset($options['type']) || $options['type'] == 'jpg')
1406 {
1407 if (!isset($options['channels']))
1408 {
1409 $options['channels'] = 3;
1410 }
1411
1412 switch ($options['channels'])
1413 {
1414 case 1:
1415 $this->objects[$id]['info']['ColorSpace'] = '/DeviceGray';
1416
1417 break;
1418
1419 default:
1420 $this->objects[$id]['info']['ColorSpace'] = '/DeviceRGB';
1421
1422 break;
1423 }
1424
1425 $this->objects[$id]['info']['Filter'] = '/DCTDecode';
1426 $this->objects[$id]['info']['BitsPerComponent'] = 8;
1427 }
1428 else if ($options['type'] == 'png')
1429 {
1430 $this->objects[$id]['info']['Filter'] = '/FlateDecode';
1431 $this->objects[$id]['info']['DecodeParms']
1432 = '<< /Predictor 15 /Colors ' . $options['ncolor'] . ' /Columns ' . $options['iw']
1433 . ' /BitsPerComponent ' . $options['bitsPerComponent'] . '>>';
1434
1435 if (strlen($options['pdata']))
1436 {
1437 $tmp = ' [ /Indexed /DeviceRGB ' . (strlen($options['pdata']) / 3 - 1) . ' ';
1438 $this->numObj++;
1439 $this->o_contents($this->numObj, 'new');
1440 $this->objects[$this->numObj]['c'] = $options['pdata'];
1441 $tmp .= $this->numObj . ' 0 R';
1442 $tmp .= ' ]';
1443 $this->objects[$id]['info']['ColorSpace'] = $tmp;
1444
1445 if (isset($options['transparency']))
1446 {
1447 switch ($options['transparency']['type'])
1448 {
1449 case 'indexed':
1450 $tmp = ' [ ' . $options['transparency']['data'] . ' '
1451 . $options['transparency']['data'] . '] ';
1452
1453 $this->objects[$id]['info']['Mask'] = $tmp;
1454 break;
1455 }
1456 }
1457 }
1458 else
1459 {
1460 $this->objects[$id]['info']['ColorSpace'] = '/' . $options['color'];
1461 }
1462
1463 $this->objects[$id]['info']['BitsPerComponent'] = $options['bitsPerComponent'];
1464 }
1465
1466 // assign it a place in the named resource dictionary as an external object, according to
1467 // the label passed in with it.
1468 $this->o_pages($this->currentNode, 'xObject', array('label' => $options['label'], 'objNum' => $id));
1469 // also make sure that we have the right procset object for it.
1470 $this->o_procset($this->procsetObjectId, 'add', 'ImageC');
1471 break;
1472
1473 case 'out':
1474 $tmp = $o['data'];
1475
1476 $res = "\n" . $id . " 0 obj\n<<";
1477
1478 foreach ($o['info'] as $k => $v)
1479 {
1480 $res .= "\n/" . $k . ' ' . $v;
1481 }
1482
1483 if ($this->encrypted)
1484 {
1485 $this->encryptInit($id);
1486 $tmp = $this->ARC4($tmp);
1487 }
1488
1489 $res .= "\n/Length " . strlen($tmp) . " >>\nstream\n" . $tmp . "\nendstream\nendobj\n";
1490 return $res;
1491 break;
1492 }
1493 }
1494
1498 function o_encryption($id, $action, $options = '')
1499 {
1500 if ($action != 'new')
1501 {
1502 $o = &$this->objects[$id];
1503 }
1504
1505 switch ($action)
1506 {
1507 case 'new':
1508 // make the new object
1509 $this->objects[$id] = array
1510 (
1511 't' => 'encryption',
1512 'info' => $options
1513 );
1514
1515 $this->arc4_objnum = $id;
1516 // figure out the additional paramaters required
1517 $pad = chr(0x28) . chr(0xBF) . chr(0x4E) . chr(0x5E) . chr(0x4E) . chr(0x75) . chr(0x8A) . chr(0x41)
1518 . chr(0x64)
1519 . chr(0x00) . chr(0x4E) . chr(0x56) . chr(0xFF) . chr(0xFA) . chr(0x01) . chr(0x08) . chr(
1520 0x2E)
1521 . chr(0x2E) . chr(0x00) . chr(0xB6) . chr(0xD0) . chr(0x68) . chr(0x3E) . chr(0x80) . chr(
1522 0x2F)
1523 . chr(0x0C) . chr(0xA9) . chr(0xFE) . chr(0x64) . chr(0x53) . chr(0x69) . chr(0x7A);
1524 $len = strlen($options['owner']);
1525
1526 if ($len > 32)
1527 {
1528 $owner = substr($options['owner'], 0, 32);
1529 }
1530 else if ($len < 32)
1531 {
1532 $owner = $options['owner'] . substr($pad, 0, 32 - $len);
1533 }
1534 else
1535 {
1536 $owner = $options['owner'];
1537 }
1538
1539 $len = strlen($options['user']);
1540
1541 if ($len > 32)
1542 {
1543 $user = substr($options['user'], 0, 32);
1544 }
1545 else if ($len < 32)
1546 {
1547 $user = $options['user'] . substr($pad, 0, 32 - $len);
1548 }
1549 else
1550 {
1551 $user = $options['user'];
1552 }
1553
1554 $tmp = $this->md5_16($owner);
1555 $okey = substr($tmp, 0, 5);
1556 $this->ARC4_init($okey);
1557 $ovalue = $this->ARC4($user);
1558 $this->objects[$id]['info']['O'] = $ovalue;
1559 // now make the u value, phew.
1560 $tmp = $this->md5_16($user . $ovalue . chr($options['p']) . chr(255) . chr(255) . chr(255)
1561 . $this->fileIdentifier);
1562 $ukey = substr($tmp, 0, 5);
1563
1564 $this->ARC4_init($ukey);
1565 $this->encryptionKey = $ukey;
1566 $this->encrypted = 1;
1567 $uvalue = $this->ARC4($pad);
1568
1569 $this->objects[$id]['info']['U'] = $uvalue;
1570 $this->encryptionKey = $ukey;
1571
1572 // initialize the arc4 array
1573 break;
1574
1575 case 'out':
1576 $res = "\n" . $id . " 0 obj\n<<";
1577
1578 $res .= "\n/Filter /Standard";
1579 $res .= "\n/V 1";
1580 $res .= "\n/R 2";
1581 $res .= "\n/O (" . $this->filterText($o['info']['O']) . ')';
1582 $res .= "\n/U (" . $this->filterText($o['info']['U']) . ')';
1583 // and the p-value needs to be converted to account for the twos-complement approach
1584 $o['info']['p'] = (($o['info']['p'] ^ 255) + 1) * -1;
1585 $res .= "\n/P " . ($o['info']['p']);
1586 $res .= "\n>>\nendobj\n";
1587
1588 return $res;
1589 break;
1590 }
1591 }
1592
1601 function md5_16($string)
1602 {
1603 $tmp = md5($string);
1604 $out = '';
1605
1606 for ($i = 0; $i <= 30; $i = $i + 2)
1607 {
1608 $out .= chr(hexdec(substr($tmp, $i, 2)));
1609 }
1610
1611 return $out;
1612 }
1613
1618 {
1619 $tmp = $this->encryptionKey;
1620 $hex = dechex($id);
1621
1622 if (strlen($hex) < 6)
1623 {
1624 $hex = substr('000000', 0, 6 - strlen($hex)) . $hex;
1625 }
1626
1627 $tmp .= chr(hexdec(substr($hex, 4, 2))) . chr(hexdec(substr($hex, 2, 2))) . chr(hexdec(substr($hex, 0,
1628 2))) . chr(0)
1629 . chr(0);
1630 $key = $this->md5_16($tmp);
1631 $this->ARC4_init(substr($key, 0, 10));
1632 }
1633
1637 function ARC4_init($key = '')
1638 {
1639 $this->arc4 = '';
1640
1641 // setup the control array
1642 if (strlen($key) == 0)
1643 {
1644 return;
1645 }
1646
1647 $k = '';
1648
1649 while (strlen($k) < 256)
1650 {
1651 $k .= $key;
1652 }
1653
1654 $k = substr($k, 0, 256);
1655
1656 for ($i = 0; $i < 256; $i++)
1657 {
1658 $this->arc4 .= chr($i);
1659 }
1660
1661 $j = 0;
1662
1663 for ($i = 0; $i < 256; $i++)
1664 {
1665 $t = $this->arc4[$i];
1666 $j = ($j + ord($t) + ord($k[$i])) % 256;
1667 $this->arc4[$i] = $this->arc4[$j];
1668 $this->arc4[$j] = $t;
1669 }
1670 }
1671
1675 function ARC4($text)
1676 {
1677 $len = strlen($text);
1678 $a = 0;
1679 $b = 0;
1680 $c = $this->arc4;
1681 $out = '';
1682
1683 for ($i = 0; $i < $len; $i++)
1684 {
1685 $a = ($a + 1) % 256;
1686 $t = $c[$a];
1687 $b = ($b + ord($t)) % 256;
1688 $c[$a] = $c[$b];
1689 $c[$b] = $t;
1690 $k = ord($c[(ord($c[$a]) + ord($c[$b])) % 256]);
1691 $out .= chr(ord($text[$i]) ^ $k);
1692 }
1693
1694 return $out;
1695 }
1696
1704 function addLink($url, $x0, $y0, $x1, $y1)
1705 {
1706 $this->numObj++;
1707 $info = array
1708 (
1709 'type' => 'link',
1710 'url' => $url,
1711 'rect' => array($x0, $y0, $x1, $y1)
1712 );
1713
1714 $this->o_annotation($this->numObj, 'new', $info);
1715 }
1716
1720 function addInternalLink($label, $x0, $y0, $x1, $y1)
1721 {
1722 $this->numObj++;
1723 $info = array
1724 (
1725 'type' => 'ilink',
1726 'label' => $label,
1727 'rect' => array($x0, $y0, $x1, $y1)
1728 );
1729
1730 $this->o_annotation($this->numObj, 'new', $info);
1731 }
1732
1738 function setEncryption($userPass = '', $ownerPass = '', $pc = array(
1739 ))
1740 {
1741 $p = bindec(11000000);
1742
1743 $options = array
1744 (
1745 'print' => 4,
1746 'modify' => 8,
1747 'copy' => 16,
1748 'add' => 32
1749 );
1750
1751 foreach ($pc as $k => $v)
1752 {
1753 if ($v && isset($options[$k]))
1754 {
1755 $p += $options[$k];
1756 }
1757 else if (isset($options[$v]))
1758 {
1759 $p += $options[$v];
1760 }
1761 }
1762
1763 // implement encryption on the document
1764 if ($this->arc4_objnum == 0)
1765 {
1766 // then the block does not exist already, add it.
1767 $this->numObj++;
1768
1769 if (strlen($ownerPass) == 0)
1770 {
1771 $ownerPass = $userPass;
1772 }
1773
1774 $this->o_encryption($this->numObj, 'new', array('user' => $userPass, 'owner' => $ownerPass, 'p' => $p));
1775 }
1776 }
1777
1781 function checkAllHere()
1782 {
1783 }
1784
1788 function output($debug = 0)
1789 {
1790 if ($debug)
1791 {
1792 // turn compression off
1793 $this->options['compression'] = 0;
1794 }
1795
1796 if ($this->arc4_objnum)
1797 {
1798 $this->ARC4_init($this->encryptionKey);
1799 }
1800
1801 $this->checkAllHere();
1802
1803 $xref = array(
1804 );
1805
1806 $content = "%PDF-1.3\n%âãÏÓ\n";
1807 // $content="%PDF-1.3\n";
1808 $pos = strlen($content);
1809
1810 foreach ($this->objects as $k => $v)
1811 {
1812 $tmp = 'o_' . $v['t'];
1813 $cont = $this->$tmp($k, 'out');
1814 $content .= $cont;
1815 $xref[] = $pos;
1816 $pos += strlen($cont);
1817 }
1818
1819 $content .= "\nxref\n0 " . (count($xref) + 1) . "\n0000000000 65535 f \n";
1820
1821 foreach ($xref as $p)
1822 {
1823 $content .= substr('0000000000', 0, 10 - strlen($p)) . $p . " 00000 n \n";
1824 }
1825
1826 $content .= "\ntrailer\n << /Size " . (count($xref)
1827 + 1) . "\n /Root 1 0 R\n /Info " . $this->infoObject
1828 . " 0 R\n";
1829
1830 // if encryption has been applied to this document then add the marker for this dictionary
1831 if ($this->arc4_objnum > 0)
1832 {
1833 $content .= "/Encrypt " . $this->arc4_objnum . " 0 R\n";
1834 }
1835
1836 if (strlen($this->fileIdentifier))
1837 {
1838 $content .= "/ID[<" . $this->fileIdentifier . "><" . $this->fileIdentifier . ">]\n";
1839 }
1840
1841 $content .= " >>\nstartxref\n" . $pos . "\n%%EOF\n";
1842 return $content;
1843 }
1844
1852 function newDocument($pageSize = array(0, 0, 612, 792))
1853 {
1854 $this->numObj = 0;
1855 $this->objects = array(
1856 );
1857
1858 $this->numObj++;
1859 $this->o_catalog($this->numObj, 'new');
1860
1861 $this->numObj++;
1862 $this->o_outlines($this->numObj, 'new');
1863
1864 $this->numObj++;
1865 $this->o_pages($this->numObj, 'new');
1866
1867 $this->o_pages($this->numObj, 'mediaBox', $pageSize);
1868 $this->currentNode = 3;
1869
1870 $this->numObj++;
1871 $this->o_procset($this->numObj, 'new');
1872
1873 $this->numObj++;
1874 $this->o_info($this->numObj, 'new');
1875
1876 $this->numObj++;
1877 $this->o_page($this->numObj, 'new');
1878
1879 // need to store the first page id as there is no way to get it to the user during
1880 // startup
1881 $this->firstPageId = $this->currentContents;
1882 }
1883
1893 function openFont($font)
1894 {
1895 // assume that $font contains both the path and perhaps the extension to the file, split them
1896 $pos = strrpos($font, '/');
1897
1898 if ($pos === false)
1899 {
1900 $dir = './';
1901 $name = $font;
1902 }
1903 else
1904 {
1905 $dir = substr($font, 0, $pos + 1);
1906 $name = substr($font, $pos + 1);
1907 }
1908
1909 if (substr($name, -4) == '.afm')
1910 {
1911 $name = substr($name, 0, strlen($name) - 4);
1912 }
1913
1914 $this->addMessage('openFont: ' . $font . ' - ' . $name);
1915
1916 if (file_exists($dir . 'php_' . $name . '.afm'))
1917 {
1918 $this->addMessage('openFont: php file exists ' . $dir . 'php_' . $name . '.afm');
1919 $tmp = file($dir . 'php_' . $name . '.afm');
1920 $this->fonts[$font] = unserialize($tmp[0]);
1921
1922 if (!isset($this->fonts[$font]['_version_']) || $this->fonts[$font]['_version_'] < 1)
1923 {
1924 // if the font file is old, then clear it out and prepare for re-creation
1925 $this->addMessage('openFont: clear out, make way for new version.');
1926 unset($this->fonts[$font]);
1927 }
1928 }
1929
1930 if (!isset($this->fonts[$font]) && file_exists($dir . $name . '.afm'))
1931 {
1932 // then rebuild the php_<font>.afm file from the <font>.afm file
1933 $this->addMessage('openFont: build php file from ' . $dir . $name . '.afm');
1934 $data = array(
1935 );
1936
1937 $file = file($dir . $name . '.afm');
1938
1939 foreach ($file as $rowA)
1940 {
1941 $row = trim($rowA);
1942 $pos = strpos($row, ' ');
1943
1944 if ($pos)
1945 {
1946 // then there must be some keyword
1947 $key = substr($row, 0, $pos);
1948
1949 switch ($key)
1950 {
1951 case 'FontName':
1952 case 'FullName':
1953 case 'FamilyName':
1954 case 'Weight':
1955 case 'ItalicAngle':
1956 case 'IsFixedPitch':
1957 case 'CharacterSet':
1958 case 'UnderlinePosition':
1959 case 'UnderlineThickness':
1960 case 'Version':
1961 case 'EncodingScheme':
1962 case 'CapHeight':
1963 case 'XHeight':
1964 case 'Ascender':
1965 case 'Descender':
1966 case 'StdHW':
1967 case 'StdVW':
1968 case 'StartCharMetrics':
1969 $data[$key] = trim(substr($row, $pos));
1970
1971 break;
1972
1973 case 'FontBBox':
1974 $data[$key] = explode(' ', trim(substr($row, $pos)));
1975
1976 break;
1977
1978 case 'C':
1979 //C 39 ; WX 222 ; N quoteright ; B 53 463 157 718 ;
1980 $bits = explode(';', trim($row));
1981
1982 $dtmp = array(
1983 );
1984
1985 foreach ($bits as $bit)
1986 {
1987 $bits2 = explode(' ', trim($bit));
1988
1989 if (strlen($bits2[0]))
1990 {
1991 if (count($bits2) > 2)
1992 {
1993 $dtmp[$bits2[0]] = array(
1994 );
1995
1996 for ($i = 1; $i < count($bits2); $i++)
1997 {
1998 $dtmp[$bits2[0]][] = $bits2[$i];
1999 }
2000 }
2001 else if (count($bits2) == 2)
2002 {
2003 $dtmp[$bits2[0]] = $bits2[1];
2004 }
2005 }
2006 }
2007
2008 if ($dtmp['C'] >= 0)
2009 {
2010 $data['C'][$dtmp['C']] = $dtmp;
2011 $data['C'][$dtmp['N']] = $dtmp;
2012 }
2013 else
2014 {
2015 $data['C'][$dtmp['N']] = $dtmp;
2016 }
2017
2018 break;
2019
2020 case 'KPX':
2021 //KPX Adieresis yacute -40
2022 $bits = explode(' ', trim($row));
2023
2024 $data['KPX'][$bits[1]][$bits[2]] = $bits[3];
2025 break;
2026 }
2027 }
2028 }
2029
2030 $data['_version_'] = 1;
2031 $this->fonts[$font] = $data;
2032 $fp = fopen($dir . 'php_' . $name . '.afm', 'w');
2033 fwrite($fp, serialize($data));
2034 fclose($fp);
2035 }
2036 else if (!isset($this->fonts[$font]))
2037 {
2038 $this->addMessage('openFont: no font file found');
2039 // echo 'Font not Found '.$font;
2040 }
2041 }
2042
2051 function selectFont($fontName, $encoding = '', $set = 1)
2052 {
2053 if (strpos($fontName, $this->fonts_path) === false)
2054 $fontName = $this->fonts_path . '/' . $fontName;
2055 //echo $fontName;
2056
2057 if (!isset($this->fonts[$fontName]))
2058 {
2059 // load the file
2060 $this->openFont($fontName);
2061
2062 if (isset($this->fonts[$fontName]))
2063 {
2064 $this->numObj++;
2065 $this->numFonts++;
2066 $pos = strrpos($fontName, '/');
2067 // $dir=substr($fontName,0,$pos+1);
2068 $name = substr($fontName, $pos + 1);
2069
2070 if (substr($name, -4) == '.afm')
2071 {
2072 $name = substr($name, 0, strlen($name) - 4);
2073 }
2074
2075 $options = array('name' => $name);
2076
2077 if (is_array($encoding))
2078 {
2079 // then encoding and differences might be set
2080 if (isset($encoding['encoding']))
2081 {
2082 $options['encoding'] = $encoding['encoding'];
2083 }
2084
2085 if (isset($encoding['differences']))
2086 {
2087 $options['differences'] = $encoding['differences'];
2088 }
2089 }
2090 else if (strlen($encoding))
2091 {
2092 // then perhaps only the encoding has been set
2093 $options['encoding'] = $encoding;
2094 }
2095
2096 $fontObj = $this->numObj;
2097 $this->o_font($this->numObj, 'new', $options);
2098 $this->fonts[$fontName]['fontNum'] = $this->numFonts;
2099 // if this is a '.afm' font, and there is a '.pfa' file to go with it ( as there
2100 // should be for all non-basic fonts), then load it into an object and put the
2101 // references into the font object
2102 $basefile = substr($fontName, 0, strlen($fontName) - 4);
2103
2104 if (file_exists($basefile . '.pfb'))
2105 {
2106 $fbtype = 'pfb';
2107 }
2108 else if (file_exists($basefile . '.ttf'))
2109 {
2110 $fbtype = 'ttf';
2111 }
2112 else
2113 {
2114 $fbtype = '';
2115 }
2116
2117 $fbfile = $basefile . '.' . $fbtype;
2118
2119 // $pfbfile = substr($fontName,0,strlen($fontName)-4).'.pfb';
2120 // $ttffile = substr($fontName,0,strlen($fontName)-4).'.ttf';
2121 $this->addMessage('selectFont: checking for - ' . $fbfile);
2122
2123 if (substr($fontName, -4) == '.afm' && strlen($fbtype))
2124 {
2125 $adobeFontName = $this->fonts[$fontName]['FontName'];
2126 // $fontObj = $this->numObj;
2127 $this->addMessage('selectFont: adding font file - ' . $fbfile . ' - ' . $adobeFontName);
2128 // find the array of fond widths, and put that into an object.
2129 $firstChar = -1;
2130 $lastChar = 0;
2131 $widths = array(
2132 );
2133
2134 foreach ($this->fonts[$fontName]['C'] as $num => $d)
2135 {
2136 if (intval($num) > 0 || $num == '0')
2137 {
2138 if ($lastChar > 0 && $num > $lastChar + 1)
2139 {
2140 for ($i = $lastChar + 1; $i < $num; $i++)
2141 {
2142 $widths[] = 0;
2143 }
2144 }
2145
2146 $widths[] = $d['WX'];
2147
2148 if ($firstChar == -1)
2149 {
2150 $firstChar = $num;
2151 }
2152
2153 $lastChar = $num;
2154 }
2155 }
2156
2157 // also need to adjust the widths for the differences array
2158 if (isset($options['differences']))
2159 {
2160 foreach ($options['differences'] as $charNum => $charName)
2161 {
2162 if ($charNum > $lastChar)
2163 {
2164 for ($i = $lastChar + 1; $i <= $charNum; $i++)
2165 {
2166 $widths[] = 0;
2167 }
2168
2169 $lastChar = $charNum;
2170 }
2171
2172 if (isset($this->fonts[$fontName]['C'][$charName]))
2173 {
2174 $widths[$charNum - $firstChar] = $this->fonts[$fontName]['C'][$charName]['WX'];
2175 }
2176 }
2177 }
2178
2179 $this->addMessage('selectFont: FirstChar=' . $firstChar);
2180 $this->addMessage('selectFont: LastChar=' . $lastChar);
2181 $this->numObj++;
2182 $this->o_contents($this->numObj, 'new', 'raw');
2183 $this->objects[$this->numObj]['c'] .= '[';
2184
2185 foreach ($widths as $width)
2186 {
2187 $this->objects[$this->numObj]['c'] .= ' ' . $width;
2188 }
2189
2190 $this->objects[$this->numObj]['c'] .= ' ]';
2191 $widthid = $this->numObj;
2192
2193 // load the pfb file, and put that into an object too.
2194 // note that pdf supports only binary format type 1 font files, though there is a
2195 // simple utility to convert them from pfa to pfb.
2196 $fp = fopen($fbfile, 'rb');
2197 $data = fread($fp, filesize($fbfile));
2198 fclose($fp);
2199
2200 // create the font descriptor
2201 $this->numObj++;
2202 $fontDescriptorId = $this->numObj;
2203 $this->numObj++;
2204 $pfbid = $this->numObj;
2205 // determine flags (more than a little flakey, hopefully will not matter much)
2206 $flags = 0;
2207
2208 if ($this->fonts[$fontName]['ItalicAngle'] != 0)
2209 {
2210 $flags += pow(2, 6);
2211 }
2212
2213 if ($this->fonts[$fontName]['IsFixedPitch'] == 'true')
2214 {
2215 $flags += 1;
2216 }
2217
2218 $flags += pow(2, 5); // assume non-sybolic
2219
2220 $list = array
2221 (
2222 'Ascent' => 'Ascender',
2223 'CapHeight' => 'CapHeight',
2224 'Descent' => 'Descender',
2225 'FontBBox' => 'FontBBox',
2226 'ItalicAngle' => 'ItalicAngle'
2227 );
2228
2229 $fdopt = array
2230 (
2231 'Flags' => $flags,
2232 'FontName' => $adobeFontName,
2233 'StemV' => 100 // don't know what the value for this should be!
2234 );
2235
2236 foreach ($list as $k => $v)
2237 {
2238 if (isset($this->fonts[$fontName][$v]))
2239 {
2240 $fdopt[$k] = $this->fonts[$fontName][$v];
2241 }
2242 }
2243
2244 if ($fbtype == 'pfb')
2245 {
2246 $fdopt['FontFile'] = $pfbid;
2247 }
2248 else if ($fbtype == 'ttf')
2249 {
2250 $fdopt['FontFile2'] = $pfbid;
2251 }
2252
2253 $this->o_fontDescriptor($fontDescriptorId, 'new', $fdopt);
2254
2255 // embed the font program
2256 $this->o_contents($this->numObj, 'new');
2257 $this->objects[$pfbid]['c'] .= $data;
2258
2259 // determine the cruicial lengths within this file
2260 if ($fbtype == 'pfb')
2261 {
2262 $l1 = strpos($data, 'eexec') + 6;
2263 $l2 = strpos($data, '00000000') - $l1;
2264 $l3 = strlen($data) - $l2 - $l1;
2265 $this->o_contents($this->numObj, 'add',
2266 array('Length1' => $l1, 'Length2' => $l2, 'Length3' => $l3));
2267 }
2268 else if ($fbtype == 'ttf')
2269 {
2270 $l1 = strlen($data);
2271 $this->o_contents($this->numObj, 'add', array('Length1' => $l1));
2272 }
2273
2274 // tell the font object about all this new stuff
2275 $tmp = array
2276 (
2277 'BaseFont' => $adobeFontName,
2278 'Widths' => $widthid,
2279 'FirstChar' => $firstChar,
2280 'LastChar' => $lastChar,
2281 'FontDescriptor' => $fontDescriptorId
2282 );
2283
2284 if ($fbtype == 'ttf')
2285 {
2286 $tmp['SubType'] = 'TrueType';
2287 }
2288
2289 $this->addMessage('adding extra info to font.(' . $fontObj . ')');
2290
2291 foreach ($tmp as $fk => $fv)
2292 {
2293 $this->addMessage($fk . " : " . $fv);
2294 }
2295
2296 $this->o_font($fontObj, 'add', $tmp);
2297 }
2298 else
2299 {
2300 $this->addMessage(
2301 'selectFont: pfb or ttf file not found, ok if this is one of the 14 standard fonts');
2302 }
2303
2304 // also set the differences here, note that this means that these will take effect only the
2305 //first time that a font is selected, else they are ignored
2306 if (isset($options['differences']))
2307 {
2308 $this->fonts[$fontName]['differences'] = $options['differences'];
2309 }
2310 }
2311 }
2312
2313 if ($set && isset($this->fonts[$fontName]))
2314 {
2315 // so if for some reason the font was not set in the last one then it will not be selected
2316 $this->currentBaseFont = $fontName;
2317 // the next line means that if a new font is selected, then the current text state will be
2318 // applied to it as well.
2319 $this->setCurrentFont();
2320 }
2321
2322 return $this->currentFontNum;
2323 }
2324
2338 {
2339 if (strlen($this->currentBaseFont) == 0)
2340 {
2341 // then assume an initial font
2342 $this->selectFont($this->fonts_path . '/Helvetica.afm');
2343 }
2344
2345 $cf = substr($this->currentBaseFont, strrpos($this->currentBaseFont, '/') + 1);
2346
2347 if (strlen($this->currentTextState) && isset($this->fontFamilies[$cf]) && isset(
2348 $this->fontFamilies[$cf][$this->currentTextState]))
2349 {
2350 // then we are in some state or another
2351 // and this font has a family, and the current setting exists within it
2352 // select the font, then return it
2353 $nf = substr($this->currentBaseFont, 0,
2354 strrpos($this->currentBaseFont, '/') + 1) . $this->fontFamilies[$cf][$this->currentTextState];
2355 $this->selectFont($nf, '', 0);
2356 $this->currentFont = $nf;
2357 $this->currentFontNum = $this->fonts[$nf]['fontNum'];
2358 }
2359 else
2360 {
2361 // the this font must not have the right family member for the current state
2362 // simply assume the base font
2363 $this->currentFont = $this->currentBaseFont;
2364 $this->currentFontNum = $this->fonts[$this->currentFont]['fontNum'];
2365 }
2366 }
2367
2373 {
2374 return $this->firstPageId;
2375 }
2376
2382 function addContent($content)
2383 {
2384 $this->objects[$this->currentContents]['c'] .= $content;
2385 }
2386
2390 function setColor($r, $g, $b, $force = 0)
2391 {
2392 if ($r >= 0 && ($force || $r != $this->currentColour['r'] || $g != $this->currentColour['g']
2393 || $b != $this->currentColour['b']))
2394 {
2395 $this->objects[$this->currentContents]['c'] .= "\n" . __sprintf('%.3f',
2396 $r) . ' ' . __sprintf('%.3f',
2397 $g) . ' '
2398 . __sprintf('%.3f', $b) . ' rg';
2399 $this->currentColour = array
2400 (
2401 'r' => $r,
2402 'g' => $g,
2403 'b' => $b
2404 );
2405 }
2406 }
2407
2411 function setStrokeColor($r, $g, $b, $force = 0)
2412 {
2413 if ($r >= 0 && ($force || $r != $this->currentStrokeColour['r'] || $g != $this->currentStrokeColour['g']
2414 || $b != $this->currentStrokeColour['b']))
2415 {
2416 $this->objects[$this->currentContents]['c'] .= "\n" . __sprintf('%.3f',
2417 $r) . ' ' . __sprintf('%.3f',
2418 $g) . ' '
2419 . __sprintf('%.3f', $b) . ' RG';
2420 $this->currentStrokeColour = array
2421 (
2422 'r' => $r,
2423 'g' => $g,
2424 'b' => $b
2425 );
2426 }
2427 }
2428
2432 function line($x1, $y1, $x2, $y2)
2433 {
2434 $this->objects[$this->currentContents]['c'] .= "\n" . __sprintf('%.3f',
2435 $x1) . ' ' . __sprintf('%.3f',
2436 $y1) . ' m '
2437 . __sprintf('%.3f',
2438 $x2) . ' ' . __sprintf('%.3f', $y2) . ' l S';
2439 }
2440
2444 function curve($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3)
2445 {
2446 // in the current line style, draw a bezier curve from (x0,y0) to (x3,y3) using the other two points
2447 // as the control points for the curve.
2448 $this->objects[$this->currentContents]['c'] .= "\n" . __sprintf('%.3f',
2449 $x0) . ' ' . __sprintf('%.3f',
2450 $y0) . ' m '
2451 . __sprintf('%.3f', $x1) . ' ' . __sprintf('%.3f', $y1);
2452 $this->objects[$this->currentContents]['c'] .= ' ' . __sprintf('%.3f',
2453 $x2) . ' ' . __sprintf('%.3f',
2454 $y2) . ' '
2455 . __sprintf('%.3f',
2456 $x3) . ' ' . __sprintf('%.3f', $y3) . ' c S';
2457 }
2458
2462 function partEllipse($x0, $y0, $astart, $afinish, $r1, $r2 = 0, $angle = 0, $nSeg = 8)
2463 {
2464 $this->ellipse($x0, $y0, $r1, $r2, $angle, $nSeg, $astart, $afinish, 0);
2465 }
2466
2470 function filledEllipse($x0, $y0, $r1, $r2 = 0, $angle = 0, $nSeg = 8, $astart = 0, $afinish = 360)
2471 {
2472 return $this->ellipse($x0, $y0, $r1, $r2 = 0, $angle, $nSeg, $astart, $afinish, 1, 1);
2473 }
2474
2485 function ellipse($x0, $y0, $r1, $r2 = 0, $angle = 0, $nSeg = 8, $astart = 0, $afinish = 360, $close = 1, $fill = 0)
2486 {
2487 if ($r1 == 0)
2488 {
2489 return;
2490 }
2491
2492 if ($r2 == 0)
2493 {
2494 $r2 = $r1;
2495 }
2496
2497 if ($nSeg < 2)
2498 {
2499 $nSeg = 2;
2500 }
2501
2502 $astart = deg2rad((float)$astart);
2503 $afinish = deg2rad((float)$afinish);
2504 $totalAngle = $afinish - $astart;
2505
2506 $dt = $totalAngle / $nSeg;
2507 $dtm = $dt / 3;
2508
2509 if ($angle != 0)
2510 {
2511 $a = -1 * deg2rad((float)$angle);
2512 $tmp = "\n q ";
2513 $tmp .= __sprintf('%.3f',
2514 cos($a)) . ' ' . __sprintf('%.3f',
2515 (-1.0 * sin($a))) . ' ' . __sprintf('%.3f',
2516 sin($a)) . ' '
2517 . __sprintf('%.3f', cos($a)) . ' ';
2518 $tmp .= __sprintf('%.3f', $x0) . ' ' . __sprintf('%.3f', $y0) . ' cm';
2519 $this->objects[$this->currentContents]['c'] .= $tmp;
2520 $x0 = 0;
2521 $y0 = 0;
2522 }
2523
2524 $t1 = $astart;
2525 $a0 = $x0 + $r1 * cos($t1);
2526 $b0 = $y0 + $r2 * sin($t1);
2527 $c0 = -$r1 * sin($t1);
2528 $d0 = $r2 * cos($t1);
2529
2530 $this->objects[$this->currentContents]['c'] .= "\n" . __sprintf('%.3f',
2531 $a0) . ' ' . __sprintf('%.3f', $b0) . ' m ';
2532
2533 for ($i = 1; $i <= $nSeg; $i++)
2534 {
2535 // draw this bit of the total curve
2536 $t1 = $i * $dt + $astart;
2537 $a1 = $x0 + $r1 * cos($t1);
2538 $b1 = $y0 + $r2 * sin($t1);
2539 $c1 = -$r1 * sin($t1);
2540 $d1 = $r2 * cos($t1);
2541 $this->objects[$this->currentContents]['c'] .= "\n" . __sprintf('%.3f',
2542 ($a0 + $c0 * $dtm)) . ' ' . __sprintf(
2543 '%.3f',
2544 ($b0 + $d0
2545 * $dtm));
2546 $this->objects[$this->currentContents]['c'] .= ' ' . __sprintf('%.3f',
2547 ($a1 - $c1 * $dtm)) . ' ' . __sprintf(
2548 '%.3f',
2549 ($b1 - $d1
2550 * $dtm))
2551 . ' ' . __sprintf(
2552 '%.3f',
2553 $a1) . ' ' . __sprintf('%.3f', $b1) . ' c';
2554 $a0 = $a1;
2555 $b0 = $b1;
2556 $c0 = $c1;
2557 $d0 = $d1;
2558 }
2559
2560 if ($fill)
2561 {
2562 $this->objects[$this->currentContents]['c'] .= ' f';
2563 }
2564 else
2565 {
2566 if ($close)
2567 {
2568 $this->objects[$this->currentContents]['c'] .= ' s'; // small 's' signifies closing the path as well
2569 }
2570 else
2571 {
2572 $this->objects[$this->currentContents]['c'] .= ' S';
2573 }
2574 }
2575
2576 if ($angle != 0)
2577 {
2578 $this->objects[$this->currentContents]['c'] .= ' Q';
2579 }
2580 }
2581
2595 function setLineStyle($width = 1, $cap = '', $join = '', $dash = '', $phase = 0)
2596 {
2597
2598 // this is quite inefficient in that it sets all the parameters whenever 1 is changed, but will fix another day
2599 $string = '';
2600
2601 if ($width > 0)
2602 {
2603 $string .= $width . ' w';
2604 }
2605
2606 $ca = array
2607 (
2608 'butt' => 0,
2609 'round' => 1,
2610 'square' => 2
2611 );
2612
2613 if (isset($ca[$cap]))
2614 {
2615 $string .= ' ' . $ca[$cap] . ' J';
2616 }
2617
2618 $ja = array
2619 (
2620 'miter' => 0,
2621 'round' => 1,
2622 'bevel' => 2
2623 );
2624
2625 if (isset($ja[$join]))
2626 {
2627 $string .= ' ' . $ja[$join] . ' j';
2628 }
2629
2630 if (is_array($dash))
2631 {
2632 $string .= ' [';
2633
2634 foreach ($dash as $len)
2635 {
2636 $string .= ' ' . $len;
2637 }
2638
2639 $string .= ' ] ' . $phase . ' d';
2640 }
2641
2642 $this->currentLineStyle = $string;
2643 $this->objects[$this->currentContents]['c'] .= "\n" . $string;
2644 }
2645
2649 function polygon($p, $np, $f = 0)
2650 {
2651 $this->objects[$this->currentContents]['c'] .= "\n";
2652 $this->objects[$this->currentContents]['c'] .= __sprintf('%.3f',
2653 $p[0]) . ' ' . __sprintf('%.3f', $p[1]) . ' m ';
2654
2655 for ($i = 2; $i < $np * 2; $i = $i + 2)
2656 {
2657 $this->objects[$this->currentContents]['c'] .= __sprintf('%.3f',
2658 $p[$i]) . ' ' . __sprintf('%.3f',
2659 $p[$i + 1]) . ' l ';
2660 }
2661
2662 if ($f == 1)
2663 {
2664 $this->objects[$this->currentContents]['c'] .= ' f';
2665 }
2666 else
2667 {
2668 $this->objects[$this->currentContents]['c'] .= ' S';
2669 }
2670 }
2671
2676 function filledRectangle($x1, $y1, $width, $height)
2677 {
2678 $this->objects[$this->currentContents]['c'] .= "\n" . __sprintf('%.3f',
2679 $x1) . ' ' . __sprintf('%.3f',
2680 $y1) . ' '
2681 . __sprintf('%.3f',
2682 $width) . ' ' . __sprintf('%.3f',
2683 $height) . ' re f';
2684 }
2685
2690 function rectangle($x1, $y1, $width, $height)
2691 {
2692 $this->objects[$this->currentContents]['c'] .= "\n" . __sprintf('%.3f',
2693 $x1) . ' ' . __sprintf('%.3f',
2694 $y1) . ' '
2695 . __sprintf('%.3f',
2696 $width) . ' ' . __sprintf('%.3f',
2697 $height) . ' re S';
2698 }
2699
2704 function newPage($insert = 0, $id = 0, $pos = 'after')
2705 {
2706
2707 // if there is a state saved, then go up the stack closing them
2708 // then on the new page, re-open them with the right setings
2709
2710 if ($this->nStateStack)
2711 {
2712 for ($i = $this->nStateStack; $i >= 1; $i--)
2713 {
2714 $this->restoreState($i);
2715 }
2716 }
2717
2718 $this->numObj++;
2719
2720 if ($insert)
2721 {
2722 // the id from the ezPdf class is the od of the contents of the page, not the page object itself
2723 // query that object to find the parent
2724 $rid = $this->objects[$id]['onPage'];
2725 $opt = array
2726 (
2727 'rid' => $rid,
2728 'pos' => $pos
2729 );
2730
2731 $this->o_page($this->numObj, 'new', $opt);
2732 }
2733 else
2734 {
2735 $this->o_page($this->numObj, 'new');
2736 }
2737
2738 // if there is a stack saved, then put that onto the page
2739 if ($this->nStateStack)
2740 {
2741 for ($i = 1; $i <= $this->nStateStack; $i++)
2742 {
2743 $this->saveState($i);
2744 }
2745 }
2746
2747 // and if there has been a stroke or fill colour set, then transfer them
2748 if ($this->currentColour['r'] >= 0)
2749 {
2750 $this->setColor($this->currentColour['r'], $this->currentColour['g'], $this->currentColour['b'], 1);
2751 }
2752
2753 if ($this->currentStrokeColour['r'] >= 0)
2754 {
2755 $this->setStrokeColor($this->currentStrokeColour['r'], $this->currentStrokeColour['g'],
2756 $this->currentStrokeColour['b'], 1);
2757 }
2758
2759 // if there is a line style set, then put this in too
2760 if (strlen($this->currentLineStyle))
2761 {
2762 $this->objects[$this->currentContents]['c'] .= "\n" . $this->currentLineStyle;
2763 }
2764
2765 // the call to the o_page object set currentContents to the present page, so this can be returned as the page id
2766 return $this->currentContents;
2767 }
2768
2773 function stream($options = '')
2774 {
2775 // setting the options allows the adjustment of the headers
2776 // values at the moment are:
2777 // 'Content-Disposition'=>'filename' - sets the filename, though not too sure how well this will
2778 // work as in my trial the browser seems to use the filename of the php file with .pdf on the end
2779 // 'Accept-Ranges'=>1 or 0 - if this is not set to 1, then this header is not included, off by default
2780 // this header seems to have caused some problems despite tha fact that it is supposed to solve
2781 // them, so I am leaving it off by default.
2782 // 'compress'=> 1 or 0 - apply content stream compression, this is on (1) by default
2783 if (!is_array($options))
2784 {
2785 $options = array(
2786 );
2787 }
2788
2789 if (isset($options['compress']) && $options['compress'] == 0)
2790 {
2791 $tmp = $this->output(1);
2792 }
2793 else
2794 {
2795 $tmp = $this->output();
2796 }
2797
2798 header("Content-type: application/pdf");
2799 header("Content-Length: " . strlen(ltrim($tmp)));
2800 $fileName = (isset($options['Content-Disposition']) ? $options['Content-Disposition'] : 'file.pdf');
2801 header("Content-Disposition: inline; filename=" . $fileName);
2802
2803 if (isset($options['Accept-Ranges']) && $options['Accept-Ranges'] == 1)
2804 {
2805 header("Accept-Ranges: " . strlen(ltrim($tmp)));
2806 }
2807
2808 echo ltrim($tmp);
2809 }
2810
2814 function getFontHeight($size)
2815 {
2816 if (!$this->numFonts)
2817 {
2818 $this->selectFont($this->fonts_path . '/Helvetica');
2819 }
2820
2821 // for the current font, and the given size, what is the height of the font in user units
2822 $h = $this->fonts[$this->currentFont]['FontBBox'][3] - $this->fonts[$this->currentFont]['FontBBox'][1];
2823 return $size * $h / 1000;
2824 }
2825
2831 function getFontDecender($size)
2832 {
2833 // note that this will most likely return a negative value
2834 if (!$this->numFonts)
2835 {
2836 $this->selectFont($this->fonts_path . '/Helvetica');
2837 }
2838
2839 $h = $this->fonts[$this->currentFont]['FontBBox'][1];
2840 return $size * $h / 1000;
2841 }
2842
2849 function filterText($text)
2850 {
2851 $text = str_replace('\\', '\\\\', $text);
2852 $text = str_replace('(', '\‍(', $text);
2853 $text = str_replace(')', '\‍)', $text);
2854 $text = str_replace('&lt;', '<', $text);
2855 $text = str_replace('&gt;', '>', $text);
2856 $text = str_replace('&#039;', '\'', $text);
2857 $text = str_replace('&quot;', '"', $text);
2858 $text = str_replace('&amp;', '&', $text);
2859
2860 return $text;
2861 }
2862
2869 function PRVTgetTextPosition($x, $y, $angle, $size, $wa, $text)
2870 {
2871 // given this information return an array containing x and y for the end position as elements 0 and 1
2872 $w = $this->getTextWidth($size, $text);
2873 // need to adjust for the number of spaces in this text
2874 $words = explode(' ', $text);
2875 $nspaces = count($words) - 1;
2876 $w += $wa * $nspaces;
2877 $a = deg2rad((float)$angle);
2878 return array(cos($a) * $w + $x, -sin($a) * $w + $y);
2879 }
2880
2886 function PRVTcheckTextDirective(&$text, $i, &$f)
2887 {
2888 $x = 0;
2889 $y = 0;
2890 return $this->PRVTcheckTextDirective1($text, $i, $f, 0, $x, $y);
2891 }
2892
2902 function PRVTcheckTextDirective1(&$text, $i, &$f, $final, &$x, &$y, $size = 0, $angle = 0, $wordSpaceAdjust = 0)
2903 {
2904 $directive = 0;
2905 $j = $i;
2906
2907 if ($text[$j] == '<')
2908 {
2909 $j++;
2910
2911 switch ($text[$j])
2912 {
2913 case '/':
2914 $j++;
2915
2916 if (strlen($text) <= $j)
2917 {
2918 return $directive;
2919 }
2920
2921 switch ($text[$j])
2922 {
2923 case 'b':
2924 case 'i':
2925 $j++;
2926
2927 if ($text[$j] == '>')
2928 {
2929 $p = strrpos($this->currentTextState, $text[$j - 1]);
2930
2931 if ($p !== false)
2932 {
2933 // then there is one to remove
2934 $this->currentTextState = substr($this->currentTextState, 0,
2935 $p) . substr($this->currentTextState, $p + 1);
2936 }
2937
2938 $directive = $j - $i + 1;
2939 }
2940
2941 break;
2942
2943 case 'c':
2944 // this this might be a callback function
2945 $j++;
2946
2947 $k = strpos($text, '>', $j);
2948
2949 if ($k !== false && $text[$j] == ':')
2950 {
2951 // then this will be treated as a callback directive
2952 $directive = $k - $i + 1;
2953 $f = 0;
2954 // split the remainder on colons to get the function name and the paramater
2955 $tmp = substr($text, $j + 1, $k - $j - 1);
2956 $b1 = strpos($tmp, ':');
2957
2958 if ($b1 !== false)
2959 {
2960 $func = substr($tmp, 0, $b1);
2961 $parm = substr($tmp, $b1 + 1);
2962 }
2963 else
2964 {
2965 $func = $tmp;
2966 $parm = '';
2967 }
2968
2969 if (!isset($func) || !strlen(trim($func)))
2970 {
2971 $directive = 0;
2972 }
2973 else
2974 {
2975 // only call the function if this is the final call
2976 if ($final)
2977 {
2978 // need to assess the text position, calculate the text width to this point
2979 // can use getTextWidth to find the text width I think
2980 $tmp = $this->PRVTgetTextPosition(
2981 $x, $y, $angle, $size, $wordSpaceAdjust, substr($text, 0, $i));
2982 $info = array
2983 (
2984 'x' => $tmp[0],
2985 'y' => $tmp[1],
2986 'angle' => $angle,
2987 'status' => 'end',
2988 'p' => $parm,
2989 'nCallback' => $this->nCallback
2990 );
2991
2992 $x = $tmp[0];
2993 $y = $tmp[1];
2994 $ret = $this->$func($info);
2995
2996 if (is_array($ret))
2997 {
2998 // then the return from the callback function could set the position, to start with, later will do font colour, and font
2999 foreach ($ret as $rk => $rv)
3000 {
3001 switch ($rk)
3002 {
3003 case 'x':
3004 case 'y':
3005 $$rk = $rv;
3006
3007 break;
3008 }
3009 }
3010 }
3011
3012 // also remove from to the stack
3013 // for simplicity, just take from the end, fix this another day
3014 $this->nCallback--;
3015
3016 if ($this->nCallback < 0)
3017 {
3018 $this->nCallBack = 0;
3019 }
3020 }
3021 }
3022 }
3023
3024 break;
3025 }
3026
3027 break;
3028
3029 case 'b':
3030 case 'i':
3031 $j++;
3032
3033 if ($text[$j] == '>')
3034 {
3035 $this->currentTextState .= $text[$j - 1];
3036 $directive = $j - $i + 1;
3037 }
3038
3039 break;
3040
3041 case 'C': $noClose = 1;
3042
3043 case 'c':
3044 // this this might be a callback function
3045 $j++;
3046
3047 $k = strpos($text, '>', $j);
3048
3049 if ($k !== false && $text[$j] == ':')
3050 {
3051 // then this will be treated as a callback directive
3052 $directive = $k - $i + 1;
3053 $f = 0;
3054 // split the remainder on colons to get the function name and the paramater
3055 // $bits = explode(':',substr($text,$j+1,$k-$j-1));
3056 $tmp = substr($text, $j + 1, $k - $j - 1);
3057 $b1 = strpos($tmp, ':');
3058
3059 if ($b1 !== false)
3060 {
3061 $func = substr($tmp, 0, $b1);
3062 $parm = substr($tmp, $b1 + 1);
3063 }
3064 else
3065 {
3066 $func = $tmp;
3067 $parm = '';
3068 }
3069
3070 if (!isset($func) || !strlen(trim($func)))
3071 {
3072 $directive = 0;
3073 }
3074 else
3075 {
3076 // only call the function if this is the final call, ie, the one actually doing printing, not measurement
3077 if ($final)
3078 {
3079 // need to assess the text position, calculate the text width to this point
3080 // can use getTextWidth to find the text width I think
3081 // also add the text height and decender
3082 $tmp = $this->PRVTgetTextPosition($x, $y, $angle, $size, $wordSpaceAdjust,
3083 substr($text, 0, $i));
3084 $info = array
3085 (
3086 'x' => $tmp[0],
3087 'y' => $tmp[1],
3088 'angle' => $angle,
3089 'status' => 'start',
3090 'p' => $parm,
3091 'f' => $func,
3092 'height' => $this->getFontHeight($size),
3093 'decender' => $this->getFontDecender($size)
3094 );
3095
3096 $x = $tmp[0];
3097 $y = $tmp[1];
3098
3099 if (!isset($noClose) || !$noClose)
3100 {
3101 // only add to the stack if this is a small 'c', therefore is a start-stop pair
3102 $this->nCallback++;
3103 $info['nCallback'] = $this->nCallback;
3104 $this->callback[$this->nCallback] = $info;
3105 }
3106
3107 $ret = $this->$func($info);
3108
3109 if (is_array($ret))
3110 {
3111 // then the return from the callback function could set the position, to start with, later will do font colour, and font
3112 foreach ($ret as $rk => $rv)
3113 {
3114 switch ($rk)
3115 {
3116 case 'x':
3117 case 'y':
3118 $$rk = $rv;
3119
3120 break;
3121 }
3122 }
3123 }
3124 }
3125 }
3126 }
3127
3128 break;
3129 }
3130 }
3131
3132 return $directive;
3133 }
3134
3138 function addText($x, $y, $size, $text, $angle = 0, $wordSpaceAdjust = 0)
3139 {
3140 if (!$this->numFonts)
3141 {
3142 $this->selectFont($this->fonts_path . '/Helvetica');
3143 }
3144
3145 // if there are any open callbacks, then they should be called, to show the start of the line
3146 if ($this->nCallback > 0)
3147 {
3148 for ($i = $this->nCallback; $i > 0; $i--)
3149 {
3150 // call each function
3151 $info = array
3152 (
3153 'x' => $x,
3154 'y' => $y,
3155 'angle' => $angle,
3156 'status' => 'sol',
3157 'p' => $this->callback[$i]['p'],
3158 'nCallback' => $this->callback[$i]['nCallback'],
3159 'height' => $this->callback[$i]['height'],
3160 'decender' => $this->callback[$i]['decender']
3161 );
3162
3163 $func = $this->callback[$i]['f'];
3164 $this->$func($info);
3165 }
3166 }
3167
3168 if ($angle == 0)
3169 {
3170 $this->objects[$this->currentContents]['c'] .= "\n" . 'BT ' . __sprintf('%.3f',
3171 $x) . ' ' . __sprintf('%.3f',
3172 $y) . ' Td';
3173 }
3174 else
3175 {
3176 $a = deg2rad((float)$angle);
3177 $tmp = "\n" . 'BT ';
3178 $tmp .= __sprintf('%.3f',
3179 cos($a)) . ' ' . __sprintf('%.3f',
3180 (-1.0 * sin($a))) . ' ' . __sprintf('%.3f',
3181 sin($a)) . ' '
3182 . __sprintf('%.3f', cos($a)) . ' ';
3183 $tmp .= __sprintf('%.3f', $x) . ' ' . __sprintf('%.3f', $y) . ' Tm';
3184 $this->objects[$this->currentContents]['c'] .= $tmp;
3185 }
3186
3187 if ($wordSpaceAdjust != 0 || $wordSpaceAdjust != $this->wordSpaceAdjust)
3188 {
3189 $this->wordSpaceAdjust = $wordSpaceAdjust;
3190 $this->objects[$this->currentContents]['c'] .= ' ' . __sprintf('%.3f', $wordSpaceAdjust) . ' Tw';
3191 }
3192
3193 $len = strlen($text);
3194 $start = 0;
3195
3196 for ($i = 0; $i < $len; $i++)
3197 {
3198 $f = 1;
3199 $directive = $this->PRVTcheckTextDirective($text, $i, $f);
3200
3201 if ($directive)
3202 {
3203 // then we should write what we need to
3204 if ($i > $start)
3205 {
3206 $part = substr($text, $start, $i - $start);
3207 $this->objects[$this->currentContents]['c']
3208 .= ' /F' . $this->currentFontNum . ' ' . __sprintf('%.1f', $size) . ' Tf ';
3209 $this->objects[$this->currentContents]['c'] .= ' (' . $this->filterText($part) . ') Tj';
3210 }
3211
3212 if ($f)
3213 {
3214 // then there was nothing drastic done here, restore the contents
3215 $this->setCurrentFont();
3216 }
3217 else
3218 {
3219 $this->objects[$this->currentContents]['c'] .= ' ET';
3220 $f = 1;
3221 $xp = $x;
3222 $yp = $y;
3223 $directive = $this->PRVTcheckTextDirective1(
3224 $text, $i, $f, 1, $xp, $yp, $size, $angle, $wordSpaceAdjust);
3225
3226 // restart the text object
3227 if ($angle == 0)
3228 {
3229 $this->objects[$this->currentContents]['c'] .= "\n" . 'BT ' . __sprintf('%.3f',
3230 $xp) . ' '
3231 . __sprintf('%.3f', $yp) . ' Td';
3232 }
3233 else
3234 {
3235 $a = deg2rad((float)$angle);
3236 $tmp = "\n" . 'BT ';
3237 $tmp .= __sprintf('%.3f',
3238 cos($a)) . ' ' . __sprintf('%.3f',
3239 (-1.0 * sin($a))) . ' ' . __sprintf('%.3f',
3240 sin($a)) . ' '
3241 . __sprintf('%.3f', cos($a)) . ' ';
3242 $tmp .= __sprintf('%.3f', $xp) . ' ' . __sprintf('%.3f', $yp) . ' Tm';
3243 $this->objects[$this->currentContents]['c'] .= $tmp;
3244 }
3245
3246 if ($wordSpaceAdjust != 0 || $wordSpaceAdjust != $this->wordSpaceAdjust)
3247 {
3248 $this->wordSpaceAdjust = $wordSpaceAdjust;
3249 $this->objects[$this->currentContents]['c'] .= ' ' . __sprintf('%.3f',
3250 $wordSpaceAdjust) . ' Tw';
3251 }
3252 }
3253
3254 // and move the writing point to the next piece of text
3255 $i = $i + $directive - 1;
3256 $start = $i + 1;
3257 }
3258 }
3259
3260 if ($start < $len)
3261 {
3262 $part = substr($text, $start);
3263 $this->objects[$this->currentContents]['c'] .= ' /F' . $this->currentFontNum . ' ' . __sprintf('%.1f',
3264 $size)
3265 . ' Tf ';
3266 $this->objects[$this->currentContents]['c'] .= ' (' . $this->filterText($part) . ') Tj';
3267 }
3268
3269 $this->objects[$this->currentContents]['c'] .= ' ET';
3270
3271 // if there are any open callbacks, then they should be called, to show the end of the line
3272 if ($this->nCallback > 0)
3273 {
3274 for ($i = $this->nCallback; $i > 0; $i--)
3275 {
3276 // call each function
3277 $tmp = $this->PRVTgetTextPosition($x, $y, $angle, $size, $wordSpaceAdjust, $text);
3278 $info = array
3279 (
3280 'x' => $tmp[0],
3281 'y' => $tmp[1],
3282 'angle' => $angle,
3283 'status' => 'eol',
3284 'p' => $this->callback[$i]['p'],
3285 'nCallback' => $this->callback[$i]['nCallback'],
3286 'height' => $this->callback[$i]['height'],
3287 'decender' => $this->callback[$i]['decender']
3288 );
3289
3290 $func = $this->callback[$i]['f'];
3291 $this->$func($info);
3292 }
3293 }
3294 }
3295
3300 function getTextWidth($size, $text)
3301 {
3302 // this function should not change any of the settings, though it will need to
3303 // track any directives which change during calculation, so copy them at the start
3304 // and put them back at the end.
3305 $store_currentTextState = $this->currentTextState;
3306
3307 if (!$this->numFonts)
3308 {
3309 $this->selectFont($this->fonts_path . '/Helvetica');
3310 }
3311
3312 // converts a number or a float to a string so it can get the width
3313 $text = "$text";
3314
3315 // hmm, this is where it all starts to get tricky - use the font information to
3316 // calculate the width of each character, add them up and convert to user units
3317 $w = 0;
3318 $len = strlen($text);
3319 $cf = $this->currentFont;
3320
3321 for ($i = 0; $i < $len; $i++)
3322 {
3323 $f = 1;
3324 $directive = $this->PRVTcheckTextDirective($text, $i, $f);
3325
3326 if ($directive)
3327 {
3328 if ($f)
3329 {
3330 $this->setCurrentFont();
3331 $cf = $this->currentFont;
3332 }
3333
3334 $i = $i + $directive - 1;
3335 }
3336 else
3337 {
3338 $char = ord($text[$i]);
3339
3340 if (isset($this->fonts[$cf]['differences'][$char]))
3341 {
3342 // then this character is being replaced by another
3343 $name = $this->fonts[$cf]['differences'][$char];
3344
3345 if (isset($this->fonts[$cf]['C'][$name]['WX']))
3346 {
3347 $w += $this->fonts[$cf]['C'][$name]['WX'];
3348 }
3349 }
3350 else if (isset($this->fonts[$cf]['C'][$char]['WX']))
3351 {
3352 $w += $this->fonts[$cf]['C'][$char]['WX'];
3353 }
3354 }
3355 }
3356
3357 $this->currentTextState = $store_currentTextState;
3358 $this->setCurrentFont();
3359
3360 return $w * $size / 1000;
3361 }
3362
3368 function PRVTadjustWrapText($text, $actual, $width, &$x, &$adjust, $justification)
3369 {
3370 switch ($justification)
3371 {
3372 case 'left':
3373 return;
3374
3375 break;
3376
3377 case 'right':
3378 $x += $width - $actual;
3379
3380 break;
3381
3382 case 'center':
3383 case 'centre':
3384 $x += ($width - $actual) / 2;
3385
3386 break;
3387
3388 case 'full':
3389 // count the number of words
3390 $words = explode(' ', $text);
3391
3392 $nspaces = count($words) - 1;
3393
3394 if ($nspaces > 0)
3395 {
3396 $adjust = ($width - $actual) / $nspaces;
3397 }
3398 else
3399 {
3400 $adjust = 0;
3401 }
3402
3403 break;
3404 }
3405 }
3406
3413 function addTextWrap($x, $y, $width, $size, $text, $justification = 'left', $angle = 0, $test = 0)
3414 {
3415 // this will display the text, and if it goes beyond the width $width, will backtrack to the
3416 // previous space or hyphen, and return the remainder of the text.
3417
3418 // $justification can be set to 'left','right','center','centre','full'
3419
3420 // need to store the initial text state, as this will change during the width calculation
3421 // but will need to be re-set before printing, so that the chars work out right
3422 $store_currentTextState = $this->currentTextState;
3423
3424 if (!$this->numFonts)
3425 {
3426 $this->selectFont($this->fonts_path . '/Helvetica');
3427 }
3428
3429 if ($width <= 0)
3430 {
3431 // error, pretend it printed ok, otherwise risking a loop
3432 return '';
3433 }
3434
3435 $w = 0;
3436 $break = 0;
3437 $breakWidth = 0;
3438 $len = strlen($text);
3439 $cf = $this->currentFont;
3440 $tw = $width / $size * 1000;
3441
3442 for ($i = 0; $i < $len; $i++)
3443 {
3444 $f = 1;
3445 $directive = $this->PRVTcheckTextDirective($text, $i, $f);
3446
3447 if ($directive)
3448 {
3449 if ($f)
3450 {
3451 $this->setCurrentFont();
3452 $cf = $this->currentFont;
3453 }
3454
3455 $i = $i + $directive - 1;
3456 }
3457 else
3458 {
3459 $cOrd = ord($text[$i]);
3460
3461 if (isset($this->fonts[$cf]['differences'][$cOrd]))
3462 {
3463 // then this character is being replaced by another
3464 $cOrd2 = $this->fonts[$cf]['differences'][$cOrd];
3465 }
3466 else
3467 {
3468 $cOrd2 = $cOrd;
3469 }
3470
3471 if (isset($this->fonts[$cf]['C'][$cOrd2]['WX']))
3472 {
3473 $w += $this->fonts[$cf]['C'][$cOrd2]['WX'];
3474 }
3475
3476 if ($w > $tw)
3477 {
3478 // then we need to truncate this line
3479 if ($break > 0)
3480 {
3481 // then we have somewhere that we can split :)
3482 if ($text[$break] == ' ')
3483 {
3484 $tmp = substr($text, 0, $break);
3485 }
3486 else
3487 {
3488 $tmp = substr($text, 0, $break + 1);
3489 }
3490
3491 $adjust = 0;
3492 $this->PRVTadjustWrapText($tmp, $breakWidth, $width, $x, $adjust, $justification);
3493
3494 // reset the text state
3495 $this->currentTextState = $store_currentTextState;
3496 $this->setCurrentFont();
3497
3498 if (!$test)
3499 {
3500 $this->addText($x, $y, $size, $tmp, $angle, $adjust);
3501 }
3502
3503 return substr($text, $break + 1);
3504 }
3505 else
3506 {
3507 // just split before the current character
3508 $tmp = substr($text, 0, $i);
3509 $adjust = 0;
3510 $ctmp = ord($text[$i]);
3511
3512 if (isset($this->fonts[$cf]['differences'][$ctmp]))
3513 {
3514 $ctmp = $this->fonts[$cf]['differences'][$ctmp];
3515 }
3516
3517 $tmpw = ($w - $this->fonts[$cf]['C'][$ctmp]['WX']) * $size / 1000;
3518 $this->PRVTadjustWrapText($tmp, $tmpw, $width, $x, $adjust, $justification);
3519 // reset the text state
3520 $this->currentTextState = $store_currentTextState;
3521 $this->setCurrentFont();
3522
3523 if (!$test)
3524 {
3525 $this->addText($x, $y, $size, $tmp, $angle, $adjust);
3526 }
3527
3528 return substr($text, $i);
3529 }
3530 }
3531
3532 if ($text[$i] == '-')
3533 {
3534 $break = $i;
3535 $breakWidth = $w * $size / 1000;
3536 }
3537
3538 if ($text[$i] == ' ')
3539 {
3540 $break = $i;
3541 $ctmp = ord($text[$i]);
3542
3543 if (isset($this->fonts[$cf]['differences'][$ctmp]))
3544 {
3545 $ctmp = $this->fonts[$cf]['differences'][$ctmp];
3546 }
3547
3548 $breakWidth = ($w - $this->fonts[$cf]['C'][$ctmp]['WX']) * $size / 1000;
3549 }
3550 }
3551 }
3552
3553 // then there was no need to break this line
3554 if ($justification == 'full')
3555 {
3556 $justification = 'left';
3557 }
3558
3559 $adjust = 0;
3560 $tmpw = $w * $size / 1000;
3561 //echo "text=$text tmpw=$tmpw<br>";
3562 $this->PRVTadjustWrapText($text, $tmpw, $width, $x, $adjust, $justification);
3563 // reset the text state
3564 $this->currentTextState = $store_currentTextState;
3565 $this->setCurrentFont();
3566
3567 if (!$test)
3568 {
3569 $this->addText($x, $y, $size, $text, $angle, $adjust, $angle);
3570 }
3571
3572 return '';
3573 }
3574
3581 function saveState($pageEnd = 0)
3582 {
3583 if ($pageEnd)
3584 {
3585 // this will be called at a new page to return the state to what it was on the
3586 // end of the previous page, before the stack was closed down
3587 // This is to get around not being able to have open 'q' across pages
3588 $opt = $this->stateStack[$pageEnd]; // ok to use this as stack starts numbering at 1
3589 $this->setColor($opt['col']['r'], $opt['col']['g'], $opt['col']['b'], 1);
3590 $this->setStrokeColor($opt['str']['r'], $opt['str']['g'], $opt['str']['b'], 1);
3591 $this->objects[$this->currentContents]['c'] .= "\n" . $opt['lin'];
3592 // $this->currentLineStyle = $opt['lin'];
3593 }
3594 else
3595 {
3596 $this->nStateStack++;
3597 $this->stateStack[$this->nStateStack] = array
3598 (
3599 'col' => $this->currentColour,
3600 'str' => $this->currentStrokeColour,
3601 'lin' => $this->currentLineStyle
3602 );
3603 }
3604
3605 $this->objects[$this->currentContents]['c'] .= "\nq";
3606 }
3607
3611 function restoreState($pageEnd = 0)
3612 {
3613 if (!$pageEnd)
3614 {
3615 $n = $this->nStateStack;
3616 $this->currentColour = $this->stateStack[$n]['col'];
3617 $this->currentStrokeColour = $this->stateStack[$n]['str'];
3618 $this->objects[$this->currentContents]['c'] .= "\n" . $this->stateStack[$n]['lin'];
3619 $this->currentLineStyle = $this->stateStack[$n]['lin'];
3620 unset($this->stateStack[$n]);
3621 $this->nStateStack--;
3622 }
3623
3624 $this->objects[$this->currentContents]['c'] .= "\nQ";
3625 }
3626
3633 function openObject()
3634 {
3635 $this->nStack++;
3636 $this->stack[$this->nStack] = array
3637 (
3638 'c' => $this->currentContents,
3639 'p' => $this->currentPage
3640 );
3641
3642 // add a new object of the content type, to hold the data flow
3643 $this->numObj++;
3644 $this->o_contents($this->numObj, 'new');
3645 $this->currentContents = $this->numObj;
3646 $this->looseObjects[$this->numObj] = 1;
3647
3648 return $this->numObj;
3649 }
3650
3655 {
3656 $this->nStack++;
3657 $this->stack[$this->nStack] = array
3658 (
3659 'c' => $this->currentContents,
3660 'p' => $this->currentPage
3661 );
3662
3663 $this->currentContents = $id;
3664
3665 // also if this object is the primary contents for a page, then set the current page to its parent
3666 if (isset($this->objects[$id]['onPage']))
3667 {
3668 $this->currentPage = $this->objects[$id]['onPage'];
3669 }
3670 }
3671
3675 function closeObject()
3676 {
3677 // close the object, as long as there was one open in the first place, which will be indicated by
3678 // an objectId on the stack.
3679 if ($this->nStack > 0)
3680 {
3681 $this->currentContents = $this->stack[$this->nStack]['c'];
3682 $this->currentPage = $this->stack[$this->nStack]['p'];
3683 $this->nStack--;
3684 // easier to probably not worry about removing the old entries, they will be overwritten
3685 // if there are new ones.
3686 }
3687 }
3688
3692 function stopObject($id)
3693 {
3694 // if an object has been appearing on pages up to now, then stop it, this page will
3695 // be the last one that could contian it.
3696 if (isset($this->addLooseObjects[$id]))
3697 {
3698 $this->addLooseObjects[$id] = '';
3699 }
3700 }
3701
3705 function addObject($id, $options = 'add')
3706 {
3707 // add the specified object to the page
3708 if (isset($this->looseObjects[$id]) && $this->currentContents != $id)
3709 {
3710 // then it is a valid object, and it is not being added to itself
3711 switch ($options)
3712 {
3713 case 'all':
3714 // then this object is to be added to this page (done in the next block) and
3715 // all future new pages.
3716 $this->addLooseObjects[$id] = 'all';
3717
3718 case 'add':
3719 if (isset($this->objects[$this->currentContents]['onPage']))
3720 {
3721 // then the destination contents is the primary for the page
3722 // (though this object is actually added to that page)
3723 $this->o_page($this->objects[$this->currentContents]['onPage'], 'content', $id);
3724 }
3725
3726 break;
3727
3728 case 'even':
3729 $this->addLooseObjects[$id] = 'even';
3730
3731 $pageObjectId = $this->objects[$this->currentContents]['onPage'];
3732
3733 if ($this->objects[$pageObjectId]['info']['pageNum'] % 2 == 0)
3734 {
3735 $this->addObject($id); // hacky huh :)
3736 }
3737
3738 break;
3739
3740 case 'odd':
3741 $this->addLooseObjects[$id] = 'odd';
3742
3743 $pageObjectId = $this->objects[$this->currentContents]['onPage'];
3744
3745 if ($this->objects[$pageObjectId]['info']['pageNum'] % 2 == 1)
3746 {
3747 $this->addObject($id); // hacky huh :)
3748 }
3749
3750 break;
3751
3752 case 'next':
3753 $this->addLooseObjects[$id] = 'all';
3754
3755 break;
3756
3757 case 'nexteven':
3758 $this->addLooseObjects[$id] = 'even';
3759
3760 break;
3761
3762 case 'nextodd':
3763 $this->addLooseObjects[$id] = 'odd';
3764
3765 break;
3766 }
3767 }
3768 }
3769
3773 function addInfo($label, $value = 0)
3774 {
3775 // this will only work if the label is one of the valid ones.
3776 // modify this so that arrays can be passed as well.
3777 // if $label is an array then assume that it is key=>value pairs
3778 // else assume that they are both scalar, anything else will probably error
3779 if (is_array($label))
3780 {
3781 foreach ($label as $l => $v)
3782 {
3783 $this->o_info($this->infoObject, $l, $v);
3784 }
3785 }
3786 else
3787 {
3788 $this->o_info($this->infoObject, $label, $value);
3789 }
3790 }
3791
3795 function setPreferences($label, $value = 0)
3796 {
3797 // this will only work if the label is one of the valid ones.
3798 if (is_array($label))
3799 {
3800 foreach ($label as $l => $v)
3801 {
3802 $this->o_catalog($this->catalogId, 'viewerPreferences', array($l => $v));
3803 }
3804 }
3805 else
3806 {
3807 $this->o_catalog($this->catalogId, 'viewerPreferences', array($label => $value));
3808 }
3809 }
3810
3816 function PRVT_getBytes(&$data, $pos, $num)
3817 {
3818 // return the integer represented by $num bytes from $pos within $data
3819 $ret = 0;
3820
3821 for ($i = 0; $i < $num; $i++)
3822 {
3823 $ret = $ret * 256;
3824 $ret += ord($data[$pos + $i]);
3825 }
3826
3827 return $ret;
3828 }
3829
3834 function addPngFromFile($file, $x, $y, $w = 0, $h = 0)
3835 {
3836 // read in a png file, interpret it, then add to the system
3837 $error = 0;
3838 $fp = @fopen($file, 'rb');
3839
3840 if ($fp)
3841 {
3842 $data = '';
3843
3844 while (!feof($fp))
3845 {
3846 $data .= fread($fp, 1024);
3847 }
3848
3849 fclose($fp);
3850 }
3851 else
3852 {
3853 $error = 1;
3854 $errormsg = 'trouble opening file: ' . $file;
3855 }
3856
3857 if (!$error)
3858 {
3859 $header = chr(137) . chr(80) . chr(78) . chr(71) . chr(13) . chr(10) . chr(26) . chr(10);
3860
3861 if (substr($data, 0, 8) != $header)
3862 {
3863 $error = 1;
3864 $errormsg = 'this file does not have a valid header';
3865 }
3866 }
3867
3868 if (!$error)
3869 {
3870 // set pointer
3871 $p = 8;
3872 $len = strlen($data);
3873 // cycle through the file, identifying chunks
3874 $haveHeader = 0;
3875 $info = array(
3876 );
3877
3878 $idata = '';
3879 $pdata = '';
3880
3881 while ($p < $len)
3882 {
3883 $chunkLen = $this->PRVT_getBytes($data, $p, 4);
3884 $chunkType = substr($data, $p + 4, 4);
3885 // echo $chunkType.' - '.$chunkLen.'<br>';
3886
3887 switch ($chunkType)
3888 {
3889 case 'IHDR':
3890 // this is where all the file information comes from
3891 $info['width'] = $this->PRVT_getBytes($data, $p + 8, 4);
3892
3893 $info['height'] = $this->PRVT_getBytes($data, $p + 12, 4);
3894 $info['bitDepth'] = ord($data[$p + 16]);
3895 $info['colorType'] = ord($data[$p + 17]);
3896 $info['compressionMethod'] = ord($data[$p + 18]);
3897 $info['filterMethod'] = ord($data[$p + 19]);
3898 $info['interlaceMethod'] = ord($data[$p + 20]);
3899 //print_r($info);
3900 $haveHeader = 1;
3901
3902 if ($info['compressionMethod'] != 0)
3903 {
3904 $error = 1;
3905 $errormsg = 'unsupported compression method';
3906 }
3907
3908 if ($info['filterMethod'] != 0)
3909 {
3910 $error = 1;
3911 $errormsg = 'unsupported filter method';
3912 }
3913
3914 break;
3915
3916 case 'PLTE':
3917 $pdata .= substr($data, $p + 8, $chunkLen);
3918
3919 break;
3920
3921 case 'IDAT':
3922 $idata .= substr($data, $p + 8, $chunkLen);
3923
3924 break;
3925
3926 case 'tRNS':
3927 //this chunk can only occur once and it must occur after the PLTE chunk and before IDAT chunk
3928 //print "tRNS found, color type = ".$info['colorType']."<BR>";
3929 $transparency = array(
3930 );
3931
3932 if ($info['colorType'] == 3)
3933 { // indexed color, rbg
3934 /* corresponding to entries in the plte chunk
3935 Alpha for palette index 0: 1 byte
3936 Alpha for palette index 1: 1 byte
3937 ...etc...
3938 */
3939 // there will be one entry for each palette entry. up until the last non-opaque entry.
3940 // set up an array, stretching over all palette entries which will be o (opaque) or 1 (transparent)
3941 $transparency['type'] = 'indexed';
3942 $numPalette = strlen($pdata) / 3;
3943 $trans = 0;
3944
3945 for ($i = $chunkLen; $i >= 0; $i--)
3946 {
3947 if (ord($data[$p + 8 + $i]) == 0)
3948 {
3949 $trans = $i;
3950 }
3951 }
3952
3953 $transparency['data'] = $trans;
3954 }
3955 elseif ($info['colorType'] == 0)
3956 { // grayscale
3957 /* corresponding to entries in the plte chunk
3958 Gray: 2 bytes, range 0 .. (2^bitdepth)-1
3959 */
3960 // $transparency['grayscale']=$this->PRVT_getBytes($data,$p+8,2); // g = grayscale
3961 $transparency['type'] = 'indexed';
3962 $transparency['data'] = ord($data[$p + 8 + 1]);
3963 }
3964 elseif ($info['colorType'] == 2)
3965 { // truecolor
3966 /* corresponding to entries in the plte chunk
3967 Red: 2 bytes, range 0 .. (2^bitdepth)-1
3968 Green: 2 bytes, range 0 .. (2^bitdepth)-1
3969 Blue: 2 bytes, range 0 .. (2^bitdepth)-1
3970 */
3971 $transparency['r'] = $this->PRVT_getBytes($data, $p + 8, 2); // r from truecolor
3972 $transparency['g'] = $this->PRVT_getBytes($data, $p + 10, 2); // g from truecolor
3973 $transparency['b'] = $this->PRVT_getBytes($data, $p + 12, 2); // b from truecolor
3974 }
3975 else
3976 {
3977 //unsupported transparency type
3978 }
3979
3980 // KS End new code
3981 break;
3982
3983 default: break;
3984 }
3985
3986 $p += $chunkLen + 12;
3987 }
3988
3989 if (!$haveHeader)
3990 {
3991 $error = 1;
3992 $errormsg = 'information header is missing';
3993 }
3994
3995 if (isset($info['interlaceMethod']) && $info['interlaceMethod'])
3996 {
3997 $error = 1;
3998 $errormsg = 'There appears to be no support for interlaced images in pdf.';
3999 }
4000 }
4001
4002 if (!$error && $info['bitDepth'] > 8)
4003 {
4004 $error = 1;
4005 $errormsg = 'only bit depth of 8 or less is supported';
4006 }
4007
4008 if (!$error)
4009 {
4010 if ($info['colorType'] != 2 && $info['colorType'] != 0 && $info['colorType'] != 3)
4011 {
4012 $error = 1;
4013 $errormsg
4014 = 'transparancey alpha channel not supported, transparency only supported for palette images.';
4015 }
4016 else
4017 {
4018 switch ($info['colorType'])
4019 {
4020 case 3:
4021 $color = 'DeviceRGB';
4022
4023 $ncolor = 1;
4024 break;
4025
4026 case 2:
4027 $color = 'DeviceRGB';
4028
4029 $ncolor = 3;
4030 break;
4031
4032 case 0:
4033 $color = 'DeviceGray';
4034
4035 $ncolor = 1;
4036 break;
4037 }
4038 }
4039 }
4040
4041 if ($error)
4042 {
4043 $this->addMessage('PNG error - (' . $file . ') ' . $errormsg);
4044 return;
4045 }
4046
4047 if ($w == 0)
4048 {
4049 $w = $h / $info['height'] * $info['width'];
4050 }
4051
4052 if ($h == 0)
4053 {
4054 $h = $w * $info['height'] / $info['width'];
4055 }
4056
4057 //print_r($info);
4058 // so this image is ok... add it in.
4059 $this->numImages++;
4060 $im = $this->numImages;
4061 $label = 'I' . $im;
4062 $this->numObj++;
4063 // $this->o_image($this->numObj,'new',array('label'=>$label,'data'=>$idata,'iw'=>$w,'ih'=>$h,'type'=>'png','ic'=>$info['width']));
4064 $options = array
4065 (
4066 'label' => $label,
4067 'data' => $idata,
4068 'bitsPerComponent' => $info['bitDepth'],
4069 'pdata' => $pdata,
4070 'iw' => $info['width'],
4071 'ih' => $info['height'],
4072 'type' => 'png',
4073 'color' => $color,
4074 'ncolor' => $ncolor
4075 );
4076
4077 if (isset($transparency))
4078 {
4079 $options['transparency'] = $transparency;
4080 }
4081
4082 $this->o_image($this->numObj, 'new', $options);
4083
4084 $this->objects[$this->currentContents]['c'] .= "\nq";
4085 $this->objects[$this->currentContents]['c'] .= "\n" . __sprintf('%.3f',
4086 $w) . " 0 0 " . __sprintf('%.3f',
4087 $h) . " "
4088 . __sprintf('%.3f',
4089 $x) . " " . __sprintf('%.3f', $y) . " cm";
4090 $this->objects[$this->currentContents]['c'] .= "\n/" . $label . ' Do';
4091 $this->objects[$this->currentContents]['c'] .= "\nQ";
4092 }
4093
4097 function addJpegFromFile($img, $x, $y, $w = 0, $h = 0)
4098 {
4099 // attempt to add a jpeg image straight from a file, using no GD commands
4100 // note that this function is unable to operate on a remote file.
4101
4102 if (!file_exists($img))
4103 {
4104 return;
4105 }
4106
4107 $tmp = getimagesize($img);
4108 $imageWidth = $tmp[0];
4109 $imageHeight = $tmp[1];
4110
4111 if (isset($tmp['channels']))
4112 {
4113 $channels = $tmp['channels'];
4114 }
4115 else
4116 {
4117 $channels = 3;
4118 }
4119
4120 if ($w <= 0 && $h <= 0)
4121 {
4122 $w = $imageWidth;
4123 }
4124
4125 if ($w == 0)
4126 {
4127 $w = $h / $imageHeight * $imageWidth;
4128 }
4129
4130 if ($h == 0)
4131 {
4132 $h = $w * $imageHeight / $imageWidth;
4133 }
4134
4135 $fp = fopen($img, 'rb');
4136
4137 $data = fread($fp, filesize($img));
4138
4139 fclose($fp);
4140
4141 $this->addJpegImage_common($data, $x, $y, $w, $h, $imageWidth, $imageHeight, $channels);
4142 }
4143
4149 function addImage(&$img, $x, $y, $w = 0, $h = 0, $quality = 75)
4150 {
4151 // add a new image into the current location, as an external object
4152 // add the image at $x,$y, and with width and height as defined by $w & $h
4153
4154 // note that this will only work with full colour images and makes them jpg images for display
4155 // later versions could present lossless image formats if there is interest.
4156
4157 // there seems to be some problem here in that images that have quality set above 75 do not appear
4158 // not too sure why this is, but in the meantime I have restricted this to 75.
4159 if ($quality > 75)
4160 {
4161 $quality = 75;
4162 }
4163
4164 // if the width or height are set to zero, then set the other one based on keeping the image
4165 // height/width ratio the same, if they are both zero, then give up :)
4166 $imageWidth = imagesx($img);
4167 $imageHeight = imagesy($img);
4168
4169 if ($w <= 0 && $h <= 0)
4170 {
4171 return;
4172 }
4173
4174 if ($w == 0)
4175 {
4176 $w = $h / $imageHeight * $imageWidth;
4177 }
4178
4179 if ($h == 0)
4180 {
4181 $h = $w * $imageHeight / $imageWidth;
4182 }
4183
4184 // gotta get the data out of the img..
4185
4186 // so I write to a temp file, and then read it back.. soo ugly, my apologies.
4187 $tmpDir = '/tmp';
4188 $tmpName = tempnam($tmpDir, 'img');
4189 imagejpeg($img, $tmpName, $quality);
4190 $fp = fopen($tmpName, 'rb');
4191
4192 $fp = @fopen($tmpName, 'rb');
4193
4194 if ($fp)
4195 {
4196 $data = '';
4197
4198 while (!feof($fp))
4199 {
4200 $data .= fread($fp, 1024);
4201 }
4202
4203 fclose($fp);
4204 }
4205 else
4206 {
4207 $error = 1;
4208 $errormsg = 'trouble opening file';
4209 }
4210
4211 // $data = fread($fp,filesize($tmpName));
4212
4213 // fclose($fp);
4214 unlink($tmpName);
4215 $this->addJpegImage_common($data, $x, $y, $w, $h, $imageWidth, $imageHeight);
4216 }
4217
4223 function addJpegImage_common(&$data, $x, $y, $w = 0, $h = 0, $imageWidth, $imageHeight, $channels = 3)
4224 {
4225 // note that this function is not to be called externally
4226 // it is just the common code between the GD and the file options
4227 $this->numImages++;
4228 $im = $this->numImages;
4229 $label = 'I' . $im;
4230 $this->numObj++;
4231 $this->o_image($this->numObj,
4232 'new',
4233 array('label' => $label, 'data' => $data, 'iw' => $imageWidth, 'ih' => $imageHeight,
4234 'channels' => $channels));
4235
4236 $this->objects[$this->currentContents]['c'] .= "\nq";
4237 $this->objects[$this->currentContents]['c'] .= "\n" . __sprintf('%.3f',
4238 $w) . " 0 0 " . __sprintf('%.3f',
4239 $h) . " "
4240 . __sprintf('%.3f',
4241 $x) . " " . __sprintf('%.3f', $y) . " cm";
4242 $this->objects[$this->currentContents]['c'] .= "\n/" . $label . ' Do';
4243 $this->objects[$this->currentContents]['c'] .= "\nQ";
4244 }
4245
4249 function openHere($style, $a = 0, $b = 0, $c = 0)
4250 {
4251 // this function will open the document at a specified page, in a specified style
4252 // the values for style, and the required paramters are:
4253 // 'XYZ' left, top, zoom
4254 // 'Fit'
4255 // 'FitH' top
4256 // 'FitV' left
4257 // 'FitR' left,bottom,right
4258 // 'FitB'
4259 // 'FitBH' top
4260 // 'FitBV' left
4261 $this->numObj++;
4262 $this->o_destination($this->numObj, 'new',
4263 array('page' => $this->currentPage, 'type' => $style, 'p1' => $a, 'p2' => $b, 'p3' => $c));
4264 $id = $this->catalogId;
4265 $this->o_catalog($id, 'openHere', $this->numObj);
4266 }
4267
4271 function addDestination($label, $style, $a = 0, $b = 0, $c = 0)
4272 {
4273 // associates the given label with the destination, it is done this way so that a destination can be specified after
4274 // it has been linked to
4275 // styles are the same as the 'openHere' function
4276 $this->numObj++;
4277 $this->o_destination($this->numObj, 'new',
4278 array('page' => $this->currentPage, 'type' => $style, 'p1' => $a, 'p2' => $b, 'p3' => $c));
4279 $id = $this->numObj;
4280 // store the label->idf relationship, note that this means that labels can be used only once
4281 $this->destinations["$label"] = $id;
4282 }
4283
4289 function setFontFamily($family, $options = '')
4290 {
4291 if (!is_array($options))
4292 {
4293 if ($family == 'init')
4294 {
4295 // set the known family groups
4296 // these font families will be used to enable bold and italic markers to be included
4297 // within text streams. html forms will be used... <b></b> <i></i>
4298 $this->fontFamilies['Helvetica.afm'] = array
4299 (
4300 'b' => 'Helvetica-Bold.afm',
4301 'i' => 'Helvetica-Oblique.afm',
4302 'bi' => 'Helvetica-BoldOblique.afm',
4303 'ib' => 'Helvetica-BoldOblique.afm'
4304 );
4305
4306 $this->fontFamilies['Courier.afm'] = array
4307 (
4308 'b' => 'Courier-Bold.afm',
4309 'i' => 'Courier-Oblique.afm',
4310 'bi' => 'Courier-BoldOblique.afm',
4311 'ib' => 'Courier-BoldOblique.afm'
4312 );
4313
4314 $this->fontFamilies['Times-Roman.afm'] = array
4315 (
4316 'b' => 'Times-Bold.afm',
4317 'i' => 'Times-Italic.afm',
4318 'bi' => 'Times-BoldItalic.afm',
4319 'ib' => 'Times-BoldItalic.afm'
4320 );
4321 }
4322 }
4323 else
4324 {
4325 // the user is trying to set a font family
4326 // note that this can also be used to set the base ones to something else
4327 if (strlen($family))
4328 {
4329 $this->fontFamilies[$family] = $options;
4330 }
4331 }
4332 }
4333
4337 function addMessage($message)
4338 {
4339 $this->messages .= $message . "\n";
4340 }
4341
4345 /* PHP 4
4346 function transaction($action){
4347 switch ($action){
4348 case 'start':
4349 // store all the data away into the checkpoint variable
4350 $data = get_object_vars($this);
4351 $this->checkpoint = $data;
4352 unset($data);
4353 break;
4354 case 'commit':
4355 if (is_array($this->checkpoint) && isset($this->checkpoint['checkpoint'])){
4356 $tmp = $this->checkpoint['checkpoint'];
4357 $this->checkpoint = $tmp;
4358 unset($tmp);
4359 } else {
4360 $this->checkpoint='';
4361 }
4362 break;
4363 case 'rewind':
4364 // do not destroy the current checkpoint, but move us back to the state then, so that we can try again
4365 if (is_array($this->checkpoint)){
4366 // can only abort if were inside a checkpoint
4367 $tmp = $this->checkpoint;
4368 foreach ($tmp as $k=>$v){
4369 if ($k != 'checkpoint'){
4370 $this->$k=$v;
4371 }
4372 }
4373 unset($tmp);
4374 }
4375 break;
4376 case 'abort':
4377 if (is_array($this->checkpoint)){
4378 // can only abort if were inside a checkpoint
4379 $tmp = $this->checkpoint;
4380 foreach ($tmp as $k=>$v){
4381 $this->$k=$v;
4382 }
4383 unset($tmp);
4384 }
4385 break;
4386 }
4387
4388 }
4389 */
4390 /* PHP 5 */
4391
4393 {
4394 switch ($action)
4395 {
4396 case 'start':
4397 // store all the data away into the checkpoint variable
4398 $this->checkpoint = clone $this;
4399
4400 break;
4401
4402 case 'commit':
4403 if (is_object($this->checkpoint) && isset($this->checkpoint->checkpoint))
4404 {
4405 $tmp = $this->checkpoint->checkpoint;
4406 $this->checkpoint = $tmp;
4407 unset($tmp);
4408 }
4409 else
4410 {
4411 $this->checkpoint = '';
4412 }
4413
4414 break;
4415
4416 case 'rewind':
4417 // do not destroy the current checkpoint, but move us back to the state then, so that we can try again
4418 if (is_object($this->checkpoint))
4419 {
4420 // can only abort if were inside a checkpoint
4421 $tmp = $this->checkpoint;
4422
4423 foreach ($tmp as $k => $v)
4424 {
4425 if ($k != 'checkpoint')
4426 {
4427 $this->$k = $v;
4428 }
4429 }
4430
4431 unset($tmp);
4432 }
4433
4434 break;
4435
4436 case 'abort':
4437 if (is_object($this->checkpoint))
4438 {
4439 // can only abort if were inside a checkpoint
4440 $tmp = $this->checkpoint;
4441
4442 foreach ($tmp as $k => $v)
4443 {
4444 $this->$k = $v;
4445 }
4446
4447 unset($tmp);
4448 }
4449
4450 break;
4451 }
4452 }
4453
4454
4455 function SetFontsPath($path)
4456 {
4457 $this->fonts_path = $path;
4458 }
4459} // end of class
4460?>
addContent($content)
Definição class.pdf.php:2382
$options
Definição class.pdf.php:138
partEllipse($x0, $y0, $astart, $afinish, $r1, $r2=0, $angle=0, $nSeg=8)
Definição class.pdf.php:2462
PRVTcheckTextDirective1(&$text, $i, &$f, $final, &$x, &$y, $size=0, $angle=0, $wordSpaceAdjust=0)
Definição class.pdf.php:2902
addMessage($message)
Definição class.pdf.php:4337
$destinations
Definição class.pdf.php:200
curve($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3)
Definição class.pdf.php:2444
addPngFromFile($file, $x, $y, $w=0, $h=0)
Definição class.pdf.php:3834
ARC4($text)
Definição class.pdf.php:1675
o_info($id, $action, $options='')
Definição class.pdf.php:967
addLink($url, $x0, $y0, $x1, $y1)
Definição class.pdf.php:1704
$messages
Definição class.pdf.php:166
o_destination($id, $action, $options='')
Definição class.pdf.php:250
setEncryption($userPass='', $ownerPass='', $pc=array())
Definição class.pdf.php:1738
$objects
Definição class.pdf.php:39
stream($options='')
Definição class.pdf.php:2773
__construct($pageSize=array(0, 0, 612, 792))
Definição class.pdf.php:221
transaction($action)
Definição class.pdf.php:4392
$currentFont
Definição class.pdf.php:54
restoreState($pageEnd=0)
Definição class.pdf.php:3611
$wordSpaceAdjust
Definição class.pdf.php:147
$fontFamilies
Definição class.pdf.php:157
o_viewerPreferences($id, $action, $options='')
Definição class.pdf.php:301
addImage(&$img, $x, $y, $w=0, $h=0, $quality=75)
Definição class.pdf.php:4149
$currentContents
Definição class.pdf.php:74
$procsetObjectId
Definição class.pdf.php:151
addTextWrap($x, $y, $width, $size, $text, $justification='left', $angle=0, $test=0)
Definição class.pdf.php:3413
addText($x, $y, $size, $text, $angle=0, $wordSpaceAdjust=0)
Definição class.pdf.php:3138
$currentFontNum
Definição class.pdf.php:62
reopenObject($id)
Definição class.pdf.php:3654
$nStateStack
Definição class.pdf.php:100
$numObj
Definição class.pdf.php:35
$encrypted
Definição class.pdf.php:182
filledRectangle($x1, $y1, $width, $height)
Definição class.pdf.php:2676
selectFont($fontName, $encoding='', $set=1)
Definição class.pdf.php:2051
encryptInit($id)
Definição class.pdf.php:1617
setFontFamily($family, $options='')
Definição class.pdf.php:4289
o_outlines($id, $action, $options='')
Definição class.pdf.php:605
o_font($id, $action, $options='')
Definição class.pdf.php:655
addObject($id, $options='add')
Definição class.pdf.php:3705
$currentNode
Definição class.pdf.php:66
getFontHeight($size)
Definição class.pdf.php:2814
$currentLineStyle
Definição class.pdf.php:90
$firstPageId
Definição class.pdf.php:142
$encryptionKey
Definição class.pdf.php:186
PRVTcheckTextDirective(&$text, $i, &$f)
Definição class.pdf.php:2886
$numFonts
Definição class.pdf.php:78
setCurrentFont()
Definição class.pdf.php:2337
md5_16($string)
Definição class.pdf.php:1601
filledEllipse($x0, $y0, $r1, $r2=0, $angle=0, $nSeg=8, $astart=0, $afinish=360)
Definição class.pdf.php:2470
$arc4_objnum
Definição class.pdf.php:174
o_pages($id, $action, $options='')
Definição class.pdf.php:434
saveState($pageEnd=0)
Definição class.pdf.php:3581
addInfo($label, $value=0)
Definição class.pdf.php:3773
$nCallback
Definição class.pdf.php:195
o_procset($id, $action, $options='')
Definição class.pdf.php:915
setStrokeColor($r, $g, $b, $force=0)
Definição class.pdf.php:2411
setLineStyle($width=1, $cap='', $join='', $dash='', $phase=0)
Definição class.pdf.php:2595
$addLooseObjects
Definição class.pdf.php:123
PRVT_getBytes(&$data, $pos, $num)
Definição class.pdf.php:3816
$currentStrokeColour
Definição class.pdf.php:86
checkAllHere()
Definição class.pdf.php:1781
filterText($text)
Definição class.pdf.php:2849
$currentColour
Definição class.pdf.php:82
Cpdf($pageSize=array(0, 0, 612, 792))
Definição class.pdf.php:216
addInternalLink($label, $x0, $y0, $x1, $y1)
Definição class.pdf.php:1720
openObject()
Definição class.pdf.php:3633
addJpegImage_common(&$data, $x, $y, $w=0, $h=0, $imageWidth, $imageHeight, $channels=3)
Definição class.pdf.php:4223
PRVTadjustWrapText($text, $actual, $width, &$x, &$adjust, $justification)
Definição class.pdf.php:3368
output($debug=0)
Definição class.pdf.php:1788
o_page($id, $action, $options='')
Definição class.pdf.php:1189
addDestination($label, $style, $a=0, $b=0, $c=0)
Definição class.pdf.php:4271
getFirstPageId()
Definição class.pdf.php:2372
$fileIdentifier
Definição class.pdf.php:178
polygon($p, $np, $f=0)
Definição class.pdf.php:2649
o_action($id, $action, $options='')
Definição class.pdf.php:1035
o_fontDescriptor($id, $action, $options='')
Definição class.pdf.php:781
newDocument($pageSize=array(0, 0, 612, 792))
Definição class.pdf.php:1852
$numPages
Definição class.pdf.php:104
ellipse($x0, $y0, $r1, $r2=0, $angle=0, $nSeg=8, $astart=0, $afinish=360, $close=1, $fill=0)
Definição class.pdf.php:2485
$catalogId
Definição class.pdf.php:44
ARC4_init($key='')
Definição class.pdf.php:1637
$callback
Definição class.pdf.php:190
setPreferences($label, $value=0)
Definição class.pdf.php:3795
o_image($id, $action, $options='')
Definição class.pdf.php:1381
$fonts
Definição class.pdf.php:49
$currentTextState
Definição class.pdf.php:162
o_contents($id, $action, $options='')
Definição class.pdf.php:1300
openFont($font)
Definição class.pdf.php:1893
addJpegFromFile($img, $x, $y, $w=0, $h=0)
Definição class.pdf.php:4097
o_catalog($id, $action, $options='')
Definição class.pdf.php:357
setColor($r, $g, $b, $force=0)
Definição class.pdf.php:2390
PRVTgetTextPosition($x, $y, $angle, $size, $wa, $text)
Definição class.pdf.php:2869
rectangle($x1, $y1, $width, $height)
Definição class.pdf.php:2690
getFontDecender($size)
Definição class.pdf.php:2831
newPage($insert=0, $id=0, $pos='after')
Definição class.pdf.php:2704
stopObject($id)
Definição class.pdf.php:3692
$infoObject
Definição class.pdf.php:129
$checkpoint
Definição class.pdf.php:207
$looseObjects
Definição class.pdf.php:118
o_fontEncoding($id, $action, $options='')
Definição class.pdf.php:856
$fonts_path
Definição class.pdf.php:214
o_annotation($id, $action, $options='')
Definição class.pdf.php:1109
openHere($style, $a=0, $b=0, $c=0)
Definição class.pdf.php:4249
$stateStack
Definição class.pdf.php:95
line($x1, $y1, $x2, $y2)
Definição class.pdf.php:2432
$currentPage
Definição class.pdf.php:70
o_encryption($id, $action, $options='')
Definição class.pdf.php:1498
getTextWidth($size, $text)
Definição class.pdf.php:3300
$numImages
Definição class.pdf.php:133
closeObject()
Definição class.pdf.php:3675
SetFontsPath($path)
Definição class.pdf.php:4455
$currentBaseFont
Definição class.pdf.php:58
__sprintf($fmt, $value)
Definição class.pdf.php:2
$action
Definição base.php:4
$url
Definição base.php:2
$id
Definição base.php:5