10

I am working on a project where an admin can create a card template in which they can insert placeholder variables like {first_name}, {last_name}, {website} etc. Then a card will be created by having a user fill in their first name, last name etc. So basically the placeholders will be replaced by the actual content provided by the user. To do that I am creating an SVG image from the template created by the admin and replacing those placeholder variables with the user's data on server side.

The issue is that, if the content provided by the user is too long, then it might extend outside of the canvas boundary, and so might get cut off when the actual card is printed.

Is there some way to detect that, after replacing the placeholders, a canvas element extends outside of the canvas boundary? If so, is there a way to find that element and make it shrink until it fits within the boundary? Basically, I'd like something like this but on server side.

Here's some sample code that I'm using to generate the SVG image:

$message_string = array('{first_name}','{last_name}');
$replace_string = array('Fist Name of User','Last Name Of User');
$front_svg_url = $svg_url.$res_code[0]['front_side_svg_image'];
$front_raw_svg = file_get_contents($front_svg_url);
$front_side_svg = str_ireplace($message_string, $replace_string, $front_raw_svg);
$file_name = uniqid($prefix).".svg";
$file_handle = fopen("$folder_name/".$file_name, 'w');
fwrite($file_handle, $front_side_svg);
fclose($file_handle);

On the server side I am just replacing the variables, so I'm not sure how to achieve this on the server. I am open to any ideas which can achieve my expected output.

Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153
DS9
  • 2,995
  • 4
  • 52
  • 102

1 Answers1

7

You can use PHP function imageftfbox (GD lib should be enabled).

It returns array of coordinates [x0,y0, x1,y1, x2,y2, x3,y3].

Based on them you can determine whether it's out of your SVG element placement, here's an example of how you can do this:

function cutStringToPix($str, $svgWidth, $fontSize = 14, $font='times_new_roman.ttf', $delimiter = '') 
  $font = './fonts/' .$font;
  $sWidth = $svgWidth;
  $newStr = $str;
  $words = $delimiter
     ? explode($delimiter, $str)
     : str_split($str);
  $wordsCnt = count($words);

  // Reduce your string until it fits
  for (;$sWidth >= $svgWidth && $wordsCnt; $wordsCnt--) {
    $newStr = implode(' ', array_slice($words, 0, $wordsCnt));
    $bbox = imagettfbbox($fontSize, 0, $font, $newStr);
    $sWidth = $bbox[2] - $bbox[0];
  };
  return $newStr;
}
// Now use your $newStr

So ok, that's your example from comment

It uses TimesNewRoman font, you need to find TTF for it(for instance this...) and save it on server in "fonts" dir (relatively to your lib.php where you deside to store 'cutStringToPix' func) as 'times_new_roman.ttf'

then your SVG-forming part will be like this:

//include 'cutStringPix' func

$message_string = array('{first_name}','{last_name}');
$replace_string = array('Fist Name of User','Last Name Of User');
$front_svg_url = $svg_url.$res_code[0]['front_side_svg_image'];
$front_raw_svg = file_get_contents($front_svg_url);
//so what we adding:
$replace_string = cutStringToPix($replace_string, 162, 13);

$front_side_svg = str_ireplace($message_string, $replace_string, $front_raw_svg);
$file_name = uniqid($prefix).".svg";
2oppin
  • 1,941
  • 20
  • 33
  • If you can provide the example using svg then it might be more clear. You can checkout this svg: https://codepen.io/dhavalsisodiya/pen/bvGGvp So how should i implement your method using that svg? exa. {qr_code_value} value might be too long so it might be outside of boundary. – DS9 Mar 15 '18 at 08:52
  • 1
    it's no matter wether it svg or not. you have an image with width in pixels, your {qr_code_value} is an variable that you can check in php, ($str), your example svg have width = 255, and {qr_code_value} offset is 93, so for you $svgWidth = 162. Now you need to load somewhere times_new_roman.ttf on your server, and use that example that I've posted to reduce your {qr_code_value} before "str_ireplace" – 2oppin Mar 15 '18 at 09:17
  • yupp. and forgot to add that fontSize in your example 13, so first param of imagettfbbox should be 13 (not 14) – 2oppin Mar 15 '18 at 09:31