ONO::Lib::PDF::Elements::Train

package ONO::Lib::PDF::Elements::Train;
################################################################################
# COPYRIGHT / LICENSE #
################################################################################
#
# This file is part of the ONO Software Project.
#
# Copyright (C) 2000-2025 Jos KIRPS [ www.kirps.com | jos_AT_kirps_DOT_com ]
# and The Joopita Project [ www.joopita.org | contact_AT_joopita_DOT_com ]
#
# This file, as well as other parts of the ONO Software Project or related
# elements, are FREE SOFTWARE available under the ARTISTIC LICENSE 2.0.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# For the full license, see /ono/osr/license/LICENSE.txt, or write to
# jos_AT_kirps_DOT_com or contact_AT_joopita_DOT_com.
#
################################################################################
# END OF COPYRIGHT / LICENSE, HERE COMES THE CODE ... #
################################################################################

use strict;

use ONO::Lib::PDF::Draw;
use ONO::Lib::Image::Canvas::Draw;

#: This module generates specific PDF content.

sub train {

my (
$self,
$canvas,
$x,
$y,
$type,
$width,
$height,
$switches,
$opt_main,
$COLOR_MAIN,
$opt_ref,
$color_ref,
$vars_ref,
) = @_;

#: This generates a train image, supporting both PDF and HTML output.
#:
#: Switches:
#:
#: -B Black & White
#: -C EU comma conversion for data
#: -D Dummy engine (rounded rectangle)
#: -H HTML mode (as PDF is default)
#: -I input field on empty car (HTML mode only)
#:
#: x / y x = 0 is always the position on the left
#: y = 0 is top of track, bottom of train, so that train is always on track
#: this will be ignored in HTML mode!
#:
#: type train, track, engine, or car - can also be type:subtype for example
#:
#: width the width of the track, engine, car, etc...
#: height the height of the train, from standard roof top to track
#: track height will be adjusted automatically
#:
#: length entire track length, or engine/car length
#:
#: opt specific options
#: color specific colors

my $MODE = "pdf";
if ($switches =~ /H/) {
$MODE = "html";
}

my $height2 = $height+5;
my $canvas2 = "0:$height2";

$x = int($x*10)/10;
$y = int($y*10)/10;

my (%opt,%color,%vars,$HTML);

if ($opt_ref) {
%opt = %$opt_ref;
}
if ($color_ref) {
%color = %$color_ref;
}
if ($vars_ref) {
%vars = %$vars_ref;
}

if (!$width) {
$width = $height*1.36;
}

my ($r1,$r2,$r3) = (int(rand(255)),int(rand(255)),int(rand(255)));

my $c1 = 10+int(rand(50));
my $COLOR_BLACK = "0:22:22:22";
my $COLOR_BLACK_RAND = "0:$c1:$c1:$c1";

my $c1 = 140+int(rand(60));
my $COLOR_GREY = "0:188:188:188";
my $COLOR_GREY_RAND = "0:$c1:$c1:$c1";

my $c1 = 240+int(rand(10));
my $c2 = 240+int(rand(10));
my $c3 = 240+int(rand(10));
my $COLOR_WHITE = "0:244:244:244";
my $COLOR_WHITE_RAND = "0:$c1:$c2:$c3";

my $COLOR_RED = "0:188:20:20";

my $c1 = 180+int(35);
my $c2 = $c1+int(35);
my $COLOR_WIN = "0:212:212:232";
my $COLOR_WIN_RAND = "0:$c1:$c1:$c2";

my $COLOR_RAND = "0:$r1:$r2:$r3";

my $l1 = $r1+int(rand(100));
my $l2 = $r2+int(rand(100));
my $l3 = $r3+int(rand(100));

if ($l1 > 230) {
$l1 = 230;
}
if ($l2 > 230) {
$l2 = 230;
}
if ($l3 > 230) {
$l3 = 230;
}

my $COLOR_RAND_LIGHT = "0:$l1:$l2:$l3";

if ($switches =~ /B/) {

$COLOR_BLACK_RAND = $COLOR_BLACK;
$COLOR_GREY_RAND = $COLOR_GREY;
$COLOR_WHITE_RAND = $COLOR_WHITE;

$COLOR_RAND = "0:120:120:120";
$COLOR_RAND_LIGHT = "0:240:240:240";
$COLOR_RED = "0:120:120:120";

$COLOR_WIN = "0:250:250:250";
$COLOR_WIN_RAND = "0:250:250:250";

}

my $border = int($height)/10; # used by PDF
# my $border2 = int($height)/20; # used by HTML
# my $border3 = "border:${border2}px solid #555555"; # used by HTML
my $border_color = "0:55:55:55";

my $buffer = $height/12;

my $x_left = int(($x+$buffer)*10)/10;
my $x_right = int(($x-$buffer+$width)*10)/10;

my $y_top = $y-$height;
my $y_high = int(($y_top+int($height/1.2)/2)*10)/10;
my $y_plat = int(($y_top+int($height)/1.45)*10)/10;
my $y_low = int(($y_top+int($height)/1.15)*10)/10;
my $y_bot = $y;

if ($type =~ /^train/) {

# opt_main is the number of cars

my $track_width = 20;

my $car_width = $height;
if ($opt{'car_width'}) {
$car_width = $opt{'car_width'};
}

my @engine_models = ('steam','electric','diesel');
my $engine_model_nums = @engine_models;
my $engine_model = "engine_".$engine_models[int(rand($engine_model_nums))];
my $engine_width = $height*1.36;

my $car_model = "car";
if (int(rand(100)) > 50) {
$car_model = "car_freight";
}

$HTML .= &train("",$canvas,$x+2,$y,$engine_model,$engine_width,$height,$switches,"","","","",$vars_ref);

for (my $c = 0; $c < $opt_main; $c++) {

my %opts;
$opts{'text'} = $opt{"car_${c}_text"};
$opts{'placeholder'} = $opt{"car_${c}_placeholder"};
$opts{'id'} = $c;
if ($opt{'car_text_transform_dot_comma'}) {
$opts{'car_text_transform_dot_comma'}++;
}

my $car_x = 0;

if ($MODE eq "pdf") {
$car_x = $x+2+$engine_width+$c*$car_width;
}

$HTML .= &train("",$canvas,$car_x,$y,$car_model,$car_width,$height,$switches,"R","",\%opts,"",$vars_ref);

$track_width = $track_width + $car_width;

}

if ($MODE eq "pdf") {
&train("",$canvas,$x,$y,"track",$track_width,$height,$switches);
}

}

if ($type =~ /^track/) {

if (!$width) {
$width = 100;
}
$height = int($height/2)/10;

my $c3 = 50+int(rand(25));
my $c2 = 50+$c3+int(rand(25));
my $c1 = 50+$c2+int(rand(25));

if ($switches =~ /B/) {
($c1,$c2,$c3) = (188,188,188);
}

if ($MODE eq "pdf") {
ONO::Lib::PDF::Draw->rect($canvas,$x,$y,$x+$width,$y+$height,0,"","0:$c1:$c2:$c3");
} else {
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,$x,$y,$x+$width,$y+$height,0,"","0:188:188:188");
}

my $x_pos = $x+$height*2;

my $whilecounter;
while ($whilecounter < 4096 && $x_pos < $x+$width-$height-1) {
$whilecounter++;
my $c3 = int(rand(50));
my $c2 = $c3+int(rand(50));
my $c1 = $c2+int(rand(50));

if ($switches =~ /B/) {
($c1,$c2,$c3) = (88,88,88);
}

if ($MODE eq "pdf") {
ONO::Lib::PDF::Draw->rect($canvas,$x_pos,$y+$height,$x_pos+$height*2,$y+$height*2,0,"","0:$c1:$c2:$c3");
} else {
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,$x_pos,$y+$height,$x_pos+$height*2,$y+$height*2,0,"","0:$c1:$c2:$c3");
}
$x_pos = $x_pos+$height*3;
}

}

