Embedding SVGs into PDFs with embedded fonts - pdf

I want to embed an SVG image into a PDF, and have the font families specified in the SVG text elements render using the correct fonts.
The fonts I am using are the 'Lato' TTF fonts.
Here is the code I have used to convert the fonts to TCPDF's "native format":
$variants = [
'Black',
'BlackItalic',
'Bold',
'BoldItalic',
'Hairline',
'HairlineItalic',
'Heavy',
'HeavyItalic',
'Italic',
'Light',
'LightItalic',
'Medium',
'MediumItalic',
'Regular',
'Semibold',
'SemiboldItalic',
'Thin',
'ThinItalic',
];
foreach ($variants as $variant) {
\TCPDF_FONTS::addTTFfont(
'/var/www/fonts/Lato-' . $variant . '.ttf',
'',
'',
32,
'/var/www/fonts/output/'
);
}
And here is the code I've used to generate a test PDF with an embedded SVG:
$svg_content = '<svg width="600px" height="800px">';
foreach ($variants as $key => $variant) {
$svg_content .= '<text x="30" y="' . ( 30 * ( $key + 1 ) ) . '" fill="#ED6E46" font-size="20" font-family="\'Lato-' . $variant . '\'" text-anchor="start">The quick brown fox jumped over the lazy dog (' . $variant . ').</text>';
}
$svg_content .= '</svg>';
$pdf = new TCPDF();
$pdf->SetPrintHeader(false);
$pdf->SetPrintFooter(false);
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
$pdf->SetMargins(0, 0, -1, true);
$pdf->SetAutoPageBreak(false, 0);
$pdf->AddPage();
$pdf->AddFont('Lato-Black', '', '/var/www/fonts/output/latoblack.php');
$pdf->ImageSVG('#' . $svg_content, 0, 0, 300, 300, '', $align='', $palign='C', $border=0, false);
$pdf->Output(
preg_replace('/[^A-Za-z0-9]/', '', $influencer->getName()) . '.pdf',
'I'
);
The result I get is that all the text is rendered in what I assume is Helvetica:
If I add a line just before the call to ImageSVG() like this:
$pdf->SetFont('Lato-Black', '', null, '/var/www/fonts/output/latoblack.php');
Then all the text is rendered in Lato-Black:
It seems to me that the fonts are being embedded in the PDF fine, but the SetFont obviously sets the current font for subsequent PDF text elements, and the text elements within the SVG image render using this font.
My desired behaviour is that the font-family attributes defined on the SVG text elements are honoured within the PDF, so that each line renders using the font variant mentioned in the brackets at the end of the line.
How can I do this?

You could start with the following code and work backwards incorporating your changes.
To be clear I'm not specifically advocating this as the way to do it, only that this is one way that works and so should help as a starting point.
Font Converter:
$variants = [
'Black',
'BlackItalic',
'Bold',
'BoldItalic',
'Hairline',
'HairlineItalic',
'Heavy',
'HeavyItalic',
'Italic',
'Light',
'LightItalic',
'Medium',
'MediumItalic',
'Regular',
'Semibold',
'SemiboldItalic',
'Thin',
'ThinItalic',
];
foreach ($variants as $variant) {
\TCPDF_FONTS::addTTFfont(dirname(__FILE__) . '/fonts/Lato-' . $variant . '.ttf', 'TrueTypeUnicode', '', 96);
}
echo 'Done!';
This puts the .php, .z and .ctg.z files within /tecnickcom/tcpdf/fonts.
PDF Generator:
Note the different font-family names in the $variants array:
$variants = [
'lato',
'latob',
'latobi',
'latoblack',
'latoblacki',
'latohairline',
'latohairlinei',
'latoheavy',
'latoheavyi',
'latoi',
'latolight',
'latolighti',
'latomedium',
'latomediumi',
'latosemib',
'latosemibi',
'latothin',
'latothini'
];
$svg_content = '<svg width="600px" height="800px">';
foreach ($variants as $key => $variant) {
$svg_content .= '<text x="30" y="' . ( 30 * ( $key + 1 ) ) . '" fill="#ED6E46" font-size="20" font-family="\'' . $variant . '\'" text-anchor="start">The quick brown fox jumped over the lazy dog (' . $variant . ').</text>';
}
$svg_content .= '</svg>';
ob_start();
$pdf = new TCPDF();
$pdf->SetPrintHeader(false);
$pdf->SetPrintFooter(false);
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
$pdf->SetMargins(0, 0, -1, true);
$pdf->SetAutoPageBreak(false, 0);
$pdf->AddPage();
//$pdf->AddFont('latoblack', '', dirname(__FILE__) . '/fonts/output/latoblack.php');
$pdf->ImageSVG('#' . $svg_content, 0, 0, 300, 300, '', $align='', $palign='C', $border=0, false);
$pdf->Output('example_001.pdf', 'I');
Output:

