Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add possibility to show scissors instead of text if printable=false #258

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
/example/HtmlOutput/html-example.htm
/example/FpdfOutput/fpdf_example.pdf
/.php-cs-fixer.cache
/.phpunit.result.cache
/composer.lock
.idea/
18 changes: 15 additions & 3 deletions example/FpdfOutput/fpdf-example.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php declare(strict_types=1);

use Sprain\SwissQrBill as QrBill;
use Sprain\SwissQrBill\PaymentPart\Output\PrintOptions;

require __DIR__ . '/../../vendor/autoload.php';

Expand All @@ -16,15 +17,26 @@
// use \Fpdf\Traits\MemoryImageSupport\MemImageTrait;
// };

// In case you want to draw scissors and dashed lines, use this way to create your FPDF instance:
// $fpdf = new class('P', 'mm', 'A4') extends \Fpdf\Fpdf {
// use \Sprain\SwissQrBill\PaymentPart\Output\FpdfOutput\FpdfTrait;
// };

$fpdf->AddPage();

// 3. Create a full payment part for FPDF
// 3. Optional, set layout options
$options = new PrintOptions();
$options
->setPrintable(false)
->setSeparatorSymbol(false); // TRUE to show scissors instead of text

// 4. Create a full payment part for FPDF
$output = new QrBill\PaymentPart\Output\FpdfOutput\FpdfOutput($qrBill, 'en', $fpdf);
$output
->setPrintable(false)
->setPrintOptions($options)
->getPaymentPart();

// 4. For demo purposes, let's save the generated example in a file
// 5. For demo purposes, let's save the generated example in a file
$examplePath = __DIR__ . "/fpdf_example.pdf";
$fpdf->Output($examplePath, 'F');

Expand Down
13 changes: 10 additions & 3 deletions example/HtmlOutput/html-example.php
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
<?php declare(strict_types=1);

use Sprain\SwissQrBill as QrBill;
use Sprain\SwissQrBill\PaymentPart\Output\PrintOptions;

require __DIR__ . '/../../vendor/autoload.php';

// 1. Let's load the base example to define the qr bill contents
require __DIR__ . '/../example.php';

// 2. Create a full payment part in HTML
// 2. Optional, set layout options
$options = new PrintOptions();
$options
->setPrintable(false)
->setSeparatorSymbol(false); // TRUE to show scissors instead of text

// 3. Create a full payment part in HTML
$output = new QrBill\PaymentPart\Output\HtmlOutput\HtmlOutput($qrBill, 'en');

$html = $output
->setPrintable(false)
->setPrintOptions($options)
->getPaymentPart();

// 3. For demo purposes, let's save the generated example in a file
// 4. For demo purposes, let's save the generated example in a file
$examplePath = __DIR__ . '/html-example.htm';
file_put_contents($examplePath, $html);

Expand Down
13 changes: 10 additions & 3 deletions example/TcPdfOutput/tcpdf-example.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php declare(strict_types=1);

use Sprain\SwissQrBill as QrBill;
use Sprain\SwissQrBill\PaymentPart\Output\PrintOptions;

require __DIR__ . '/../../vendor/autoload.php';

Expand All @@ -14,13 +15,19 @@
$tcPdf->setPrintFooter(false);
$tcPdf->AddPage();

// 3. Create a full payment part for TcPDF
// 3. Optional, set layout options
$options = new PrintOptions();
$options
->setPrintable(false)
->setSeparatorSymbol(false); // TRUE to show scissors instead of text

// 4. Create a full payment part for TcPDF
$output = new QrBill\PaymentPart\Output\TcPdfOutput\TcPdfOutput($qrBill, 'en', $tcPdf);
$output
->setPrintable(false)
->setPrintOptions($options)
->getPaymentPart();

// 4. For demo purposes, let's save the generated example in a file
// 5. For demo purposes, let's save the generated example in a file
$examplePath = __DIR__ . "/tcpdf_example.pdf";
$tcPdf->Output($examplePath, 'F');

