PageRenderTime 25ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/application/third_party/dompdf/lib/php-svg-lib/src/Svg/Document.php

https://gitlab.com/Japang-Jawara/jawara-penilaian
PHP | 404 lines | 298 code | 80 blank | 26 comment | 29 complexity | 7bd4a2c90750c3b79086503b380c1bdd MD5 | raw file
  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 GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
  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\ClipPath;
  16. use Svg\Tag\Image;
  17. use Svg\Tag\Line;
  18. use Svg\Tag\LinearGradient;
  19. use Svg\Tag\Path;
  20. use Svg\Tag\Polygon;
  21. use Svg\Tag\Polyline;
  22. use Svg\Tag\Rect;
  23. use Svg\Tag\Stop;
  24. use Svg\Tag\Text;
  25. use Svg\Tag\StyleTag;
  26. use Svg\Tag\UseTag;
  27. class Document extends AbstractTag
  28. {
  29. protected $filename;
  30. public $inDefs = false;
  31. protected $x;
  32. protected $y;
  33. protected $width;
  34. protected $height;
  35. protected $subPathInit;
  36. protected $pathBBox;
  37. protected $viewBox;
  38. /** @var resource */
  39. protected $parser;
  40. /** @var SurfaceInterface */
  41. protected $surface;
  42. /** @var AbstractTag[] */
  43. protected $stack = array();
  44. /** @var AbstractTag[] */
  45. protected $defs = array();
  46. /** @var \Sabberworm\CSS\CSSList\Document[] */
  47. protected $styleSheets = array();
  48. public function loadFile($filename)
  49. {
  50. $this->filename = $filename;
  51. }
  52. protected function initParser() {
  53. $parser = xml_parser_create("utf-8");
  54. xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
  55. xml_set_element_handler(
  56. $parser,
  57. array($this, "_tagStart"),
  58. array($this, "_tagEnd")
  59. );
  60. xml_set_character_data_handler(
  61. $parser,
  62. array($this, "_charData")
  63. );
  64. return $this->parser = $parser;
  65. }
  66. public function __construct() {
  67. }
  68. /**
  69. * @return SurfaceInterface
  70. */
  71. public function getSurface()
  72. {
  73. return $this->surface;
  74. }
  75. public function getStack()
  76. {
  77. return $this->stack;
  78. }
  79. public function getWidth()
  80. {
  81. return $this->width;
  82. }
  83. public function getHeight()
  84. {
  85. return $this->height;
  86. }
  87. public function getDimensions() {
  88. $rootAttributes = null;
  89. $parser = xml_parser_create("utf-8");
  90. xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
  91. xml_set_element_handler(
  92. $parser,
  93. function ($parser, $name, $attributes) use (&$rootAttributes) {
  94. if ($name === "svg" && $rootAttributes === null) {
  95. $attributes = array_change_key_case($attributes, CASE_LOWER);
  96. $rootAttributes = $attributes;
  97. }
  98. },
  99. function ($parser, $name) {}
  100. );
  101. $fp = fopen($this->filename, "r");
  102. while ($line = fread($fp, 8192)) {
  103. xml_parse($parser, $line, false);
  104. if ($rootAttributes !== null) {
  105. break;
  106. }
  107. }
  108. xml_parser_free($parser);
  109. return $this->handleSizeAttributes($rootAttributes);
  110. }
  111. public function handleSizeAttributes($attributes){
  112. if ($this->width === null) {
  113. if (isset($attributes["width"])) {
  114. $width = Style::convertSize($attributes["width"], 400);
  115. $this->width = $width;
  116. }
  117. if (isset($attributes["height"])) {
  118. $height = Style::convertSize($attributes["height"], 300);
  119. $this->height = $height;
  120. }
  121. if (isset($attributes['viewbox'])) {
  122. $viewBox = preg_split('/[\s,]+/is', trim($attributes['viewbox']));
  123. if (count($viewBox) == 4) {
  124. $this->x = $viewBox[0];
  125. $this->y = $viewBox[1];
  126. if (!$this->width) {
  127. $this->width = $viewBox[2];
  128. }
  129. if (!$this->height) {
  130. $this->height = $viewBox[3];
  131. }
  132. }
  133. }
  134. }
  135. return array(
  136. 0 => $this->width,
  137. 1 => $this->height,
  138. "width" => $this->width,
  139. "height" => $this->height,
  140. );
  141. }
  142. public function getDocument(){
  143. return $this;
  144. }
  145. /**
  146. * Append a style sheet
  147. *
  148. * @param \Sabberworm\CSS\CSSList\Document $stylesheet
  149. */
  150. public function appendStyleSheet($stylesheet) {
  151. $this->styleSheets[] = $stylesheet;
  152. }
  153. /**
  154. * Get the document style sheets
  155. *
  156. * @return \Sabberworm\CSS\CSSList\Document[]
  157. */
  158. public function getStyleSheets() {
  159. return $this->styleSheets;
  160. }
  161. protected function before($attributes)
  162. {
  163. $surface = $this->getSurface();
  164. $style = new DefaultStyle();
  165. $style->inherit($this);
  166. $style->fromAttributes($attributes);
  167. $this->setStyle($style);
  168. $surface->setStyle($style);
  169. }
  170. public function render(SurfaceInterface $surface)
  171. {
  172. $this->inDefs = false;
  173. $this->surface = $surface;
  174. $parser = $this->initParser();
  175. if ($this->x || $this->y) {
  176. $surface->translate(-$this->x, -$this->y);
  177. }
  178. $fp = fopen($this->filename, "r");
  179. while ($line = fread($fp, 8192)) {
  180. xml_parse($parser, $line, false);
  181. }
  182. xml_parse($parser, "", true);
  183. xml_parser_free($parser);
  184. }
  185. protected function svgOffset($attributes)
  186. {
  187. $this->attributes = $attributes;
  188. $this->handleSizeAttributes($attributes);
  189. }
  190. public function getDef($id) {
  191. $id = ltrim($id, "#");
  192. return isset($this->defs[$id]) ? $this->defs[$id] : null;
  193. }
  194. private function _tagStart($parser, $name, $attributes)
  195. {
  196. $this->x = 0;
  197. $this->y = 0;
  198. $tag = null;
  199. $attributes = array_change_key_case($attributes, CASE_LOWER);
  200. switch (strtolower($name)) {
  201. case 'defs':
  202. $this->inDefs = true;
  203. return;
  204. case 'svg':
  205. if (count($this->attributes)) {
  206. $tag = new Group($this, $name);
  207. }
  208. else {
  209. $tag = $this;
  210. $this->svgOffset($attributes);
  211. }
  212. break;
  213. case 'path':
  214. $tag = new Path($this, $name);
  215. break;
  216. case 'rect':
  217. $tag = new Rect($this, $name);
  218. break;
  219. case 'circle':
  220. $tag = new Circle($this, $name);
  221. break;
  222. case 'ellipse':
  223. $tag = new Ellipse($this, $name);
  224. break;
  225. case 'image':
  226. $tag = new Image($this, $name);
  227. break;
  228. case 'line':
  229. $tag = new Line($this, $name);
  230. break;
  231. case 'polyline':
  232. $tag = new Polyline($this, $name);
  233. break;
  234. case 'polygon':
  235. $tag = new Polygon($this, $name);
  236. break;
  237. case 'lineargradient':
  238. $tag = new LinearGradient($this, $name);
  239. break;
  240. case 'radialgradient':
  241. $tag = new LinearGradient($this, $name);
  242. break;
  243. case 'stop':
  244. $tag = new Stop($this, $name);
  245. break;
  246. case 'style':
  247. $tag = new StyleTag($this, $name);
  248. break;
  249. case 'a':
  250. $tag = new Anchor($this, $name);
  251. break;
  252. case 'g':
  253. case 'symbol':
  254. $tag = new Group($this, $name);
  255. break;
  256. case 'clippath':
  257. $tag = new ClipPath($this, $name);
  258. break;
  259. case 'use':
  260. $tag = new UseTag($this, $name);
  261. break;
  262. case 'text':
  263. $tag = new Text($this, $name);
  264. break;
  265. case 'desc':
  266. return;
  267. }
  268. if ($tag) {
  269. if (isset($attributes["id"])) {
  270. $this->defs[$attributes["id"]] = $tag;
  271. }
  272. else {
  273. /** @var AbstractTag $top */
  274. $top = end($this->stack);
  275. if ($top && $top != $tag) {
  276. $top->children[] = $tag;
  277. }
  278. }
  279. $this->stack[] = $tag;
  280. $tag->handle($attributes);
  281. }
  282. }
  283. function _charData($parser, $data)
  284. {
  285. $stack_top = end($this->stack);
  286. if ($stack_top instanceof Text || $stack_top instanceof StyleTag) {
  287. $stack_top->appendText($data);
  288. }
  289. }
  290. function _tagEnd($parser, $name)
  291. {
  292. /** @var AbstractTag $tag */
  293. $tag = null;
  294. switch (strtolower($name)) {
  295. case 'defs':
  296. $this->inDefs = false;
  297. return;
  298. case 'svg':
  299. case 'path':
  300. case 'rect':
  301. case 'circle':
  302. case 'ellipse':
  303. case 'image':
  304. case 'line':
  305. case 'polyline':
  306. case 'polygon':
  307. case 'radialgradient':
  308. case 'lineargradient':
  309. case 'stop':
  310. case 'style':
  311. case 'text':
  312. case 'g':
  313. case 'symbol':
  314. case 'clippath':
  315. case 'use':
  316. case 'a':
  317. $tag = array_pop($this->stack);
  318. break;
  319. }
  320. if (!$this->inDefs && $tag) {
  321. $tag->handleEnd();
  322. }
  323. }
  324. }