<?php require('template.hack');
/*
render.hack---makes a raster rendition of a text string.
Chris K. Young <cky@pobox.com>, October 2002.
$Id: render.hack,v 1.6 2006-10-08 11:55:48 cky Exp $

Copyright (c) 2002, 2005, 2006 Chris K. Young.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public Licence as published by
the Free Software Foundation; either version 2 of the Licence, or (at
your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public Licence for more details.

You should have received a copy of the GNU General Public Licence
along with this program; if not, write to Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
*/

class render {
    var 
$_args;

    function 
print_header() {}

    function 
_validate_num(&$var$field$min$max$def 0$opt false) {
        
$val $_POST[$field];
        if (
strlen($val)) {
            if (!
is_numeric($val) || $val $min || $val $max)
                return 
false;
            
$var $val;
            return 
true;
        }
        
$var $def;
        return 
$opt;
    }

    function 
_validate_str(&$var$field$pcre$def ''$opt false) {
        
$val $_POST[$field];
        if (
strlen($val)) {
            if (!
preg_match($pcre$val))
                return 
false;
            
$var $val;
            return 
true;
        }
        
$var $def;
        return 
$opt;
    }

    function 
_validate_col(&$var$field$def ''$opt false) {
        if (!
$this->_validate_str($val$field'/^#[[:xdigit:]]{6}$/',
                                  
$def$opt))
            return 
false;
        
sscanf($val'#%2x%2x%2x'$r$g$b);
        
$var = array($r$g$b);
        return 
true;
    }

    function 
validate_input() {
        if (
$this->_validate_str($face'face'':^[^/]+$:') &&
            
$this->_validate_num($size'size'172) &&       /* arbitrary */
            
$this->_validate_str($text'text''//') &&
            
$this->_validate_num($angle'angle'03600true) &&
            
$this->_validate_num($ls'ls', -10101true) && /* arbitrary */
            
$this->_validate_col($fg'fgcol''#000000'true) &&
            
$this->_validate_col($bg'bgcol''#ffffff'true) &&
            
$this->_validate_num($pad'pad'0640true))  /* arbitrary */
        
{
            
$this->_args = array($face$size$text$angle$ls$fg$bg,
                                 
$pad);
            return 
true;
        }
        return 
false;
    }

    function 
process_input() {
        list(
$face$size$text$angle$ls$fg$bg$pad) = $this->_args;
        
$face "php/$face";

        
$bbox =& imageftbbox($size$angle$face$text,
                             array(
'linespacing' => $ls));
        if (!
$bbox)
            return;
        
$xs = array($bbox[0], $bbox[2], $bbox[4], $bbox[6]);
        
$ys = array($bbox[1], $bbox[3], $bbox[5], $bbox[7]);
        
$maxx max($xs);
        
$minx min($xs);
        
$maxy max($ys);
        
$miny min($ys);

        
$im =& imagecreate($maxx $minx $pad,
                           
$maxy $miny $pad);
        if (!
$im)
            return;
        
imagecolortransparent($im,
            
imagecolorresolve($im$bg[0], $bg[1], $bg[2]));
        
$fgcol imagecolorresolve($im$fg[0], $fg[1], $fg[2]);
        if (isset(
$_POST['frame'])) {
            
imagerectangle($im$pad$pad$maxx $minx $pad,
                           
$maxy $miny $pad$fgcol);
        }
        if (!
imagefttext($im$size$angle$pad $minx$pad $miny,
                         isset(
$_POST['noaa']) ? -$fgcol $fgcol$face,
                         
$text, array('linespacing' => $ls)))
            return;
        
header('Content-Type: image/png');
        
imagepng($im);
    }

