PageRenderTime 26ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Renderer/ListBullet.php

https://gitlab.com/oritadeu/dompdf
PHP | 248 lines | 174 code | 44 blank | 30 comment | 15 complexity | eab506429f37bd9ca4bac5305b9339b0 MD5 | raw file
  1. <?php
  2. /**
  3. * @package dompdf
  4. * @link http://dompdf.github.com/
  5. * @author Benj Carson <benjcarson@digitaljunkies.ca>
  6. * @author Helmut Tischer <htischer@weihenstephan.org>
  7. * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  8. */
  9. namespace Dompdf\Renderer;
  10. use Dompdf\Helpers;
  11. use Dompdf\FontMetrics;
  12. use Dompdf\Frame;
  13. use Dompdf\Image\Cache;
  14. use Dompdf\FrameDecorator\ListBullet as ListBulletFrameDecorator;
  15. /**
  16. * Renders list bullets
  17. *
  18. * @access private
  19. * @package dompdf
  20. */
  21. class ListBullet extends AbstractRenderer
  22. {
  23. static function get_counter_chars($type)
  24. {
  25. static $cache = array();
  26. if (isset($cache[$type])) {
  27. return $cache[$type];
  28. }
  29. $uppercase = false;
  30. $text = "";
  31. switch ($type) {
  32. case "decimal-leading-zero":
  33. case "decimal":
  34. case "1":
  35. return "0123456789";
  36. case "upper-alpha":
  37. case "upper-latin":
  38. case "A":
  39. $uppercase = true;
  40. case "lower-alpha":
  41. case "lower-latin":
  42. case "a":
  43. $text = "abcdefghijklmnopqrstuvwxyz";
  44. break;
  45. case "upper-roman":
  46. case "I":
  47. $uppercase = true;
  48. case "lower-roman":
  49. case "i":
  50. $text = "ivxlcdm";
  51. break;
  52. case "lower-greek":
  53. for ($i = 0; $i < 24; $i++) {
  54. $text .= Helpers::unichr($i + 944);
  55. }
  56. break;
  57. }
  58. if ($uppercase) {
  59. $text = strtoupper($text);
  60. }
  61. return $cache[$type] = "$text.";
  62. }
  63. /**
  64. * @param integer $n
  65. * @param string $type
  66. * @param integer $pad
  67. *
  68. * @return string
  69. */
  70. private function make_counter($n, $type, $pad = null)
  71. {
  72. $n = intval($n);
  73. $text = "";
  74. $uppercase = false;
  75. switch ($type) {
  76. case "decimal-leading-zero":
  77. case "decimal":
  78. case "1":
  79. if ($pad)
  80. $text = str_pad($n, $pad, "0", STR_PAD_LEFT);
  81. else
  82. $text = $n;
  83. break;
  84. case "upper-alpha":
  85. case "upper-latin":
  86. case "A":
  87. $uppercase = true;
  88. case "lower-alpha":
  89. case "lower-latin":
  90. case "a":
  91. $text = chr(($n % 26) + ord('a') - 1);
  92. break;
  93. case "upper-roman":
  94. case "I":
  95. $uppercase = true;
  96. case "lower-roman":
  97. case "i":
  98. $text = Helpers::dec2roman($n);
  99. break;
  100. case "lower-greek":
  101. $text = Helpers::unichr($n + 944);
  102. break;
  103. }
  104. if ($uppercase) {
  105. $text = strtoupper($text);
  106. }
  107. return "$text.";
  108. }
  109. function render(Frame $frame)
  110. {
  111. $style = $frame->get_style();
  112. $font_size = $style->get_font_size();
  113. $line_height = $style->length_in_pt($style->line_height, $frame->get_containing_block("w"));
  114. $this->_set_opacity($frame->get_opacity($style->opacity));
  115. $li = $frame->get_parent();
  116. // Don't render bullets twice if if was split
  117. if ($li->_splitted) {
  118. return;
  119. }
  120. // Handle list-style-image
  121. // If list style image is requested but missing, fall back to predefined types
  122. if ($style->list_style_image !== "none" &&
  123. !Cache::is_broken($img = $frame->get_image_url())
  124. ) {
  125. list($x, $y) = $frame->get_position();
  126. //For expected size and aspect, instead of box size, use image natural size scaled to DPI.
  127. // Resample the bullet image to be consistent with 'auto' sized images
  128. // See also Image::get_min_max_width
  129. // Tested php ver: value measured in px, suffix "px" not in value: rtrim unnecessary.
  130. //$w = $frame->get_width();
  131. //$h = $frame->get_height();
  132. list($width, $height) = Helpers::dompdf_getimagesize($img, $this->_dompdf->getHttpContext());
  133. $dpi = $this->_dompdf->get_option("dpi");
  134. $w = ((float)rtrim($width, "px") * 72) / $dpi;
  135. $h = ((float)rtrim($height, "px") * 72) / $dpi;
  136. $x -= $w;
  137. $y -= ($line_height - $font_size) / 2; //Reverse hinting of list_bullet_positioner
  138. $this->_canvas->image($img, $x, $y, $w, $h);
  139. } else {
  140. $bullet_style = $style->list_style_type;
  141. $fill = false;
  142. switch ($bullet_style) {
  143. default:
  144. case "disc":
  145. $fill = true;
  146. case "circle":
  147. list($x, $y) = $frame->get_position();
  148. $r = ($font_size * (ListBulletFrameDecorator::BULLET_SIZE /*-ListBulletFrameDecorator::BULLET_THICKNESS*/)) / 2;
  149. $x -= $font_size * (ListBulletFrameDecorator::BULLET_SIZE / 2);
  150. $y += ($font_size * (1 - ListBulletFrameDecorator::BULLET_DESCENT)) / 2;
  151. $o = $font_size * ListBulletFrameDecorator::BULLET_THICKNESS;
  152. $this->_canvas->circle($x, $y, $r, $style->color, $o, null, $fill);
  153. break;
  154. case "square":
  155. list($x, $y) = $frame->get_position();
  156. $w = $font_size * ListBulletFrameDecorator::BULLET_SIZE;
  157. $x -= $w;
  158. $y += ($font_size * (1 - ListBulletFrameDecorator::BULLET_DESCENT - ListBulletFrameDecorator::BULLET_SIZE)) / 2;
  159. $this->_canvas->filled_rectangle($x, $y, $w, $w, $style->color);
  160. break;
  161. case "decimal-leading-zero":
  162. case "decimal":
  163. case "lower-alpha":
  164. case "lower-latin":
  165. case "lower-roman":
  166. case "lower-greek":
  167. case "upper-alpha":
  168. case "upper-latin":
  169. case "upper-roman":
  170. case "1": // HTML 4.0 compatibility
  171. case "a":
  172. case "i":
  173. case "A":
  174. case "I":
  175. $pad = null;
  176. if ($bullet_style === "decimal-leading-zero") {
  177. $pad = strlen($li->get_parent()->get_node()->getAttribute("dompdf-children-count"));
  178. }
  179. $node = $frame->get_node();
  180. if (!$node->hasAttribute("dompdf-counter")) {
  181. return;
  182. }
  183. $index = $node->getAttribute("dompdf-counter");
  184. $text = $this->make_counter($index, $bullet_style, $pad);
  185. if (trim($text) == "") {
  186. return;
  187. }
  188. $spacing = 0;
  189. $font_family = $style->font_family;
  190. $line = $li->get_containing_line();
  191. list($x, $y) = array($frame->get_position("x"), $line->y);
  192. $x -= $this->_dompdf->getFontMetrics()->getTextWidth($text, $font_family, $font_size, $spacing);
  193. // Take line-height into account
  194. $line_height = $style->line_height;
  195. $y += ($line_height - $font_size) / 4; // FIXME I thought it should be 2, but 4 gives better results
  196. $this->_canvas->text($x, $y, $text,
  197. $font_family, $font_size,
  198. $style->color, $spacing);
  199. case "none":
  200. break;
  201. }
  202. }
  203. }
  204. }