if ($type =~ /^buffers/) {

my $h5 = $height/5;
my $h15 = $height/15;
my $h40 = $height/40;

my $buff_x1 = $x+$h40;
my $buff_x2 = $x-$h40+$width;
my $buff_x3 = $x+$width-$h40;

my $buff_y1 = $y-$h5;
my $buff_y2 = $y-$h5-$h15;
my $buff_y3 = $y-$h5+$h15;

if ($MODE eq "pdf") {

ONO::Lib::PDF::Draw->line($canvas,$buff_x1,$buff_y1,$buff_x3,$buff_y1,$border);
ONO::Lib::PDF::Draw->line($canvas,$buff_x1,$buff_y2,$buff_x1,$buff_y3,$border);
ONO::Lib::PDF::Draw->line($canvas,$buff_x2,$buff_y2,$buff_x2,$buff_y3,$border);

} else {

$HTML .= ONO::Lib::Image::Canvas::Draw->line($canvas2,$buff_x1,$buff_y1,$buff_x3,$buff_y1);
$HTML .= ONO::Lib::Image::Canvas::Draw->line($canvas2,$buff_x1,$buff_y2,$buff_x1,$buff_y3);
$HTML .= ONO::Lib::Image::Canvas::Draw->line($canvas2,$buff_x2,$buff_y2,$buff_x2,$buff_y3);

}

}

