Changeset 336
- Timestamp:
- 03/07/08 08:33:04 (4 years ago)
- Location:
- cleversvg/trunk
- Files:
-
- 14 added
- 15 modified
-
CHANGELOG (modified) (2 diffs)
-
INSTALL (modified) (1 diff)
-
base/csBaseElement.class.php (modified) (3 diffs)
-
cleversvg.php (modified) (1 diff)
-
container (added)
-
container/csElementsContainer.class.php (added)
-
document/csDocument.class.php (modified) (29 diffs)
-
elements/csEllipse.class.php (modified) (7 diffs)
-
elements/csGroup.class.php (modified) (3 diffs)
-
elements/csLink.class.php (modified) (5 diffs)
-
elements/csPath.class.php (modified) (18 diffs)
-
exceptions/csException.class.php (modified) (1 diff)
-
importer (added)
-
importer/csImporter.class.php (added)
-
quick_examples.php (modified) (1 diff)
-
tests/csBaseTestCase.class.php (modified) (5 diffs)
-
tests/csCircleTest.php (modified) (1 diff)
-
tests/csDocumentTest.php (modified) (4 diffs)
-
tests/csEllipseTest.php (added)
-
tests/csGroupTest.php (added)
-
tests/csImageTest.php (added)
-
tests/csImporterTest.php (added)
-
tests/csLineTest.php (added)
-
tests/csLinkTest.php (added)
-
tests/csPathTest.php (added)
-
tests/csPolylineTest.php (added)
-
tests/csRectTest.php (added)
-
tests/csTestSuite.php (modified) (2 diffs)
-
tests/csTextTest.php (added)
Legend:
- Unmodified
- Added
- Removed
-
cleversvg/trunk/CHANGELOG
r327 r336 1 1 == Roadmap == 2 2 3 === version 0.6 === 3 4 * Write complete PHPUnit test suite … … 7 8 8 9 == Changelog == 10 11 === 2008-03-XX - 0.6 === 12 * Complete PHPUnit test suite 13 * Refactorized containers classes (BC) 14 9 15 === 2008-02-26 - 0.5 === 10 16 * Initial public release. Features: -
cleversvg/trunk/INSTALL
r315 r336 3 3 4 4 ==== Installation ==== 5 The CleverSvg library is only available through svn export :5 The CleverSvg library is only available through svn export at this time: 6 6 {{{ 7 $ svn export http://www.clever-age.org/svn/cleversvg/trunk/ cleversvg 7 $ svn export http://www.clever-age.org/svn/cleversvg/trunk/ cleversvg 8 8 }}} 9 9 -
cleversvg/trunk/base/csBaseElement.class.php
r335 r336 76 76 } 77 77 } 78 $element_node->setAttribute('style', implode('; ', $styles)); 78 if (count($styles) > 0) 79 { 80 $element_node->setAttribute('style', implode('; ', $styles)); 81 } 79 82 break; 80 83 default: … … 260 263 if (!is_null($value)) 261 264 { 262 $this->attributes[ $name] = $value;265 $this->attributes[strtolower($name)] = $value; 263 266 } 264 267 } … … 271 274 public function setDepth($depth) 272 275 { 273 if (!is_null($depth) && is_int($depth)) 276 if (is_null($depth)) 277 { 278 unset($this->attributes['style']['z-index']); 279 } 280 elseif (is_int($depth)) 274 281 { 275 282 $this->attributes['style']['z-index'] = (string) $depth; -
cleversvg/trunk/cleversvg.php
r318 r336 1 <?php 2 /** 3 * CleverSvg library 4 * Include this file to be able to use the library, eg. : 5 * <pre> 6 * require_once('cleversvg.php'); 7 * $doc = new csDocument(550, 400, 'Untitled Document'); 8 * $rect = new csRect(10, 10, 100, 100); 9 * $rect->setFill('red'); 10 * $doc->addElement($rect); 11 * header("content-type: image/svg+xml; charset=utf-8"); 12 * echo $doc->toXML(); 13 * </pre> 14 * 15 * @author Nicolas Perriault <nperriault@gmail.com> 16 * @package cleversvg 17 */ 18 1 <?php // CleverSvg framework class autoloading 19 2 function __autoload($class) 20 3 { 21 $dirs = array('exceptions', 'base', 'gradients', 'elements', 'document'); 4 $dirs = array('exceptions', 5 'base', 6 'container', 7 'gradients', 8 'elements', 9 'importer', 10 'document', 11 'interfaces'); 22 12 $pwd = dirname(__FILE__); 23 13 foreach ($dirs as $dir) 24 14 { 25 $class_file = sprintf('%s%s%s%s%s.class.php', 26 $pwd, DIRECTORY_SEPARATOR, 27 $dir, DIRECTORY_SEPARATOR, $class); 28 if (file_exists($class_file)) 15 foreach (array('class', 'interface') as $type) 29 16 { 30 class_exists($class) or require($class_file); 17 $class_file = sprintf('%s%s%s%s%s.%s.php', 18 $pwd, DIRECTORY_SEPARATOR, 19 $dir, DIRECTORY_SEPARATOR, $class, 20 $type); 21 if (file_exists($class_file)) 22 { 23 if ($type == 'interface') 24 { 25 interface_exists($class) or require($class_file); 26 } 27 else 28 { 29 class_exists($class) or require($class_file); 30 } 31 } 31 32 } 32 33 } 33 34 } 35 36 /** 37 * CleverSvg default PHP error handler 38 * 39 * TODO: switch from error code to provide specific errors 40 * 41 * @param int $code 42 * @param string $message 43 * @param string $file 44 * @param int $line 45 * @throws csException 46 */ 47 function cs_error_handler($code, $message, $file, $line) 48 { 49 switch ($code) 50 { 51 case E_USER_ERROR: 52 $type = 'Error'; 53 $exception = 'csException'; 54 break; 55 case E_USER_WARNING: 56 $type = 'Warning'; 57 $exception = 'csException'; 58 break; 59 case E_USER_NOTICE: 60 $type = 'Notice'; 61 $exception = 'csException'; 62 break; 63 default: 64 $type = 'Unknown error'; 65 $exception = 'csException'; 66 break; 67 } 68 $message = sprintf('%s "%s" in %s line %d', 69 $type, $message, $file, $line); 70 throw new $exception($message, $code); 71 } 72 set_error_handler('cs_error_handler'); -
cleversvg/trunk/document/csDocument.class.php
r335 r336 17 17 18 18 /** 19 * Definitions container20 * @var array21 */ 22 protected $ definitions = array();19 * Definitions and elements container 20 * @var csElementsContainer 21 */ 22 protected $container; 23 23 24 24 /** … … 41 41 42 42 /** 43 * Used definitions references container44 * @var array45 */46 protected $used_definitions = array();47 48 /**49 * Document elements container50 * @var array51 */52 protected $elements = array();53 54 /**55 * DOM document unique id attributes container56 * @var array57 */58 protected $dom_ids = array();59 60 /**61 43 * Document description 62 44 * @var string … … 86 68 * @var boolean 87 69 */ 88 p rotected$embedded = false;70 public static $embedded = false; 89 71 90 72 /** … … 107 89 $this->setHeight($height); 108 90 $this->setTitle($title); 91 $this->container = new csElementsContainer(); 109 92 $this->attributes = array_merge($attrs, $this->attributes); 110 93 $this->initDefaults(); … … 115 98 * 116 99 * @param mixed $element SVG element to add 117 * @param mixed $depth Depth (default: auto when set to NULL)118 * @param boolean $replace_at_depth Replace element at depth if exist ?119 100 * @throws csException 120 101 */ 121 public function addElement($element, $depth = null, $replace_at_depth = false) 122 { 123 // Add DOM id to document list, if any 124 $id = $element->getId(); 125 if (!is_null($id)) 126 { 127 if (in_array($id, $this->dom_ids)) 128 { 129 throw new csException( 130 sprintf('Document has already an element with id "%s"', $id)); 131 } 132 $this->dom_ids[] = $id; 133 } 134 135 if (is_null($element->getDepth())) 136 { 137 if (!$replace_at_depth && array_key_exists($depth, $this->elements)) 138 { 139 throw new csException( 140 sprintf('Unable to add element at depth "%d", a "%s" element already'. 141 ' exist at this index', 142 $depth, $this->elements[$depth]->getElementName(false))); 143 } 144 elseif (!is_int($depth)) 145 { 146 $depth = ++$this->maxdepth; 147 } 148 } 149 else 150 { 151 $depth = $element->getDepth(); 152 } 153 $this->elements[$depth] = $element; 154 } 155 156 /** 102 public function addElement($element) 103 { 104 return $this->container->addElement($element); 105 } 106 107 /** 157 108 * Create an svg element and returns its instance 158 109 * … … 162 113 public function createElement($name) 163 114 { 164 $class_name = sprintf('cs%s', ucfirst($name)); 165 if (!class_exists($class_name)) 166 { 167 throw new csException(sprintf('Element class "%s" does not exist', 168 $class_name)); 169 } 170 return new $class_name; 115 return $this->container->createElement($name); 171 116 } 172 117 … … 179 124 public function dropElementById($id) 180 125 { 181 foreach ($this->getElements() as $index => $element) 182 { 183 if ($element->getId() == $id) 184 { 185 foreach ($this->dom_ids as $dom_index => $dom_id) 186 { 187 if ($dom_id == $id) 188 { 189 unset($this->dom_ids[$dom_index]); 190 } 191 } 192 unset($this->elements[$index]); 193 return; 194 } 195 } 126 return $this->container->dropElementById($id); 196 127 } 197 128 … … 205 136 public function getElementById($id) 206 137 { 207 foreach ($this->elements as $element) 208 { 209 if ($element->getId() == $id) 210 { 211 return $element; 212 } 213 } 214 throw new csException(sprintf('No element with id "%s"', $id)); 138 return $this->container->getElementById($id); 215 139 } 216 140 … … 222 146 protected function getElements() 223 147 { 224 return $this->elements; 148 return $this->container->getElements(); 149 } 150 151 /** 152 * Checks if SVG output should be in embed mode 153 * 154 * @return boolean 155 */ 156 public static function getIsEmbedded() 157 { 158 return self::$embedded; 225 159 } 226 160 … … 230 164 * @return string 231 165 */ 232 p rotectedfunction getNodeNS()166 public static function getNodeNS() 233 167 { 234 168 $prefix = ''; 235 if ( $this->embedded === true)169 if (self::$embedded === true) 236 170 { 237 171 $prefix = 'svg:'; … … 293 227 public function addAsDefinition($definition, $id = null) 294 228 { 295 $is_element = is_callable(array($definition, 'setId')); 296 if (is_string($id) && trim($id) != '' && $is_element) 297 { 298 $definition->setId($id); 299 } 300 $id = $definition->getId(); 301 if (is_null($id)) 302 { 303 throw new csException( 304 sprintf('A definition must have an id specified')); 305 } 306 elseif ($this->hasId($id)) 307 { 308 throw new csException( 309 sprintf('The DOM id "%s" has been already defined', $id)); 310 } 311 else 312 { 313 $this->definitions[$id] = $definition; 314 $this->dom_ids[] = $id; 315 } 229 return $this->container->addAsDefinition($definition, $id); 316 230 } 317 231 … … 323 237 protected function getDefinitions() 324 238 { 325 return $this-> definitions;239 return $this->container->getDefinitions(); 326 240 } 327 241 … … 333 247 protected function getUsedDefinitions() 334 248 { 335 return $this-> used_definitions;249 return $this->container->getUsedDefinitions(); 336 250 } 337 251 … … 339 253 * Returns a defined element alias (a <use/> tag) 340 254 * 255 * @param string $id 341 256 * @return array 257 * @throws csException 342 258 */ 343 259 protected function getDefinition($id) 344 260 { 345 if (!isset($this->definitions[$id])) 346 { 347 throw new csException( 348 sprintf('Unable to find id "%s" in current document.')); 349 } 350 else 351 { 352 return $this->definitions[$id]; 353 } 261 return $this->container->getDefinition($id); 354 262 } 355 263 … … 384 292 break; 385 293 } 386 if (true === $this->embedded)294 if (true === self::$embedded) 387 295 { 388 296 $dom = new DOMDocument('1.0', 'UTF-8'); … … 408 316 public function useDefinition($id, $attrs = array()) 409 317 { 410 $this->used_definitions[] = array($this->getDefinition($id), $attrs);318 return $this->container->useDefinition($id, $attrs); 411 319 } 412 320 … … 421 329 public function swapDepths($id1, $id2) 422 330 { 423 if ($id1 == $id2) 424 { 425 return; 426 } 427 $e1 = $this->getElementById($id1); 428 $e2 = $this->getElementById($id2); 429 $e1depth = $e1->getDepth(); 430 $e2depth = $e2->getDepth(); 431 $e2->setDepth($e1depth); 432 $e1->setDepth($e2depth); 433 $this->dropElementById($id1); 434 $this->dropElementById($id2); 435 $this->addElement($e1, $e1depth, true); 436 $this->addElement($e2, $e2depth, true); 331 return $this->container->swapDepths($id1, $id2); 437 332 } 438 333 … … 440 335 * Checks if a DOM id already exists in current SVG Document 441 336 * 442 * @param string $ dom_id337 * @param string $id 443 338 * @return boolean 444 339 */ 445 public function hasId($ dom_id)446 { 447 return in_array($dom_id, $this->dom_ids);340 public function hasId($id) 341 { 342 return $this->container->hasId($id); 448 343 } 449 344 … … 486 381 public function setEmbedded($flag) 487 382 { 488 $this->embedded = (boolean) $flag;383 self::$embedded = (boolean) $flag; 489 384 } 490 385 … … 627 522 $dom->normalizeDocument(); 628 523 629 // Validation 630 $this->validate($dom); 524 // Validation if strict mode 525 if (true === $this->strict_mode) 526 { 527 $this->validate(); 528 } 631 529 632 530 // Output 633 if ( $this->embedded === true)531 if (self::$embedded === true) 634 532 { 635 533 return $dom->saveXml($dom->documentElement, LIBXML_NOXMLDECL); … … 642 540 643 541 /** 644 * Process definitions nif any542 * Process definitions if any 645 543 * 646 544 */ 647 545 protected function processDefinitions() 648 546 { 649 $dom = $this->getDomDocument(); 650 if (count($this->getDefinitions()) > 0) 651 { 652 // Definitions declaration 653 $defs_node = $dom->createElement($this->getNodeNS().'defs'); 654 foreach ($this->getDefinitions() as $definition) 655 { 656 // Define elements 657 $definition_node = $definition->compile($this->embedded); 658 $def_node = $dom->importNode($definition_node, true); 659 $defs_node->appendChild($def_node); 660 } 661 $dom->documentElement->appendChild($defs_node); 662 } 547 return $this->container->processDefinitions($this->getDomDocument()); 663 548 } 664 549 … … 669 554 protected function processElements() 670 555 { 671 $dom = $this->getDomDocument(); 672 foreach ($this->getElements() as $element) 673 { 674 $element_node = $element->compile($this->embedded); 675 $node_element = $dom->importNode($element_node, true); 676 $dom->documentElement->appendChild($node_element); 677 } 556 return $this->container->processElements($this->getDomDocument()); 678 557 } 679 558 … … 690 569 foreach ($this->embed_styles as $style) 691 570 { 692 $style_node = $dom->createElement( $this->getNodeNS().'style');571 $style_node = $dom->createElement(self::getNodeNS().'style'); 693 572 $style_node->setAttribute('type', $style['type']); 694 573 $style_node->setAttribute('media', $style['media']); … … 733 612 if (!is_null($this->title)) 734 613 { 735 $title_node = $dom->createElement( $this->getNodeNS().'title',614 $title_node = $dom->createElement(self::getNodeNS().'title', 736 615 strip_tags($this->title)); 737 616 $dom->documentElement->appendChild($title_node); … … 742 621 if (!is_null($this->description)) 743 622 { 744 $desc_node = $dom->createElement( $this->getNodeNS().'desc',623 $desc_node = $dom->createElement(self::getNodeNS().'desc', 745 624 strip_tags($this->description)); 746 625 $dom->documentElement->appendChild($desc_node); … … 755 634 { 756 635 $dom = $this->getDomDocument(); 757 $root = $this->dom_document->createElement( $this->getNodeNS().'svg');636 $root = $this->dom_document->createElement(self::getNodeNS().'svg'); 758 637 $dom->appendChild($root); 759 638 foreach ($this->attributes as $attr_name => $attr_value) … … 767 646 768 647 /** 648 * Process used definitions, if any 649 * 650 */ 651 protected function processUsedDefinitions() 652 { 653 return $this->container->processUsedDefinitions($this->getDomDocument()); 654 } 655 656 /** 769 657 * Process scripts, if any 770 658 * … … 778 666 foreach ($this->scripts as $script) 779 667 { 780 $script_node = $dom->createElement( $this->getNodeNS().'script');668 $script_node = $dom->createElement(self::getNodeNS().'script'); 781 669 $script_node->setAttribute('type', $script[1]); 782 670 $script_content = $dom->createCDATASection($script[0]); … … 788 676 789 677 /** 790 * Process used definitions, if any 791 * 792 */ 793 protected function processUsedDefinitions() 794 { 795 $dom = $this->getDomDocument(); 796 if (count($this->getUsedDefinitions()) > 0) 797 { 798 foreach ($this->getUsedDefinitions() as $used_definition) 678 * Validates document 679 * 680 * @throws csException 681 */ 682 public function validate() 683 { 684 try 685 { 686 $this->getDomDocument()->validate(); 687 } 688 catch (csException $e) 689 { 690 if (preg_match('/php_network_getaddresses/', $e->getMessage())) 799 691 { 800 $element = $used_definition[0]; 801 $attributes = $used_definition[1]; 802 $use_node = $dom->createElement($this->getNodeNS().'use'); 803 $use_node->setAttribute('xlink:href', '#'.$element->getId()); 804 foreach ($attributes as $attr_name => $attr_value) 805 { 806 $use_node->setAttribute($attr_name, $attr_value); 807 } 808 $dom->documentElement->appendChild($use_node); 692 throw new csException( 693 'An internet connection is required to validate document'); 809 694 } 810 } 811 } 812 813 /** 814 * Validates document 815 * 816 * @throws csException 817 */ 818 protected function validate(DOMDocument $dom) 819 { 820 if (true == $this->strict_mode && !$dom->validate()) 821 { 822 throw new csException('This SVG Document does not validate'); 695 throw new csException( 696 'SVG document validation failed: '.$e->getMessage()); 823 697 } 824 698 } -
cleversvg/trunk/elements/csEllipse.class.php
r318 r336 2 2 /** 3 3 * SVG Ellipse class 4 * 4 * 5 5 * @author Nicolas Perriault <nperriault@gmail.com> 6 6 * @package cleversvg … … 14 14 /** 15 15 * Class constructor 16 * 16 * 17 17 */ 18 18 public function __construct($cx=null, $cy=null, $rx=null, $ry=null, $attrs=array()) … … 24 24 $this->attributes = array_merge($attrs, $this->attributes); 25 25 } 26 26 27 27 /** 28 28 * The x-axis coordinate of the center of the circle. 29 * 30 * @param int $cx 29 * 30 * @param int $cx 31 31 */ 32 32 public function setCx($cx) … … 34 34 $this->setAttribute('cx', $cx); 35 35 } 36 36 37 37 /** 38 38 * The y-axis coordinate of the center of the circle. 39 * 40 * @param int $cy 39 * 40 * @param int $cy 41 41 */ 42 42 public function setCy($cy) … … 44 44 $this->setAttribute('cy', $cy); 45 45 } 46 46 47 47 /** 48 48 * Sets the x-radius of the circle 49 * 49 * 50 50 * @param int $xradius 51 51 */ … … 54 54 $this->setAttribute('rx', $xradius); 55 55 } 56 56 57 57 /** 58 58 * Sets the y-radius of the circle 59 * 59 * 60 60 * @param int $yradius 61 61 */ … … 64 64 $this->setAttribute('ry', $yradius); 65 65 } 66 66 67 67 } -
cleversvg/trunk/elements/csGroup.class.php
r322 r336 2 2 /** 3 3 * SVG Group class 4 * 4 * 5 5 * @author Nicolas Perriault <nperriault@gmail.com> 6 6 * @package cleversvg 7 7 * @subpackage elements 8 8 */ 9 class csGroup extends cs BaseElement9 class csGroup extends csElementsContainer 10 10 { 11 11 12 protected 13 $elements = array(), 14 $used_definitions = array(), 15 $xml_node_name = 'g'; 12 /** 13 * Definitions and elements container 14 * @var csElementsContainer 15 */ 16 protected $container = null; 17 18 /** 19 * SVG XML node name 20 * @var string 21 */ 22 protected $xml_node_name = 'g'; 16 23 17 24 /** 18 25 * Class constructor 19 * 26 * 20 27 * @param mixed $id The DOM id of the element 21 28 * @param array $attrs More attributes to affect 22 29 */ 23 public function __construct($id =null, $attrs=array())30 public function __construct($id = null, $attrs = array()) 24 31 { 25 32 $this->setId($id); 26 33 $this->attributes = array_merge($attrs, $this->attributes); 34 $this->container = new csElementsContainer(); 27 35 } 28 36 29 37 /** 30 38 * Computes DOMXML Node 31 * 39 * 32 40 * @param boolean $embedded Is SVG element embedded ? 33 41 * @return DOMElement 34 42 */ 35 public function compile($embedded =false)43 public function compile($embedded = false) 36 44 { 37 45 $group_node = parent::compile($embedded); 38 46 $dom = $this->getDomDocument(); 39 47 40 48 # Prefix 41 49 $prefix = $embedded === true ? 'svg:' : ''; 42 50 43 51 // Add elements to current group node 44 52 foreach ($this->getElements() as $element) … … 47 55 $group_node->appendChild($node_element); 48 56 } 49 57 50 58 // Add used definitions 51 59 foreach ($this->used_definitions as $used_definition) … … 65 73 $group_node->appendChild($use_node); 66 74 } 67 75 68 76 return $group_node; 69 77 } 70 78 71 79 /** 72 * Adds a SVG element to current group 73 * 74 * @param mixed $element SVG element to add 80 * Adds a SVG shape or group to current SVG Document at a certain depth 81 * 82 * @param mixed $element SVG element to add 83 * @throws csException 75 84 */ 76 85 public function addElement($element) 77 86 { 78 $this->elements[] = $element;87 return $this->container->addElement($element); 79 88 } 80 89 90 /** 91 * Retrieve an contained element instance by its DOM id 92 * 93 * @param string $id 94 * @return csBaseElement 95 * @throw csException 96 */ 97 public function getElementById($id) 98 { 99 return $this->container->getElementById($id); 100 } 101 81 102 /** 82 103 * Returns an array containing current group elements 83 * 84 * @return array 104 * 105 * @return array 85 106 */ 86 p rotectedfunction getElements()107 public function getElements() 87 108 { 88 return $this-> elements;109 return $this->container->getElements(); 89 110 } 90 111 112 /** 113 * Checks if a DOM id already exists in current SVG Document 114 * 115 * @param string $id 116 * @return boolean 117 */ 118 public function hasId($id) 119 { 120 return $this->container->hasId($id); 121 } 122 91 123 /** 92 124 * Uses a definition in current group 93 * 125 * 94 126 * @param mixed $element 95 127 * @param array $attrs More atributes to add to <use/> tag 96 128 */ 97 public function useDefinition($definition, $attrs =array())129 public function useDefinition($definition, $attrs = array()) 98 130 { 99 $this->used_definitions[] = array($definition, $attrs);131 return $this->container->useDefinition($definition, $attrs); 100 132 } 101 133 102 134 } -
cleversvg/trunk/elements/csLink.class.php
r322 r336 2 2 /** 3 3 * SVG Link class 4 * 4 * 5 5 * @author Nicolas Perriault <nperriault@gmail.com> 6 6 * @package cleversvg 7 7 * @subpackage elements 8 8 */ 9 class csLink extends cs BaseElement9 class csLink extends csElementsContainer 10 10 { 11 11 12 protected 13 $elements = array(), 14 $xml_node_name = 'a'; 12 /** 13 * Elements container 14 * @var csElementsContainer 15 */ 16 protected $container = null; 17 18 /** 19 * Document elements 20 * @var array 21 */ 22 protected $elements = array(); 23 24 /** 25 * XML node name 26 * @var string 27 */ 28 protected $xml_node_name = 'a'; 15 29 16 30 /** 17 31 * Class constructor 18 * 32 * 19 33 * @param mixed $href Link 20 34 * @param mixed $target Target … … 26 40 $this->setTarget($target); 27 41 $this->attributes = array_merge($attrs, $this->attributes); 42 $this->container = new csElementsContainer(); 28 43 } 29 44 30 45 /** 31 46 * Computes DOMXML Node 32 * 47 * 33 48 * @param boolean $embedded Is SVG element embedded ? 34 49 * @return DOMElement … … 36 51 public function compile($embedded=false) 37 52 { 38 $ group_node = parent::compile($embedded);53 $link_node = parent::compile($embedded); 39 54 $dom = $this->getDomDocument(); 40 55 41 56 // Add elements to current group node 42 57 foreach ($this->getElements() as $element) 43 58 { 44 59 $node_element = $dom->importNode($element->compile($embedded), true); 45 $ group_node->appendChild($node_element);60 $link_node->appendChild($node_element); 46 61 } 47 48 return $ group_node;62 63 return $link_node; 49 64 } 50 65 51 66 /** 52 * Adds a SVG element to current group 53 * 54 * @param mixed $element SVG element to add 67 * Adds a SVG shape or group to current SVG Document at a certain depth 68 * 69 * @param mixed $element SVG element to add 70 * @param mixed $depth Depth (default: auto when set to NULL) 71 * @param boolean $replace_at_depth Replace element at depth if exist? 72 * @throws csException 55 73 */ 56 public function addElement($element )74 public function addElement($element, $depth = null, $replace_at_depth = false) 57 75 { 58 $this->elements[] = $element;76 return $this->container->addElement($element, $depth, $replace_at_depth); 59 77 } 60 78 79 /** 80 * Retrieve an contained element instance by its DOM id 81 * 82 * @param string $id 83 * @return csBaseElement 84 * @throw csException 85 */ 86 public function getElementById($id) 87 { 88 return $this->container->getElementById($id); 89 } 90 61 91 /** 62 92 * Returns an array containing current group elements 63 * 64 * @return array 93 * 94 * @return array 65 95 */ 66 p rotectedfunction getElements()96 public function getElements() 67 97 { 68 return $this-> elements;98 return $this->container->getElements(); 69 99 } 70 100 101 /** 102 * Checks if a DOM id already exists in current SVG Document 103 * 104 * @param string $id 105 * @return boolean 106 */ 107 public function hasId($id) 108 { 109 return $this->container->hasId($id); 110 } 111 71 112 /** 72 113 * Sets the href attribute of the link 73 * 114 * 74 115 * @param string $href 75 116 */ … … 78 119 $this->setAttribute('xlink:href', $href); 79 120 } 80 121 81 122 /** 82 123 * Sets the target attribute of the link 83 * 124 * 84 125 * @param string $target 85 126 */ … … 88 129 $this->setAttribute('target', $target); 89 130 } 90 131 91 132 } -
cleversvg/trunk/elements/csPath.class.php
r318 r336 2 2 /** 3 3 * SVG Path class 4 * 4 * 5 5 * @author Nicolas Perriault <nperriault@gmail.com> 6 6 * @package cleversvg … … 10 10 { 11 11 12 protected 12 protected 13 13 $xml_node_name = 'path', 14 14 $path_array = array(); … … 16 16 /** 17 17 * Class constructor 18 * 18 * 19 19 */ 20 public function __construct($path_data =array(), $attrs=array())20 public function __construct($path_data = array(), $attrs = array()) 21 21 { 22 22 $this->setPathDataArray($path_data); … … 24 24 $this->attributes = array_merge($attrs, $this->attributes); 25 25 } 26 26 27 27 /** 28 28 * Compute current path data array 29 * 29 * 30 30 */ 31 31 protected function computePath() … … 36 36 if (isset($move[1])) 37 37 { 38 $path_string .= sprintf('%s %s', 38 $path_string .= sprintf('%s %s', 39 39 $move[0], 40 40 implode(' ', $move[1])); … … 47 47 $this->setPathDataString(trim($path_string)); 48 48 } 49 49 50 50 /** 51 51 * Sets the path data from an array 52 * 52 * 53 * @param array 53 54 */ 54 55 public function setPathDataArray($path_data_array) … … 57 58 $this->computePath(); 58 59 } 59 60 60 61 /** 61 62 * Sets the path string 62 * 63 * 64 * @param string 63 65 */ 64 66 public function setPathDataString($path_data_string) … … 71 73 $this->setAttribute('d', $path_data_string); 72 74 } 73 75 74 76 /** 75 77 * Init path data array and ready to receive path building directions 76 * 78 * 77 79 */ 78 80 public function begin() … … 80 82 $this->path_data_array = array(); 81 83 } 82 84 83 85 public function end() 84 86 { … … 86 88 $this->computePath(); 87 89 } 88 90 89 91 /** 90 92 * Move to a point 91 * 93 * 94 * @param int $x 95 * @param int $y 92 96 */ 93 97 public function moveTo($x, $y) … … 95 99 $this->path_data_array[] = array('M', array($x, $y)); 96 100 } 97 101 98 102 /** 99 103 * Draws a line moving to a point 100 * 104 * 105 * @param int $x 106 * @param int $y 101 107 */ 102 108 public function lineTo($x, $y) … … 104 110 $this->path_data_array[] = array('L', array($x, $y)); 105 111 } 106 112 107 113 /** 108 114 * Draws a horizontal line moving to a point 109 * 115 * 116 * @param int $x 110 117 */ 111 118 public function hLineTo($x) … … 113 120 $this->path_data_array[] = array('H', array($x)); 114 121 } 115 122 116 123 /** 117 124 * Draws a vertical line moving to a point 118 * 125 * 126 * @param int $y 119 127 */ 120 128 public function vLineTo($y) … … 122 130 $this->path_data_array[] = array('V', array($y)); 123 131 } 124 132 125 133 /** 126 134 * Draws a curve moving to a point 127 * 135 * 128 136 */ 129 137 public function curveTo($x, $y, $x1, $y1, $x2, $y2) … … 131 139 $this->path_data_array[] = array('C', array($x, $y, $x1, $y1, $x2, $y2)); 132 140 } 133 141 134 142 /** 135 143 * Draws a smooth curve moving to a point 136 * 144 * 137 145 */ 138 146 public function smoothCurveTo($x, $y, $x2, $y2) … … 140 148 $this->path_data_array[] = array('S', array($x, $y, $x2, $y2)); 141 149 } 142 150 143 151 /** 144 152 * The x-axis coordinate of one corner of the rectangular region into which an 145 153 * embedded 'svg' element is placed. 146 * 154 * 155 * @param int 147 156 */ 148 157 public function setX($x) … … 150 159 $this->setAttribute('x', $x); 151 160 } 152 161 153 162 /** 154 163 * The y-axis coordinate of one corner of the rectangular region into which an 155 164 * embedded 'svg' element is placed. 156 * 165 * 166 * @param int 157 167 */ 158 168 public function setY($y) … … 160 170 $this->setAttribute('y', $y); 161 171 } 162 163 172 173 164 174 } -
cleversvg/trunk/exceptions/csException.class.php
r318 r336 2 2 /** 3 3 * SVG Generation exception 4 * 4 * 5 5 * @author Nicolas Perriault <nperriault@gmail.com> 6 6 * @package cleversvg 7 * @subpackage e sxceptions7 * @subpackage exceptions 8 8 */ 9 9 class csException extends Exception -
cleversvg/trunk/quick_examples.php
r323 r336 1 1 <?php 2 //First, require the library call script3 2 require_once('cleversvg.php'); 4 5 //Instanciate a SVG document, specifying its width and height 6 $doc = new csDocument(1000, 700, 'Un document SVG de test'); 3 $doc = new csDocument(550, 400, 'SVG test document'); 7 4 8 5 $gradient = new csLinearGradient(0, 0, '100%', '100%'); 9 6 $gradient->addStop('0%', 'yellow'); 10 7 $gradient->addStop('100%', 'red'); 11 $doc->addAsDefinition($gradient, ' myLinearGradient');8 $doc->addAsDefinition($gradient, 'gradient'); 12 9 13 $polygon = new csPolygon(); 14 $polygon->setPointsArray(array(array(350,75), 15 array(379,161), 16 array(469,161), 17 array(397,215), 18 array(423,301), 19 array(350,250), 20 array(277,301), 21 array(303,215), 22 array(231,161), 23 array(321,161))); 24 $polygon->setStroke('blue'); 25 $polygon->setFill('url(#myLinearGradient)'); 26 $polygon->setStrokeWidth(3); 27 $doc->addElement($polygon); 10 $star = new csPolygon(); 11 $star->setPointsArray(array(array(350,75), array(379,161), 12 array(469,161), array(397,215), 13 array(423,301), array(350,250), 14 array(277,301), array(303,215), 15 array(231,161), array(321,161))); 16 $star->setStroke('blue'); 17 $star->setFill('url(#gradient)'); 18 $star->setStrokeWidth(4); 19 $linkedstar = new csLink(); 20 $linkedstar->setHref('http://prendreuncafe.com/blog/'); 21 $linkedstar->addElement($star); 22 $doc->addElement($linkedstar); 28 23 29 30 31 $gradient = new csRadialGradient('50%', '50%', '30%', '30%', '50%');32 $gradient->addStop('15%', 'lightblue', 0.5);33 $gradient->addStop('100%', 'darkblue');34 $doc->addAsDefinition($gradient, 'myRadialGradient');35 36 $path = new csPath();37 $path->begin();38 $path->moveTo(600, 25);39 $path->lineTo(120, 25);40 $path->lineTo(350, 500);41 $path->end();42 $path->setStroke('orange');43 $path->setStrokeWidth(3);44 $path->setFill('url(#myRadialGradient)');45 $doc->addElement($path);46 47 48 //Never forget to send image/svg+xml headers before outputing49 24 header("Content-type: image/svg+xml"); 50 51 //When you're done, render the document as a standalone one 52 echo $doc->toXML(true); 53 54 //Or an embedded one : 55 //echo $doc->toXML(true); 56 ?> 25 echo $doc->toXML(); -
cleversvg/trunk/tests/csBaseTestCase.class.php
r335 r336 27 27 28 28 /** 29 * Checks if an attribute exists for given node 30 * 31 * @param csDocument $doc 32 * @param string $xpath_query 33 * @param string $attr_name 34 * @return boolean 35 */ 36 public function assertNodeAttrExists($doc, $xpath_query, $attr_name) 37 { 38 $result = $this->documentXpath($doc, $xpath_query); 39 $this->assertNodeExists($doc, $xpath_query); 40 if (!$result->item(0)->hasAttribute($attr_name)) 41 { 42 throw new PHPUnit_Framework_ExpectationFailedException( 43 sprintf('No attribute "%s" found in node retrieved by "%s". Source: %s', 44 $attr_name, $xpath_query, "\n".$doc->toXML())); 45 } 46 } 47 48 /** 49 * Checks that an attribute does not exist for given node 50 * 51 * @param csDocument $doc 52 * @param string $xpath_query 53 * @param string $attr_name 54 * @return boolean 55 */ 56 public function assertNodeAttrNotExists($doc, $xpath_query, $attr_name) 57 { 58 $result = $this->documentXpath($doc, $xpath_query); 59 $this->assertNodeExists($doc, $xpath_query); 60 if ($result->item(0)->hasAttribute($attr_name)) 61 { 62 throw new PHPUnit_Framework_ExpectationFailedException( 63 sprintf('Attribute %s="%s" retrieved by node "%s". Source: %s', 64 $attr_name, 65 $result->item(0)->getAttribute($attr_name), 66 $xpath_query, "\n".$doc->toXML())); 67 } 68 } 69 70 /** 29 71 * Checks if an attribute xpath query matches given value for given doc. 30 72 * … … 51 93 $xpath_query, $value, $attr_value, "\n".$doc->toXML())); 52 94 } 53 return true;54 95 } 55 96 … … 57 98 { 58 99 $result = $this->documentXpath($doc, $xpath_query); 59 return !is_null($result->item(0)); 100 if (is_null($result->item(0))) 101 { 102 throw new PHPUnit_Framework_ExpectationFailedException( 103 sprintf('XPath query "%s" does not return a result. Source: %s', 104 $xpath_query, "\n".$doc->toXML())); 105 } 60 106 } 61 107 62 108 protected function assertNodeDoesNotExist($doc, $xpath_query) 63 109 { 64 return !$this->assertNodeExists($doc, $xpath_query); 110 $result = $this->documentXpath($doc, $xpath_query); 111 if (!is_null($result->item(0))) 112 { 113 throw new PHPUnit_Framework_ExpectationFailedException( 114 sprintf('XPath query "%s" return a result. Source: %s', 115 $xpath_query, "\n".$doc->toXML())); 116 } 65 117 } 66 118 … … 74 126 $xpath_query, $value, "\n".$doc->toXML())); 75 127 } 76 return true;77 128 } 78 129 … … 88 139 private function documentXpath(csDocument $doc, $xpath_query) 89 140 { 90 $dom = DOMDocument::loadXML($doc->toXML()); // yeah, I *must* reload the xml 141 $dom = new DOMDocument(); 142 $dom->loadXML($doc->toXML()); // yeah, I *must* reload the xml 91 143 $xpath = new DOMXPath($dom); 92 144 $xpath->registerNamespace("svg", "http://www.w3.org/2000/svg"); // uh oh 145 $xpath->registerNamespace("xlink", "http://www.w3.org/1999/xlink"); 93 146 return $xpath->query($xpath_query, $dom); 94 147 } -
cleversvg/trunk/tests/csCircleTest.php
r333 r336 46 46 $doc->addElement($circle); 47 47 $xml = $doc->toXML(); 48 $this->assertEquals(preg_match('#z-index: 4#s', $xml), 1, $xml); 48 $this->assertAttrValueEquals($doc, '/svg:svg/svg:circle/@style', 'z-index: 4'); 49 $circle->setDepth(null); 50 $this->assertNodeAttrNotExists($doc, '/svg:svg/svg:circle', 'style'); 49 51 } 50 52 -
cleversvg/trunk/tests/csDocumentTest.php
r335 r336 11 11 { 12 12 13 public function testAddAsDefinition() 14 { 15 $doc = new csDocument(320, 240, 'Blah'); 16 $circle = new csCircle(); 17 $circle->setStroke('yellow'); 18 $circle->setStrokeWidth(2); 19 $circle->setFill('orange'); 20 $circle->setId('circle1'); 21 $doc->addAsDefinition($circle, 'c1'); 22 $this->assertNodeExists($doc, '/svg:svg/svg:defs/svg:circle[@id = "c1"]'); 23 $this->assertType('csCircle', $doc->getElementById('c1')); 24 } 25 26 /** 27 * @expectedException csException 28 * 29 */ 30 public function testAddElement() 31 { 32 $doc = new csDocument(320, 240, 'Blah'); 33 $c = $doc->createElement('circle'); 34 $c->setId('myId'); 35 $doc->addElement($c); 36 $this->assertType('csCircle', $doc->getElementById('myId')); 37 $rect = new csRect(100, 50, 40, 20); 38 $rect->setId('myId'); 39 $doc->addElement($rect); 40 } 41 13 42 public function testConstructor() 14 43 { … … 41 70 } 42 71 72 public function testGetDomDocument() 73 { 74 $doc = new csDocument(320, 240, 'Blah'); 75 $this->assertType('DOMDocument', $doc->getDomDocument()); 76 } 77 78 public function testGetElementById() 79 { 80 $doc = new csDocument(320, 240, 'Blah'); 81 82 // Testing flat level search 83 $c = new csCircle(); 84 $c->setRadius(10); 85 $c->setStroke('red'); 86 $c->setId('c1'); 87 $doc->addElement($c); 88 $this->assertType('csBaseElement', $doc->getElementById('c1')); 89 90 // Testing deep level search 91 $c2 = clone($c); 92 $c2->setId('c2'); 93 $g1 = new csGroup('g1'); 94 $g1->addElement($c2); 95 $doc->addElement($g1); 96 $this->assertType('csBaseElement', $doc->getElementById('c2')); 97 98 $c3 = clone($c); 99 $c3->setId('c3'); 100 $g2 = new csGroup('g2'); 101 $g2->addElement($c3); 102 $g3 = new csGroup('g3'); 103 $g3->addElement($g2); 104 $doc->addElement($g3); 105 $this->assertType('csBaseElement', $doc->getElementById('c3')); 106 } 107 43 108 public function testHasId() 44 109 { … … 55 120 $this->assertTrue($doc->hasId('circle2')); 56 121 $this->assertFalse($doc->hasId('jfhkjsdfh')); 122 $doc->dropElementById('circle1'); 123 $this->assertFalse($doc->hasId('circle1')); 124 $this->assertTrue($doc->hasId('circle2')); 125 $doc->dropElementById('circle2'); 126 $this->assertFalse($doc->hasId('circle2')); 57 127 } 58 128 … … 106 176 } 107 177 178 public function testUseDefinition() 179 { 180 $doc = new csDocument(320, 240, 'Blah'); 181 $circle = new csCircle(); 182 $doc->addAsDefinition($circle, 'c1'); 183 $doc->useDefinition('c1', array('x' => 200, 'y' => 100)); 184 $this->assertAttrValueEquals($doc, '/svg:svg/svg:use/@xlink:href', '#c1'); 185 } 186 187 public function testValidation() 188 { 189 $doc = new csDocument(320, 240, 'Test depths'); 190 $c1 = new csCircle(160, 120, 40); 191 $c1->setDepth(20); 192 $c1->setId('c1'); 193 $c2 = new csCircle(140, 100, 40); 194 $c2->setDepth(40); 195 $c2->setId('c2'); 196 $doc->addElement($c1); 197 $doc->addElement($c2); 198 $doc->setStrictMode(true); 199 $doc->toXML(); 200 } 201 108 202 public function testViewBox() 109 203 { -
cleversvg/trunk/tests/csTestSuite.php
r326 r336 5 5 require_once 'csCircleTest.php'; 6 6 require_once 'csDocumentTest.php'; 7 require_once 'csEllipseTest.php'; 8 require_once 'csGroupTest.php'; 9 require_once 'csImageTest.php'; 10 require_once 'csLineTest.php'; 11 require_once 'csLinkTest.php'; 12 require_once 'csPathTest.php'; 13 require_once 'csPolylineTest.php'; 14 require_once 'csRectTest.php'; 15 require_once 'csTextTest.php'; 7 16 8 17 if (!defined('PHPUnit_MAIN_METHOD')) … … 21 30 public static function suite() 22 31 { 23 $suite = new PHPUnit_Framework_TestSuite('CleverSvg'); 32 $suite = new PHPUnit_Framework_TestSuite('CleverSvg::csDocument'); 33 $suite->addTestSuite('csCircleTest'); 24 34 $suite->addTestSuite('csDocumentTest'); 25 $suite->addTestSuite('csCircleTest'); 35 $suite->addTestSuite('csEllipseTest'); 36 $suite->addTestSuite('csGroupTest'); 37 $suite->addTestSuite('csImageTest'); 38 $suite->addTestSuite('csLineTest'); 39 $suite->addTestSuite('csLinkTest'); 40 $suite->addTestSuite('csPathTest'); 41 $suite->addTestSuite('csPolylineTest'); 42 $suite->addTestSuite('csRectTest'); 43 $suite->addTestSuite('csTextTest'); 26 44 return $suite; 27 45 }