Expand Down
28 changes: 22 additions & 6 deletions src/PaymentPart/Output/AbstractOutput.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Sprain\SwissQrBill\DataGroup\Element\PaymentReference;
use Sprain\SwissQrBill\PaymentPart\Output\Element\FurtherInformation;
use Sprain\SwissQrBill\PaymentPart\Output\Element\OutputElementInterface;
use Sprain\SwissQrBill\PaymentPart\Output\Element\Placeholder;
use Sprain\SwissQrBill\PaymentPart\Output\Element\Text;
use Sprain\SwissQrBill\PaymentPart\Output\Element\Title;
Expand All @@ -15,14 +14,14 @@ abstract class AbstractOutput implements OutputInterface
{
protected QrBill $qrBill;
protected string $language;
protected bool $printable;
protected PrintOptions $printOptions;
protected string $qrCodeImageFormat;

public function __construct(QrBill $qrBill, string $language)
{
$this->qrBill = $qrBill;
$this->language = $language;
$this->printable = false;
$this->printOptions = new PrintOptions();
$this->qrCodeImageFormat = QrCode::FILE_FORMAT_SVG;
}

Expand All @@ -36,16 +35,33 @@ public function getLanguage(): ?string
return $this->language;
}

/**
* @deprecated Will be removed in next major release. Use setPrintOptions() instead.
*/
public function setPrintable(bool $printable): static
{
$this->printable = $printable;

$this->printOptions->setPrintable($printable);
return $this;
}

/**
* @deprecated Will be removed in next major release. Use getPrintOptions() instead.
*/
public function isPrintable(): bool
{
return $this->printable;
return $this->printOptions->isPrintable();
}

public function setPrintOptions(PrintOptions $printOptions): static
{
$this->printOptions = $printOptions;

return $this;
}
tafel marked this conversation as resolved.
Show resolved Hide resolved

public function getPrintOptions(): PrintOptions
{
return $this->printOptions;
}

public function setQrCodeImageFormat(string $fileExtension): static
Expand Down
84 changes: 74 additions & 10 deletions src/PaymentPart/Output/FpdfOutput/FpdfOutput.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
use Sprain\SwissQrBill\PaymentPart\Output\Element\Placeholder;
use Sprain\SwissQrBill\PaymentPart\Output\Element\Text;
use Sprain\SwissQrBill\PaymentPart\Output\Element\Title;
use Sprain\SwissQrBill\PaymentPart\Output\LineStyle;
use Sprain\SwissQrBill\PaymentPart\Output\VerticalSeparatorSymbolPosition;
use Sprain\SwissQrBill\PaymentPart\Translation\Translation;
use Sprain\SwissQrBill\QrBill;
use Sprain\SwissQrBill\QrCode\QrCode;
Expand All @@ -24,6 +26,9 @@ final class FpdfOutput extends AbstractOutput
private const ALIGN_RIGHT = 'R';
private const ALIGN_CENTER = 'C';
private const FONT = 'Helvetica';
private const FONT_UNICODE = 'zapfdingbats';
private const FONT_UNICODE_CHAR_SCISSORS = '"';
private const FONT_UNICODE_CHAR_DOWN_ARROW = 't';

// Positioning
private const CURRENCY_AMOUNT_Y = 259.3;
Expand All @@ -41,6 +46,8 @@ final class FpdfOutput extends AbstractOutput
private const FONT_SIZE_TITLE_PAYMENT_PART = 8;
private const FONT_SIZE_PAYMENT_PART = 10;
private const FONT_SIZE_FURTHER_INFORMATION = 7;
private const FONT_SIZE_SCISSORS = 14;
private const FONT_SIZE_DOWN_ARROW = 10;

// Line spacing
private const LINE_SPACING_RECEIPT = 3.4;
Expand Down Expand Up @@ -135,7 +142,7 @@ private function addSwissQrCodeImage(): void
private function addInformationContentReceipt(): void
{
// Title
$this->fpdf->SetFont(self::FONT, 'B', self::FONT_SIZE_MAIN_TITLE);
$this->fpdf->SetFont($this->getFont(), 'B', self::FONT_SIZE_MAIN_TITLE);
$this->SetXY(self::LEFT_PART_X, self::TITLE_Y);
$this->fpdf->MultiCell(0, 7, $this->convertEncoding(Translation::get('receipt', $this->language)));

Expand All @@ -147,15 +154,15 @@ private function addInformationContentReceipt(): void
}

// Acceptance section
$this->fpdf->SetFont(self::FONT, 'B', self::FONT_SIZE_TITLE_RECEIPT);
$this->fpdf->SetFont($this->getFont(), 'B', self::FONT_SIZE_TITLE_RECEIPT);
$this->SetXY(self::LEFT_PART_X, 274.3);
$this->fpdf->Cell(54, 0, $this->convertEncoding(Translation::get('acceptancePoint', $this->language)), self::BORDER, '', self::ALIGN_RIGHT);
}