if ($type =~ /^wheel/) {

# -l larger
# -L largest

my $wheel_size = $height/4;
if ($opt_main eq "l") {
$wheel_size = $wheel_size*1.2;
}
if ($opt_main eq "L") {
$wheel_size = $wheel_size*1.2;
}

if (!$COLOR_MAIN) {
$COLOR_MAIN = "0:55:55:55";
}

my $wheel_x = $x;
my $wheel_y = int(($y-$wheel_size/2+$height/800)*10)/10;

if ($MODE eq "pdf") {
ONO::Lib::PDF::Draw->circle($canvas,$wheel_x,$wheel_y,$wheel_size/2,$wheel_size/4,$COLOR_MAIN,"0:128:128:128");
} else {
$HTML .= ONO::Lib::Image::Canvas::Draw->circle($canvas2,$wheel_x,$wheel_y,$wheel_size/2,$wheel_size/4,$COLOR_MAIN,"0:128:128:128");
}

}

if ($type =~ /^engine/) {

my $model;
if ($type =~ /^engine_(.*?)$/) {
$model = $1;
}
if (!$model) {
$model = "steam";
}

if (!$opt{'id'}) {
$opt{'id'} = 1;
}

my $COLOR_MAIN_LIGHT = "0:244:244:244";

if (!$COLOR_MAIN) {
$COLOR_MAIN = $COLOR_RAND;
$COLOR_MAIN_LIGHT = $COLOR_RAND_LIGHT;
}

# transmitted color override

if ($vars{"engine_$opt{'id'}_transmit_color_main"}) {
$COLOR_MAIN = $vars{"engine_$opt{'id'}_transmit_color_main"};
}

# buffers

$HTML .= &train("",$canvas,$x,$y,"buffers",$width,$height,$switches);

if ($switches =~ /D/) {
$model = "dummy";
}

if ($model eq "dummy") {
my @rect = ($x_left,$y_top,$x_left+int($width*0.9),$y_top+$height);
if ($MODE eq "pdf") {
ONO::Lib::PDF::Draw->rect($canvas,@rect,1,"0:22:22:22","0:111:111:111",1);
} else {
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect,1,"0:22:22:22","0:111:111:111");
}
}

if ($model eq "steam") {

# exhaust + boiler

# exhaust

my $x_left_2 = int(($x_left+$width/10)*10)/10;
my $x_left_3 = int(($x_left+$width/5)*10)/10;
my $y_top_2 = int(($y_top+$height/10)*10)/10;

# box on top of boiler (PDF only)

my $x_left_4 = int(($x_left+$width/2.5)*10)/10;
my $x_left_5 = int(($x_left+$width/3.5)*10)/10;
my $y_top_4 = int(($y_top+$height/3.0)*10)/10;

# box on top of exhaust

my $x_left_6 = int(($x_left+$width/18)*10)/10;
my $x_left_7 = int(($x_left+$width/4)*10)/10;
my $y_top_6 = int(($y_top+$height/3.5)*10)/10;

# some more stuff...

my $w1 = $width/10;
my $w2 = $width-$x_left_2;
my $h1 = $width/3.8;
my $h2 = $width/3.8;

my @rect1 = ($x_left_2, $y_top_2, $x_left_3, $y_low);
my @rect2 = ($x_left_4, $y_top_4, $x_left_5, $y_low);
my @rect3 = ($x_left, $y_high, $x_right, $y_low);
my @rect4 = ($x_left, $y_high, $x_right, $y_plat);

if ($MODE eq "pdf") {
ONO::Lib::PDF::Draw->rect($canvas,@rect1,$border,$border_color,$COLOR_BLACK_RAND);
ONO::Lib::PDF::Draw->rect($canvas,@rect2,$border,$border_color,$COLOR_BLACK_RAND);
ONO::Lib::PDF::Draw->rect($canvas,@rect3,$border,$border_color,$COLOR_RED);
ONO::Lib::PDF::Draw->rect($canvas,@rect4,$border,$border_color,$COLOR_BLACK_RAND);
} else {
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect1,$border,$border_color,$COLOR_BLACK_RAND);
# $HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect2,$border,$border_color,$COLOR_BLACK_RAND);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect3,$border,$border_color,$COLOR_RED);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect4,$border,$border_color,$COLOR_BLACK_RAND);
}

