diff options
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | perl-install/standalone/draksplash2 | 345 |
2 files changed, 352 insertions, 1 deletions
@@ -2,7 +2,7 @@ include Makefile.config DIRS = tools kernel mdk-stage1 perl-install rescue -.PHONY: dirs install +.PHONY: dirs install isolinux-graphic.bmp.parameters isolinux-graphic-simple.bmp.parameters install: dirs images rescue install_only @@ -84,3 +84,9 @@ upload_only: upload $(IMAGES_DEST)/alternatives '' ;\ upload $(GENERIC_INSTALL_DEST)/isolinux '' ;\ echo + +isolinux-graphic.bmp.parameters: isolinux-graphic.bmp isolinux + perl -I perl-install perl-install/standalone/draksplash2 --isolinux --kernel isolinux/alt0/vmlinuz --initrd isolinux/alt0/all.rdz $< + +isolinux-graphic-simple.bmp.parameters: isolinux-graphic-simple.bmp isolinux + perl -I perl-install perl-install/standalone/draksplash2 --isolinux --size 1400 $< diff --git a/perl-install/standalone/draksplash2 b/perl-install/standalone/draksplash2 new file mode 100644 index 000000000..7e1087c3e --- /dev/null +++ b/perl-install/standalone/draksplash2 @@ -0,0 +1,345 @@ +#!/usr/bin/perl + +use strict; + +use lib '/usr/lib/libDrakX'; +use Getopt::Long; +use ugtk2 qw(:all); +use Gtk2::Gdk::Keysyms; +use MDK::Common; +use Image::Magick; + + +my $kernel_size = 1500; #- in KiB +my $initrd_size = 130; #- in KiB + +my $lilo_block_size = 50; #- in KiB +my $isolinux_block_size = 64; #- in KiB + +my @modes = ( + { Vesa => 0x101, X => 640, Y => 480 }, + { Vesa => 0x103, X => 800, Y => 600 }, + { Vesa => 0x105, X => 1024, Y => 768 }, + { Vesa => 0x107, X => 1280, Y => 1024 }, +); + +my (%image_size, $kernel_and_initrd_size); +my ($progress_rect, $progress_color) = ([], {}); +my ($timer_pos, $timer_bg, $timer_fg) = ({}, {}, {}); +my ($entry_rect, $entry_selected_color, $entry_color) = ([], {}, {}); +my $isolinux_mode; + +my $magick = Image::Magick->new; + +my ($current_rect, $current_point); +my ($image_area, $image_pixbuf); + +sub move_point { + my ($up_down, $direction) = @_; + my $wanted = $current_point->{$direction} + $up_down; + if (0 <= $wanted && $wanted < $image_size{$direction}) { + $current_point->{$direction} += $up_down; + } + $image_area->queue_draw; +} +sub create_image_area() { + $image_area = Gtk2::DrawingArea->new; + $image_area->can_focus(1); + $image_area->add_events('button-press-mask'); + $image_area->signal_connect(button_press_event => \&image_button_pressed); + $image_area->signal_connect(expose_event => \&image_expose); + gtkmodify_font($image_area, 'Monospace 12'); + + my $keys = { + $Gtk2::Gdk::Keysyms{Down} => sub { move_point( ($_[0] ? 5 : 1), 'Y') }, + $Gtk2::Gdk::Keysyms{Up} => sub { move_point(-($_[0] ? 5 : 1), 'Y') }, + $Gtk2::Gdk::Keysyms{Left} => sub { move_point(-($_[0] ? 5 : 1), 'X') }, + $Gtk2::Gdk::Keysyms{Right} => sub { move_point( ($_[0] ? 5 : 1), 'X') }, + $Gtk2::Gdk::Keysyms{q} => sub { Gtk2->main_quit }, + $Gtk2::Gdk::Keysyms{Escape} => sub { Gtk2->main_quit }, + }; + + $image_area->signal_connect(key_press_event => sub { + my (undef, $event) = @_; + + if (my $f = $keys->{$event->keyval}) { + $f->(member('control-mask', @{$event->state})); + } + 1; + }); + + $image_area->grab_focus; + $image_area->show; + $image_area; +} +sub image_expose { + my ($widget) = @_; + my $window = $widget->window; + $window->draw_pixbuf($widget->style->white_gc, $image_pixbuf, 0, 0, 0, 0, -1, -1, 'none', 0, 0); + + if (!$isolinux_mode) { + { + my $layout = $widget->create_pango_layout('--:--'); + my ($width, $height) = $layout->get_pixel_size; + $window->draw_rectangle(color_index2gc($window, $timer_bg), 1, $timer_pos->{X}, $timer_pos->{Y}, $width, $height); + $window->draw_layout(color_index2gc($window, $timer_fg), $timer_pos->{X}, $timer_pos->{Y}, $layout); + } + my ($x, $y, $w, $h) = rectangle2xywh($entry_rect); + my @std_labels = ('linux', 'failsafe', '2.6.3-7mdk', 'X' x ($w / 8)); + for (my $nb = 0; $nb < int($h / 16); $y += 16, $nb++) { + my $label = shift(@std_labels) || 'label_' . ($nb+1); + my $gc = color_index2gc($window, !$nb ? $entry_selected_color : $entry_color); + my $layout = $widget->create_pango_layout($label); + $window->draw_layout($gc, $x, $y, $layout); + } + } + if ($current_rect) { + my ($x, $y, $w, $h) = rectangle2xywh($current_rect); + $window->draw_rectangle($widget->style->black_gc, 0, $x, $y, $w, $h); + } + if ($current_rect != $progress_rect) { + my ($x, $y, $w, $h) = rectangle2xywh($progress_rect); + $window->draw_rectangle(color_index2gc($window, $progress_color), 1, $x, $y, $w, $h); + } + 0; +} +sub image_button_pressed { + my (undef, $event) = @_; + + if ($event->button eq '3') { + create_popup()->popup(undef, undef, undef, undef, '3', $event->time); + return 1; + } + + my $point = { X => $event->x, Y => $event->y }; + my $chosen_point; + + if ($current_rect) { + if (!@$current_rect) { + my @corners = ({ X => 0, Y => 0 }, + { X => 0, Y => $image_size{Y} - 1 }, + { X => $image_size{X} - 1, Y => 0 }, + { X => $image_size{X} - 1, Y => $image_size{Y} - 1 }); + @$current_rect = ($corners[farthest($point, @corners)], nearest($point, @corners)); + } + $current_point = nearest($point, @$current_rect); + } elsif ($current_point) { + %$current_point or %$current_point = %$point; + } else { + return; + } + + %$current_point = %$point; + $current_point->{Color} = $magick->Get("index[$point->{X},$point->{Y}]"); + + $image_area->queue_draw; + 1; +} + +sub image_set_file { + my ($file) = @_; + + $image_pixbuf = Gtk2::Gdk::Pixbuf->new_from_file($file); + %image_size = (X => $image_pixbuf->get_width, Y => $image_pixbuf->get_height); + $image_area->set_size_request($image_size{X}, $image_size{Y}); + $image_area->queue_draw; +} + +sub color_index2gc { + my ($window, $color) = @_; + my ($r, $g, $b) = split(',', $magick->Get("colormap[$color->{Color}]")); + my $gc = Gtk2::Gdk::GC->new($window); + + my $gdk_color = Gtk2::Gdk::Color->new($r, $g, $b) or die "bad color for $r,$g,$b"; + $window->get_colormap->rgb_find_color($gdk_color); + $gc->set_rgb_fg_color($gdk_color); + $gc; +} + +sub rectangle2xywh { + my ($rect) = @_; + + my $x = min($rect->[0]{X} , $rect->[1]{X}); + my $y = min($rect->[0]{Y} , $rect->[1]{Y}); + my $w = abs($rect->[0]{X} - $rect->[1]{X}); + my $h = abs($rect->[0]{Y} - $rect->[1]{Y}); + ($x, $y, $w, $h); +} + +sub distance { + my ($p1, $p2) = @_; + sqr($p1->{X} - $p2->{X}) + sqr($p1->{Y} - $p2->{Y}); +} + +sub farthest { + my ($point, @others) = @_; + my $i = 0; + my $dist = 0; + my $farthest; + foreach (@others) { + my $d = distance($point, $_); + if ($d >= $dist) { + $dist = $d; + $farthest = $_; + } + } + $farthest; +} + +sub nearest { + my ($point, @others) = @_; + my $i = 0; + my $dist; + my $nearest; + foreach (@others) { + my $d = distance($point, $_); + if (! defined $dist || $d < $dist) { + $dist = $d; + $nearest = $_; + } + } + $nearest; +} + +sub create_popup() { + my %l = my @l = ( + 'Progress bar position' => sub { $current_rect = $progress_rect }, + 'Progress bar color' => sub { $current_point = $progress_color }, + '' => sub {}, + $isolinux_mode ? ( + 'switch to lilo mode' => sub { $isolinux_mode = 0 }, + ) : ( + 'Timer position' => sub { $current_point = $timer_pos }, + 'Timer text color' => sub { $current_point = $timer_fg }, + 'Timer background' => sub { $current_point = $timer_bg }, + '' => sub {}, + 'Entry position' => sub { $current_rect = $entry_rect }, + 'Entry text selected color' => sub { $current_point = $entry_selected_color }, + 'Entry text color' => sub { $current_point = $entry_color }, + '' => sub {}, + 'switch to isolinux mode' => sub { $isolinux_mode = 1 }, + ), + + ); + + my $popup = Gtk2::Menu->new; + foreach (group_by2(@l)) { + my ($descr, $f) = @$_; + gtkappend($popup, + gtksignal_connect(Gtk2::MenuItem->new_with_label($descr), + activate => sub { + $current_rect = $current_point = undef; + $f->(); + })); + } + $popup +} + +sub read_parameters { + my ($file) = @_; + my %h = getVarsFromSh($file); + + $entry_rect->[0]{X} = $h{'entry_x'}; + $entry_rect->[0]{Y} = $h{'entry_y'}; + $entry_rect->[1]{X} = $h{'entry_x'} + $h{'entry_w'}; + $entry_rect->[1]{Y} = $h{'entry_y'} + $h{'entry_h'}; + $entry_color->{Color} = $h{'entry_bg'} - 64; + $entry_selected_color->{Color} = $h{'entry_fg'} - 64; + + $timer_pos->{X} = $h{'timer_x'}; + $timer_pos->{Y} = $h{'timer_y'}; + $timer_bg->{Color} = $h{'timer_bg'} - 64; + $timer_fg->{Color} = $h{'timer_fg'} - 64; + + $progress_color->{Color} = $h{'progress_c'} - 64; + $progress_rect->[0]{X} = $h{'progress_x'}; + $progress_rect->[0]{Y} = $h{'progress_y'}; + $progress_rect->[1]{X} = $h{'progress_x'} + $h{'progress_real_w'}; + $progress_rect->[1]{Y} = $h{'progress_y'} + $h{'progress_h'}; + + $isolinux_mode = $h{'isolinux_mode'}; +} + +sub save_parameters { + my ($file) = @_; + my %h; + + $h{'mode'} = (find { $image_size{X} eq $_->{X} } @modes)->{Vesa}; + $h{'clear_h'} = $image_size{X}; + $h{'clear_w'} = $image_size{Y}; + + if (!$isolinux_mode) { + ($h{'entry_x'}, $h{'entry_y'}, $h{'entry_w'}, $h{'entry_h'}) = rectangle2xywh($entry_rect); + $h{'entry_w_chr'} = int($h{'entry_w'} / 8); + $h{'entry_h_chr'} = int($h{'entry_h'} / 16); + $h{'entry_bg'} = $entry_color->{Color} + 64; + $h{'entry_fg'} = $entry_selected_color->{Color} + 64; + + $h{'timer_x'} = $timer_pos->{X}; + $h{'timer_y'} = $timer_pos->{Y}; + $h{'timer_bg'} = $timer_bg->{Color} + 64; + $h{'timer_fg'} = $timer_fg->{Color} + 64; + } + + $h{'progress_c'} = $progress_color->{Color} + 64; + ($h{'progress_x'}, $h{'progress_y'}, $h{'progress_real_w'}, $h{'progress_h'}) = rectangle2xywh($progress_rect); + my $nb_steps = $kernel_and_initrd_size / ($isolinux_mode ? $isolinux_block_size : $lilo_block_size); + $h{'progress_w'} = int($h{'progress_real_w'} / $nb_steps); + + $h{'isolinux_mode'} = $isolinux_mode; + + output($file, map { "$_=$h{$_}\n" } sort keys %h); +} + +# MAIN ######################################################################### +my $usage = <<EOF; +usage: $0 [--kernel <kernel> --initrd <initrd>] [--size <size in KiB>] <image> +(kernel and initrd are used to compute the size of data to load) +EOF + +GetOptions('kernel=s' => \ (my $kernel), + 'initrd=s' => \ (my $initrd), + 'size=s' => \ $kernel_and_initrd_size, + 'isolinux' => \ (my $force_isolinux_mode), + ) or die $usage; + +my ($file) = @ARGV; +@ARGV == 1 && -e $file or die $usage; + +if ($kernel_and_initrd_size) { + $kernel and die "give kernel and initrd or size, not both\n"; +} else { + if ($kernel) { + $initrd or die "give both kernel and initrd\n"; + $kernel_size = (-s $kernel) / 1024 or die "bad file $kernel: $!\n"; + $initrd_size = (-s $initrd) / 1024 or die "bad file $initrd: $!\n"; + } + $kernel_and_initrd_size = $kernel_size + $initrd_size; +} + +my $err; +$err = $magick->Read($file) and die $err; + +my $bmp_file_name = $file; +$bmp_file_name =~ s/\.\w\w\w?$//; +$bmp_file_name .= '.bmp'; + +if ($file ne $bmp_file_name || $magick->Get('colors') > 128) { + warn "writing $bmp_file_name\n"; + $err = $magick->Quantize(colors => 128, dither => 'False') and die $err; + $err = $magick->Write(filename => "bmp3:$bmp_file_name", compression => 'None') and die $err; +} +read_parameters("$bmp_file_name.parameters"); +$isolinux_mode ||= $force_isolinux_mode; + +my $window_widget = Gtk2::Window->new('toplevel'); +$window_widget->signal_connect(destroy => sub { Gtk2->main_quit }); +gtkadd($window_widget, + gtkpack(Gtk2::VBox->new(0,0), create_image_area())); +image_set_file($bmp_file_name); + +$window_widget->show; +$image_area->window->set_cursor(Gtk2::Gdk::Cursor->new('crosshair')); +Gtk2->main; + +save_parameters("$bmp_file_name.parameters"); |