/**
  * Get a instance of a Path.
  *
  * @param string or array $d the points
  * @param string $id of element
  * @param string or SVGStyle object $style of element
  * 
  * @return SVGPath
  */
 public static function getInstance($d, $id, $style)
 {
     $path = new SVGPath('<path></path>');
     //if is as array make implode to glue it
     if (is_array($d)) {
         $d = implode(' ', $d);
     }
     $path->setAttribute('d', $d);
     $path->setId($id);
     $path->setAttribute('style', $style);
     return $path;
 }
Beispiel #2
0
 private static function parseNode($node)
 {
     $type = $node->getName();
     if ($type === 'g') {
         $element = new SVGGroup();
         $children = $node->children();
         foreach ($children as $child) {
             $element->addChild(self::parseNode($child));
         }
     } else {
         if ($type === 'rect') {
             $w = isset($node['width']) ? $node['width'] : 0;
             $h = isset($node['height']) ? $node['height'] : 0;
             $x = isset($node['x']) ? $node['x'] : 0;
             $y = isset($node['y']) ? $node['y'] : 0;
             $element = new SVGRect($x, $y, $w, $h);
         } else {
             if ($type === 'circle') {
                 $cx = isset($node['cx']) ? $node['cx'] : 0;
                 $cy = isset($node['cy']) ? $node['cy'] : 0;
                 $r = isset($node['r']) ? $node['r'] : 0;
                 $element = new SVGCircle($cx, $cy, $r);
             } else {
                 if ($type === 'ellipse') {
                     $cx = isset($node['cx']) ? $node['cx'] : 0;
                     $cy = isset($node['cy']) ? $node['cy'] : 0;
                     $rx = isset($node['rx']) ? $node['rx'] : 0;
                     $ry = isset($node['ry']) ? $node['ry'] : 0;
                     $element = new SVGEllipse($cx, $cy, $rx, $ry);
                 } else {
                     if ($type === 'line') {
                         $x1 = isset($node['x1']) ? $node['x1'] : 0;
                         $y1 = isset($node['y1']) ? $node['y1'] : 0;
                         $x2 = isset($node['x2']) ? $node['x2'] : 0;
                         $y2 = isset($node['y2']) ? $node['y2'] : 0;
                         $element = new SVGLine($x1, $y1, $x2, $y2);
                     } else {
                         if ($type === 'polygon' || $type === 'polyline') {
                             $element = $type === 'polygon' ? new SVGPolygon() : new SVGPolyline();
                             $points = isset($node['points']) ? preg_split('/[\\s,]+/', $node['points']) : array();
                             for ($i = 0, $n = floor(count($points) / 2); $i < $n; $i++) {
                                 $element->addPoint($points[$i * 2], $points[$i * 2 + 1]);
                             }
                         } else {
                             if ($type === 'path') {
                                 $d = isset($node['d']) ? $node['d'] : '';
                                 $element = new SVGPath($d);
                             }
                         }
                     }
                 }
             }
         }
     }
     if (!isset($element)) {
         return false;
     }
     $attributes = $node->attributes();
     $ignoredAttributes = array('x', 'y', 'width', 'height', 'x1', 'y1', 'x2', 'y2', 'cx', 'cy', 'r', 'rx', 'ry', 'points', 'style');
     foreach ($attributes as $attribute => $value) {
         if (in_array($attribute, $ignoredAttributes)) {
             continue;
         }
         $element->setStyle($attribute, $value);
     }
     if (isset($node['style'])) {
         $styles = self::parseStyles($node['style']);
         foreach ($styles as $style => $value) {
             $element->setStyle($style, $value);
         }
     }
     return $element;
 }
