+ /**
+ * Output Page Annotations.
+ * See section 8.4 of PDF reference.
+ * @param int $n page number
+ * @access protected
+ * @author Nicola Asuni
+ * @since 4.0.018 (2008-08-06)
+ */
+ function _putannots($n) {
+ if (isset($this->PageAnnots[$n])) {
+ $annots = '/Annots [';
+ foreach ($this->PageAnnots[$n] as $key => $pl) {
+ $pl['opt'] = array_change_key_case($pl['opt'], CASE_LOWER);
+ $a = $pl['x'] * $this->k;
+ $b = $this->hPt - $pl['y'] * $this->k;
+ $c = $pl['w'] * $this->k;
+ $d = $pl['h'] * $this->k;
+ $rect = sprintf('%.2f %.2f %.2f %.2f', $a, $b, $a+$c, $b-$d);
+ $annots .= '<</Type /Annot';
+ $annots .= ' /Subtype /'.$pl['opt']['subtype'];
+ $annots .= ' /Rect ['.$rect.']';
+ $annots .= ' /Contents '.$this->_textstring($pl['txt']);
+ //$annots .= ' /P ';
+ $annots .= ' /NM '.$this->_textstring(sprintf('%04u-%04u', $n, $key));
+ $annots .= ' /M '.$this->_datestring('D:'.date('YmdHis'));
+ if (isset($pl['opt']['f'])) {
+ $val = 0;
+ if (is_array($pl['opt']['f'])) {
+ foreach ($pl['opt']['f'] as $f) {
+ switch (strtolower($f)) {
+ case 'invisible': {
+ $val += 1 << 0;
+ break;
+ }
+ case 'hidden': {
+ $val += 1 << 1;
+ break;
+ }
+ case 'print': {
+ $val += 1 << 2;
+ break;
+ }
+ case 'nozoom': {
+ $val += 1 << 3;
+ break;
+ }
+ case 'norotate': {
+ $val += 1 << 4;
+ break;
+ }
+ case 'noview': {
+ $val += 1 << 5;
+ break;
+ }
+ case 'readonly': {
+ $val += 1 << 6;
+ break;
+ }
+ case 'locked': {
+ $val += 1 << 8;
+ break;
+ }
+ case 'togglenoview': {
+ $val += 1 << 9;
+ break;
+ }
+ case 'lockedcontents': {
+ $val += 1 << 10;
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
+ }
+ $annots .= ' /F '.intval($val);
+ }
+ //$annots .= ' /AP ';
+ //$annots .= ' /AS ';
+ $annots .= ' /Border [';
+ if (isset($pl['opt']['border']) AND (count($pl['opt']['border']) >= 3)) {
+ $annots .= intval($pl['opt']['border'][0]).' ';
+ $annots .= intval($pl['opt']['border'][1]).' ';
+ $annots .= intval($pl['opt']['border'][2]);
+ if (isset($pl['opt']['border'][3]) AND is_array($pl['opt']['border'][3])) {
+ $annots .= ' [';
+ foreach ($pl['opt']['border'][3] as $dash) {
+ $annots .= intval($dash).' ';
+ }
+ $annots .= ']';
+ }
+ } else {
+ $annots .= '0 0 0';
+ }
+ $annots .= ']';
+ if (isset($pl['opt']['bs']) AND (is_array($pl['opt']['bs']))) {
+ $annots .= ' /BS <<Type /Border';
+ if (isset($pl['opt']['bs']['w'])) {
+ $annots .= ' /W '.sprintf("%.4f", floatval($pl['opt']['bs']['w']));
+ }
+ $bstyles = array('S', 'D', 'B', 'I', 'U');
+ if (isset($pl['opt']['bs']['s']) AND in_array($pl['opt']['bs']['s'], $markups)) {
+ $annots .= ' /S /'.$pl['opt']['bs']['s'];
+ }
+ if (isset($pl['opt']['bs']['d']) AND (is_array($pl['opt']['bs']['d']))) {
+ $annots .= ' /D [';
+ foreach ($pl['opt']['bs']['d'] as $cord) {
+ $cord = floatval($cord);
+ $annots .= sprintf(" %.4f", $cord);
+ }
+ $annots .= ']';
+ }
+ $annots .= '>>';
+ }
+ if (isset($pl['opt']['be']) AND (is_array($pl['opt']['be']))) {
+ $annots .= ' /BE <<';
+ $bstyles = array('S', 'C');
+ if (isset($pl['opt']['be']['s']) AND in_array($pl['opt']['be']['s'], $markups)) {
+ $annots .= ' /S /'.$pl['opt']['bs']['s'];
+ } else {
+ $annots .= ' /S /S';
+ }
+ if (isset($pl['opt']['be']['i']) AND ($pl['opt']['be']['i'] >= 0) AND ($pl['opt']['be']['i'] <= 2)) {
+ $annots .= ' /I '.sprintf(" %.4f", $pl['opt']['be']['i']);
+ }
+ $annots .= '>>';
+ }
+ $annots .= ' /C [';
+ if (isset($pl['opt']['c']) AND (is_array($pl['opt']['c']))) {
+ foreach ($pl['opt']['c'] as $col) {
+ $col = intval($col);
+ $color = $col <= 0 ? 0 : ($col >= 255 ? 1 : $col / 255);
+ $annots .= sprintf(" %.4f", $color);
+ }
+ }
+ $annots .= ']';
+ //$annots .= ' /StructParent ';
+ //$annots .= ' /OC ';
+ $markups = array('text', 'freetext', 'line', 'square', 'circle', 'polygon', 'polyline', 'highlight', 'underline', 'squiggly', 'strikeout', 'stamp', 'caret', 'ink', 'fileattachment', 'sound');
+ if (in_array(strtolower($pl['opt']['subtype']), $markups)) {
+ // this is a markup type
+ if (isset($pl['opt']['t']) AND is_string($pl['opt']['t'])) {
+ $annots .= ' /T '.$this->_textstring($pl['opt']['t']);
+ }
+ //$annots .= ' /Popup ';
+ if (isset($pl['opt']['ca'])) {
+ $annots .= ' /CA '.sprintf("%.4f", floatval($pl['opt']['ca']));
+ }
+ if (isset($pl['opt']['rc'])) {
+ $annots .= ' /RC '.$this->_textstring($pl['opt']['rc']);
+ }
+ $annots .= ' /CreationDate '.$this->_datestring('D:'.date('YmdHis'));
+ //$annots .= ' /IRT ';
+ if (isset($pl['opt']['subj'])) {
+ $annots .= ' /Subj '.$this->_textstring($pl['opt']['subj']);
+ }
+ //$annots .= ' /RT ';
+ //$annots .= ' /IT ';
+ //$annots .= ' /ExData ';
+ }
+ switch (strtolower($pl['opt']['subtype'])) {
+ case 'text': {
+ if (isset($pl['opt']['open'])) {
+ $annots .= ' /Open '. (strtolower($pl['opt']['open']) == 'true' ? 'true' : 'false');
+ }
+ $iconsapp = array('Comment', 'Help', 'Insert', 'Key', 'NewParagraph', 'Note', 'Paragraph');
+ if (isset($pl['opt']['name']) AND in_array($pl['opt']['name'], $iconsapp)) {
+ $annots .= ' /Name /'.$pl['opt']['name'];
+ } else {
+ $annots .= ' /Name /Note';
+ }
+ $statemodels = array('Marked', 'Review');
+ if (isset($pl['opt']['statemodel']) AND in_array($pl['opt']['statemodel'], $statemodels)) {
+ $annots .= ' /StateModel /'.$pl['opt']['statemodel'];
+ } else {
+ $pl['opt']['statemodel'] = 'Marked';
+ $annots .= ' /StateModel /'.$pl['opt']['statemodel'];
+ }
+ if ($pl['opt']['statemodel'] == 'Marked') {
+ $states = array('Accepted', 'Unmarked');
+ } else {
+ $states = array('Accepted', 'Rejected', 'Cancelled', 'Completed', 'None');
+ }
+ if (isset($pl['opt']['state']) AND in_array($pl['opt']['state'], $states)) {
+ $annots .= ' /State /'.$pl['opt']['state'];
+ } else {
+ if ($pl['opt']['statemodel'] == 'Marked') {
+ $annots .= ' /State /Unmarked';
+ } else {
+ $annots .= ' /State /None';
+ }
+ }
+ break;
+ }
+ case 'link': {
+ $annots .= ' /A <</S /URI /URI '.$this->_uristring($pl['txt']).'>>';
+ $hmodes = array('N', 'I', 'O', 'P');
+ if (isset($pl['opt']['h']) AND in_array($pl['opt']['h'], $hmodes)) {
+ $annots .= ' /H /'.$pl['opt']['h'];
+ } else {
+ $annots .= ' /H /I';
+ }
+ //$annots .= ' /Dest ';
+ //$annots .= ' /PA ';
+ //$annots .= ' /Quadpoints ';
+ break;
+ }
+ case 'freetext': {
+ $annots .= ' /DA '.$this->_textstring($pl['txt']);
+ if (isset($pl['opt']['q']) AND ($pl['opt']['q'] >= 0) AND ($pl['opt']['q'] <= 2)) {
+ $annots .= ' /Q '.intval($pl['opt']['q']);
+ }
+ if (isset($pl['opt']['rc'])) {
+ $annots .= ' /RC '.$this->_textstring($pl['opt']['rc']);
+ }
+ if (isset($pl['opt']['ds'])) {
+ $annots .= ' /DS '.$this->_textstring($pl['opt']['ds']);
+ }
+ if (isset($pl['opt']['cl']) AND is_array($pl['opt']['cl'])) {
+ $annots .= ' /CL [';
+ foreach ($pl['opt']['cl'] as $cl) {
+ $annots .= sprintf("%.4f ", $cl * $this->k);
+ }
+ $annots .= ']';
+ }
+ $tfit = array('FreeTextCallout', 'FreeTextTypeWriter');
+ if (isset($pl['opt']['it']) AND in_array($pl['opt']['it'], $tfit)) {
+ $annots .= ' /IT '.$pl['opt']['it'];
+ }
+ if (isset($pl['opt']['rd']) AND is_array($pl['opt']['rd'])) {
+ $l = $pl['opt']['rd'][0] * $this->k;
+ $r = $pl['opt']['rd'][1] * $this->k;
+ $t = $pl['opt']['rd'][2] * $this->k;
+ $b = $pl['opt']['rd'][3] * $this->k;
+ $annots .= ' /RD ['.sprintf('%.2f %.2f %.2f %.2f', $l, $r, $t, $b).']';
+ }
+ //$annots .= ' /LE ';
+ break;
+ }
+ // ... to be completed ...
+ case 'line': {
+ break;
+ }
+ case 'square': {
+ break;
+ }
+ case 'circle': {
+ break;
+ }
+ case 'polygon': {
+ break;
+ }
+ case 'polyline': {
+ break;
+ }
+ case 'highlight': {
+ break;
+ }
+ case 'underline': {
+ break;
+ }
+ case 'squiggly': {
+ break;
+ }
+ case 'strikeout': {
+ break;
+ }
+ case 'stamp': {
+ break;
+ }
+ case 'caret': {
+ break;
+ }
+ case 'ink': {
+ break;
+ }
+ case 'popup': {
+ break;
+ }
+ case 'fileattachment': {
+ break;
+ }
+ case 'sound': {
+ break;
+ }
+ case 'movie': {
+ break;
+ }
+ case 'widget': {
+ break;
+ }
+ case 'screen': {
+ break;
+ }
+ case 'printermark': {
+ break;
+ }
+ case 'trapnet': {
+ break;
+ }
+ case 'watermark': {
+ break;
+ }
+ case '3d': {
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ $annots .= '>>';
+ }
+ $this->_out($annots.']');
+ }
+ }
+