if (int(rand(100)) > 50) {
if ($MODE eq "pdf") {
ONO::Lib::PDF::Draw->rect($canvas,$x_left_6, $y_top_2, $x_left_7, $y_top_6,$border,$border_color,$COLOR_BLACK_RAND);
} else {
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,$x_left_6, $y_top_2, $x_left_7, $y_top_6,$border,$border_color,$COLOR_BLACK_RAND);
}
}

# cabin

my $x_cabin = $x_right-$height/2;
my $cabin_width = $x_right-$x_cabin;
my $cabin_window = $cabin_width/5;

# cabin, windows, roof:

if ($MODE eq "pdf") {
ONO::Lib::PDF::Draw->rect($canvas,$x_cabin,$y_top,$x_cabin+$cabin_width,$y_plat,$border,$border_color,$COLOR_MAIN);
ONO::Lib::PDF::Draw->rect($canvas,$x_cabin,$y_top,$x_cabin+$cabin_width,$y_plat-$height/4,$border,$border_color,$COLOR_MAIN_LIGHT);

if (int(rand(100)) > 50) {
ONO::Lib::PDF::Draw->rect($canvas,$x_cabin+$cabin_window,$y_top+$height/7,$x_cabin+$cabin_window*2,$y_high,$border,$border_color,$COLOR_WIN_RAND);
ONO::Lib::PDF::Draw->rect($canvas,$x_cabin+$cabin_window*3,$y_top+$height/7,$x_cabin+$cabin_window*4,$y_high,$border,$border_color,$COLOR_WIN_RAND);
} else {
ONO::Lib::PDF::Draw->rect($canvas,$x_cabin+$cabin_window,$y_top+$height/7,$x_cabin+$cabin_window*4,$y_high,$border,$border_color,$COLOR_WIN_RAND);
}

ONO::Lib::PDF::Draw->rect($canvas,$x_cabin-$height/20,$y_top,$x_cabin+$cabin_width+$height/20,$y_top+$height/10,$border,$border_color,$COLOR_GREY_RAND);
} else {
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,$x_cabin,$y_top,$x_cabin+$cabin_width,$y_plat,$border,$border_color,$COLOR_MAIN);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,$x_cabin,$y_top,$x_cabin+$cabin_width,$y_plat-$height/4,$border,$border_color,$COLOR_MAIN_LIGHT);

if (int(rand(100)) > 50) {
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,$x_cabin+$cabin_window,$y_top+$height/7,$x_cabin+$cabin_window*2,$y_high,$border,$border_color,$COLOR_WIN_RAND);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,$x_cabin+$cabin_window*3,$y_top+$height/7,$x_cabin+$cabin_window*4,$y_high,$border,$border_color,$COLOR_WIN_RAND);
} else {
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,$x_cabin+$cabin_window,$y_top+$height/7,$x_cabin+$cabin_window*4,$y_high,$border,$border_color,$COLOR_WIN_RAND);
}

$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,$x_cabin-$height/20,$y_top,$x_cabin+$cabin_width+$height/20,$y_top+$height/10,$border,$border_color,$COLOR_GREY_RAND);
}

my $x_pos = $x_left+$width/3.5;
for (my $w = 0; $w < 2; $w++) {
$HTML .= &train("",$canvas,$x_pos,$y_bot,"wheel",$width,$height,$switches,"l",$COLOR_RED);
$x_pos = $x_pos + $width/3.5;
}

}

