Source for file main.php

Documentation is available at main.php

  1. <?php
  2.  
  3. class de_linkm_fontrenderer {
  4.  
  5. var $_font;
  6. var $bbox_left;
  7. var $bbox_above;
  8. var $bbox_below;
  9. var $fontsize;
  10. var $lineheight;
  11. var $left_indent;
  12. var $first_indent;
  13. var $_max_width;
  14. var $_text;
  15. var $_lines;
  16. var $linecount;
  17. var $_hard_warp;
  18. var $bbox;
  19. var $_render_code;
  20. var $_cache_dir;
  21. var $_cache_prefix;
  22. var $_serial;
  23. function de_linkm_fontrenderer ($config = null) {
  24. debug_push("fontrenderer::constructor");
  25. if (is_null($config) ) {
  26. debug_add("Default Constructor is not allowed. Aborting", MIDCOM_LOG_ERROR);
  27. debug_pop();
  28. $this = false;
  29. return false;
  30. }
  31. $this->_font = imagepsloadfont ($config["font-file"]);
  32. if ($this->_font === false) {
  33. debug_add("Could not load font. Aborting", MIDCOM_LOG_ERROR);
  34. debug_pop();
  35. $this = false;
  36. return false;
  37. }
  38. if (! is_null($config["encoding-file"]))
  39. imagepsencodefont ($this->_font, $config["encoding-file"]);
  40. $this->fontsize = intval($config["font-size"]);
  41. // Transform the font metrics to real pixel values
  42. $this->bbox_left = intval(round($config["bbox-left"] * $this->fontsize / 1000));
  43. $this->bbox_above = intval(round($config["bbox-above"] * $this->fontsize / 1000));
  44. $this->bbox_below = intval(round($config["bbox-below"] * $this->fontsize / 1000));
  45. $this->lineheight = abs($this->bbox_above) + abs($this->bbox_below);
  46. $this->first_indent = intval($config["first-indent"]);
  47. $this->left_indent = intval($config["left-indent"]);
  48. $this->_max_width = intval($config["max-width"]);
  49. $this->_hard_wrap = $config["hard-wrap"];
  50. if (! mgd_snippet_exists ("/sitegroup-config/de.linkm.fontrenderer/" . $config["render-code"])) {
  51. debug_add("Render Code Snippet \"/sitegroup-config/de.linkm.fontrenderer/{$config['render-code']}\" "
  52. . "does not exists. Aborting",
  53. MIDCOM_LOG_ERROR);
  54. debug_pop();
  55. $this = false;
  56. return false;
  57. }
  58. $tmp = mgd_get_snippet_by_path("/sitegroup-config/de.linkm.fontrenderer/" . $config["render-code"]);
  59. $this->_render_code = $tmp->code;
  60. debug_print_r("Render Code loaded:", $this->_render_code, MIDCOM_LOG_DEBUG);
  61. if (! array_key_exists("cache-dir", $config)) {
  62. debug_add("Setting Cache to default", MIDCOM_LOG_DEBUG);
  63. $this->_cache_dir = $_SERVER["DOCUMENT_ROOT"] . "/de.linkm.fontrenderer/" . $config["render-code"] . "/";
  64. $this->_cache_prefix = "/de.linkm.fontrenderer/" . $config["render-code"] . "/";
  65. } else if (array_key_exist("cache-prefix", $config)) {
  66. debug_add("Custom Cache Init", MIDCOM_LOG_DEBUG);
  67. $this->_cache_dir = $config["cache-dir"];
  68. if (substr($this->_cache_dir,-1) != "/")
  69. $this->_cache_dir .= "/";
  70. $this->_cache_prefix = $config["cache-prefix"];
  71. if (substr($this->_cache_prefix,-1) != "/")
  72. $this->_cache_prefix .= "/";
  73. } else {
  74. debug_add("A cache-dir directive without a cache-prefix directive was present. This is illegal, aborting.", MIDCOM_LOG_ERROR);
  75. debug_pop();
  76. $this = false;
  77. return false;
  78. }
  79. debug_add("Executing: " . 'mkdir -p ' . escapeshellarg($this->_cache_dir), MIDCOM_LOG_DEBUG);
  80. exec('mkdir -p ' . escapeshellarg($this->_cache_dir));
  81. $this->_serial = strtotime($config["serial"]);
  82. if ($this->_serial == -1) {
  83. debug_add("Could not parse Serial, aborting.", MIDCOM_LOG_ERROR);
  84. debug_pop();
  85. $this = false;
  86. return false;
  87. }
  88. $this->_text = null;
  89. $this->_lines = null;
  90. $this->bbox = null;
  91. debug_pop();
  92. }
  93. function _set_text ($text) {
  94. debug_push("fontrenderer::set_text");
  95. $this->_lines = Array();
  96. $this->bbox = null;
  97. $this->_text = trim($text);
  98. debug_add("We have to render \"" . $this->_text . "\"", MIDCOM_LOG_DEBUG);
  99. // Here we should wrap the text using the given rules
  100. // and return a bounding box in like imagepsbbox does.
  101. // Internally we store something like this:
  102. // x/y delta coordinate for each line where the text rendering starts
  103. // the string to paint there
  104. // other data like its width and the original boundingbox
  105. $remaining = $text;
  106. $line = 0;
  107. while ($remaining != "") {
  108. debug_add("We are now looking at line $line", MIDCOM_LOG_DEBUG);
  109. $available = $this->_max_width - $this->left_indent;
  110. if ($line == 0)
  111. $available -= $this->first_indent;
  112. debug_add("Available space = $available", MIDCOM_LOG_DEBUG);
  113. $current = $remaining;
  114. $newremaining = "";
  115. $linecomplete = false;
  116. do {
  117. // Calculate width of the string, note that the "+2" is due to possible
  118. // off-by-one values of imagepsbbox.
  119. $box = imagepsbbox($current, $this->_font, $this->fontsize, 0,0,0);
  120. $width = $box[2] - $box[0] + 2;
  121. debug_add("The remaining string would be $width pixels long", MIDCOM_LOG_DEBUG);
  122. if ($width < $available) {
  123. debug_add("Which means that it fits into the available width", MIDCOM_LOG_DEBUG);
  124. $this->_lines[$line]["string"] = $current;
  125. $this->_lines[$line]["dx"] = $this->left_indent;
  126. $this->_lines[$line]["dy"] = $line * $this->lineheight;
  127. $this->_lines[$line]["bbox"] = $box;
  128. $this->_lines[$line]["width"] = $width;
  129. if ($line == 0)
  130. $this->_lines[$line]["dx"] += $this->first_indent;
  131. $remaining = trim($newremaining);
  132. $line++;
  133. $linecomplete = true;
  134. } else {
  135. debug_add("Which is too wide, so we'll have to compute a possible linebreak.", MIDCOM_LOG_DEBUG);
  136. $space = strrpos ($current, " ");
  137. $minus = strrpos ($current, "-");
  138. debug_add("RAW indexes: space = $space -- minus = $minus", MIDCOM_LOG_DEBUG);
  139. // Ignore Matches to the last character of the string!
  140. // The following logic will move one character to the left so
  141. // setting it to false should be safe.
  142. if ($space == (strlen($current) - 1))
  143. $space = false;
  144. if ($minus == (strlen($current) - 1))
  145. $minus = false;
  146. debug_add("cleaned indexes: space = $space -- minus = $minus", MIDCOM_LOG_DEBUG);
  147. if ($space === false and $minus === false) {
  148. if (! $this->_hard_wrap) {
  149. debug_add("Hard Word Wrapping has been disabled and we didn't find any space or minus. Aborting!", MIDCOM_LOG_ERROR);
  150. debug_pop();
  151. return null;
  152. }
  153. $break = strlen($current) - 2; // Found no space or minus, so we do chop of a single char.
  154. } elseif ($minus === false)
  155. $break = $space-1; // We found a space at $space but no minus
  156. elseif ($space === false)
  157. $break = $minus; // We found a minus at $minus but no space
  158. else if ($space > $minus)
  159. $break = $space-1; // There was a space at $space and a minus at $minus, decided for $break
  160. else
  161. $break = $minus; // There was a space at $space and a minus at $minus, decided for $break
  162. // Now $break should point to the last character that is part of
  163. // the current line, everything behind it is the new line.
  164. // So we build these strings
  165. $newremaining = substr($current, $break+1) . $newremaining;
  166. $current = substr($current, 0, $break+1);
  167. // current string we test is now $current, new remaining string stored is $newremaining
  168. } // if - else (width > available)
  169. } while (! $linecomplete);
  170. } // while remaining != ""
  171. // Now we make a litte sanity check:
  172. if (count($this->_lines) == 0) {
  173. debug_add("this->_lines does not contain any elements, there is something really wrong.", MIDCOM_LOG_ERROR);
  174. debug_pop();
  175. return null;
  176. }
  177. ksort($this->_lines, SORT_NUMERIC);
  178. $this->linecount = count($this->_lines);
  179. debug_print_r("We ended up with these " . $this->linecount . " lines:",$this->_lines, MIDCOM_LOG_DEBUG);
  180. // The last step we have to do is to compute the real bounding box around
  181. // the (hypothetical) text base location. This will take any indents into
  182. // account. Note, that the base location is to the _left_ side of all
  183. // indents, i.e. they are included in the bounding box.
  184. //
  185. // We start with the extent of the text out to the left of the starting point
  186. // This value is taken out of all included bounding boxes, so that the real
  187. // string size is taken into account here (including indents)
  188. //
  189. // We do the same thing for the right side
  190. $x1_corr = min($this->left_indent, 0);
  191. $x1 = $this->_lines[0]["bbox"][0] + min(($this->first_indent + $this->left_indent), 0);
  192. $x2 = $this->_lines[0]["bbox"][2] + $this->_lines[0]["dx"];
  193. debug_add("Scanning for bounding box, x1_corr = $x1_corr, initial x1, x2 = $x1, $x2", MIDCOM_LOG_DEBUG);
  194. foreach ($this->_lines as $line => $data) {
  195. if ($line == 0)
  196. continue;
  197. if (($data["bbox"][0] + $x1_corr) < $x1)
  198. $x1 = $data["bbox"][0] + $x1_corr;
  199. if (($data["bbox"][2] + $data["dx"]) > $x2)
  200. $x2 = $data["bbox"][2] + $data["dx"];
  201. }
  202. // The lower and upper boundaries are easier:
  203. $lastline = $this->_lines[count($this->_lines)-1];
  204. $y1 = (-1 * $lastline["dy"]) + $lastline["bbox"][1];
  205. $y2 = $this->_lines[0]["bbox"][3];
  206. $this->bbox = Array($x1,$y1,$x2,$y2);
  207. debug_add("Now we are finished: x1/y1 = $x1/$y1, x2/$y2 = $x2/$y2", MIDCOM_LOG_DEBUG);
  208. debug_pop();
  209. return $this->bbox;
  210. }
  211. function draw_text ($image, $x, $y, $col_fg, $col_bg) {
  212. foreach ($this->_lines as $line => $data)
  213. imagepstext($image, $data["string"], $this->_font, $this->fontsize, $col_fg, $col_bg, intval($x+$data["dx"]), intval($y+$data["dy"]), 0, 0, 0, 16);
  214. }
  215. function _create_image () {
  216. debug_push("fontrenderer::_create_image");
  217. $image = null;
  218. debug_push("fontrenderer::_create_image::RENDER_CODE");
  219. eval($this->_render_code);
  220. debug_pop();
  221. if (is_null($image)) {
  222. debug_add("The Render-Code did not populate $image. Aborting!", MIDCOM_LOG_ERROR);
  223. debug_pop();
  224. return false;
  225. }
  226. $filename = $this->_cache_dir . md5($this->_text) . ".png";
  227. debug_add("Filename: $filename");
  228. if (file_exists($filename))
  229. if (!unlink($filename)) {
  230. debug_add("This file does already exist and we could not delete it. Aborting", MIDCOM_LOG_ERROR);
  231. debug_pop();
  232. return false;
  233. }
  234. debug_add("Writing image", MIDCOM_LOG_DEBUG);
  235. imagepng ($image, $filename);
  236. if (!file_exists($filename)) {
  237. debug_add("Something (look for PHP messages) went wrong when writing the image. Aborting", MIDCOM_LOG_ERROR);
  238. debug_pop();
  239. return false;
  240. }
  241. debug_pop();
  242. return true;
  243. }
  244. function get_image ($string) {
  245. debug_push("fontrenderer::get_image");
  246. $file = md5(trim($string)) . ".png";
  247. $filename = $this->_cache_dir . $file;
  248. debug_add("We should retrieve an image for the string \"" . trim($string) . "\" whose filename should be \"$filename\"", MIDCOM_LOG_INFO);
  249. $generate = false;
  250. if (!file_exists($filename)) {
  251. $generate = true;
  252. debug_add("This file was not found.", MIDCOM_LOG_DEBUG);
  253. } else {
  254. $stat = stat($filename);
  255. if ($stat[10] < $this->_serial) {
  256. $generate = true;
  257. debug_print_r("This file seems too old, here are its stats, serial is " . $this->_serial . ":", $stat, MIDCOM_LOG_DEBUG);
  258. }
  259. }
  260. if ($generate) {
  261. if (is_null($this->_set_text($string))) {
  262. debug_add("Could not format the text.", MIDCOM_LOG_ERROR);
  263. debug_pop();
  264. return false;
  265. }
  266. if (!$this->_create_image()) {
  267. debug_add("Could not create image.", MIDCOM_LOG_ERROR);
  268. debug_pop();
  269. return false;
  270. }
  271. debug_add("File created successfully", MIDCOM_LOG_INFO);
  272. }
  273. $info = getimagesize($filename);
  274. if ($info === false || $info[2] != 3) {
  275. debug_add("This does not look like an PNG Image, getimagesize returned this:", $info, MIDCOM_LOG_ERROR);
  276. debug_pop();
  277. return false;
  278. }
  279. $result = Array();
  280. $result["url"] = $this->_cache_prefix . $file;
  281. $result["size_x"] = $info[0];
  282. $result["size_y"] = $info[1];
  283. $result["size_line"] = $info[3];
  284. debug_print_r("Cache Hit. Returning this:", $result, MIDCOM_LOG_DEBUG);
  285. debug_pop();
  286. return $result;
  287. }
  288. }
  289.  
  290.  
  291. ?>

Documentation generated on Mon, 21 Nov 2005 18:18:12 +0100 by phpDocumentor 1.3.0RC3