tcpdf

// appunti sul API tcpdf
<?php
namespace PDFEtichettaFornitori {

    
//----------------------------------------------------------------------------
    //
    //----------------------------------------------------------------------------

    // ritorna paginate di label data
    class ItemValRecPager {
        const 
LABEL_NUM_PER_PAGE 10;
        protected 
$data = [];
        
// quante pagine ha il report
        public function getPagesCount() {
            return 
ceil(count($this->data) / self::LABEL_NUM_PER_PAGE );
        }
        public function 
getRecordByIdx($idx) {
            if (isset(
$this->data[$idx])) {
                return 
$this->data[$idx];
            }
            return 
null;
        }

        
// real data from database
        public function initData(array $a_rec) {
            foreach (
$a_rec as $rec) {
                
$this->data[] = new ItemValRec($rec);
            }
        }

        
//----------------------------------------------------------------------------
        //  test data generator
        //----------------------------------------------------------------------------
        // random test data
        public function initRandomData($num_etichette) {
            for (
$i 0$i $num_etichette$i++) {
                
$rec = [
                    
'code' => 'QC12345C',
                    
'image' => self::getRandImg(),
                    
'color' => 'Grigio-Nero / Grey-Black',
                    
'barcode' => '8058129030004',
                    
'lotto' => '22187',
                    
'compat_list' => self::getCompatList(),
                ];
                
$this->data[] = new ItemValRec($rec);
            }
        }
        protected static function 
getRandImg() {
            
$a_images = [
                
'QF38004.jpg'// ratio:2
                'QG37133.jpg'// ratio:3
            ];
            
$rand_i rand(0count($a_images) - 1);
            return 
$a_images[$rand_i];
        }
        
// genera una lista casuale di compatibilità auto
        protected static function getCompatList() {
            
$a_compat = [];
            static 
$c 1;
            
$c++;
            
$c min($c8); // al massimo 8 label
            for ($i 0$i $c$i++) {
                
$a_compat[] = "DACIA DUSTER 0$i/10>05/12";
            }
            return 
$a_compat;
        }
    }

    
// mantiene i valori da stampare nell'etichetta
    // eventuali formattazioni o elaborazioni sui dati
    class ItemValRec {
        protected 
$code;
        protected 
$image;
        protected 
$color;
        protected 
$barcode;
        protected 
$lotto;
        protected 
$compat_list;
        function 
__construct(array $values) {
            
$this->code $values['code'];
            
$this->image $values['image'];
            
$this->color $values['color'];
            
$this->barcode $values['barcode'];
            
$this->lotto $values['lotto'];
            
$this->compat_list $values['compat_list'];
        }
        public function 
getCode() {
            return 
$this->code;
        }
        function 
getImg() {
            return 
sprintf('%s/../../data/img/%s'__DIR__$this->image);
        }
        public function 
getColor() {
            return 
$this->color;
        }
        public function 
getBarCode() {
            return 
$this->barcode;
        }
        public function 
getLotto() {
            return 
$this->lotto;
        }
        public function 
getCompatList() {
            return 
$this->compat_list;
        }
    }

