package ONO::Lib::PDF::Elements::Grid;
################################################################################
# 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 grid {
my (
$self,
$canvas,
$x1,
$y1,
$x2,
$y2,
$spacing,
$weight_inner,
$weight_outer,
$outset,
$color,
$switches,
$data_ref,
$color_line,
$font_ref,
) = @_;
#: This generates a grid.
#:
#: spacing is required -> integers draw a squared grid
#: -> "x:y" allows for grids that are not square
#: -> "x/y" will draw a grid with x cols and y rows (spacing will thus be calculated)
#:
#: outset (optional) allows to draw lines beyond the actual grid (top, bottom, left & right)
#:
#: color is the background of the entire grid -> "g/r/c" will colorize background, top row, left col,
#: creating a spreadsheet-like grid (all optional),
#: top row has priority (always on top of left grid)
#:
#: data_ref -> array containing data to be filled into the created grid boxes,
#: will simply fill from left to right, top to bottom
#:
#: -A autocrop, will limit the global size to spacing values (otherwise the result may be larger than
#: the indicated grid size)
#: -C comma in EU format (replaces commas in ALL cell data)
#: -f font options enabled (also disables default center text, required for font_ref)
#: -l light (combinable with -L)
#: -L even lighter (combinable with -l)
#: -m millimeter mode (only works if spacing = 1, will highlight 5 mm grid)
#: -M math symbol processing
#: -X clear all data that's not in the header row/col
my $DEBUG;
if ($spacing) {
eval "use PDF::Reuse";
if (!$@) {
my ($whilecounter,$disable_size_fix,@colors,$cols,$rows,$update_font_color);
my ($draw_x,$draw_y) = ($x1,$y1);
my ($spac_x,$spac_y) = ($spacing,$spacing);
if ($spacing =~ m~^(.*?):(.*?)$~) {
($spac_x,$spac_y) = ($1,$2);
}
if ($spacing =~ m~^(.*?)/(.*?)$~) {
my ($one,$two) = ($1,$2);
if ($one && $two) {
$spac_x = ($x2-$x1)/$one;
$spac_y = ($y2-$y1)/$two;
$disable_size_fix++;
}
}
$DEBUG .= qq~hello grid, ori = $draw_x,$draw_y, spacing = $spac_x,$spac_y, ~;
my $COLOR_LINE = "0:0:0:0";
if ($color_line) {
$COLOR_LINE = $color_line;
}
if ($spacing == 1 && $switches =~ /m/) {
if (!$color_line) {
$color_line = "0:0:0:0";
}
$COLOR_LINE = ONO::Lib::PDF::Draw->color_calc($color_line,30);
}
if ($switches =~ /l/) {
$COLOR_LINE = "0:70:70:70";
$color_line = ONO::Lib::PDF::Draw->color_calc($color_line,60);
}
if ($switches =~ /L/) {
$COLOR_LINE = "0:140:140:140";
$color_line = ONO::Lib::PDF::Draw->color_calc($color_line,60);
}
if ($switches =~ /l/ && $switches =~ /L/) {
$COLOR_LINE = "0:210:210:210";
$color_line = ONO::Lib::PDF::Draw->color_calc($color_line,50);
}
if (!$disable_size_fix) {
$DEBUG .= qq~size fixing for $x2,$y2 = ~;
# make sure that $x2 and $y2 are multiples of spacing
my ($ori_x,$ori_y) = ($x2,$y2);
my ($test_x,$test_y) = ($spac_x,$spac_y);
if ($spacing == 1 && $switches =~ /m/) {
($test_x,$test_y) = (5,5);
}
if ($test_x > 0) {
my $test = $x1;
if (($x2-$x1)%$test_x != 0) {
while ($test < $x2 && $whilecounter < 4096) {
$whilecounter++;
$test = $test + $test_x;
}
$x2 = $test;
}
}
if ($test_y > 0) {
my $test = $y1;
if (($y2-$y1)%$test_y != 0) {
while ($test < $y2 && $whilecounter < 4096) {
$whilecounter++;
$test = $test + $test_y;
}
$y2 = $test;
}
}
if ($switches =~ /A/) {
if ($x2 > $ori_x) {
$x2 = $x2-$test_x;
}
if ($y2 > $ori_y) {
$y2 = $y2-$test_y;
}
}
$DEBUG .= qq~$x2,$y2, ~;
}
# colors
if ($color) {
$DEBUG .= "input color = $color, ";
@colors = ($color);
if ($color =~ /\//) {
@colors = split(/\//,$color);
}
ONO::Lib::PDF::Draw->rect($canvas,$x1,$y1,$x2,$y2,0,"",$colors[0]);
if ($colors[2]) {
ONO::Lib::PDF::Draw->rect($canvas,$x1,$y1,$x1+$spac_x,$y2,0,"",$colors[2]);
}
if ($colors[1]) {
ONO::Lib::PDF::Draw->rect($canvas,$x1,$y1,$x2,$y1+$spac_y,0,"",$colors[1]);
}
}
# draw the grid
while ($draw_y < $y2+1 && $whilecounter < 4096) {
ONO::Lib::PDF::Draw->line($canvas,$x1-$outset-$weight_inner/6,$draw_y,$x2+$outset+$weight_inner/6,$draw_y,$weight_inner,$COLOR_LINE);
$draw_y = $draw_y + $spac_y;
$whilecounter++;
$rows++;
}
while ($draw_x < $x2+1 && $whilecounter < 4096) {
ONO::Lib::PDF::Draw->line($canvas,$draw_x,$y1-$outset-$weight_inner/6,$draw_x,$y2+$outset+$weight_inner/6,$weight_inner,$COLOR_LINE);
$draw_x = $draw_x + $spac_x;
$whilecounter++;
$cols++;
}
if ($spacing == 1 && $switches =~ /m/) {
my ($draw_x,$draw_y) = ($x1,$y1);
while ($draw_y < $y2+1 && $whilecounter < 4096) {
ONO::Lib::PDF::Draw->line($canvas,$x1-$outset,$draw_y,$x2+$outset,$draw_y,$weight_inner*2,$color_line);
$draw_y = $draw_y + 5;
$whilecounter++;
$rows++;
}
while ($draw_x < $x2+1 && $whilecounter < 4096) {
ONO::Lib::PDF::Draw->line($canvas,$draw_x,$y1-$outset,$draw_x,$y2+$outset,$weight_inner*2,$color_line);
$draw_x = $draw_x + 5;
$whilecounter++;
$cols++;
}
}
# outer border
if ($weight_outer > 0 && $weight_outer != $weight_inner) {
ONO::Lib::PDF::Draw->rect($canvas,$x1,$y1,$x2,$y2,$weight_outer,$COLOR_LINE);
}
# fill in data
if ($data_ref) {
$DEBUG .= "using table content data, ";
my @data = @$data_ref;
my $data_counter;
my %font;
my $FONT = "H";
if ($switches =~ /f/ && $font_ref) {
%font = %$font_ref;
$DEBUG .= "using custom font settings ($font{'align'},$font{'size'},$font{'type'},$font{'color'}), ";
if ($font{'type'} || $font{'size'}) {
if ($font{'type'} =~ /b/) {
$FONT = "HB";
}
if ($font{'type'} =~ /i/) {
$FONT = "HO";
if ($font{'type'} =~ /b/) {
$FONT = "HBO";
}
}
ONO::Lib::PDF::Draw->font($FONT,$font{'size'});
$update_font_color++;
}
if ($font{'color'}) {
ONO::Lib::PDF::Draw->color($font{'color'});
$update_font_color++;
}
}
for (my $r = 0; $r < $rows-1; $r++) {
for (my $c = 0; $c < $cols-1; $c++) {
if ($switches !~ /X/ || $r == 0 || $c == 0) {
if ($switches =~ /C/) {
$data[$data_counter] =~ s~\.~\,~g;
}
if ($switches =~ /M/ && $data[$data_counter] =~ /^(\+|\-|x|\/|add|sub|mul|div)$/) {
ONO::Lib::PDF::Draw->text_math_symbol($canvas,$x1+$c*$spac_x+$spac_x/2,$y1+$r*$spac_y+$spac_y*0.52,2.5,$data[$data_counter]);
} else {
my @fontdata = (
$x1+$c*$spac_x+$spac_x/2,
$y1+$r*$spac_y+$spac_y*0.66,
$data[$data_counter],
"c",
);
if ($switches =~ /f/) {
@fontdata = (
$x1+$c*$spac_x+2,
$y1+$r*$spac_y+$spac_y*0.66,
$data[$data_counter],
"",
);
if ($font{'align'} eq "center") {
@fontdata = (
$x1+$c*$spac_x+$spac_x/2,
$y1+$r*$spac_y+$spac_y*0.66,
$data[$data_counter],
"c",
);
}
if ($font{'align'} eq "right") {
@fontdata = (
$x1+$c*$spac_x+$spac_x-2,
$y1+$r*$spac_y+$spac_y*0.66,
$data[$data_counter],
"r",
);
}
}
if ($font{'type_cola'} =~ /(b|i)/) {
my $FONT2 = $FONT;
if ($c == 0 && ($r || !$font{'type_row0'})) {
if ($font{'type_cola'} =~ /i/) {
$FONT2 = "HO";
}
if ($font{'type_cola'} =~ /b/) {
$FONT2 = "HB";
if ($font{'type_cola'} =~ /i/) {
$FONT2 = "HBO";
}
}
}
ONO::Lib::PDF::Draw->font($FONT2,$font{'size'});
$update_font_color++;
}
if ($font{'type_row0'} =~ /(b|i)/ && $r == 0) {
my $FONT2 = $FONT;
if ($r == 0) {
if ($font{'type_row0'} =~ /i/) {
$FONT2 = "HO";
}
if ($font{'type_row0'} =~ /b/) {
$FONT2 = "HB";
if ($font{'type_row0'} =~ /i/) {
$FONT2 = "HBO";
}
}
}
ONO::Lib::PDF::Draw->font($FONT2,$font{'size'});
$update_font_color++;
}
my $COLOR;
if ($font{'color'} && ($font{'color_row0'} || $font{'color_cola'})) {
$COLOR = $font{'color'};
}
if ($c == 0 && $font{'color_cola'}) {
$COLOR = $font{'color_cola'};
}
if ($r == 0 && $font{'color_row0'}) {
$COLOR = $font{'color_row0'};
}
if ($COLOR) {
ONO::Lib::PDF::Draw->color($COLOR);
}
ONO::Lib::PDF::Draw->text($canvas,@fontdata);
}
}
$data_counter++;
}
}
if ($switches =~ /f/) {
if ($font{'size'} || $font{'type'}) {
ONO::Lib::PDF::Draw->font('H',12);
$update_font_color = 0;
}
if ($font{'color'}) {
ONO::Lib::PDF::Draw->color();
$update_font_color = 0;
}
}
}
if ($update_font_color) {
ONO::Lib::PDF::Draw->font('H',12);
ONO::Lib::PDF::Draw->color();
}
# done
}
}
return $DEBUG;
}
###############################################################################
# end of script
###############################################################################
1;
__END__