PDFLib_Adapter

PDF rendering interface.

Defined (1)

The class is defined in the following location(s).

/lib/dompdf/include/pdflib_adapter.cls.php  
  1. class PDFLib_Adapter implements Canvas { 
  2.  
  3. /** 
  4. * Dimensions of paper sizes in points 
  5. * @var array; 
  6. */ 
  7. static public $PAPER_SIZES = array(); // Set to CPDF_Adapter::$PAPER_SIZES below. 
  8.  
  9. /** 
  10. * Whether to create PDFs in memory or on disk 
  11. * @var bool 
  12. */ 
  13. static $IN_MEMORY = true; 
  14.  
  15. /** 
  16. * @var DOMPDF 
  17. */ 
  18. private $_dompdf; 
  19.  
  20. /** 
  21. * Instance of PDFLib class 
  22. * @var PDFlib 
  23. */ 
  24. private $_pdf; 
  25.  
  26. /** 
  27. * Name of temporary file used for PDFs created on disk 
  28. * @var string 
  29. */ 
  30. private $_file; 
  31.  
  32. /** 
  33. * PDF width, in points 
  34. * @var float 
  35. */ 
  36. private $_width; 
  37.  
  38. /** 
  39. * PDF height, in points 
  40. * @var float 
  41. */ 
  42. private $_height; 
  43.  
  44. /** 
  45. * Last fill color used 
  46. * @var array 
  47. */ 
  48. private $_last_fill_color; 
  49.  
  50. /** 
  51. * Last stroke color used 
  52. * @var array 
  53. */ 
  54. private $_last_stroke_color; 
  55.  
  56. /** 
  57. * Cache of image handles 
  58. * @var array 
  59. */ 
  60. private $_imgs; 
  61.  
  62. /** 
  63. * Cache of font handles 
  64. * @var array 
  65. */ 
  66. private $_fonts; 
  67.  
  68. /** 
  69. * List of objects (templates) to add to multiple pages 
  70. * @var array 
  71. */ 
  72. private $_objs; 
  73.  
  74. /** 
  75. * Current page number 
  76. * @var int 
  77. */ 
  78. private $_page_number; 
  79.  
  80. /** 
  81. * Total number of pages 
  82. * @var int 
  83. */ 
  84. private $_page_count; 
  85.  
  86. /** 
  87. * Text to display on every page 
  88. * @var array 
  89. */ 
  90. private $_page_text; 
  91.  
  92. /** 
  93. * Array of pages for accesing after rendering is initially complete 
  94. * @var array 
  95. */ 
  96. private $_pages; 
  97.  
  98. /** 
  99. * Class constructor 
  100. * @param mixed $paper The size of paper to use either a string (see {@link CPDF_Adapter::$PAPER_SIZES}) or 
  101. * an array(xmin, ymin, xmax, ymax) 
  102. * @param string $orientation The orientation of the document (either 'landscape' or 'portrait') 
  103. * @param DOMPDF $dompdf 
  104. */ 
  105. function __construct($paper = "letter", $orientation = "portrait", DOMPDF $dompdf) { 
  106. if ( is_array($paper) ) { 
  107. $size = $paper; 
  108. else if ( isset(self::$PAPER_SIZES[mb_strtolower($paper)]) ) { 
  109. $size = self::$PAPER_SIZES[mb_strtolower($paper)]; 
  110. else { 
  111. $size = self::$PAPER_SIZES["letter"]; 
  112.  
  113. if ( mb_strtolower($orientation) === "landscape" ) { 
  114. list($size[2], $size[3]) = array($size[3], $size[2]); 
  115.  
  116. $this->_width = $size[2] - $size[0]; 
  117. $this->_height= $size[3] - $size[1]; 
  118.  
  119. $this->_dompdf = $dompdf; 
  120.  
  121. $this->_pdf = new PDFLib(); 
  122.  
  123. if ( defined("DOMPDF_PDFLIB_LICENSE") ) 
  124. $this->_pdf->set_parameter( "license", DOMPDF_PDFLIB_LICENSE); 
  125.  
  126. $this->_pdf->set_parameter("textformat", "utf8"); 
  127. $this->_pdf->set_parameter("fontwarning", "false"); 
  128.  
  129. $this->_pdf->set_info("Creator", "DOMPDF"); 
  130.  
  131. // Silence pedantic warnings about missing TZ settings 
  132. $tz = @date_default_timezone_get(); 
  133. date_default_timezone_set("UTC"); 
  134. $this->_pdf->set_info("Date", date("Y-m-d")); 
  135. date_default_timezone_set($tz); 
  136.  
  137. if ( self::$IN_MEMORY ) 
  138. $this->_pdf->begin_document("", ""); 
  139. else { 
  140. $tmp_dir = $this->_dompdf->get_options("temp_dir"); 
  141. $tmp_name = tempnam($tmp_dir, "libdompdf_pdf_"); 
  142. @unlink($tmp_name); 
  143. $this->_file = "$tmp_name.pdf"; 
  144. $this->_pdf->begin_document($this->_file, ""); 
  145.  
  146. $this->_pdf->begin_page_ext($this->_width, $this->_height, ""); 
  147.  
  148. $this->_page_number = $this->_page_count = 1; 
  149. $this->_page_text = array(); 
  150.  
  151. $this->_imgs = array(); 
  152. $this->_fonts = array(); 
  153. $this->_objs = array(); 
  154.  
  155. // Set up font paths 
  156. $families = Font_Metrics::get_font_families(); 
  157. foreach ($families as $files) { 
  158. foreach ($files as $file) { 
  159. $face = basename($file); 
  160. $afm = null; 
  161.  
  162. // Prefer ttfs to afms 
  163. if ( file_exists("$file.ttf") ) { 
  164. $outline = "$file.ttf"; 
  165.  
  166. } else if ( file_exists("$file.TTF") ) { 
  167. $outline = "$file.TTF"; 
  168.  
  169. } else if ( file_exists("$file.pfb") ) { 
  170. $outline = "$file.pfb"; 
  171.  
  172. if ( file_exists("$file.afm") ) { 
  173. $afm = "$file.afm"; 
  174.  
  175. } else if ( file_exists("$file.PFB") ) { 
  176. $outline = "$file.PFB"; 
  177. if ( file_exists("$file.AFM") ) { 
  178. $afm = "$file.AFM"; 
  179. } else { 
  180. continue; 
  181.  
  182. $this->_pdf->set_parameter("FontOutline", "\{$face\}=\{$outline\}"); 
  183.  
  184. if ( !is_null($afm) ) { 
  185. $this->_pdf->set_parameter("FontAFM", "\{$face\}=\{$afm\}"); 
  186.  
  187. function get_dompdf() { 
  188. return $this->_dompdf; 
  189.  
  190. /** 
  191. * Close the pdf 
  192. */ 
  193. protected function _close() { 
  194. $this->_place_objects(); 
  195.  
  196. // Close all pages 
  197. $this->_pdf->suspend_page(""); 
  198. for ($p = 1; $p <= $this->_page_count; $p++) { 
  199. $this->_pdf->resume_page("pagenumber=$p"); 
  200. $this->_pdf->end_page_ext(""); 
  201.  
  202. $this->_pdf->end_document(""); 
  203.  
  204.  
  205. /** 
  206. * Returns the PDFLib instance 
  207. * @return PDFLib 
  208. */ 
  209. function get_pdflib() { 
  210. return $this->_pdf; 
  211.  
  212. /** 
  213. * Add meta information to the PDF 
  214. * @param string $label label of the value (Creator, Producter, etc.) 
  215. * @param string $value the text to set 
  216. */ 
  217. function add_info($label, $value) { 
  218. $this->_pdf->set_info($label, $value); 
  219.  
  220. /** 
  221. * Opens a new 'object' (template in PDFLib-speak) 
  222. * While an object is open, all drawing actions are recorded to the 
  223. * object instead of being drawn on the current page. Objects can 
  224. * be added later to a specific page or to several pages. 
  225. * The return value is an integer ID for the new object. 
  226. * @see PDFLib_Adapter::close_object() 
  227. * @see PDFLib_Adapter::add_object() 
  228. * @return int 
  229. */ 
  230. function open_object() { 
  231. $this->_pdf->suspend_page(""); 
  232. $ret = $this->_pdf->begin_template($this->_width, $this->_height); 
  233. $this->_pdf->save(); 
  234. $this->_objs[$ret] = array("start_page" => $this->_page_number); 
  235. return $ret; 
  236.  
  237. /** 
  238. * Reopen an existing object (NOT IMPLEMENTED) 
  239. * PDFLib does not seem to support reopening templates. 
  240. * @param int $object the ID of a previously opened object 
  241. * @throws DOMPDF_Exception 
  242. * @return void 
  243. */ 
  244. function reopen_object($object) { 
  245. throw new DOMPDF_Exception("PDFLib does not support reopening objects."); 
  246.  
  247. /** 
  248. * Close the current template 
  249. * @see PDFLib_Adapter::open_object() 
  250. */ 
  251. function close_object() { 
  252. $this->_pdf->restore(); 
  253. $this->_pdf->end_template(); 
  254. $this->_pdf->resume_page("pagenumber=".$this->_page_number); 
  255.  
  256. /** 
  257. * Adds the specified object to the document 
  258. * $where can be one of: 
  259. * - 'add' add to current page only 
  260. * - 'all' add to every page from the current one onwards 
  261. * - 'odd' add to all odd numbered pages from now on 
  262. * - 'even' add to all even numbered pages from now on 
  263. * - 'next' add the object to the next page only 
  264. * - 'nextodd' add to all odd numbered pages from the next one 
  265. * - 'nexteven' add to all even numbered pages from the next one 
  266. * @param int $object the object handle returned by open_object() 
  267. * @param string $where 
  268. */ 
  269. function add_object($object, $where = 'all') { 
  270.  
  271. if ( mb_strpos($where, "next") !== false ) { 
  272. $this->_objs[$object]["start_page"]++; 
  273. $where = str_replace("next", "", $where); 
  274. if ( $where == "" ) 
  275. $where = "add"; 
  276.  
  277. $this->_objs[$object]["where"] = $where; 
  278.  
  279. /** 
  280. * Stops the specified template from appearing in the document. 
  281. * The object will stop being displayed on the page following the 
  282. * current one. 
  283. * @param int $object 
  284. */ 
  285. function stop_object($object) { 
  286.  
  287. if ( !isset($this->_objs[$object]) ) 
  288. return; 
  289.  
  290. $start = $this->_objs[$object]["start_page"]; 
  291. $where = $this->_objs[$object]["where"]; 
  292.  
  293. // Place the object on this page if required 
  294. if ( $this->_page_number >= $start && 
  295. (($this->_page_number % 2 == 0 && $where === "even") || 
  296. ($this->_page_number % 2 == 1 && $where === "odd") || 
  297. ($where === "all")) ) { 
  298. $this->_pdf->fit_image($object, 0, 0, ""); 
  299.  
  300. $this->_objs[$object] = null; 
  301. unset($this->_objs[$object]); 
  302.  
  303. /** 
  304. * Add all active objects to the current page 
  305. */ 
  306. protected function _place_objects() { 
  307.  
  308. foreach ( $this->_objs as $obj => $props ) { 
  309. $start = $props["start_page"]; 
  310. $where = $props["where"]; 
  311.  
  312. // Place the object on this page if required 
  313. if ( $this->_page_number >= $start && 
  314. (($this->_page_number % 2 == 0 && $where === "even") || 
  315. ($this->_page_number % 2 == 1 && $where === "odd") || 
  316. ($where === "all")) ) { 
  317. $this->_pdf->fit_image($obj, 0, 0, ""); 
  318.  
  319.  
  320. function get_width() { return $this->_width; } 
  321.  
  322. function get_height() { return $this->_height; } 
  323.  
  324. function get_page_number() { return $this->_page_number; } 
  325.  
  326. function get_page_count() { return $this->_page_count; } 
  327.  
  328. function set_page_number($num) { $this->_page_number = (int)$num; } 
  329.  
  330. function set_page_count($count) { $this->_page_count = (int)$count; } 
  331.  
  332.  
  333. /** 
  334. * Sets the line style 
  335. * @param float $width 
  336. * @param $cap 
  337. * @param string $join 
  338. * @param array $dash 
  339. * @return void 
  340. */ 
  341. protected function _set_line_style($width, $cap, $join, $dash) { 
  342.  
  343. if ( count($dash) == 1 ) 
  344. $dash[] = $dash[0]; 
  345.  
  346. if ( count($dash) > 1 ) 
  347. $this->_pdf->setdashpattern("dasharray={" . implode(" ", $dash) . "}"); 
  348. else 
  349. $this->_pdf->setdash(0, 0); 
  350.  
  351. switch ( $join ) { 
  352. case "miter": 
  353. $this->_pdf->setlinejoin(0); 
  354. break; 
  355.  
  356. case "round": 
  357. $this->_pdf->setlinejoin(1); 
  358. break; 
  359.  
  360. case "bevel": 
  361. $this->_pdf->setlinejoin(2); 
  362. break; 
  363.  
  364. default: 
  365. break; 
  366.  
  367. switch ( $cap ) { 
  368. case "butt": 
  369. $this->_pdf->setlinecap(0); 
  370. break; 
  371.  
  372. case "round": 
  373. $this->_pdf->setlinecap(1); 
  374. break; 
  375.  
  376. case "square": 
  377. $this->_pdf->setlinecap(2); 
  378. break; 
  379.  
  380. default: 
  381. break; 
  382.  
  383. $this->_pdf->setlinewidth($width); 
  384.  
  385.  
  386. /** 
  387. * Sets the line color 
  388. * @param array $color array(r, g, b) 
  389. */ 
  390. protected function _set_stroke_color($color) { 
  391. if($this->_last_stroke_color == $color) 
  392. return; 
  393.  
  394. $this->_last_stroke_color = $color; 
  395.  
  396. if (isset($color[3])) { 
  397. $type = "cmyk"; 
  398. list($c1, $c2, $c3, $c4) = array($color[0], $color[1], $color[2], $color[3]); 
  399. elseif (isset($color[2])) { 
  400. $type = "rgb"; 
  401. list($c1, $c2, $c3, $c4) = array($color[0], $color[1], $color[2], null); 
  402. else { 
  403. $type = "gray"; 
  404. list($c1, $c2, $c3, $c4) = array($color[0], $color[1], null, null); 
  405.  
  406. $this->_pdf->setcolor("stroke", $type, $c1, $c2, $c3, $c4); 
  407.  
  408. /** 
  409. * Sets the fill color 
  410. * @param array $color array(r, g, b) 
  411. */ 
  412. protected function _set_fill_color($color) { 
  413. if($this->_last_fill_color == $color) 
  414. return; 
  415.  
  416. $this->_last_fill_color = $color; 
  417.  
  418. if (isset($color[3])) { 
  419. $type = "cmyk"; 
  420. list($c1, $c2, $c3, $c4) = array($color[0], $color[1], $color[2], $color[3]); 
  421. elseif (isset($color[2])) { 
  422. $type = "rgb"; 
  423. list($c1, $c2, $c3, $c4) = array($color[0], $color[1], $color[2], null); 
  424. else { 
  425. $type = "gray"; 
  426. list($c1, $c2, $c3, $c4) = array($color[0], $color[1], null, null); 
  427.  
  428. $this->_pdf->setcolor("fill", $type, $c1, $c2, $c3, $c4); 
  429.  
  430. /** 
  431. * Sets the opacity  
  432. *  
  433. * @param $opacity 
  434. * @param $mode 
  435. */ 
  436. function set_opacity($opacity, $mode = "Normal") { 
  437. if ( $mode === "Normal" ) { 
  438. $gstate = $this->_pdf->create_gstate("opacityfill=$opacity opacitystroke=$opacity"); 
  439. $this->_pdf->set_gstate($gstate); 
  440.  
  441. function set_default_view($view, $options = array()) { 
  442. // TODO 
  443. // http://www.pdflib.com/fileadmin/pdflib/pdf/manuals/PDFlib-8.0.2-API-reference.pdf 
  444. /** 
  445. * fitheight Fit the page height to the window, with the x coordinate left at the left edge of the window. 
  446. * fitrect Fit the rectangle specified by left, bottom, right, and top to the window. 
  447. * fitvisible Fit the visible contents of the page (the ArtBox) to the window. 
  448. * fitvisibleheight Fit the visible contents of the page to the window with the x coordinate left at the left edge of the window. 
  449. * fitvisiblewidth Fit the visible contents of the page to the window with the y coordinate top at the top edge of the window. 
  450. * fitwidth Fit the page width to the window, with the y coordinate top at the top edge of the window. 
  451. * fitwindow Fit the complete page to the window. 
  452. * fixed 
  453. */ 
  454. //$this->_pdf->set_parameter("openaction", $view); 
  455.  
  456. /** 
  457. * Loads a specific font and stores the corresponding descriptor. 
  458. * @param string $font 
  459. * @param string $encoding 
  460. * @param string $options 
  461. * @return int the font descriptor for the font 
  462. */ 
  463. protected function _load_font($font, $encoding = null, $options = "") { 
  464.  
  465. // Check if the font is a native PDF font 
  466. // Embed non-native fonts 
  467. $test = strtolower(basename($font)); 
  468. if ( in_array($test, DOMPDF::$native_fonts) ) { 
  469. $font = basename($font); 
  470.  
  471. } else { 
  472. // Embed non-native fonts 
  473. $options .= " embedding=true"; 
  474.  
  475. if ( is_null($encoding) ) { 
  476.  
  477. // Unicode encoding is only available for the commerical 
  478. // version of PDFlib and not PDFlib-Lite 
  479. if ( defined("DOMPDF_PDFLIB_LICENSE") ) 
  480. $encoding = "unicode"; 
  481. else 
  482. $encoding = "auto"; 
  483.  
  484.  
  485. $key = "$font:$encoding:$options"; 
  486.  
  487. if ( isset($this->_fonts[$key]) ) 
  488. return $this->_fonts[$key]; 
  489.  
  490. else { 
  491.  
  492. $this->_fonts[$key] = $this->_pdf->load_font($font, $encoding, $options); 
  493. return $this->_fonts[$key]; 
  494.  
  495.  
  496.  
  497. /** 
  498. * Remaps y coords from 4th to 1st quadrant 
  499. * @param float $y 
  500. * @return float 
  501. */ 
  502. protected function y($y) { return $this->_height - $y; } 
  503.  
  504. //........................................................................ 
  505.  
  506. /** 
  507. * @param float $x1 
  508. * @param float $y1 
  509. * @param float $x2 
  510. * @param float $y2 
  511. * @param array $color 
  512. * @param float $width 
  513. * @param array $style 
  514. */ 
  515. function line($x1, $y1, $x2, $y2, $color, $width, $style = null) { 
  516. $this->_set_line_style($width, "butt", "", $style); 
  517. $this->_set_stroke_color($color); 
  518.  
  519. $y1 = $this->y($y1); 
  520. $y2 = $this->y($y2); 
  521.  
  522. $this->_pdf->moveto($x1, $y1); 
  523. $this->_pdf->lineto($x2, $y2); 
  524. $this->_pdf->stroke(); 
  525.  
  526. function arc($x1, $y1, $r1, $r2, $astart, $aend, $color, $width, $style = array()) { 
  527. $this->_set_line_style($width, "butt", "", $style); 
  528. $this->_set_stroke_color($color); 
  529.  
  530. $y1 = $this->y($y1); 
  531.  
  532. $this->_pdf->arc($x1, $y1, $r1, $astart, $aend); 
  533. $this->_pdf->stroke(); 
  534.  
  535. //........................................................................ 
  536.  
  537. function rectangle($x1, $y1, $w, $h, $color, $width, $style = null) { 
  538. $this->_set_stroke_color($color); 
  539. $this->_set_line_style($width, "butt", "", $style); 
  540.  
  541. $y1 = $this->y($y1) - $h; 
  542.  
  543. $this->_pdf->rect($x1, $y1, $w, $h); 
  544. $this->_pdf->stroke(); 
  545.  
  546. //........................................................................ 
  547.  
  548. function filled_rectangle($x1, $y1, $w, $h, $color) { 
  549. $this->_set_fill_color($color); 
  550.  
  551. $y1 = $this->y($y1) - $h; 
  552.  
  553. $this->_pdf->rect(floatval($x1), floatval($y1), floatval($w), floatval($h)); 
  554. $this->_pdf->fill(); 
  555.  
  556. function clipping_rectangle($x1, $y1, $w, $h) { 
  557. $this->_pdf->save(); 
  558.  
  559. $y1 = $this->y($y1) - $h; 
  560.  
  561. $this->_pdf->rect(floatval($x1), floatval($y1), floatval($w), floatval($h)); 
  562. $this->_pdf->clip(); 
  563.  
  564. function clipping_roundrectangle($x1, $y1, $w, $h, $rTL, $rTR, $rBR, $rBL) { 
  565. // @todo 
  566. $this->clipping_rectangle($x1, $y1, $w, $h); 
  567.  
  568. function clipping_end() { 
  569. $this->_pdf->restore(); 
  570.  
  571. function save() { 
  572. $this->_pdf->save(); 
  573.  
  574. function restore() { 
  575. $this->_pdf->restore(); 
  576.  
  577. function rotate($angle, $x, $y) { 
  578. $pdf = $this->_pdf; 
  579. $pdf->translate($x, $this->_height-$y); 
  580. $pdf->rotate(-$angle); 
  581. $pdf->translate(-$x, -$this->_height+$y); 
  582.  
  583. function skew($angle_x, $angle_y, $x, $y) { 
  584. $pdf = $this->_pdf; 
  585. $pdf->translate($x, $this->_height-$y); 
  586. $pdf->skew($angle_y, $angle_x); // Needs to be inverted 
  587. $pdf->translate(-$x, -$this->_height+$y); 
  588.  
  589. function scale($s_x, $s_y, $x, $y) { 
  590. $pdf = $this->_pdf; 
  591. $pdf->translate($x, $this->_height-$y); 
  592. $pdf->scale($s_x, $s_y); 
  593. $pdf->translate(-$x, -$this->_height+$y); 
  594.  
  595. function translate($t_x, $t_y) { 
  596. $this->_pdf->translate($t_x, -$t_y); 
  597.  
  598. function transform($a, $b, $c, $d, $e, $f) { 
  599. $this->_pdf->concat($a, $b, $c, $d, $e, $f); 
  600.  
  601. //........................................................................ 
  602.  
  603. function polygon($points, $color, $width = null, $style = null, $fill = false) { 
  604.  
  605. $this->_set_fill_color($color); 
  606. $this->_set_stroke_color($color); 
  607.  
  608. if ( !$fill && isset($width) ) 
  609. $this->_set_line_style($width, "square", "miter", $style); 
  610.  
  611. $y = $this->y(array_pop($points)); 
  612. $x = array_pop($points); 
  613. $this->_pdf->moveto($x, $y); 
  614.  
  615. while (count($points) > 1) { 
  616. $y = $this->y(array_pop($points)); 
  617. $x = array_pop($points); 
  618. $this->_pdf->lineto($x, $y); 
  619.  
  620. if ( $fill ) 
  621. $this->_pdf->fill(); 
  622. else 
  623. $this->_pdf->closepath_stroke(); 
  624.  
  625. //........................................................................ 
  626.  
  627. function circle($x, $y, $r, $color, $width = null, $style = null, $fill = false) { 
  628.  
  629. $this->_set_fill_color($color); 
  630. $this->_set_stroke_color($color); 
  631.  
  632. if ( !$fill && isset($width) ) 
  633. $this->_set_line_style($width, "round", "round", $style); 
  634.  
  635. $y = $this->y($y); 
  636.  
  637. $this->_pdf->circle($x, $y, $r); 
  638.  
  639. if ( $fill ) 
  640. $this->_pdf->fill(); 
  641. else 
  642. $this->_pdf->stroke(); 
  643.  
  644.  
  645. //........................................................................ 
  646.  
  647. function image($img_url, $x, $y, $w, $h, $resolution = "normal") { 
  648. $w = (int)$w; 
  649. $h = (int)$h; 
  650.  
  651. $img_type = Image_Cache::detect_type($img_url); 
  652. $img_ext = Image_Cache::type_to_ext($img_type); 
  653.  
  654. if ( !isset($this->_imgs[$img_url]) ) { 
  655. $this->_imgs[$img_url] = $this->_pdf->load_image($img_ext, $img_url, ""); 
  656.  
  657. $img = $this->_imgs[$img_url]; 
  658.  
  659. $y = $this->y($y) - $h; 
  660. $this->_pdf->fit_image($img, $x, $y, 'boxsize={'."$w $h".'} fitmethod=entire'); 
  661.  
  662. //........................................................................ 
  663.  
  664. function text($x, $y, $text, $font, $size, $color = array(0, 0, 0), $word_spacing = 0, $char_spacing = 0, $angle = 0) { 
  665. $fh = $this->_load_font($font); 
  666.  
  667. $this->_pdf->setfont($fh, $size); 
  668. $this->_set_fill_color($color); 
  669.  
  670. $y = $this->y($y) - Font_Metrics::get_font_height($font, $size); 
  671.  
  672. $word_spacing = (float)$word_spacing; 
  673. $char_spacing = (float)$char_spacing; 
  674. $angle = -(float)$angle; 
  675.  
  676. $this->_pdf->fit_textline($text, $x, $y, "rotate=$angle wordspacing=$word_spacing charspacing=$char_spacing "); 
  677.  
  678.  
  679. //........................................................................ 
  680.  
  681. function javascript($code) { 
  682. if ( defined("DOMPDF_PDFLIB_LICENSE") ) { 
  683. $this->_pdf->create_action("JavaScript", $code); 
  684.  
  685. //........................................................................ 
  686.  
  687. /** 
  688. * Add a named destination (similar to <a name="foo">...</a> in html) 
  689. * @param string $anchorname The name of the named destination 
  690. */ 
  691. function add_named_dest($anchorname) { 
  692. $this->_pdf->add_nameddest($anchorname, ""); 
  693.  
  694. //........................................................................ 
  695.  
  696. /** 
  697. * Add a link to the pdf 
  698. * @param string $url The url to link to 
  699. * @param float $x The x position of the link 
  700. * @param float $y The y position of the link 
  701. * @param float $width The width of the link 
  702. * @param float $height The height of the link 
  703. */ 
  704. function add_link($url, $x, $y, $width, $height) { 
  705.  
  706. $y = $this->y($y) - $height; 
  707. if ( strpos($url, '#') === 0 ) { 
  708. // Local link 
  709. $name = substr($url, 1); 
  710. if ( $name ) 
  711. $this->_pdf->create_annotation($x, $y, $x + $width, $y + $height, 'Link', "contents={$url} destname=". substr($url, 1) . " linewidth=0"); 
  712. } else { 
  713.  
  714. list($proto, $host, $path, $file) = explode_url($url); 
  715.  
  716. if ( $proto == "" || $proto === "file://" ) 
  717. return; // Local links are not allowed 
  718. $url = build_url($proto, $host, $path, $file); 
  719. $url = '{' . rawurldecode($url) . '}'; 
  720.  
  721. $action = $this->_pdf->create_action("URI", "url=" . $url); 
  722. $this->_pdf->create_annotation($x, $y, $x + $width, $y + $height, 'Link', "contents={$url} action={activate=$action} linewidth=0"); 
  723.  
  724. //........................................................................ 
  725.  
  726. function get_text_width($text, $font, $size, $word_spacing = 0, $letter_spacing = 0) { 
  727. $fh = $this->_load_font($font); 
  728.  
  729. // Determine the additional width due to extra spacing 
  730. $num_spaces = mb_substr_count($text, " "); 
  731. $delta = $word_spacing * $num_spaces; 
  732.  
  733. if ( $letter_spacing ) { 
  734. $num_chars = mb_strlen($text); 
  735. $delta += ($num_chars - $num_spaces) * $letter_spacing; 
  736.  
  737. return $this->_pdf->stringwidth($text, $fh, $size) + $delta; 
  738.  
  739. //........................................................................ 
  740.  
  741. function get_font_height($font, $size) { 
  742.  
  743. $fh = $this->_load_font($font); 
  744.  
  745. $this->_pdf->setfont($fh, $size); 
  746.  
  747. $asc = $this->_pdf->get_value("ascender", $fh); 
  748. $desc = $this->_pdf->get_value("descender", $fh); 
  749.  
  750. // $desc is usually < 0,  
  751. $ratio = $this->_dompdf->get_option("font_height_ratio"); 
  752. return $size * ($asc - $desc) * $ratio; 
  753.  
  754. function get_font_baseline($font, $size) { 
  755. $ratio = $this->_dompdf->get_option("font_height_ratio"); 
  756. return $this->get_font_height($font, $size) / $ratio * 1.1; 
  757.  
  758. //........................................................................ 
  759.  
  760. /** 
  761. * Writes text at the specified x and y coordinates on every page 
  762. * The strings '{PAGE_NUM}' and '{PAGE_COUNT}' are automatically replaced 
  763. * with their current values. 
  764. * See {@link Style::munge_color()} for the format of the color array. 
  765. * @param float $x 
  766. * @param float $y 
  767. * @param string $text the text to write 
  768. * @param string $font the font file to use 
  769. * @param float $size the font size, in points 
  770. * @param array $color 
  771. * @param float $word_space word spacing adjustment 
  772. * @param float $char_space char spacing adjustment 
  773. * @param float $angle angle to write the text at, measured CW starting from the x-axis 
  774. */ 
  775. function page_text($x, $y, $text, $font, $size, $color = array(0, 0, 0), $word_space = 0.0, $char_space = 0.0, $angle = 0.0) { 
  776. $_t = "text"; 
  777. $this->_page_text[] = compact("_t", "x", "y", "text", "font", "size", "color", "word_space", "char_space", "angle"); 
  778.  
  779. //........................................................................ 
  780.  
  781. /** 
  782. * Processes a script on every page 
  783. * The variables $pdf, $PAGE_NUM, and $PAGE_COUNT are available. 
  784. * This function can be used to add page numbers to all pages 
  785. * after the first one, for example. 
  786. * @param string $code the script code 
  787. * @param string $type the language type for script 
  788. */ 
  789. function page_script($code, $type = "text/php") { 
  790. $_t = "script"; 
  791. $this->_page_text[] = compact("_t", "code", "type"); 
  792.  
  793. //........................................................................ 
  794.  
  795. function new_page() { 
  796.  
  797. // Add objects to the current page 
  798. $this->_place_objects(); 
  799.  
  800. $this->_pdf->suspend_page(""); 
  801. $this->_pdf->begin_page_ext($this->_width, $this->_height, ""); 
  802. $this->_page_number = ++$this->_page_count; 
  803.  
  804.  
  805. //........................................................................ 
  806.  
  807. /** 
  808. * Add text to each page after rendering is complete 
  809. */ 
  810. protected function _add_page_text() { 
  811.  
  812. if ( !count($this->_page_text) ) 
  813. return; 
  814.  
  815. $this->_pdf->suspend_page(""); 
  816.  
  817. for ($p = 1; $p <= $this->_page_count; $p++) { 
  818. $this->_pdf->resume_page("pagenumber=$p"); 
  819.  
  820. foreach ($this->_page_text as $pt) { 
  821. extract($pt); 
  822.  
  823. switch ($_t) { 
  824.  
  825. case "text": 
  826. $text = str_replace(array("{PAGE_NUM}", "{PAGE_COUNT}"),  
  827. array($p, $this->_page_count), $text); 
  828. $this->text($x, $y, $text, $font, $size, $color, $word_space, $char_space, $angle); 
  829. break; 
  830.  
  831. case "script": 
  832. if (!$eval) { 
  833. $eval = new PHP_Evaluator($this); 
  834. $eval->evaluate($code, array('PAGE_NUM' => $p, 'PAGE_COUNT' => $this->_page_count)); 
  835. break; 
  836.  
  837. $this->_pdf->suspend_page(""); 
  838.  
  839. $this->_pdf->resume_page("pagenumber=".$this->_page_number); 
  840.  
  841. //........................................................................ 
  842.  
  843. function stream($filename, $options = null) { 
  844.  
  845. // Add page text 
  846. $this->_add_page_text(); 
  847.  
  848. if ( isset($options["compress"]) && $options["compress"] != 1 ) 
  849. $this->_pdf->set_value("compress", 0); 
  850. else 
  851. $this->_pdf->set_value("compress", 6); 
  852.  
  853. $this->_close(); 
  854.  
  855. $data = ""; 
  856.  
  857. if ( self::$IN_MEMORY ) { 
  858. $data = $this->_pdf->get_buffer(); 
  859. //$size = strlen($data); 
  860. } else { 
  861. //$size = filesize($this->_file); 
  862.  
  863.  
  864. $filename = str_replace(array("\n", "'"), "", $filename); 
  865. $attach = (isset($options["Attachment"]) && $options["Attachment"]) ? "attachment" : "inline"; 
  866.  
  867. header("Cache-Control: private"); 
  868. header("Content-type: application/pdf"); 
  869. header("Content-Disposition: $attach; filename=\"$filename\""); 
  870.  
  871. //header("Content-length: " . $size); 
  872.  
  873. if ( self::$IN_MEMORY ) 
  874. echo $data; 
  875.  
  876. else { 
  877.  
  878. // Chunked readfile() 
  879. $chunk = (1 << 21); // 2 MB 
  880. $fh = fopen($this->_file, "rb"); 
  881. if ( !$fh ) 
  882. throw new DOMPDF_Exception("Unable to load temporary PDF file: " . $this->_file); 
  883.  
  884. while ( !feof($fh) ) 
  885. echo fread($fh, $chunk); 
  886. fclose($fh); 
  887.  
  888. //debugpng 
  889. if (DEBUGPNG) print '[pdflib stream unlink '.$this->_file.']'; 
  890. if (!DEBUGKEEPTEMP) 
  891.  
  892. unlink($this->_file); 
  893. $this->_file = null; 
  894. unset($this->_file); 
  895.  
  896. flush(); 
  897.  
  898. //........................................................................ 
  899.  
  900. function output($options = null) { 
  901.  
  902. // Add page text 
  903. $this->_add_page_text(); 
  904.  
  905. if ( isset($options["compress"]) && $options["compress"] != 1 ) 
  906. $this->_pdf->set_value("compress", 0); 
  907. else 
  908. $this->_pdf->set_value("compress", 6); 
  909.  
  910. $this->_close(); 
  911.  
  912. if ( self::$IN_MEMORY ) 
  913. $data = $this->_pdf->get_buffer(); 
  914.  
  915. else { 
  916. $data = file_get_contents($this->_file); 
  917.  
  918. //debugpng 
  919. if (DEBUGPNG) print '[pdflib output unlink '.$this->_file.']'; 
  920. if (!DEBUGKEEPTEMP) 
  921.  
  922. unlink($this->_file); 
  923. $this->_file = null; 
  924. unset($this->_file); 
  925.  
  926. return $data;