Beispiel #3
0
for ($x = 0; $x < $imgW; $x++) {
    for ($y = 0; $y < $imgH; $y++) {
        $rgb = imagecolorat($img, $x, $y);
        $color = imagecolorsforindex($img, $rgb);
        if ($color['alpha'] < 126) {
            $hex = RGBToHex($color['red'], $color['green'], $color['blue']);
            //$rect = SVGRect::getInstance( $x, $y, null, 1, 1, new SVGStyle( array( 'fill' => $hex ) ) );
            //$d = "m $x,$y 1,0 0,1 -1,0 z";
            $x1 = $x + 1;
            $y1 = $y + 1;
            $d = "M {$x},{$y} {$x},{$y1} {$x1},{$y1} {$x1},{$y} ";
            @($paths[$hex] .= $d);
            /* @$paths[$hex][$x . ',' . $y] = $x . ',' . $y;
               @$paths[$hex][$x . ',' . $y1] = $x . ',' . $y1;
               @$paths[$hex][$x1 . ',' . $y1] = $x1 . ',' . $y1;
               @$paths[$hex][$x1 . ',' . $y] = $x1 . ',' . $y; */
            //M 25,20 25,21 26,21 26,20 z
            //$path = SVGPath::getInstance( $d, null, new SVGStyle( array( 'fill' => $hex ) ) );
            //$svg->append( $path );
        }
    }
}
echo '<pre>';
foreach ($paths as $hex => $d) {
    //$d = implode( ' L ', $res );
    $path = SVGPath::getInstance($d . ' z', null, new SVGStyle(array('fill' => $hex)));
    $svg->append($path);
}
$svg->asXML($svgPath, TRUE);
echo "<img src='{$imagePath}'/>";
echo '<embed style="border:solid 1px gray;" src="' . $svgPath . '" type="image/svg+xml" pluginspage="http://www.adobe.com/svg/viewer/install/" /><br / >';
Beispiel #4
0
 private function parseLines()
 {
     /* Set standard line options */
     $this->svgObjects->pushGroup('lines');
     $this->svgObjects->setOption('stroke', 'black');
     $this->svgObjects->setOption('stroke-width', '2');
     $this->svgObjects->setOption('fill', 'none');
     /* The grid is not uniform, so we need to determine the longest row. */
     $maxCols = 0;
     $bound = count($this->grid);
     for ($r = 0; $r < $bound; $r++) {
         $maxCols = max($maxCols, count($this->grid[$r]));
     }
     for ($c = 0; $c < $maxCols; $c++) {
         for ($r = 0; $r < $bound; $r++) {
             /* This gets set if we find a line-start here. */
             $dir = false;
             $line = new SVGPath();
             /*
              * Since the column count isn't uniform, don't attempt to handle any
              * rows that don't extend out this far.
              */
             if (!isset($this->grid[$r][$c])) {
                 continue;
             }
             $char = $this->getChar($r, $c);
             switch ($char) {
                 /*
                  * Do marker characters first. These are the easiest because they are
                  * basically guaranteed to represent the start of the line.
                  */
                 case '<':
                     $e = $this->getChar($r, $c + 1);
                     if ($this->isEdge($e, self::DIR_RIGHT) || $this->isCorner($e)) {
                         $line->addMarker($c, $r, Point::IMARKER);
                         $dir = self::DIR_RIGHT;
                     } else {
                         $se = $this->getChar($r + 1, $c + 1);
                         $ne = $this->getChar($r - 1, $c + 1);
                         if ($se == "\\") {
                             $line->addMarker($c, $r, Point::IMARKER);
                             $dir = self::DIR_SE;
                         } elseif ($ne == '/') {
                             $line->addMarker($c, $r, Point::IMARKER);
                             $dir = self::DIR_NE;
                         }
                     }
                     break;
                 case '^':
                     $s = $this->getChar($r + 1, $c);
                     if ($this->isEdge($s, self::DIR_DOWN) || $this->isCorner($s)) {
                         $line->addMarker($c, $r, Point::IMARKER);
                         $dir = self::DIR_DOWN;
                     } elseif ($this->getChar($r + 1, $c + 1) == "\\") {
                         /* Don't need to check west for diagonals. */
                         $line->addMarker($c, $r, Point::IMARKER);
                         $dir = self::DIR_SE;
                     }
                     break;
                 case '>':
                     $w = $this->getChar($r, $c - 1);
                     if ($this->isEdge($w, self::DIR_LEFT) || $this->isCorner($w)) {
                         $line->addMarker($c, $r, Point::IMARKER);
                         $dir = self::DIR_LEFT;
                     }
                     /* All diagonals come from west, so we don't need to check */
                     break;
                 case 'v':
                     $n = $this->getChar($r - 1, $c);
                     if ($this->isEdge($n, self::DIR_UP) || $this->isCorner($n)) {
                         $line->addMarker($c, $r, Point::IMARKER);
                         $dir = self::DIR_UP;
                     } elseif ($this->getChar($r - 1, $c + 1) == '/') {
                         $line->addMarker($c, $r, Point::IMARKER);
                         $dir = self::DIR_NE;
                     }
                     break;
                     /*
                      * Edges are handled specially. We have to look at the context of the
                      * edge to determine whether it's the start of a line. A vertical edge
                      * can appear as the start of a line in the following circumstances:
                      *
                      * +-------------      +--------------     +----    | (s)
                      * |                   |                   |        |
                      * |      | (s)        +-------+           |(s)     |
                      * +------+                    | (s)
                      *
                      * From this we can extrapolate that we are a starting edge if our
                      * southern neighbor is a vertical edge or corner, but we have no line
                      * material to our north (and vice versa). This logic does allow for
                      * the southern / northern neighbor to be part of a separate
                      * horizontal line.
                      */
                 /*
                  * Edges are handled specially. We have to look at the context of the
                  * edge to determine whether it's the start of a line. A vertical edge
                  * can appear as the start of a line in the following circumstances:
                  *
                  * +-------------      +--------------     +----    | (s)
                  * |                   |                   |        |
                  * |      | (s)        +-------+           |(s)     |
                  * +------+                    | (s)
                  *
                  * From this we can extrapolate that we are a starting edge if our
                  * southern neighbor is a vertical edge or corner, but we have no line
                  * material to our north (and vice versa). This logic does allow for
                  * the southern / northern neighbor to be part of a separate
                  * horizontal line.
                  */
                 case ':':
                     $line->setOption('stroke-dasharray', '5 5');
                     /* FALLTHROUGH */
                 /* FALLTHROUGH */
                 case '|':
                     $n = $this->getChar($r - 1, $c);
                     $s = $this->getChar($r + 1, $c);
                     if (($s == '|' || $s == ':' || $this->isCorner($s)) && $n != '|' && $n != ':' && !$this->isCorner($n) && $n != '^') {
                         $dir = self::DIR_DOWN;
                     } elseif (($n == '|' || $n == ':' || $this->isCorner($n)) && $s != '|' && $s != ':' && !$this->isCorner($s) && $s != 'v') {
                         $dir = self::DIR_UP;
                     }
                     break;
                     /*
                      * Horizontal edges have the same properties for search as vertical
                      * edges, except we need to look east / west. The diagrams for the
                      * vertical case are still accurate to visualize this case; just
                      * mentally turn them 90 degrees clockwise.
                      */
                 /*
                  * Horizontal edges have the same properties for search as vertical
                  * edges, except we need to look east / west. The diagrams for the
                  * vertical case are still accurate to visualize this case; just
                  * mentally turn them 90 degrees clockwise.
                  */
                 case '=':
                     $line->setOption('stroke-dasharray', '5 5');
                     /* FALLTHROUGH */
                 /* FALLTHROUGH */
                 case '-':
                     $w = $this->getChar($r, $c - 1);
                     $e = $this->getChar($r, $c + 1);
                     if (($w == '-' || $w == '=' || $this->isCorner($w)) && $e != '=' && $e != '-' && !$this->isCorner($e) && $e != '>') {
                         $dir = self::DIR_LEFT;
                     } elseif (($e == '-' || $e == '=' || $this->isCorner($e)) && $w != '=' && $w != '-' && !$this->isCorner($w) && $w != '<') {
                         $dir = self::DIR_RIGHT;
                     }
                     break;
                     /*
                      * We can only find diagonals going north or south and east. This is
                      * simplified due to the fact that they have no corners. We are
                      * guaranteed to run into their westernmost point or their relevant
                      * marker.
                      */
                 /*
                  * We can only find diagonals going north or south and east. This is
                  * simplified due to the fact that they have no corners. We are
                  * guaranteed to run into their westernmost point or their relevant
                  * marker.
                  */
                 case '/':
                     $ne = $this->getChar($r - 1, $c + 1);
                     if ($ne == '/' || $ne == '^' || $ne == '>') {
                         $dir = self::DIR_NE;
                     }
                     break;
                 case "\\":
                     $se = $this->getChar($r + 1, $c + 1);
                     if ($se == "\\" || $se == "v" || $se == '>') {
                         $dir = self::DIR_SE;
                     }
                     break;
                     /*
                      * The corner case must consider all four directions. Though a
                      * reasonable person wouldn't use slant corners for this, they are
                      * considered corners, so it kind of makes sense to handle them the
                      * same way. For this case, envision the starting point being a corner
                      * character in both the horizontal and vertical case. And then
                      * mentally overlay them and consider that :).
                      */
                 /*
                  * The corner case must consider all four directions. Though a
                  * reasonable person wouldn't use slant corners for this, they are
                  * considered corners, so it kind of makes sense to handle them the
                  * same way. For this case, envision the starting point being a corner
                  * character in both the horizontal and vertical case. And then
                  * mentally overlay them and consider that :).
                  */
                 case '+':
                 case '#':
                     $ne = $this->getChar($r - 1, $c + 1);
                     $se = $this->getChar($r + 1, $c + 1);
                     if ($ne == '/' || $ne == '^' || $ne == '>') {
                         $dir = self::DIR_NE;
                     } elseif ($se == "\\" || $se == "v" || $se == '>') {
                         $dir = self::DIR_SE;
                     }
                     /* FALLTHROUGH */
                 /* FALLTHROUGH */
                 case '.':
                 case "'":
                     $n = $this->getChar($r - 1, $c);
                     $w = $this->getChar($r, $c - 1);
                     $s = $this->getChar($r + 1, $c);
                     $e = $this->getChar($r, $c + 1);
                     if (($w == '=' || $w == '-') && $n != '|' && $n != ':' && $w != '-' && $e != '=' && $e != '|' && $s != ':') {
                         $dir = self::DIR_LEFT;
                     } elseif (($e == '=' || $e == '-') && $n != '|' && $n != ':' && $w != '-' && $w != '=' && $s != '|' && $s != ':') {
                         $dir = self::DIR_RIGHT;
                     } elseif (($s == '|' || $s == ':') && $n != '|' && $n != ':' && $w != '-' && $w != '=' && $e != '-' && $e != '=' && ($char != '.' && $char != "'" || $char == '.' && $s != '.' || $char == "'" && $s != "'")) {
                         $dir = self::DIR_DOWN;
                     } elseif (($n == '|' || $n == ':') && $s != '|' && $s != ':' && $w != '-' && $w != '=' && $e != '-' && $e != '=' && ($char != '.' && $char != "'" || $char == '.' && $s != '.' || $char == "'" && $s != "'")) {
                         $dir = self::DIR_UP;
                     }
                     break;
             }
             /* It does actually save lines! */
             if ($dir !== false) {
                 $rInc = 0;
                 $cInc = 0;
                 if (!$this->isMarker($char)) {
                     $line->addPoint($c, $r);
                 }
                 /*
                  * The walk routine may attempt to add the point again, so skip it.
                  * If we don't, we can miss the line or end up with just a point.
                  */
                 if ($dir == self::DIR_UP) {
                     $rInc = -1;
                     $cInc = 0;
                 } elseif ($dir == self::DIR_DOWN) {
                     $rInc = 1;
                     $cInc = 0;
                 } elseif ($dir == self::DIR_RIGHT) {
                     $rInc = 0;
                     $cInc = 1;
                 } elseif ($dir == self::DIR_LEFT) {
                     $rInc = 0;
                     $cInc = -1;
                 } elseif ($dir == self::DIR_NE) {
                     $rInc = -1;
                     $cInc = 1;
                 } elseif ($dir == self::DIR_SE) {
                     $rInc = 1;
                     $cInc = 1;
                 }
                 /*
                  * Walk the points of this line. Note we don't use wallFollow; we are
                  * operating under the assumption that lines do not meander. (And, in
                  * any event, that algorithm is intended to find a closed object.)
                  */
                 $this->walk($line, $r + $rInc, $c + $cInc, $dir);
                 /*
                  * Remove it so that we don't confuse any other lines. This leaves
                  * corners in tact, still.
                  */
                 $this->clearObject($line);
                 $this->svgObjects->addObject($line);
                 /* We may be able to find more lines starting from this same point */
                 if ($this->isCorner($char)) {
                     $r--;
                 }
             }
         }
     }
     $this->svgObjects->popGroup();
 }