Unicode in the footer does not wotk - unicode

I'm using the following snippet to add a footer to a PDF document.
It works fine, but although I have the UNCODE working in the PDF
document, it does not work in the footer. Otherwise what I ADDED
to the document.
gs -q -dNOPAUSE \
-sDEVICE=pdfwrite \
-sOUTPUTFILE=output.pdf \
-c '<< /EndPage \
{ exch pop 0 eq dup \
{ /CharterRegular 10 selectfont \
/ms {moveto show} bind def \
(J'aime le café) 40 40 ms \
} if \
} bind \
>> setpagedevice' \
-dBATCH input.pdf \
Any idea?
Thanks in advance

PDF does not generally use UTF-8 so it should fail as a PostScript command. This use of basic western characters can be a challenge to ensure the font is available or folder is defined or substituted in the fontmap.gs AND possibly Unicode charmap is correctly identified in octal. One unicode source I found for windows (unsure if 100% relevant) has
0xE9 0x00E9 #LATIN SMALL LETTER E WITH ACUTE so in octal that is \351
and this "works for me"
Note there are windows specific differences but those should be easily Portable, but I used MS Arial for testing. current GS 9.55/9.56 may need -dNEWPDF=false and do not use -q until testing is done.
gswin32c -sDEVICE=pdfwrite -dNEWPDF=false -sFONTPATH="C:\Windows\Fonts" -o"french.pdf" -c "<< /EndPage { exch pop 0 eq dup { /Arial 10 selectfont /ms {moveto show} bind def (J'aime le caf\351) 40 40 ms } if } bind >> setpagedevice" -f input.pdf
Later edit found an old CharterITCReg.ttf lurking about but note the difference in naming and only found that by trail [sic] and error.
gs9.56.1\bin>gs -dNEWPDF=false -sDEVICE=pdfwrite -sFONTPATH=c:\usr\myfonts\ -ofrench.pdf -c "<< /EndPage { exch pop 0 eq dup { /CharterITC-Regu 10 selectfont /ms {moveto show} bind def (J'aime le caf\351) 40 40 ms } if } bind >> setpagedevice" -f in.pdf

