Implementing font importing functionality and copy to clipboard

of imported fonts.
This commit is contained in:
Sergiotarxz 2024-10-23 02:54:12 +02:00
parent 08ff96cdc6
commit d5d6fdb063
8 changed files with 252 additions and 66 deletions

View File

@ -18,10 +18,10 @@ use Exd::FileFormat::DB;
use Exd::FileFormat::Fontconfig;
has dir => ( is => 'rw' );
has _fontconfig => (is => 'lazy');
has fontconfig => (is => 'lazy');
has dbh => (is => 'lazy');
sub _build__fontconfig($self) {
sub _build_fontconfig($self) {
return Exd::FileFormat::Fontconfig->new(exd => $self);
}
@ -150,7 +150,7 @@ sub execute( $self, $printer ) {
if ($@) {
die $@;
}
$self->_fontconfig->set_current;
$self->fontconfig->set_current;
$sub->( $self, $printer );
}

View File

@ -38,6 +38,7 @@ sub _migrate {
my $dbh = shift;
local $dbh->{RaiseError} = 0;
local $dbh->{PrintError} = 0;
say 'Trying to migrate';
my @migrations = Exd::FileFormat::DB::Migrations::MIGRATIONS();
if ( $class->get_current_migration($dbh) > @migrations ) {
warn "Something happened there, wrong migration number.";
@ -47,6 +48,7 @@ sub _migrate {
return;
}
$class->_apply_migrations( $exd, $dbh, \@migrations );
say 'Database migrated';
}
sub _apply_migrations {

View File

@ -28,8 +28,13 @@ sub MIGRATIONS {
name TEXT NOT NULL
);',
sub ($exd, $dbh) {
my $fontconfig = Exd::FileFormat::Fontconfig->new(exd => $exd);
$fontconfig->migration2;
eval {
my $fontconfig = Exd::FileFormat::Fontconfig->new(exd => $exd);
$fontconfig->migration2;
};
if ($@) {
warn $@;
}
}
);
}

View File

@ -27,13 +27,29 @@ sub restore_system_config($self) {
}
sub list_fonts($self) {
return $self->_list_fonts_c;
my $fonts = $self->_list_fonts_c($self->_font_dir->child('dir'));
return $fonts;
}
sub _font_dir($self) {
return $self->exd->dir->child('fonts');
}
sub import_font($self, $file) {
my $exd_font_dir = $self->_font_dir->child('dir');
my $font_file = path($file);
my $sha = sha256_hex $font_file->slurp_raw;
system 'cp', '-v', $font_file, $exd_font_dir->child($sha);
my $name = $font_file->basename;
$name =~ s/\..*?$//;
eval {
$self->_add_font_to_database($name, $sha);
};
if ($@) {
warn $@;
}
}
sub migration1($self) {
my $exd = $self->exd;
my $app_font_dir =
@ -106,10 +122,15 @@ _set_current_c(SV *self, char *font_dir) {
}
AV *
_list_fonts_c(SV *self) {
_list_fonts_c(SV *self, char *font_dir) {
AV *return_array = newAV();
FcConfig *config = FcConfigGetCurrent();
FcConfig *config = FcConfigCreate();
FcConfigAppFontAddDir(config, font_dir);
FcConfigBuildFonts(config);
FcFontSet *fonts = FcConfigGetFonts(config, FcSetApplication);
if (fonts == NULL) {
return return_array;
}
for (int i = 0; i < fonts->nfont; i++) {
FcPattern *pattern = fonts->fonts[i];
FcChar8 *family;
@ -120,10 +141,10 @@ _list_fonts_c(SV *self) {
FcPatternGetString(pattern, FC_FILE, 0, &file);
char *familyKey;
HV *hash = newHV();
SV *hash_ref = newRV_inc((SV *) hash);
hv_stores(hash, "family", newRV_inc(sv_2mortal(newSVpv(family, 0))));
hv_stores(hash, "style", newRV_inc(sv_2mortal(newSVpv(style, 0))));
hv_stores(hash, "file", newRV_inc(sv_2mortal(newSVpv(file, 0))));
SV *hash_ref = newRV_noinc((SV *) hash);
hv_stores(hash, "family", newSVpv(family, 0));
hv_stores(hash, "style", newSVpv(style, 0));
hv_stores(hash, "file", newSVpv(file, 0));
av_push(return_array, hash_ref);
}
return return_array;

View File

@ -8,4 +8,41 @@ use utf8;
use Moo;
use Inline C => DATA => LIBS => '-lfontconfig -lfreetype';
sub list_fonts($self) {
my $fonts = $self->_list_fonts_c;
return $fonts;
}
1;
__DATA__
__C__
#include <stdio.h>
#include <fontconfig/fontconfig.h>
AV *
_list_fonts_c(SV *self) {
AV *return_array = newAV();
FcConfig *config = FcConfigGetCurrent();
FcFontSet *fonts = FcConfigGetFonts(config, FcSetSystem);
if (fonts == NULL) {
return return_array;
}
for (int i = 0; i < fonts->nfont; i++) {
FcPattern *pattern = fonts->fonts[i];
FcChar8 *family;
FcChar8 *style;
FcChar8 *file;
FcPatternGetString(pattern, FC_FAMILY, 0, &family);
FcPatternGetString(pattern, FC_STYLE, 0, &style);
FcPatternGetString(pattern, FC_FILE, 0, &file);
char *familyKey;
HV *hash = newHV();
SV *hash_ref = newRV_noinc((SV *) hash);
hv_stores(hash, "family", newSVpv(family, 0));
hv_stores(hash, "style", newSVpv(style, 0));
hv_stores(hash, "file", newSVpv(file, 0));
av_push(return_array, hash_ref);
}
return return_array;
}

View File

@ -222,24 +222,32 @@ sub _on_run_script_packet( $self, $instance_id, $json ) {
$json->@{ 'exd_dir', 'device', 'verbose' };
$device = $self->device_hash_to_object($device);
# if ( $self->_last_script_run_pid
# && $self->_last_script_run_device->isa('Exd::DeviceToImage')
# && !$verbose )
# {
# kill 'KILL', $self->_last_script_run_pid;
# }
# $self->_last_script_run_device($device);
my ($read, $write);
pipe $read, $write;
my $new_pid = fork;
if ( !$new_pid ) {
eval {
$self->_on_run_script( $instance_id, path($exd_dir), $device,
$verbose );
};
if ($@) {
warn $@;
}
open STDOUT, '>&', $write;
open STDERR, '>&', $write;
$self->_on_run_script( $instance_id, path($exd_dir), $device,
$verbose );
STDOUT->flush;
$write->flush;
close $read;
exit;
}
close $write;
if ($verbose) {
my $log_getter_pid = fork;
if (!$log_getter_pid) {
$self->_log($instance_id, '### STARTED EXECUTION ###');
while (my $line = <$read>) {
$self->_log($instance_id, $line);
}
$self->_log($instance_id, '### TERMINATED EXECUTION ###');
exit;
}
}
$self->_last_script_run_pid($new_pid);
}
@ -268,23 +276,10 @@ sub device_hash_to_object( $self, $device_hash ) {
sub _on_run_script( $self, $instance_id, $exd_dir, $device, $verbose = 1 ) {
my $printer = Exd::Printer->new( device => $device );
local $| = 1;
my $exd = Exd::FileFormat->new( dir => $exd_dir );
my ( $stdout, $stderr, $exit ) = capture {
eval { $exd->execute($printer); };
if ($@) {
if ($verbose) {
$self->_log( $instance_id, $@ . "\n" );
}
}
};
if ($verbose) {
$self->_log( $instance_id, $stdout . "\n" );
$self->_log( $instance_id, $stderr . "\n" );
}
$exd->execute($printer);
}
sub _monitor_run($self) {

View File

@ -8,15 +8,139 @@ use utf8;
use Moo;
has app => (is => 'ro', required => 1);
has _window => ( is => 'rw', );
use Pango;
use Exd::Fontconfig;
has instance => ( is => 'ro', required => 1 );
has _window => ( is => 'rw', );
has _fontconfig => ( is => 'lazy' );
sub _build__fontconfig($self) {
return Exd::Fontconfig->new;
}
sub start($self) {
my $window = Gtk4::Window->new;
$self->_window($window);
$window->set_default_size( 650, 600 );
$window->set_title('Font gallery');
$window->set_transient_for( $self->app->window );
$self->_update_window;
$window->present;
}
sub _update_window($self) {
my $window = $self->_window;
$window->set_default_size( 650, 600 );
$window->set_title('Font gallery');
$window->set_transient_for( $self->instance->window );
my $box_window = Gtk4::Box->new( 'horizontal', 10 );
my $box_system_fonts = Gtk4::Box->new( 'vertical', 10 );
my $box_exd_fonts = Gtk4::Box->new( 'vertical', 10 );
$self->_generate_system_fonts($box_system_fonts);
$self->_generate_exd_fonts($box_exd_fonts);
$box_window->append($box_system_fonts);
$box_window->append($box_exd_fonts);
$box_window->set_hexpand(1);
$box_window->set_vexpand(1);
$window->set_child($box_window);
}
sub _generate_system_fonts( $self, $box ) {
my $label = Gtk4::Label->new('System fonts');
my $font_window = Gtk4::ScrolledWindow->new;
$font_window->set_vexpand(1);
$font_window->set_hexpand(1);
$box->append($label);
my $box_fonts = Gtk4::Box->new( 'vertical', 10 );
$box_fonts->set_vexpand(1);
$box_fonts->set_hexpand(1);
my %seen_fonts;
for my $font ( $self->_fontconfig->list_fonts->@* ) {
if ( $seen_fonts{ $font->{family} . '#' . $font->{style} } ) {
next;
}
$seen_fonts{ $font->{family} . '#' . $font->{style} } = 1;
$self->_create_box_for_system_font( $font, $box_fonts );
}
$font_window->set_child($box_fonts);
$box->append($font_window);
$box->set_hexpand(1);
$box->set_vexpand(1);
}
sub _create_box_for_system_font( $self, $font, $box ) {
my $family = $font->{family};
my $style = $font->{style};
my $file = $font->{file};
my $box_font = Gtk4::Box->new( 'vertical', 10 );
my $font_label = Gtk4::Label->new("$family $style");
my $dest = Pango::FontDescription->from_string("$family $style 10");
my $attributes = Pango::AttrList->new;
my $attr = Pango::AttrFontDesc->new($dest);
$attributes->insert($attr);
$font_label->set_attributes($attributes);
$font_label->set_halign('start');
$font_label->set_hexpand(1);
$box_font->append($font_label);
$box_font->set_hexpand(1);
my $box_buttons = Gtk4::Box->new( 'horizontal', 10 );
my $button_copy = Gtk4::Button->new_with_label('Copy to file');
$button_copy->signal_connect(clicked => sub {
$self->instance->file_format->fontconfig->import_font($file);
$self->_update_window;
});
$box_buttons->set_margin_start(10);
$box_buttons->append($button_copy);
$box_font->append($box_buttons);
$box->append($box_font);
}
sub _create_box_for_exd_font($self, $font, $box) {
my $family = $font->{family};
my $style = $font->{style};
my $box_font = Gtk4::Box->new( 'vertical', 10 );
my $font_label = Gtk4::Label->new("$family $style");
my $dest = Pango::FontDescription->from_string("$family $style 10");
my $attributes = Pango::AttrList->new;
my $attr = Pango::AttrFontDesc->new($dest);
$attributes->insert($attr);
$font_label->set_attributes($attributes);
$font_label->set_halign('start');
$font_label->set_hexpand(1);
$box_font->append($font_label);
$box_font->set_hexpand(1);
my $box_buttons = Gtk4::Box->new( 'horizontal', 10 );
my $button_copy = Gtk4::Button->new_with_label('Copy to clipboard');
$button_copy->signal_connect( clicked => sub {
$self->instance->set_clipboard("'$family $style'");
$self->_window->close;
});
$box_buttons->set_margin_start(10);
$box_buttons->append($button_copy);
$box_font->append($box_buttons);
$box->append($box_font);
}
sub _generate_exd_fonts( $self, $box ) {
my $label = Gtk4::Label->new('File fonts');
my $font_window = Gtk4::ScrolledWindow->new;
$font_window->set_vexpand(1);
$font_window->set_hexpand(1);
$box->append($label);
my $box_fonts = Gtk4::Box->new( 'vertical', 10 );
$box_fonts->set_vexpand(1);
$box_fonts->set_hexpand(1);
my %seen_fonts;
for my $font ( $self->instance->file_format->fontconfig->list_fonts->@* ) {
if ( $seen_fonts{ $font->{family} . '#' . $font->{style} } ) {
next;
}
$seen_fonts{ $font->{family} . '#' . $font->{style} } = 1;
$self->_create_box_for_exd_font( $font, $box_fonts );
}
$font_window->set_child($box_fonts);
$box->append($font_window);
$box->set_hexpand(1);
$box->set_vexpand(1);
}
1;

View File

@ -19,7 +19,7 @@ has window => ( is => 'rw' );
has _editor => ( is => 'rw', );
has _safe_to_exit => ( is => 'rw', default => sub { 1 } );
has device => ( is => 'rw' );
has _file_format => (
has file_format => (
is => 'rw',
default => sub {
my $tmp = Exd::FileFormat->new_tmp;
@ -62,6 +62,9 @@ sub start( $self, $exd_file ) {
$win->set_show_menubar(1);
$self->window($win);
if ( defined $exd_file ) {
$self->_open_file($exd_file);
}
my $box_vertical = Gtk4::Box->new( 'vertical', 10 );
$self->_create_popover_menu($box_vertical);
my $execute_log = Gtk4::TextView->new;
@ -148,9 +151,6 @@ sub start( $self, $exd_file ) {
$execute_log_window->set_child($execute_log);
$box_vertical->append($execute_log_window);
$win->set_child($box_vertical);
if ( defined $exd_file ) {
$self->_open_file($exd_file);
}
$win->present;
}
@ -217,7 +217,7 @@ sub _populate_editor( $self, $box_editor_preview ) {
my $end_iter = $buffer->get_end_iter;
my $script = $buffer->get_text( $begin_iter, $end_iter, 0 );
$self->_file_format->set_script($script);
$self->file_format->set_script($script);
$self->_generate_preview_file(0);
}
);
@ -243,8 +243,10 @@ sub _populate_editor_and_preview( $self, $box_vertical ) {
sub _update_editor_buffer($self) {
my $editor = $self->_editor;
my $buffer = $editor->get_buffer();
$buffer->set_text( $self->_file_format->get_script, -1 );
if (defined $editor) {
my $buffer = $editor->get_buffer();
$buffer->set_text( $self->file_format->get_script, -1 );
}
}
sub _populate_preview( $self, $box_editor_preview ) {
@ -294,7 +296,7 @@ sub _run_script( $self, $device = undef, $verbose = 1 ) {
{
type => 'run_script',
data => {
exd_dir => '' . $self->_file_format->dir,
exd_dir => '' . $self->file_format->dir,
device => $device->serialize,
verbose => $verbose,
}
@ -345,13 +347,13 @@ sub _on_preview($self) {
}
sub _open_fonts_gallery($self) {
my $font_gallery = Exd::Gui::FontGallery->new( app => $self );
my $font_gallery = Exd::Gui::FontGallery->new( instance => $self );
$font_gallery->start;
}
sub _create_gallery_image( $self, $hash ) {
my $picture = Gtk4::Picture->new;
my $image_file = $self->_file_format->get_image($hash);
my $image_file = $self->file_format->get_image($hash);
$picture->set_property( 'width-request', 180 );
$picture->set_property( 'height-request', 180 );
$picture->set_content_fit('fill');
@ -391,7 +393,7 @@ sub _open_gallery($self) {
"$file is not png." );
return;
}
$self->_file_format->add_png_image(
$self->file_format->add_png_image(
path($file)->slurp_raw, $label );
$buffer->set_text( '', -1 );
$self->_update_gallery_images( $window,
@ -416,7 +418,7 @@ sub _open_gallery($self) {
}
sub _update_gallery_images( $self, $window, $images_scroll ) {
my %image_hashes_to_label = $self->_file_format->image_hashes_to_label->%*;
my %image_hashes_to_label = $self->file_format->image_hashes_to_label->%*;
my $gallery_box = Gtk4::Box->new( 'vertical', 10 );
my $i = 0;
my $row_image;
@ -432,14 +434,14 @@ sub _update_gallery_images( $self, $window, $images_scroll ) {
$copy->signal_connect(
'clicked',
sub {
$self->_set_clipboard("\$exd->get_image('$hash')");
$self->set_clipboard("\$exd->get_image('$hash')");
$window->close;
}
);
$copy_gd->signal_connect(
'clicked',
sub {
$self->_set_clipboard("\$exd->get_image_gd('$hash')");
$self->set_clipboard("\$exd->get_image_gd('$hash')");
$window->close;
}
);
@ -463,7 +465,7 @@ sub _update_gallery_images( $self, $window, $images_scroll ) {
$copy->signal_connect(
'clicked',
sub {
$self->_set_clipboard(
$self->set_clipboard(
"\$exd->get_image_from_label('$label')");
$window->close;
}
@ -471,7 +473,7 @@ sub _update_gallery_images( $self, $window, $images_scroll ) {
$copy_gd->signal_connect(
'clicked',
sub {
$self->_set_clipboard(
$self->set_clipboard(
"\$exd->get_image_gd_from_label('$label')");
$window->close;
}
@ -497,7 +499,7 @@ sub _get_row_image( $self, $i, $gallery_box, $row_image ) {
return $row_image;
}
sub _set_clipboard( $self, $text ) {
sub set_clipboard( $self, $text ) {
my $display = Gdk::Display::get_default();
my $clipboard = $display->get_clipboard;
my $wrapper =
@ -506,7 +508,7 @@ sub _set_clipboard( $self, $text ) {
}
sub _save_as_action($self) {
my $file_format = $self->_file_format;
my $file_format = $self->file_format;
my $dialog = Gtk4::FileDialog->new;
$dialog->set_initial_name('project.exd');
$dialog->save(
@ -523,7 +525,7 @@ sub _save_as_action($self) {
}
sub _open_action($self) {
my $file_format = $self->_file_format;
my $file_format = $self->file_format;
my $dialog = Gtk4::FileDialog->new;
$dialog->set_initial_name('project.exd');
my $window = $self->window;
@ -561,13 +563,13 @@ sub _open_file( $self, $file ) {
my $window = $self->window;
$window->set_title(
"Exd (Thermal Printer) " . path( $self->_save_path )->basename );
$self->_file_format( Exd::FileFormat->from_zip_file($file) );
$self->file_format( Exd::FileFormat->from_zip_file($file) );
$self->_update_editor_buffer;
}
sub _save_action($self) {
my $instance_id = $self->instance_id;
my $file_format = $self->_file_format;
my $file_format = $self->file_format;
my $dialog = Gtk4::FileDialog->new;
if ( defined $self->_save_path ) {
$self->_send_save_request( $file_format->dir . '', $self->_save_path );