if ($model eq "electric") {

my $x_pos = $x_left+$width/6.5;
for (my $w = 0; $w < 3; $w++) {
$HTML .= &train("",$canvas,$x_pos,$y_bot,"wheel",$width,$height,$switches,"l",$COLOR_BLACK_RAND);
$x_pos = $x_pos + $width/3.5;
}

my $x_cabin = $x_left;
my $cabin_width = $x_right-$x_cabin;

my $cabin_window = $cabin_width/5;

# bottom

my @rect1 = ($x_left, $y_high, $x_right, $y_low);

# cabin

my @rect2 = ($x_cabin+$width/10,$y_top,$x_cabin+$cabin_width-$width/10,$y_plat);
my @rect3 = ($x_cabin,$y_top+$height/2.4,$x_cabin+$cabin_width,$y_plat);

# windows

my @rect4 = ($x_cabin+$width/20,$y_top+$height/8,$x_cabin+$width/20+$cabin_window,$y_high);
my @rect5 = ($x_cabin-$width/20+$cabin_window*4,$y_top+$height/8,$x_cabin-$width/20+$cabin_window*5,$y_high);

# ?

my @rect6 = ($x_cabin+$width/3.5,$y_top+$height/5,$x_cabin+$width/1.69,$y_high+$height/10);
my @rect7 = ($x_cabin,$y_top,$x_cabin+$cabin_width,$y_top+$height/10);

# panto

my @pan1 = ($x_left+$width/2,$y_top-$height/3);
my @pan2 = ($x_left+$width/2-$width/4,$y_top-$height/6);
my @pan3 = ($x_left+$width/2+$width/4,$pan2[1]);
my @pan4 = ($pan1[0],$y_top);

my @line1 = ($pan1[0]-$width/15,$pan1[1],$pan1[0]+$width/15,$pan1[1]);
my @line2 = ($pan1[0],$pan1[1],$pan2[0],$pan2[1]);
my @line3 = ($pan1[0],$pan1[1],$pan3[0],$pan3[1]);

my @line4 = ($pan4[0],$pan4[1],$pan2[0],$pan2[1]);
my @line5 = ($pan4[0],$pan4[1],$pan3[0],$pan3[1]);

if ($MODE eq "pdf") {

ONO::Lib::PDF::Draw->line($canvas,@line1,$height/10,$COLOR_GREY_RAND);
ONO::Lib::PDF::Draw->line($canvas,@line2,$height/10,$COLOR_GREY_RAND);
ONO::Lib::PDF::Draw->line($canvas,@line3,$height/10,$COLOR_GREY_RAND);
ONO::Lib::PDF::Draw->line($canvas,@line4,$height/10,$COLOR_GREY_RAND);
ONO::Lib::PDF::Draw->line($canvas,@line5,$height/10,$COLOR_GREY_RAND);

ONO::Lib::PDF::Draw->rect($canvas,@rect1,$border,$border_color,$COLOR_BLACK_RAND);
ONO::Lib::PDF::Draw->rect($canvas,@rect2,$border,$border_color,$COLOR_MAIN_LIGHT);
ONO::Lib::PDF::Draw->rect($canvas,@rect3,$border,$border_color,$COLOR_MAIN);
ONO::Lib::PDF::Draw->rect($canvas,@rect4,$border,$border_color,$COLOR_WIN_RAND);
ONO::Lib::PDF::Draw->rect($canvas,@rect5,$border,$border_color,$COLOR_WIN_RAND);
ONO::Lib::PDF::Draw->rect($canvas,@rect6,$border,$border_color,$COLOR_GREY_RAND);
ONO::Lib::PDF::Draw->rect($canvas,@rect7,$border,$border_color,$COLOR_GREY_RAND);

} else {

$HTML .= ONO::Lib::Image::Canvas::Draw->line($canvas2,@line1,$height/10,$COLOR_GREY_RAND);
$HTML .= ONO::Lib::Image::Canvas::Draw->line($canvas2,@line2,$height/10,$COLOR_GREY_RAND);
$HTML .= ONO::Lib::Image::Canvas::Draw->line($canvas2,@line3,$height/10,$COLOR_GREY_RAND);
$HTML .= ONO::Lib::Image::Canvas::Draw->line($canvas2,@line4,$height/10,$COLOR_GREY_RAND);
$HTML .= ONO::Lib::Image::Canvas::Draw->line($canvas2,@line5,$height/10,$COLOR_GREY_RAND);

$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect1,$border,$border_color,$COLOR_BLACK_RAND);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect2,$border,$border_color,$COLOR_MAIN_LIGHT);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect3,$border,$border_color,$COLOR_MAIN);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect4,$border,$border_color,$COLOR_WIN_RAND);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect5,$border,$border_color,$COLOR_WIN_RAND);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect6,$border,$border_color,$COLOR_GREY_RAND);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect7,$border,$border_color,$COLOR_GREY_RAND);

}

}

