--- /dev/null
+<?php
+
+/*
+The base node includes:
+ fromNode - convert the XML_Tree node into object with vars
+ (and parse styles)
+
+ // iternate tree with writePDF
+ writePDF($pdf,$data)
+ childrenWritePDF($pdf,$data)
+
+ // shift coordinates of group dynamic elements
+ // so the x is relative to the block corner.
+ shiftChildren($x,$y) {
+ shift($x,$y)
+
+ // find a dynamic block and calculate how much data it can hold.
+ // so you know how many pages are needed.
+ calcPerPage()
+*/
+
+class XML_SvgToPDF_Base {
+
+ var $x = 0;
+ var $y = 0;
+ var $width = 0; // used in svg..
+ var $height= 0;
+
+ var $style = array();
+ var $children = array();
+
+ var $transform = '';
+
+ function fromXmlNode($node)
+ {
+ // extract attributes
+ foreach($node->attributes as $k=>$v) {
+ if (in_array($k, array('style'))) {
+ continue;
+ }
+
+ $this->$k = $v->value;
+ if (preg_match('/[0-9]+mm$/',$v->value)) {
+ $vv = str_replace('mm','',$v->value);
+ $vv = $vv * 3.543307;
+
+ $this->$k = $vv;
+ continue;
+ }
+ }
+ // deal with style..
+ if ($node->hasAttribute('style') && strlen($node->getAttribute('style'))) {
+
+ $s = explode(';',$node->getAttribute('style'));
+ foreach($s as $ss) {
+ if (!strlen(trim($ss))) {
+ continue;
+ }
+ if (strpos($ss,':') === false) {
+ $style[$ss] = true;
+ continue;
+ }
+ $sss = explode(':',$ss);
+ if (preg_match('/[0-9]+pt$/',$sss[1])) {
+ $sss[1] = str_replace('pt','',$sss[1]);
+ }
+ $style[$sss[0]] = $sss[1];
+ }
+ $this->style = $style;
+ }
+
+ $this->transform();
+ // if node is a tspan
+
+
+
+ }
+
+
+ function fromNode($node) {
+
+ if ($node->attributes) {
+ foreach($node->attributes as $k=>$v) {
+
+ echo $node->name . ":" . $k . "=>". $v. "<BR>";
+
+ if (strpos($k,':')) {
+ $kk = explode(':',$k);
+ $k = $kk[1];
+ }
+ $this->$k = $v;
+ if (preg_match('/[0-9]+mm$/',$v)) {
+ $v = str_replace('mm','',$v);
+ $v = $v * 3.543307;
+
+ $this->$k = $v;
+ continue;
+ }
+
+ }
+ }
+
+ if (isset($this->style)) {
+ $s = explode(';',$this->style);
+ foreach($s as $ss) {
+ if (!strlen(trim($ss))) {
+ continue;
+ }
+ if (strpos($ss,':') === false) {
+ $style[$ss] = true;
+ continue;
+ }
+ $sss = explode(':',$ss);
+ if (preg_match('/[0-9]+pt$/',$sss[1])) {
+ $sss[1] = str_replace('pt','',$sss[1]);
+ }
+ $style[$sss[0]] = $sss[1];
+ }
+ $this->style = $style;
+ }
+
+
+ if ($node->content) {
+ $this->content = trim($node->content);
+ echo $node->name . ":CONTENT=>". $node->content. "<BR>";
+ }
+ if ($node->children) {
+ $this->children = $node->children;
+ }
+ echo "<PRE>BEFORE:";print_r($this->toArray());
+ $this->transform();
+ echo "<PRE>AFTER:";print_r($this->toArray());
+ }
+
+
+ function transform() {
+ if (empty($this->transform)) {
+ return;
+ }
+ // do not transform tspans -- done by overwriting this...
+ //if ($this->x === false) {
+ // return;
+ // }
+
+ // deal with transformation..
+ $tr = $this->transform;
+ if (preg_match('/scale\(([0-9e.-]+),([0-9e.-]+)\)/',$tr,$args)) {
+ $xscale = $args[1];
+ $yscale = $args[2];
+ $method = 'scale';
+ } else if (preg_match('/matrix\(([0-9e.-]+),([0-9e.-]+),([0-9e.-]+),([0-9e.-]+),([0-9e.-]+),([0-9e.-]+)\)/',$tr,$args)) {
+ array_shift($args);
+ require_once 'Math/Matrix.php';
+ $matrix = new Math_Matrix( array(
+ array($args[0],$args[2],$args[4]),
+ array($args[1],$args[3],$args[5]),
+ array( 0, 0, 1))
+ );
+ $method = 'matrix';
+ } else if (preg_match('/translate\(([0-9e.-]+),([0-9e.-]+)\)/',$tr,$args)) {
+ $x = $args[1];
+ $y = $args[2];
+ $method = 'translate';
+ } else {
+ echo "<PRE>no match?";print_r($this); exit;
+ return;
+ }
+ //
+ switch ($method) {
+ case 'scale':
+ $this->x *= $xscale;
+ $this->y *= $yscale;
+ if (empty($this->children)) {
+ return;
+ }
+ foreach(array_keys($this->children) as $i) {
+ if ($this->children[$i]->x === false) {
+ continue;
+ // echo "<PRE>";print_r($this);exit;
+ }
+ $this->children[$i]->x *= $xscale;
+ $this->children[$i]->y *= $yscale;
+ }
+ break;
+ case 'matrix':
+ $v = new Math_Vector(array($this->x,$this->y,0));
+
+ $r = $matrix->vectorMultiply($v);
+ $r = $r->getData();
+ $this->x = $r[0];
+ $this->y = $r[1];
+ //echo "<PRE>";var_dump( $r);exit;
+ if (empty($this->children)) {
+ return;
+ }
+ foreach(array_keys($this->children) as $i) {
+ if ($this->children[$i]->x === false) {
+ continue;
+ // echo "<PRE>";print_r($this);exit;
+ }
+ $v = new Math_Vector(array($this->children[$i]->x,$this->children[$i]->y,0));
+ $r = $matrix->vectorMultiply($v);
+ $r = $r->getData();
+ $this->children[$i]->x = $r[0];
+ $this->children[$i]->y = $r[1];
+
+ }
+ break;
+ case 'translate':
+ if ($this->x !== false && $this->y !== false) {
+
+ $this->x += $x;
+ $this->y += $y;
+ }
+ if (empty($this->children)) {
+ return;
+ }
+ foreach(array_keys($this->children) as $i) {
+ if ($this->children[$i]->x === false || $this->children[$i]->y === false) {
+ continue;
+ // echo "<PRE>";print_r($this);exit;
+ }
+ $this->children[$i]->x += $x;
+ $this->children[$i]->y += $y;
+ }
+ break;
+
+ }
+ }
+
+
+
+
+
+ function writePDF($pdf,&$data) {
+ $this->childrenWritePDF($pdf,$data);
+ }
+
+ function childrenWritePDF(&$pdf,&$data) {
+ if (!@$this->children) {
+ return;
+ }
+ foreach(array_keys($this->children) as $k) {
+ if (empty($this->children[$k])) {
+ continue;
+ }
+ if (!method_exists($this->children[$k],'writePDF')) {
+ echo "OOPS unknown object? <PRE>" ; print_r($this->children[$k]); exit;
+ }
+ $this->children[$k]->writePDF($pdf,$data);
+ }
+ }
+
+
+ // add the values to the children..
+ function shiftChildren($x,$y) {
+ if (empty($this->children)) {
+ return;
+ }
+ foreach(array_keys($this->children) as $k) {
+ if (!$this->children[$k]) {
+ continue;
+ }
+ $this->children[$k]->shift($x,$y);
+ }
+ }
+
+ function shift($x,$y) {
+ //XML_SvgToPDF::debug('shift');
+ //XML_SvgToPDF::debug(array($x,$y));
+ //XML_SvgToPDF::debug($this);
+
+ if ($x === false) {
+ return;
+ }
+
+ //var_dump(array("SHIFT", $x, $y, "TO: ", $this->x , $this->y));
+ if ($this->x !== false) {
+ $this->x += $x;
+ }
+ if ($this->y !== false) {
+ $this->y += $y;
+ }
+ //XML_SvgToPDF::debug($this);
+ $this->shiftChildren($x,$y);
+ }
+ function calcPerPage() {
+ $ret = array();
+ foreach($this->children as $n) {
+ if (!$n) {
+ continue;
+ }
+ if (!is_a($n, 'XML_SvgToPDF_G')) {
+ continue;
+ }
+ if (!isset($n->settings) || !isset($n->settings['dynamic'])) {
+ continue;
+ }
+
+
+ $rows = isset($n->settings['rows']) ? $n->settings['rows'] : 1;
+ $cols = isset($n->settings['cols']) ? $n->settings['cols'] : 1;
+ // return array($n->settings['dynamic'], $rows * $cols);
+
+
+ $ret[$n->settings['dynamic']] = $rows * $cols;
+
+
+
+
+ }
+ //return array('',0);
+
+ return $ret;
+
+
+
+
+
+ }
+
+ function toColor($color) {
+ if (!$color || ($color == 'none')) {
+ return false;
+ }
+
+ if ($color == 'black') {
+ $color = '#000000';
+ }
+
+ return array(
+ hexdec(substr($color,1,2)),
+ hexdec(substr($color,3,2)),
+ hexdec(substr($color,5,2)));
+
+ }
+ function toArray()
+ {
+ $ret = array();
+ $ar = (array) $this;
+ $ret['__CLASS__'] = get_class($this);
+ foreach($ar as $k=>$v) {
+ if (is_array($v) || is_object($v)) {
+ $ret[$k] = "**ARRAY|OBJECT**";
+ continue;
+ }
+ $ret[$k] = $v;
+ }
+ return $ret;
+ }
+
+
+}
--- /dev/null
+<?php
+
+/* code that deals with svg groups
+it does alot of smart stuff to handle 'dynamic' blocks
+
+*/
+
+
+class XML_SvgToPDF_G extends XML_SvgToPDF_Base
+{
+ var $boundingbox = false; // for repeats...
+ var $settings = array(); // cols/rows..
+
+ function fromXmlNode($node)
+ {
+ // print_r("G:fromXmlNode");
+ parent::fromXmlNode($node);
+
+
+ if (empty($this->dynamic)) {
+ return;
+ }
+ $settings = array(
+ 'rows' => $this->rows,
+ 'cols' => $this->cols,
+ 'dynamic' => $this->dynamic
+ );
+
+
+ //look for the bounding box..
+ $boundingbox = false;
+//echo "<PRE>";print_r($this->children);exit;
+ foreach(array_keys($this->children) as $k) {
+ if (!is_a($this->children[$k], 'XML_SvgToPDF_Rect')) {
+ continue;
+ }
+ if (empty($this->children[$k]->nonprintable) || ($this->children[$k]->nonprintable != 'true')) {
+ continue;
+ }
+ // echo "SETTING BOUNDING BOX"; exit;
+ $boundingbox = clone($this->children[$k]);
+ // box will be rendered..
+ $this->children[$k]->style['fill'] = 'none';
+ // unset($this->children[$k]);
+
+ }
+ if (!$boundingbox) {
+ return;
+ }
+ //echo "<PRE>";print_r($boundingbox ); exit;
+
+ $this->boundingbox = $boundingbox ;
+ $this->settings = $settings;
+
+ // change the X/Y values of all the child elements..
+
+
+ $this->shiftChildren(-1* $this->boundingbox->x,-1 * $this->boundingbox->y);
+ //$this->shiftChildren($this->boundingbox->x,$this->boundingbox->y);
+
+ }
+
+ // not sure why this is done twice?
+
+ function fromNode($node) {
+ parent::fromNode($node);
+
+
+//----------- applyDynamic...
+
+ // look for
+ if (empty($this->children)) {
+ return;
+ }
+
+ if (empty($this->dynamic)) {
+ return;
+ }
+ $settings = array(
+ 'rows' => $this->rows,
+ 'cols' => $this->cols,
+ 'dynamic' => $this->dynamic
+ );
+
+
+
+ //look for the bounding box..
+ $boundingbox = false;
+ foreach(array_keys($this->children) as $k) {
+ if (!is_a($this->children[$k], 'XML_SvgToPDF_Rect')) {
+ continue;
+ }
+ if (@$this->children[$k]->nonprintable == 'true') {
+ $boundingbox = clone($this->children[$k]);
+ $this->children[$k]->style['fill'] = 'none';
+ // unset($this->children[$k]);
+ }
+ }
+ if (!$boundingbox) {
+ return;
+ }
+ //echo "<PRE>";print_r($boundingbox );
+
+ $this->boundingbox = $boundingbox ;
+ $this->settings = $settings;
+ $this->shiftChildren($this->boundingbox->x,$this->boundingbox->y);
+ }
+
+ function shift($x,$y) {
+
+ if ($this->boundingbox) {
+ return;
+ }
+
+ $this->shiftChildren($x,$y);
+
+ }
+
+
+
+ function writePDF($pdf,&$data) {
+ // g group = does it have a
+ // look for
+ if (empty($this->children)) {
+ return;
+ }
+
+ // not dynamic.. -> just dump..
+ if (empty($this->settings)) {
+ return $this->childrenWritePDF($pdf,$data);
+ }
+
+ $use = false;
+ if (substr($this->settings['dynamic'],-2,2) == '()') {
+
+ $use = $data->{substr($this->settings['dynamic'],0,-2)}();
+
+ } else {
+ $use = empty($data[$this->settings['dynamic']]) ? '' : $data[$this->settings['dynamic']];
+ }
+
+
+ if (empty($use)) {
+ return;
+ }
+ // if use is a value - make it an array with a single element, so that the bounding box
+ // additions apply..
+ if (!is_array($use)) {
+ $use = array($use);
+ }
+
+ // echo "<PRE>";print_r($boundingbox );
+
+
+ $this->x = $x = $this->boundingbox->x;
+ $this->y =$y = $this->boundingbox->y;
+ $w = $this->boundingbox->width;
+ $h = $this->boundingbox->height;
+
+
+ //echo '<PRE>';print_r($this);exit;
+ // shift... ** this does not handle groups!!!
+
+ //print_R($use);
+ $keys = array_keys($use);
+ $kpos = 0;
+ $kmax = count($keys);
+ //XML_SvgToPDF::debug(array($x,$y,$w,$h));
+ //XML_SvgToPDF::debug($keys);
+ XML_SvgToPDF::debug($this->settings);
+
+ $yy = $y;
+
+ for($r=0;$r<$this->settings['rows'];$r++) {
+ $record = $use[$keys[$kpos]];
+
+
+ for($c=0;$c<$this->settings['cols'];$c++) {
+
+ $record = $use[$keys[$kpos]];
+
+ $xx = $x + ($c*$w);
+ XML_SvgToPDF::debug(array($xx,$yy));
+ foreach(array_keys($this->children) as $k) {
+ if (!$this->children[$k]) {
+ continue;
+ }
+
+ // if (is_object($use[$keys[$kpos]]) && method_exists($use[$keys[$kpos]], 'loadSvg')) {
+ // // set the defaults, as we cant do it in the thing now..
+ // $use[$keys[$kpos]]->loadSvg();
+ // }
+
+
+ $this->children[$k]->xx = $xx;
+ $this->children[$k]->yy = $yy;
+ $this->children[$k]->maxWidth = $w - 20;
+ $this->children[$k]->writePDF($pdf,$use[$keys[$kpos]]);
+ }
+ $kpos++;
+ if ($kpos >= $kmax) {
+ break 2;
+ }
+ }
+ $yy += !empty($record->userows) ? ($record->userows) * $h : $h;
+
+
+ }
+
+
+
+ }
+
+
+
+
+}
--- /dev/null
+<?php
+
+/* output a rectangle
+
+*/
+
+class XML_SvgToPDF_Image extends XML_SvgToPDF_Base {
+ function writePDF($pdf,$data) {
+
+
+ $dir = dirname($GLOBALS['_XML_SVGTOPDF']['options']['file']);
+ $pdf->Image($dir .'/'.basename($this->href), $this->x/ 3.543307, $this->y/ 3.543307, $this->width/ 3.543307,$this->height/ 3.543307);
+
+
+ }
+
+
+
+
+}
--- /dev/null
+<?php
+
+/* output a line
+
+*/
+
+class XML_SvgToPDF_Path extends XML_SvgToPDF_Base {
+ var $d; // stores the details of the path..
+
+
+ function fromXmlNode($node) {
+ parent::fromXmlNode($node);
+ $d = explode(' ',trim($this->d));
+ $i=0;
+ $data = array();
+
+ while ($i < count($d)) {
+ $action = $d[$i];
+ switch(strtolower($action)) {
+
+
+
+ case 'c': // ????
+
+ $data[] = array('L',$d[$i+3],$d[$i+4]);
+ $i+=7;
+ break;
+ case 'm': // move
+ case 'l': // line
+ $data[] = array($action,$d[$i+1],$d[$i+2]);
+ $i+=3;
+ break;
+ case 'h': // move horizontal
+ case 'v': // move horizontal
+ $data[] = array($action,$d[$i+1]);
+ $i+=2;
+ break;
+
+
+ case 'z': // close path..
+ $data[] = array($action);
+ $i++;
+ break;
+ default:
+ echo "oops found something odd in path? '$action'";
+ echo $this->d;
+ exit;
+ break;
+ }
+ }
+ $this->d = $data;
+ }
+
+
+ // TODO!! - shift!!!
+
+
+
+
+
+ function shift($x,$y) {
+ //XML_SvgToPDF::debug('shift');
+ //XML_SvgToPDF::debug(array($x,$y));
+ //XML_SvgToPDF::debug($this);
+ foreach($this->d as $i=>$a) {
+ if (count($a) < 2) {
+ continue;
+ }
+ if ($a[0] == 'v') {
+ $this->d[$i][1] -= $y;
+ } else {
+ $this->d[$i][1] -= $x;
+ if (isset($this->d[$i][2])) {
+ $this->d[$i][2] -= $y;
+ }
+ }
+ }
+
+ }
+
+
+
+ function writePDF($pdf,$data) {
+
+ $l = $this->toColor(@$this->style['stroke']);
+ if ($l) {
+ $pdf->setDrawColor($l[0],$l[1],$l[2]);
+ }
+ $pdf->setLineWidth($this->style['stroke-width']/ 3.543307);
+
+ $c = array();
+ if (count($this->d) > 2) {
+ $cc = array();
+ foreach($this->d as $a) {
+ if (count($a) < 2) {
+ continue;
+ }
+ $x = $a[1] + @$this->xx;
+ $y = $a[2] + @$this->yy;
+ $cc[] = $x/ 3.543307;
+ $cc[] = $y/ 3.543307;
+ }
+ $pdf->line($cc,0,0,0);
+ return;
+ }
+
+ foreach($this->d as $a) {
+ switch($a[0]) {
+ case 'M':
+ $x = $a[1] + @$this->xx;
+ $y = $a[2] + @$this->yy;
+ $c = array($x,$y);
+ break;
+
+ case 'L':
+ $x = $a[1] + @$this->xx;
+ $y = $a[2] + @$this->yy;
+ $pdf->line($c[0]/ 3.543307,$c[1]/ 3.543307,$x/ 3.543307,$y/ 3.543307);
+ $c = array($x,$y);
+ break;
+ default:
+ break;
+ }
+ }
+
+
+
+
+ }
+
+
+
+
+
+ function toColor($color) {
+ if (!$color || ($color == 'none')) {
+ return false;
+ }
+ return array(
+ hexdec(substr($color,1,2)),
+ hexdec(substr($color,3,2)),
+ hexdec(substr($color,5,2)));
+
+ }
+
+
+
+}
--- /dev/null
+<?php
+
+/* output a rectangle
+
+*/
+
+class XML_SvgToPDF_Rect extends XML_SvgToPDF_Base {
+
+ var $xx = 0;
+ var $yy = 0;
+ var $nonprintable = false;
+
+ function writePDF($pdf,$data) {
+
+ //print_r(array("rect:", $this->x , $this->y , ':', $this->xx, $this->yy));
+
+ $x = $this->x + @$this->xx;
+ $y = $this->y + @$this->yy;
+
+
+
+ $pdf->setLineWidth($this->style['stroke-width']);
+ $f = $this->toColor($this->style['fill']);
+ if ($f) {
+ $pdf->setFillColor($f[0],$f[1],$f[2]);
+ }
+
+ $l = $this->toColor(@$this->style['stroke']);
+ if ($l) {
+ $pdf->setDrawColor($l[0],$l[1],$l[2]);
+ }
+ // no fill, no line = dont draw...
+ if (!$l && !$f) {
+ return;
+ }
+ XML_SvgToPDF::debug("RECT:" .($x/ 3.543307).',' .($y/ 3.543307). ','
+ .($this->width/ 3.543307).',' . ($this->height/ 3.543307));
+ $pdf->rect($x/ 3.543307,$y/ 3.543307,
+ $this->width/ 3.543307,$this->height/ 3.543307,($l ? 'D' : ''). ($f ? 'F' : ''));
+
+
+
+ }
+
+
+ function toColor($color) {
+ if (!$color || ($color == 'none')) {
+ return false;
+ }
+ return array(
+ hexdec(substr($color,1,2)),
+ hexdec(substr($color,3,2)),
+ hexdec(substr($color,5,2)));
+
+ }
+
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+
+class XML_SvgToPDF_Text extends XML_SvgToPDF_Base {
+
+ function fromXmlNode($node) {
+
+ parent::fromXmlNode($node);
+
+ // any text ???
+ if (empty($this->children) || empty($this->children[0]->content)) {
+ return;
+ }
+
+ // modify the alignment of the if this block content of the first child is "=="
+
+ if (substr($this->children[0]->content,0,2) == '==') {
+ $this->style['text-anchor'] = 'justify';
+ $this->children[0]->content = substr($this->children[0]->content,2);
+ }
+ }
+
+ function transform() {
+
+ parent::transform();
+ if (empty($this->transform)) {
+ return;
+ }
+ if (preg_match('/scale\(([0-9e.-]+),([0-9e.-]+)\)/',$this->transform,$args)) {
+ $xscale = $args[1]; // do we use this??? = what do do about 'e'?
+ $yscale = $args[2];
+ $this->style['font-size'] *= $args[1];
+ }
+ }
+
+
+
+ function writePDF($pdf,$data) {
+ // set up font..
+
+ $font = strtolower($this->style['font-family']);
+ $font = trim($font, "'");
+
+ static $map = array(
+ 'times new roman' => 'times',
+ 'courier new' => 'courier',
+ 'arial' => 'arial',
+ );
+ if (isset($map[$font])) {
+ $font = $map[$font];
+ } else {
+ $font = 'times';
+ }
+ $ffont = $font;
+ if (preg_match('/big5/i',$this->style['font-family'])) {
+ $ffont = 'ARIALUNI';
+ $font = 'arial'; // default if not big4
+ }
+
+
+
+ $weight = '';
+ if ($this->style['font-weight'] == 'bold') {
+ $weight .= 'B';
+ }
+ if (@$this->style['font-style'] == 'italic') {
+ $weight .= 'I';
+ }
+
+ if (@$this->style['text-decoration'] == 'underline') {
+ $weight .= 'U';
+ }
+ // size..
+ $size = $this->style['font-size'] * 0.85;
+
+ $pdf->setFont($font,$weight,$size);
+
+ switch(@$this->style['text-anchor']) {
+ case 'end':
+ $align = 'E';
+ break;
+ case 'middle':
+ $align = 'M';
+ break;
+ case 'justify':
+ $align = 'J';
+ $max = 0;
+ foreach ($this->children as $child) {
+ if (!@$child->content) {
+ continue;
+ }
+ $l = $pdf->getStringWidth($child->content);
+ $max = ($l > $max) ? $l : $max;
+ }
+ // fudge factor!
+ $this->justifyLen = $max;
+ break;
+ default:
+ $align = 'L';
+
+ }
+
+ $f = $this->toColor(@$this->style['fill']);
+ if ($f) {
+ $pdf->setTextColor($f[0],$f[1],$f[2]);
+ }
+
+
+
+ $yoffset = 0;
+ $x = $this->x + @$this->xx;
+ $y = $this->y + @$this->yy;
+ if (empty($this->children)) {
+ return;
+ }
+ $lineno = 0;
+ foreach($this->children as $i=>$c) {
+
+ $xx = $c->x !== false ? $c->x + @$this->xx : $x;
+ $yy = $c->y !== false ? $c->y + @$this->yy : $y + ($lineno * $size * 1.3);
+ $lineno++;
+ $val = $c->content;
+ if ($ffont == 'ARIALUNI') { //) && preg_match('/[\x7f-\xff]+/',$val)) {
+ $pdf->setFont('ARIALUNI' ,
+ $weight,
+ $size);
+ }
+ if (isset($c->args)) {
+
+ $args = array();
+ foreach($c->args as $v) {
+ if ($v == 'page') {
+ $args[] = $pdf->PageNo();
+ continue;
+ }
+ if ($v == 'nb') {
+ $args[] = '{nb}';
+ continue;
+ }
+
+ // echo "GET: $v : '$val'<BR>";
+ $args[] = trim($this->getValue($data,trim($v))); // removes trailing CRLF...
+ }
+
+
+ $has_template = preg_match('/%s/', $val);
+
+ $val = trim(vsprintf($val,$args));
+
+ if ($has_template && ($ffont == 'ARIALUNI') && preg_match('/[\x7f-\xff]+/',$val)) {
+ //require_once 'Text/ZhDetect.php';
+ //$detect = new Text_zhDetect;
+ //$type = $detect->guess($val);
+ //if ($v == 'S') {
+
+ // $val = @iconv('utf8', 'GB2312//IGNORE', $val);
+ // $pdf->setFont('GB' ,
+ // $weight,
+ // $size);
+ //} else {
+// $val = @iconv('utf8', 'BIG5//IGNORE', $val);
+ $pdf->setFont('ARIALUNI' ,
+ $weight,
+ $size);
+ //}
+ } else {
+ $val = @iconv('utf8','ascii//ignore',$val);
+ }
+
+
+
+
+ }
+ $talign = $align;
+ if ((!@$this->children[$i+1] || !strlen(trim(@$this->children[$i+1]->content))) && ($align == 'J')) {
+ $talign = 'L';
+ }
+
+ $yoffset += $this->multiLine($pdf, str_replace("\r", "", explode("\n",$val)),
+ $xx/ 3.543307,
+ ($yy / 3.543307) + $yoffset,
+ ($size / 3.543307) + 1,
+ $talign
+ );
+
+
+ }
+
+ // now daraw
+
+ }
+
+ /**
+ * get a value from the data
+ *
+ * eg. $data = array(
+ * 'fred' => 'somevalue'
+ *
+ * getValue ($data,'fred') returns 'somevalue'
+ *
+ * value can also be a method = eg. getFred()
+ *
+ * @param object|array $data
+ * @param string $v key to get.
+ *
+ *
+ * @return string
+ * @access public
+ */
+
+ function getValue($data,$v) {
+
+ // print_R(array("GET VALUE: ", $v));
+ // not a method:
+
+ if ($v[strlen($v)-1] != ')') {
+
+ $data = (array) $data;
+ //echo "<PRE>";print_r(array_keys($data));
+ if (false === strpos($v,'.')) {
+ if (!isset($data[$v])) {
+ // echo "missing $v\n";
+ return '';
+ }
+ if (is_array($data[$v]) || is_object($data[$v])) {
+ // echo "array/object $v\n";
+ return '';
+ }
+ //echo "returning $v\n";
+ return $data[$v];
+ }
+ $dd = (array)$data;
+ foreach(explode('.', $v) as $vv) {
+ if (!is_array($dd)) {
+ return '';
+ }
+ if (!isset($dd[$vv])) {
+ return '';
+ }
+ $dd = is_object($dd[$vv]) ? ((array) $dd[$vv]) : $dd[$vv];
+ }
+ //echo "ATTEMPT: $v: got $dd\n";
+ //exit;
+ if (is_array($dd) || is_object($dd)) {
+ return '';
+ }
+ return $dd;
+ }
+ // method !!!
+ if (!is_object($data)) {
+ return '';
+ }
+ $method = substr($v,0,-2);
+
+ if (is_object($data) && method_exists($data,$method)) {
+ // echo "call $method<BR>";
+ $ret = $data->$method();
+ // echo "done $method $ret<BR>";
+ if (is_array($ret) || is_object($ret)) {
+ return '';
+ }
+ return '' . $ret;
+ }
+
+ //echo
+ //print_r($data);
+
+ //exit;
+ return "no method $method in ".get_class($data);
+
+
+ }
+
+
+ function breakLines($pdf,$str,$x,$y,$h,$align) {
+ // do the estimation...
+ $len = strlen($str);
+
+ $total = $pdf->getStringWidth($str . ' ');
+
+ $charsize = $total/$len;
+
+ $max_chars = floor(($this->maxWidth / 3.543307) / $charsize);
+ //echo "LEN: $len, $total, $charsize, $max_chars";
+ $lines = explode("\n",wordwrap($str,$max_chars));
+
+ return $this->multiLine($pdf,$lines,$x,$y,$h,$align);
+ }
+ var $maxWidth = false;
+
+ function multiLine($pdf,$lines,$x,$y,$h,$align) {
+ // now dealing with mm
+ ///XML_SvgToPDF::debug("MULTILINE " .implode("\n",$lines) . " $x, $y, $h");
+ $yoffset = 0;
+ $line = -1;
+ foreach ($lines as $l=>$v) {
+ $line++;
+ if ($this->maxWidth !== false && ($pdf->getStringWidth($v) > ($this->maxWidth / 3.543307))) {
+ $yoffset += $this->breakLines($pdf,$v,$x,$y + ($l * $h) + $yoffset, $h,$align);
+ continue;
+ }
+ XML_SvgToPDF::debug("TEXT: $x,$y, $l * $h + $yoffset,$v");
+ $xoffset = 0;
+ if ($align == 'M') { // center
+ $xoffset = -1 * ($pdf->getStringWidth($v) / 2);
+ }
+ if ($align == 'E') { // right/end
+ $xoffset = -1 * $pdf->getStringWidth($v);
+ }
+
+ if ($align == 'J' ) { // justified (eg. started with ==
+ $this->justify($pdf, $x , $y + ($l * $h) + $yoffset , $v, $this->justifyLen);
+ continue;
+ }
+ $pdf->text(
+ $xoffset + $x ,
+ $y + ($l * $h) + $yoffset ,
+ $v);
+
+ }
+ return ($l * $h) + $yoffset;
+
+ }
+
+
+ function justify($pdf,$x,$y,$text,$len) {
+ if (!strlen(trim($text))) {
+ return;
+ }
+ $bits = explode(' ', $text);
+ $textlen = $pdf->getStringWidth(implode('',$bits));
+ $spacesize = ($len - $textlen) / (count($bits) -1);
+ foreach($bits as $word) {
+ $pdf->text($x , $y ,$word );
+ $x += $spacesize + $pdf->getStringWidth($word);
+ }
+ }
+
+
+
+}
--- /dev/null
+<?php
+
+/* the actual text container..
+
+does a quick bit of parsing to see if it a {template}var ..
+*/
+
+class XML_SvgToPDF_Tspan extends XML_SvgToPDF_Base {
+
+ var $content = ''; // applies to tspan only..
+ var $x = false;
+ var $y = false;
+ var $args = array(); // arguments..
+ function fromXmlNode($node) {
+ parent::fromXmlNode($node);
+ $this->x = false;
+ $this->y = false;
+ $this->content = $node->textContent;
+ /*
+ if (isset($this->x)) {
+ unset($this->x);
+ }
+ if (isset($this->y)) {
+ unset($this->y);
+ }
+ */
+ static $trans = false;
+ if (!$trans) {
+ $trans = array_flip(get_html_translation_table(HTML_ENTITIES));
+ }
+
+ if (strlen($this->content)) {
+ // convert & etc.
+ if (strpos($this->content,'&') !== false) {
+ $this->content = strtr($this->content, $trans);
+ $this->content = str_replace(''',"'",$this->content);
+
+ $this->content = preg_replace_callback('/&#(\d+);/m', array($this, 'content_replace'),
+ $this->content);
+ }
+ if (!empty($node->language)) {
+ // todo - other conversions....
+ $this->content = mb_convert_encoding($this->content,'BIG-5','UTF-8');
+
+ }
+ // dynamic parts..
+ if (false === strpos($this->content,'{')) {
+ return;
+ }
+ preg_match_all('/\{([a-z0-9_.]+(\(\))?)\}/i',$this->content,$matches);
+
+ $this->args = $matches[1];
+ foreach($this->args as $v) {
+ $this->content = str_replace('{'.$v.'}', '%s',$this->content);
+ }
+ //$this->content = preg_replace('/\{('.implode('|',$matches[1]).')\}/','%s',$this->content);
+ }
+
+
+ }
+
+ function content_replace($matches) { // php5.2 needs this to be a function...
+ return chr($matches[1]);
+ }
+
+
+ function shift() // disable shifting on text
+ {
+ return;
+ }
+ function transform()
+ {
+
+ }
+
+
+
+
+}