Zend PDF word wrapping - php

Does Zend_Pdf already support automatic wrapping of text?
For example I want to create a textblock and fill it with text. This is a very important feature and unless Zend Pdf does not have it I am not able to switch from FPDF.
Also I think a Framework that says it has PDF support should be able to offer their developers this kind of feature.
Or am I missing something here?

Indeed Zend_Pdf is not mature enough to compare with the regular Zend_YouNameIt component.
In my oppinion Zend_Pdf should not be part of Zend. It is very limited and can't be used in most cases because one or the other feature is missing.
As for the feature you are missing, you would have to check the Manual or read the code but in general I advise to use something else for PDF generation until Zend_Pdf is mature enough.
I think the best solution would be for Zend_Pdf to be a wrapper for some kind of command line tool.

couple of years later with Zend 1.11 this is working for me in a pdf class function
/**
* puts text box to a page
*
* #param integer $offset_x
* #param integer $offset_y
*/
public function drawTextArea($text, $pos_x, $pos_y, $height, $length = 0, $offset_x = 0, $offset_y = 0) {
$x = $pos_x + $offset_x;
$y = $pos_y + $offset_y;);
if ($length != 0) {
$text = wordwrap($text, $length, "\n", false);
}
$token = strtok($text, "\n");
while ($token != false) {
$this->page->drawText($token, $x, $y);
$token = strtok("\n");
$y -= $height;
}
}
if someone likes it use it

Zend pdf is not supporting automatic word wrap.

I can recommend you to use dompdf instead. It allows you to define the page in html and render it into a pdf. Wordwrap will be handled fine!
It even allows for page breaks, so multi-page pdfs are possible.

Related

How to use PDF_get_option() method to get font name?

