Skip to content

Instantly share code, notes, and snippets.

@jef-sure
Last active March 19, 2021 14:09
Show Gist options
  • Save jef-sure/b0f780b8d4273b4721618f46f74a708c to your computer and use it in GitHub Desktop.
Save jef-sure/b0f780b8d4273b4721618f46f74a708c to your computer and use it in GitHub Desktop.
use PDF::Haru;
use Text::QRCode;
use POSIX 'floor';
use strict;
use warnings;
# create new document
my $pdf = PDF::Haru::New();
#$pdf->LoadTTFontFromFile("/usr/share/fonts/truetype/msttcorefonts/arial.ttf", HPDF_TRUE);
# add page
my $page = $pdf->AddPage();
# set page size and orientation
$page->SetSize(HPDF_PAGE_SIZE_A4, HPDF_PAGE_PORTRAIT);
#my $font = $pdf->GetFont("ArialMT", "StandardEncoding");
my $font = $pdf->GetFont("Helvetica", "StandardEncoding");
$page->SetFontAndSize($font, 12);
my $max = 100;
my $page_width = $page->GetWidth();
my $page_height = $page->GetHeight();
my $pixes_in_mm = $page->GetWidth() / 210;
my $zero_width = $page->TextWidth("0");
my $template_width = $page->TextWidth("0" x 9);
sub mm_to_pix ($) {
return $_[0] * $pixes_in_mm;
}
my @divisors_set;
sub init_divisors_set {
for (0 .. 99) {
$divisors_set[$_] = $_ < 3 || $_ == 10 ? 0 : 1;
}
}
sub get_divisor {
my $sum = 0;
$sum += $_ for @divisors_set;
my $w = rand() * $sum;
my $d;
$sum = 0;
for ($d = 0; $d < @divisors_set; ++$d) {
$sum += $divisors_set[$d];
if ($sum > $w) {
last;
}
}
$divisors_set[$d] /= 3;
return $d;
}
sub make_equation {
my $divisor = get_divisor();
my $d = rand > 0.0 ? int(rand(90000)) + 10000 : int(rand(9000)) + 1000;
my $q = floor($d / $divisor);
$d = $q * $divisor;
return ("$d : $divisor", $q);
}
sub draw_qr {
my ($code, $x, $y, $width) = @_;
my $lw = $page->GetLineWidth();
my ($r, $g, $b) = $page->GetRGBStroke();
$page->SetRGBStroke(0.0, 0.0, 0.0);
my $qr_text_array = Text::QRCode->new()->plot($code);
my $qrpw = mm_to_pix($width / @$qr_text_array);
$page->SetLineWidth($qrpw);
for (my $row = 0; $row < @$qr_text_array; ++$row) {
my $ql = $qr_text_array->[$row];
for (my $col = 0; $col < @$ql; ++$col) {
if ($ql->[$col] eq '*') { # black
$page->MoveTo($x + $col * $qrpw, $y + $row * $qrpw);
$page->LineTo($x + ($col + 1) * $qrpw, $y + ($row + 0) * $qrpw);
}
}
}
$page->Stroke();
$page->SetLineWidth($lw);
$page->SetRGBStroke($r, $g, $b);
}
sub draw_equation {
my ($x, $y) = @_;
my ($text, $q) = make_equation();
my $tw = $page->TextWidth($text);
my $qr_shift = mm_to_pix(7 + 2);
draw_qr($q, $x, $y, 7);
my $xo = ($template_width - $tw) / 2;
$page->BeginText();
$page->TextOut($x + $xo + $qr_shift, $y, $text);
$page->TextOut($x + $template_width + $qr_shift, $y, "=");
$page->EndText();
$page->MoveTo($x + $template_width + $qr_shift + $zero_width + mm_to_pix(2), $y + mm_to_pix(-1));
$page->LineTo($x + $template_width + $qr_shift + $zero_width * 8, $y + mm_to_pix(-1));
$page->Stroke();
my ($r, $g, $b) = $page->GetRGBStroke();
$page->SetRGBStroke(0.0, 0.6, 1.0);
$page->SetLineWidth(0.3);
for (my $ly = $y + mm_to_pix(-4); $ly > $y - mm_to_pix(55); $ly -= mm_to_pix(5)) {
$page->MoveTo($x, $ly);
$page->LineTo($x + mm_to_pix(50), $ly);
}
for (my $lx = $x + mm_to_pix(2); $lx < $x + mm_to_pix(50); $lx += mm_to_pix(5)) {
$page->MoveTo($lx, $y - mm_to_pix(2));
$page->LineTo($lx, $y - mm_to_pix(57));
}
$page->Stroke();
$page->SetRGBStroke($r, $g, $b);
$page->SetLineWidth(1);
}
init_divisors_set();
for (my $x = mm_to_pix(20); $x < $page_width - int mm_to_pix 70; $x += int mm_to_pix 57) {
for (my $y = mm_to_pix(70); $y < $page_height - mm_to_pix(20); $y += int mm_to_pix 65) {
draw_equation($x, $y);
}
}
my $bottom = 10;
my $top = 297 - 20;
my $left = 15;
my $right = 210 - 15;
my $radius = 3;
$page->Arc(mm_to_pix($left + $radius), mm_to_pix($bottom + $radius), mm_to_pix($radius), 180, 270);
$page->Stroke();
$page->Arc(mm_to_pix($right - $radius), mm_to_pix($bottom + $radius), mm_to_pix($radius), 90, 180);
$page->Stroke();
$page->Arc(mm_to_pix($left + $radius), mm_to_pix($top - $radius), mm_to_pix($radius), 270, 360);
$page->Stroke();
$page->Arc(mm_to_pix($right - $radius), mm_to_pix($top - $radius), mm_to_pix($radius), 0, 90);
$page->Stroke();
$page->MoveTo(mm_to_pix($right - $radius), mm_to_pix($bottom));
$page->LineTo(mm_to_pix($left + $radius), mm_to_pix($bottom));
$page->MoveTo(mm_to_pix($right - $radius), mm_to_pix($top));
$page->LineTo(mm_to_pix($left + $radius), mm_to_pix($top));
$page->MoveTo(mm_to_pix($left), mm_to_pix($top - $radius));
$page->LineTo(mm_to_pix($left), mm_to_pix($bottom + $radius));
$page->MoveTo(mm_to_pix($right), mm_to_pix($top - $radius));
$page->LineTo(mm_to_pix($right), mm_to_pix($bottom + $radius));
$page->Stroke();
# save the document to a file
$pdf->SaveToFile("filename.pdf");
# cleanup
$pdf->Free();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment