did not output top margins/padding for 1st/2nd div if ($array_size == 0) { $this->finishFlowingBlock(true); } // true = END of flowing block // mPDF 6 // ALL the chunks of textbuffer need to have at least basic OTLdata set // First make sure each element/chunk has the OTLdata for Bidi set. for ($i = 0; $i < $array_size; $i++) { if (empty($arrayaux[$i][18])) { if (substr($arrayaux[$i][0], 0, 3) == "\xbb\xa4\xac") { // object identifier has been identified! $unicode = [0xFFFC]; // Object replacement character } else { $unicode = $this->UTF8StringToArray($arrayaux[$i][0], false); } $is_strong = false; $this->getBasicOTLdata($arrayaux[$i][18], $unicode, $is_strong); } // Gets messed up if try and use core fonts inside a paragraph of text which needs to be BiDi re-ordered or OTLdata set if (($blockdir == 'rtl' || $this->biDirectional) && isset($arrayaux[$i][4]) && in_array($arrayaux[$i][4], ['ccourier', 'ctimes', 'chelvetica', 'csymbol', 'czapfdingbats'])) { throw new \Mpdf\MpdfException("You cannot use core fonts in a document which contains RTL text."); } } // mPDF 6 // Process bidirectional text ready for bidi-re-ordering (which is done after line-breaks are established in WriteFlowingBlock etc.) if (($blockdir == 'rtl' || $this->biDirectional) && !$table_draft) { if (empty($this->otl)) { $this->otl = new Otl($this, $this->fontCache); } $this->otl->bidiPrepare($arrayaux, $blockdir); $array_size = count($arrayaux); } // Remove empty items // mPDF 6 for ($i = $array_size - 1; $i > 0; $i--) { if (empty($arrayaux[$i][0]) && (isset($arrayaux[$i][16]) && $arrayaux[$i][16] !== '0') && empty($arrayaux[$i][7])) { unset($arrayaux[$i]); } } // Correct adjoining borders for inline elements if (isset($arrayaux[0][16])) { $lastspanborder = $arrayaux[0][16]; } else { $lastspanborder = false; } for ($i = 1; $i < $array_size; $i++) { if (isset($arrayaux[$i][16]) && $arrayaux[$i][16] == $lastspanborder && ((!isset($arrayaux[$i][9]['bord-decoration']) && !isset($arrayaux[$i - 1][9]['bord-decoration'])) || (isset($arrayaux[$i][9]['bord-decoration']) && isset($arrayaux[$i - 1][9]['bord-decoration']) && $arrayaux[$i][9]['bord-decoration'] == $arrayaux[$i - 1][9]['bord-decoration']) ) ) { if (isset($arrayaux[$i][16]['R'])) { $lastspanborder = $arrayaux[$i][16]; } else { $lastspanborder = false; } $arrayaux[$i][16]['L']['s'] = 0; $arrayaux[$i][16]['L']['w'] = 0; $arrayaux[$i - 1][16]['R']['s'] = 0; $arrayaux[$i - 1][16]['R']['w'] = 0; } else { if (isset($arrayaux[$i][16]['R'])) { $lastspanborder = $arrayaux[$i][16]; } else { $lastspanborder = false; } } } for ($i = 0; $i < $array_size; $i++) { // COLS $oldcolumn = $this->CurrCol; $vetor = isset($arrayaux[$i]) ? $arrayaux[$i] : null; if ($i == 0 && $vetor[0] != "\n" && ! $this->ispre) { $vetor[0] = ltrim($vetor[0]); if (!empty($vetor[18])) { $this->otl->trimOTLdata($vetor[18], true, false); } // *OTL* } // FIXED TO ALLOW IT TO SHOW '0' if (empty($vetor[0]) && !($vetor[0] === '0') && empty($vetor[7])) { // Ignore empty text and not carrying an internal link // Check if it is the last element. If so then finish printing the block if ($i == ($array_size - 1)) { $this->finishFlowingBlock(true); } // true = END of flowing block continue; } // Activating buffer properties if (isset($vetor[11]) && $vetor[11] != '') { // Font Size if ($is_table && $this->shrin_k) { $this->SetFontSize($vetor[11] / $this->shrin_k, false); } else { $this->SetFontSize($vetor[11], false); } } if (isset($vetor[17]) && !empty($vetor[17])) { // TextShadow $this->textshadow = $vetor[17]; } if (isset($vetor[16]) && !empty($vetor[16])) { // Border $this->spanborddet = $vetor[16]; $this->spanborder = true; } if (isset($vetor[15])) { // Word spacing $this->wSpacingCSS = $vetor[15]; if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') { $this->minwSpacing = $this->sizeConverter->convert($this->wSpacingCSS, $this->FontSize) / $this->shrin_k; // mPDF 5.7.3 } } if (isset($vetor[14])) { // Letter spacing $this->lSpacingCSS = $vetor[14]; if (($this->lSpacingCSS || $this->lSpacingCSS === '0') && strtoupper($this->lSpacingCSS) != 'NORMAL') { $this->fixedlSpacing = $this->sizeConverter->convert($this->lSpacingCSS, $this->FontSize) / $this->shrin_k; // mPDF 5.7.3 } } if (isset($vetor[10]) and ! empty($vetor[10])) { // Background color $this->spanbgcolorarray = $vetor[10]; $this->spanbgcolor = true; } if (isset($vetor[9]) and ! empty($vetor[9])) { // Text parameters - Outline + hyphens $this->textparam = $vetor[9]; $this->SetTextOutline($this->textparam); // mPDF 5.7.3 inline text-decoration parameters if ($is_table && $this->shrin_k) { if (isset($this->textparam['text-baseline'])) { $this->textparam['text-baseline'] /= $this->shrin_k; } if (isset($this->textparam['decoration-baseline'])) { $this->textparam['decoration-baseline'] /= $this->shrin_k; } if (isset($this->textparam['decoration-fontsize'])) { $this->textparam['decoration-fontsize'] /= $this->shrin_k; } } } if (isset($vetor[8])) { // mPDF 5.7.1 $this->textvar = $vetor[8]; } if (isset($vetor[7]) and $vetor[7] != '') { // internal target: $ily = $this->y; if ($this->table_rotate) { $this->internallink[$vetor[7]] = ["Y" => $ily, "PAGE" => $this->page, "tbrot" => true]; } elseif ($this->kwt) { $this->internallink[$vetor[7]] = ["Y" => $ily, "PAGE" => $this->page, "kwt" => true]; } elseif ($this->ColActive) { $this->internallink[$vetor[7]] = ["Y" => $ily, "PAGE" => $this->page, "col" => $this->CurrCol]; } elseif (!$this->keep_block_together) { $this->internallink[$vetor[7]] = ["Y" => $ily, "PAGE" => $this->page]; } if (empty($vetor[0])) { // Ignore empty text // Check if it is the last element. If so then finish printing the block if ($i == ($array_size - 1)) { $this->finishFlowingBlock(true); } // true = END of flowing block continue; } } if (isset($vetor[5]) and $vetor[5] != '') { // Language // mPDF 6 $this->currentLang = $vetor[5]; } if (isset($vetor[4]) and $vetor[4] != '') { // Font Family $font = $this->SetFont($vetor[4], $this->FontStyle, 0, false); } if (!empty($vetor[3])) { // Font Color $cor = $vetor[3]; $this->SetTColor($cor); } if (isset($vetor[2]) and $vetor[2] != '') { // Bold,Italic styles $this->SetStyles($vetor[2]); } if (isset($vetor[12]) and $vetor[12] != '') { // Requested Bold,Italic $this->ReqFontStyle = $vetor[12]; } if (isset($vetor[1]) and $vetor[1] != '') { // LINK if (strpos($vetor[1], ".") === false && strpos($vetor[1], "@") !== 0) { // assuming every external link has a dot indicating extension (e.g: .html .txt .zip www.somewhere.com etc.) // Repeated reference to same anchor? while (array_key_exists($vetor[1], $this->internallink)) { $vetor[1] = "#" . $vetor[1]; } $this->internallink[$vetor[1]] = $this->AddLink(); $vetor[1] = $this->internallink[$vetor[1]]; } $this->HREF = $vetor[1]; // HREF link style set here ****** } // SPECIAL CONTENT - IMAGES & FORM OBJECTS // Print-out special content if (substr($vetor[0], 0, 3) == "\xbb\xa4\xac") { // identifier has been identified! $objattr = $this->_getObjAttr($vetor[0]); /* -- TABLES -- */ if ($objattr['type'] == 'nestedtable') { if ($objattr['nestedcontent']) { $level = $objattr['level']; $table = &$this->table[$level][$objattr['table']]; if ($table_draft) { $this->y += $this->table[($level + 1)][$objattr['nestedcontent']]['h']; // nested table height $this->finishFlowingBlock(false, 'nestedtable'); } else { $cell = &$table['cells'][$objattr['row']][$objattr['col']]; $this->finishFlowingBlock(false, 'nestedtable'); $save_dw = $this->divwidth; $save_buffer = $this->cellBorderBuffer; $this->cellBorderBuffer = []; $ncx = $this->x; list($dummyx, $w) = $this->_tableGetWidth($table, $objattr['row'], $objattr['col']); $ntw = $this->table[($level + 1)][$objattr['nestedcontent']]['w']; // nested table width if (!$this->simpleTables) { if ($this->packTableData) { list($bt, $br, $bb, $bl) = $this->_getBorderWidths($cell['borderbin']); } else { $br = $cell['border_details']['R']['w']; $bl = $cell['border_details']['L']['w']; } if ($table['borders_separate']) { $innerw = $w - $bl - $br - $cell['padding']['L'] - $cell['padding']['R'] - $table['border_spacing_H']; } else { $innerw = $w - $bl / 2 - $br / 2 - $cell['padding']['L'] - $cell['padding']['R']; } } elseif ($this->simpleTables) { if ($table['borders_separate']) { $innerw = $w - $table['simple']['border_details']['L']['w'] - $table['simple']['border_details']['R']['w'] - $cell['padding']['L'] - $cell['padding']['R'] - $table['border_spacing_H']; } else { $innerw = $w - $table['simple']['border_details']['L']['w'] / 2 - $table['simple']['border_details']['R']['w'] / 2 - $cell['padding']['L'] - $cell['padding']['R']; } } if ($cell['a'] == 'C' || $this->table[($level + 1)][$objattr['nestedcontent']]['a'] == 'C') { $ncx += ($innerw - $ntw) / 2; } elseif ($cell['a'] == 'R' || $this->table[($level + 1)][$objattr['nestedcontent']]['a'] == 'R') { $ncx += $innerw - $ntw; } $this->x = $ncx; $this->_tableWrite($this->table[($level + 1)][$objattr['nestedcontent']]); $this->cellBorderBuffer = $save_buffer; $this->x = $bak_x; $this->divwidth = $save_dw; } $this->newFlowingBlock($this->divwidth, $this->divheight, $align, $is_table, $blockstate, false, $blockdir, $table_draft); } } else { /* -- END TABLES -- */ if ($is_table) { // *TABLES* $maxWidth = $this->divwidth; // *TABLES* } // *TABLES* else { // *TABLES* $maxWidth = $this->divwidth - ($this->blk[$this->blklvl]['padding_left'] + $this->blk[$this->blklvl]['border_left']['w'] + $this->blk[$this->blklvl]['padding_right'] + $this->blk[$this->blklvl]['border_right']['w']); } // *TABLES* /* -- CSS-IMAGE-FLOAT -- */ // If float (already) exists at this level if (isset($this->floatmargins['R']) && $this->y <= $this->floatmargins['R']['y1'] && $this->y >= $this->floatmargins['R']['y0']) { $maxWidth -= $this->floatmargins['R']['w']; } if (isset($this->floatmargins['L']) && $this->y <= $this->floatmargins['L']['y1'] && $this->y >= $this->floatmargins['L']['y0']) { $maxWidth -= $this->floatmargins['L']['w']; } /* -- END CSS-IMAGE-FLOAT -- */ list($skipln) = $this->inlineObject($objattr['type'], '', $this->y, $objattr, $this->lMargin, ($this->flowingBlockAttr['contentWidth'] / Mpdf::SCALE), $maxWidth, $this->flowingBlockAttr['height'], false, $is_table); // 1 -> New line needed because of width // -1 -> Will fit width on line but NEW PAGE REQUIRED because of height // -2 -> Will not fit on line therefore needs new line but thus NEW PAGE REQUIRED $iby = $this->y; $oldpage = $this->page; $oldcol = $this->CurrCol; if (($skipln == 1 || $skipln == -2) && !isset($objattr['float'])) { $this->finishFlowingBlock(false, $objattr['type']); $this->newFlowingBlock($this->divwidth, $this->divheight, $align, $is_table, $blockstate, false, $blockdir, $table_draft); } if (!$table_draft) { $thispage = $this->page; if ($this->CurrCol != $oldcol) { $changedcol = true; } else { $changedcol = false; } // the previous lines can already have triggered page break or column change if (!$changedcol && $skipln < 0 && $this->AcceptPageBreak() && $thispage == $oldpage) { $this->AddPage($this->CurOrientation); // Added to correct Images already set on line before page advanced // i.e. if second inline image on line is higher than first and forces new page if (count($this->objectbuffer)) { $yadj = $iby - $this->y; foreach ($this->objectbuffer as $ib => $val) { if ($this->objectbuffer[$ib]['OUTER-Y']) { $this->objectbuffer[$ib]['OUTER-Y'] -= $yadj; } if ($this->objectbuffer[$ib]['BORDER-Y']) { $this->objectbuffer[$ib]['BORDER-Y'] -= $yadj; } if ($this->objectbuffer[$ib]['INNER-Y']) { $this->objectbuffer[$ib]['INNER-Y'] -= $yadj; } } } } // Added to correct for OddEven Margins if ($this->page != $oldpage) { if (($this->page - $oldpage) % 2 == 1) { $bak_x += $this->MarginCorrection; } $oldpage = $this->page; $y = $this->tMargin - $paint_ht_corr; $this->oldy = $this->tMargin - $paint_ht_corr; $old_height = 0; } $this->x = $bak_x; /* -- COLUMNS -- */ // COLS // OR COLUMN CHANGE if ($this->CurrCol != $oldcolumn) { if ($this->directionality == 'rtl') { // *OTL* $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); // *OTL* } // *OTL* else { // *OTL* $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); } // *OTL* $this->x = $bak_x; $oldcolumn = $this->CurrCol; $y = $this->y0 - $paint_ht_corr; $this->oldy = $this->y0 - $paint_ht_corr; $old_height = 0; } /* -- END COLUMNS -- */ } /* -- CSS-IMAGE-FLOAT -- */ if ($objattr['type'] == 'image' && isset($objattr['float'])) { $fy = $this->y; // DIV TOP MARGIN/BORDER/PADDING if ($this->flowingBlockAttr['newblock'] && ($this->flowingBlockAttr['blockstate'] == 1 || $this->flowingBlockAttr['blockstate'] == 3) && $this->flowingBlockAttr['lineCount'] == 0) { $fy += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w']; } if ($objattr['float'] == 'R') { $fx = $this->w - $this->rMargin - $objattr['width'] - ($this->blk[$this->blklvl]['outer_right_margin'] + $this->blk[$this->blklvl]['border_right']['w'] + $this->blk[$this->blklvl]['padding_right']); } elseif ($objattr['float'] == 'L') { $fx = $this->lMargin + ($this->blk[$this->blklvl]['outer_left_margin'] + $this->blk[$this->blklvl]['border_left']['w'] + $this->blk[$this->blklvl]['padding_left']); } $w = $objattr['width']; $h = abs($objattr['height']); $widthLeft = $maxWidth - ($this->flowingBlockAttr['contentWidth'] / Mpdf::SCALE); $maxHeight = $this->h - ($this->tMargin + $this->margin_header + $this->bMargin + 10); // For Images $extraWidth = ($objattr['border_left']['w'] + $objattr['border_right']['w'] + $objattr['margin_left'] + $objattr['margin_right']); $extraHeight = ($objattr['border_top']['w'] + $objattr['border_bottom']['w'] + $objattr['margin_top'] + $objattr['margin_bottom']); if ($objattr['itype'] == 'wmf' || $objattr['itype'] == 'svg') { $file = $objattr['file']; $info = $this->formobjects[$file]; } else { $file = $objattr['file']; $info = $this->images[$file]; } $img_w = $w - $extraWidth; $img_h = $h - $extraHeight; if ($objattr['border_left']['w']) { $objattr['BORDER-WIDTH'] = $img_w + (($objattr['border_left']['w'] + $objattr['border_right']['w']) / 2); $objattr['BORDER-HEIGHT'] = $img_h + (($objattr['border_top']['w'] + $objattr['border_bottom']['w']) / 2); $objattr['BORDER-X'] = $fx + $objattr['margin_left'] + (($objattr['border_left']['w']) / 2); $objattr['BORDER-Y'] = $fy + $objattr['margin_top'] + (($objattr['border_top']['w']) / 2); } $objattr['INNER-WIDTH'] = $img_w; $objattr['INNER-HEIGHT'] = $img_h; $objattr['INNER-X'] = $fx + $objattr['margin_left'] + ($objattr['border_left']['w']); $objattr['INNER-Y'] = $fy + $objattr['margin_top'] + ($objattr['border_top']['w']); $objattr['ID'] = $info['i']; $objattr['OUTER-WIDTH'] = $w; $objattr['OUTER-HEIGHT'] = $h; $objattr['OUTER-X'] = $fx; $objattr['OUTER-Y'] = $fy; if ($objattr['float'] == 'R') { // If R float already exists at this level $this->floatmargins['R']['skipline'] = false; if (isset($this->floatmargins['R']['y1']) && $this->floatmargins['R']['y1'] > 0 && $fy < $this->floatmargins['R']['y1']) { $this->WriteFlowingBlock($vetor[0], $vetor[18]); // mPDF 5.7.1 } // If L float already exists at this level elseif (isset($this->floatmargins['L']['y1']) && $this->floatmargins['L']['y1'] > 0 && $fy < $this->floatmargins['L']['y1']) { // Final check distance between floats is not now too narrow to fit text $mw = 2 * $this->GetCharWidth('W', false); if (($this->blk[$this->blklvl]['inner_width'] - $w - $this->floatmargins['L']['w']) < $mw) { $this->WriteFlowingBlock($vetor[0], $vetor[18]); // mPDF 5.7.1 } else { $this->floatmargins['R']['x'] = $fx; $this->floatmargins['R']['w'] = $w; $this->floatmargins['R']['y0'] = $fy; $this->floatmargins['R']['y1'] = $fy + $h; if ($skipln == 1) { $this->floatmargins['R']['skipline'] = true; $this->floatmargins['R']['id'] = count($this->floatbuffer) + 0; $objattr['skipline'] = true; } $this->floatbuffer[] = $objattr; } } else { $this->floatmargins['R']['x'] = $fx; $this->floatmargins['R']['w'] = $w; $this->floatmargins['R']['y0'] = $fy; $this->floatmargins['R']['y1'] = $fy + $h; if ($skipln == 1) { $this->floatmargins['R']['skipline'] = true; $this->floatmargins['R']['id'] = count($this->floatbuffer) + 0; $objattr['skipline'] = true; } $this->floatbuffer[] = $objattr; } } elseif ($objattr['float'] == 'L') { // If L float already exists at this level $this->floatmargins['L']['skipline'] = false; if (isset($this->floatmargins['L']['y1']) && $this->floatmargins['L']['y1'] > 0 && $fy < $this->floatmargins['L']['y1']) { $this->floatmargins['L']['skipline'] = false; $this->WriteFlowingBlock($vetor[0], $vetor[18]); // mPDF 5.7.1 } // If R float already exists at this level elseif (isset($this->floatmargins['R']['y1']) && $this->floatmargins['R']['y1'] > 0 && $fy < $this->floatmargins['R']['y1']) { // Final check distance between floats is not now too narrow to fit text $mw = 2 * $this->GetCharWidth('W', false); if (($this->blk[$this->blklvl]['inner_width'] - $w - $this->floatmargins['R']['w']) < $mw) { $this->WriteFlowingBlock($vetor[0], $vetor[18]); // mPDF 5.7.1 } else { $this->floatmargins['L']['x'] = $fx + $w; $this->floatmargins['L']['w'] = $w; $this->floatmargins['L']['y0'] = $fy; $this->floatmargins['L']['y1'] = $fy + $h; if ($skipln == 1) { $this->floatmargins['L']['skipline'] = true; $this->floatmargins['L']['id'] = count($this->floatbuffer) + 0; $objattr['skipline'] = true; } $this->floatbuffer[] = $objattr; } } else { $this->floatmargins['L']['x'] = $fx + $w; $this->floatmargins['L']['w'] = $w; $this->floatmargins['L']['y0'] = $fy; $this->floatmargins['L']['y1'] = $fy + $h; if ($skipln == 1) { $this->floatmargins['L']['skipline'] = true; $this->floatmargins['L']['id'] = count($this->floatbuffer) + 0; $objattr['skipline'] = true; } $this->floatbuffer[] = $objattr; } } } else { /* -- END CSS-IMAGE-FLOAT -- */ $this->WriteFlowingBlock($vetor[0], (isset($vetor[18]) ? $vetor[18] : null)); // mPDF 5.7.1 /* -- CSS-IMAGE-FLOAT -- */ } /* -- END CSS-IMAGE-FLOAT -- */ } // *TABLES* } // END If special content else { // THE text if ($this->tableLevel) { $paint_ht_corr = 0; } // To move the y up when new column/page started if div border needed else { $paint_ht_corr = $this->blk[$this->blklvl]['border_top']['w']; } if ($vetor[0] == "\n") { // We are reading a now turned into newline ("\n") if ($this->flowingBlockAttr['content']) { $this->finishFlowingBlock(false, 'br'); } elseif ($is_table) { $this->y+= $this->_computeLineheight($this->cellLineHeight); } elseif (!$is_table) { $this->DivLn($this->lineheight); if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS* } // Added to correct for OddEven Margins if ($this->page != $oldpage) { if (($this->page - $oldpage) % 2 == 1) { $bak_x += $this->MarginCorrection; } $oldpage = $this->page; $y = $this->tMargin - $paint_ht_corr; $this->oldy = $this->tMargin - $paint_ht_corr; $old_height = 0; } $this->x = $bak_x; /* -- COLUMNS -- */ // COLS // OR COLUMN CHANGE if ($this->CurrCol != $oldcolumn) { if ($this->directionality == 'rtl') { // *OTL* $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); // *OTL* } // *OTL* else { // *OTL* $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); } // *OTL* $this->x = $bak_x; $oldcolumn = $this->CurrCol; $y = $this->y0 - $paint_ht_corr; $this->oldy = $this->y0 - $paint_ht_corr; $old_height = 0; } /* -- END COLUMNS -- */ $this->newFlowingBlock($this->divwidth, $this->divheight, $align, $is_table, $blockstate, false, $blockdir, $table_draft); } else { $this->WriteFlowingBlock($vetor[0], $vetor[18]); // mPDF 5.7.1 // Added to correct for OddEven Margins if ($this->page != $oldpage) { if (($this->page - $oldpage) % 2 == 1) { $bak_x += $this->MarginCorrection; $this->x = $bak_x; } $oldpage = $this->page; $y = $this->tMargin - $paint_ht_corr; $this->oldy = $this->tMargin - $paint_ht_corr; $old_height = 0; } /* -- COLUMNS -- */ // COLS // OR COLUMN CHANGE if ($this->CurrCol != $oldcolumn) { if ($this->directionality == 'rtl') { // *OTL* $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); // *OTL* } // *OTL* else { // *OTL* $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); } // *OTL* $this->x = $bak_x; $oldcolumn = $this->CurrCol; $y = $this->y0 - $paint_ht_corr; $this->oldy = $this->y0 - $paint_ht_corr; $old_height = 0; } /* -- END COLUMNS -- */ } } // Check if it is the last element. If so then finish printing the block if ($i == ($array_size - 1)) { $this->finishFlowingBlock(true); // true = END of flowing block // Added to correct for OddEven Margins if ($this->page != $oldpage) { if (($this->page - $oldpage) % 2 == 1) { $bak_x += $this->MarginCorrection; $this->x = $bak_x; } $oldpage = $this->page; $y = $this->tMargin - $paint_ht_corr; $this->oldy = $this->tMargin - $paint_ht_corr; $old_height = 0; } /* -- COLUMNS -- */ // COLS // OR COLUMN CHANGE if ($this->CurrCol != $oldcolumn) { if ($this->directionality == 'rtl') { // *OTL* $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); // *OTL* } // *OTL* else { // *OTL* $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); } // *OTL* $this->x = $bak_x; $oldcolumn = $this->CurrCol; $y = $this->y0 - $paint_ht_corr; $this->oldy = $this->y0 - $paint_ht_corr; $old_height = 0; } /* -- END COLUMNS -- */ } // RESETTING VALUES $this->SetTColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); $this->SetFColor($this->colorConverter->convert(255, $this->PDFAXwarnings)); $this->colorarray = ''; $this->spanbgcolorarray = ''; $this->spanbgcolor = false; $this->spanborder = false; $this->spanborddet = []; $this->HREF = ''; $this->textparam = []; $this->SetTextOutline(); $this->textvar = 0x00; // mPDF 5.7.1 $this->OTLtags = []; $this->textshadow = ''; $this->currentfontfamily = ''; $this->currentfontsize = ''; $this->currentfontstyle = ''; $this->currentLang = $this->default_lang; // mPDF 6 $this->RestrictUnicodeFonts($this->default_available_fonts); // mPDF 6 /* -- TABLES -- */ if ($this->tableLevel) { $this->SetLineHeight('', $this->table[1][1]['cellLineHeight']); // *TABLES* } else { /* -- END TABLES -- */ if (isset($this->blk[$this->blklvl]['line_height']) && $this->blk[$this->blklvl]['line_height']) { $this->SetLineHeight('', $this->blk[$this->blklvl]['line_height']); // sets default line height } } $this->ResetStyles(); $this->lSpacingCSS = ''; $this->wSpacingCSS = ''; $this->fixedlSpacing = false; $this->minwSpacing = 0; $this->SetDash(); $this->dash_on = false; $this->dotted_on = false; }//end of for(i=0;iReset(); // mPDF 6 // PAINT DIV BORDER // DISABLED IN COLUMNS AS DOESN'T WORK WHEN BROKEN ACROSS COLS?? if ((isset($this->blk[$this->blklvl]['border']) || isset($this->blk[$this->blklvl]['bgcolor']) || isset($this->blk[$this->blklvl]['box_shadow'])) && $blockstate && ($this->y != $this->oldy)) { $bottom_y = $this->y; // Does not include Bottom Margin if (isset($this->blk[$this->blklvl]['startpage']) && $this->blk[$this->blklvl]['startpage'] != $this->page && $blockstate != 1) { $this->PaintDivBB('pagetop', $blockstate); } elseif ($blockstate != 1) { $this->PaintDivBB('', $blockstate); } $this->y = $bottom_y; $this->x = $bak_x; } // Reset Font $this->SetFontSize($this->default_font_size, false); if ($table_draft) { $ch = $this->y - $bak_y; $this->y = $bak_y; $this->x = $bak_x; return $ch; } } function _setDashBorder($style, $div, $cp, $side) { if ($style == 'dashed' && (($side == 'L' || $side == 'R') || ($side == 'T' && $div != 'pagetop' && !$cp) || ($side == 'B' && $div != 'pagebottom') )) { $dashsize = 2; // final dash will be this + 1*linewidth $dashsizek = 1.5; // ratio of Dash/Blank $this->SetDash($dashsize, ($dashsize / $dashsizek) + ($this->LineWidth * 2)); } elseif ($style == 'dotted' || ($side == 'T' && ($div == 'pagetop' || $cp)) || ($side == 'B' && $div == 'pagebottom')) { // Round join and cap $this->SetLineJoin(1); $this->SetLineCap(1); $this->SetDash(0.001, ($this->LineWidth * 3)); } } function _setBorderLine($b, $k = 1) { $this->SetLineWidth($b['w'] / $k); $this->SetDColor($b['c']); if ($b['c'][0] == 5) { // RGBa $this->SetAlpha(ord($b['c'][4]) / 100, 'Normal', false, 'S'); // mPDF 5.7.2 } elseif ($b['c'][0] == 6) { // CMYKa $this->SetAlpha(ord($b['c'][5]) / 100, 'Normal', false, 'S'); // mPDF 5.7.2 } } function PaintDivBB($divider = '', $blockstate = 0, $blvl = 0) { // Borders & backgrounds are done elsewhere for columns - messes up the repositioning in printcolumnbuffer if ($this->ColActive) { return; } // *COLUMNS* if ($this->keep_block_together) { return; } // mPDF 6 $save_y = $this->y; if (!$blvl) { $blvl = $this->blklvl; } $x0 = $x1 = $y0 = $y1 = 0; // Added mPDF 3.0 Float DIV if (isset($this->blk[$blvl]['bb_painted'][$this->page]) && $this->blk[$blvl]['bb_painted'][$this->page]) { return; } // *CSS-FLOAT* if (isset($this->blk[$blvl]['x0'])) { $x0 = $this->blk[$blvl]['x0']; } // left if (isset($this->blk[$blvl]['y1'])) { $y1 = $this->blk[$blvl]['y1']; } // bottom // Added mPDF 3.0 Float DIV - ensures backgrounds/borders are drawn to bottom of page if ($y1 == 0) { if ($divider == 'pagebottom') { $y1 = $this->h - $this->bMargin; } else { $y1 = $this->y; } } $continuingpage = (isset($this->blk[$blvl]['startpage']) && $this->blk[$blvl]['startpage'] != $this->page); if (isset($this->blk[$blvl]['y0'])) { $y0 = $this->blk[$blvl]['y0']; } $h = $y1 - $y0; $w = $this->blk[$blvl]['width']; $x1 = $x0 + $w; // Set border-widths as used here $border_top = $this->blk[$blvl]['border_top']['w']; $border_bottom = $this->blk[$blvl]['border_bottom']['w']; $border_left = $this->blk[$blvl]['border_left']['w']; $border_right = $this->blk[$blvl]['border_right']['w']; if (!$this->blk[$blvl]['border_top'] || $divider == 'pagetop' || $continuingpage) { $border_top = 0; } if (!$this->blk[$blvl]['border_bottom'] || $blockstate == 1 || $divider == 'pagebottom') { $border_bottom = 0; } $brTL_H = 0; $brTL_V = 0; $brTR_H = 0; $brTR_V = 0; $brBL_H = 0; $brBL_V = 0; $brBR_H = 0; $brBR_V = 0; $brset = false; /* -- BORDER-RADIUS -- */ if (isset($this->blk[$blvl]['border_radius_TL_H'])) { $brTL_H = $this->blk[$blvl]['border_radius_TL_H']; $brset = true; } if (isset($this->blk[$blvl]['border_radius_TL_V'])) { $brTL_V = $this->blk[$blvl]['border_radius_TL_V']; $brset = true; } if (isset($this->blk[$blvl]['border_radius_TR_H'])) { $brTR_H = $this->blk[$blvl]['border_radius_TR_H']; $brset = true; } if (isset($this->blk[$blvl]['border_radius_TR_V'])) { $brTR_V = $this->blk[$blvl]['border_radius_TR_V']; $brset = true; } if (isset($this->blk[$blvl]['border_radius_BR_H'])) { $brBR_H = $this->blk[$blvl]['border_radius_BR_H']; $brset = true; } if (isset($this->blk[$blvl]['border_radius_BR_V'])) { $brBR_V = $this->blk[$blvl]['border_radius_BR_V']; $brset = true; } if (isset($this->blk[$blvl]['border_radius_BL_H'])) { $brBL_H = $this->blk[$blvl]['border_radius_BL_H']; $brset = true; } if (isset($this->blk[$blvl]['border_radius_BL_V'])) { $brBL_V = $this->blk[$blvl]['border_radius_BL_V']; $brset = true; } if (!$this->blk[$blvl]['border_top'] || $divider == 'pagetop' || $continuingpage) { $brTL_H = 0; $brTL_V = 0; $brTR_H = 0; $brTR_V = 0; } if (!$this->blk[$blvl]['border_bottom'] || $blockstate == 1 || $divider == 'pagebottom') { $brBL_H = 0; $brBL_V = 0; $brBR_H = 0; $brBR_V = 0; } // Disallow border-radius if it is smaller than the border width. if ($brTL_H < min($border_left, $border_top)) { $brTL_H = $brTL_V = 0; } if ($brTL_V < min($border_left, $border_top)) { $brTL_V = $brTL_H = 0; } if ($brTR_H < min($border_right, $border_top)) { $brTR_H = $brTR_V = 0; } if ($brTR_V < min($border_right, $border_top)) { $brTR_V = $brTR_H = 0; } if ($brBL_H < min($border_left, $border_bottom)) { $brBL_H = $brBL_V = 0; } if ($brBL_V < min($border_left, $border_bottom)) { $brBL_V = $brBL_H = 0; } if ($brBR_H < min($border_right, $border_bottom)) { $brBR_H = $brBR_V = 0; } if ($brBR_V < min($border_right, $border_bottom)) { $brBR_V = $brBR_H = 0; } // CHECK FOR radii that sum to > width or height of div ******** $f = min($h / ($brTL_V + $brBL_V + 0.001), $h / ($brTR_V + $brBR_V + 0.001), $w / ($brTL_H + $brTR_H + 0.001), $w / ($brBL_H + $brBR_H + 0.001)); if ($f < 1) { $brTL_H *= $f; $brTL_V *= $f; $brTR_H *= $f; $brTR_V *= $f; $brBL_H *= $f; $brBL_V *= $f; $brBR_H *= $f; $brBR_V *= $f; } /* -- END BORDER-RADIUS -- */ $tbcol = $this->colorConverter->convert(255, $this->PDFAXwarnings); for ($l = 0; $l <= $blvl; $l++) { if ($this->blk[$l]['bgcolor']) { $tbcol = $this->blk[$l]['bgcolorarray']; } } // BORDERS if (isset($this->blk[$blvl]['y0']) && $this->blk[$blvl]['y0']) { $y0 = $this->blk[$blvl]['y0']; } $h = $y1 - $y0; $w = $this->blk[$blvl]['width']; if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) { $tbd = $this->blk[$blvl]['border_top']; $legend = ''; $legbreakL = 0; $legbreakR = 0; // BORDER LEGEND if (isset($this->blk[$blvl]['border_legend']) && $this->blk[$blvl]['border_legend']) { $legend = $this->blk[$blvl]['border_legend']; // Same structure array as textbuffer $txt = $legend[0] = ltrim($legend[0]); if (!empty($legend[18])) { $this->otl->trimOTLdata($legend[18], true, false); } // *OTL* // Set font, size, style, color $this->SetFont($legend[4], $legend[2], $legend[11]); if (isset($legend[3]) && $legend[3]) { $cor = $legend[3]; $this->SetTColor($cor); } $stringWidth = $this->GetStringWidth($txt, true, $legend[18], $legend[8]); $save_x = $this->x; $save_y = $this->y; $save_currentfontfamily = $this->FontFamily; $save_currentfontsize = $this->FontSizePt; $save_currentfontstyle = $this->FontStyle; $this->y = $y0 - $this->FontSize / 2 + $this->blk[$blvl]['border_top']['w'] / 2; $this->x = $x0 + $this->blk[$blvl]['padding_left'] + $this->blk[$blvl]['border_left']['w']; // Set the distance from the border line to the text ? make configurable variable $gap = 0.2 * $this->FontSize; $legbreakL = $this->x - $gap; $legbreakR = $this->x + $stringWidth + $gap; $this->magic_reverse_dir($txt, $this->blk[$blvl]['direction'], $legend[18]); $fill = ''; $this->Cell($stringWidth, $this->FontSize, $txt, '', 0, 'C', $fill, '', 0, 0, 0, 'M', $fill, false, $legend[18], $legend[8]); // Reset $this->x = $save_x; $this->y = $save_y; $this->SetFont($save_currentfontfamily, $save_currentfontstyle, $save_currentfontsize); $this->SetTColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); } if (isset($tbd['s']) && $tbd['s']) { if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { $this->writer->write('q'); $this->SetLineWidth(0); $this->writer->write(sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE)); $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE)); $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE)); $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE)); $this->writer->write(' h W n '); // Ends path no-op & Sets the clipping path } $this->_setBorderLine($tbd); if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { $legbreakL -= $border_top / 2; // because line cap different $legbreakR += $border_top / 2; $this->_setDashBorder($tbd['style'], $divider, $continuingpage, 'T'); } /* -- BORDER-RADIUS -- */ elseif (($brTL_V && $brTL_H) || ($brTR_V && $brTR_H) || $tbd['style'] == 'solid' || $tbd['style'] == 'double') { $this->SetLineJoin(0); $this->SetLineCap(0); } $s = ''; if ($brTR_H && $brTR_V) { $s .= ($this->_EllipseArc($x0 + $w - $brTR_H, $y0 + $brTR_V, $brTR_H - $border_top / 2, $brTR_V - $border_top / 2, 1, 2, true)) . "\n"; } else { /* -- END BORDER-RADIUS -- */ if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { $s .= (sprintf('%.3F %.3F m ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; } else { $s .= (sprintf('%.3F %.3F m ', ($x0 + $w - ($border_top / 2)) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; } } /* -- BORDER-RADIUS -- */ if ($brTL_H && $brTL_V) { if ($legend) { if ($legbreakR < ($x0 + $w - $brTR_H)) { $s .= (sprintf('%.3F %.3F l ', $legbreakR * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; } if ($legbreakL > ($x0 + $brTL_H )) { $s .= (sprintf('%.3F %.3F m ', $legbreakL * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; $s .= (sprintf('%.3F %.3F l ', ($x0 + $brTL_H ) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE) . "\n"); } else { $s .= (sprintf('%.3F %.3F m ', ($x0 + $brTL_H ) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; } } else { $s .= (sprintf('%.3F %.3F l ', ($x0 + $brTL_H ) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; } $s .= ($this->_EllipseArc($x0 + $brTL_H, $y0 + $brTL_V, $brTL_H - $border_top / 2, $brTL_V - $border_top / 2, 2, 1)) . "\n"; } else { /* -- END BORDER-RADIUS -- */ if ($legend) { if ($legbreakR < ($x0 + $w)) { $s .= (sprintf('%.3F %.3F l ', $legbreakR * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; } if ($legbreakL > ($x0)) { $s .= (sprintf('%.3F %.3F m ', $legbreakL * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { $s .= (sprintf('%.3F %.3F l ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; } else { $s .= (sprintf('%.3F %.3F l ', ($x0 + ($border_top / 2)) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; } } elseif ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { $s .= (sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; } else { $s .= (sprintf('%.3F %.3F m ', ($x0 + $border_top / 2) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; } } elseif ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { $s .= (sprintf('%.3F %.3F l ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; } else { $s .= (sprintf('%.3F %.3F l ', ($x0 + ($border_top / 2)) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; } /* -- BORDER-RADIUS -- */ } /* -- END BORDER-RADIUS -- */ $s .= 'S' . "\n"; $this->writer->write($s); if ($tbd['style'] == 'double') { $this->SetLineWidth($tbd['w'] / 3); $this->SetDColor($tbcol); $this->writer->write($s); } if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { $this->writer->write('Q'); } // Reset Corners and Dash off $this->SetLineWidth(0.1); $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); $this->SetLineJoin(2); $this->SetLineCap(2); $this->SetDash(); } } // Reinstate line above for dotted line divider when block border crosses a page // elseif ($divider == 'pagetop' || $continuingpage) { if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') { $tbd = $this->blk[$blvl]['border_bottom']; if (isset($tbd['s']) && $tbd['s']) { if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { $this->writer->write('q'); $this->SetLineWidth(0); $this->writer->write(sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE)); $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE)); $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE)); $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE)); $this->writer->write(' h W n '); // Ends path no-op & Sets the clipping path } $this->_setBorderLine($tbd); if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { $this->_setDashBorder($tbd['style'], $divider, $continuingpage, 'B'); } /* -- BORDER-RADIUS -- */ elseif (($brBL_V && $brBL_H) || ($brBR_V && $brBR_H) || $tbd['style'] == 'solid' || $tbd['style'] == 'double') { $this->SetLineJoin(0); $this->SetLineCap(0); } $s = ''; if ($brBL_H && $brBL_V) { $s .= ($this->_EllipseArc($x0 + $brBL_H, $y0 + $h - $brBL_V, $brBL_H - $border_bottom / 2, $brBL_V - $border_bottom / 2, 3, 2, true)) . "\n"; } else { /* -- END BORDER-RADIUS -- */ if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { $s .= (sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_bottom / 2))) * Mpdf::SCALE)) . "\n"; } else { $s .= (sprintf('%.3F %.3F m ', ($x0 + ($border_bottom / 2)) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_bottom / 2))) * Mpdf::SCALE)) . "\n"; } } /* -- BORDER-RADIUS -- */ if ($brBR_H && $brBR_V) { $s .= (sprintf('%.3F %.3F l ', ($x0 + $w - ($border_bottom / 2) - $brBR_H ) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_bottom / 2))) * Mpdf::SCALE)) . "\n"; $s .= ($this->_EllipseArc($x0 + $w - $brBR_H, $y0 + $h - $brBR_V, $brBR_H - $border_bottom / 2, $brBR_V - $border_bottom / 2, 4, 1)) . "\n"; } else { /* -- END BORDER-RADIUS -- */ if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { $s .= (sprintf('%.3F %.3F l ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_bottom / 2))) * Mpdf::SCALE)) . "\n"; } else { $s .= (sprintf('%.3F %.3F l ', ($x0 + $w - ($border_bottom / 2)) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_bottom / 2))) * Mpdf::SCALE)) . "\n"; } } $s .= 'S' . "\n"; $this->writer->write($s); if ($tbd['style'] == 'double') { $this->SetLineWidth($tbd['w'] / 3); $this->SetDColor($tbcol); $this->writer->write($s); } if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { $this->writer->write('Q'); } // Reset Corners and Dash off $this->SetLineWidth(0.1); $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); $this->SetLineJoin(2); $this->SetLineCap(2); $this->SetDash(); } } // Reinstate line below for dotted line divider when block border crosses a page // elseif ($blockstate == 1 || $divider == 'pagebottom') { if ($this->blk[$blvl]['border_left']) { $tbd = $this->blk[$blvl]['border_left']; if (isset($tbd['s']) && $tbd['s']) { if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { $this->writer->write('q'); $this->SetLineWidth(0); $this->writer->write(sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE)); $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE)); $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE)); $this->writer->write(sprintf('%.3F %.3F l ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE)); $this->writer->write(' h W n '); // Ends path no-op & Sets the clipping path } $this->_setBorderLine($tbd); if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { $this->_setDashBorder($tbd['style'], $divider, $continuingpage, 'L'); } /* -- BORDER-RADIUS -- */ elseif (($brTL_V && $brTL_H) || ($brBL_V && $brBL_H) || $tbd['style'] == 'solid' || $tbd['style'] == 'double') { $this->SetLineJoin(0); $this->SetLineCap(0); } $s = ''; if ($brTL_V && $brTL_H) { $s .= ($this->_EllipseArc($x0 + $brTL_H, $y0 + $brTL_V, $brTL_H - $border_left / 2, $brTL_V - $border_left / 2, 2, 2, true)) . "\n"; } else { /* -- END BORDER-RADIUS -- */ if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { $s .= (sprintf('%.3F %.3F m ', ($x0 + ($border_left / 2)) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE)) . "\n"; } else { $s .= (sprintf('%.3F %.3F m ', ($x0 + ($border_left / 2)) * Mpdf::SCALE, ($this->h - ($y0 + ($border_left / 2))) * Mpdf::SCALE)) . "\n"; } } /* -- BORDER-RADIUS -- */ if ($brBL_V && $brBL_H) { $s .= (sprintf('%.3F %.3F l ', ($x0 + ($border_left / 2)) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_left / 2) - $brBL_V) ) * Mpdf::SCALE)) . "\n"; $s .= ($this->_EllipseArc($x0 + $brBL_H, $y0 + $h - $brBL_V, $brBL_H - $border_left / 2, $brBL_V - $border_left / 2, 3, 1)) . "\n"; } else { /* -- END BORDER-RADIUS -- */ if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { $s .= (sprintf('%.3F %.3F l ', ($x0 + ($border_left / 2)) * Mpdf::SCALE, ($this->h - ($y0 + $h) ) * Mpdf::SCALE)) . "\n"; } else { $s .= (sprintf('%.3F %.3F l ', ($x0 + ($border_left / 2)) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_left / 2)) ) * Mpdf::SCALE)) . "\n"; } } $s .= 'S' . "\n"; $this->writer->write($s); if ($tbd['style'] == 'double') { $this->SetLineWidth($tbd['w'] / 3); $this->SetDColor($tbcol); $this->writer->write($s); } if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { $this->writer->write('Q'); } // Reset Corners and Dash off $this->SetLineWidth(0.1); $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); $this->SetLineJoin(2); $this->SetLineCap(2); $this->SetDash(); } } if ($this->blk[$blvl]['border_right']) { $tbd = $this->blk[$blvl]['border_right']; if (isset($tbd['s']) && $tbd['s']) { if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { $this->writer->write('q'); $this->SetLineWidth(0); $this->writer->write(sprintf('%.3F %.3F m ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE)); $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE)); $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE)); $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE)); $this->writer->write(' h W n '); // Ends path no-op & Sets the clipping path } $this->_setBorderLine($tbd); if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { $this->_setDashBorder($tbd['style'], $divider, $continuingpage, 'R'); } /* -- BORDER-RADIUS -- */ elseif (($brTR_V && $brTR_H) || ($brBR_V && $brBR_H) || $tbd['style'] == 'solid' || $tbd['style'] == 'double') { $this->SetLineJoin(0); $this->SetLineCap(0); } $s = ''; if ($brBR_V && $brBR_H) { $s .= ($this->_EllipseArc($x0 + $w - $brBR_H, $y0 + $h - $brBR_V, $brBR_H - $border_right / 2, $brBR_V - $border_right / 2, 4, 2, true)) . "\n"; } else { /* -- END BORDER-RADIUS -- */ if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { $s .= (sprintf('%.3F %.3F m ', ($x0 + $w - ($border_right / 2)) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE)) . "\n"; } else { $s .= (sprintf('%.3F %.3F m ', ($x0 + $w - ($border_right / 2)) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_right / 2))) * Mpdf::SCALE)) . "\n"; } } /* -- BORDER-RADIUS -- */ if ($brTR_V && $brTR_H) { $s .= (sprintf('%.3F %.3F l ', ($x0 + $w - ($border_right / 2)) * Mpdf::SCALE, ($this->h - ($y0 + ($border_right / 2) + $brTR_V) ) * Mpdf::SCALE)) . "\n"; $s .= ($this->_EllipseArc($x0 + $w - $brTR_H, $y0 + $brTR_V, $brTR_H - $border_right / 2, $brTR_V - $border_right / 2, 1, 1)) . "\n"; } else { /* -- END BORDER-RADIUS -- */ if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { $s .= (sprintf('%.3F %.3F l ', ($x0 + $w - ($border_right / 2)) * Mpdf::SCALE, ($this->h - ($y0) ) * Mpdf::SCALE)) . "\n"; } else { $s .= (sprintf('%.3F %.3F l ', ($x0 + $w - ($border_right / 2)) * Mpdf::SCALE, ($this->h - ($y0 + ($border_right / 2)) ) * Mpdf::SCALE)) . "\n"; } } $s .= 'S' . "\n"; $this->writer->write($s); if ($tbd['style'] == 'double') { $this->SetLineWidth($tbd['w'] / 3); $this->SetDColor($tbcol); $this->writer->write($s); } if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { $this->writer->write('Q'); } // Reset Corners and Dash off $this->SetLineWidth(0.1); $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); $this->SetLineJoin(2); $this->SetLineCap(2); $this->SetDash(); } } $this->SetDash(); $this->y = $save_y; // BACKGROUNDS are disabled in columns/kbt/headers - messes up the repositioning in printcolumnbuffer if ($this->ColActive || $this->kwt || $this->keep_block_together) { return; } $bgx0 = $x0; $bgx1 = $x1; $bgy0 = $y0; $bgy1 = $y1; // Defined br values represent the radius of the outer curve - need to take border-width/2 from each radius for drawing the borders if (isset($this->blk[$blvl]['background_clip']) && $this->blk[$blvl]['background_clip'] == 'padding-box') { $brbgTL_H = max(0, $brTL_H - $this->blk[$blvl]['border_left']['w']); $brbgTL_V = max(0, $brTL_V - $this->blk[$blvl]['border_top']['w']); $brbgTR_H = max(0, $brTR_H - $this->blk[$blvl]['border_right']['w']); $brbgTR_V = max(0, $brTR_V - $this->blk[$blvl]['border_top']['w']); $brbgBL_H = max(0, $brBL_H - $this->blk[$blvl]['border_left']['w']); $brbgBL_V = max(0, $brBL_V - $this->blk[$blvl]['border_bottom']['w']); $brbgBR_H = max(0, $brBR_H - $this->blk[$blvl]['border_right']['w']); $brbgBR_V = max(0, $brBR_V - $this->blk[$blvl]['border_bottom']['w']); $bgx0 += $this->blk[$blvl]['border_left']['w']; $bgx1 -= $this->blk[$blvl]['border_right']['w']; if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) { $bgy0 += $this->blk[$blvl]['border_top']['w']; } if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') { $bgy1 -= $this->blk[$blvl]['border_bottom']['w']; } } elseif (isset($this->blk[$blvl]['background_clip']) && $this->blk[$blvl]['background_clip'] == 'content-box') { $brbgTL_H = max(0, $brTL_H - $this->blk[$blvl]['border_left']['w'] - $this->blk[$blvl]['padding_left']); $brbgTL_V = max(0, $brTL_V - $this->blk[$blvl]['border_top']['w'] - $this->blk[$blvl]['padding_top']); $brbgTR_H = max(0, $brTR_H - $this->blk[$blvl]['border_right']['w'] - $this->blk[$blvl]['padding_right']); $brbgTR_V = max(0, $brTR_V - $this->blk[$blvl]['border_top']['w'] - $this->blk[$blvl]['padding_top']); $brbgBL_H = max(0, $brBL_H - $this->blk[$blvl]['border_left']['w'] - $this->blk[$blvl]['padding_left']); $brbgBL_V = max(0, $brBL_V - $this->blk[$blvl]['border_bottom']['w'] - $this->blk[$blvl]['padding_bottom']); $brbgBR_H = max(0, $brBR_H - $this->blk[$blvl]['border_right']['w'] - $this->blk[$blvl]['padding_right']); $brbgBR_V = max(0, $brBR_V - $this->blk[$blvl]['border_bottom']['w'] - $this->blk[$blvl]['padding_bottom']); $bgx0 += $this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left']; $bgx1 -= $this->blk[$blvl]['border_right']['w'] + $this->blk[$blvl]['padding_right']; if (($this->blk[$blvl]['border_top']['w'] || $this->blk[$blvl]['padding_top']) && $divider != 'pagetop' && !$continuingpage) { $bgy0 += $this->blk[$blvl]['border_top']['w'] + $this->blk[$blvl]['padding_top']; } if (($this->blk[$blvl]['border_bottom']['w'] || $this->blk[$blvl]['padding_bottom']) && $blockstate != 1 && $divider != 'pagebottom') { $bgy1 -= $this->blk[$blvl]['border_bottom']['w'] + $this->blk[$blvl]['padding_bottom']; } } else { $brbgTL_H = $brTL_H; $brbgTL_V = $brTL_V; $brbgTR_H = $brTR_H; $brbgTR_V = $brTR_V; $brbgBL_H = $brBL_H; $brbgBL_V = $brBL_V; $brbgBR_H = $brBR_H; $brbgBR_V = $brBR_V; } // Set clipping path $s = ' q 0 w '; // Line width=0 $s .= sprintf('%.3F %.3F m ', ($bgx0 + $brbgTL_H ) * Mpdf::SCALE, ($this->h - $bgy0) * Mpdf::SCALE); // start point TL before the arc /* -- BORDER-RADIUS -- */ if ($brbgTL_H || $brbgTL_V) { $s .= $this->_EllipseArc($bgx0 + $brbgTL_H, $bgy0 + $brbgTL_V, $brbgTL_H, $brbgTL_V, 2); // segment 2 TL } /* -- END BORDER-RADIUS -- */ $s .= sprintf('%.3F %.3F l ', ($bgx0) * Mpdf::SCALE, ($this->h - ($bgy1 - $brbgBL_V )) * Mpdf::SCALE); // line to BL /* -- BORDER-RADIUS -- */ if ($brbgBL_H || $brbgBL_V) { $s .= $this->_EllipseArc($bgx0 + $brbgBL_H, $bgy1 - $brbgBL_V, $brbgBL_H, $brbgBL_V, 3); // segment 3 BL } /* -- END BORDER-RADIUS -- */ $s .= sprintf('%.3F %.3F l ', ($bgx1 - $brbgBR_H ) * Mpdf::SCALE, ($this->h - ($bgy1)) * Mpdf::SCALE); // line to BR /* -- BORDER-RADIUS -- */ if ($brbgBR_H || $brbgBR_V) { $s .= $this->_EllipseArc($bgx1 - $brbgBR_H, $bgy1 - $brbgBR_V, $brbgBR_H, $brbgBR_V, 4); // segment 4 BR } /* -- END BORDER-RADIUS -- */ $s .= sprintf('%.3F %.3F l ', ($bgx1) * Mpdf::SCALE, ($this->h - ($bgy0 + $brbgTR_V)) * Mpdf::SCALE); // line to TR /* -- BORDER-RADIUS -- */ if ($brbgTR_H || $brbgTR_V) { $s .= $this->_EllipseArc($bgx1 - $brbgTR_H, $bgy0 + $brbgTR_V, $brbgTR_H, $brbgTR_V, 1); // segment 1 TR } /* -- END BORDER-RADIUS -- */ $s .= sprintf('%.3F %.3F l ', ($bgx0 + $brbgTL_H ) * Mpdf::SCALE, ($this->h - $bgy0) * Mpdf::SCALE); // line to TL // Box Shadow $shadow = ''; if (isset($this->blk[$blvl]['box_shadow']) && $this->blk[$blvl]['box_shadow'] && $h > 0) { foreach ($this->blk[$blvl]['box_shadow'] as $sh) { // Colors if ($sh['col'][0] == 1) { $colspace = 'Gray'; if ($sh['col'][2] == 1) { $col1 = '1' . $sh['col'][1] . '1' . $sh['col'][3]; } else { $col1 = '1' . $sh['col'][1] . '1' . chr(100); } $col2 = '1' . $sh['col'][1] . '1' . chr(0); } elseif ($sh['col'][0] == 4) { // CMYK $colspace = 'CMYK'; $col1 = '6' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . $sh['col'][4] . chr(100); $col2 = '6' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . $sh['col'][4] . chr(0); } elseif ($sh['col'][0] == 5) { // RGBa $colspace = 'RGB'; $col1 = '5' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . $sh['col'][4]; $col2 = '5' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . chr(0); } elseif ($sh['col'][0] == 6) { // CMYKa $colspace = 'CMYK'; $col1 = '6' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . $sh['col'][4] . $sh['col'][5]; $col2 = '6' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . $sh['col'][4] . chr(0); } else { $colspace = 'RGB'; $col1 = '5' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . chr(100); $col2 = '5' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . chr(0); } // Use clipping path as set above (and rectangle around page) to clip area outside box $shadow .= $s; // Use the clipping path with W* $shadow .= sprintf('0 %.3F m %.3F %.3F l ', $this->h * Mpdf::SCALE, $this->w * Mpdf::SCALE, $this->h * Mpdf::SCALE); $shadow .= sprintf('%.3F 0 l 0 0 l 0 %.3F l ', $this->w * Mpdf::SCALE, $this->h * Mpdf::SCALE); $shadow .= 'W n' . "\n"; $sh['blur'] = abs($sh['blur']); // cannot have negative blur value // Ensure spread/blur do not make effective shadow width/height < 0 // Could do more complex things but this just adjusts spread value if (-$sh['spread'] + $sh['blur'] / 2 > min($w / 2, $h / 2)) { $sh['spread'] = $sh['blur'] / 2 - min($w / 2, $h / 2) + 0.01; } // Shadow Offset if ($sh['x'] || $sh['y']) { $shadow .= sprintf(' q 1 0 0 1 %.4F %.4F cm', $sh['x'] * Mpdf::SCALE, -$sh['y'] * Mpdf::SCALE) . "\n"; } // Set path for INNER shadow $shadow .= ' q 0 w '; $shadow .= $this->SetFColor($col1, true) . "\n"; if ($col1[0] == 5 && ord($col1[4]) < 100) { // RGBa $shadow .= $this->SetAlpha(ord($col1[4]) / 100, 'Normal', true, 'F') . "\n"; } elseif ($col1[0] == 6 && ord($col1[5]) < 100) { // CMYKa $shadow .= $this->SetAlpha(ord($col1[5]) / 100, 'Normal', true, 'F') . "\n"; } elseif ($col1[0] == 1 && $col1[2] == 1 && ord($col1[3]) < 100) { // Gray $shadow .= $this->SetAlpha(ord($col1[3]) / 100, 'Normal', true, 'F') . "\n"; } // Blur edges $mag = 0.551784; // Bezier Control magic number for 4-part spline for circle/ellipse $mag2 = 0.551784; // Bezier Control magic number to fill in edge of blurred rectangle $d1 = $sh['spread'] + $sh['blur'] / 2; $d2 = $sh['spread'] - $sh['blur'] / 2; $bl = $sh['blur']; $x00 = $x0 - $d1; $y00 = $y0 - $d1; $w00 = $w + $d1 * 2; $h00 = $h + $d1 * 2; // If any border-radius is greater width-negative spread(inner edge), ignore radii for shadow or screws up $flatten = false; if (max($brbgTR_H, $brbgTL_H, $brbgBR_H, $brbgBL_H) >= $w + $d2) { $flatten = true; } if (max($brbgTR_V, $brbgTL_V, $brbgBR_V, $brbgBL_V) >= $h + $d2) { $flatten = true; } // TOP RIGHT corner $p1x = $x00 + $w00 - $d1 - $brbgTR_H; $p1c2x = $p1x + ($d2 + $brbgTR_H) * $mag; $p1y = $y00 + $bl; $p2x = $x00 + $w00 - $d1 - $brbgTR_H; $p2c2x = $p2x + ($d1 + $brbgTR_H) * $mag; $p2y = $y00; $p2c1y = $p2y + $bl / 2; $p3x = $x00 + $w00; $p3c2x = $p3x - $bl / 2; $p3y = $y00 + $d1 + $brbgTR_V; $p3c1y = $p3y - ($d1 + $brbgTR_V) * $mag; $p4x = $x00 + $w00 - $bl; $p4y = $y00 + $d1 + $brbgTR_V; $p4c2y = $p4y - ($d2 + $brbgTR_V) * $mag; if (-$d2 > min($brbgTR_H, $brbgTR_V) || $flatten) { $p1x = $x00 + $w00 - $bl; $p1c2x = $p1x; $p2x = $x00 + $w00 - $bl; $p2c2x = $p2x + $bl * $mag2; $p3y = $y00 + $bl; $p3c1y = $p3y - $bl * $mag2; $p4y = $y00 + $bl; $p4c2y = $p4y; } $shadow .= sprintf('%.3F %.3F m ', ($p1x ) * Mpdf::SCALE, ($this->h - ($p1y )) * Mpdf::SCALE); $shadow .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($p1c2x) * Mpdf::SCALE, ($this->h - ($p1y)) * Mpdf::SCALE, ($p4x) * Mpdf::SCALE, ($this->h - ($p4c2y)) * Mpdf::SCALE, ($p4x) * Mpdf::SCALE, ($this->h - ($p4y)) * Mpdf::SCALE); $patch_array[0]['f'] = 0; $patch_array[0]['points'] = [$p1x, $p1y, $p1x, $p1y, $p2x, $p2c1y, $p2x, $p2y, $p2c2x, $p2y, $p3x, $p3c1y, $p3x, $p3y, $p3c2x, $p3y, $p4x, $p4y, $p4x, $p4y, $p4x, $p4c2y, $p1c2x, $p1y]; $patch_array[0]['colors'] = [$col1, $col2, $col2, $col1]; // RIGHT $p1x = $x00 + $w00; // control point only matches p3 preceding $p1y = $y00 + $d1 + $brbgTR_V; $p2x = $x00 + $w00 - $bl; // control point only matches p4 preceding $p2y = $y00 + $d1 + $brbgTR_V; $p3x = $x00 + $w00 - $bl; $p3y = $y00 + $h00 - $d1 - $brbgBR_V; $p4x = $x00 + $w00; $p4c1x = $p4x - $bl / 2; $p4y = $y00 + $h00 - $d1 - $brbgBR_V; if (-$d2 > min($brbgTR_H, $brbgTR_V) || $flatten) { $p1y = $y00 + $bl; $p2y = $y00 + $bl; } if (-$d2 > min($brbgBR_H, $brbgBR_V) || $flatten) { $p3y = $y00 + $h00 - $bl; $p4y = $y00 + $h00 - $bl; } $shadow .= sprintf('%.3F %.3F l ', ($p3x ) * Mpdf::SCALE, ($this->h - ($p3y )) * Mpdf::SCALE); $patch_array[1]['f'] = 2; $patch_array[1]['points'] = [$p2x, $p2y, $p3x, $p3y, $p3x, $p3y, $p3x, $p3y, $p4c1x, $p4y, $p4x, $p4y, $p4x, $p4y, $p1x, $p1y]; $patch_array[1]['colors'] = [$col1, $col2]; // BOTTOM RIGHT corner $p1x = $x00 + $w00 - $bl; // control points only matches p3 preceding $p1y = $y00 + $h00 - $d1 - $brbgBR_V; $p1c2y = $p1y + ($d2 + $brbgBR_V) * $mag; $p2x = $x00 + $w00; // control point only matches p4 preceding $p2y = $y00 + $h00 - $d1 - $brbgBR_V; $p2c2y = $p2y + ($d1 + $brbgBR_V) * $mag; $p3x = $x00 + $w00 - $d1 - $brbgBR_H; $p3c1x = $p3x + ($d1 + $brbgBR_H) * $mag; $p3y = $y00 + $h00; $p3c2y = $p3y - $bl / 2; $p4x = $x00 + $w00 - $d1 - $brbgBR_H; $p4c2x = $p4x + ($d2 + $brbgBR_H) * $mag; $p4y = $y00 + $h00 - $bl; if (-$d2 > min($brbgBR_H, $brbgBR_V) || $flatten) { $p1y = $y00 + $h00 - $bl; $p1c2y = $p1y; $p2y = $y00 + $h00 - $bl; $p2c2y = $p2y + $bl * $mag2; $p3x = $x00 + $w00 - $bl; $p3c1x = $p3x + $bl * $mag2; $p4x = $x00 + $w00 - $bl; $p4c2x = $p4x; } $shadow .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($p1x) * Mpdf::SCALE, ($this->h - ($p1c2y)) * Mpdf::SCALE, ($p4c2x) * Mpdf::SCALE, ($this->h - ($p4y)) * Mpdf::SCALE, ($p4x) * Mpdf::SCALE, ($this->h - ($p4y)) * Mpdf::SCALE); $patch_array[2]['f'] = 2; $patch_array[2]['points'] = [$p2x, $p2c2y, $p3c1x, $p3y, $p3x, $p3y, $p3x, $p3c2y, $p4x, $p4y, $p4x, $p4y, $p4c2x, $p4y, $p1x, $p1c2y]; $patch_array[2]['colors'] = [$col2, $col1]; // BOTTOM $p1x = $x00 + $w00 - $d1 - $brbgBR_H; // control point only matches p3 preceding $p1y = $y00 + $h00; $p2x = $x00 + $w00 - $d1 - $brbgBR_H; // control point only matches p4 preceding $p2y = $y00 + $h00 - $bl; $p3x = $x00 + $d1 + $brbgBL_H; $p3y = $y00 + $h00 - $bl; $p4x = $x00 + $d1 + $brbgBL_H; $p4y = $y00 + $h00; $p4c1y = $p4y - $bl / 2; if (-$d2 > min($brbgBR_H, $brbgBR_V) || $flatten) { $p1x = $x00 + $w00 - $bl; $p2x = $x00 + $w00 - $bl; } if (-$d2 > min($brbgBL_H, $brbgBL_V) || $flatten) { $p3x = $x00 + $bl; $p4x = $x00 + $bl; } $shadow .= sprintf('%.3F %.3F l ', ($p3x ) * Mpdf::SCALE, ($this->h - ($p3y )) * Mpdf::SCALE); $patch_array[3]['f'] = 2; $patch_array[3]['points'] = [$p2x, $p2y, $p3x, $p3y, $p3x, $p3y, $p3x, $p3y, $p4x, $p4c1y, $p4x, $p4y, $p4x, $p4y, $p1x, $p1y]; $patch_array[3]['colors'] = [$col1, $col2]; // BOTTOM LEFT corner $p1x = $x00 + $d1 + $brbgBL_H; $p1c2x = $p1x - ($d2 + $brbgBL_H) * $mag; // control points only matches p3 preceding $p1y = $y00 + $h00 - $bl; $p2x = $x00 + $d1 + $brbgBL_H; $p2c2x = $p2x - ($d1 + $brbgBL_H) * $mag; // control point only matches p4 preceding $p2y = $y00 + $h00; $p3x = $x00; $p3c2x = $p3x + $bl / 2; $p3y = $y00 + $h00 - $d1 - $brbgBL_V; $p3c1y = $p3y + ($d1 + $brbgBL_V) * $mag; $p4x = $x00 + $bl; $p4y = $y00 + $h00 - $d1 - $brbgBL_V; $p4c2y = $p4y + ($d2 + $brbgBL_V) * $mag; if (-$d2 > min($brbgBL_H, $brbgBL_V) || $flatten) { $p1x = $x00 + $bl; $p1c2x = $p1x; $p2x = $x00 + $bl; $p2c2x = $p2x - $bl * $mag2; $p3y = $y00 + $h00 - $bl; $p3c1y = $p3y + $bl * $mag2; $p4y = $y00 + $h00 - $bl; $p4c2y = $p4y; } $shadow .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($p1c2x) * Mpdf::SCALE, ($this->h - ($p1y)) * Mpdf::SCALE, ($p4x) * Mpdf::SCALE, ($this->h - ($p4c2y)) * Mpdf::SCALE, ($p4x) * Mpdf::SCALE, ($this->h - ($p4y)) * Mpdf::SCALE); $patch_array[4]['f'] = 2; $patch_array[4]['points'] = [$p2c2x, $p2y, $p3x, $p3c1y, $p3x, $p3y, $p3c2x, $p3y, $p4x, $p4y, $p4x, $p4y, $p4x, $p4c2y, $p1c2x, $p1y]; $patch_array[4]['colors'] = [$col2, $col1]; // LEFT - joins on the right (C3-C4 of previous): f = 2 $p1x = $x00; // control point only matches p3 preceding $p1y = $y00 + $h00 - $d1 - $brbgBL_V; $p2x = $x00 + $bl; // control point only matches p4 preceding $p2y = $y00 + $h00 - $d1 - $brbgBL_V; $p3x = $x00 + $bl; $p3y = $y00 + $d1 + $brbgTL_V; $p4x = $x00; $p4c1x = $p4x + $bl / 2; $p4y = $y00 + $d1 + $brbgTL_V; if (-$d2 > min($brbgBL_H, $brbgBL_V) || $flatten) { $p1y = $y00 + $h00 - $bl; $p2y = $y00 + $h00 - $bl; } if (-$d2 > min($brbgTL_H, $brbgTL_V) || $flatten) { $p3y = $y00 + $bl; $p4y = $y00 + $bl; } $shadow .= sprintf('%.3F %.3F l ', ($p3x ) * Mpdf::SCALE, ($this->h - ($p3y )) * Mpdf::SCALE); $patch_array[5]['f'] = 2; $patch_array[5]['points'] = [$p2x, $p2y, $p3x, $p3y, $p3x, $p3y, $p3x, $p3y, $p4c1x, $p4y, $p4x, $p4y, $p4x, $p4y, $p1x, $p1y]; $patch_array[5]['colors'] = [$col1, $col2]; // TOP LEFT corner $p1x = $x00 + $bl; // control points only matches p3 preceding $p1y = $y00 + $d1 + $brbgTL_V; $p1c2y = $p1y - ($d2 + $brbgTL_V) * $mag; $p2x = $x00; // control point only matches p4 preceding $p2y = $y00 + $d1 + $brbgTL_V; $p2c2y = $p2y - ($d1 + $brbgTL_V) * $mag; $p3x = $x00 + $d1 + $brbgTL_H; $p3c1x = $p3x - ($d1 + $brbgTL_H) * $mag; $p3y = $y00; $p3c2y = $p3y + $bl / 2; $p4x = $x00 + $d1 + $brbgTL_H; $p4c2x = $p4x - ($d2 + $brbgTL_H) * $mag; $p4y = $y00 + $bl; if (-$d2 > min($brbgTL_H, $brbgTL_V) || $flatten) { $p1y = $y00 + $bl; $p1c2y = $p1y; $p2y = $y00 + $bl; $p2c2y = $p2y - $bl * $mag2; $p3x = $x00 + $bl; $p3c1x = $p3x - $bl * $mag2; $p4x = $x00 + $bl; $p4c2x = $p4x; } $shadow .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($p1x) * Mpdf::SCALE, ($this->h - ($p1c2y)) * Mpdf::SCALE, ($p4c2x) * Mpdf::SCALE, ($this->h - ($p4y)) * Mpdf::SCALE, ($p4x) * Mpdf::SCALE, ($this->h - ($p4y)) * Mpdf::SCALE); $patch_array[6]['f'] = 2; $patch_array[6]['points'] = [$p2x, $p2c2y, $p3c1x, $p3y, $p3x, $p3y, $p3x, $p3c2y, $p4x, $p4y, $p4x, $p4y, $p4c2x, $p4y, $p1x, $p1c2y]; $patch_array[6]['colors'] = [$col2, $col1]; // TOP - joins on the right (C3-C4 of previous): f = 2 $p1x = $x00 + $d1 + $brbgTL_H; // control point only matches p3 preceding $p1y = $y00; $p2x = $x00 + $d1 + $brbgTL_H; // control point only matches p4 preceding $p2y = $y00 + $bl; $p3x = $x00 + $w00 - $d1 - $brbgTR_H; $p3y = $y00 + $bl; $p4x = $x00 + $w00 - $d1 - $brbgTR_H; $p4y = $y00; $p4c1y = $p4y + $bl / 2; if (-$d2 > min($brbgTL_H, $brbgTL_V) || $flatten) { $p1x = $x00 + $bl; $p2x = $x00 + $bl; } if (-$d2 > min($brbgTR_H, $brbgTR_V) || $flatten) { $p3x = $x00 + $w00 - $bl; $p4x = $x00 + $w00 - $bl; } $shadow .= sprintf('%.3F %.3F l ', ($p3x ) * Mpdf::SCALE, ($this->h - ($p3y )) * Mpdf::SCALE); $patch_array[7]['f'] = 2; $patch_array[7]['points'] = [$p2x, $p2y, $p3x, $p3y, $p3x, $p3y, $p3x, $p3y, $p4x, $p4c1y, $p4x, $p4y, $p4x, $p4y, $p1x, $p1y]; $patch_array[7]['colors'] = [$col1, $col2]; $shadow .= ' h f Q ' . "\n"; // Close path and Fill the inner solid shadow if ($bl) { $shadow .= $this->gradient->CoonsPatchMesh($x00, $y00, $w00, $h00, $patch_array, $x00, $x00 + $w00, $y00, $y00 + $h00, $colspace, true); } if ($sh['x'] || $sh['y']) { $shadow .= ' Q' . "\n"; // Shadow Offset } $shadow .= ' Q' . "\n"; // Ends path no-op & Sets the clipping path } } $s .= ' W n '; // Ends path no-op & Sets the clipping path if ($this->blk[$blvl]['bgcolor']) { $this->pageBackgrounds[$blvl][] = [ 'x' => $x0, 'y' => $y0, 'w' => $w, 'h' => $h, 'col' => $this->blk[$blvl]['bgcolorarray'], 'clippath' => $s, 'visibility' => $this->visibility, 'shadow' => $shadow, 'z-index' => $this->current_layer, ]; } elseif ($shadow) { $this->pageBackgrounds[$blvl][] = [ 'x' => 0, 'y' => 0, 'w' => 0, 'h' => 0, 'shadowonly' => true, 'col' => '', 'clippath' => '', 'visibility' => $this->visibility, 'shadow' => $shadow, 'z-index' => $this->current_layer, ]; } /* -- BACKGROUNDS -- */ if (isset($this->blk[$blvl]['gradient'])) { $g = $this->gradient->parseBackgroundGradient($this->blk[$blvl]['gradient']); if ($g) { $gx = $x0; $gy = $y0; $this->pageBackgrounds[$blvl][] = [ 'gradient' => true, 'x' => $gx, 'y' => $gy, 'w' => $w, 'h' => $h, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => $s, 'visibility' => $this->visibility, 'z-index' => $this->current_layer ]; } } if (isset($this->blk[$blvl]['background-image'])) { if (isset($this->blk[$blvl]['background-image']['gradient']) && $this->blk[$blvl]['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $this->blk[$blvl]['background-image']['gradient'])) { $g = $this->gradient->parseMozGradient($this->blk[$blvl]['background-image']['gradient']); if ($g) { $gx = $x0; $gy = $y0; // origin specifies the background-positioning-area (bpa) if ($this->blk[$blvl]['background-image']['origin'] == 'padding-box') { $gx += $this->blk[$blvl]['border_left']['w']; $w -= ($this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['border_right']['w']); if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) { $gy += $this->blk[$blvl]['border_top']['w']; } if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') { $gy1 = $y1 - $this->blk[$blvl]['border_bottom']['w']; } else { $gy1 = $y1; } $h = $gy1 - $gy; } elseif ($this->blk[$blvl]['background-image']['origin'] == 'content-box') { $gx += $this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left']; $w -= ($this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left'] + $this->blk[$blvl]['border_right']['w'] + $this->blk[$blvl]['padding_right']); if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) { $gy += $this->blk[$blvl]['border_top']['w'] + $this->blk[$blvl]['padding_top']; } if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') { $gy1 = $y1 - ($this->blk[$blvl]['border_bottom']['w'] + $this->blk[$blvl]['padding_bottom']); } else { $gy1 = $y1 - $this->blk[$blvl]['padding_bottom']; } $h = $gy1 - $gy; } if (isset($this->blk[$blvl]['background-image']['size']['w']) && $this->blk[$blvl]['background-image']['size']['w']) { $size = $this->blk[$blvl]['background-image']['size']; if ($size['w'] != 'contain' && $size['w'] != 'cover') { if (stristr($size['w'], '%')) { $size['w'] = (float) $size['w']; $size['w'] /= 100; $w *= $size['w']; } elseif ($size['w'] != 'auto') { $w = $size['w']; } if (stristr($size['h'], '%')) { $size['h'] = (float) $size['h']; $size['h'] /= 100; $h *= $size['h']; } elseif ($size['h'] != 'auto') { $h = $size['h']; } } } $this->pageBackgrounds[$blvl][] = [ 'gradient' => true, 'x' => $gx, 'y' => $gy, 'w' => $w, 'h' => $h, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => $s, 'visibility' => $this->visibility, 'z-index' => $this->current_layer ]; } } else { $image_id = $this->blk[$blvl]['background-image']['image_id']; $orig_w = $this->blk[$blvl]['background-image']['orig_w']; $orig_h = $this->blk[$blvl]['background-image']['orig_h']; $x_pos = $this->blk[$blvl]['background-image']['x_pos']; $y_pos = $this->blk[$blvl]['background-image']['y_pos']; $x_repeat = $this->blk[$blvl]['background-image']['x_repeat']; $y_repeat = $this->blk[$blvl]['background-image']['y_repeat']; $resize = $this->blk[$blvl]['background-image']['resize']; $opacity = $this->blk[$blvl]['background-image']['opacity']; $itype = $this->blk[$blvl]['background-image']['itype']; $size = $this->blk[$blvl]['background-image']['size']; // origin specifies the background-positioning-area (bpa) $bpa = ['x' => $x0, 'y' => $y0, 'w' => $w, 'h' => $h]; if ($this->blk[$blvl]['background-image']['origin'] == 'padding-box') { $bpa['x'] = $x0 + $this->blk[$blvl]['border_left']['w']; $bpa['w'] = $w - ($this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['border_right']['w']); if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) { $bpa['y'] = $y0 + $this->blk[$blvl]['border_top']['w']; } else { $bpa['y'] = $y0; } if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') { $bpay = $y1 - $this->blk[$blvl]['border_bottom']['w']; } else { $bpay = $y1; } $bpa['h'] = $bpay - $bpa['y']; } elseif ($this->blk[$blvl]['background-image']['origin'] == 'content-box') { $bpa['x'] = $x0 + $this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left']; $bpa['w'] = $w - ($this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left'] + $this->blk[$blvl]['border_right']['w'] + $this->blk[$blvl]['padding_right']); if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) { $bpa['y'] = $y0 + $this->blk[$blvl]['border_top']['w'] + $this->blk[$blvl]['padding_top']; } else { $bpa['y'] = $y0 + $this->blk[$blvl]['padding_top']; } if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') { $bpay = $y1 - ($this->blk[$blvl]['border_bottom']['w'] + $this->blk[$blvl]['padding_bottom']); } else { $bpay = $y1 - $this->blk[$blvl]['padding_bottom']; } $bpa['h'] = $bpay - $bpa['y']; } $this->pageBackgrounds[$blvl][] = [ 'x' => $x0, 'y' => $y0, 'w' => $w, 'h' => $h, 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => $s, 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype, 'visibility' => $this->visibility, 'z-index' => $this->current_layer, 'size' => $size, 'bpa' => $bpa ]; } } /* -- END BACKGROUNDS -- */ // Float DIV $this->blk[$blvl]['bb_painted'][$this->page] = true; } /* -- BORDER-RADIUS -- */ function _EllipseArc($x0, $y0, $rx, $ry, $seg = 1, $part = false, $start = false) { // Anticlockwise segment 1-4 TR-TL-BL-BR (part=1 or 2) $s = ''; if ($rx < 0) { $rx = 0; } if ($ry < 0) { $ry = 0; } $rx *= Mpdf::SCALE; $ry *= Mpdf::SCALE; $astart = 0; if ($seg == 1) { // Top Right $afinish = 90; $nSeg = 4; } elseif ($seg == 2) { // Top Left $afinish = 180; $nSeg = 8; } elseif ($seg == 3) { // Bottom Left $afinish = 270; $nSeg = 12; } else { // Bottom Right $afinish = 360; $nSeg = 16; } $astart = deg2rad((float) $astart); $afinish = deg2rad((float) $afinish); $totalAngle = $afinish - $astart; $dt = $totalAngle / $nSeg; // segment angle $dtm = $dt / 3; $x0 *= Mpdf::SCALE; $y0 = ($this->h - $y0) * Mpdf::SCALE; $t1 = $astart; $a0 = $x0 + ($rx * cos($t1)); $b0 = $y0 + ($ry * sin($t1)); $c0 = -$rx * sin($t1); $d0 = $ry * cos($t1); $op = false; for ($i = 1; $i <= $nSeg; $i++) { // Draw this bit of the total curve $t1 = ($i * $dt) + $astart; $a1 = $x0 + ($rx * cos($t1)); $b1 = $y0 + ($ry * sin($t1)); $c1 = -$rx * sin($t1); $d1 = $ry * cos($t1); if ($i > ($nSeg - 4) && (!$part || ($part == 1 && $i <= $nSeg - 2) || ($part == 2 && $i > $nSeg - 2))) { if ($start && !$op) { $s .= sprintf('%.3F %.3F m ', $a0, $b0); } $s .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($a0 + ($c0 * $dtm)), ($b0 + ($d0 * $dtm)), ($a1 - ($c1 * $dtm)), ($b1 - ($d1 * $dtm)), $a1, $b1); $op = true; } $a0 = $a1; $b0 = $b1; $c0 = $c1; $d0 = $d1; } return $s; } /* -- END BORDER-RADIUS -- */ function PaintDivLnBorder($state = 0, $blvl = 0, $h = 0) { // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom $this->ColDetails[$this->CurrCol]['bottom_margin'] = $this->y + $h; $save_y = $this->y; $w = $this->blk[$blvl]['width']; $x0 = $this->x; // left $y0 = $this->y; // top $x1 = $this->x + $w; // bottom $y1 = $this->y + $h; // bottom $continuingpage = (isset($this->blk[$blvl]['startpage']) && $this->blk[$blvl]['startpage'] != $this->page); if ($this->blk[$blvl]['border_top'] && ($state == 1 || $state == 3)) { $tbd = $this->blk[$blvl]['border_top']; if (isset($tbd['s']) && $tbd['s']) { $this->_setBorderLine($tbd); $this->y = $y0 + ($tbd['w'] / 2); if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { $this->_setDashBorder($tbd['style'], '', $continuingpage, 'T'); $this->Line($x0 + ($tbd['w'] / 2), $this->y, $x0 + $w - ($tbd['w'] / 2), $this->y); } else { $this->SetLineJoin(0); $this->SetLineCap(0); $this->Line($x0, $this->y, $x0 + $w, $this->y); } $this->y += $tbd['w']; // Reset Corners and Dash off $this->SetLineJoin(2); $this->SetLineCap(2); $this->SetDash(); } } if ($this->blk[$blvl]['border_left']) { $tbd = $this->blk[$blvl]['border_left']; if (isset($tbd['s']) && $tbd['s']) { $this->_setBorderLine($tbd); if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { $this->y = $y0 + ($tbd['w'] / 2); $this->_setDashBorder($tbd['style'], '', $continuingpage, 'L'); $this->Line($x0 + ($tbd['w'] / 2), $this->y, $x0 + ($tbd['w'] / 2), $y0 + $h - ($tbd['w'] / 2)); } else { $this->y = $y0; $this->SetLineJoin(0); $this->SetLineCap(0); $this->Line($x0 + ($tbd['w'] / 2), $this->y, $x0 + ($tbd['w'] / 2), $y0 + $h); } $this->y += $tbd['w']; // Reset Corners and Dash off $this->SetLineJoin(2); $this->SetLineCap(2); $this->SetDash(); } } if ($this->blk[$blvl]['border_right']) { $tbd = $this->blk[$blvl]['border_right']; if (isset($tbd['s']) && $tbd['s']) { $this->_setBorderLine($tbd); if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { $this->y = $y0 + ($tbd['w'] / 2); $this->_setDashBorder($tbd['style'], '', $continuingpage, 'R'); $this->Line($x0 + $w - ($tbd['w'] / 2), $this->y, $x0 + $w - ($tbd['w'] / 2), $y0 + $h - ($tbd['w'] / 2)); } else { $this->y = $y0; $this->SetLineJoin(0); $this->SetLineCap(0); $this->Line($x0 + $w - ($tbd['w'] / 2), $this->y, $x0 + $w - ($tbd['w'] / 2), $y0 + $h); } $this->y += $tbd['w']; // Reset Corners and Dash off $this->SetLineJoin(2); $this->SetLineCap(2); $this->SetDash(); } } if ($this->blk[$blvl]['border_bottom'] && $state > 1) { $tbd = $this->blk[$blvl]['border_bottom']; if (isset($tbd['s']) && $tbd['s']) { $this->_setBorderLine($tbd); $this->y = $y0 + $h - ($tbd['w'] / 2); if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { $this->_setDashBorder($tbd['style'], '', $continuingpage, 'B'); $this->Line($x0 + ($tbd['w'] / 2), $this->y, $x0 + $w - ($tbd['w'] / 2), $this->y); } else { $this->SetLineJoin(0); $this->SetLineCap(0); $this->Line($x0, $this->y, $x0 + $w, $this->y); } $this->y += $tbd['w']; // Reset Corners and Dash off $this->SetLineJoin(2); $this->SetLineCap(2); $this->SetDash(); } } $this->SetDash(); $this->y = $save_y; } function PaintImgBorder($objattr, $is_table) { // Borders are disabled in columns - messes up the repositioning in printcolumnbuffer if ($this->ColActive) { return; } // *COLUMNS* if ($is_table) { $k = $this->shrin_k; } else { $k = 1; } $h = (isset($objattr['BORDER-HEIGHT']) ? $objattr['BORDER-HEIGHT'] : 0); $w = (isset($objattr['BORDER-WIDTH']) ? $objattr['BORDER-WIDTH'] : 0); $x0 = (isset($objattr['BORDER-X']) ? $objattr['BORDER-X'] : 0); $y0 = (isset($objattr['BORDER-Y']) ? $objattr['BORDER-Y'] : 0); // BORDERS if ($objattr['border_top']) { $tbd = $objattr['border_top']; if (!empty($tbd['s'])) { $this->_setBorderLine($tbd, $k); if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { $this->_setDashBorder($tbd['style'], '', '', 'T'); } $this->Line($x0, $y0, $x0 + $w, $y0); // Reset Corners and Dash off $this->SetLineJoin(2); $this->SetLineCap(2); $this->SetDash(); } } if ($objattr['border_left']) { $tbd = $objattr['border_left']; if (!empty($tbd['s'])) { $this->_setBorderLine($tbd, $k); if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { $this->_setDashBorder($tbd['style'], '', '', 'L'); } $this->Line($x0, $y0, $x0, $y0 + $h); // Reset Corners and Dash off $this->SetLineJoin(2); $this->SetLineCap(2); $this->SetDash(); } } if ($objattr['border_right']) { $tbd = $objattr['border_right']; if (!empty($tbd['s'])) { $this->_setBorderLine($tbd, $k); if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { $this->_setDashBorder($tbd['style'], '', '', 'R'); } $this->Line($x0 + $w, $y0, $x0 + $w, $y0 + $h); // Reset Corners and Dash off $this->SetLineJoin(2); $this->SetLineCap(2); $this->SetDash(); } } if ($objattr['border_bottom']) { $tbd = $objattr['border_bottom']; if (!empty($tbd['s'])) { $this->_setBorderLine($tbd, $k); if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { $this->_setDashBorder($tbd['style'], '', '', 'B'); } $this->Line($x0, $y0 + $h, $x0 + $w, $y0 + $h); // Reset Corners and Dash off $this->SetLineJoin(2); $this->SetLineCap(2); $this->SetDash(); } } $this->SetDash(); $this->SetAlpha(1); } /* -- END HTML-CSS -- */ function Reset() { $this->SetTColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); $this->SetFColor($this->colorConverter->convert(255, $this->PDFAXwarnings)); $this->SetAlpha(1); $this->colorarray = ''; $this->spanbgcolorarray = ''; $this->spanbgcolor = false; $this->spanborder = false; $this->spanborddet = []; $this->ResetStyles(); $this->HREF = ''; $this->textparam = []; $this->SetTextOutline(); $this->textvar = 0x00; // mPDF 5.7.1 $this->OTLtags = []; $this->textshadow = ''; $this->currentLang = $this->default_lang; // mPDF 6 $this->RestrictUnicodeFonts($this->default_available_fonts); // mPDF 6 $this->SetFont($this->default_font, '', 0, false); $this->SetFontSize($this->default_font_size, false); $this->currentfontfamily = ''; $this->currentfontsize = ''; $this->currentfontstyle = ''; /* -- TABLES -- */ if ($this->tableLevel && isset($this->table[1][1]['cellLineHeight'])) { $this->SetLineHeight('', $this->table[1][1]['cellLineHeight']); // *TABLES* } else { /* -- END TABLES -- */ if (isset($this->blk[$this->blklvl]['line_height']) && $this->blk[$this->blklvl]['line_height']) { $this->SetLineHeight('', $this->blk[$this->blklvl]['line_height']); // sets default line height } } $this->lSpacingCSS = ''; $this->wSpacingCSS = ''; $this->fixedlSpacing = false; $this->minwSpacing = 0; $this->SetDash(); // restore to no dash $this->dash_on = false; $this->dotted_on = false; $this->divwidth = 0; $this->divheight = 0; $this->cellTextAlign = ''; $this->cellLineHeight = ''; $this->cellLineStackingStrategy = ''; $this->cellLineStackingShift = ''; $this->oldy = -1; $bodystyle = []; if (isset($this->cssManager->CSS['BODY']['FONT-STYLE'])) { $bodystyle['FONT-STYLE'] = $this->cssManager->CSS['BODY']['FONT-STYLE']; } if (isset($this->cssManager->CSS['BODY']['FONT-WEIGHT'])) { $bodystyle['FONT-WEIGHT'] = $this->cssManager->CSS['BODY']['FONT-WEIGHT']; } if (isset($this->cssManager->CSS['BODY']['COLOR'])) { $bodystyle['COLOR'] = $this->cssManager->CSS['BODY']['COLOR']; } if (isset($bodystyle)) { $this->setCSS($bodystyle, 'BLOCK', 'BODY'); } } /* -- HTML-CSS -- */ function ReadMetaTags($html) { // changes anykey=anyvalue to anykey="anyvalue" (only do this when this happens inside tags) $regexp = '/ (\\w+?)=([^\\s>"]+)/si'; $html = preg_replace($regexp, " \$1=\"\$2\"", $html); if (preg_match('/(.*?)<\/title>/si', $html, $m)) { $this->SetTitle($m[1]); } preg_match_all('/]*?(name|content)="([^>]*?)" [^>]*?(name|content)="([^>]*?)".*?>/si', $html, $aux); $firstattr = $aux[1]; $secondattr = $aux[3]; for ($i = 0; $i < count($aux[0]); $i++) { $name = ( strtoupper($firstattr[$i]) == "NAME" ) ? strtoupper($aux[2][$i]) : strtoupper($aux[4][$i]); $content = ( strtoupper($firstattr[$i]) == "CONTENT" ) ? $aux[2][$i] : $aux[4][$i]; switch ($name) { case "KEYWORDS": $this->SetKeywords($content); break; case "AUTHOR": $this->SetAuthor($content); break; case "DESCRIPTION": $this->SetSubject($content); break; } } } function ReadCharset($html) { // Charset conversion if ($this->allow_charset_conversion) { if (preg_match('//si', $html, $m)) { if (strtoupper($m[1]) != 'UTF-8') { $this->charset_in = strtoupper($m[1]); } } } } function setCSS($arrayaux, $type = '', $tag = '') { // type= INLINE | BLOCK | TABLECELL // tag= BODY if (!is_array($arrayaux)) { return; // Removes PHP Warning } // mPDF 5.7.3 inline text-decoration parameters $preceeding_fontkey = $this->FontFamily . $this->FontStyle; $preceeding_fontsize = $this->FontSize; $spanbordset = false; $spanbgset = false; // mPDF 6 $prevlevel = (($this->blklvl == 0) ? 0 : $this->blklvl - 1); // Set font size first so that e.g. MARGIN 0.83em works on font size for this element if (isset($arrayaux['FONT-SIZE'])) { $v = $arrayaux['FONT-SIZE']; $firstLetter = substr($v, 0, 1); if (is_numeric($firstLetter) || ($firstLetter === '.')) { if ($type == 'BLOCK' && $this->blklvl > 0 && isset($this->blk[$this->blklvl - 1]['InlineProperties']) && isset($this->blk[$this->blklvl - 1]['InlineProperties']['size'])) { $mmsize = $this->sizeConverter->convert($v, $this->blk[$this->blklvl - 1]['InlineProperties']['size']); } elseif ($type == 'TABLECELL') { $mmsize = $this->sizeConverter->convert($v, $this->default_font_size / Mpdf::SCALE); } else { $mmsize = $this->sizeConverter->convert($v, $this->FontSize); } $this->SetFontSize($mmsize * (Mpdf::SCALE), false); // Get size in points (pt) } else { $v = strtoupper($v); if (isset($this->fontsizes[$v])) { $this->SetFontSize($this->fontsizes[$v] * $this->default_font_size, false); } } if ($tag == 'BODY') { $this->SetDefaultFontSize($this->FontSizePt); } } // mPDF 6 if (isset($arrayaux['LANG']) && $arrayaux['LANG']) { if ($this->autoLangToFont && !$this->usingCoreFont) { if ($arrayaux['LANG'] != $this->default_lang && $arrayaux['LANG'] != 'UTF-8') { list ($coreSuitable, $mpdf_pdf_unifont) = $this->languageToFont->getLanguageOptions($arrayaux['LANG'], $this->useAdobeCJK); if ($mpdf_pdf_unifont) { $arrayaux['FONT-FAMILY'] = $mpdf_pdf_unifont; } if ($tag == 'BODY') { $this->default_lang = $arrayaux['LANG']; } } } $this->currentLang = $arrayaux['LANG']; } // FOR INLINE and BLOCK OR 'BODY' if (isset($arrayaux['FONT-FAMILY'])) { $v = $arrayaux['FONT-FAMILY']; // If it is a font list, get all font types $aux_fontlist = explode(",", $v); $found = 0; foreach ($aux_fontlist as $f) { $fonttype = trim($f); $fonttype = preg_replace('/["\']*(.*?)["\']*/', '\\1', $fonttype); $fonttype = preg_replace('/ /', '', $fonttype); $v = strtolower(trim($fonttype)); if (isset($this->fonttrans[$v]) && $this->fonttrans[$v]) { $v = $this->fonttrans[$v]; } if ((!$this->onlyCoreFonts && in_array($v, $this->available_unifonts)) || in_array($v, ['ccourier', 'ctimes', 'chelvetica']) || ($this->onlyCoreFonts && in_array($v, ['courier', 'times', 'helvetica', 'arial'])) || in_array($v, ['sjis', 'uhc', 'big5', 'gb'])) { $fonttype = $v; $found = 1; break; } } if (!$found) { foreach ($aux_fontlist as $f) { $fonttype = trim($f); $fonttype = preg_replace('/["\']*(.*?)["\']*/', '\\1', $fonttype); $fonttype = preg_replace('/ /', '', $fonttype); $v = strtolower(trim($fonttype)); if (isset($this->fonttrans[$v]) && $this->fonttrans[$v]) { $v = $this->fonttrans[$v]; } if (in_array($v, $this->sans_fonts) || in_array($v, $this->serif_fonts) || in_array($v, $this->mono_fonts)) { $fonttype = $v; break; } } } if ($tag == 'BODY') { $this->SetDefaultFont($fonttype); } $this->SetFont($fonttype, $this->currentfontstyle, 0, false); } else { $this->SetFont($this->currentfontfamily, $this->currentfontstyle, 0, false); } foreach ($arrayaux as $k => $v) { if ($type != 'INLINE' && $tag != 'BODY' && $type != 'TABLECELL') { switch ($k) { // BORDERS case 'BORDER-TOP': $this->blk[$this->blklvl]['border_top'] = $this->border_details($v); if ($this->blk[$this->blklvl]['border_top']['s']) { $this->blk[$this->blklvl]['border'] = 1; } break; case 'BORDER-BOTTOM': $this->blk[$this->blklvl]['border_bottom'] = $this->border_details($v); if ($this->blk[$this->blklvl]['border_bottom']['s']) { $this->blk[$this->blklvl]['border'] = 1; } break; case 'BORDER-LEFT': $this->blk[$this->blklvl]['border_left'] = $this->border_details($v); if ($this->blk[$this->blklvl]['border_left']['s']) { $this->blk[$this->blklvl]['border'] = 1; } break; case 'BORDER-RIGHT': $this->blk[$this->blklvl]['border_right'] = $this->border_details($v); if ($this->blk[$this->blklvl]['border_right']['s']) { $this->blk[$this->blklvl]['border'] = 1; } break; // PADDING case 'PADDING-TOP': $this->blk[$this->blklvl]['padding_top'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); break; case 'PADDING-BOTTOM': $this->blk[$this->blklvl]['padding_bottom'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); break; case 'PADDING-LEFT': if (($tag == 'UL' || $tag == 'OL') && $v == 'auto') { $this->blk[$this->blklvl]['padding_left'] = 'auto'; break; } $this->blk[$this->blklvl]['padding_left'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); break; case 'PADDING-RIGHT': if (($tag == 'UL' || $tag == 'OL') && $v == 'auto') { $this->blk[$this->blklvl]['padding_right'] = 'auto'; break; } $this->blk[$this->blklvl]['padding_right'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); break; // MARGINS case 'MARGIN-TOP': $tmp = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); if (isset($this->blk[$this->blklvl]['lastbottommargin'])) { if ($tmp > $this->blk[$this->blklvl]['lastbottommargin']) { $tmp -= $this->blk[$this->blklvl]['lastbottommargin']; } else { $tmp = 0; } } $this->blk[$this->blklvl]['margin_top'] = $tmp; break; case 'MARGIN-BOTTOM': $this->blk[$this->blklvl]['margin_bottom'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); break; case 'MARGIN-LEFT': $this->blk[$this->blklvl]['margin_left'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); break; case 'MARGIN-RIGHT': $this->blk[$this->blklvl]['margin_right'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); break; /* -- BORDER-RADIUS -- */ case 'BORDER-TOP-LEFT-RADIUS-H': $this->blk[$this->blklvl]['border_radius_TL_H'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); break; case 'BORDER-TOP-LEFT-RADIUS-V': $this->blk[$this->blklvl]['border_radius_TL_V'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); break; case 'BORDER-TOP-RIGHT-RADIUS-H': $this->blk[$this->blklvl]['border_radius_TR_H'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); break; case 'BORDER-TOP-RIGHT-RADIUS-V': $this->blk[$this->blklvl]['border_radius_TR_V'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); break; case 'BORDER-BOTTOM-LEFT-RADIUS-H': $this->blk[$this->blklvl]['border_radius_BL_H'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); break; case 'BORDER-BOTTOM-LEFT-RADIUS-V': $this->blk[$this->blklvl]['border_radius_BL_V'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); break; case 'BORDER-BOTTOM-RIGHT-RADIUS-H': $this->blk[$this->blklvl]['border_radius_BR_H'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); break; case 'BORDER-BOTTOM-RIGHT-RADIUS-V': $this->blk[$this->blklvl]['border_radius_BR_V'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); break; /* -- END BORDER-RADIUS -- */ case 'BOX-SHADOW': $bs = $this->cssManager->setCSSboxshadow($v); if ($bs) { $this->blk[$this->blklvl]['box_shadow'] = $bs; } break; case 'BACKGROUND-CLIP': if (strtoupper($v) == 'PADDING-BOX') { $this->blk[$this->blklvl]['background_clip'] = 'padding-box'; } elseif (strtoupper($v) == 'CONTENT-BOX') { $this->blk[$this->blklvl]['background_clip'] = 'content-box'; } break; case 'PAGE-BREAK-AFTER': if (strtoupper($v) == 'AVOID') { $this->blk[$this->blklvl]['page_break_after_avoid'] = true; } elseif (strtoupper($v) == 'ALWAYS' || strtoupper($v) == 'LEFT' || strtoupper($v) == 'RIGHT') { $this->blk[$this->blklvl]['page_break_after'] = strtoupper($v); } break; // mPDF 6 pagebreaktype case 'BOX-DECORATION-BREAK': if (strtoupper($v) == 'CLONE') { $this->blk[$this->blklvl]['box_decoration_break'] = 'clone'; } elseif (strtoupper($v) == 'SLICE') { $this->blk[$this->blklvl]['box_decoration_break'] = 'slice'; } break; case 'WIDTH': if (strtoupper($v) != 'AUTO') { $this->blk[$this->blklvl]['css_set_width'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); } break; // mPDF 6 Lists // LISTS case 'LIST-STYLE-TYPE': $this->blk[$this->blklvl]['list_style_type'] = strtolower($v); break; case 'LIST-STYLE-IMAGE': $this->blk[$this->blklvl]['list_style_image'] = strtolower($v); break; case 'LIST-STYLE-POSITION': $this->blk[$this->blklvl]['list_style_position'] = strtolower($v); break; }//end of switch($k) } if ($type != 'INLINE' && $type != 'TABLECELL') { // All block-level, including BODY tag switch ($k) { case 'TEXT-INDENT': // Computed value - to inherit $this->blk[$this->blklvl]['text_indent'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false) . 'mm'; break; case 'MARGIN-COLLAPSE': // Custom tag to collapse margins at top and bottom of page if (strtoupper($v) == 'COLLAPSE') { $this->blk[$this->blklvl]['margin_collapse'] = true; } break; case 'LINE-HEIGHT': $this->blk[$this->blklvl]['line_height'] = $this->fixLineheight($v); if (!$this->blk[$this->blklvl]['line_height']) { $this->blk[$this->blklvl]['line_height'] = 'N'; } // mPDF 6 break; // mPDF 6 case 'LINE-STACKING-STRATEGY': $this->blk[$this->blklvl]['line_stacking_strategy'] = strtolower($v); break; case 'LINE-STACKING-SHIFT': $this->blk[$this->blklvl]['line_stacking_shift'] = strtolower($v); break; case 'TEXT-ALIGN': // left right center justify switch (strtoupper($v)) { case 'LEFT': $this->blk[$this->blklvl]['align'] = "L"; break; case 'CENTER': $this->blk[$this->blklvl]['align'] = "C"; break; case 'RIGHT': $this->blk[$this->blklvl]['align'] = "R"; break; case 'JUSTIFY': $this->blk[$this->blklvl]['align'] = "J"; break; } break; /* -- BACKGROUNDS -- */ case 'BACKGROUND-GRADIENT': if ($type == 'BLOCK') { $this->blk[$this->blklvl]['gradient'] = $v; } break; /* -- END BACKGROUNDS -- */ case 'DIRECTION': if ($v) { $this->blk[$this->blklvl]['direction'] = strtolower($v); } break; } } // FOR INLINE ONLY if ($type == 'INLINE') { switch ($k) { case 'DISPLAY': if (strtoupper($v) == 'NONE') { $this->inlineDisplayOff = true; } break; case 'DIRECTION': break; } } // FOR INLINE ONLY if ($type == 'INLINE') { switch ($k) { // BORDERS case 'BORDER-TOP': $this->spanborddet['T'] = $this->border_details($v); $this->spanborder = true; $spanbordset = true; break; case 'BORDER-BOTTOM': $this->spanborddet['B'] = $this->border_details($v); $this->spanborder = true; $spanbordset = true; break; case 'BORDER-LEFT': $this->spanborddet['L'] = $this->border_details($v); $this->spanborder = true; $spanbordset = true; break; case 'BORDER-RIGHT': $this->spanborddet['R'] = $this->border_details($v); $this->spanborder = true; $spanbordset = true; break; case 'VISIBILITY': // block is set in OpenTag $v = strtolower($v); if ($v == 'visible' || $v == 'hidden' || $v == 'printonly' || $v == 'screenonly') { $this->textparam['visibility'] = $v; } break; }//end of switch($k) } if ($type != 'TABLECELL') { // FOR INLINE and BLOCK switch ($k) { case 'TEXT-ALIGN': // left right center justify if (strtoupper($v) == 'NOJUSTIFY' && $this->blk[$this->blklvl]['align'] == "J") { $this->blk[$this->blklvl]['align'] = ""; } break; // bgcolor only - to stay consistent with original html2fpdf case 'BACKGROUND': case 'BACKGROUND-COLOR': $cor = $this->colorConverter->convert($v, $this->PDFAXwarnings); if ($cor) { if ($tag == 'BODY') { $this->bodyBackgroundColor = $cor; } elseif ($type == 'INLINE') { $this->spanbgcolorarray = $cor; $this->spanbgcolor = true; $spanbgset = true; } else { $this->blk[$this->blklvl]['bgcolorarray'] = $cor; $this->blk[$this->blklvl]['bgcolor'] = true; } } elseif ($type != 'INLINE') { if ($this->ColActive) { $this->blk[$this->blklvl]['bgcolorarray'] = $this->blk[$prevlevel]['bgcolorarray']; $this->blk[$this->blklvl]['bgcolor'] = $this->blk[$prevlevel]['bgcolor']; } } break; case 'VERTICAL-ALIGN': // super and sub only dealt with here e.g. and switch (strtoupper($v)) { case 'SUPER': $this->textvar = ($this->textvar | TextVars::FA_SUPERSCRIPT); // mPDF 5.7.1 $this->textvar = ($this->textvar & ~TextVars::FA_SUBSCRIPT); // mPDF 5.7.3 inline text-decoration parameters if (isset($this->textparam['text-baseline'])) { $this->textparam['text-baseline'] += ($this->baselineSup) * $preceeding_fontsize; } else { $this->textparam['text-baseline'] = ($this->baselineSup) * $preceeding_fontsize; } break; case 'SUB': $this->textvar = ($this->textvar | TextVars::FA_SUBSCRIPT); $this->textvar = ($this->textvar & ~TextVars::FA_SUPERSCRIPT); // mPDF 5.7.3 inline text-decoration parameters if (isset($this->textparam['text-baseline'])) { $this->textparam['text-baseline'] += ($this->baselineSub) * $preceeding_fontsize; } else { $this->textparam['text-baseline'] = ($this->baselineSub) * $preceeding_fontsize; } break; case 'BASELINE': $this->textvar = ($this->textvar & ~TextVars::FA_SUBSCRIPT); $this->textvar = ($this->textvar & ~TextVars::FA_SUPERSCRIPT); // mPDF 5.7.3 inline text-decoration parameters if (isset($this->textparam['text-baseline'])) { unset($this->textparam['text-baseline']); } break; // mPDF 5.7.3 inline text-decoration parameters default: $lh = $this->_computeLineheight($this->blk[$this->blklvl]['line_height']); $sz = $this->sizeConverter->convert($v, $lh, $this->FontSize, false); $this->textvar = ($this->textvar & ~TextVars::FA_SUBSCRIPT); $this->textvar = ($this->textvar & ~TextVars::FA_SUPERSCRIPT); if ($sz) { if ($sz > 0) { $this->textvar = ($this->textvar | TextVars::FA_SUPERSCRIPT); } else { $this->textvar = ($this->textvar | TextVars::FA_SUBSCRIPT); } if (isset($this->textparam['text-baseline'])) { $this->textparam['text-baseline'] += $sz; } else { $this->textparam['text-baseline'] = $sz; } } } break; }//end of switch($k) } // FOR ALL switch ($k) { case 'LETTER-SPACING': $this->lSpacingCSS = $v; if (($this->lSpacingCSS || $this->lSpacingCSS === '0') && strtoupper($this->lSpacingCSS) != 'NORMAL') { $this->fixedlSpacing = $this->sizeConverter->convert($this->lSpacingCSS, $this->FontSize); } break; case 'WORD-SPACING': $this->wSpacingCSS = $v; if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') { $this->minwSpacing = $this->sizeConverter->convert($this->wSpacingCSS, $this->FontSize); } break; case 'FONT-STYLE': // italic normal oblique switch (strtoupper($v)) { case 'ITALIC': case 'OBLIQUE': $this->SetStyle('I', true); break; case 'NORMAL': $this->SetStyle('I', false); break; } break; case 'FONT-WEIGHT': // normal bold // Does not support: bolder, lighter, 100..900(step value=100) switch (strtoupper($v)) { case 'BOLD': $this->SetStyle('B', true); break; case 'NORMAL': $this->SetStyle('B', false); break; } break; case 'FONT-KERNING': if (strtoupper($v) == 'NORMAL' || (strtoupper($v) == 'AUTO' && $this->useKerning)) { /* -- OTL -- */ if ($this->CurrentFont['haskernGPOS']) { if (isset($this->OTLtags['Plus'])) { $this->OTLtags['Plus'] .= ' kern'; } else { $this->OTLtags['Plus'] = ' kern'; } } /* -- END OTL -- */ else { // *OTL* $this->textvar = ($this->textvar | TextVars::FC_KERNING); } // *OTL* } elseif (strtoupper($v) == 'NONE' || (strtoupper($v) == 'AUTO' && !$this->useKerning)) { if (isset($this->OTLtags['Plus'])) { $this->OTLtags['Plus'] = str_replace('kern', '', $this->OTLtags['Plus']); // *OTL* } if (isset($this->OTLtags['FFPlus'])) { $this->OTLtags['FFPlus'] = preg_replace('/kern[\d]*/', '', $this->OTLtags['FFPlus']); } $this->textvar = ($this->textvar & ~TextVars::FC_KERNING); } break; /* -- OTL -- */ case 'FONT-LANGUAGE-OVERRIDE': $v = strtoupper($v); if (strpos($v, 'NORMAL') !== false) { $this->fontLanguageOverride = ''; } else { $this->fontLanguageOverride = trim($v); } break; case 'FONT-VARIANT-POSITION': if (isset($this->OTLtags['Plus'])) { $this->OTLtags['Plus'] = str_replace(['sups', 'subs'], '', $this->OTLtags['Plus']); } switch (strtoupper($v)) { case 'SUPER': $this->OTLtags['Plus'] .= ' sups'; break; case 'SUB': $this->OTLtags['Plus'] .= ' subs'; break; case 'NORMAL': break; } break; case 'FONT-VARIANT-CAPS': $v = strtoupper($v); if (!isset($this->OTLtags['Plus'])) { $this->OTLtags['Plus'] = ''; } $this->OTLtags['Plus'] = str_replace(['c2sc', 'smcp', 'c2pc', 'pcap', 'unic', 'titl'], '', $this->OTLtags['Plus']); $this->textvar = ($this->textvar & ~TextVars::FC_SMALLCAPS); // ?????????????? if (strpos($v, 'ALL-SMALL-CAPS') !== false) { $this->OTLtags['Plus'] .= ' c2sc smcp'; } elseif (strpos($v, 'SMALL-CAPS') !== false) { if (isset($this->CurrentFont['hassmallcapsGSUB']) && $this->CurrentFont['hassmallcapsGSUB']) { $this->OTLtags['Plus'] .= ' smcp'; } else { $this->textvar = ($this->textvar | TextVars::FC_SMALLCAPS); } } elseif (strpos($v, 'ALL-PETITE-CAPS') !== false) { $this->OTLtags['Plus'] .= ' c2pc pcap'; } elseif (strpos($v, 'PETITE-CAPS') !== false) { $this->OTLtags['Plus'] .= ' pcap'; } elseif (strpos($v, 'UNICASE') !== false) { $this->OTLtags['Plus'] .= ' unic'; } elseif (strpos($v, 'TITLING-CAPS') !== false) { $this->OTLtags['Plus'] .= ' titl'; } break; case 'FONT-VARIANT-LIGATURES': $v = strtoupper($v); if (!isset($this->OTLtags['Plus'])) { $this->OTLtags['Plus'] = ''; } if (!isset($this->OTLtags['Minus'])) { $this->OTLtags['Minus'] = ''; } if (strpos($v, 'NORMAL') !== false) { $this->OTLtags['Minus'] = str_replace(['liga', 'clig', 'calt'], '', $this->OTLtags['Minus']); $this->OTLtags['Plus'] = str_replace(['dlig', 'hlig'], '', $this->OTLtags['Plus']); } elseif (strpos($v, 'NONE') !== false) { $this->OTLtags['Minus'] .= ' liga clig calt'; $this->OTLtags['Plus'] = str_replace(['dlig', 'hlig'], '', $this->OTLtags['Plus']); } if (strpos($v, 'NO-COMMON-LIGATURES') !== false) { $this->OTLtags['Minus'] .= ' liga clig'; } elseif (strpos($v, 'COMMON-LIGATURES') !== false) { $this->OTLtags['Minus'] = str_replace(['liga', 'clig'], '', $this->OTLtags['Minus']); } if (strpos($v, 'NO-CONTEXTUAL') !== false) { $this->OTLtags['Minus'] .= ' calt'; } elseif (strpos($v, 'CONTEXTUAL') !== false) { $this->OTLtags['Minus'] = str_replace('calt', '', $this->OTLtags['Minus']); } if (strpos($v, 'NO-DISCRETIONARY-LIGATURES') !== false) { $this->OTLtags['Plus'] = str_replace('dlig', '', $this->OTLtags['Plus']); } elseif (strpos($v, 'DISCRETIONARY-LIGATURES') !== false) { $this->OTLtags['Plus'] .= ' dlig'; } if (strpos($v, 'NO-HISTORICAL-LIGATURES') !== false) { $this->OTLtags['Plus'] = str_replace('hlig', '', $this->OTLtags['Plus']); } elseif (strpos($v, 'HISTORICAL-LIGATURES') !== false) { $this->OTLtags['Plus'] .= ' hlig'; } break; case 'FONT-VARIANT-NUMERIC': $v = strtoupper($v); if (!isset($this->OTLtags['Plus'])) { $this->OTLtags['Plus'] = ''; } if (strpos($v, 'NORMAL') !== false) { $this->OTLtags['Plus'] = str_replace(['ordn', 'zero', 'lnum', 'onum', 'pnum', 'tnum', 'frac', 'afrc'], '', $this->OTLtags['Plus']); } if (strpos($v, 'ORDINAL') !== false) { $this->OTLtags['Plus'] .= ' ordn'; } if (strpos($v, 'SLASHED-ZERO') !== false) { $this->OTLtags['Plus'] .= ' zero'; } if (strpos($v, 'LINING-NUMS') !== false) { $this->OTLtags['Plus'] .= ' lnum'; $this->OTLtags['Plus'] = str_replace('onum', '', $this->OTLtags['Plus']); } elseif (strpos($v, 'OLDSTYLE-NUMS') !== false) { $this->OTLtags['Plus'] .= ' onum'; $this->OTLtags['Plus'] = str_replace('lnum', '', $this->OTLtags['Plus']); } if (strpos($v, 'PROPORTIONAL-NUMS') !== false) { $this->OTLtags['Plus'] .= ' pnum'; $this->OTLtags['Plus'] = str_replace('tnum', '', $this->OTLtags['Plus']); } elseif (strpos($v, 'TABULAR-NUMS') !== false) { $this->OTLtags['Plus'] .= ' tnum'; $this->OTLtags['Plus'] = str_replace('pnum', '', $this->OTLtags['Plus']); } if (strpos($v, 'DIAGONAL-FRACTIONS') !== false) { $this->OTLtags['Plus'] .= ' frac'; $this->OTLtags['Plus'] = str_replace('afrc', '', $this->OTLtags['Plus']); } elseif (strpos($v, 'STACKED-FRACTIONS') !== false) { $this->OTLtags['Plus'] .= ' afrc'; $this->OTLtags['Plus'] = str_replace('frac', '', $this->OTLtags['Plus']); } break; case 'FONT-VARIANT-ALTERNATES': // Only supports historical-forms $v = strtoupper($v); if (!isset($this->OTLtags['Plus'])) { $this->OTLtags['Plus'] = ''; } if (strpos($v, 'NORMAL') !== false) { $this->OTLtags['Plus'] = str_replace('hist', '', $this->OTLtags['Plus']); } if (strpos($v, 'HISTORICAL-FORMS') !== false) { $this->OTLtags['Plus'] .= ' hist'; } break; case 'FONT-FEATURE-SETTINGS': $v = strtolower($v); if (strpos($v, 'normal') !== false) { $this->OTLtags['FFMinus'] = ''; $this->OTLtags['FFPlus'] = ''; } else { if (!isset($this->OTLtags['FFPlus'])) { $this->OTLtags['FFPlus'] = ''; } if (!isset($this->OTLtags['FFMinus'])) { $this->OTLtags['FFMinus'] = ''; } $tags = preg_split('/[,]/', $v); foreach ($tags as $t) { if (preg_match('/[\"\']([a-zA-Z0-9]{4})[\"\']\s*(on|off|\d*){0,1}/', $t, $m)) { if ($m[2] == 'off' || $m[2] === '0') { if (strpos($this->OTLtags['FFMinus'], $m[1]) === false) { $this->OTLtags['FFMinus'] .= ' ' . $m[1]; } $this->OTLtags['FFPlus'] = preg_replace('/' . $m[1] . '[\d]*/', '', $this->OTLtags['FFPlus']); } else { if ($m[2] == 'on') { $m[2] = '1'; } if (strpos($this->OTLtags['FFPlus'], $m[1]) === false) { $this->OTLtags['FFPlus'] .= ' ' . $m[1] . $m[2]; } $this->OTLtags['FFMinus'] = str_replace($m[1], '', $this->OTLtags['FFMinus']); } } } } break; /* -- END OTL -- */ case 'TEXT-TRANSFORM': // none uppercase lowercase // Does support: capitalize switch (strtoupper($v)) { // Not working 100% case 'CAPITALIZE': $this->textvar = ($this->textvar | TextVars::FT_CAPITALIZE); // mPDF 5.7.1 $this->textvar = ($this->textvar & ~TextVars::FT_UPPERCASE); // mPDF 5.7.1 $this->textvar = ($this->textvar & ~TextVars::FT_LOWERCASE); // mPDF 5.7.1 break; case 'UPPERCASE': $this->textvar = ($this->textvar | TextVars::FT_UPPERCASE); // mPDF 5.7.1 $this->textvar = ($this->textvar & ~TextVars::FT_LOWERCASE); // mPDF 5.7.1 $this->textvar = ($this->textvar & ~TextVars::FT_CAPITALIZE); // mPDF 5.7.1 break; case 'LOWERCASE': $this->textvar = ($this->textvar | TextVars::FT_LOWERCASE); // mPDF 5.7.1 $this->textvar = ($this->textvar & ~TextVars::FT_UPPERCASE); // mPDF 5.7.1 $this->textvar = ($this->textvar & ~TextVars::FT_CAPITALIZE); // mPDF 5.7.1 break; case 'NONE': break; $this->textvar = ($this->textvar & ~TextVars::FT_UPPERCASE); // mPDF 5.7.1 $this->textvar = ($this->textvar & ~TextVars::FT_LOWERCASE); // mPDF 5.7.1 $this->textvar = ($this->textvar & ~TextVars::FT_CAPITALIZE); // mPDF 5.7.1 } break; case 'TEXT-SHADOW': $ts = $this->cssManager->setCSStextshadow($v); if ($ts) { $this->textshadow = $ts; } break; case 'HYPHENS': if (strtoupper($v) == 'NONE') { $this->textparam['hyphens'] = 2; } elseif (strtoupper($v) == 'AUTO') { $this->textparam['hyphens'] = 1; } elseif (strtoupper($v) == 'MANUAL') { $this->textparam['hyphens'] = 0; } break; case 'TEXT-OUTLINE': if (strtoupper($v) == 'NONE') { $this->textparam['outline-s'] = false; } break; case 'TEXT-OUTLINE-WIDTH': case 'OUTLINE-WIDTH': switch (strtoupper($v)) { case 'THIN': $v = '0.03em'; break; case 'MEDIUM': $v = '0.05em'; break; case 'THICK': $v = '0.07em'; break; } $w = $this->sizeConverter->convert($v, $this->FontSize, $this->FontSize); if ($w) { $this->textparam['outline-WIDTH'] = $w; $this->textparam['outline-s'] = true; } else { $this->textparam['outline-s'] = false; } break; case 'TEXT-OUTLINE-COLOR': case 'OUTLINE-COLOR': if (strtoupper($v) == 'INVERT') { if ($this->colorarray) { $cor = $this->colorarray; $this->textparam['outline-COLOR'] = $this->colorConverter->invert($cor); } else { $this->textparam['outline-COLOR'] = $this->colorConverter->convert(255, $this->PDFAXwarnings); } } else { $cor = $this->colorConverter->convert($v, $this->PDFAXwarnings); if ($cor) { $this->textparam['outline-COLOR'] = $cor; } } break; case 'COLOR': // font color $cor = $this->colorConverter->convert($v, $this->PDFAXwarnings); if ($cor) { $this->colorarray = $cor; $this->SetTColor($cor); } break; }//end of switch($k) }//end of foreach // mPDF 5.7.3 inline text-decoration parameters // Needs to be set at the end - after vertical-align = super/sub, so that textparam['text-baseline'] is set if (isset($arrayaux['TEXT-DECORATION'])) { $v = $arrayaux['TEXT-DECORATION']; // none underline line-through (strikeout) // Does not support: blink if (stristr($v, 'LINE-THROUGH')) { $this->textvar = ($this->textvar | TextVars::FD_LINETHROUGH); // mPDF 5.7.3 inline text-decoration parameters if (isset($this->textparam['text-baseline'])) { $this->textparam['s-decoration']['baseline'] = $this->textparam['text-baseline']; } else { $this->textparam['s-decoration']['baseline'] = 0; } $this->textparam['s-decoration']['fontkey'] = $this->FontFamily . $this->FontStyle; $this->textparam['s-decoration']['fontsize'] = $this->FontSize; $this->textparam['s-decoration']['color'] = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG } if (stristr($v, 'UNDERLINE')) { $this->textvar = ($this->textvar | TextVars::FD_UNDERLINE); // mPDF 5.7.3 inline text-decoration parameters if (isset($this->textparam['text-baseline'])) { $this->textparam['u-decoration']['baseline'] = $this->textparam['text-baseline']; } else { $this->textparam['u-decoration']['baseline'] = 0; } $this->textparam['u-decoration']['fontkey'] = $this->FontFamily . $this->FontStyle; $this->textparam['u-decoration']['fontsize'] = $this->FontSize; $this->textparam['u-decoration']['color'] = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG } if (stristr($v, 'OVERLINE')) { $this->textvar = ($this->textvar | TextVars::FD_OVERLINE); // mPDF 5.7.3 inline text-decoration parameters if (isset($this->textparam['text-baseline'])) { $this->textparam['o-decoration']['baseline'] = $this->textparam['text-baseline']; } else { $this->textparam['o-decoration']['baseline'] = 0; } $this->textparam['o-decoration']['fontkey'] = $this->FontFamily . $this->FontStyle; $this->textparam['o-decoration']['fontsize'] = $this->FontSize; $this->textparam['o-decoration']['color'] = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG } if (stristr($v, 'NONE')) { $this->textvar = ($this->textvar & ~TextVars::FD_UNDERLINE); $this->textvar = ($this->textvar & ~TextVars::FD_LINETHROUGH); $this->textvar = ($this->textvar & ~TextVars::FD_OVERLINE); // mPDF 5.7.3 inline text-decoration parameters if (isset($this->textparam['u-decoration'])) { unset($this->textparam['u-decoration']); } if (isset($this->textparam['s-decoration'])) { unset($this->textparam['s-decoration']); } if (isset($this->textparam['o-decoration'])) { unset($this->textparam['o-decoration']); } } } // mPDF 6 if ($spanbordset) { // BORDER has been set on this INLINE element if (isset($this->textparam['text-baseline'])) { $this->textparam['bord-decoration']['baseline'] = $this->textparam['text-baseline']; } else { $this->textparam['bord-decoration']['baseline'] = 0; } $this->textparam['bord-decoration']['fontkey'] = $this->FontFamily . $this->FontStyle; $this->textparam['bord-decoration']['fontsize'] = $this->FontSize; } if ($spanbgset) { // BACKGROUND[-COLOR] has been set on this INLINE element if (isset($this->textparam['text-baseline'])) { $this->textparam['bg-decoration']['baseline'] = $this->textparam['text-baseline']; } else { $this->textparam['bg-decoration']['baseline'] = 0; } $this->textparam['bg-decoration']['fontkey'] = $this->FontFamily . $this->FontStyle; $this->textparam['bg-decoration']['fontsize'] = $this->FontSize; } } /* -- END HTML-CSS -- */ function SetStyle($tag, $enable) { $this->$tag = $enable; $style = ''; foreach (['B', 'I'] as $s) { if ($this->$s) { $style .= $s; } } $this->currentfontstyle = $style; $this->SetFont('', $style, 0, false); } // Set multiple styles at one time function SetStylesArray($arr) { $style = ''; foreach (['B', 'I'] as $s) { if (isset($arr[$s])) { if ($arr[$s]) { $this->$s = true; $style .= $s; } else { $this->$s = false; } } elseif ($this->$s) { $style .= $s; } } $this->currentfontstyle = $style; $this->SetFont('', $style, 0, false); } // Set multiple styles at one $str e.g. "BI" function SetStyles($str) { $style = ''; foreach (['B', 'I'] as $s) { if (strpos($str, $s) !== false) { $this->$s = true; $style .= $s; } else { $this->$s = false; } } $this->currentfontstyle = $style; $this->SetFont('', $style, 0, false); } function ResetStyles() { foreach (['B', 'I'] as $s) { $this->$s = false; } $this->currentfontstyle = ''; $this->SetFont('', '', 0, false); } function DisableTags($str = '') { if ($str == '') { // enable all tags // Insert new supported tags in the long string below. $this->enabledtags = "