composer package updates
[openemr.git] / vendor / phenx / php-svg-lib / src / Svg / Surface / SurfacePDFLib.php
bloba4d17342bc96097bd62a4de1890241b610b993c0
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 */
9 namespace Svg\Surface;
11 use Svg\Style;
12 use Svg\Document;
14 class SurfacePDFLib implements SurfaceInterface
16 const DEBUG = false;
18 private $canvas;
20 private $width;
21 private $height;
23 /** @var Style */
24 private $style;
26 public function __construct(Document $doc, $canvas = null)
28 if (self::DEBUG) echo __FUNCTION__ . "\n";
30 $dimensions = $doc->getDimensions();
31 $w = $dimensions["width"];
32 $h = $dimensions["height"];
34 if (!$canvas) {
35 $canvas = new \PDFlib();
37 /* all strings are expected as utf8 */
38 $canvas->set_option("stringformat=utf8");
39 $canvas->set_option("errorpolicy=return");
41 /* open new PDF file; insert a file name to create the PDF on disk */
42 if ($canvas->begin_document("", "") == 0) {
43 die("Error: " . $canvas->get_errmsg());
45 $canvas->set_info("Creator", "PDFlib starter sample");
46 $canvas->set_info("Title", "starter_graphics");
48 $canvas->begin_page_ext($w, $h, "");
51 // Flip PDF coordinate system so that the origin is in
52 // the top left rather than the bottom left
53 $canvas->setmatrix(
54 1, 0,
55 0, -1,
56 0, $h
59 $this->width = $w;
60 $this->height = $h;
62 $this->canvas = $canvas;
65 function out()
67 if (self::DEBUG) echo __FUNCTION__ . "\n";
69 $this->canvas->end_page_ext("");
70 $this->canvas->end_document("");
72 return $this->canvas->get_buffer();
75 public function save()
77 if (self::DEBUG) echo __FUNCTION__ . "\n";
78 $this->canvas->save();
81 public function restore()
83 if (self::DEBUG) echo __FUNCTION__ . "\n";
84 $this->canvas->restore();
87 public function scale($x, $y)
89 if (self::DEBUG) echo __FUNCTION__ . "\n";
90 $this->canvas->scale($x, $y);
93 public function rotate($angle)
95 if (self::DEBUG) echo __FUNCTION__ . "\n";
96 $this->canvas->rotate($angle);
99 public function translate($x, $y)
101 if (self::DEBUG) echo __FUNCTION__ . "\n";
102 $this->canvas->translate($x, $y);
105 public function transform($a, $b, $c, $d, $e, $f)
107 if (self::DEBUG) echo __FUNCTION__ . "\n";
108 $this->canvas->concat($a, $b, $c, $d, $e, $f);
111 public function beginPath()
113 if (self::DEBUG) echo __FUNCTION__ . "\n";
114 // TODO: Implement beginPath() method.
117 public function closePath()
119 if (self::DEBUG) echo __FUNCTION__ . "\n";
120 $this->canvas->closepath();
123 public function fillStroke()
125 if (self::DEBUG) echo __FUNCTION__ . "\n";
126 $this->canvas->fill_stroke();
129 public function clip()
131 if (self::DEBUG) echo __FUNCTION__ . "\n";
132 $this->canvas->clip();
135 public function fillText($text, $x, $y, $maxWidth = null)
137 if (self::DEBUG) echo __FUNCTION__ . "\n";
138 $this->canvas->set_text_pos($x, $y);
139 $this->canvas->show($text);
142 public function strokeText($text, $x, $y, $maxWidth = null)
144 if (self::DEBUG) echo __FUNCTION__ . "\n";
145 // TODO: Implement drawImage() method.
148 public function drawImage($image, $sx, $sy, $sw = null, $sh = null, $dx = null, $dy = null, $dw = null, $dh = null)
150 if (self::DEBUG) echo __FUNCTION__ . "\n";
152 if (strpos($image, "data:") === 0) {
153 $data = substr($image, strpos($image, ";") + 1);
154 if (strpos($data, "base64") === 0) {
155 $data = base64_decode(substr($data, 7));
158 else {
159 $data = file_get_contents($image);
162 $image = tempnam("", "svg");
163 file_put_contents($image, $data);
165 $img = $this->canvas->load_image("auto", $image, "");
167 $sy = $sy - $sh;
168 $this->canvas->fit_image($img, $sx, $sy, 'boxsize={' . "$sw $sh" . '} fitmethod=entire');
170 unlink($image);
173 public function lineTo($x, $y)
175 if (self::DEBUG) echo __FUNCTION__ . "\n";
176 $this->canvas->lineto($x, $y);
179 public function moveTo($x, $y)
181 if (self::DEBUG) echo __FUNCTION__ . "\n";
182 $this->canvas->moveto($x, $y);
185 public function quadraticCurveTo($cpx, $cpy, $x, $y)
187 if (self::DEBUG) echo __FUNCTION__ . "\n";
189 // FIXME not accurate
190 $this->canvas->curveTo($cpx, $cpy, $cpx, $cpy, $x, $y);
193 public function bezierCurveTo($cp1x, $cp1y, $cp2x, $cp2y, $x, $y)
195 if (self::DEBUG) echo __FUNCTION__ . "\n";
196 $this->canvas->curveto($cp1x, $cp1y, $cp2x, $cp2y, $x, $y);
199 public function arcTo($x1, $y1, $x2, $y2, $radius)
201 if (self::DEBUG) echo __FUNCTION__ . "\n";
204 public function arc($x, $y, $radius, $startAngle, $endAngle, $anticlockwise = false)
206 if (self::DEBUG) echo __FUNCTION__ . "\n";
207 $this->canvas->arc($x, $y, $radius, $startAngle, $endAngle);
210 public function circle($x, $y, $radius)
212 if (self::DEBUG) echo __FUNCTION__ . "\n";
213 $this->canvas->circle($x, $y, $radius);
216 public function ellipse($x, $y, $radiusX, $radiusY, $rotation, $startAngle, $endAngle, $anticlockwise)
218 if (self::DEBUG) echo __FUNCTION__ . "\n";
219 $this->canvas->ellipse($x, $y, $radiusX, $radiusY);
222 public function fillRect($x, $y, $w, $h)
224 if (self::DEBUG) echo __FUNCTION__ . "\n";
225 $this->rect($x, $y, $w, $h);
226 $this->fill();
229 public function rect($x, $y, $w, $h, $rx = 0, $ry = 0)
231 if (self::DEBUG) echo __FUNCTION__ . "\n";
233 $canvas = $this->canvas;
235 if ($rx <= 0.000001/* && $ry <= 0.000001*/) {
236 $canvas->rect($x, $y, $w, $h);
238 return;
241 /* Define a path for a rectangle with corners rounded by a given radius.
242 * Start from the lower left corner and proceed counterclockwise.
244 $canvas->moveto($x + $rx, $y);
246 /* Start of the arc segment in the lower right corner */
247 $canvas->lineto($x + $w - $rx, $y);
249 /* Arc segment in the lower right corner */
250 $canvas->arc($x + $w - $rx, $y + $rx, $rx, 270, 360);
252 /* Start of the arc segment in the upper right corner */
253 $canvas->lineto($x + $w, $y + $h - $rx );
255 /* Arc segment in the upper right corner */
256 $canvas->arc($x + $w - $rx, $y + $h - $rx, $rx, 0, 90);
258 /* Start of the arc segment in the upper left corner */
259 $canvas->lineto($x + $rx, $y + $h);
261 /* Arc segment in the upper left corner */
262 $canvas->arc($x + $rx, $y + $h - $rx, $rx, 90, 180);
264 /* Start of the arc segment in the lower left corner */
265 $canvas->lineto($x , $y + $rx);
267 /* Arc segment in the lower left corner */
268 $canvas->arc($x + $rx, $y + $rx, $rx, 180, 270);
271 public function fill()
273 if (self::DEBUG) echo __FUNCTION__ . "\n";
274 $this->canvas->fill();
277 public function strokeRect($x, $y, $w, $h)
279 if (self::DEBUG) echo __FUNCTION__ . "\n";
280 $this->rect($x, $y, $w, $h);
281 $this->stroke();
284 public function stroke()
286 if (self::DEBUG) echo __FUNCTION__ . "\n";
287 $this->canvas->stroke();
290 public function endPath()
292 if (self::DEBUG) echo __FUNCTION__ . "\n";
293 $this->canvas->endPath();
296 public function measureText($text)
298 if (self::DEBUG) echo __FUNCTION__ . "\n";
299 $style = $this->getStyle();
300 $font = $this->getFont($style->fontFamily, $style->fontStyle);
302 return $this->canvas->stringwidth($text, $font, $this->getStyle()->fontSize);
305 public function getStyle()
307 if (self::DEBUG) echo __FUNCTION__ . "\n";
308 return $this->style;
311 public function setStyle(Style $style)
313 if (self::DEBUG) echo __FUNCTION__ . "\n";
315 $this->style = $style;
316 $canvas = $this->canvas;
318 if ($stroke = $style->stroke && is_array($style->stroke)) {
319 $canvas->setcolor(
320 "stroke",
321 "rgb",
322 $stroke[0] / 255,
323 $stroke[1] / 255,
324 $stroke[2] / 255,
325 null
329 if ($fill = $style->fill && is_array($style->fill)) {
330 $canvas->setcolor(
331 "fill",
332 "rgb",
333 $fill[0] / 255,
334 $fill[1] / 255,
335 $fill[2] / 255,
336 null
340 if ($fillRule = strtolower($style->fillRule)) {
341 $map = array(
342 "nonzero" => "winding",
343 "evenodd" => "evenodd",
346 if (isset($map[$fillRule])) {
347 $fillRule = $map[$fillRule];
349 $canvas->set_parameter("fillrule", $fillRule);
353 $opts = array();
354 if ($style->strokeWidth > 0.000001) {
355 $opts[] = "linewidth=$style->strokeWidth";
358 if (in_array($style->strokeLinecap, array("butt", "round", "projecting"))) {
359 $opts[] = "linecap=$style->strokeLinecap";
362 if (in_array($style->strokeLinejoin, array("miter", "round", "bevel"))) {
363 $opts[] = "linejoin=$style->strokeLinejoin";
366 $canvas->set_graphics_option(implode(" ", $opts));
368 $opts = array();
369 $opacity = $style->opacity;
370 if ($opacity !== null && $opacity < 1.0) {
371 $opts[] = "opacityfill=$opacity";
372 $opts[] = "opacitystroke=$opacity";
374 else {
375 $fillOpacity = $style->fillOpacity;
376 if ($fillOpacity !== null && $fillOpacity < 1.0) {
377 $opts[] = "opacityfill=$fillOpacity";
380 $strokeOpacity = $style->strokeOpacity;
381 if ($strokeOpacity !== null && $strokeOpacity < 1.0) {
382 $opts[] = "opacitystroke=$strokeOpacity";
386 if (count($opts)) {
387 $gs = $canvas->create_gstate(implode(" ", $opts));
388 $canvas->set_gstate($gs);
391 $font = $this->getFont($style->fontFamily, $style->fontStyle);
392 if ($font) {
393 $canvas->setfont($font, $style->fontSize);
397 private function getFont($family, $style)
399 $map = array(
400 "serif" => "Times",
401 "sans-serif" => "Helvetica",
402 "fantasy" => "Symbol",
403 "cursive" => "Times",
404 "monospace" => "Courier",
406 "arial" => "Helvetica",
407 "verdana" => "Helvetica",
410 $family = strtolower($family);
411 if (isset($map[$family])) {
412 $family = $map[$family];
415 return $this->canvas->load_font($family, "unicode", "fontstyle=$style");
418 public function setFont($family, $style, $weight)
420 // TODO: Implement setFont() method.