Coder Social home page Coder Social logo

Add tFPDF compatibility about fpdi HOT 27 CLOSED

setasign avatar setasign commented on June 24, 2024
Add tFPDF compatibility

from fpdi.

Comments (27)

JanSlabon avatar JanSlabon commented on June 24, 2024 3

Ok, the POC has some missing features :-)

Change your code to:

$pdf->setSourceFile(storage_path('app/templates/plain_certificate_sh_v12.pdf'));
$templateId = $pdf->importPage(1);
$size = $pdf->getTemplateSize($templateId);
$pdf->AddPage($size['orientation'], $size);
$pdf->useTemplate($templateId);

from fpdi.

JanSlabon avatar JanSlabon commented on June 24, 2024 3

We just added a clone repository of tFPDF and added support for it in FPDIs "dev-master"-branch. Could you please test it?

We also created a metadata package. So installing it via composer this way:

"require": {
	"setasign/fpdi": "dev-master as 2.1",
	"setasign/fpdi-tfpdf": "^2.1"
}

Feedback is welcome!

from fpdi.

drjayvee avatar drjayvee commented on June 24, 2024 1

from fpdi.

drjayvee avatar drjayvee commented on June 24, 2024

I'm adding this to make the issue more verbose. From the tFPDF documentation:

This class is a modified version of FPDF that adds UTF-8 support. Moreover, it embeds only the necessary parts of the fonts that are used in the document, making the file size much smaller than if the whole fonts were embedded. These features were originally developed for the mPDF project.

I would argue that UTF-8 support is an essential feature for a modern PDF library, so I hope that FPDI adds this feature.

The latest version of tFPDF is 1.25 and is based on FPDF 1.7. FPDF's latest version is 1.81. The changes made by tFPDF are substantial, so adding compatability is most likely not as simple as applying the diff between tFPDF and FPDF 1.7 to FPDF 1.81. (I'd be happy to try, but I have no knowledge of pdf / ttf, nor are there any unit tests to guide me.)

from fpdi.

JanSlabon avatar JanSlabon commented on June 24, 2024

@drjayvee thanks for triggering this issue!

After all this is not a big deal but for an official implementation we need to offer a sync repository of tFPDF through packagist. I will see if we are going to set this up in the near future.

Until that: Use this simple class which brings back FPDI functionalities (not FpdfTpl) to tFPDF 1.25. Feedback is welcome!

from fpdi.

drjayvee avatar drjayvee commented on June 24, 2024

I was looking at the 2.0 version because we want to be ready for PHP 7.2 in the near future. We're currently using FPDI v1.4, which works fine with PHP <= 7.1, but breaks in 7.2*. Under the hood though, (t)FPDF is in dire need of modernization.

Actually, I was secretly hoping that Setasign was working towards unifying all the different PDF libs to create the one true PHP PDF library. Currently, we've got FPDI extends FPDF_TPL extends tFPDF, which is a fork of an older version of FPDF... it's a mess! One fork supports UTF-8, another one supports templates, yet another implements rounded corners, sub/sup text, etc.

From what you're saying about offering a sync repo of tFPDF, it sounds like you wish to keep FPDF_TPL / tFPDF under the hood. Is that correct? Are there plans to refactor, modernize and combine the base libraries?

I'd be happy to help, but like I said, I'm not at all familiar with the internals.

* I got an error about use of each, but now that I've looked at the code, there's only one call in FPDI v1.4. I'll take a look at newer versions.

from fpdi.

JanSlabon avatar JanSlabon commented on June 24, 2024

hoping that Setasign was working towards [...] to create the one true PHP PDF library.

That's really in our minds and on our roadmap. Last puzzles are licensing, financing and man power/time.

From what you're saying about offering a sync repo of tFPDF

We simply need this to have it in our development process via composer (require-dev).

[...]it sounds like you wish to keep FPDF_TPL / tFPDF under the hood. Is that correct?

The features of FpdfTpl are still available in FPDI 2. But not in the given class of my previous reply for tFPDF. I omit this due to the class structure which collides here again.

Are there plans to refactor, modernize and combine the base libraries?

No. We would create a complete new state of the art library.

Currently my collegue is working on a kind of proxy class which is compatible to the interface of FPDF/FPDI but uses SetaPDF in the back, which comes with font subsetting (simliar to tFPDF but much faster and more stable/tested). If you're a SetaPDF customer this thing could be a temporary solution for you, too.