if ($model eq "diesel") {

my $x_pos = $x_left+$width/3.5;
for (my $w = 0; $w < 2; $w++) {
$HTML .= &train("",$canvas,$x_pos,$y_bot,"wheel",$width,$height,$switches,"l",$COLOR_BLACK_RAND);
$x_pos = $x_pos + $width/3;
}

my $x_cabin = $x_left;
my $cabin_width = $x_right-$x_cabin;

my $cabin_window = $cabin_width/5;

# bottom

my @rect1 = ($x_left, $y_high+$height/6, $x_right, $y_low);

# cabin

my @rect2 = ($x_cabin+$width/20,$y_top+$height/3.5,$x_cabin+$cabin_width-$width/20,$y_plat);
my @rect3 = ($x_cabin+$width/2.5,$y_top,$x_cabin+$cabin_width-$width/8,$y_plat);

# windows

my @rect4 = ($x_cabin+$width/2,$y_top+$height/8,$x_cabin+$width/2+$cabin_window,$y_high);

# roof

my @rect7 = ($x_cabin+$width/3,$y_top,$x_cabin+$cabin_width*0.95,$y_top+$height/10);

if ($MODE eq "pdf") {

ONO::Lib::PDF::Draw->rect($canvas,@rect1,$border,$border_color,$COLOR_BLACK_RAND);
ONO::Lib::PDF::Draw->rect($canvas,@rect2,$border,$border_color,$COLOR_MAIN);
ONO::Lib::PDF::Draw->rect($canvas,@rect3,$border,$border_color,$COLOR_MAIN_LIGHT);
ONO::Lib::PDF::Draw->rect($canvas,@rect4,$border,$border_color,$COLOR_WIN_RAND);
ONO::Lib::PDF::Draw->rect($canvas,@rect7,$border,$border_color,$COLOR_GREY_RAND);

} else {

$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect1,$border,$border_color,$COLOR_BLACK_RAND);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect2,$border,$border_color,$COLOR_MAIN);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect3,$border,$border_color,$COLOR_MAIN_LIGHT);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect4,$border,$border_color,$COLOR_WIN_RAND);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,@rect7,$border,$border_color,$COLOR_GREY_RAND);

}

}

if ($MODE eq "html") {
$HTML .= &train("",$canvas,$x,$y,"track",$width,$height,$switches);
}

$HTML = &train_canvas_wrapper("",$HTML,$width,$height,$switches,"","engine","",$vars_ref);
$HTML .= qq~<input type="hidden" name="engine_$opt{'id'}_transmit_color_main" value="$COLOR_MAIN">~;

}

if ($type =~ /^car/) {

# -R random roof color

my $model;
if ($type =~ /^car_(.*?)$/) {
$model = $1;
}
if (!$model) {
$model = "passenger";
}

if (!$COLOR_MAIN) {
$COLOR_MAIN = $COLOR_WHITE_RAND;
}

my $color_roof = "0:128:128:128";;

if (!$color_roof || $opt_main =~ /R/) {
$color_roof = $COLOR_RAND;
}

# custom vars color

if ($vars{"car_$opt{'id'}_color"}) {
$COLOR_MAIN = $vars{"car_$opt{'id'}_color"};
$color_roof = $vars{"car_$opt{'id'}_color"};
}

# transmitted color override

if ($vars{"car_$opt{'id'}_transmit_color_main"}) {
$COLOR_MAIN = $vars{"car_$opt{'id'}_transmit_color_main"};
}
if ($vars{"car_$opt{'id'}_transmit_color_roof"}) {
$color_roof = $vars{"car_$opt{'id'}_transmit_color_roof"};
}

# buffers
$HTML .= &train("",$canvas,$x,$y,"buffers",$width,$height,$switches);

# wheels:
$HTML .= &train("",$canvas,$x_left+$height/5,$y_bot,"wheel",$width,$height,$switches);
$HTML .= &train("",$canvas,$x_right-$height/5,$y_bot,"wheel",$width,$height,$switches);

if ($width > $height*1.5) {
$HTML .= &train("",$canvas,$x_left+$height/2,$y_bot,"wheel",$width,$height,$switches);
$HTML .= &train("",$canvas,$x_right-$height/2,$y_bot,"wheel",$width,$height,$switches);
}

my $y_text = ($y_high+$y_low)/2-$height/25;

if ($model eq "passenger") {

# box + roof:
if ($MODE eq "pdf") {
ONO::Lib::PDF::Draw->rect($canvas,$x_left,$y_top,$x_right,$y_low,$border,$border_color,$COLOR_MAIN);
ONO::Lib::PDF::Draw->rect($canvas,$x_left-$width/30,$y_top,$x_right+$width/30,$y_top+$height/10,$border,$border_color,$color_roof);
} else {
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,$x_left,$y_top,$x_right,$y_low,$border,$border_color,$COLOR_MAIN);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,$x_left-$width/30,$y_top,$x_right+$width/30,$y_top+$height/10,$border,$border_color,$color_roof);
}

}

