I would like to use this configuration and make a line break every 60 characters.
The example i saw on the other pages does not explain how i can make a line break every 60 characters.
$pdf->Text(77, 94, utf8_decode("$objet"));
You can use wordwrap to break sentences into multiple lines without breaking the word and without the line exceeding the desired length.
Then simply iterate the lines, increasing the Y coordinate on each iteration, adjust the Y coordinate as necessary to suit the size of your text.
$object = "This is a very long text that I want to break into multiple lines every 60 characters.";
$object_lines = wordwrap($object, 60, "\n", true);
$object_lines = explode("\n", $object_lines);
$y = 94;
foreach ($object_lines as $line) {
$pdf->Text(77, $y, utf8_decode($line));
$y += 10;
}
Related
I want to trim a given text at a given number of pixels.
To achieve this, I loop through the length of the text and with each loop, I add the next character and measure the string with the help of the method imagettfbbox. - This works fine for me on "normal text's" e.g. like this posting. ;)
But if I add some emoji's to my text, the length is even shorter than expected. I think this is because emojis encoded with more than 1 byte. -
That's why, I'm using mb_strwidth and mb_substr.
The method imagettfbbox expects a font-file to measure the given string. This font is able to display my emoji's.
Here's my code
$Line = "🏡 Garden, 🕓 Clock, some other things";
$MaxLength = 100; // Pixel
// Start looping through the line, start with 15 characters
for ( $Len = 15; $Len < mb_strwidth($Line); $Len++ ) {
// Grep x Chars from line
$NewLine = mb_substr($Line, 0, $Len);
// Measure string
$FontBox = imagettfbbox(12, 0, "fonts/OpenSansEmoji.ttf", $NewLine);
$TextWidth = $FontBox[2];
// Compare measured string with given max length
if ( $TextWidth > $MaxLength ) {
$Line = mb_substr($Line, 0, $Len - 2) . "...";
break;
}
}
$Line = NewLine;
Expample lines
"🏡 Garden, 🕓 Clock, some other things"
"🏡🏡🏡🏡🏡🏡🏡🏡🏡🏡🏡🏡🏡🏡🏡🏡 Gaaaaaaaaaaaardeeeeeeeeeeeeeeeeeen"
"mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"
"iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"
"erufgbwuiergbvfuipwervbpiuwebvruiwbevuibwüeriuvbwieuörvböwieuvbr"
Result
As you can see, the more emoji's i use, the shorter the line.
Kind regards from a non native speaker. :)
I'm a junior PHP developer.
For a costumer I need to place some strings into a pdf. I'm using FPDI and I like it.
I have an existing template PDF and I need to insert every characters of a string into a little graphic box (see image).
Every characters must have 2 millimeters (8px approximately) from each others.
Every strings can have different length, so I thought do like this:
$name = 'namenamename';
$stringcount = strlen($name)-1;
$countspace = $stringcount*2;
//121 = coordinate of first box
for ($x=121; $x <= $x+$countspace; $x = $x+2) {
for ($i=0; $i <= $stringcount; $i++) {
$pdf->SetXY($x, 37);
$pdf->Write(0,$name[$i]);
}
}
That doesn't work. This is the error:
Maximum execution time of 30 seconds
Can you help me please with the correct approach and with good explanation for a newbie? :)
Try this code:
$name = 'namenamename';
$string_length = strlen($name);
$coordinate = 121; //Give to the variable coordinate the beginning value, in this case 121
for ($i=0; $i < $string_length; $i++){ //make only one loop for the string length so the loop ends when there is no more characters
$char = substr($name,$i,1); // this is "the tricky part", with substr you can grab each character with its position in the string
$pdf -> SetXY($coordinate, 37); // here you put the coordinate for the character
$pdf -> Write(0, $char); // write it
$coordinate += 2; // and increment it by two, since the character are two spaces away from each other
}
hope that will help..
Maybe not a great solution but you can modify the execution time with this line of code
set_time_limit ( $seconds );
Anyway give it a try but i think that is more an error in the logic of the loop maybe.
Can you say exactly the coordinate where you need the two first characters, the first is 121 + something or 121?
I have scraped 5000 files, stored them in individual files (0-4999.txt), now i need to find duplicate content in them. so i am comparing each file with one another in nested loop (ETA 82 hours). This approach will definitely take hours to complete. My main concern here is the no. of iterations. Can anyone suggest a better approach to cut down iterations and reduce time taken?
current code: NCD algorithm
function ncd_new($sx, $sy, $prec=0, $MAXLEN=9000) {
# NCD with gzip artifact correctoin and percentual return.
# sx,sy = strings to compare.
# Use $prec=-1 for result range [0-1], $pres=0 for percentual,
# For NCD definition see http://arxiv.org/abs/0809.2553
$x = $min = strlen(gzcompress($sx));
$y = $max = strlen(gzcompress($sy));
$xy= strlen(gzcompress($sx.$sy));
$a = $sx;
if ($x>$y) { # swap min/max
$min = $y;
$max = $x;
$a = $sy;
}
$res = ($xy-$min)/$max; # NCD definition.
if ($MAXLEN<0 || $xy<$MAXLEN) {
$aa= strlen(gzcompress($a.$a));
$ref = ($aa-$min)/$min;
$res = $res - $ref; # correction
}
return ($prec<0)? $res: 100*round($res,2+$prec);
}
looping over each file:
$totalScraped = 5000;
for($fileC=0;$fileC<$totalScraped;$fileC++)
{
$f1 = file_get_contents($fileC.".txt");
$stripstr = array('/\bis\b/i', '/\bwas\b/i', '/\bthe\b/i', '/\ba\b/i');
$file1 = preg_replace($stripstr, '', $f1);
// 0+fileC => exclude already compared files
// eg. if fileC=10 , start loop 11 to 4999
for($fileD=(0+$fileC);$fileD<$totalScraped;$fileD++)
{
$f2 = file_get_contents($fileD.".txt", FILE_USE_INCLUDE_PATH);
$stripstr = array('/\bis\b/i', '/\bwas\b/i', '/\bthe\b/i', '/\ba\b/i');
$file2 = preg_replace($stripstr, '', $f2);
$total=ncd_new($file1,$file2);
echo "$fileName1 vs $fileName2 is: $total%\n";
}
}
You may want to find a way to distinguish likely candidates from unlikely ones.
So, maybe there is a way that you can compute a value for each file (say: a word count, a count of sentences / paragraphs... maybe even a count of individual letters), to identify the unlikely candidates beforehand.
If you could achieve this, you could reduce the amount of comparisons by ordering your arrays by this computed number.
another process that i tried was:
strip html tags from page
replace \s{2,} with \s, \n{2,} with \n, so that text b/w each tag is presented in a single line(almost)
compare two such generated files by taking a line, preg_matching, if found -> duplicate, else break line into array of words, calculate array_intersect, if count is 70% or more of line length -> duplicate.
which was very efficient and i could compare 5000 files in ~10 minutes
but still slow for my requirements.
So i implemented the first logic "ncd algo" method in C language, and it completes the task with 5-10 seconds (depending on the average page size)
I have been reading/testing examples since last night, but the cows never came home.
I have a file with (for example) approx. 1000 characters in one line and want to split it into 10 equal parts then write back to the file.
Goal:
1. Open the file in question and read its content
2. Count up to 100 characters for example, then put a line break
3. Count 100 again and another line break, and so on till it's done.
4. Write/overwrite the file with the new split content
For example:
I want to turn this => KNMT2zSOMs4j4vXsBlb7uCjrGxgXpr
Into this:
KNMT2zSOMs
4j4vXsBlb7
uCjrGxgXpr
This is what I have so far:
<?php
$MyString = fopen('file.txt', "r");
$MyNewString;
$n = 100; // How many you want before seperation
$MyNewString = substr($MyString,0,$n);
$i = $n;
while ($i < strlen($MyString)) {
$MyNewString .= "\n"; // Seperator Character
$MyNewString .= substr($MyString,$i,$n);
$i = $i + $n;
}
file_put_contents($MyString, $MyNewString);
fclose($MyString);
?>
But that is not working quite the way I anticipated.
I realize that there are other similiar questions like mine, but they were not showing how to read a file, then write back to it.
<?php
$str = "aonoeincoieacaonoeincoieacaonoeincoieacaonoeincoieacaonoeincoieacaon";
$pieces = 10;
$ch = chunk_split($str, $pieces);
$piece = explode("\n", $ch);
foreach($piece as $line) {
// write to file
}
?>
http://php.net/manual/en/function.chunk-split.php
Hold on here. You're not giving a file name/path to file_put_contents();, you're giving a file handle.
Try this:
file_put_contents("newFileWithText.txt", $MyNewString);
You see, when doing $var=fopen();, you're giving $var a value of a handle, which is not meant to be used with file_put_contents(); as it doesnt ask for a handle, but a filename instead. So, it should be: file_put_contents("myfilenamehere.txt", "the data i want in my file here...");
Simple.
Take a look at the documentation for str_split. It will take a string and split it into chunks based on length, storing each chunk at a separate index in an array that it returns. You can then iterate over the array adding a line break after each index.
I am generating a PDF with fPDF.
I need to strikethrough a long text inside a MultiCell. The text is justified to left and right, which probably is the source of the problem.
Here is my code:
//get the starting x and y of the cell to strikeout
$strikeout_y_start = $pdf->GetY();
$strikeout_x = $pdf->getX();
$strikeText = "Some text with no New Lines (\n), which is wrapped automaticly, cause it is very very very very very very very very very very long long long long long long long long long long long long long long long long long long"
//draw the text
$pdf->MultiCell(180, 4, $strikeText);
//get the y end of cell
$strikeout_y_end = $pdf->GetY();
$strikeout_y = $strikeout_y_start+2;
$strikeCount = 0;
for ($strikeout_y; $strikeout_y < $strikeout_y_end - 4; $strikeout_y+=4) {
$strikeCount++;
//strike out the full width of all lines but last one - works OK
$pdf->Line($strikeout_x, $strikeout_y, $strikeout_x + 180, $strikeout_y);
}
//this works, but gives incorrect results
$width = $pdf->GetStringWidth($strikeText);
$width = $width - $strikeCount*180;
//the line below will strike out some text, but not all the letters of last line
$pdf->line($strikeout_x, $strikeout_y, $strikeout_x+$width, $strikeout_y);
The problem is that as the text in multicell is justified (and have to be), the spacec in previous lines are wider than the GetStringWidth assumes, so GetStringWidth underestimates the full width of this text.
As a result, the last line is stroked out in, say, 70%, and some letters on the end of it are not stroked out.
Any ideas how to calculate the width of last line in multicell?
I found the solution myself.
Sorry for asking unnecessary questions.
Here is what I had done:
class VeraPDF extends FPDF {
/**
* Returns width of the last line in a multicell
* useful for strike out / strike through
*
*
* #param string $s - the string measured
* #param int $lineWidth - with of the cell/line
* #return int
*/
function GetStringWidth_JustifiedLastLineWidth($s, $lineWidth)
{
//Get width of a string in the current font
$s=(string)$s;
$words = split(' ',$s);
$cw=&$this->CurrentFont['cw'];
$w=0;
$spaceWidth = $this->GetStringWidth(' ');
for($i=0, $wordsCount = count($words); $i<$wordsCount; $i++){
// sum up all the words width, and add space withs between the words
$w += $this->GetStringWidth($words[$i]) + $spaceWidth;
if ($w > $lineWidth) {
//if current width is more than the line width, then the current word
//will be moved to next line, we need to count it again
$i--;
}
if ($w >= $lineWidth) {
//if the current width is equal or grater than the line width,
//we need to reset current width, and count the width of remaining text
$w = 0;
}
}
//at last, we have only the width of the text that remain on the last line!
return $w;
}
}
Hope this helped someone :)
the spacec in previous lines are wider
than the GetStringWidth assumes, so
GetStringWidth underestimates the full
width of this text.
Have you tried to count the spaces and add the missing width yourself. Say every space is supposed to be 5px wide, but fpdf etimates it to be 4px, maybe you could add 1px per space to the total width in the end.