Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Imagick not using custom fonts when converting SVG to JPG with PHP

I'm having an issue with custom fonts not rendering when attempting to convert an SVG to a JPG image. I am using font-family="Lobster" defined for an SVG text element.

My server setup is as follows:

  • CentOS 6.5 (32 bit)
  • ImageMagick 6.5.4-7
  • PHP 5.2.17

The PHP code I am testing with, but does not work. I am attempting to use the custom font Lobster.

//Setup SVG to be read by Imagick.
$SVG = '<?xml version="1.0" encoding="utf-8"?>';
$SVG .= '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';
$SVG .= '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="158px" height="92px" viewBox="0 0 158 92" enable-background="new 0 0 158 92" xml:space="preserve">';
$SVG .= '<text transform="matrix(1 0 0 1 32 58)" font-family="Lobster" font-style="normal" font-size="20px" font-weight="400">Lobster</text>';
$SVG .= '</svg>';

$image = new Imagick();

//Convert SVG to JPG
$image->readImageBlob($SVG);
$image->setImageFormat("jpeg");

//Save the thumbnail.
$save_path = '/home/username/lobster.jpg';
$image->writeImage($save_path);


echo '<img src="lobster.jpg" alt="" /><br />';

Which produces the following image:

Lobster.jpg

What I have tried:

I've created a type.xml file located at /home/username/.magick/type.xml with the Lobster font definition as shown here:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE typemap [
<!ELEMENT typemap (type)+>
<!ELEMENT type (#PCDATA)>
<!ELEMENT include (#PCDATA)>
<!ATTLIST type name CDATA #REQUIRED>
<!ATTLIST type fullname CDATA #IMPLIED>
<!ATTLIST type family CDATA #IMPLIED>
<!ATTLIST type foundry CDATA #IMPLIED>
<!ATTLIST type weight CDATA #IMPLIED>
<!ATTLIST type style CDATA #IMPLIED>
<!ATTLIST type stretch CDATA #IMPLIED>
<!ATTLIST type format CDATA #IMPLIED>
<!ATTLIST type metrics CDATA #IMPLIED>
<!ATTLIST type glyphs CDATA #REQUIRED>
<!ATTLIST type version CDATA #IMPLIED>
<!ATTLIST include file CDATA #REQUIRED>
]>
<typemap>

  <type
     format="ttf"
     name="Lobster"
     fullname="Lobster"
     family="Lobster"
     glyphs="/home/username/fonts/Lobster/Lobster.ttf"
     style="normal"
     stretch="normal"
     weight="400"
     />

</typemap>

I've included a direct include in the /usr/lib/ImageMagick-6.5.4/config/type.xml file like this:

<typemap>
   <include file="type-ghostscript.xml" />
   <include file="/home/username/.magick/type.xml" />
</typemap>

When outputting the fonts using the $image->queryfonts(); method, I can see the Lobster font defined in the list. For example, this:

$image = new Imagick();
$fonts = $image->queryfonts();
foreach($fonts as $font) {
    echo $font . '<br />';
}

Returns this:

[...]
Hershey-Plain-Triplex-Regular
Hershey-Script-Complex-Regular
Hershey-Script-Simplex-Regular
Lobster
MeriendaOne
NewCenturySchlbk-Bold
NewCenturySchlbk-BoldItalic
NewCenturySchlbk-Italic
NewCenturySchlbk-Roman
[...etc]

Additionally, I believe ImageMagick is using it's own internal SVG renderer. The shell command:

convert -list format | grep SVG

Returns:

MSVG  SVG       rw+   ImageMagick's own SVG internal renderer
SVG  SVG       rw+   Scalable Vector Graphics (RSVG 2.26.0)
SVGZ  SVG       rw+   Compressed Scalable Vector Graphics (RSVG 2.26.0)

Any ideas as to why this isn't working?

like image 218
Axel Avatar asked Nov 11 '22 07:11

Axel


1 Answers

I was having the same problem converting SVG to PNG using Imagemagick but was unable to make it work using that approach. I was somehow able to get the result I need using docraptor:

 DocRaptor.createAndDownloadDoc("YOUR_API_KEY", {
    test: true, // test documents are free, but watermarked
    type: "pdf",
    document_content: document.getElementById('container_of_svg').innerHTML
  }) 

Just make sure to add the font declarations inside the container_of_svg element like below and make sure to add an absolute URL to your fonts:

@font-face {
    font-family: 'DaimlerCS-Demi';
    src: url("https://staging.xxx.com/xx/fonts/xx/FontCS-Demi.eot")
}
page {
      size: 21.16cm 15.87cm;
      padding: 1cm;
      margin:0;
      background: #E6E6E6;
}

Just check their document here: https://docraptor.com/documentation/jquery

Note: docraptor is not free but if your client can pay for it, I think its a solid option.

like image 190
bananaCute Avatar answered Nov 15 '22 12:11

bananaCute