    class 
LabelPDFGenerator {
        var 
$debug false;
        public function 
__construct($debug=false) {
            
$this->debug $debug;
            
define('K_TCPDF_THROW_EXCEPTION_ERROR'true );
            
//
            ini_set("memory_limit",-1);
            
set_time_limit(0);
            
// create new PDF document
            $this->= new \TCPDF(
                
$orientation=PDF_PAGE_ORIENTATION$unit='mm'$format='A4'$unicode=true,
                
$encoding='UTF-8'$diskcache=false$pdfa=false
            
);

            
// remove header and footer
            $this->P->setPrintHeader(false);
            
$this->P->setPrintFooter(false);

            
// set margins
            $this->P->SetMargins($left=0$top=0$right=0$keepmargins=true);
            
// set auto page breaks false, altrimenti se "lotto" sfora, tcpd lo piazza in una nuova pagina
            $this->P->SetAutoPageBreak(false0);

            
// set image
            $this->P->setImageScale(PDF_IMAGE_SCALE_RATIO);
            
$this->P->setJPEGQuality(100);

            
// set font
            $this->P->SetFont('helvetica'''8.5);
            
$this->P->setCellMargins($left 0$top 0$right 0$bottom 0);
            
// set default monospaced font
            $this->P->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
        }

        
//------------------------------------------------------------------------------
        // genera il pdf in memoria, successivamente va chiamata una funzione di output
        public function generate(ItemValRecPager $data_pager) {
            
$x 0// orizzontale
            $y 0// verticale
            $idx 0// contatore record corrente
            $label_num_per_col = (ItemValRecPager::LABEL_NUM_PER_PAGE 2) -1// numero di etichette per collonna, meno 1 perché array parte con 0 che indica la prima etichetta
            for ($page_i 0$page_i $data_pager->getPagesCount(); $page_i++) {
                
// add a page
                $this->addPage();

                
$y_label_offset 57;
                
$y_range range(0$label_num_per_col $y_label_offset$y_label_offset); //[10,20,30,40,50]
                foreach ($y_range as $y) {
                    foreach ([
10115] as $x) { // cicla per la collonna 0 e 110
                        $this->generateLabel($x$y$item=$data_pager->getRecordByIdx($idx));
                        
$idx++;
                    }
                }
            }
        }
        public function 
saveToFile($file_path) {
            
// Close and output PDF document to a file
            $this->P->Output($file_path'F');
        }
        public function 
download() {
            
// Close and output PDF document to a file, I => inline download
            $this->P->Output('''I');
        }
        
//----------------------------------------------------------------------------
        //  sub generators
        //----------------------------------------------------------------------------
        function generateLabel($x$yItemValRec $item null) {
            if (empty(
$item)) {
                return; 
// no op
            }
            
$x_initial $x//conserva posizione di partenza
            $y_initial $y//conserva posizione di partenza
            $this->addText('Art.' $item->getCode(), $x$y, ['style' => 'B']);
            
$this->addText('Set fodere SUPERIOR per / SUPERIOR seat cover for'$x$y += 3.5);
            
//
            $a_compat $item->getCompatList();
            list(
$y_compat_label_offset$compat_label_fontsize) = $this->getCompatListSizeVariant($a_compat);
            foreach (
$a_compat as $i => $str_compat) {
                
$label_y $y $y_compat_label_offset + ($i $y_compat_label_offset);
                
$this->addText($str_compat$x$label_y, ['size' => $compat_label_fontsize]);
            }
            
// resetta y per gestire il fatto che il numero di auto compatibili varia da 1 a x
            $y $y 24;
            
$this->addText($item->getColor(), $x$y, ['style' => 'B']);
            
$this->addBarcode($item->getBarCode(), $x$y += 15);
            
$y_before_barcode $y;
            
//
            $this->addText('Lotto: ' $item->getLotto(), $x$y-1.5, ['size' => 6.5]);
            
// Image example with resizing
            $file_name $item->getImg();
            
$x_col2 $x 42;
            
// dimensioni immagine
            $aspect_ratio self::getAspectRatio($file_name);
            
$h 15;
            
$w = ($h $aspect_ratio);
            
$w round($w3);
            
//
            $this->addImage($file_name$x_col2$y_before_barcode$w$h);
            
//
            // corner crop marks
            $h $x_initial == 10 40//sulla prima colonna corto, altrimenti lungo
            //// $this->addCropMark($x - 5, $y_before_barcode + 18, $t = 'TR', $h); // bottom-left mark

        }

        
// da un filename ricava l'aspect ration $w/$h
        public static function getAspectRatio($file_name) {
            
$a_size getimagesize($file_name);
            
$w $a_size[0];
            
$h $a_size[1];
            if (!empty(
$w) && !empty($h)) {
                return 
$w $h;
            } else {
                return 
1;
            }
        }
        
// la grandezza del font, e quindi dell'interlinea dipendono da quante compatibilità veicolo sono presenti
        // gestisce fino a 8 labels
        public function getCompatListSizeVariant(array $a_compat) {
            
$c count($a_compat);
            if (
$c >= 8) {
                
$y_compat_label_offset 2.5;
                
$compat_label_fontsize 5.5;
            } elseif (
$c == 7) {
                
$y_compat_label_offset 3;
                
$compat_label_fontsize 6;
            } elseif (
$c == 6) {
                
$y_compat_label_offset 3.5;
                
$compat_label_fontsize 6.5;
            } elseif (
$c == 5) {
                
$y_compat_label_offset 4;
                
$compat_label_fontsize 7;
            } else { 
// 4 o meno
                $y_compat_label_offset 5;
                
$compat_label_fontsize 8;
            }
            return [
$y_compat_label_offset$compat_label_fontsize];
        }
        
//----------------------------------------------------------------------------
        // utils
        //----------------------------------------------------------------------------
        function addPage(){
            
$this->P->AddPage();
            if( 
$this->debug ){
                
// Display image on full page
                $bg_img_path =  __DIR__.'/../../public/img/BG.png';
                
$autocalc=0;// w h auto
                $this->P->Image(
                    
$bg_img_path$x=0$y=0$w=210$h=297$type='PNG'
                    
,$link=''$align=''$resize=false$dpi=300$palign='',
                    
$ismask=false$imgmask=false$border=0$fitbox=false$hidden=false$fitonpage=true,
                    
$alt=false$altimgs=[]
                    );
            }
        }
        function 
addText($txt$x$y, array $opt = []) {
            
$option array_merge([
                
'size' => 8.5,
                
// $style = BI B= bold I=italic
                'style' => '',
            ], 
$opt);
            
extract($option);
            
// set font
            $this->P->SetFont($family 'helvetica'$style$size);
            
$this->P->SetXY($x$y);
            
$this->P->Cell(
                
$w 63.5$h 33$txt$border 0$ln 0$align 'L'$fill false$link ''$stretch 0$ignore_min_height false$calign 'C'$valign 'B'
            
);
        }
        function 
addLongText() {
            
// print a message
            // $txt = "";
            // $this->P->MultiCell(70, 50, $txt, 0, 'J', false, 1, 125, 30, true, 0, false, true, 0, 'T', false);
            // $this->P->SetY(30);
        }
        function 
addBarcode($code$x$y$w 43$h 15) {
            
$this->P->SetXY($x$y);
            
// The width is set to the the same as the cell containing the name.
            // The Y position is also adjusted slightly.
            // define barcode style
            // Reset X,Y so wrapping cell wraps around the barcode's cell.
            $style = [
                
'position' => '',
                
'align' => 'L',
                
'stretch' => false,
                
'fitwidth' => false,
                
'cellfitalign' => '',
                
'border' => false,
                
'hpadding' => 'auto',
                
'vpadding' => 'auto',
                
'fgcolor' => [000],
                
'bgcolor' => false//[255,255,255],
                'text' => true,
                
'font' => 'helvetica',
                
'fontsize' => 7,
                
'stretchtext' => 0,
            ];
            
$this->P->write1DBarcode(
                
$code$type 'EAN13'$x$y$w$h$xres 0.4$style$align 'L'
            
);
        }
        function 
addImage($file_name$x$y$w$h) {
            
$this->P->Image(
                
$file_name$x$y,
                
$w,
                
$h,
                
$type 'JPG'$link '',
                
$align ''$resize false$dpi 300$palign ''$ismask false,
                
$imgmask false$border 0$fitbox false$hidden false$fitonpage false,
                
$alt false$altimgs = []
            );
        }
        public function 
addCropMark($x$y$t$h 60$c_gray = [192192192]) {
            
$this->P->cropMark($x$y$w 80$h$t$c_gray); // bottom-right mark
        }
    }
}
//----------------------------------------------------------------------------
// main
//----------------------------------------------------------------------------
namespace {
    require_once 
__DIR__.'/../application/lib/PDFEtichettaFornitori.php';
    require_once 
__DIR__ '/../vendor/autoload.php';
    
date_default_timezone_set('Europe/Rome');
    
// init numero random data da stampare
    $num_etichette = (isset($_SERVER['argv'][1])) ? $_SERVER['argv'][1] : rand(124);
    
$data_pager = new \PDFEtichettaFornitori\ItemValRecPager();
    
$data_pager->initRandomData($num_etichette);
    
//
    $pdf_gen = new \PDFEtichettaFornitori\LabelPDFGenerator($debug=true );
    
$pdf_gen->generate($data_pager);
    
$file_path __DIR__ '/barcodes.pdf';
    
$pdf_gen->saveToFile($file_path);
}
# pacchetti accessori necessari al funzionamento PDF
#  sudo apt-get install texlive-latex-base
#  sudo apt-get install texlive-xetex
#  sudo apt-get install texlive-fonts-recommended
#  sudo apt-get install texlive-latex-extra
 
# markdown to html
pandoc  -s   \
  -H ./manual.css \
  --from markdown_phpextra+footnotes+inline_code_attributes+fenced_code_attributes+grid_tables \
  --highlight-style kate   \
  -A ./footer.md \
  --to html ./index.md > ./_maual.html
# markdown to PDF
pandoc --toc ./index.md --latex-engine=xelatex -o example13.pdf

css @media: print debug