| Salathe |
01-07-2008 02:15 PM |
Here's my code submission, it's rather long (217 lines) but could've been much, much longer!
It's a messy mixture of a collection of design patterns (badly implemented, this isn't a clean code contest) making a mess of an OOP approach. You get brownie points if you can recognise the patterns being used, hehe. The end result is a rendering of "Hello World" on the screen, as displayed in the screenshot below proving that, even with uggglllyyy code, beautiful results can be achieved... if you like red text. :-P
Click for 100% scale version
The Code
To run this, you'll need 'Georgia.ttf' else a whole slew of errors will be thrown in your face.
PHP Code:
<?phpinterface Outputtable { public function generate (); public function output (); }abstract class HelloWorld { protected $phrase = 'Hello World'; }class HelloXml extends HelloWorld implements Outputtable { private $root = 'phrase'; public function generate () { $output = '<?xml version="1.0" encoding="utf-8"?>'; $output .= "\n"; $output .= sprintf('<%1$s>%2$s</%1$s>', $this-> root, $this-> phrase); return $output; } public function output () { header('Content-Type: application/xml; charset=utf-8'); echo $this-> generate(); }}class TextImage implements Outputtable { public $img; public $text; protected $palette; const FONT_FILE = 'Georgia.ttf'; const FONT_SIZE = 20; const FONT_ANGLE = 4; public function __construct($text) { $this-> text = $text; $this-> generate(); } public function resource () { return $this-> img; } public function generate () { $bbox = (object ) array_combine (array('llx', 'lly', 'lrx', 'lry', 'urx', 'ury', 'ulx', 'uly'), imagettfbbox (self:: FONT_SIZE, self:: FONT_ANGLE, TextImage:: FONT_FILE, $this-> text)); $width = abs(max($bbox-> lrx, $bbox-> urx) - min($bbox-> llx, $bbox-> ulx)); $height = abs(max($bbox-> lry, $bbox-> lly) - min($bbox-> ury, $bbox-> uly)); $left = min($bbox-> llx, $bbox-> lrx); $bottom = min($bbox-> lly, $bbox-> lry); $this-> img = imagecreatetruecolor ($width, $height); $this-> generate_palette(); imagefill ($this-> img, 0, 0, $this-> palette[ 'white'] ); imagettftext ($this-> img, self:: FONT_SIZE, self:: FONT_ANGLE, max(0, abs($bbox-> ulx)), self:: FONT_ANGLE < 0 ? abs($bbox-> lly - $bbox-> uly) : abs($bbox-> lly - $bbox-> ury), $this-> palette[ 'red'], self:: FONT_FILE, $this-> text); } public function output () { header('Content-Type: image/png'); imagepng ($this-> img); imagedestroy ($this-> img); } private function generate_palette () { $this-> palette = array( 'white' => imagecolorallocate ($this-> img, 255, 255, 255), 'black' => imagecolorallocate ($this-> img, 0, 0, 0 ), 'red' => imagecolorallocate ($this-> img, 255, 0, 0 ) ); }}class Image2Text implements Outputtable { private $img; private $text = 'hello'; public function __construct(TextImage $img, $text = 'text', $elem = 'span') { $this-> img = $img; $this-> elem = $elem; $this-> text = $text; } public function generate () { $img = $this-> img-> img; $width = imagesx ($img); $height = imagesy ($img); $counter = 0; $output = ''; for ($y = 0; $y < $height; $y++ ) { for ($x = 0; $x < $width; $x++ ) { $counter %= strlen($this-> text); $colour = imagecolorat ($img, $x, $y); $rgb = imagecolorsforindex ($img, $colour); $hex = self:: rgb2hex(array($rgb[ 'red'], $rgb[ 'green'], $rgb[ 'blue'] )); $output .= sprintf('<%s style="color: #%s;">%s</%s>', $this-> elem, $hex, $this-> text[ $counter], $this-> elem); $counter++; } $output .= '<br />'; } return $output; } public function output () { header('Content-Type: text/html; charset=utf-8'); echo $this-> generate(); } public static function rgb2hex ($rgb) { $rgb = array_slice(array_pad($rgb, 3, 0), 0, 3); $hex = array(); foreach ($rgb as $dec) { $hex[] = str_pad(dechex($dec), 2, '0', STR_PAD_RIGHT ); } return implode($hex); }}class HelloImage implements Outputtable { protected $source; public function __construct(HelloXml $source) { $this-> source = $source; } public function generate () { $xml_raw = $this-> source-> generate(); $xml = new SimpleXMLElement ($xml_raw); $phrase = (string ) $xml; $img = new TextImage ($phrase); $text = new Image2Text ($img, preg_replace('/[^a-zA-Z]+/', '', $phrase), 'span'); echo '<style type="text/css">body {font:normal 8px/1.0 courier, monospace;}</style>'; echo $text-> generate(); exit; return $phrase; } public function output () { //header('Content-Type: image/png'); echo $this-> generate(); }}class HelloContest extends HelloWorld implements Outputtable { protected $renderer; public function __construct() { $this-> renderer = new HelloImage (new HelloXml ); } public function generate () { } public function output () { $this-> renderer-> output(); }}// Singleton patternclass Hello { private static $instance = false; private function __construct() { } private function __clone() { } // Factory pattern public static function instance ($key) { if (self:: $instance === false and $key == 'contest') { return new HelloContest; } return self:: $instance; }}$hello = Hello:: instance('contest'); $hello-> output();
Now, to get the dirty, dirty code off I'm going to scrub myself raw with lashings of soapy water. Unclean! Unclean! :-P
|