from fpdi.

drjayvee avatar drjayvee commented on June 24, 2024

Great to hear you're working on a completely modernized library! Hals- & Beinbruch ;p

I guess we'll just wait until FPDI includes templating and UTF-8 before we upgrade to FPDI 2.x.

Thanks a lot for taking the time to reply.

from fpdi.

JanSlabon avatar JanSlabon commented on June 24, 2024

This version does not work for you because of the missing features of FPDF_TPL/FpdfTpl?

We're actually not working on it but have it in mind or on our roadmap.

from fpdi.

drjayvee avatar drjayvee commented on June 24, 2024

We do need template support added by FPDF_TPL (importPage, useTemplate), so Tfpdi won't work for us.

If you could bump up priority for template support, I'd be very grateful. I'd be happy to (beta) test once you have something working which supports templates and UTF-8.

from fpdi.

JanSlabon avatar JanSlabon commented on June 24, 2024

Jeroen, if you are only using importPage() and useTemplate() you're ready to go! The methods beginTemplate() and endTemplate() of FpdfTpl are missing. The main functionalities of FPDI are available! It's only the manual creation of templates which is actually missing.

from fpdi.

drjayvee avatar drjayvee commented on June 24, 2024

Jan, thanks for pointing that out! This combination works fine for our requirements.

For reference, I'm now using

class PDF extends Tfpdi {

    public function getAsString () {
        return $this->buffer;
    }

    /**
     * Draw rectangle with rouded corners
     *
     * @author Christophe Prugnaud
     * @link   http://www.fpdf.org/en/script/script35.php
     *
     * @param int    $x       x
     * @param int    $y       y
     * @param int    $w       width
     * @param int    $h       height
     * @param int    $r       radius
     * @param string $style
     * @param string $corners numbers of the corners to be rounded: 1, 2, 3, 4 or any combination (1=top left, 2=top right, 3=bottom right, 4=bottom left).
     */
    public function RoundedRect ($x, $y, $w, $h, $r, $style = '', $corners = '1234') {
        $k = $this->k;
        $hp = $this->h;
        if ($style == 'F')
            $op = 'f';
        elseif ($style == 'FD' || $style == 'DF')
            $op = 'B';
        else
            $op = 'S';
        $MyArc = 4 / 3 * (sqrt(2) - 1);
        $this->_out(sprintf('%.2F %.2F m', ($x + $r) * $k, ($hp - $y) * $k));
        $xc = $x + $w - $r;
        $yc = $y + $r;
        $this->_out(sprintf('%.2F %.2F l', $xc * $k, ($hp - $y) * $k));
        if (strpos($corners, '2') === false)
            $this->_out(sprintf('%.2F %.2F l', ($x + $w) * $k, ($hp - $y) * $k));
        else
            $this->_Arc($xc + $r * $MyArc, $yc - $r, $xc + $r, $yc - $r * $MyArc, $xc + $r, $yc);

        $xc = $x + $w - $r;
        $yc = $y + $h - $r;
        $this->_out(sprintf('%.2F %.2F l', ($x + $w) * $k, ($hp - $yc) * $k));
        if (strpos($corners, '3') === false)
            $this->_out(sprintf('%.2F %.2F l', ($x + $w) * $k, ($hp - ($y + $h)) * $k));
        else
            $this->_Arc($xc + $r, $yc + $r * $MyArc, $xc + $r * $MyArc, $yc + $r, $xc, $yc + $r);

        $xc = $x + $r;
        $yc = $y + $h - $r;
        $this->_out(sprintf('%.2F %.2F l', $xc * $k, ($hp - ($y + $h)) * $k));
        if (strpos($corners, '4') === false)
            $this->_out(sprintf('%.2F %.2F l', ($x) * $k, ($hp - ($y + $h)) * $k));
        else
            $this->_Arc($xc - $r * $MyArc, $yc + $r, $xc - $r, $yc + $r * $MyArc, $xc - $r, $yc);

        $xc = $x + $r;
        $yc = $y + $r;
        $this->_out(sprintf('%.2F %.2F l', ($x) * $k, ($hp - $yc) * $k));
        if (strpos($corners, '1') === false) {
            $this->_out(sprintf('%.2F %.2F l', ($x) * $k, ($hp - $y) * $k));
            $this->_out(sprintf('%.2F %.2F l', ($x + $r) * $k, ($hp - $y) * $k));
        } else
            $this->_Arc($xc - $r, $yc - $r * $MyArc, $xc - $r * $MyArc, $yc - $r, $xc, $yc - $r);
        $this->_out($op);
    }