Returning to say that your solution worked for me.
'show' function does not do any Unicode conversion and I had to do it in advance my self. Nothing was wrong with my fonts, which I thought initially as the culprit.
Finally this is how I fixed the problem:
Picked up the right Unicode bloc for Latin script (Latin-1 Supplement) satisfying my needs (here)
Write a (ruby) function converting on the fly my strings to Unicode strings replacing the accentuated chars with their corresponding code.
Sending this string to the 'show' function.
While I was there I added the Even/Odd page aware footer message which I needed.
Here's the final code:
<< /EndPage
{ 0 eq dup
{ /Lora-Regular 8 selectfont
/ms {moveto show} bind def
exch 2 mod 0 eq
{
(J'aime le caf\351 - Even page ) 30 25 ms
}
{
(J'aime toujours le caf\351 - Odd page ) 30 25 ms
}
ifelse
} if
} bind
>> setpagedevice
Here are the Unicode char codes in case it can help somebody:
UNICODE = {
'â' => { oct: '342', hex: '00E2' },
'Â' => { oct: '302', hex: '00C2' },
'à' => { oct: '340', hex: '00E0' },
'À' => { oct: '300', hex: '00C0' },
'á' => { oct: '341', hex: '00E1' },
'Á' => { oct: '301', hex: '00C1' },
'æ' => { oct: '346', hex: '00E6' },
'Æ' => { oct: '306', hex: '00C6' },
'å' => { oct: '345', hex: '00E5' },
'Å' => { oct: '305', hex: '00C5' },
'ç' => { oct: '347', hex: '00E7' },
'Ç' => { oct: '307', hex: '00C7' },
'é' => { oct: '351', hex: '00E9' },
'É' => { oct: '311', hex: '00C9' },
'è' => { oct: '350', hex: '00E8' },
'È' => { oct: '310', hex: '00C8' },
'ë' => { oct: '353', hex: '00EB' },
'Ë' => { oct: '313', hex: '00CB' },
'ï' => { oct: '357', hex: '00EF' },
'Ï' => { oct: '317', hex: '00CF' },
'î' => { oct: '356', hex: '00EE' },
'Î' => { oct: '316', hex: '00CE' },
'ì' => { oct: '354', hex: '00EC' },
'Ì' => { oct: '314', hex: '00CC' },
'í' => { oct: '355', hex: '00ED' },
'Í' => { oct: '315', hex: '00CD' },
'ô' => { oct: '364', hex: '00F4' },
'Ô' => { oct: '324', hex: '00D4' },
'ö' => { oct: '366', hex: '00F6' },
'Ö' => { oct: '326', hex: '00D6' },
'ó' => { oct: '363', hex: '00F3' },
'Ó' => { oct: '323', hex: '00D3' },
'ò' => { oct: '362', hex: '00F2' },
'Ò' => { oct: '322', hex: '00D2' },
'õ' => { oct: '365', hex: '00F5' },
'Õ' => { oct: '325', hex: '00D5' },
'û' => { oct: '370', hex: '00F8' },
'Û' => { oct: '330', hex: '00D8' },
'ù' => { oct: '371', hex: '00F9' },
'Ù' => { oct: '331', hex: '00D9' },
'ú' => { oct: '372', hex: '00FA' },
'Ú' => { oct: '332', hex: '00DA' },
'ñ' => { oct: '361', hex: '00F1' },
'Ñ' => { oct: '321', hex: '00D1' },
'ý' => { oct: '375', hex: '00FD' },
'Ý' => { oct: '315', hex: '00CD' },
'®' => { oct: '256', hex: '00AE' },
'©' => { oct: '251', hex: '00A9' }
}
I kept the Hex values even though I don't use them (for now).
Thanks again #k-j. Seeing that it was working for you, told me that I was wrong in my assumptions blaming the poor fonts.

Related

Merging of duplicate path values of a Perl HOH

I have a perl HOH (hash of hash) wherein i have serial numbers 1,2,3.... so on and directory paths with associated counter values. Could anyone please suggest a way in which i can merge the duplicate internal paths (e.g, /usr/lib , /bin/ ) to a form a new hash with addition of the values?
Sample HOH:
$VAR1 = {
'1' => {
'/usr/lib' => 18
},
'3' => {
'/bin/' => '3'
},
'4' => {
'/usr/lib' => 12
},
'2' => {
'/bin/' => '6'
},
'5' => {
'/dev/' => '2'
},
'6' => {
'/tmp/' => '8'
}
};
Final output requirement i am looking for is a simple hash with combined values. No need of serial numbers:
$VAR1 = {
'/usr/lib' => '30',
'/bin/' => '9',
'/dev/' => '2',
'/tmp/' => '8'
};
Try
sub aggregate_counts {
my $HOH = shift;
my %out;
for my $h (values %$HOH) {
for my $k ( keys %$h) {
$out{$k} += $h->{$k};
}
}
\%out
}
Use this subroutine like aggregate_counts($hoh) to get hash reference in required format.
Complete Script for testing:
use strict;
use warnings;
sub aggregate_counts {
my $HOH = shift;
my %out;
for my $h (values %$HOH) {
for my $k ( keys %$h) {
$out{$k} += $h->{$k};
}
}
\%out
}
my
$VAR1 = {
'1' => {
'/usr/lib' => 18
},
'3' => {
'/bin/' => '3'
},
'4' => {
'/usr/lib' => 12
},
'2' => {
'/bin/' => '6'
},
'5' => {
'/dev/' => '2'
},
'6' => {
'/tmp/' => '8'
}
};
use Data::Dumper;
print Dumper(aggregate_counts($VAR1))
Output:
$VAR1 = {
'/dev/' => '2',
'/tmp/' => '8',
'/bin/' => 9,
'/usr/lib' => 30
};
This could help you:
use strict; use warnings;
use Data::Dumper;
my %hash = (
'1' => {
'/usr/lib' => 18
},
'3' => {
'/bin/' => '3'
},
'4' => {
'/usr/lib' => 12
},
'2' => {
'/bin/' => '6'
},
'5' => {
'/dev/' => '2'
},
'6' => {
'/tmp/' => '8'
}
);
my %result;
foreach my $key (keys %hash){
foreach my $inner (keys %{$hash{$key}}) {
$result{$inner} += $hash{$key}{$inner};
}
}
print Dumper(\%result);
Output:
$VAR1 = {
'/usr/lib' => 30,
'/bin/' => 9,
'/dev/' => 2,
'/tmp/' => 8
};
Note: Please post your code as well in the question while asking for a help in SO.
You don't care about the keys of the outer hash. So let's start with values(%$VAR1):
{ '/usr/lib' => 18 },
{ '/bin/' => '3' },
{ '/usr/lib' => 12 },
{ '/bin/' => '6' },
{ '/dev/' => '2' },
{ '/tmp/' => '8' },
Hashes are great for grouping. We're going to iterate over the above list, then we're going to iterates over the elements of each of those hashes, using a hash to group them.
my %grouped;
for my $inner (values(%$VAR1)) {
for my $key (keys(%$inner)) {
my $val = $inner->{$key};
$grouped{$key} += $val;
}
}
And we're already done.

How to print first element of subhash in reverse manner Perl

I want to print the values of every first $family reversely, and the first value it prints is the total scalar value in each $community.
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use Tie::Autotie 'Tie::IxHash';
my #NAMES = qw(AA AB AC BA BB BC CA CB CC AA AB AC BA BB BC CA CB CC AA AB AC BA BB BC CA CB CC AD CD CE CF BD BE);
my #FAMILIES = qw(A A A B B B C C C A A A B B B C C C A A A B B B C C C A C C C B B);
my #COMMUNITIES = qw(0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 0 2 2 2 1 1);
tie my %community_family_name, 'Tie::IxHash' ;
undef $community_family_name{ $COMMUNITIES[$_] }{ $FAMILIES[$_]}{$NAMES[$_]}
for 0 .. $#NAMES;
for my $community (keys %community_family_name) {
my $i = 0;
for my $family (keys %{ $community_family_name{$community} }) {
for my $name (keys %{ $community_family_name{$community}{$family} }) {
$community_family_name{$community}{$family}{$name} = $i++;
}
}
}
foreach my $community (sort keys %community_family_name)
{
foreach my $family (keys %{ $community_family_name{$community} })
{
foreach my $name (keys %{ $community_family_name{$community}{$family}})
{
print "[$community] = ";
print scalar "%{ $community_family_name{$community}";
print reverse "$community_family_name{$community}{$family}{$name}";
print " ";
}
}
}
print Dumper(\%community_family_name);
Current output:
[0] = HASH(0x1038c80)0 [0] = HASH(0x1038c80)1 [0] = HASH(0x1038c80)2 [0] = HASH(0x1038c80)3 [0] = HASH(0x1038c80)4 [0] = HASH(0x1038c80)5 [0] = HASH(0x1038c80)6 ...
Expected output:
[0] = 10 7 4 0
[1] = 11 8 3 0
[2] = 12 6 3 0
What is in the %community_family_name
$VAR1 = {
'0' => {
'A' => {
'AA' => [
0
],
'AB' => [
1
],
'AC' => [
2
],
'AD' => [
3
]
},
'B' => {
'BA' => [
4
],
'BB' => [
5
],
'BC' => [
6
]
},
'C' => {
'CA' => [
7
],
'CB' => [
8
],
'CC' => [
9
]
}
},
'1' => {
'A' => {
'AA' => [
0
],
'AB' => [
1
],
'AC' => [
2
]
},
'B' => {
'BA' => [
3
],
'BB' => [
4
],
'BC' => [
5
],
'BD' => [
6
],
'BE' => [
7
]
},
'C' => {
'CA' => [
8
],
'CB' => [
9
],
'CC' => [
10
]
}
},
'2' => {
'A' => {
'AA' => [
0
],
'AB' => [
1
],
'AC' => [
2
]
},
'B' => {
'BA' => [
3
],
'BB' => [
4
],
'BC' => [
5
]
},
'C' => {
'CA' => [
6
],
'CB' => [
7
],
'CC' => [
8
],
'CD' => [
9
],
'CE' => [
10
],
'CF' => [
11
]
}
}
};
You are almost there.
The first point is your expected result is per community, so your print functions must stay in the first loop.
The second is you must use scalar and reverse to arrays, not to scalar value such as double-quoted strings.
# Let me shorten your variable name, that's way too long...
my %cfn = %community_family_name;
foreach my $com (sort keys %cfn) {
# Count up keys in the community
my $count = map { keys %{$cfn{$com}->{$_}} } keys %{$cfn{$com}};
my #vals;
foreach my $family (reverse sort keys %{$cfn{$com}}) {
my ($first) = sort keys %{$cfn{$com}->{$family}};
push #vals, #{$cfn{$com}->{$family}->{$first}};
}
printf "[%d] = %s", $com, join q{ }, $count, #vals;
print "\n";
}

Issue accessing Hash in perl

I have a Hash of following structure in perl -
my %testHash = (
KeyL1 => {
KeyLL1 => {
KeyLLL1 => [1,2],
KeyLLL2 => [2,3],
},
KeyLL2 => {
KeyLLL1 => [1,2],
KeyLLL2 => [2,3],
},
KeyLL3 => {
KeyLLL1 => [1,2],
KeyLLL2 => [2,3],
},
},
KeyL2 => {
KeyLL1 => {
KeyLLL1 => [1,2],
KeyLLL2 => [2,3],
},
KeyLL2 => {
KeyLLL1 => [1,2],
KeyLLL2 => [2,3],
},
KeyLL3 => {
KeyLLL1 => [1,2],
KeyLLL2 => [2,3],
},
},
);
Now, when I am trying to access it the following way, I am getting 'undef' as a result
my %tempHash = $testHash{'KeyL1'};
print Data::Dumper::Dumper($tempHash{'KeyLL1'});
print Data::Dumper::Dumper($tempHash{'KeyLL1'}{'KeyLLL1'});
Result --
$VAR1 = undef; $VAR1 = undef;
Please point to me what am I doing wrong. I am pretty new to perl.
The value of $testHash{'KeyL1'} is a hashref, not a hash.
Hashrefs are scalars. my %tempHash = is not expecting a scalar.
You need to dereference it:
my %tempHash = %{$testHash{'KeyL1'}};
Also, you could do it this way if its just about viewing the structures.
Also try:
print Dumper $testHash{KeyL1} ;
print Dumper $testHash{KeyL1}{KeyLL1} ;
print Dumper $testHash{KeyL1}{KeyLL1}{KeyLLL1} ;
Output:
%_Host#User> ./hash.pl
$VAR1 = {
'KeyLL1' => {
'KeyLLL2' => [
2,
3
],
'KeyLLL1' => [
1,
2
]
},
'KeyLL2' => {
'KeyLLL2' => [
2,
3
],
'KeyLLL1' => [
1,
2
]
},
'KeyLL3' => {
'KeyLLL2' => [
2,
3
],
'KeyLLL1' => [
1,
2
]
}
};
$VAR1 = {
'KeyLLL2' => [
2,
3
],
'KeyLLL1' => [
1,
2
]
};
$VAR1 = [
1,
2
];
%_Host#User>

dynamically create url from hash ref in perl

I want to create url from input hash ref. Suppose I give hash ref as
my $input_hash_ref = {
'1' => 'A',
'2' => 'B',
'3' => {
'4' => {
'5' => {
'6' => [
'ice cream','drink'
],
'7' => 'large'
}
'8' => 'perl'
'9' => 'rosy'
},
'10'=>'june'
},
};
Then this is to be converted as
1=A&2=B&3.4.5.6=ice cream|drinks&3.4.5.7=large&3.8=perl&3.9=rosy&10=june
Help needed.
I just have to say, you shouldn't be composing query strings with a naive implementation with join.
use URI;
use URI::QueryParam;
my $u = URI->new("","http");
Then you can simply:
$u->query_param_append("1" => "A", "2" => "B", ....);
Or even
$u->query_form_hash( %somedata );
Note that this does not automatically deal with your custom schema for serialized nesting, but it does guarantee that you'll emit a valid query string that any server will understand.
Though you can also use a Perl Module to convert from a deeply-nested Hash to a Flat hash and back again:
Data::SplitSerializer
And you can use this to convert between formats on both sides.
Example usage:
use strict;
use warnings;
use utf8;
use Data::SplitSerializer;
use Data::Dump qw(pp);
use URI;
use URI::QueryParam;
my $input_hash = {
'1' => 'A',
'2' => 'B',
'3' => {
'4' => {
'5' => {
'6' => [
'ice cream','drink'
],
'7' => 'large'
}
},
},
'8' => 'june',
'9' => "Challenging & Value",
};
my $flattened = Data::SplitSerializer->new( path_style => 'DZIL' )->serialize($input_hash);
pp $flattened;
my $uri = URI->new("http://example.com/thing?");
$uri->query_form_hash( $flattened );
printf "%s\n", $uri;
my $copy = URI->new( $uri . "" ); # simulate getting it server side
my $copy_hash = $copy->query_form_hash;
pp $copy_hash;
my $deep = Data::
SplitSerializer->new( path_style => 'DZIL' )->deserialize($copy_hash);
pp $deep;
Example Output:
{
"1" => "A",
"2" => "B",
"3.4.5.6[0]" => "ice cream",
"3.4.5.6[1]" => "drink",
"3.4.5.7" => "large",
"8" => "june",
"9" => "Challenging & Value",
}
http://example.com/thing?9=Challenging+%26+Value&3.4.5.6%5B1%5D=drink&2=B&8=june&3.4.5.6%5B0%5D=ice+cream&1=A&3.4.5.7=large
{
"1" => "A",
"2" => "B",
"3.4.5.6[0]" => "ice cream",
"3.4.5.6[1]" => "drink",
"3.4.5.7" => "large",
"8" => "june",
"9" => "Challenging & Value",
}
{
1 => "A",
2 => "B",
3 => { 4 => { 5 => { 6 => ["ice cream", "drink"], 7 => "large" } } },
8 => "june",
9 => "Challenging & Value",
}
use URI::Escape;
sub serial {
my ($h, $p) = #_;
return join "&", map {
my $v = $h->{$_};
my $ref = ref($v);
my $isH = $ref eq "HASH";
my $pp = join ".", grep defined, $p, $_;
$v = $isH ? serial($v,$pp)
: $ref ? join("|", map uri_escape($_), #$v)
: uri_escape($v);
$isH ? $v : "$pp=$v";
}
sort keys %$h;
}
my $input_hash_ref = {
'1' => 'A',
'2' => 'B',
'3' => {
'4' => {
'5' => {
'6' => [
'ice cream','drink'
],
'7' => 'large'
}
},
},
'8' => 'june'
};
print serial($input_hash_ref);
output
1=A&2=B&3.4.5.6=ice cream|drink&3.4.5.7=large&8=june
sub c {
my ($v, $p) = #_;
my $r = ref($v);
return map { c($v->{$_}, $p ? $p . '.' . $_ : $_) } keys(%$v) if $r eq 'HASH';
return $p . '=' . join('|', #$v) if $r eq 'ARRAY';
return $p . '=' . $v;
}
say(join('&', c($input_hash_ref)));

Hash merge/concatenation

this is a dump of my hashes: %hash1
$VAR1 = {
abc => {
123 => [
'xx',
'yy',
'zy'
],
456 => [
'ab',
'cd',
'ef'
]
}
};
and the second one: %hash2
$VAR2 = {
def => {
659 => [
'wx',
'yg',
'kl'
],
456 => [
'as',
'sd',
'df'
]
},
abc => {
987 => [
'lk',
'dm',
'sd'
]
}
};
Now I want to merge these two hashes in a new hash, but if a key is duplicated (here 'abc'), the values should be appended, not replaced, so the keys should remain unique, and all the values should be retained as well. How can this be done in Perl?
The output should be as follows:
$VAR1 = {
def => {
659 => [
'wx',
'yg',
'kl'
],
456 => [
'as',
'sd',
'df'
]
},
abc => {
987 => [
'lk',
'dm',
'sd'
],
123 => [
'xx',
'yy',
'zy'
],
456 => [
'ab',
'cd',
'ef'
]
}
};
Use the CPAN modules Hash::Merge or Hash::Merge::Simple. The first is highly configurable and the second is very simple to use.
for my $x (keys(%h2)) {
for my $y (keys(%{ $h2{$x} })) {
push #{ $h1{$x}{$y} }, #{ $h2{$x}{$y} };
}
}
For the sample data provided, the following would perform the merging you describe:
my %merged = map {
$_ => {
%{$a{$_} // {}},
%{$b{$_} // {}}
}
} ( keys %a, keys %b );
Test:
use strict;
use warnings;
use Data::Dump 'dd';
my %a = (
abc => {
123 => [
'xx',
'yy',
'zy'
],
456 => [
'ab',
'cd',
'ef'
]
}
);
my %b = (
def => {
659 => [
'wx',
'yg',
'kl'
],
456 => [
'as',
'sd',
'df'
]
},
abc => {
987 => [
'lk',
'dm',
'sd'
]
}
);
my %merged = map {
$_ => {
%{$a{$_} // {}},
%{$b{$_} // {}}
}
} ( keys %a, keys %b );
dd \%merged;
# {
# abc => {
# 123 => ["xx", "yy", "zy"],
# 456 => ["ab", "cd", "ef"],
# 987 => ["lk", "dm", "sd"],
# },
# def => { 456 => ["as", "sd", "df"], 659 => ["wx", "yg", "kl"] },
# }
sub merge_hashes {
my ($h1, $h2) = #_;
foreach my $key (keys %$h2) {
if (!exists $h1->{$key} || ref($h1->{$key}) ne 'HASH' || ref($h2->{$key}) ne 'HASH') {
$h1->{$key} = $h2->{$key};
}
else {
merge_hashes($h1->{$key}, $h2->{$key});
}
}
}
merge_hashes(\%hash1, \%hash2);