Skip to content

Instantly share code, notes, and snippets.

@jaydreyer
Created June 26, 2021 20:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jaydreyer/58eb413beeada300e70cc6660539f2bf to your computer and use it in GitHub Desktop.
Save jaydreyer/58eb413beeada300e70cc6660539f2bf to your computer and use it in GitHub Desktop.
zem_ir image replacement textpattern plugin code
function zem_ir_set($atts) {
global $zem_ir_set;
$group = (empty($atts['group']) ? 'default' : $atts['group']);
$orig = (isset($zem_ir_set[$group]) ? $zem_ir_set[$group] : array());
$zem_ir_set[$group] = array_merge($orig, $atts);
return '';
}
function zem_ir_get_atts($atts) {
global $pfr, $txpcfg, $img_dir;
$group = (empty($atts['group']) ? 'default' : $atts['group']);
$wraptag = (empty($atts["wraptag"]) ? "h1" : $atts["wraptag"]);
$position = (empty($atts["position"]) ? "top left" : $atts["position"]);
$limit = (empty($atts["limit"]) ? 0 : $atts["limit"]);
$class = (empty($atts["class"]) ? "" : $atts["class"]);
$font = (empty($atts["font"]) ? "" : $atts["font"]);
$font_dir = (empty($atts["fontdir"]) ? dirname($txpcfg["doc_root"]) : $atts["fontdir"]);
$font_size = (empty($atts["fontsize"]) ? 24 : (int)$atts["fontsize"]);
$angle = (empty($atts["angle"]) ? 0 : $atts["angle"]);
$color = (empty($atts["color"]) ? "#000000" : $atts["color"]);
$backgroundcolor = (empty($atts["backgroundcolor"]) ? "#ffffff" : $atts["backgroundcolor"]);
$cachedir = (empty($atts["cachedir"]) ? "$img_dir/zir" : $atts["cachedir"]);
$ft = (isset($atts["ft"]) ? $atts["ft"] : 0);
$aa = (isset($atts["aa"]) ? $atts["aa"] : 1);
$info = (isset($atts["info"]) ? $atts["info"] : 0);
$trans = (isset($atts["trans"]) ? $atts["trans"] : 1);
$cache = (isset($atts["cache"]) ? $atts["cache"] : 1);
$depth = (empty($atts["depth"]) ? 8 : $atts["depth"]);
$method = (empty($atts["method"]) ? "phark" : $atts["method"]);
$align = (empty($atts["align"]) ? "left" : $atts["align"]);
$padding = (empty($atts["padding"]) ? "0" : $atts["padding"]);
$text = (empty($atts['text']) ? '' : $atts['text']);
$wrap = (empty($atts['wrap']) ? 0 : $atts['wrap']);
$tr = (empty($atts['tr']) ? '' : $atts['tr']);
$tt = (empty($atts['tt']) ? ' ' : $atts['tt']);
$charset = (empty($atts['charset']) ? 'ISO-8859-15' : $atts['charset']);
$transform = (empty($atts['transform']) ? '' : $atts['transform']);
$pad = preg_split('/\s+/', trim($padding));
if (count($pad) != 4)
$pad = array_fill(0, 4, $pad[0]);
if (substr($font_dir, -1, 1) != DIRECTORY_SEPARATOR) $font_dir .= DIRECTORY_SEPARATOR;
$font_file = $font_dir . $font;
$cache_folder = $txpcfg["doc_root"].$pfr.$cachedir;
return compact('wraptag', 'position', 'limit', 'class', 'font', 'font_dir', 'font_size', 'angle', 'color', 'backgroundcolor', 'cachedir', 'ft', 'aa', 'info', 'trans', 'cache', 'depth', 'method', 'align', 'padding', 'text', 'wrap', 'tr', 'charset', 'transform', 'pad', 'font_file', 'cache_folder');
}
function zem_image_replace($atts, $thing) {
return zem_ir($atts, $thing);
}
function zem_ir($atts, $thing=NULL) {
global $pfr, $zem_ir_set, $txpcfg;
# Merge any settings configured by zem_ir_set with the attributes for this tag
$group = (empty($atts['group']) ? 'default' : $atts['group']);
$defaults = (isset($zem_ir_set[$group]) ? $zem_ir_set[$group] : array());
$settings = zem_ir_get_atts(array_merge($defaults, $atts));
extract($settings);
$content = $text;
if ($thing) {
$content = parse($thing);
$text = trim(html_entity_decode(strip_tags($content), ENT_NOQUOTES, $charset));
if ($limit)
$text = substr($text, 0, $limit);
}
if ($tr) {
$tr = html_entity_decode($tr, ENT_NOQUOTES, $charset);
$tt = substr(html_entity_decode($tt, ENT_NOQUOTES, $charset), 0, 1);
$text = strtr($text, $tr, str_repeat($tt, strlen($tr)));
}
if ($transform == 'capitalize')
$text = ucwords($text);
elseif ($transform == 'lowercase')
$text = strtolower($text);
elseif ($transform == 'uppercase')
$text = strtoupper($text);
if ($info) {
ob_start();
echo "<pre>";
var_dump(compact("text", "font_file", "font_size", "angle", "color", "backgroundcolor", "cache_folder", "aa", "trans", "depth", "ft", "cache", "method", "align", "pad"));
echo "doc_root setting ".$txpcfg['doc_root']." ". ($txpcfg['doc_root'] == $_SERVER['DOCUMENT_ROOT'] ? "does" : "<b>does not</b>"). " match the server setting '".$_SERVER['DOCUMENT_ROOT']."'\n";
echo "cache folder $cache_folder " . (is_dir($cache_folder) ? "is" : "is <b>not</b>") . " a directory\n";
echo "cache folder $cache_folder " . (is_writable($cache_folder) ? "is" : "is <b>not</b>") . " writable\n";
echo "font file $font_file " . (is_file($font_file) ? "is" : "is <b>not</b>") . " a file\n";
echo "font file $font_file " . (is_readable($font_file) ? "is" : "is <b>not</b>") . " readable\n";
echo "freetype 2 " . (is_callable("imagefttext") ? "is" : "is <b>not</b>") . " supported\n";
echo "freetype 1 " . (is_callable("imagettfbbox") ? "is" : "is <b>not</b>") . " supported\n";
echo "</pre>";
return ob_get_clean();
}
// Skip the image routines if there's no text to display
if (!trim($text))
return tag($wraptag, $content);
$old_umask = umask(0000);
$result = dynamic_image($text, $settings);
umask($old_umask);
if ($result[0]) {
return $result[1];
}
list($error, $data, $w, $h) = $result;
$url = $pfr . $cachedir . "/" . $data;
$height = (empty($atts["height"]) ? $h : $atts["height"]);
$width = (empty($atts["width"]) ? $w : $atts["width"]);
$title = " title=\"{$text}\"";
if ($class) {
$style = " style=\"background: url($url) no-repeat {$position};\"";
$class = " class=\"$class\"";
}
elseif ($method == "radu") {
$style = " style=\"margin: 0 0 0 -5000px; background: url($url) no-repeat top right; height: {$height}px;\"";
}
elseif ($method == "lir") {
$style = " style=\"padding: {$height}px 0 0 0; overflow: hidden; background: url($url) no-repeat {$position}; height: 0px !important; height /**/: {$height}px;\"";
}
elseif ($method == "dwyer") {
$style = " style=\"background: url($url) no-repeat {$position}; height: {$height}px; width: {$width}px;\"";
$spanstyle = " style=\"display: block; width: 0; height: 0; overflow: hidden;\"";
$content = tag($content, "span", $spanstyle);
}
elseif ($method == "img") {
$wraptag = "img";
$style = " src=\"{$url}\" alt=\"{$text}\"";
}
else {
// Default: Phark Revisited
$style = " style=\"text-indent: -5000px; background: url($url) no-repeat {$position}; height: {$height}px;\"";
}
return tag($content, $wraptag, $class.$style.$title);
}
# The following code is taken from Stewart Rosenberger's header.php, with modifications to allow text rotation and FT support
# http://www.stewartspeak.com/headings/
function dynamic_image($content, $settings) {
extract($settings);
$text = $content;
$transparent_background = $trans ;
$mime_type = "image/png" ;
$extension = ".png" ;
$send_buffer_size = 4096 ;
// check for GD support
if(!function_exists("ImageCreate"))
return array(1, "Error: Server does not support PHP image generation");
// look for cached copy, send if it exists
$hash = md5(join('-', array(basename($font_file), $font_size , $color , $angle , $aa, $ft , $depth , $backgroundcolor , $trans, $padding , $wrap, $text)));
$cache_filename = $cache_folder . DIRECTORY_SEPARATOR . $hash . $extension ;
if($cache && is_readable($cache_filename))
{
list($w, $h) = getimagesize($cache_filename);
return array(0, $hash.$extension, $w, $h);
}
// check font availability
$font_found = is_readable($font_file) ;
if(!$font_found)
{
return array(1, "Error: The server is missing the specified font '$font_file'.") ;
}
// create cache dir if necessary
if (!is_dir($cache_folder)) {
mkdir($cache_folder, 0777);
if (!is_dir($cache_folder)) {
return array(1, "Error: unable to create cache folder '$cache_folder'.") ;
}
}
if (!is_writable($cache_folder)) {
return array(1, "Error: unable to write to cache folder '$cache_folder'.") ;
}
// create image
$background_rgb = hex_to_rgb($backgroundcolor) ;
$font_rgb = hex_to_rgb($color) ;
if ($ft and is_callable('imageftbbox'))
$boxfn = 'imageftbbox';
else
$boxfn = 'imagettfbbox';
if ($wrap) {
# Word wrapping is measured in characters, not pixels. We have to guess the number of characters
# that will fit in the specified pixel width, then gradually reduce our guess until the text fits.
$wrapstart = max($wrap/4, 80);
for ($i = $wrapstart; $i >= 6; $i--) {
$box = @$boxfn($font_size, 0, $font_file, wordwrap($text, $i, "\n", 1));
$wrap_w = max($box[0], $box[2], $box[4], $box[6]) - min($box[0], $box[2], $box[4], $box[6]);
if ($wrap_w <= $wrap) {
$text = wordwrap($text, $i, "\n", 1);
break;
}
}
}
else {
$box = @$boxfn($font_size,0,$font_file,$text) ;
}
@list($w, $h, $base_x, $base_y) = imagerotatedbbox($box, $angle, $pad);
if (isset($w, $h, $base_x, $base_y)) {
if ($depth == 24 and is_callable("imagecreatetruecolor"))
$image = @ImageCreateTrueColor($w, $h);
else
$image = @ImageCreate($w,$h) ;
}
if(!$image || !$box)
{
return array(1, "Error: The server could not create this heading image.") ;
}
// allocate colors and draw text
$background_color = ImageColorAllocate($image,$background_rgb["red"],
$background_rgb["green"],$background_rgb["blue"]) ;
$font_color = ImageColorAllocate($image,$font_rgb["red"],
$font_rgb["green"],$font_rgb["blue"]) ;
// have to explicitly draw the background color for 24-bit
imageFilledRectangle($image, 0, 0, $w, $h, $background_color);
if ($ft and is_callable("imagefttext")) {
if (!$aa)
$font_color = -$font_color;
imagefttext($image, $font_size, $angle, $base_x, $base_y,
$font_color, $font_file, $text) ;
}
else {
ImageTTFText($image, $font_size, $angle, $base_x, $base_y,
$font_color, $font_file, $text) ;
}
// set transparency
if($transparent_background)
ImageColorTransparent($image,$background_color) ;
// save copy of image for cache
ImagePNG($image,$cache_filename) ;
ImageDestroy($image) ;
return array(0, $hash.$extension, $w, $h);
}
/*
decode an HTML hex-code into an array of R,G, and B values.
accepts these formats: (case insensitive) #ffffff, ffffff, #fff, fff
*/
function hex_to_rgb($hex)
{
// remove "#"
if(substr($hex,0,1) == "#")
$hex = substr($hex,1) ;
// expand short form ("fff") color
if(strlen($hex) == 3)
{
$hex = substr($hex,0,1) . substr($hex,0,1) .
substr($hex,1,1) . substr($hex,1,1) .
substr($hex,2,1) . substr($hex,2,1) ;
}
if(strlen($hex) != 6)
print("Error: Invalid color \"$hex\"") ;
// convert
$rgb["red"] = hexdec(substr($hex,0,2)) ;
$rgb["green"] = hexdec(substr($hex,2,2)) ;
$rgb["blue"] = hexdec(substr($hex,4,2)) ;
return $rgb ;
}
// Determine the text bounding box after rotation is applied
function imagerotatedbbox($bbox, $angle=0, $pad=0) {
if (count($bbox) != 8)
return;
if (empty($pad))
$pad = array(0,0,0,0);
$a = $angle * M_PI / 180;
$cosa = cos($a);
$sina = sin($a);
$result = array();
# baseline and total width/height of text when horizontal
$base_x = abs($bbox[6]);
$base_y = abs($bbox[7]);
$old_w = max($bbox[0], $bbox[2], $bbox[4], $bbox[6]) - min($bbox[0], $bbox[2], $bbox[4], $bbox[6]);
$old_h = max($bbox[1], $bbox[3], $bbox[5], $bbox[7]) - min($bbox[1], $bbox[3], $bbox[5], $bbox[7]);
// rotate the box coordinates to get the new width & height of the final image
for ($i = 0; $i < 7; $i += 2) {
$result[$i] = round($bbox[$i] * $cosa + $bbox[$i+1] * $sina);
$result[$i+1] = round($bbox[$i+1] * $cosa - $bbox[$i] * $sina);
}
$w = max($result[0], $result[2], $result[4], $result[6]) - min($result[0], $result[2], $result[4], $result[6]);
$h = max($result[1], $result[3], $result[5], $result[7]) - min($result[1], $result[3], $result[5], $result[7]);
$pad_w = $w + ($pad[3] + $pad[1]);
$pad_h = $h + ($pad[0] + $pad[2]);
// center of bounding box (xc,yc);
$xc = $old_w/2.0;
$yc = $old_h/2.0;
// center of image
$px = $w/2.0;
$py = $h/2.0;
// baseline coordinates relative to the center
$x1 = $base_x - $xc;
$y1 = $base_y - $yc;
// baseline after rotation
$x2= intval( $x1*$cosa+$y1*$sina+$px+0.5);
$y2= intval(-$x1*$sina+$y1*$cosa+$py+0.5);
return array($pad_w, $pad_h, $x2 + $pad[3], $y2 + $pad[0]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment