Show
Ignore:
Timestamp:
03/07/08 08:33:04 (4 years ago)
Author:
nperriault
Message:

Clever Svg:

  • refs #40: more elements tests
  • Removed depth management, as svg handle it natively

Warning: breaks BC from 0.5.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • cleversvg/trunk/document/csDocument.class.php

    r335 r336  
    1717 
    1818  /** 
    19    * Definitions container 
    20    * @var array 
    21    */ 
    22   protected $definitions = array(); 
     19   * Definitions and elements container 
     20   * @var csElementsContainer 
     21   */ 
     22  protected $container; 
    2323 
    2424  /** 
     
    4141 
    4242  /** 
    43    * Used definitions references container 
    44    * @var array 
    45    */ 
    46   protected $used_definitions = array(); 
    47  
    48   /** 
    49    * Document elements container 
    50    * @var array 
    51    */ 
    52   protected $elements = array(); 
    53  
    54   /** 
    55    * DOM document unique id attributes container 
    56    * @var array 
    57    */ 
    58   protected $dom_ids = array(); 
    59  
    60   /** 
    6143   * Document description 
    6244   * @var string 
     
    8668   * @var boolean 
    8769   */ 
    88   protected $embedded = false; 
     70  public static $embedded = false; 
    8971 
    9072  /** 
     
    10789    $this->setHeight($height); 
    10890    $this->setTitle($title); 
     91    $this->container = new csElementsContainer(); 
    10992    $this->attributes = array_merge($attrs, $this->attributes); 
    11093    $this->initDefaults(); 
     
    11598   * 
    11699   * @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 ? 
    119100   * @throws csException 
    120101   */ 
    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/** 
    157108   * Create an svg element and returns its instance 
    158109   * 
     
    162113  public function createElement($name) 
    163114  { 
    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); 
    171116  } 
    172117 
     
    179124  public function dropElementById($id) 
    180125  { 
    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); 
    196127  } 
    197128 
     
    205136  public function getElementById($id) 
    206137  { 
    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); 
    215139  } 
    216140 
     
    222146  protected function getElements() 
    223147  { 
    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; 
    225159  } 
    226160 
     
    230164   * @return string 
    231165   */ 
    232   protected function getNodeNS() 
     166  public static function getNodeNS() 
    233167  { 
    234168    $prefix = ''; 
    235     if ($this->embedded === true) 
     169    if (self::$embedded === true) 
    236170    { 
    237171      $prefix = 'svg:'; 
     
    293227  public function addAsDefinition($definition, $id = null) 
    294228  { 
    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); 
    316230  } 
    317231 
     
    323237  protected function getDefinitions() 
    324238  { 
    325     return $this->definitions; 
     239    return $this->container->getDefinitions(); 
    326240  } 
    327241 
     
    333247  protected function getUsedDefinitions() 
    334248  { 
    335     return $this->used_definitions; 
     249    return $this->container->getUsedDefinitions(); 
    336250  } 
    337251 
     
    339253   * Returns a defined element alias (a <use/> tag) 
    340254   * 
     255   * @param  string  $id 
    341256   * @return array 
     257   * @throws csException 
    342258   */ 
    343259  protected function getDefinition($id) 
    344260  { 
    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); 
    354262  } 
    355263 
     
    384292        break; 
    385293      } 
    386       if (true === $this->embedded) 
     294      if (true === self::$embedded) 
    387295      { 
    388296        $dom = new DOMDocument('1.0', 'UTF-8'); 
     
    408316  public function useDefinition($id, $attrs = array()) 
    409317  { 
    410     $this->used_definitions[] = array($this->getDefinition($id), $attrs); 
     318    return $this->container->useDefinition($id, $attrs); 
    411319  } 
    412320 
     
    421329  public function swapDepths($id1, $id2) 
    422330  { 
    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); 
    437332  } 
    438333 
     
    440335   * Checks if a DOM id already exists in current SVG Document 
    441336   * 
    442    * @param  string  $dom_id 
     337   * @param  string  $id 
    443338   * @return boolean 
    444339   */ 
    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); 
    448343  } 
    449344 
     
    486381  public function setEmbedded($flag) 
    487382  { 
    488     $this->embedded = (boolean) $flag; 
     383    self::$embedded = (boolean) $flag; 
    489384  } 
    490385 
     
    627522    $dom->normalizeDocument(); 
    628523 
    629     // Validation 
    630     $this->validate($dom); 
     524    // Validation if strict mode 
     525    if (true === $this->strict_mode) 
     526    { 
     527      $this->validate(); 
     528    } 
    631529 
    632530    // Output 
    633     if ($this->embedded === true) 
     531    if (self::$embedded === true) 
    634532    { 
    635533      return $dom->saveXml($dom->documentElement, LIBXML_NOXMLDECL); 
     
    642540 
    643541  /** 
    644    * Process definitionsn if any 
     542   * Process definitions if any 
    645543   * 
    646544   */ 
    647545  protected function processDefinitions() 
    648546  { 
    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()); 
    663548  } 
    664549 
     
    669554  protected function processElements() 
    670555  { 
    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()); 
    678557  } 
    679558 
     
    690569      foreach ($this->embed_styles as $style) 
    691570      { 
    692         $style_node = $dom->createElement($this->getNodeNS().'style'); 
     571        $style_node = $dom->createElement(self::getNodeNS().'style'); 
    693572        $style_node->setAttribute('type',  $style['type']); 
    694573        $style_node->setAttribute('media', $style['media']); 
     
    733612    if (!is_null($this->title)) 
    734613    { 
    735       $title_node = $dom->createElement($this->getNodeNS().'title', 
     614      $title_node = $dom->createElement(self::getNodeNS().'title', 
    736615                                        strip_tags($this->title)); 
    737616      $dom->documentElement->appendChild($title_node); 
     
    742621    if (!is_null($this->description)) 
    743622    { 
    744       $desc_node = $dom->createElement($this->getNodeNS().'desc', 
     623      $desc_node = $dom->createElement(self::getNodeNS().'desc', 
    745624                                       strip_tags($this->description)); 
    746625      $dom->documentElement->appendChild($desc_node); 
     
    755634  { 
    756635    $dom = $this->getDomDocument(); 
    757     $root = $this->dom_document->createElement($this->getNodeNS().'svg'); 
     636    $root = $this->dom_document->createElement(self::getNodeNS().'svg'); 
    758637    $dom->appendChild($root); 
    759638    foreach ($this->attributes as $attr_name => $attr_value) 
     
    767646 
    768647  /** 
     648   * Process used definitions, if any 
     649   * 
     650   */ 
     651  protected function processUsedDefinitions() 
     652  { 
     653    return $this->container->processUsedDefinitions($this->getDomDocument()); 
     654  } 
     655 
     656  /** 
    769657   * Process scripts, if any 
    770658   * 
     
    778666      foreach ($this->scripts as $script) 
    779667      { 
    780         $script_node = $dom->createElement($this->getNodeNS().'script'); 
     668        $script_node = $dom->createElement(self::getNodeNS().'script'); 
    781669        $script_node->setAttribute('type', $script[1]); 
    782670        $script_content = $dom->createCDATASection($script[0]); 
     
    788676 
    789677  /** 
    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())) 
    799691      { 
    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'); 
    809694      } 
    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()); 
    823697    } 
    824698  }