function nvpdf_WrapString($my_pdf,$string,$width,$width_in_chars = "") {
// known problem: can only be called after the pdf document has been
// started, font size set, etc as it relies on the pdf being in the
// page scope to use pdf_stringwidth (see PDFLib manual p.83).
// returns an array: 1st level column
// 2nd level data string broken up into lines that fit the column
$string = str_replace('\n', "\n", $string);
$inlines = explode("\n",$string);
$outlines = array();
$font_size = PDF_get_option($my_pdf, "fontsize", "");
$font_name = pdf_get_parameter($my_pdf, "fontname", 0);
$font_id = PDF_load_font($my_pdf, $font_name, "host","");
I got a deprecation warning from php saying that I should use pdf_get_option() instead of pdf_get_parameter(). But how can I convert this pdf_get_parameter() to pdf_get_option()?
I need a method that will return me the font name of $mypdf.
Found the solve. pdf_get_option() wont give me the font name. All I have to do is use pdf_info_font() and then use pdf_get_string() to get the fontname.
nice that you could find the solution yourself.
Another quick note: If you have found a deprecated warning for a PDFlib function, it is recommended to replace it even if the functionality still works in the version you are using. This is because the deprecated function may no longer be available when updating.
The current PDFlib 9 and 10 packages include a PDFlib Migration Guide which describes all necessary changes in detail.
You can also find the latest PDFlib 10 Migration Guide on the PDFlib Web site pdflib.com.
for this particular question you would find the explanation in chapter 2.1 table 2.3:
deprecated parameter:
ascender, ascenderfaked, capheight, capheightfaked, descende,
descenderfaked, fontencoding, fontname,fontmaxcode, xheight, xheightfaked
deprecated since:
PDFlib 7
replacement method and option:
PDF_info_font( ) with same-named keywords; for the numerical
values fontsize=1 must be supplied;
parameter fontencoding: use keyword encoding
A sample usage is also available in the PDFlib cookbook "font/font_info".
/* Get the font name: use "api" to get the font name used by PDFlib.
* (use "acrobat" for the Acrobat font name or use "full" for
* retrieving the full font name)
*/
$p->fit_textline("fontname (api):", $x, $y-=$yoffset, "");
$info = $p->info_font($font, "fontname", "api");
if ($info > -1) {
$fontname = $p->get_string($info, "");
$p->fit_textline($fontname, $xindent, $y, "");
}

Is possible to embed fontawesome font in fpdf?

I'd like to use fontawesome in pdf. I generate my pdf using php library fpdf and font embedding. However I cannot make it works.
I use this tool to generate afm file: http://fpdf.fruit-lab.de/
But when I try to use fontawesome I always get white square instead of icons.
I use this syntax to add icon:
MultiCell(0,8,"\uF000 ",0,'C')
I cannot answer for fpdf since I have never used it. However, I do use mPDF and there I use fontawesome regularly - no issues at all. The only thing I have to ensure is that the content I output to the PDF document (mPDF takes this in the form of HTML markup) hast to be UTF8 encoded.
mPDF is very good so if you are at an early stage of your project you might just consider switching to it. Otherwise, it is worth exploring whether you too are not running into a UTF8 encoding issue.
I figured this out even though this thread is over a year old. It is possible to use font-awesome although you can only use up to 256 characters per subset. I created several character maps to encompass all of the glyphs as of font awesome version 4.3.0. You just use the map that contains the characters you're going to use or you can make three subsets of it. It's not necessarily as performant as other solutions, but fPDF is still much faster than some of the alternatives because it is lacking a lot of the more modern features like unicode support.
http://code.deweyartdesign.com/fpdf/makefont/fa1.map
http://code.deweyartdesign.com/fpdf/makefont/fa2.map
http://code.deweyartdesign.com/fpdf/makefont/fa3.map
First, you need to use ttf2pt1 to create the afm file for the font.
ttf2pt1 -a fontawesome-webfont.ttf fontawesome-webfont
I made three copies of the webfont to run through makefont.php and used each encoding on the corresponding font.
require "makefont.php";
makefont('fontawesome-webfont1.ttf','fa1.map');
makefont('fontawesome-webfont2.ttf','fa2.map');
makefont('fontawesome-webfont3.ttf','fa3.map');
To use them in fPDF, put the files generated in the font folder and add them like this:
$pdf->AddFont('FA1','',fontawesome-webfont1.php);
$pdf->AddFont('FA2','',fontawesome-webfont2.php);
$pdf->AddFont('FA3','',fontawesome-webfont3.php);
Then you use the character number to render the glyph for the corresponding subset of font-awesome. The three font maps above contain the character numbers to use :
$pdf->SetFont('FA1','',14);
$WineGlass = chr(32);
$pdf->Cell(40,10,$WineGlass);
I also made a character map generator that will show the character numbers below the glyphs.
<?php
require_once($_SERVER['DOCUMENT_ROOT'] . '/pdf/fpdf.php');
// Establish / Get variables
function GETVAR($key, $default = null, $prefix = null, $suffix = null) {
return isset($_GET[$key]) ? $prefix . $_GET[$key] . $suffix : $prefix . $default . $suffix;
}
$font = GETVAR('font','fontawesome-webfont1','','.php');
$pdf = new FPDF('L','mm',array(268.33,415.3));
$pdf->AddPage();
$pdf->SetMargins(0,0,0);
$pdf->SetAutoPageBreak(0,0);
// add custom fonts
$pdf->AddFont('H','','helvetica.php');
$pdf->AddFont('FA','',$font);
$pdf->SetFillColor(200,200,200);
$pdf->SetXY(9,9);
for ($i = 32; $i <= 256; $i++) {
$y = $pdf->GetY();
$x = $pdf->GetX();
$pdf->SetX($x);
$pdf->SetTextColor(0, 0, 0);
$pdf->SetFont('FA','',14);
$pdf->Cell(12,12,chr($i),1,0,'C');
$pdf->SetXY($x,$y+12);
$pdf->SetTextColor(0, 0, 0);
$pdf->SetFont('H','',14);
$pdf->Cell(12,12,$i,1,0,'C',1);
$y = $pdf->GetY();
$x = $pdf->GetX();
$pdf->SetXY($x,$y-12);
if ($x > 400) {
$pdf->SetXY(9,$y+14);
}
if ($i == 328){
$pdf->AddPage();
}
}
$pdf->Output("charmap.pdf",'I');
You can re-create the font-awesome and re-map it to A-Z characters,
and that way, use it easily in fpdf.
// Import and prepare font for usage by engine:
$pdf->AddFont('fontawesome-123-full','','fontawesome-123-full.php');
...
// print FontAwesome's asterisk
$pdf->Text($x, $y, chr(0x21));
You can download the ready font and ready-to-use FPDF font files here:
http://mdb-blog.blogspot.com/2021/12/using-fontawesome-in-php-fpdf.html

Searching through very large files with php to extract a block very efficiently

I've been having a major headache lately with parsing metadata from video files, and found part of the problem is a disregard of various standards (or at least differences in interepretation) by video-production software vendors (and other reasons).
As a result I need to be able scan through very large video (and image) files, of various formats, containers and codecs, and dig out the metadata. I've already got FFMpeg, ExifTool Imagick and Exiv2 each to handle different types of metadata in various filetypes and been through various other options to fill some other gaps (please don't suggest libraries or other tools, I've tried them all :)).
Now I'm down to scanning the large files (upto 2GB each) for an XMP block (which is commonly written to movie files by Adobe suite and some other software). I've written a function to do it, but I'm concerned it could be improved.
function extractBlockReverse($file, $searchStart, $searchEnd)
{
$handle = fopen($file, "r");
if($handle)
{
$startLen = strlen($searchStart);
$endLen = strlen($searchEnd);
for($pos = 0,
$output = '',
$length = 0,
$finished = false,
$target = '';
$length < 10000 &&
!$finished &&
fseek($handle, $pos, SEEK_END) !== -1;
$pos--)
{
$currChar = fgetc($handle);
if(!empty($output))
{
$output = $currChar . $output;
$length++;
$target = $currChar . substr($target, 0, $startLen - 1);
$finished = ($target == $searchStart);
}
else
{
$target = $currChar . substr($target, 0, $endLen - 1);
if($target == $searchEnd)
{
$output = $target;
$length = $length + $endLen;
$target = '';
}
}
}
fclose($handle);
return $output;
}
else
{
throw new Exception('not found file');
}
return false;
}
echo extractBlockReverse("very_large_video_file.mov",
'<x:xmpmeta',
'</x:xmpmeta>');
At the moment it's 'ok' but I'd really like to get the most out of php here without crippling my server so I'm wondering if there is a better way to do this (or tweaks to the code which would improve it) as this approach seems a bit over the top for something as simple as finding a couple of strings and pulling out anything between them.
You can use one of the fast string searching algorithms - like Knuth-Morris-Pratt
or Boyer-Moore in order to find the positions of the start and end tags, and then read all the data between them.
You should measure their performance though, as with such small search patterns it might turn out that the constant of the chosen algorithm is not good enough for it to be worth it.
With files this big, I think that the most important optimization would be to NOT search the string everywhere. I don't believe that a video or image will ever have a XML block smack in the middle - or if it has, it will likely be garbage.
Okay, it IS possible - TIFF can do this, and JPEG too, and PNG; so why not video formats? But in real world applications, loose-format metadata such as XMP are usually stored last. More rarely, they are stored near the beginning of the file, but that's less common.
Also, I think that most XMP blocks will not have sizes too great (even if Adobe routinely pads them in order to be able to "almost always" quickly update them in-place).
So my first attempt would be to extract the first, say, 100 Kb and last 100 Kb of information from the file. Then scan these two blocks for "
If the search does not succeed, you will still be able to run the exhaustive search, but if it succeeds it will return in one ten-thousandth of the time. Conversely, even if this "trick" only succeeded one time in one thousand, it would still be worthwhile.

How can I add a drop-shadow to an image using PHP?

I am looking for a way to add a drop shadow to an image using PHP. Before you answer or vote to close: I am not looking to do this using CSS or HTML. I want to generate an image file. This is not a duplicate of this question nor this one.
I am looking for a very specific effect. For example, given this input image:
I want to produce the following image:
TL;DR: This image above was generated using Photoshop's Drop Shadow effect. I want a look very similar to that. For reference, here's the settings our design team used. Ideally, I'd have similar control in my code for angle, distance, opacity, etc:
I have full access to our debian-linus-based servers, so any GD or ImageMagick solution will work. As will any FOSS linux software solution, although I'd prefer a way to do it with IM or GD as those are already installed and don't require new software to be installed.
The shadow must be able to be placed on a transparent, non-rectangular PNG!
I'm asking the question mainly because the scripts and solutions I have found on the web either only produce rectangular shadows, look like total poo, or just plain don't work at all.
Just for the hell of it (I know it was answered and accepted): a few months ago, in response to a question on graphic design stackexchange about recovering a mask from a PNG where the source file was lost I slapped together something which uses PHP GD functions to extract the alpha channel from a transparent PNG. As Joe in a comment mentioned above, you can use the alpha channel as the drop shadow, merely offset it by x and y pixels, and then apply an image convolution blur filter to it, then copymerge the original on top. Following code is probably SLOW and proof of concept, but it is a start and it is in PHP as you originally requested.
<?php
$im = imagecreatefrompng('./images/alphatest_nolayer.png');
$w = imagesx($im);
$h = imagesy($im);
$om = imagecreatetruecolor($w,$h);
for ($x = 0; $x < $w; $x++) {
for ($y = 0; $y < $h; $y++) {
$rgb = imagecolorat($im, $x, $y);
$colors = imagecolorsforindex($im, $rgb);
$orgb = imagecolorallocate($om,$colors['alpha'],$colors['alpha'],$colors['alpha']);
imagesetpixel($om,$x,$y,$orgb);
}
}
header('Content-Type: image/png');
imagepng($om);
imagedestroy($om);
imagedestroy($im);
?>
Actually this can be done with image magick's convert, no need for GD library:
<?php
$cmd = 'convert /path/to/source.png \( +clone -background black -shadow 80x3+4+4 \) \+swap -background none -layers merge +repage /path/to/destination.png';
exec($cmd);
?>
you can play a little with the shadow parameter.
-shadow percent-opacity{xsigma}{+-}x{+-}y{%}
You're not going to be able to do this in PHP without building in a full edge-detector algorithm and significant processing overhead. Look into using GIMP with some script-fu, and let it do the hard work for you.
I used Marc B's advice, and called upon The GIMP to do this for me. If anyone else cares, here's the code I used:
/**
* Call upon The GIMP to apply a dropshadow to a given image.
*
* NOTE: This will overwrite the image file at $filename! Be sure to make a copy
* of this file first if you need one.
*
* #param string $filename
* #param int $offset_x
* #param int $offset_y
* #param float $radius
* #param array $color
* #param int $opacity
* #return type
* #todo Resize the canvas so there's room to apply dropshadows to images which have no whitespace around them.
*/
function apply_gimp_dropshadow($filename,$offset_x=8,$offset_y=8,$radius=15,$color=false,$opacity=40)
{
if(!is_array($color))
$color = array(0,0,0);
$color = join(' ',$color);
$gimpScript = <<<END_OF_SCHEME_CODE_OH_HOW_I_HATE_YOU_SCHEME
(define (dropshadow filename)
(let* (
(image (car (gimp-file-load RUN-NONINTERACTIVE filename filename)))
(drawable (car (gimp-image-get-active-layer image)))
)
(script-fu-drop-shadow image drawable 8 8 15 '($color) 40 FALSE)
(set! drawable (car (gimp-image-merge-visible-layers image 0)))
(gimp-file-save RUN-NONINTERACTIVE image drawable filename filename)
(gimp-image-delete image)
)
)
(dropshadow "$filename")
(gimp-quit 0)
END_OF_SCHEME_CODE_OH_HOW_I_HATE_YOU_SCHEME;
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
);
$cwd = '/tmp';
$gimp = proc_open('/usr/bin/gimp -i -b -', $descriptorspec, $pipes, $cwd);
if (!is_resource($gimp))
throw new Exception('Could not open a pipe to GIMP');
fwrite($pipes[0], $gimpScript);
fclose($pipes[0]);
$gimpOutput = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$gimpResult = proc_close($gimp);
return $gimpResult;
}
You can use PHPs GD Image Processing Libraries
Here is a tutorial on how to add the shadow effect. However if this doesn't fit your needs i'm sure googling "PHP GD Drop Shadow" will do the trick.
This answer doesn't provide a Python solution, but it does give the generic algorithm required.
Taking images from an outstanding question about drop-shadows that i have, we start with an image:
convert the image to black and white:
apply a gaussian blur, and offset the image as desired:
finally overlay the original image:
i don't know Python, or anything about it, but presumably this algorithm can help you, or someone else stumbling across this question.
Note: Strictly speaking this should be a comment, but i really wanted to be able to show the images.

Can PHP read text from a PowerPoint file?

I want to have PHP read an (uploaded) powerpoint presentation, and minimally extract the text from each slide (grabbing more info like images and layouts would even be better, but I would settle for just the text at this point).
I know that google apps does it in its presentation app, so I am guessing there is some way to translate the powerpoint binary, but I can't seem to find any info on how to do it.
Any ideas on what to try?
Thanks -
Depending on the version, you can take a look on the Zend Framework as Zend_Search_Lucene is able to index PowerPoint 2007 files. Just take a look at the corresponding class file, i think it's something like Zend_Search_Lucene_Document_Pptx.
Yes of course it's possible.
[Here's a start.](http://download.microsoft.com/download/0/B/E/0BE8BDD7-E5E8-422A-ABFD-4342ED7AD886/PowerPoint97-2007BinaryFileFormat(ppt)Specification.pdf) I wouldn't say it's very well documented/formated, but it's not that hard once you get started. Start by focusing only on elements you need (slides, text, etc).
A less detailed and simpler approach would be to open .ppt file in hex editor and look for information you are interesed in (you should be able to see text within the binary data) and what surrounds it. Then based on what surrounds that information you could write a parser which extracts this information.
Here's a sample function I created form a similar one that extracts text from Word documents. I tested it with Microsoft PowerPoint files, but it won't decode OpenOfficeImpress files saved as .ppt
For .pptx files you might want to take a look at Zend Lucene.
function parsePPT($filename) {
// This approach uses detection of the string "chr(0f).Hex_value.chr(0x00).chr(0x00).chr(0x00)" to find text strings, which are then terminated by another NUL chr(0x00). [1] Get text between delimiters [2]
$fileHandle = fopen($filename, "r");
$line = #fread($fileHandle, filesize($filename));
$lines = explode(chr(0x0f),$line);
$outtext = '';
foreach($lines as $thisline) {
if (strpos($thisline, chr(0x00).chr(0x00).chr(0x00)) == 1) {
$text_line = substr($thisline, 4);
$end_pos = strpos($text_line, chr(0x00));
$text_line = substr($text_line, 0, $end_pos);
$text_line = preg_replace("/[^a-zA-Z0-9\s\,\.\-\n\r\t#\/\_\(\)]/","",$text_line);
if (strlen($text_line) > 1) {
$outtext.= substr($text_line, 0, $end_pos)."\n";
}
}
}
return $outtext;
}
I wanted to post my resolution to this.
Unfortunately, I was unable to get PHP to reliably read the binary data.
My solution was to write a small vb6 app that does the work by automating PowerPoint.
Not what I was looking for, but, solves the issue for now.
That being said, the Zend option looks like it may be viable at some point, so I will watch that.
Thanks.

Categories