PageRenderTime 46ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/phenx/php-svg-lib/src/Svg/Document.php

https://bitbucket.org/openemr/openemr
PHP | 353 lines | 270 code | 69 blank | 14 comment | 27 complexity | e28b10d336d33bc7c55236afa50139db MD5 | raw file
Possible License(s): Apache-2.0, AGPL-1.0, GPL-2.0, LGPL-3.0, BSD-3-Clause, Unlicense, MPL-2.0, GPL-3.0, LGPL-2.1
  1. <?php
  2. /**
  3. * @package php-svg-lib
  4. * @link http://github.com/PhenX/php-svg-lib
  5. * @author Fabien Ménager <fabien.menager@gmail.com>
  6. * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  7. */
  8. namespace Svg;
  9. use Svg\Surface\SurfaceInterface;
  10. use Svg\Tag\AbstractTag;
  11. use Svg\Tag\Anchor;
  12. use Svg\Tag\Circle;
  13. use Svg\Tag\Ellipse;
  14. use Svg\Tag\Group;
  15. use Svg\Tag\Image;
  16. use Svg\Tag\Line;
  17. use Svg\Tag\LinearGradient;
  18. use Svg\Tag\Path;
  19. use Svg\Tag\Polygon;
  20. use Svg\Tag\Polyline;
  21. use Svg\Tag\Rect;
  22. use Svg\Tag\Stop;
  23. use Svg\Tag\Text;
  24. class Document extends AbstractTag
  25. {
  26. protected $filename;
  27. protected $inDefs = false;
  28. protected $x;
  29. protected $y;
  30. protected $width;
  31. protected $height;
  32. protected $subPathInit;
  33. protected $pathBBox;
  34. protected $viewBox;
  35. /** @var resource */
  36. protected $parser;
  37. /** @var SurfaceInterface */
  38. protected $surface;
  39. /** @var AbstractTag[] */
  40. protected $stack = array();
  41. /** @var AbstractTag[] */
  42. protected $defs = array();
  43. public function loadFile($filename)
  44. {
  45. $this->filename = $filename;
  46. }
  47. protected function initParser() {
  48. $parser = xml_parser_create("utf-8");
  49. xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
  50. xml_set_element_handler(
  51. $parser,
  52. array($this, "_tagStart"),
  53. array($this, "_tagEnd")
  54. );
  55. xml_set_character_data_handler(
  56. $parser,
  57. array($this, "_charData")
  58. );
  59. return $this->parser = $parser;
  60. }
  61. public function __construct() {
  62. }
  63. /**
  64. * @return SurfaceInterface
  65. */
  66. public function getSurface()
  67. {
  68. return $this->surface;
  69. }
  70. public function getStack()
  71. {
  72. return $this->stack;
  73. }
  74. public function getWidth()
  75. {
  76. return $this->width;
  77. }
  78. public function getHeight()
  79. {
  80. return $this->height;
  81. }
  82. public function getDimensions() {
  83. $rootAttributes = null;
  84. $parser = xml_parser_create("utf-8");
  85. xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
  86. xml_set_element_handler(
  87. $parser,
  88. function ($parser, $name, $attributes) use (&$rootAttributes) {
  89. if ($name === "svg" && $rootAttributes === null) {
  90. $attributes = array_change_key_case($attributes, CASE_LOWER);
  91. $rootAttributes = $attributes;
  92. }
  93. },
  94. function ($parser, $name) {}
  95. );
  96. $fp = fopen($this->filename, "r");
  97. while ($line = fread($fp, 8192)) {
  98. xml_parse($parser, $line, false);
  99. if ($rootAttributes !== null) {
  100. break;
  101. }
  102. }
  103. xml_parser_free($parser);
  104. return $this->handleSizeAttributes($rootAttributes);
  105. }
  106. public function handleSizeAttributes($attributes){
  107. if ($this->width === null) {
  108. if (isset($attributes["width"])) {
  109. $width = (int)$attributes["width"];
  110. $this->width = $width;
  111. }
  112. if (isset($attributes["height"])) {
  113. $height = (int)$attributes["height"];
  114. $this->height = $height;
  115. }
  116. if (isset($attributes['viewbox'])) {
  117. $viewBox = preg_split('/[\s,]+/is', trim($attributes['viewbox']));
  118. if (count($viewBox) == 4) {
  119. $this->x = $viewBox[0];
  120. $this->y = $viewBox[1];
  121. if (!$this->width) {
  122. $this->width = $viewBox[2];
  123. }
  124. if (!$this->height) {
  125. $this->height = $viewBox[3];
  126. }
  127. }
  128. }
  129. }
  130. return array(
  131. 0 => $this->width,
  132. 1 => $this->height,
  133. "width" => $this->width,
  134. "height" => $this->height,
  135. );
  136. }
  137. protected function getDocument(){
  138. return $this;
  139. }
  140. protected function before($attribs)
  141. {
  142. $surface = $this->getSurface();
  143. $style = new DefaultStyle();
  144. $style->inherit($this);
  145. $style->fromAttributes($attribs);
  146. $this->setStyle($style);
  147. $surface->setStyle($style);
  148. }
  149. public function render(SurfaceInterface $surface)
  150. {
  151. $this->inDefs = false;
  152. $this->surface = $surface;
  153. $parser = $this->initParser();
  154. if ($this->x || $this->y) {
  155. $surface->translate(-$this->x, -$this->y);
  156. }
  157. $fp = fopen($this->filename, "r");
  158. while ($line = fread($fp, 8192)) {
  159. xml_parse($parser, $line, false);
  160. }
  161. xml_parse($parser, "", true);
  162. xml_parser_free($parser);
  163. }
  164. protected function svgOffset($attributes)
  165. {
  166. $this->attributes = $attributes;
  167. $this->handleSizeAttributes($attributes);
  168. }
  169. private function _tagStart($parser, $name, $attributes)
  170. {
  171. $this->x = 0;
  172. $this->y = 0;
  173. $tag = null;
  174. $attributes = array_change_key_case($attributes, CASE_LOWER);
  175. switch (strtolower($name)) {
  176. case 'defs':
  177. $this->inDefs = true;
  178. return;
  179. case 'svg':
  180. if (count($this->attributes)) {
  181. $tag = new Group($this);
  182. }
  183. else {
  184. $tag = $this;
  185. $this->svgOffset($attributes);
  186. }
  187. break;
  188. case 'path':
  189. $tag = new Path($this);
  190. break;
  191. case 'rect':
  192. $tag = new Rect($this);
  193. break;
  194. case 'circle':
  195. $tag = new Circle($this);
  196. break;
  197. case 'ellipse':
  198. $tag = new Ellipse($this);
  199. break;
  200. case 'image':
  201. $tag = new Image($this);
  202. break;
  203. case 'line':
  204. $tag = new Line($this);
  205. break;
  206. case 'polyline':
  207. $tag = new Polyline($this);
  208. break;
  209. case 'polygon':
  210. $tag = new Polygon($this);
  211. break;
  212. case 'lineargradient':
  213. $tag = new LinearGradient($this);
  214. break;
  215. case 'radialgradient':
  216. $tag = new LinearGradient($this);
  217. break;
  218. case 'stop':
  219. $tag = new Stop($this);
  220. break;
  221. case 'a':
  222. $tag = new Anchor($this);
  223. break;
  224. case 'g':
  225. $tag = new Group($this);
  226. break;
  227. case 'text':
  228. $tag = new Text($this);
  229. break;
  230. }
  231. if ($tag) {
  232. if (!$this->inDefs) {
  233. $this->stack[] = $tag;
  234. $tag->handle($attributes);
  235. }
  236. else {
  237. if (isset($attributes["id"])) {
  238. $this->defs[$attributes["id"]] = $tag;
  239. }
  240. }
  241. } else {
  242. echo "Unknown: '$name'\n";
  243. }
  244. }
  245. function _charData($parser, $data)
  246. {
  247. $stack_top = end($this->stack);
  248. if ($stack_top instanceof Text) {
  249. $stack_top->appendText($data);
  250. }
  251. }
  252. function _tagEnd($parser, $name)
  253. {
  254. /** @var AbstractTag $tag */
  255. $tag = null;
  256. switch (strtolower($name)) {
  257. case 'defs':
  258. $this->inDefs = false;
  259. return;
  260. case 'svg':
  261. case 'path':
  262. case 'rect':
  263. case 'circle':
  264. case 'ellipse':
  265. case 'image':
  266. case 'line':
  267. case 'polyline':
  268. case 'polygon':
  269. case 'radialgradient':
  270. case 'lineargradient':
  271. case 'stop':
  272. case 'text':
  273. case 'g':
  274. case 'a':
  275. if (!$this->inDefs) {
  276. $tag = array_pop($this->stack);
  277. }
  278. break;
  279. }
  280. if ($tag) {
  281. $tag->handleEnd();
  282. }
  283. }
  284. }