Related

how to Attach a generated Barcode to email in Prestashop 1.7.5

Can anyone please help me,
i would like to attache a generated Barcode image (png) in the order_conf email
i started by generate the barcode image :
$barcodeobj = new TCPDFBarcode($order->order_barcode, 'C128');
$barcode = base64_encode($barcodeobj->getBarcodePNG(1, 30, array(255,255,255)));
and then :
Mail::Send(
(int) $order->id_lang, 'order_conf',
Context::getContext()->getTranslator()->trans( 'Order confirmation', array(), 'Emails.Subject', $orderLanguage->locale ),
$data,
$this->context->customer->email,
$this->context->customer->firstname . ' ' . $this->context->customer->lastname,
null,
null,
$barcode,
null,
_PS_MAIL_DIR_,
false,
(int) $order->id_shop
);
also i tried to attache it like this but i didn't work :
$extra_pdf = array();
$extra_pdf['content'] = $barcode.'.png';
$extra_pdf['name'] = 'barcode.png';
$extra_pdf['mime'] = 'image/png';
you need to get the content of your image :
$content = file_get_contents(_PS_ROOT_DIR_.'/your_img_barcode_folder/'.$barcode.'.png');
Source:
http://prestacraft.com/send-custom-template-email-with-attachment-and-variables-in-prestashop/#
or you can also create a simple $link in your email template

PHPWord generated docx watermark image with 0 margin is shifted with some space from left and top edge of document

I generate a docx document with PHPWord and want to make an image to be as a background. Watermark is totally the point for it.
Everything works fine generating document like sections, paragraphs, font styles and sizes, line heights, etc.
But I stucked with this part: my image for background with margins 0 is always shifted with some space from the document's edge.
I go with this code:
$phpWord = new \PhpOffice\PhpWord\PhpWord();
$section = $phpWord->addSection();
$header = $section->addHeader();
$header->addWatermark($path . '/images/test.jpg',
array(
'marginTop' => 0,
'marginLeft'=> 0,
)
);
$section->addText('Is Richard Deckard a replicant?');
$timestamp = date('Hi-ymd');
$filename = 'DOC_' . $timestamp;
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007');
$objWriter->save($path . '/docs/' . $filename . '.docx');
The result is:
PHPWord watermark image for background
So as you see margins are not 0 but the image is some distance from the left and top edge of the page.
I was able positioning background image to the top-left edge this way
$header = $section->addHeader();
$header->addWatermark('images/test.png',
array(
'width' => 596,
'marginTop' => -36,
'marginLeft' => -50,
'posHorizontal' => 'absolute',
'posVertical' => 'absolute',
));
I think the point is the absolute parameter.
I needed to make negative values on margins, because my body section had inner margins.
I was having the same problem and fortunately I found this question and the answer from #vorvor. Thank you for the answer #vorvor.
I did the same thing in a Laravel 5.6 project and just wanted to share my code with you.
$header = $section->addHeader();
$bg_image = Storage::url('itinerary-assets/Untitled-1_compressed.jpg');
$header->addWatermark($bg_image, [
'marginTop' => -36,
'marginLeft' => -50,
'posHorizontal' => 'absolute',
'posVertical' => 'absolute'
]);

