Skip to content

Commit

Permalink
Draw circles for dotted border
Browse files Browse the repository at this point in the history
Round caps extend outwards by half the line width, so lines and arcs
need to be shortened correspondingly.

Fixes #2239
Based on #2245

Co-authored-by: Louis Christ <l.christ54260@gmail.com>
  • Loading branch information
Mellthas and c-louis committed Jun 16, 2022
1 parent 1d6f991 commit 78102a7
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 76 deletions.
12 changes: 6 additions & 6 deletions src/Adapter/CPDF.php
Expand Up @@ -465,29 +465,29 @@ protected function y($y)
return $this->_height - $y;
}

public function line($x1, $y1, $x2, $y2, $color, $width, $style = [])
public function line($x1, $y1, $x2, $y2, $color, $width, $style = [], $cap = "butt")
{
$this->_set_stroke_color($color);
$this->_set_line_style($width, "butt", "", $style);
$this->_set_line_style($width, $cap, "", $style);

$this->_pdf->line($x1, $this->y($y1),
$x2, $this->y($y2));
$this->_set_line_transparency("Normal", $this->_current_opacity);
}

public function arc($x, $y, $r1, $r2, $astart, $aend, $color, $width, $style = [])
public function arc($x, $y, $r1, $r2, $astart, $aend, $color, $width, $style = [], $cap = "butt")
{
$this->_set_stroke_color($color);
$this->_set_line_style($width, "butt", "", $style);
$this->_set_line_style($width, $cap, "", $style);

$this->_pdf->ellipse($x, $this->y($y), $r1, $r2, 0, 8, $astart, $aend, false, false, true, false);
$this->_set_line_transparency("Normal", $this->_current_opacity);
}

public function rectangle($x1, $y1, $w, $h, $color, $width, $style = [])
public function rectangle($x1, $y1, $w, $h, $color, $width, $style = [], $cap = "butt")
{
$this->_set_stroke_color($color);
$this->_set_line_style($width, "butt", "", $style);
$this->_set_line_style($width, $cap, "", $style);
$this->_pdf->rectangle($x1, $this->y($y1) - $h, $w, $h);
$this->_set_line_transparency("Normal", $this->_current_opacity);
}
Expand Down
54 changes: 50 additions & 4 deletions src/Adapter/GD.php
Expand Up @@ -343,8 +343,32 @@ protected function convertStyle(array $style, int $color, int $width): array
return $gdStyle;
}