private function addInformationContent(): void
{
// Title
$this->fpdf->SetFont(self::FONT, 'B', self::FONT_SIZE_MAIN_TITLE);
$this->fpdf->SetFont($this->getFont(), 'B', self::FONT_SIZE_MAIN_TITLE);
$this->SetXY(self::RIGHT_PART_X, 195.2);
$this->fpdf->MultiCell(48, 7, $this->convertEncoding(Translation::get('paymentPart', $this->language)));

Expand Down Expand Up @@ -223,13 +230,65 @@ private function addFurtherInformationContent(): void

private function addSeparatorContentIfNotPrintable(): void
{
if (!$this->isPrintable()) {
$layout = $this->getPrintOptions();
if ($layout->isPrintable()) {
return;
}

if ($layout->getLineStyle() !== LineStyle::NONE) {
$this->fpdf->SetLineWidth(0.1);
if ($layout->getLineStyle() === LineStyle::DASHED) {
if (!method_exists($this->fpdf, 'swissQrBillSetDash')) {
throw new MissingTraitException('Missing FpdfTrait in this fpdf instance. See fpdf-example.php within this library.');
}
$this->fpdf->swissQrBillSetDash(2, 1);
}
$this->fpdf->Line(2 + $this->offsetX, 193 + $this->offsetY, 208 + $this->offsetX, 193 + $this->offsetY);
$this->fpdf->Line(62 + $this->offsetX, 193 + $this->offsetY, 62 + $this->offsetX, 296 + $this->offsetY);
$this->fpdf->SetFont(self::FONT, '', self::FONT_SIZE_FURTHER_INFORMATION);
$this->setY(189.6);
$this->fpdf->MultiCell(0, 0, $this->convertEncoding(Translation::get('separate', $this->language)), self::BORDER, self::ALIGN_CENTER);
if ($layout->getLineStyle() === LineStyle::DASHED && method_exists($this->fpdf, 'swissQrBillSetDash')) {
$this->fpdf->swissQrBillSetDash(0);
}
}

if ($layout->hasSeparatorSymbol()) {
$this->fpdf->SetFont(self::FONT_UNICODE, '', self::FONT_SIZE_SCISSORS);
// horizontal scissors
$this->setXY(2 + $this->offsetX + 5, 193 + $this->offsetY + 0.2);
$this->fpdf->Cell(1, 0, self::FONT_UNICODE_CHAR_SCISSORS, 0, 0, 'C');
// vertical scissors
if (!method_exists($this->fpdf, 'swissQrBillTextWithRotation')) {
throw new MissingTraitException('Missing FpdfTrait in this fpdf instance. See fpdf-example.php within this library.');
}
if ($layout->getVerticalSeparatorSymbolPosition() === VerticalSeparatorSymbolPosition::TOP) {
$this->fpdf->swissQrBillTextWithRotation(62 + $this->offsetX - 1.7, 193 + $this->offsetY + 4, self::FONT_UNICODE_CHAR_SCISSORS, -90);
} else {
$this->fpdf->swissQrBillTextWithRotation(62 + $this->offsetX + 1.7, 193 + $this->offsetY + 90, self::FONT_UNICODE_CHAR_SCISSORS, 90);
}
}

if ($layout->hasText()) {
$this->fpdf->SetFont($this->getFont(), '', self::FONT_SIZE_FURTHER_INFORMATION);
$y = 189.6;
$this->setY($y);
$separateText = $this->convertEncoding(Translation::get('separate', $this->language));
$this->fpdf->MultiCell(0, 0, $separateText, self::BORDER, self::ALIGN_CENTER);

if ($layout->hasTextDownArrows()) {
$textWidth = $this->fpdf->GetStringWidth($separateText);
$arrowMargin = 3;
$yoffset = 0.6;
$this->fpdf->SetFont(self::FONT_UNICODE, '', self::FONT_SIZE_DOWN_ARROW);

$arrows = str_pad('', 3, self::FONT_UNICODE_CHAR_DOWN_ARROW);

$xstart = ($this->fpdf->GetPageWidth() / 2) - ($textWidth / 2);
$this->fpdf->setXY($xstart - $arrowMargin, $y - $yoffset);
$this->fpdf->Cell(3, 1, $arrows, 0, 0, 'R', false);

$xstart = ($this->fpdf->getPageWidth() / 2) + ($textWidth / 2);
$this->fpdf->setXY($xstart, $y - $yoffset);
$this->fpdf->Cell(3, 1, $arrows, 0, 0, 'L', false);
}
}
}

Expand All @@ -254,7 +313,7 @@ private function setContentElement(OutputElementInterface $element, bool $isRece

private function setTitleElement(Title $element, bool $isReceiptPart): void
{
$this->fpdf->SetFont(self::FONT, 'B', $isReceiptPart ? self::FONT_SIZE_TITLE_RECEIPT : self::FONT_SIZE_TITLE_PAYMENT_PART);
$this->fpdf->SetFont($this->getFont(), 'B', $isReceiptPart ? self::FONT_SIZE_TITLE_RECEIPT : self::FONT_SIZE_TITLE_PAYMENT_PART);
$this->fpdf->MultiCell(
0,
2.8,
Expand All @@ -267,7 +326,7 @@ private function setTitleElement(Title $element, bool $isReceiptPart): void

private function setTextElement(Text $element, bool $isReceiptPart): void
{
$this->fpdf->SetFont(self::FONT, '', $isReceiptPart ? self::FONT_SIZE_RECEIPT : self::FONT_SIZE_PAYMENT_PART);
$this->fpdf->SetFont($this->getFont(), '', $isReceiptPart ? self::FONT_SIZE_RECEIPT : self::FONT_SIZE_PAYMENT_PART);
$this->fpdf->MultiCell(
$isReceiptPart ? 54 : 0,
$isReceiptPart ? 3.3 : 4,
Expand All @@ -280,7 +339,7 @@ private function setTextElement(Text $element, bool $isReceiptPart): void

private function setFurtherInformationElement(FurtherInformation $element): void
{
$this->fpdf->SetFont(self::FONT, '', self::FONT_SIZE_FURTHER_INFORMATION);
$this->fpdf->SetFont($this->getFont(), '', self::FONT_SIZE_FURTHER_INFORMATION);
$this->fpdf->MultiCell(
0,
4,
Expand Down Expand Up @@ -339,4 +398,9 @@ private function convertEncoding(string $text): string
// FPDF does not support unicode.
return mb_convert_encoding($text, 'CP1252', 'UTF-8');
}

private function getFont(): string
{
return self::FONT;
}
}
59 changes: 59 additions & 0 deletions src/PaymentPart/Output/FpdfOutput/FpdfTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php declare(strict_types=1);

namespace Sprain\SwissQrBill\PaymentPart\Output\FpdfOutput;

/**
* @internal DO NOT USE IT. Its purpose is only for the Swiss QR Bill library. Name and/or
* signature may change without any notification
*/
trait FpdfTrait
{
/**
* Set dash line style for the next ->Line() command
*
* @see http://www.fpdf.org/en/script/script33.php
*/
public function swissQrBillSetDash(float $black = 0, ?float $white = null): void
{
$white = $white === null ? $black : $white;

$s = $black > 0
? sprintf('[%.3F %.3F] 0 d', $black * $this->k, $white * $this->k)
: '[] 0 d';

$this->_out($s);
}

/**
* Rotate text
*
* @see http://www.fpdf.org/en/script/script31.php
*/
public function swissQrBillTextWithRotation(float $x, float $y, string $txt, float $txtAngle = 0, float $fontAngle = 0): void
{
$fontAngle += 90 + $txtAngle;
$txtAngle *= M_PI / 180;
$fontAngle *= M_PI / 180;

$txt_dx = cos($txtAngle);
$txt_dy = sin($txtAngle);
$font_dx = cos($fontAngle);
$font_dy = sin($fontAngle);

$s = sprintf(
'BT %.2F %.2F %.2F %.2F %.2F %.2F Tm (%s) Tj ET',
$txt_dx,
$txt_dy,
$font_dx,
$font_dy,
$x * $this->k,
($this->h-$y) * $this->k,
$this->_escape($txt)
);

if ($this->ColorFlag) {
$s = sprintf('q %s %s Q', $this->TextColor, $s);
}
$this->_out($s);
}
}
8 changes: 8 additions & 0 deletions src/PaymentPart/Output/FpdfOutput/MissingTraitException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php


namespace Sprain\SwissQrBill\PaymentPart\Output\FpdfOutput;

class MissingTraitException extends \RuntimeException
{
}
Loading
Loading