    protected function _Arc ($x1, $y1, $x2, $y2, $x3, $y3) {
        $h = $this->h;
        $this->_out(sprintf('%.2F %.2F %.2F %.2F %.2F %.2F c ', $x1 * $this->k, ($h - $y1) * $this->k,
            $x2 * $this->k, ($h - $y2) * $this->k, $x3 * $this->k, ($h - $y3) * $this->k));
    }
    
    /**
     * This function properly handles <sub>, <sup> tags in strings.
     * And prints the string on current x,y coordinates on this pdf.
     *
     * @param    string $string    might contain sub/sup tags
     */
    public function printSubSupString ( $string ) {
        if ( strstr($string, '<sup>') || strstr($string, '<sub>') ) {
            for( $i=0; $i<strlen($string); $i++ ) {
                if ( $string[$i] === '<' ) {
                    if ( substr($string, $i, 5) === '<sub>' ) {
                        $textPart = substr($string, $i+5, strpos($string, '</su', $i)-($i+5) );
                        $this->subSupWrite(5, $textPart, '', 7, -4 );
                        $i = strpos($string, '</su', $i)+5;
                    } elseif ( substr($string, $i, 5) === '<sup>' ) {
                        $textPart = substr($string, $i+5, (strpos($string, '</su', $i)-($i+5)) );
                        $this->subSupWrite(5, $textPart, '', 7, 4 );
                        $i = strpos($string, '</su', $i)+5;
                    }
                } else {
                    $char = mb_substr( $string, $i, 1 );    // ensure $char can contain multibyte chars
                    $this->Write(5, $char );
                }
            }
        } else {
            $this->Write(5, $string );
        }
    }
    
    /**
     * Output sub or sup text
     *
     * @link    http://www.fpdf.org/en/script/script61.php
     * @author    Wirus
     *
     * @param     int        $h                height
     * @param     string     $txt            text
     * @param     string     $link            link
     * @param     int     $subFontSize    fontSize
     * @param     int     $subOffset        offset, >0 for sup, <0 for sub.
     *                                     (4 is suggested as default offset)
     */
    public function subSupWrite ( $h, $txt, $link='', $subFontSize=12, $subOffset=0 ) {
        // resize font
        $subFontSizeold = $this->FontSizePt;
        $this->SetFontSize($subFontSize);
        
        // reposition y
        $subOffset = ((($subFontSize - $subFontSizeold) / $this->k) * 0.3) + ($subOffset / $this->k);
        $subX        = $this->x;
        $subY        = $this->y;
        $this->SetXY( $subX, ($subY - $subOffset) );
    
        //Output text
        $this->Write( $h, $txt, $link );
    
        // restore y position
        $subX        = $this->x;
        $subY        = $this->y;
        $this->SetXY( $subX, ($subY + $subOffset) );
    
        // restore font size
        $this->SetFontSize( $subFontSizeold );
    }
    
    /*
     * ensure $txt is string
     */
    public function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='') {
        parent::Cell($w, $h, (string)$txt, $border, $ln, $align, $fill, $link);
    }

    function Error($msg) {
        throw new \Exception($msg);
    }
}

I'd love to add these to Fpdi through a PR. Interested?

from fpdi.

JanSlabon avatar JanSlabon commented on June 24, 2024

Thanks for the PR offer but these this has nothing to do with FPDI and should be implemented individually in an extending class. We leave this issue open until tFPDF support is available by default.

from fpdi.

drjayvee avatar drjayvee commented on June 24, 2024

from fpdi.

MartinMa avatar MartinMa commented on June 24, 2024

There is an unofficial composer package of tFPDF.

@JanSlabon I only use importPage() and useTemplate(). So I will try updating to the new version of FPDI using your workaround. Thanks.

Worth mentioning. There seems to be an alternative to tFPDF called TCPDF, which is supported by FPDI by using the class \setasign\Fpdi\TcpdfFpdi. Feature-wise, I don't know the difference between tFPDF and TCPDF, but they both seem to support UTF-8 and font subsetting.