public function line($x1, $y1, $x2, $y2, $color, $width, $style = [])
{
public function line($x1, $y1, $x2, $y2, $color, $width, $style = [], $cap = "butt")
{
// Account for the fact that round and square caps are expected to
// extend outwards
if ($cap === "round" || $cap === "square") {
// Shift line by half width
$w = $width / 2;
$a = $x2 - $x1;
$b = $y2 - $y1;
$c = sqrt($a ** 2 + $b ** 2);
$dx = $a * $w / $c;
$dy = $b * $w / $c;

$x1 -= $dx;
$x2 -= $dx;
$y1 -= $dy;
$y2 -= $dy;

// Adapt dash pattern
if (is_array($style)) {
foreach ($style as $index => &$s) {
$s = $index % 2 === 0 ? $s + $width : $s - $width;
}
}
}

// Scale by the AA factor and DPI
$x1 = $this->_upscale($x1);
$y1 = $this->_upscale($y1);
Expand All @@ -369,8 +393,19 @@ public function line($x1, $y1, $x2, $y2, $color, $width, $style = [])
imageline($this->get_image(), $x1, $y1, $x2, $y2, $c);
}

public function arc($x, $y, $r1, $r2, $astart, $aend, $color, $width, $style = [])
public function arc($x, $y, $r1, $r2, $astart, $aend, $color, $width, $style = [], $cap = "butt")
{
// Account for the fact that round and square caps are expected to
// extend outwards
if ($cap === "round" || $cap === "square") {
// Adapt dash pattern
if (is_array($style)) {
foreach ($style as $index => &$s) {
$s = $index % 2 === 0 ? $s + $width : $s - $width;
}
}
}

// Scale by the AA factor and DPI
$x = $this->_upscale($x);
$y = $this->_upscale($y);
Expand Down Expand Up @@ -399,8 +434,19 @@ public function arc($x, $y, $r1, $r2, $astart, $aend, $color, $width, $style = [
imagearc($this->get_image(), $x, $y, $w, $h, $start, $end, $c);
}

public function rectangle($x1, $y1, $w, $h, $color, $width, $style = [])
public function rectangle($x1, $y1, $w, $h, $color, $width, $style = [], $cap = "butt")
{
// Account for the fact that round and square caps are expected to
// extend outwards
if ($cap === "round" || $cap === "square") {
// Adapt dash pattern
if (is_array($style)) {
foreach ($style as $index => &$s) {
$s = $index % 2 === 0 ? $s + $width : $s - $width;
}
}
}

// Scale by the AA factor and DPI
$x1 = $this->_upscale($x1);
$y1 = $this->_upscale($y1);
Expand Down
20 changes: 14 additions & 6 deletions src/Adapter/PDFLib.php
Expand Up @@ -495,6 +495,14 @@ protected function _set_line_style($width, $cap, $join, $dash)
$dash = [];
}

// Work around PDFLib limitation with 0 dash length:
// Value 0 for option 'dasharray' is too small (minimum 1.5e-05)
foreach ($dash as &$d) {
if ($d == 0) {
$d = 1.5e-5;
}
}

if (count($dash) === 1) {
$dash[] = $dash[0];
}
Expand Down Expand Up @@ -835,9 +843,9 @@ protected function y($y)
return $this->_height - $y;
}

public function line($x1, $y1, $x2, $y2, $color, $width, $style = [])
public function line($x1, $y1, $x2, $y2, $color, $width, $style = [], $cap = "butt")
{
$this->_set_line_style($width, "butt", "", $style);
$this->_set_line_style($width, $cap, "", $style);
$this->_set_stroke_color($color);

$y1 = $this->y($y1);
Expand All @@ -850,9 +858,9 @@ public function line($x1, $y1, $x2, $y2, $color, $width, $style = [])
$this->_set_stroke_opacity($this->_current_opacity, "Normal");
}

public function arc($x, $y, $r1, $r2, $astart, $aend, $color, $width, $style = [])
public function arc($x, $y, $r1, $r2, $astart, $aend, $color, $width, $style = [], $cap = "butt")
{
$this->_set_line_style($width, "butt", "", $style);
$this->_set_line_style($width, $cap, "", $style);
$this->_set_stroke_color($color);

$y = $this->y($y);
Expand All @@ -863,10 +871,10 @@ public function arc($x, $y, $r1, $r2, $astart, $aend, $color, $width, $style = [
$this->_set_stroke_opacity($this->_current_opacity, "Normal");
}

public function rectangle($x1, $y1, $w, $h, $color, $width, $style = [])
public function rectangle($x1, $y1, $w, $h, $color, $width, $style = [], $cap = "butt")
{
$this->_set_stroke_color($color);
$this->_set_line_style($width, "butt", "", $style);
$this->_set_line_style($width, $cap, "", $style);

$y1 = $this->y($y1) - $h;

Expand Down
61 changes: 32 additions & 29 deletions src/Canvas.php
Expand Up @@ -63,53 +63,56 @@ function set_page_count($count);
*
* See {@link Style::munge_color()} for the format of the color array.
* See {@link Cpdf::setLineStyle()} for a description of the format of the
* $style parameter (aka dash).
* $style and $cap parameters (aka dash and cap).
*
* @param float $x1
* @param float $y1
* @param float $x2
* @param float $y2
* @param array $color
* @param float $width
* @param array $style
* @param float $x1
* @param float $y1
* @param float $x2
* @param float $y2
* @param array $color
* @param float $width
* @param array $style
* @param string $cap `butt`, `round`, or `square`.
*/
function line($x1, $y1, $x2, $y2, $color, $width, $style = []);
function line($x1, $y1, $x2, $y2, $color, $width, $style = [], $cap = "butt");

/**
* Draws an arc
*
* See {@link Style::munge_color()} for the format of the color array.
* See {@link Cpdf::setLineStyle()} for a description of the format of the
* $style parameter (aka dash).
* $style and $cap parameters (aka dash and cap).
*
* @param float $x X coordinate of the arc
* @param float $y Y coordinate of the arc
* @param float $r1 Radius 1
* @param float $r2 Radius 2
* @param float $astart Start angle in degrees
* @param float $aend End angle in degrees
* @param array $color Color
* @param float $width
* @param array $style
* @param float $x X coordinate of the arc
* @param float $y Y coordinate of the arc
* @param float $r1 Radius 1
* @param float $r2 Radius 2
* @param float $astart Start angle in degrees
* @param float $aend End angle in degrees
* @param array $color Color
* @param float $width
* @param array $style
* @param string $cap `butt`, `round`, or `square`.
*/
function arc($x, $y, $r1, $r2, $astart, $aend, $color, $width, $style = []);
function arc($x, $y, $r1, $r2, $astart, $aend, $color, $width, $style = [], $cap = "butt");

/**
* Draws a rectangle at x1,y1 with width w and height h
*
* See {@link Style::munge_color()} for the format of the color array.
* See {@link Cpdf::setLineStyle()} for a description of the format of the
* $style parameter (aka dash).
* $style and $cap parameters (aka dash and cap).
*
* @param float $x1
* @param float $y1
* @param float $w
* @param float $h
* @param array $color
* @param float $width
* @param array $style
* @param float $x1
* @param float $y1
* @param float $w
* @param float $h
* @param array $color
* @param float $width
* @param array $style
* @param string $cap `butt`, `round`, or `square`.
*/
function rectangle($x1, $y1, $w, $h, $color, $width, $style = []);
function rectangle($x1, $y1, $w, $h, $color, $width, $style = [], $cap = "butt");

/**
* Draws a filled rectangle at x1,y1 with width w and height h
Expand Down

0 comments on commit 78102a7

Please sign in to comment.