diff --git a/phpgwapi/inc/class.pdmlwrapper.inc.php b/phpgwapi/inc/class.pdmlwrapper.inc.php new file mode 100644 index 0000000000..0cb21bc105 --- /dev/null +++ b/phpgwapi/inc/class.pdmlwrapper.inc.php @@ -0,0 +1,18 @@ + + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @link http://pdml.sourceforge.net PDML documentation + */ + class pdmlwrapper extends PDML + {} +?> diff --git a/phpgwapi/inc/fpdf/pdml.php b/phpgwapi/inc/fpdf/pdml.php new file mode 100755 index 0000000000..5dbc2622e4 --- /dev/null +++ b/phpgwapi/inc/fpdf/pdml.php @@ -0,0 +1,1065 @@ + works right. + var $B = 0; + var $I = 0; + var $U = 0; + var $left_margin = array( 28.35 ); // 1cm + var $right_margin = array( 28.35 ); // 1cm + var $bottom_margin = array( 28.35 ); // 1cm + var $div_x = array(); + var $div_y = array(); + var $cell_info; // stuff to keep around until a shows up + var $cell_text; // text to put in a cell. + var $script; // stuff to put in our script. + var $header=''; + var $footer=''; + var $parserBreak; // when you want to break parsing, put a stop word here. + var $multicol = array(); // stack of columns. you never know. + + /* Rotation extension. Should go away with 1.6 */ + var $angle=0; + function Rotate($angle,$x=-1,$y=-1) + { + if($x==-1) + $x=$this->x; + if($y==-1) + $y=$this->y; + if($this->angle!=0) + $this->_out('Q'); + $this->angle=$angle; + if($angle!=0) + { + $angle*=M_PI/180; + $c=cos($angle); + $s=sin($angle); + $cx=$x*$this->k; + $cy=($this->h-$y)*$this->k; + $this->_out(sprintf('q %.5f %.5f %.5f %.5f %.2f %.2f cm 1 0 0 1 %.2f %.2f cm',$c, $s,-$s,$c,$cx,$cy,-$cx,-$cy)); + } + } + function _endpage() + { + if($this->angle!=0) + { + $this->angle=0; + $this->_out('Q'); + } + parent::_endpage(); + } + /* End of Rotation Extension */ + + /* Ellipse extension. Should go away with 1.6 */ + function Circle($x,$y,$r,$style='') { + $this->Ellipse($x,$y,$r,$r,$style); + } + + function Ellipse($x,$y,$rx,$ry,$style='D') { + if($style=='F') + $op='f'; + elseif($style=='FD' or $style=='DF') + $op='B'; + else + $op='S'; + $lx=4/3*(M_SQRT2-1)*$rx; + $ly=4/3*(M_SQRT2-1)*$ry; + $k=$this->k; + $h=$this->h; + $this->_out(sprintf('%.2f %.2f m %.2f %.2f %.2f %.2f %.2f %.2f c', + ($x+$rx)*$k,($h-$y)*$k, + ($x+$rx)*$k,($h-($y-$ly))*$k, + ($x+$lx)*$k,($h-($y-$ry))*$k, + $x*$k,($h-($y-$ry))*$k)); + $this->_out(sprintf('%.2f %.2f %.2f %.2f %.2f %.2f c', + ($x-$lx)*$k,($h-($y-$ry))*$k, + ($x-$rx)*$k,($h-($y-$ly))*$k, + ($x-$rx)*$k,($h-$y)*$k)); + $this->_out(sprintf('%.2f %.2f %.2f %.2f %.2f %.2f c', + ($x-$rx)*$k,($h-($y+$ly))*$k, + ($x-$lx)*$k,($h-($y+$ry))*$k, + $x*$k,($h-($y+$ry))*$k)); + $this->_out(sprintf('%.2f %.2f %.2f %.2f %.2f %.2f c %s', + ($x+$lx)*$k,($h-($y+$ry))*$k, + ($x+$rx)*$k,($h-($y+$ly))*$k, + ($x+$rx)*$k,($h-$y)*$k, + $op)); + } + /* End of Ellipse Extension */ + + /* Javascript extension. That may stick here a while. */ + var $javascript; + var $n_js; + function IncludeJS($script) { + $this->javascript.=$script; + } + function _putjavascript() { + $this->_newobj(); + $this->n_js=$this->n; + $this->_out('<<'); + $this->_out('/Names [(EmbeddedJS) '.($this->n+1).' 0 R ]'); + $this->_out('>>'); + $this->_out('endobj'); + $this->_newobj(); + $this->_out('<<'); + $this->_out('/S /JavaScript'); + $this->_out('/JS '.$this->_textstring($this->javascript)); + $this->_out('>>'); + $this->_out('endobj'); + } + function _putresources() { + parent::_putresources(); + if (!empty($this->javascript)) { + $this->_putjavascript(); + } + $this->_putbookmarks(); + } + function _putcatalog() { + parent::_putcatalog(); + if (isset($this->javascript)) { + $this->_out('/Names <n_js).' 0 R>>'); + } + if(count($this->outlines)>0) + { + $this->_out('/Outlines '.$this->OutlineRoot.' 0 R'); + $this->_out('/PageMode /UseOutlines'); + } + } + /* End of Javascript Extension */ + + /* Bookmark Extension. Should go away with 1.6 */ + var $outlines=array(); + var $OutlineRoot; + function Bookmark($txt,$level=0,$y=0) + { + if($y==-1) + $y=$this->GetY(); + $this->outlines[]=array('t'=>$txt,'l'=>$level,'y'=>$y,'p'=>$this->PageNo()); + } + function _putbookmarks() + { + $nb=count($this->outlines); + if($nb==0) + return; + $lru=array(); + $level=0; + foreach($this->outlines as $i=>$o) + { + if($o['l']>0) + { + $parent=$lru[$o['l']-1]; + //Set parent and last pointers + $this->outlines[$i]['parent']=$parent; + $this->outlines[$parent]['last']=$i; + if($o['l']>$level) + { + //Level increasing: set first pointer + $this->outlines[$parent]['first']=$i; + } + } + else + $this->outlines[$i]['parent']=$nb; + if($o['l']<=$level and $i>0) + { + //Set prev and next pointers + $prev=$lru[$o['l']]; + $this->outlines[$prev]['next']=$i; + $this->outlines[$i]['prev']=$prev; + } + $lru[$o['l']]=$i; + $level=$o['l']; + } + //Outline items + $n=$this->n+1; + foreach($this->outlines as $i=>$o) + { + $this->_newobj(); + $this->_out('<_textstring($o['t'])); + $this->_out('/Parent '.($n+$o['parent']).' 0 R'); + if(isset($o['prev'])) + $this->_out('/Prev '.($n+$o['prev']).' 0 R'); + if(isset($o['next'])) + $this->_out('/Next '.($n+$o['next']).' 0 R'); + if(isset($o['first'])) + $this->_out('/First '.($n+$o['first']).' 0 R'); + if(isset($o['last'])) + $this->_out('/Last '.($n+$o['last']).' 0 R'); + $this->_out(sprintf('/Dest [%d 0 R /XYZ 0 %.2f null]',1+2*$o['p'],($this->h-$o['y'])*$this->k)); + $this->_out('/Count 0>>'); + $this->_out('endobj'); + } + //Outline root + $this->_newobj(); + $this->OutlineRoot=$this->n; + $this->_out('<_out('/Last '.($n+$lru[0]).' 0 R>>'); + $this->_out('endobj'); + } + /* End of Bookmark Extension */ + + function ParsePDML($pdml) { + // default font. + $this->SetFont($this->font_face[0],'',$this->font_size[0]); + // apply margins + $this->SetRightMargin($this->right_margin[0]); + $this->SetLeftMargin($this->left_margin[0]); + // bottom margin + $this->SetAutoPageBreak(true, $this->bottom_margin[0]); + + $this->AliasNbPages('&pagecount;'); + + $this->_parsePDML($pdml); + //return $this->final; + } + + function Header() { + $this->_parsePDML($this->header); + } + + function Footer() { + $this->_parsePDML($this->footer); + } + + function AcceptPageBreak() { + if (count($this->multicol>0)) { + // we need: starting y0, col_width, col_spacing, columns, height, break=page/line + list($x0, $y0, $width, $height, $spacing, $break, $cols, $current) = $this->multicol[0]; + if ($current<$cols-1) { + // next column + $current++; + $this->multicol[0][7] = $current; + $x = $x0 + $current * $width; + $this->SetLeftMargin($x); + $this->SetX($x); + $this->SetY($y0); + return false; + } else { + // ok. we need to break. + $this->SetLeftMargin($x0); + $this->SetX($x0); + $this->multicol[0][7] = 0; // $current + if ($break=="line") { + $y0 += $spacing + $height; // y0 + $this->multicol[0][1] = $y0; + $this->SetAutoPageBreak(true, $this->hPt - ( $y0 + $height)); + $this->SetY($y0); + //$this->Write(10,"This sux0rs."); + return false; + } else { + // page break. + return true; + } + } + } else { + // no multi-column tag. do the normal thing. + return true; + } + } + + function _parsePDML($pdml) { + $a = preg_split('/<([^<]*)\/?>/U',$pdml,-1,PREG_SPLIT_DELIM_CAPTURE); + foreach ($a as $i=>$e) { + if ($this->parserBreak) { + if ($i%2==0) { + $this->ProcessText($e); + continue; + } + if (strcasecmp($e,$this->parserBreak)) { + $this->ProcessText('<'.$e.'>'); + continue; + } + } + if ($i%2==0) { + // text + $this->ProcessText(pdml_entity_decode(preg_replace( + array( + '/\s+/', + '/&pagenumber;/', + '/&title;/', + '/&author;/', + '/&subject;/', + '/&creator;/' + ), + array( + ' ', + $this->PageNo(), + $this->title, + $this->author, + $this->subject, + $this->creator + ) ,$e))); + } else { + // tag + if ($e{0}=='/') { + $this->CloseTag(strtoupper(substr($e,1))); + } else { + $a2 = explode(' ',$e,2); + $tag = strtoupper(array_shift($a2)); + $e = substr($e, strlen($tag)+1); + // stolen from http://www.cs.sfu.ca/~cameron/REX.html + // bugified into uselessness. It's the intent that counts. right? + $NameStrt = "[A-Za-z_:]|[^\\x00-\\x7F]"; + $NameChar = "[A-Za-z0-9_:.-]|[^\\x00-\\x7F]"; + $Name = "(?:$NameStrt)(?:$NameChar)*"; + $S = "[ \\n\\t\\r]+"; + $AttValSE = "\"[^\"]*\"|'[^']*'|[^ \\n\\t\\r]+"; + $ElemTagCE = "($Name)(?:$S)?=(?:$S)?($AttValSE)"; + + $attr = array(); + preg_match_all("/$ElemTagCE/", $e, $matches, PREG_SET_ORDER); + for ($i=0;$iOpenTag($tag,$attr); + } + } + } + } + + function ProcessText($text) { + switch ($this->parserState) { + case 0: + case 1: + case 2: + // ignore text/whitespace in there. + break; + case 3: + $this->SetTitle($text); + break; + case 4: + $this->SetSubject($text); + break; + case 5: + $this->SetAuthor($text); + break; + case 6: + $this->SetKeywords($text); + break; + case 51: + $this->cell_text .= $text; + break; + case 10: + $this->script .= $text; + break; + case 63: + $this->header .= $text; + break; + case 64: + $this->footer .= $text; + break; + default: + // ignore pure whitespace + if (preg_match("/^[ \\n\\t\\r]*$/",$text)) break; + // auto-create a page if needed. + if (!$this->inPage) { + $this->inPage = true; + $this->AddPage(); + } + // write stuff. + // do we have a link to use? + if (sizeof($this->href)>0) { + if ($this->href_style[0]) { + $this->SetTextColor(0,0,255); + $this->_setStyle('U',true, true); + } + $this->Write($this->font_size[0],$text,$this->href[0]); + if ($this->href_style[0]) { + $this->_setStyle('U', $this->U>0, true); + $this->_setFontColor($this->font_color[0]); + } + } else { + $this->Write($this->font_size[0],$text); + } + } + } + + function OpenTag($tag, $attr) { + switch ($tag) { + case "PDML": + $this->_enforceState(0,1); + break; + case "HEAD": + $this->_enforceState(1,2); + break; + case "TITLE": + $this->_enforceState(2,3); + break; + case "SUBJECT": + $this->_enforceState(2,4); + break; + case "AUTHOR": + $this->_enforceState(2,5); + break; + case "KEYWORDS": + $this->_enforceState(2,6); + break; + case "SCRIPT": + $this->_enforceState(2,10); + $this->script=''; + $this->parserBreak="/script"; + break; + case "BODY": + $this->_enforceState(1,50); + break; + case "PAGE": + $this->_enforceState(50,50); + $o = "P"; + if (isset($attr["ORIENTATION"])) { + if (strcasecmp($attr["ORIENTATION"],"LANDSCAPE")==0) { + $o = "L"; + } + } + $this->inPage=true; + $this->AddPage($o); + break; + case "BR": + // no enforcement. + if ($this->parserState==51) { + $this->cell_text.="\n"; + break; + } + if (isset($attr["HEIGHT"])) { + $h=$this->_getUnit($attr["HEIGHT"], $this->font_size[0]); + $this->Ln($h); + } else { + $this->Ln($this->font_size[0]); + } + break; + case "A": + $this->_enforceState(50,50); + // name= + if (isset($attr["NAME"])) { + // local anchor + $name = $attr["NAME"]; + if (!isset($this->anchors[$name])) { + $this->anchors[$name] = $this->AddLink(); + } + $this->SetLink($this->anchors[$name], -1); + } + // href= + if (isset($attr["HREF"])) { + $href = $attr["HREF"]; + if ($href[0]=='#') { + // local anchor + $href = substr($href,1); + if (!isset($this->anchors[$href])) { + $this->anchors[$href] = $this->AddLink(); + } + array_unshift ($this->href, $this->anchors[$href]); + } else { + array_unshift ($this->href, $href); + } + // we should set style to underlined blue. XXX + array_unshift ($this->href_style, isset($attr["HIDDEN"])?0:1); + } + break; + case "B": + case "I": + case "U": + $this->_enforceState(50,50); + $this->_setStyle($tag, true); + break; + case "FONT": + $this->_enforceState(50,50); + $mask = 0; + if (isset($attr["COLOR"])) { + // hex-encoded color. no space for long color name list. + $color = $attr["COLOR"]; + if ($color[0]=="#") { $color = substr($color,1); } + array_unshift($this->font_color, $color); + $this->_setFontColor($color); + $mask |= 1; + } + if (isset($attr["SIZE"])) { + $size = $this->_getUnit($attr["SIZE"], $this->font_size[0]); + array_unshift($this->font_size, $size); + $this->SetFontSize($size); + $mask |= 2; + } + if (isset($attr["FACE"])) { + $face = $attr["FACE"]; + array_unshift($this->font_face, $face); + $this->_setFontFace($face); + $mask |= 4; + } + array_unshift($this->font_mask, $mask); + break; + case "IMG": + $this->_enforceState(50,50); + if (!isset($attr["SRC"])) break; + $src = $attr["SRC"]; + $x = $this->GetX(); + if (isset($attr["LEFT"])) { + $x = $this->_getUnit($attr["LEFT"], $this->wPt); + } + $y = $this->GetY(); + if (isset($attr["TOP"])) { + $y = $this->_getUnit($attr["TOP"], $this->hPt); + } + $width = 0; + if (isset($attr["WIDTH"])) { + $width = $this->_getUnit($attr["WIDTH"], $this->wPt); + } + $height = 0; + if (isset($attr["HEIGHT"])) { + $height = $this->_getUnit($attr["HEIGHT"], $this->hPt); + } + // try to resolve src a bit if necessary. + if (!file_exists($src)) { + $src1 = getenv("DOCUMENT_ROOT")."/".$src; + $src2 = dirname(getenv("SCRIPT_FILENAME"))."/".$src; + if (file_exists($src1)) { + $src = $src1; + } elseif (file_exists($src2)) { + $src = $src2; + } + } + if (sizeof($this->href)>0) { + $this->Image($src, $x, $y, $width, $height, '', $this->href[0]); + } else { + $this->Image($src, $x, $y, $width, $height); + } + break; + case "LINE": + $this->_enforceState(50,50); + $x1 = $this->GetX(); + $y1 = $this->GetY(); + if (isset($attr["FROM"])) { + list($x1,$y1) = explode(',',$attr["FROM"]); + $x1 = $this->_getUnit($x1, $this->wPt); + $y1 = $this->_getUnit($y1, $this->hPt); + } + $x2 = $this->wPt; + $y2 = $y1; + if (isset($attr["TO"])) { + list($x2,$y2) = explode(',',$attr["TO"]); + $x2 = $this->_getUnit($x2, $this->wPt); + $y2 = $this->_getUnit($y2, $this->hPt); + } + $color = "000000"; + if (isset($attr["COLOR"])) { + $color = $attr["COLOR"]; + if ($color[0]=="#") { $color = substr($color,1); } + } + $lwidth = $this->_getUnit("0.2mm"); + if (isset($attr["WIDTH"])) { + $lwidth = $this->_getUnit($attr["WIDTH"], $lwidth); + } + $this->_setLineColor($color); + $this->SetLineWidth($lwidth); + $this->Line($x1,$y1,$x2,$y2); + break; + case "RECT": + $this->_enforceState(50,50); + $x1 = $this->GetX(); + $y1 = $this->GetY(); + if (isset($attr["FROM"])) { + list($x1,$y1) = explode(',',$attr["FROM"]); + $x1 = $this->_getUnit($x1, $this->wPt); + $y1 = $this->_getUnit($y1, $this->hPt); + } + if (isset($attr["LEFT"])) { + $x1 = $this->_getUnit($attr["LEFT"], $this->wPt); + } + if (isset($attr["TOP"])) { + $y1 = $this->_getUnit($attr["TOP"], $this->hPt); + } + $width= 144; + $height= 36; + if (isset($attr["TO"])) { + list($x2,$y2) = explode(',',$attr["TO"]); + $x2 = $this->_getUnit($x2, $this->wPt); + $y2 = $this->_getUnit($y2, $this->hPt); + $width = $x2-$x1+1; + $height = $y2-$y1+1; + } + if (isset($attr["WIDTH"])) { + $width = $this->_getUnit($attr["WIDTH"], $this->wPt); + } + if (isset($attr["HEIGHT"])) { + $height = $this->_getUnit($attr["HEIGHT"], $this->hPt); + } + $style=""; + $color = "000000"; + if (isset($attr["COLOR"])) { + $color = $attr["COLOR"]; + if ($color[0]=="#") { $color = substr($color,1); } + $style.="D"; + } + $fill = "000000"; + if (isset($attr["FILLCOLOR"])) { + $fill = $attr["FILLCOLOR"]; + if ($fill[0]=="#") { $fill = substr($fill,1); } + $style.="F"; + } + $border = $this->_getUnit("0.2mm"); + if (isset($attr["BORDER"])) { + $border = $this->_getUnit($attr["BORDER"], $border); + } + $this->_setLineColor($color); + $this->SetLineWidth($border); + $this->_setRectColor($fill); + $this->Rect($x1,$y1,$width,$height,$style); + break; + case "CIRCLE": + case "ELLIPSE": + $this->_enforceState(50,50); + $x1 = $this->GetX(); + $y1 = $this->GetY(); + if (isset($attr["FROM"])) { + list($x1,$y1) = explode(',',$attr["FROM"]); + $x1 = $this->_getUnit($x1, $this->wPt); + $y1 = $this->_getUnit($y1, $this->hPt); + } + $radius = $this->_getAttrUnit($this->font_size[0], $attr, "RADIUS", $this->font_size[0]); + $xradius = $this->_getAttrUnit($radius, $attr, "XRADIUS", $this->font_size[0]); + $yradius = $this->_getAttrUnit($radius, $attr, "YRADIUS", $this->font_size[0]); + $style=""; + $color = "000000"; + if (isset($attr["COLOR"])) { + $color = $attr["COLOR"]; + if ($color[0]=="#") { $color = substr($color,1); } + $style.="D"; + } + $fill = "000000"; + if (isset($attr["FILLCOLOR"])) { + $fill = $attr["FILLCOLOR"]; + if ($fill[0]=="#") { $fill = substr($fill,1); } + $style.="F"; + } + $border = $this->_getUnit("0.2mm"); + if (isset($attr["BORDER"])) { + $border = $this->_getUnit($attr["BORDER"], $border); + } + $this->_setLineColor($color); + $this->SetLineWidth($border); + $this->_setRectColor($fill); + $this->Ellipse($x1, $y1, $xradius, $yradius, $style); + break; + case "DIV": + $this->_enforceState(50,50); + $save_x = $this->GetX(); + $x = $this->_getAttrUnit($save_x, $attr, "LEFT", $this->wPt); + $save_y = $this->GetY(); + $y = $this->_getAttrUnit($save_y, $attr, "TOP", $this->hPt); + $width = $this->_getAttrUnit($this->wPt-$x, $attr, "WIDTH", $this->wPt); + $height = $this->_getAttrUnit($this->hPt-$y, $attr, "HEIGHT", $this->hPt); + if ($x == $save_x) { $save_x+=$width; } + array_unshift($this->left_margin, $x); + array_unshift($this->right_margin, $this->wPt-$width-$x); + array_unshift($this->div_x, $save_x); + array_unshift($this->div_y, $save_y); + // draw a rect, just to debug. XXX + $style=""; + $color = "000000"; + if (isset($attr["COLOR"])) { + $color = $attr["COLOR"]; + if ($color[0]=="#") { $color = substr($color,1); } + $style.="D"; + } + $fill = "000000"; + if (isset($attr["FILLCOLOR"])) { + $fill = $attr["FILLCOLOR"]; + if ($fill[0]=="#") { $fill = substr($fill,1); } + $style.="F"; + } + $border = $this->_getUnit("0.2mm"); + if (isset($attr["BORDER"])) { + $border = $this->_getUnit($attr["BORDER"], $border); + } + $this->_setLineColor($color); + $this->SetLineWidth($border); + $this->_setRectColor($fill); + if ($style) { + $this->Rect($x,$y,$width,$height,$style); + } + $this->SetLeftMargin($this->left_margin[0]); + $this->SetRightMargin($this->right_margin[0]); + $this->SetXY($x,$y); + break; + case "MULTICELL": + case "CELL": + $this->_enforceState(50,51); + $save_x = $this->GetX(); + $x = $this->_getAttrUnit($save_x, $attr, "LEFT", $this->wPt); + $save_y = $this->GetY(); + $y = $this->_getAttrUnit($save_y, $attr, "TOP", $this->hPt); + $width = $this->_getAttrUnit($this->wPt-$x, $attr, "WIDTH", $this->wPt); + // used by multicell only + $inter = $this->_getAttrUnit($this->font_size[0], $attr, "INTER", $this->font_size[0]); + // used by cell only. + $height = $this->_getAttrUnit($this->font_size[0], $attr, "HEIGHT", $this->font_size[0]); + $next = 0; + if (isset($attr["NEXT"])) { + $n = strtolower($attr["NEXT"]); + switch ($n) { + case "right": $next =0; break; + case "bottom": case "down": $next=2; break; + case "break": $next = 1; break; + } + } + $style=""; + $color = "000000"; + if (isset($attr["COLOR"])) { + $color = $attr["COLOR"]; + if ($color[0]=="#") { $color = substr($color,1); } + $style.="D"; + } + $fillflag = 0; + $fill = "000000"; + if (isset($attr["FILLCOLOR"])) { + $fill = $attr["FILLCOLOR"]; + if ($fill[0]=="#") { $fill = substr($fill,1); } + $fillflag=1; + } + $borderflag=0; + $border = $this->_getUnit("0.2mm"); + if (isset($attr["BORDER"])) { + $border = $this->_getUnit($attr["BORDER"], $border); + $borderflag=1; + } + $align = ($tag=="CELL")?"L":"J"; + if (isset($attr["ALIGN"])) { + $al = strtolower($attr["ALIGN"]); + switch ($al){ + case "left": $align="L"; break; + case "center": $align="C"; break; + case "right": $align="R"; break; + case "justify": $align="J"; break; + } + } + $this->_setLineColor($color); + $this->SetLineWidth($border); + $this->_setRectColor($fill); + $this->SetXY($x,$y); + $this->cell_info = array($width, $inter, $height, $borderflag, $align, $fillflag, $next); + $this->cell_text = ''; + break; + case "ROTATE": + $angle=45; + if (isset($attr["ANGLE"])) { + $angle = $attr["ANGLE"]; + } + $x=-1; + $y=-1; + if (isset($attr["CENTER"])) { + list($x,$y) = explode(',',$attr["CENTER"]); + $x = $this->_getUnit($x, $this->wPt); + $y = $this->_getUnit($y, $this->hPt); + } + $this->rotate($angle, $x, $y); + break; + case "BOOKMARK": + if (!isset($attr["TITLE"])) break; + $title = $attr["TITLE"]; + $level = 0; + if (isset($attr["LEVEL"])) { + $level = $attr["LEVEL"]; + } + $top = -1; + if (isset($attr["TOP"])) { + $top = $this->_getUnit($attr["TOP"], $this->hPt); + } + $this->Bookmark($title, $level, $top); + break; + case "HEADER": + $this->_enforceState(50,63); + $this->header=''; + $this->parserBreak='/header'; + break; + case "FOOTER": + $this->_enforceState(50,64); + $this->footer=''; + $this->parserBreak='/footer'; + break; + case "COLUMN": + $this->_enforceState(50,50); + $save_x = $this->GetX(); + $x = $this->_getAttrUnit($save_x, $attr, "LEFT", $this->wPt); + $save_y = $this->GetY(); + $y = $this->_getAttrUnit($save_y, $attr, "TOP", $this->hPt); + $count = 2; + if (isset($attr["COUNT"])) { + $count = (int)$attr["COUNT"]; + } + $width = $this->_getAttrUnit(($this->wPt-$x)/$count, $attr, "WIDTH", $this->wPt); + $height = $this->_getAttrUnit($this->hPt-$y, $attr, "HEIGHT", $this->hPt); + $spacing = $this->_getAttrUnit($this->font_size[0], $attr, "SPACING", $this->font_size[0]); + $break = "page"; + if (isset($attr["BREAK"]) and (strtolower($attr["BREAK"])=="line")) { + $break = "line"; + } + // store stuff for acceptPageBreak to make sense of, and stuff we're saving + array_unshift($this->multicol, array($x,$y,$width,$height,$spacing, $break, $count, 0, )); + array_unshift($this->left_margin, $x); + array_unshift($this->bottom_margin, $this->hPt-($y+$height)); + // set margins to make things work. + $this->SetLeftMargin($this->left_margin[0]); + $this->SetAutoPageBreak(true, $this->bottom_margin[0]); + break; + } + } + + function CloseTag($tag) { + switch ($tag) { + case "PDML": + $this->_enforceState(1,0); + //$this->final = $this->Output("","S"); + break; + case "HEAD": + $this->_enforceState(2,1); + break; + case "TITLE": + $this->_enforceState(3,2); + break; + case "SUBJECT": + $this->_enforceState(4,2); + break; + case "AUTHOR": + $this->_enforceState(5,2); + break; + case "KEYWORDS": + $this->_enforceState(6,2); + break; + case "SCRIPT": + $this->_enforceState(10,2); + $this->IncludeJS($this->script); + $this->parserBreak=''; + break; + case "BODY": + $this->Close(); + $this->_enforceState(50,1); + break; + case "A": + array_shift ($this->href); + array_shift ($this->href_style); + // we should remove underline + blue. + break; + case "B": + case "I": + case "U": + $this->_setStyle($tag, false); + break; + case "FONT": + if (sizeof($this->font_mask)>0) { + $mask = array_shift($this->font_mask); + } + if (($mask&1)==1) { + array_shift($this->font_color); + $this->_setFontColor($this->font_color[0]); + } + if (($mask&2)==2) { + array_shift($this->font_size); + $this->SetFontSize($this->font_size[0]); + } + if (($mask&4)==4) { + array_shift($this->font_face); + $this->_setFontFace($this->font_face[0]); + } + break; + case "DIV": + if (sizeof($this->div_x)<1) break; + array_shift($this->left_margin); + array_shift($this->right_margin); + $this->SetLeftMargin($this->left_margin[0]); + $this->SetRightMargin($this->right_margin[0]); + $this->SetXY($this->div_x[0],$this->div_y[0]); + array_shift($this->div_x); + array_shift($this->div_y); + break; + case "MULTICELL": + $this->_enforceState(51,50); + // auto-create a page if needed. + if (!$this->inPage) { + $this->inPage = true; + $this->AddPage(); + } + $this->MultiCell( + $this->cell_info[0], + $this->cell_info[1], + $this->cell_text, + $this->cell_info[3], + $this->cell_info[4], + $this->cell_info[5]); + break; + case "CELL": + $this->_enforceState(51,50); + // auto-create a page if needed. + if (!$this->inPage) { + $this->inPage = true; + $this->AddPage(); + } + // redo the link logic here. blah. + if (sizeof($this->href)>0) { + if ($this->href_style[0]) { + $this->SetTextColor(0,0,255); + $this->_setStyle('U',true, true); + } + $this->Cell( + $this->cell_info[0], + $this->cell_info[2], + $this->cell_text, + $this->cell_info[3], + $this->cell_info[6], + $this->cell_info[4], + $this->cell_info[5], + $this->href[0]); + if ($this->href_style[0]) { + $this->_setStyle('U', $this->U>0, true); + $this->_setFontColor($this->font_color[0]); + } + } else { + $this->Cell( + $this->cell_info[0], + $this->cell_info[2], + $this->cell_text, + $this->cell_info[3], + $this->cell_info[6], + $this->cell_info[4], + $this->cell_info[5]); + } + break; + case "ROTATE": + $this->rotate(0); + break; + case "HEADER": + $this->_enforceState(63,50); + $this->parserBreak=''; + break; + case "FOOTER": + $this->_enforceState(64,50); + $this->parserBreak=''; + break; + case "COLUMN": + $this->_enforceState(50,50); + array_shift($this->multicol); + array_shift($this->left_margin); + array_shift($this->bottom_margin); + $this->SetLeftMargin($this->left_margin[0]); + $this->SetAutoPageBreak(true, $this->bottom_margin[0]); + break; + } + } + + function _enforceState($from, $to) { + if ($this->parserState!=$from) { + error_log("unexpected tag (from $from to $to, but state=".$this->parserState.")"); + //$this->Write("[unexpected tag (from $from to $to)]"); + } + $this->parserState=$to; + } + + // default is pt. works good for fonts, so yeah. + function _getUnit($str, $max=100) { + $str=rtrim($str); + $v=(float)$str; + if (substr($str,-1)=='%') { + return $max * $v / 100; + } + $u=substr($str,-2); + switch ($u) { + default: + case "pt": $m=1; break; + case "mm": $m=72/25.4; break; + case "cm": $m=72/2.54; break; + case "in": $m=72; break; + } + return $v * $m; + } + + function _getAttrUnit($default, $attr, $name, $ref) { + if (isset($attr[$name])) { + return $this->_getUnit($attr[$name], $ref); + } else { + return $default; + } + } + + function _setStyle($tag, $enable, $forget=0) { + $this->$tag+=($enable ? 1: -1); + $style=''; + foreach(array('B','I','U') as $s) { + if ($this->$s>0) { + $style.=$s; + } + } + $this->SetFont('',$style); + if ($forget) { + $this->$tag-=($enable ? 1: -1); + } + } + + function _setFontFace($face) { + $style=''; + foreach(array('B','I','U') as $s) { + if ($this->$s>0) { + $style.=$s; + } + } + $this->SetFont($face,$style); + } + + function _setFontColor($hex) { + $this->SetTextColor( + hexdec(substr($hex,0,2)), + hexdec(substr($hex,2,2)), + hexdec(substr($hex,4,2))); + } + + function _setLineColor($hex) { + $this->SetDrawColor( + hexdec(substr($hex,0,2)), + hexdec(substr($hex,2,2)), + hexdec(substr($hex,4,2))); + } + + function _setRectColor($hex) { + $this->SetFillColor( + hexdec(substr($hex,0,2)), + hexdec(substr($hex,2,2)), + hexdec(substr($hex,4,2))); + } + + +} + + +function ob_pdml($buffer) { + $pdml = new PDML('P','pt','A4'); // P and A4 should be customizable. XXX + $pdml->compress=0; + $pdml->ParsePDML($buffer); + $s = $pdml->Output("","S"); + Header('Content-Type: application/pdf'); + Header('Content-Length: '.strlen($s)); + Header('Content-disposition: inline; filename=doc.pdf'); + return $s; +} + +function pdml_entity_decode( $given_html, $quote_style = ENT_QUOTES ) { + $trans_table = array_flip(array_merge( + get_html_translation_table( HTML_SPECIALCHARS, $quote_style ), + get_html_translation_table( HTML_ENTITIES, $quote_style) )); + $trans_table['''] = "'"; + return ( strtr( $given_html, $trans_table ) ); +} + + +//ob_start("ob_pdml"); + +?>