if ($model eq "freight") {

$y_text = ($y_high+$y_low)/2-$height/10;

# box + roof:
if ($MODE eq "pdf") {
ONO::Lib::PDF::Draw->rect($canvas,$x_left+$width/20,$y_top,$x_right-$width/20,$y_low,$border,$border_color,$COLOR_MAIN);
ONO::Lib::PDF::Draw->rect($canvas,$x_left,$y_low-$height/10,$x_right,$y_low,$border,$border_color,$color_roof);
} else {
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,$x_left+$width/20,$y_top,$x_right-$width/20,$y_low,$border,$border_color,$COLOR_MAIN);
$HTML .= ONO::Lib::Image::Canvas::Draw->rect($canvas2,$x_left,$y_low-$height/10,$x_right,$y_low,$border,$border_color,$color_roof);
}

}

if ($opt{'text'} ne "") {
my $length = length $opt{'text'};
my $font = $height;
if ($length*$font/2 > $width) {
$font = $width/$length*3;
}
if ($font > $height) {
$font = $height;
}
if ($opt{'car_text_transform_dot_comma'} || $switches =~ /C/) {
$opt{'text'} =~ s~\.~\,~g;
}

if ($MODE eq "pdf") {
ONO::Lib::PDF::Draw->font('',$font);
ONO::Lib::PDF::Draw->text($canvas,($x_left+$x_right)/2,$y_text,$opt{'text'},"c");
} else {
$HTML .= ONO::Lib::Image::Canvas::Draw->text($canvas2,($x_left+$x_right)/2,$y_text,$opt{'text'},"c","",$font,"0:0:0:0");
}
}

if ($MODE eq "html") {
$HTML .= &train("",$canvas,$x,$y,"track",$width,$height,$switches);
}

$HTML = &train_canvas_wrapper("",$HTML,$width,$height,$switches,$opt{'id'},$opt{'text'},$opt{'placeholder'},$vars_ref);
$HTML .= qq~<input type="hidden" name="car_$opt{'id'}_transmit_color_main" value="$COLOR_MAIN">
<input type="hidden" name="car_$opt{'id'}_transmit_color_roof" value="$color_roof">
~;

}

if ($MODE eq "html") {

return $HTML;

} else {

return "";

}

}

sub train_canvas_wrapper {

my (
$self,
$HTML,
$width,
$height,
$switches,
$id,
$text,
$placeholder,
$vars_ref,
) = @_;

#: Canvas wraper for train HTML mode.

my %vars;
if ($vars_ref) {
%vars = %$vars_ref;
}

$height = $height*1.4;

my $INPUT;
if ($switches =~ /I/ && $text eq "") {
my $top = int($height/5);
my $height_input = int($height/3.5);
my $font_size = int($height/3.5);
$INPUT = qq~<div class="abs" style="width:${width}px;height:${height}px;top:${top}px">
<div class="inline auto w66">
<input type="text" name="train_car_input_text_$id" value="$vars{"train_car_input_text_$id"}" placeholder="$placeholder" class="w100 center" style="height:${height_input}px;font-size:${font_size}px">
</div>
</div>
~;
}

return qq~<div class="fl mb5 rel" style="width:${width}px;height:${height}px">$INPUT~.ONO::Lib::Image::Canvas::Draw->canvas_render($HTML,$width,$height).qq~</div>~;

}

###############################################################################
# end of script
###############################################################################

1;

__END__