How to resize image by imagine extension in yii2

I use the bellow function to resize images after upload to show on my post.
but it works just for images larger than 500px 300px. when I upload image smaller than this size, my website images row breaks down.
use yii\imagine\Image;
public function upload() {
$this->pictureFile->saveAs('../files/upload/' . $this->pictureFile->baseName . '.' . $this->pictureFile->extension);
Image::thumbnail('../files/upload/' . $this->pictureFile, 500, 300)
->save('../files/upload/thumbnail-500x300/' . $this->pictureFile->baseName . '.' . $this->pictureFile->extension,
['quality' => 70]);
unlink('../files/upload/' . $this->pictureFile->baseName . '.' . $this->pictureFile->extension);
}
Instead of Image::thumbnail, try the following
$imagine = Image::getImagine();
$image = $imagine->open('../files/upload/' . $this->pictureFile);
$image->resize(new Box(500, 300))->save('../files/upload/thumbnail-500x300/' . $this->pictureFile->baseName . '.' . $this->pictureFile->extension, ['quality' => 70]);
Haven't tested it but since yii's Image is just a wrapper over Imagine library, this should work with minor changes (if at all needed).
And yes, you need to use Imagine\Image\Box; in your file before using the code above.
Use resize method as below
use yii\imagine\Image;
use Imagine\Image\Box;
public function upload() {
$this->pictureFile->saveAs('../files/upload/' . $this->pictureFile->baseName . '.' . $this->pictureFile->extension);
Image::thumbnail('../files/upload/' . $this->pictureFile, 500, 300)
->resize(new Box(500,300))
->save('../files/upload/thumbnail-500x300/' . $this->pictureFile->baseName . '.' . $this->pictureFile->extension,
['quality' => 70]);
unlink('../files/upload/' . $this->pictureFile->baseName . '.' . $this->pictureFile->extension);
}
Yii::setAlias('newsfolder', dirname(dirname(__DIR__)) . '/frontend/web/extraimages/');
$model->img = UploadedFile::getInstance($model,'img');
if (!empty($model->img)){
$model->img->saveAs( Yii::getAlias('#newsfolder/').$filename.'.'.$model->img->extension );
$model->img = $filename.'.'.$model->img->extension;
$imagine = Image::getImagine();
$image = $imagine->open(Yii::getAlias('#newsfolder/'.$model->img));
$image->resize(new Box(500, 300))->save(Yii::getAlias('#newsfolder/'.$model->img, ['quality' => 70]));
}
$imagine = Image::getImagine();
$imagine = $imagine->open($openPath);
$sizes = getimagesize ( $openPath );
/*
[0] => 604
[1] => 244
[2] => 3
[3] => width="604" height="244"
[bits] => 8
[mime] => image/png
) */
$width = 200;
$height = round($sizes[1]*$width/$sizes[0]);
$imagine = $imagine->resize(new Box($width, $height))->save($savePath, ['quality' => 60]);

TYPO3 - Add flexform to my own extension

