Search code examples
phpfpdfstrikethrough

fPDF: how to strikeout/strikethrough justified text in multicell?


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?


Solution

  • 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 :)