From 572f3e278f340d8517a94cdd79455e4c76db56ea Mon Sep 17 00:00:00 2001 From: sergiotarxz Date: Fri, 7 Jun 2024 15:15:16 +0200 Subject: [PATCH] Adding inital support for printing. --- diploma-currado.png | Bin 0 -> 48169 bytes print.pl | 385 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 385 insertions(+) create mode 100644 diploma-currado.png create mode 100644 print.pl diff --git a/diploma-currado.png b/diploma-currado.png new file mode 100644 index 0000000000000000000000000000000000000000..d8a8f2be17ccc7fd51a08ec0072bd74185f09545 GIT binary patch literal 48169 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

J>@CYl(G6+o!C&+R{} zfG^E0{P5z}ny|A0v1if>&fYxQv=l>Xt*1cE9=EOf5?*K05P% zVw`Fn)V>yZogip5d)3x1^LLw}g$tAjm|NAY-a+wRcVoQyJl%i0;)Ivr=_1)8e_ieD z$ldOjHg3xsITcoKQzO&=-|g)b2$(kSyG)88u10r1QJp!)-=C2IR+bVxci#bTAyRM4 z-;s_Mc8?O2_19hBWsdPhmq?WOvuMF@?cGjF5BRYy8Q_X>VXbEOrR}EY{DZy-tf~y* zPx0xwz~b{wIk0LG!vV#-!&c;;Qtn;dv#X!LHXOI-X|xxA_Bm5%E=wm=n$0oZyif`k^lez literal 0 HcmV?d00001 diff --git a/print.pl b/print.pl new file mode 100644 index 0000000..ffc8f79 --- /dev/null +++ b/print.pl @@ -0,0 +1,385 @@ +#!/usr/bin/env perl + +use v5.38.2; + +use strict; +use warnings; +use feature 'signatures'; + +use Printer::ESCPOS; +use GD::Image; +use Cairo; +use Path::Tiny; +use Encode qw/decode/; +use Pango; +use Imager::QRCode; + +use Data::Dumper; + +my $debug = $ARGV[0] // 0; +my $vendor_id = 0x0416; +my $product_id = 0x5011; + +my $deviceFilePath = '/dev/usb/lp0'; + +my $device = Printer::ESCPOS->new( + driverType => 'File', + deviceFilePath => $deviceFilePath, +); + +my $diploma = get_gd_image('diploma-currado.png'); +my $black = $diploma->colorAllocate(0,0,0); +$diploma->stringFT($black, '/usr/share/fonts/noto-cjk/NotoSansCJK-Medium.ttc', 20, 0, 500, 190, 'Diploma al merito.'); +$diploma = $diploma->copyRotate90(); +my $tempdir = Path::Tiny->tempdir(CLEANUP=>0); +my $diploma_image = $tempdir->child('image.png'); +$diploma->_file($diploma_image); +image($device, ''.$diploma_image); + +$device->printer->lf for ( 0 .. 3 ); + +$device->printer->print; + +sub qr($device, $url) { + my $tmpdir = Path::Tiny->tempdir; + my $image_file = $tmpdir->child('image.png'); + my $qrcode = Imager::QRCode->new( size => 8 ); + my $img = $qrcode->plot( $url, {} ); + $img->write( file => '' . $image_file ) or die $img->errstr; + image($device, $image_file); + print_text($device, $url, 20); +} + +sub qr_as_gd_image($device, $url) { + my $tmpdir = Path::Tiny->tempdir; + my $image_file = $tmpdir->child('image.png'); + my $qrcode = Imager::QRCode->new( size => 8 ); + my $img = $qrcode->plot( $url, {} ); + $img->write( file => '' . $image_file ) or die $img->errstr; + return get_gd_image($image_file); +} + +sub get_gd_image($file) { + $file = path($file); + my ($extension) = $file =~ /\.(.*?)$/; + my $tempdir = Path::Tiny->tempdir; + my $new_image = $tempdir->child( 'image.' . $extension ); + system 'convert', $file, '-background', 'white', '-alpha', 'remove', + $new_image; + $file = $new_image; + my $image; + if ( $file =~ /\.png$/ ) { + $image = GD::Image->newFromPng( $file . '' ); + } + elsif ( $file =~ /\.jpg$/ ) { + $image = GD::Image->newFromJpeg( $file . '' ); + } + else { + die "$image format not recognized"; + } + return $image; +} + + +sub image( $device, $file ) { + my $image = get_gd_image($file); + my $width = $image->width; + my $height = $image->height; + my $dest_width = 380; + my $dest_height = $dest_width * ( $height / $width ); + my $image_dest = GD::Image->new( $dest_width, $dest_height ); + $image_dest->copyResampled( $image, 0, 0, 0, 0, $dest_width, $dest_height, + $width, $height, ); + + for ( + my $single_image_y = 0 ; + $single_image_y < $dest_height + 255 ; + $single_image_y += 255 + ) + { + if ( $single_image_y >= $dest_height ) { + last; + } + my $final_height = 255; + if ( $single_image_y + 255 > $dest_height ) { + $final_height = $dest_height - $single_image_y; + } + my $image_final = GD::Image->new( $dest_width, $final_height ); + $image_final->copy( $image_dest, 0, 0, 0, $single_image_y, $dest_width, + $final_height ); + my ($alpha) = $image_final->colorAllocateAlpha( 0, 0, 0, 127 ); + $image_final->colorDeallocate($alpha); + $image_final->colorAllocate( 255, 255, 255 ); + $device->printer->image($image_final); + } +} + +sub hex_to_char { + return pack 'C', shift; +} + +sub split_text_lines( $text, $max_width, $font, $font_size ) { + my @return; + my @lines; + if ( !ref $text ) { + @lines = map { $_ } split "\n", $text, -1; + } + else { + for my $element (@$text) { + if ( ref $element ) { + push @lines, $element; + next; + } + $element = decode 'utf-8', $element; + push @lines, $element; + } + } + my $surface = Cairo::ImageSurface->create( 'argb32', 380, 100 ); + my $cr = Cairo::Context->create($surface); + my $layout = Pango::Cairo::create_layout($cr); + $layout->set_font_description($font); + while (@lines) { + my $current_line = get_next_line( \@lines ); + my ( $w, $h ) = _get_size_text($cr, $layout, $font, $font_size, $current_line ); + my $final_line = []; + my $remainder = []; + if ( $w > $max_width ) { + LOOP_SPLIT: while (1) { + my $word = get_word($current_line); + if (!defined $word) { + die 'wtf?'; + } + my ( $w, $h ) = + _get_size_text($cr, $layout, $font, $font_size, + join_line_with_word( $final_line, $word ) ); + if ( $w > $max_width ) { + my ( $w_cutted_word, $h_cutted_word ) = + _get_size_text($cr, $layout, $font, $font_size, [$word] ); + if ( $w_cutted_word > $max_width ) { + my $i = 0; + $final_line = join_line_with_word( $final_line, $word ); + while (1) { + my $possible_cut = + substr_line( $final_line, 0, $i ); + my ( $w_cutted_word, $h_cutted_word ) = + _get_size_text($cr, $layout, $font, $font_size, $possible_cut ); + if ( $w_cutted_word > $max_width ) { + $remainder = substr_line( [@$final_line, @$current_line], $i - 1 ); + $final_line = + substr_line( $final_line, 0, $i - 1 ); + $current_line = $final_line; + last LOOP_SPLIT; + } + $i++; + } + } + $remainder = unshift_line_with_word( $word, $current_line ); + $current_line = $final_line; + last; + } + $final_line = join_line_with_word( $final_line, $word ); + } + } + $remainder->[0] =~ s/^\s+// if defined $remainder->[0] && !(ref $remainder->[0]); + unshift @lines, @$remainder if scalar @$remainder > 0; + push @return, $current_line; + } + return @return; +} + +sub substr_line( $text, $offset, $how_much = undef ) { + my $result = []; + my $cur_offset = 0; + my $element = 0; + my $needed_offset = 0; + while ( $cur_offset < $offset ) { + if ( !defined $text->[$element] ) { + die 'Overflow'; + } + if ( ref $text->[$element] ) { + $cur_offset += 1; + } + else { + my $length = (length $text->[$element]) - 1; + if ( $cur_offset + $length > $offset ) { + $needed_offset = $offset - $cur_offset; + last; + } + $cur_offset += $length; + } + $element++; + } + my $gotten = 0; + while ( !defined $how_much || $gotten < $how_much ) { + if ( !defined $text->[$element] ) { + last; + } + if ( ref $text->[$element] ) { + push @$result, $text->[$element]; + $gotten += 1; + } + else { + my $substr_length = (length $text->[$element]) - $needed_offset; + if ( defined $how_much && $gotten + $substr_length > $how_much ) { + $substr_length = $how_much - $gotten; + } + $result = join_line_with_word( $result, substr $text->[$element], + $needed_offset, $substr_length ); + $needed_offset = 0; + $gotten += $substr_length; + } + $element++; + } + return $result; +} + +sub unshift_line_with_word( $word, $line ) { + my $result = [@$line]; + if (defined $result->[0] && !ref $result->[0]) { + $result->[0] = $word.$result->[0]; + } else { + unshift @$result, $word; + } + return $result; + +} + +sub join_line_with_word( $line, $word ) { + my $result = [@$line]; + if ( scalar @$result == 0 || scalar @$result == 0 || ref $word || ref $result->[$#$result] ) { + push @$result, $word; + } + else { + $result->[$#$result] .= $word; + } + return $result; + +} + +sub get_word($line) { + if ( ref $line->[0] ) { + return shift @$line; + } + return unless @$line; + $line->[0] =~ /^(\s*\S*)(.*)$/; + if ($2 eq '') { + shift @$line; + } else { + $line->[0] = $2; + } + return $1; +} + +sub get_next_line($lines) { + my @result; + my $last_is_image = 0; + my $first = 1; + my $finish = 0; + state $calls = 0; + $calls++; + while (1) { + my $current_line = shift @$lines; + my $pre_split; + my $post_split; + if ( !defined $current_line ) { + last; + } + if ( (!(ref $current_line) && !$first && !$last_is_image) + || ($current_line =~ /^(.*?)?\n(.*)$/s)) { + $pre_split = $1 if defined $1; + $post_split = $2 if defined $2; + $finish = 1; + } + $first = 0; + $last_is_image = !!(ref $current_line); + if ($finish) { + if (defined $post_split) { + push @result, $pre_split if defined $pre_split; + unshift @$lines, $post_split; + } else { + unshift @$lines, $current_line + } + last; + } + push @result, $current_line; + } + return \@result; +} + +sub print_text( $device, $text, $font_size ) { + if ( !(ref $text) ) { + $text = decode 'utf-8', $text; + } + my $tempdir = Path::Tiny->tempdir; + my $file = $tempdir->child('result.png'); + my $font = Pango::FontDescription->from_string( + 'Noto Sans CJK JP ' . ( $font_size - ( 2 * 50 / 30 ) ) ); + + my @lines = split_text_lines( $text, 380, $font, $font_size ); + while (@lines) { + my $current_line = shift @lines; + my $height = $font_size * 30 / 17; + my $surface = Cairo::ImageSurface->create( 'argb32', 380, $height ); + my $cr = Cairo::Context->create($surface); + $cr->set_source_rgb( 1, 1, 1 ); + + $cr->rectangle( 0, 0, 380, $font_size * 30 / 17 ); + + $cr->fill; + $cr->set_source_rgb( 0, 0, 0 ); + + my $x = 0; + my $layout = Pango::Cairo::create_layout($cr); + for my $part (@$current_line) { + $cr->move_to( 0, 0 ); + if (!ref $part) { + Pango::Cairo::update_layout($cr, $layout); + $layout->set_text($part); + $layout->set_font_description($font); + $cr->move_to( $x, 0 ); + my ($new_x) = $layout->get_pixel_size; + $x += $new_x; + Pango::Cairo::show_layout( $cr, $layout ); + next; + } + my $gd_image = $part; + my $tempdir = Path::Tiny->tempdir(CLEANUP=>0); + my $image_file = $tempdir->child('out.png'); + $gd_image->_file($image_file); + my $image = Cairo::ImageSurface->create_from_png( + $image_file ); + my $ori_width = $gd_image->width; + my $ori_height = $gd_image->height; + my $scale_w = $font_size / $ori_width; + my $total_height = $font_size * 30 / 17 / $scale_w; + my $scale_h = $scale_w; + $cr->save; + $cr->scale($scale_w, $scale_h); + $cr->set_source_surface( $image, $x/$scale_w,($total_height - $x * $scale_w) / 4); + $cr->paint; + $cr->restore; + $x+= $font_size; + } + + $surface->write_to_png( $file . '' ); + my $img = GD::Image->newFromPng( $file . '' ); + $device->printer->image($img); + } +} + +sub _get_size_text( $cr, $layout, $font, $font_size, $text ) { + my $x = 0; + my $i; + for my $element (@$text) { + $cr->move_to( $x, 0 ); + if ( ref $element ) { + $x += $font_size; + next; + } + $layout->set_text($element); + $layout->set_font_description($font); + my ($new_x) = $layout->get_pixel_size; + $x += $new_x; + } + return $x; +}