I am building my own extension.
I have found this page about adding Flexform to the Extension
https://gist.github.com/alrnz/c0f00b196d378f5b9150
And in my ext_tables.php i have this:
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
$_EXTKEY,
'Xlsxtotables',
'XLSX to tables'
);
// Include flex forms
$pluginSignature = str_replace('_', '', $_EXTKEY) . '_' . 'xlsxtotables'; // from registerPlugin(...)
$TCA['tt_content']['types']['list']['subtypes_addlist'] [$pluginSignature] = 'pi_flexform';
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue(
$pluginSignature,
'FILE:EXT:' . $_EXTKEY . '/Configuration/FlexForms/flexform_xlsxtotables.xml'
);
I know that the XML-file is in the right place, but I do not get anyting from it in TYPO3 backend.
Any suggestions?
Try replace
$pluginSignature = str_replace('_', '', $_EXTKEY) . '_' . 'xlsxtotables';
by
$extensionName = strtolower(\TYPO3\CMS\Core\Utility\GeneralUtility::underscoredToUpperCamelCase($_EXTKEY));
$pluginSignature = $extensionName.'_'.'xlsxtotables';
And dont forget to empty your general cache before you see a change with your flexform.
You can try below code in ext_tables.php file
$pluginName = 'Pi1'; // Give Your Plugin Nmae
$pluginSignature = preg_replace('/[^a-z0-9]/', '', strtolower($_EXTKEY)) . '_' . strtolower($pluginName);
// FlexForm configuration
$TCA['tt_content']['types']['list']['subtypes_addlist'][$pluginSignature] = 'pi_flexform';
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue(
$pluginSignature,
'FILE:EXT:' . $_EXTKEY . '/Configuration/FlexForms/flexformname.xml'
);
For Adding Flexforms in One or More Front-end plugins you can use Below code in ext_tables.php
$extensionName = \TYPO3\CMS\Core\Utility\GeneralUtility::underscoredToUpperCamelCase($_EXTKEY);
$frontendpluginName = 'xxx'; //Your Front-end Plugin Name
$pluginSignature = strtolower($extensionName) . '_'.strtolower($frontendpluginName);
$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist'][$pluginSignature] = 'pi_flexform';
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue($pluginSignature, 'FILE:EXT:' . $_EXTKEY . '/Configuration/FlexForms/xyz.xml');

Yii preventing Apple Push Notification script from running

I have a script which does an Apple push notification to an App. The script is:
$payload['aps'] = array('alert' => 'This is the alert text',
'badge' => 1, 'sound' => 'default',
'article_id'=> '110'
);
$payload = json_encode($payload);
$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsPort = 2195;
$apnsCert = '/var/www/schoolspace/apple_server/mountmercy/MountMercy-dev.pem';
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
$deviceToken = "xxxxxxxxxxxxxxxxxxxxxxxxx";
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);
socket_close($apns);
fclose($apns);
I have created the required .pem. When I run this as a standalone script with:
php index.php
everything works and the app receives the notification. There is a warning however:
Warning: socket_close(): supplied resource is not a valid Socket resource
But it still works. However, when I run this in Yii, I get the error:
stream_socket_client() [<a href='function.stream-socket-client'>function.stream-socket-client</a>]: Unable to set private key file `/var/www/schoolspace/apple_server/mountmercy/MountMercy-dev.pem'
I get this error even when setting YII_DEBUG to false. I run this segment of code in the my Yii "Message" model in afterSave(). It's EXACTLY the same as the standalone script. But somehow Yii is preventing it from running. Any ideas?
Since you are receiving the notification that means your pem file might be okay, but
your code doesn't show where you are providing the passphrase. You can try the below code which worked for me.
$badge = 1;
$sound = 'default';
$development = false;//change it to true if in development
$passphrase='passphrase';//pass phrase of the pem file
$payload = array();
$payload['aps'] = array('alert' => $msg_text, 'badge' => intval($badge), 'sound' => $sound);
$payload = json_encode($payload);
$apns_url = NULL;
$apns_cert = NULL;
$apns_port = 2195;
if($development)
{
$apns_url = 'gateway.sandbox.push.apple.com';
$apns_cert = dirname(Yii::app()->request->scriptFile).'/file.pem';
}
else
{
$apns_url = 'gateway.push.apple.com';
$apns_cert = dirname(Yii::app()->request->scriptFile).'/file.pem';
}
$stream_context = stream_context_create();
stream_context_set_option($stream_context, 'ssl', 'local_cert', $apns_cert);
stream_context_set_option($stream_context, 'ssl', 'passphrase', $passphrase);
$apns = stream_socket_client('ssl://' . $apns_url . ':' . $apns_port, $error, $error_string, 2, STREAM_CLIENT_CONNECT, $stream_context);
$device_tokens2= "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$apns_message = chr(0) . chr(0) . chr(32) . pack('H*', $device_tokens2 ) . chr(0) . chr(strlen($payload)) . $payload;
$msg=fwrite($apns, $apns_message);
#socket_close($apns);
#fclose($apns);