    function 
print_form() {
        
$tmpl = new template('The render gimmick');
        
$tmpl->set_rcsid('$Id: render.hack,v 1.6 2006-10-08 11:55:48 cky Exp $');
        
$tmpl->print_header();
?>
<p>The <samp>render</samp> gimmick allows you to look at a text string rendered in a font of your choice by <a href="http://www.freetype.org/">FreeType</a>. An <a href="<?php printf('%s/help'$_SERVER['PHP_SELF']); ?>">explanation</a> of the fields is available.</p>
<form action="<?php print($_SERVER['PHP_SELF']); ?>" method="post">
<p><textarea name="text" rows="4" cols="80" accesskey="t"></textarea></p>
<p><label accesskey="f">Font: <input type="text" name="face" /></label>
<label accesskey="s">Size: <input type="text" name="size" size="4" /></label></p>
<p><label accesskey="a">Angle (degrees): <input type="text" name="angle" size="6" /></label>
<label accesskey="l">Line spacing: <input type="text" name="ls" size="4" /></label></p>
<p><label accesskey="c">Colour (<samp>#rrggbb</samp>): <input type="text" name="fgcol" size="7" /></label>
<label accesskey="b">Background (<samp>#rrggbb</samp>): <input type="text" name="bgcol" size="7" /></label></p>
<p><label accesskey="p">Padding: <input type="text" name="pad" size="4" /></label>
<label accesskey="d">Draw frame: <input type="checkbox" name="frame" value="1" /></label>
<label accesskey="n">No antialiasing: <input type="checkbox" name="noaa" value="1" /></label></p>
<p><input type="submit" value="Render now!" accesskey="r" /></p>
</form>
<?php
        $tmpl
->print_footer();
    }

    function 
print_footer() {}
}

class 
render_help {
    var 
$tmpl;

    function 
render_help() {
        
$this->tmpl = new template('Information on the render gimmick');
        
$this->tmpl->set_rcsid('$Id: render.hack,v 1.6 2006-10-08 11:55:48 cky Exp $');
    }

    function 
print_header() {
        
$this->tmpl->print_header();
    }

    function 
validate_input() {
        return 
false;
    }

    function 
process_input() {
        return;
    }

    function 
print_form() {
?>
<p>Here is a description of all the fields. They all have access keys corresponding to the first letter of the field name (the text field has an access key of <kbd>t</kbd>); you may be able to, for example, press <kbd>Alt-r</kbd> to select the &lsquo;Render now!&rsquo; button.</p>
<p>The text, font, and size fields have no defaults, and thus must be filled in for this program to work.</p>
<dl>
<dt>Font</dt><dd>The name of a TrueType font installed on this webserver. One day, I may write a script that generates a list of the available fonts, but for now, you'll have to live with trial and error.</dd>
<dt>Size</dt><dd>The size at which to render the text. I don't really know what unit this is in, so again, you'll just have to try and see. This field has an arbitrary maximum value of 72.</dd>
<dt>Angle</dt><dd>How many degrees to rotate the text anticlockwise. The default is 0, which renders the text left-to-right.</dd>
<dt>Line spacing</dt><dd>How much spacing is used between lines of text. The default is 1, which specifies single-spacing, and there is an arbitrary limit of -10 to 10.</dd>
<dt>Colour</dt><dd>The foreground colour of the rendered text, using standard <samp>#rrggbb</samp> notation. Defaults to <samp>#000000</samp> (black).</dd>
<dt>Background</dt><dd>The background colour on which to render the text, using standard <samp>#rrggbb</samp> notation. Since the background will be made transparent, this setting is only useful if antialiasing is enabled. Defaults to <samp>#ffffff</samp> (white).</dd>
<dt>Padding</dt><dd>The bounding box generation routine in <a href="http://www.boutell.com/gd/">gd</a> seems to be less than perfect, and some cropping may occur unless padding is added. This allows you to specify how many pixels to add on each side of the bounding box. The default value is 0, and there is an arbitrary maximum of 64.</dd>
<dt>Draw frame</dt><dd>Draws a frame that encloses the bounding box. This allows you to see how good the bounding box calculation is when you use non-zero padding.</dd>
<dt>No antialiasing</dt><dd>Disables antialiasing, which may make the rendering look less smooth.</dd>
</dl>
<?php
    
}

    function 
print_footer() {
        
$this->tmpl->print_footer();
    }
}
?>