from fpdi.

JanSlabon avatar JanSlabon commented on June 24, 2024

This unofficial repo is far away from the official release.
Feel free to use the POC I mentioned some posts above. There will be a simliar official solution as we have for TCPDF.

from fpdi.

iwasherefirst2 avatar iwasherefirst2 commented on June 24, 2024

@JanSlabon thank you for the workaround. But how do you actually include the tFPDF package? As you already mentioned, there exists no repository of tFPDF through packagist. I have problems with the unoffical tFPDF package mentioned from MartinMa, because for some reason all function names have been renamed, so this won't work with old scripts.

Your class starts with class Tfpdi extends \tFPDF so I assume you include it with composer autoload? I tried that too, but its not working, see https://stackoverflow.com/questions/51388856/adding-tfpdf-class-with-composer

Looking forward to a solution since I need UTF-8 and I need to import a PDF. Thanks for your help !

from fpdi.

JanSlabon avatar JanSlabon commented on June 24, 2024

You shall never add any foreign package to the vendor folder!

Just create your own library folder and place tFPDF in there and require it when you need it. You may call it "legacy style" but it works, too ;-)

from fpdi.

iwasherefirst2 avatar iwasherefirst2 commented on June 24, 2024

@JanSlabon okay I managed to include the tFPDF package with composer as explained here.

I added your workaround package in the folder vendor/setasign/fpdi/src/. Then I tried to import with that class only one template like this:


  $pdf->AddPage('L');
  $pdf->setSourceFile(storage_path('app/templates/plain_certificate_sh_v12.pdf'));
  $templateId = $pdf->importPage(1);
  $pdf->useTemplate($templateId, ['adjustPageSize' => true]);

But I get the error

Call to undefined method setasign\Fpdi\Tfpdi::setPageFormat()

image

Am I doing anything wrong here?

Edit: Whoups didn't see you answer! Thank you for the quick response! I will put it the folder outside vendor then.

from fpdi.

iwasherefirst2 avatar iwasherefirst2 commented on June 24, 2024

@JanSlabon Thank you! That worked :)!!!

from fpdi.

JanSlabon avatar JanSlabon commented on June 24, 2024

Implemented and new release 2.1 will support tFPDF by default.

from fpdi.

MartinMa avatar MartinMa commented on June 24, 2024

Thanks a lot! Didn't had the time to test yet. Will try this weekend. The workaround, however, worked perfectly. So I guess this will be just fine, too.

from fpdi.

drjayvee avatar drjayvee commented on June 24, 2024

Great, this (setasign\Fpdi\Tfpdf\Fpdi) works out of the box for us!

Does "2.1 will support tFPDF by default" mean users won't have to add an additional dependency (setasign/fpdi-tfpdf)? I would very much encourage that, for reasons that I've outlined above. :)

from fpdi.

JanSlabon avatar JanSlabon commented on June 24, 2024

Does "2.1 will support tFPDF by default" mean users won't have to add an additional dependency (setasign/fpdi-tfpdf)?

No. It's the other way round: Remove the dependency setasign/fpdi but use setasign/fpdi-tfpdf directly to evaluate the dependencies between tFPDF and FPDI. FPDI itself can be used with 3 different things now (FPDF, TCPDF, tFPDF). It wouldn't make sense to setup the dependency in FPDI then.

from fpdi.

JanSlabon avatar JanSlabon commented on June 24, 2024

FPDI comes not with a single method which would allow you to write text. Why should anybody think that it supports UTF-8 by default then?

from fpdi.

drjayvee avatar drjayvee commented on June 24, 2024

Oh really! :D I guess I'm confused then, sorry about that!

Between tFPDF, FPDI, FPDF_TPL, TCPDF, there are so many names (classes/packages/extensions/???) that I don't know which does what.

I would hope that one day there's a PDF library that has all the functionality (templates, UTF-8 support with font subsetting, etc) incorporated. Maybe that's a pipe dream.

For now, fpdi-tfpdf is exactly what we need, so thanks again for that.

from fpdi.

JanSlabon avatar JanSlabon commented on June 24, 2024

@iwasherefirst2 Feel free to open a new issue and provide all required details so that we are able to reproduce your issue and please do not highjack already closed issues. "setasign/fpdi-tfpdf" is a dependency in your composer.json and for sure not a class name!

from fpdi.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.