Re: Tk::Canvas to PDF module offer
Petr Pajas <[email protected]>
| Newsgroups | gmane.comp.lang.perl.tk |
|---|---|
| Message-ID | <[email protected]> |
Dne út 30. listopadu 2004 08:31 John napsal(a): > Hello > > How did you hack the module? Simply:-) It uses PDF::API2 module to create the actual PDF content. It creates a new PDF object and a PDF page, then it examinines every object on a given canvas one by one and translates it to a corresponding PDF-object. It's really only a matter of itemCget, some conversions on the object parameters and some PDF::API2 calls. The only harder thing to implement were the arrows (if a multi-line is smooth, you have to position the arrow head correctly) and shapes. > Does it work for you? With any encoding even with iso-8859-7 ? Yes, of course, it works for me fine (Linux/Windows/MacOSX-X11) :-) (I use it as one of Print outputs in a tree-editor called TrEd - used mostly for linguistic annotation, see a shot: http://ckl.mff.cuni.cz/pajas/tred_doc/pics/treddiff.png or homepage: http://ckl.mff.cuni.cz/pajas/tred/), Yes, I hope it should handle iso-8859-7 too (at least, it worked with iso-8859-2 and iso-8859-6). If using "8bit" Tk (<800) only have to specify the encoding to the PDF conversion routine. If you use unicode/utf8 Tk>804, it should work out of the box. > Could you tell us more, because that is so intresting. It's attached. It's called Tk::Canvas::PDF and uses the same namespace. It can be used in various ways, but as the simplest approach it adds a new $canvas->pdf method (very similar to $canvas->postscript) to the Tk::Canvas namespace. It depends on the attached Tk::rgb.pm (it's just color-names to rgb map) and the standard Encode module (perl>=5.7), but the later dependency should be relatively easily to remove. I think it gives best result with TrueType fonts, but PS fonts and PDF-core fonts are supported as well. It only lacks documentation, except for a short (probably outdated) synopsis-like POD. As I told earlier, I don't have time to put it all in shape, at least not right now. So if anyone was interested in taking it, probably going through the code, writing some POD and preparing it for a release, I'd be glad. If not, you can use it as it is. Maybe in the up-comming weeks I'll be able to find some to do that myself... -- Petr > ----- Original Message ----- > From: "Petr Pajas" <[email protected]> > To: <[email protected]> > Sent: Monday, November 29, 2004 8:06 PM > Subject: Tk::Canvas to PDF module offer > > > > -++**==--++**==--++**==--++**==--++**==--++**==--++**== > This message was posted through the Stanford campus mailing list > server. If you wish to unsubscribe from this mailing list, send > the message body of "unsubscribe ptk" to > [email protected]
PDF.pm
(application/x-perl-module, 14.5 KB)
#$Id: PDF.pm,v 1.5 2003/12/12 12:01:10 pajas Exp $
# Tk::Canvas to PDF convertor.
# Copyright (c) 2003 by Petr Pajas
#
# This library is free software; you can use, modify, and
# redistribute it under the terms of GPL - The General Public
# Licence. Full text of the GPL can be found at
# http://www.gnu.org/copyleft/gpl.html
#
package Tk::Canvas::PDF;
BEGIN {
use Exporter;
use Tk::rgb;
use strict;
use base qw(Tk::Canvas Exporter);
use vars qw(%media %join %capstyle @EXPORT_OK);
@EXPORT_OK=(qw(%media));
eval "use Encode";
%join = (
bevel => 2,
miter => 0,
round => 1
);
%capstyle = (
butt => 0,
round => 1,
projecting => 2
);
%media = (
Letter => [612, 792],
LetterSmall => [612, 792],
Legal => [612, 1008],
Statement => [396, 612],
Tabloid => [792, 1224],
Ledger => [1224, 792],
Folio => [612, 936],
Quarto => [610, 780],
'7x9' => [504, 648],
'9x11' => [648, 792],
'9x12' => [648, 864],
'10x13' => [720, 936],
'10x14' => [720, 1008],
Executive => [540, 720],
A0 => [2384, 3370],
A1 => [1684, 2384],
A2 => [1191, 1684],
A3 => [842, 1191],
A4 => [595, 842],
A4Small => [595, 842],
A5 => [420, 595],
A6 => [297, 420],
A7 => [210, 297],
A8 => [148, 210],
A9 => [105, 148],
A10 => [73, 105],
B0 => [2920, 4127],
B1 => [2064, 2920],
B2 => [1460, 2064],
B3 => [1032, 1460],
B4 => [729, 1032],
B5 => [516, 729],
B6 => [363, 516],
B7 => [258, 363],
B8 => [181, 258],
B9 => [127, 181],
B10 => [91, 127],
ISOB0 => [2835, 4008],
ISOB1 => [2004, 2835],
ISOB2 => [1417, 2004],
ISOB3 => [1001, 1417],
ISOB4 => [709, 1001],
ISOB5 => [499, 709],
ISOB6 => [354, 499],
ISOB7 => [249, 354],
ISOB8 => [176, 249],
ISOB9 => [125, 176],
ISOB10 => [88, 125],
C0 => [2599, 3676],
C1 => [1837, 2599],
C2 => [1298, 1837],
C3 => [918, 1296],
C4 => [649, 918],
C5 => [459, 649],
C6 => [323, 459],
C7 => [230, 323]
);
}
=item $canvas->pdf(options)
Export cavnas content to PDF. Options:
=over 4
=item -media => media-name
A4,A5,B4,etc. or a bbox array of the form [x1,y1,x2,y2].
Defaults to A4.
=item -ttfont => filename
filename of a TrueType font
=item -psfont => [font-filename, afm-filename]
PostScript font as a pair of filenames of a PostScript font (pfb) and
a PostScript font metrics file (afm)
=item -font => name
PDF corefont filename
=item -file => filename
output filename
=back
=cut
sub __debug {
# print join "",@_; print "\n";
}
sub color2gray {
my ($color)=@_;
unless (ref($color)) {
if (!defined($color)) {
return undef;
} elsif ($color =~ /^#(..)(..)(..)/) {
$color = [map hex,$1,$2,$3];
} elsif (exists($Tk::rgb::rgb{$color})) {
$color = $Tk::rgb::rgb{$color};
} else {
warn "unknown color $color\n";
return 0;
}
}
no integer;
foreach (@$color) {
$_=$_ / 255;
$_=1-(1 - $_ ** 1.5);
$_=$_ * 255;
}
my $gray = int(sqrt($color->[0]**2+$color->[1]**2+$color->[2]**2)/sqrt(3));
return ("#".(sprintf("%02x",$gray) x 3));
}
sub new {
my ($class,%opts)=@_;
require PDF::API2;
my $pdf=PDF::API2->new;
my %fontmap;
my $unicode=$opts{-unicode}; # force unicode if possible
my $encoding=$opts{-encoding} || 'utf8';
$encoding = 'utf8' if $encoding =~ /^\s*unicode\s*$|^\s*utf-?8\s*$/i;
$encoding =~ s/^\s*windows-?/cp/i;
$encoding =~ s/^\s*latin-(\d+)?/latin$1/i;
$encoding =~ s/^\s*iso-?8859(\d+)/iso-8859-$1/i;
my @media;
if ($opts{-media}) {
if (ref($opts{-media})) {
@media=@{$opts{-media}};
} elsif (exists $media{$opts{-media}}) {
@media=(0,0,@{$media{$opts{-media}}});
} else {
die "Unknown media type $opts{-media}";
}
} else {
@media=(0,0,@{$media{A4}});
}
$pdf->mediabox(@media);
__debug("Media: @media, Encoding: $encoding\n");
if ($opts{-fontmap}) {
foreach my $fn (keys %{$opts{-fontmap}}) {
if ($opts{-fontmap}->{$fn}->[0] =~ /tt|truetype/i) {
if ($unicode or $encoding eq 'utf8') {
$fontmap{$fn}=$pdf->ttfont($opts{-fontmap}->{$fn}->[1])->unicode();
} else {
$fontmap{$fn}=$pdf->ttfont($opts{-fontmap}->{$fn}->[1],
-encode => $encoding);
}
} elsif ($opts{-fontmap}->{$fn}->[0] =~ /ps|postscript/i) {
$fontmap{$fn}=$pdf->psfont($opts{-fontmap}->{$fn}->[1],$opts{-fontmap}->{$fn}->[2],
$encoding ne 'utf8' ?
(-encode => $encoding) : ()
);
} elsif ($opts{-fontmap}->{$fn}->[0] =~ /core|builtin/i) {
$fontmap{$fn}=$pdf->corefont($opts{-fontmap}->{$fn}->[1],
$encoding ne 'utf8' ?
(-encode => $encoding) : ()
);
} else {
die "Canvas::PDF->pdf: unknown font type: $opts{-fontmap}->{$fn}";
}
}
}
my $font;
my $fontType;
if ($opts{-ttfont}) {
$fontType='TT';
if ($unicode or $encoding eq 'utf8') {
$font=$pdf->ttfont($opts{-ttfont})->unicode();
} else {
$font=$pdf->ttfont($opts{-ttfont},-encode => $encoding);
}
} elsif ($opts{-psfont}) {
$fontType='PS';
$font=$pdf->psfont($opts{-psfont}->[0],$opts{-psfont}->[1],
$encoding ne 'utf8' ?
(-encode => $encoding) : ()
);
} else {
$fontType='Core';
$font=$pdf->corefont('Helvetica',
$encoding ne 'utf8' ?
(-encode => $encoding) : ()
);
}
return bless {
Debug => $opts{-debug},
Encoding => $encoding,
Unicode => $unicode,
PDF => $pdf,
FontMap => \%fontmap,
Media => \@media,
DefaultFont => $font,
DefaultFontType => $fontType
},$class;
}
sub pdf {
my ($canvas,%opts)=@_;
my $P = __PACKAGE__->new(%opts);
$P->new_page(%opts);
$P->draw_canvas($canvas,%opts);
return $P->finish(%opts);
}
sub new_page {
my ($P,%opts)=@_;
$P->{current_page} = $P->{PDF}->page;
}
sub finish {
my ($P,%opts)=@_;
if ($opts{-file}) {
$P->{PDF}->saveas($opts{-file});
$P->{PDF}->end;
} else {
my $string = $P->{PDF}->stringify;
$P->{PDF}->end;
return $string;
}
}
sub draw_canvas {
my ($P,$canvas,%opts)=@_;
my $draw = $P->{current_page}->hybrid;
if ($opts{-transform}) {
$draw->transform(%{$opts{-transform}});
}
if ($opts{-translate}) {
$draw->translate(@{$opts{-translate}});
}
if ($opts{-rotate}) {
$draw->rotate($opts{-rotate});
}
if ($opts{-scale}) {
$draw->scale(@{$opts{-scale}});
}
if ($opts{-skew}) {
$draw->skew(@{$opts{-skew}});
}
if ($opts{-matrix}) {
$draw->matrix(@{$opts{-matrix}});
}
$draw->linedash();
$draw->linecap(0);
$draw->linejoin(0);
my $x = 0;
my $y = 0;
my $w = $opts{-width} || $P->{Media}[2];
my $h = $opts{-height} || $P->{Media}[3];
my $i;
foreach my $item ($canvas->find('all')) {
$draw->save;
my $type=$canvas->type($item);
my $state = $canvas->itemcget($item, '-state');
next if $state eq 'hidden';
$state = $state eq 'disabled' ? $state : '';
my @coords=$canvas->coords($item);
__debug("$type: orig @coords");
# recalculate coords for bottom/up
my $even=0;
foreach (@coords) {
$_=$h-$_ if $even;
$even=!$even;
}
__debug "$type: new @coords";
if ($type eq 'text') {
$draw->textstart;
my $anchor=$canvas->itemcget($item,'-anchor') || 'center';
my $color=$canvas->itemcget($item,"-${state}fill");
next unless defined($color); # transparent text = no text
$color = color2gray($color) if $opts{-grayscale};
my %canvasfont = $canvas->fontActual($canvas->itemcget($item,"-font"));
__debug "FONT:", (map {" $_ => $canvasfont{$_}, "} keys %canvasfont),"\n";
my $fn;
my $font_lookup_string = lc($canvasfont{-family}." ".$canvasfont{-weight}." ".$canvasfont{-slant});
if ($P->{FontMap}{$font_lookup_string}) {
$fn=$P->{FontMap}{$font_lookup_string};
} else {
warn ("'$font_lookup_string' font isn't mapped\n") if $P->{Debug};
$fn = $P->{DefaultFont};
}
my $fnsize=abs($canvasfont{-size});
my $text=$canvas->itemcget($item,"-text");
my $textwidth=$canvas->itemcget($item,"-width");
# TODO: width
__debug "$anchor\n";
$draw->linewidth(1);
$draw->linedash();
$draw->font($fn,$fnsize);
$draw->fillcolor($color);
my ($posx,$posy)=@coords;
my $ascent=$fn->ascender*$fnsize/1000;
my $descent=-$fn->descender*$fnsize/1000;
my $height=$ascent+$descent;
# my $height = $fn->capheight*$fnsize/1000;
my $width;
if (eval "Encode::is_utf8(\$text)" and not $@) {
$width = $fn->width_utf8($text)*$fnsize;
} elsif ($P->{Unicode}) {
eval "\$text= Encode::decode(\$P->{Encoding},\$text);";
$width = $fn->width_utf8($text)*$fnsize;
} else {
$width = $fn->width($text)*$fnsize;
}
__debug "Width: $width";
$posx-=$width/2;
$posy-=$height/2;
$anchor = '' if $anchor eq 'center';
if ($anchor =~ /s/) { $posy+=$height/2 }
elsif ($anchor =~ /n/) { $posy-=$height/2 }
if ($anchor =~ /e/) { $posx-=$width/2 }
elsif ($anchor =~ /w/) { $posx+=$width/2 }
$draw->translate($posx,$posy+$descent);
__debug "Text: $posx $posy $anchor";
if (eval "Encode::is_utf8(\$text)" and not $@ or $P->{Encoding} eq 'utf8') {
$draw->text($text,-utf8 => 1);
} else {
$draw->text($text);
}
$draw->textend;
} elsif ($type eq 'line') {
my $color=$canvas->itemcget($item,"-${state}fill");
next unless defined $color; # transparent line = no line
$color = color2gray($color) if $opts{-grayscale};
my $join=$canvas->itemcget($item,'-joinstyle');
my $capstyle=$canvas->itemcget($item,'-capstyle');
my $width=$canvas->itemcget($item,'-width');
my @dash=_canvas_to_pdf_dash($width,$canvas->itemcget($item,"-${state}dash"));
@dash=() if @dash<2;
my $smooth = $canvas->itemcget($item,"-smooth");
my $arrow = $canvas->itemcget($item,"-arrow");
my $ars = $canvas->itemcget($item,"-arrowshape") || [8,10,3];
# TODO: dashoffset
$draw->linewidth($width);
$draw->linedash(@dash);
$draw->linejoin($join{$join});
$draw->linecap($capstyle{$capstyle});
$draw->strokecolor($color);
$draw->fillcolor($color);
__debug "Line: @coords";
my @c=@coords;
# shorten line for arrows
for (qw(first last)) {
if ($arrow eq $_ or $arrow eq 'both') {
# we should adjust the enpoints to make space for the arrows
my ($x1,$y1,$x2,$y2) = $_ eq 'first' ? (0..3) : (-2,-1,-4,-3);
my $len = sqrt(($c[$x2]-$c[$x1])**2 + ($c[$y2]-$c[$y1])**2);
$c[$x1]+=($c[$x2]-$c[$x1])*0.9*$ars->[0]/$len;
$c[$y1]+=($c[$y2]-$c[$y1])*0.9*$ars->[0]/$len;
}
}
# draw line
if ($smooth and @c>=6) {
$draw->move(@c[0,1]);
$draw->curve(@c);
} else {
$draw->move(@c[0,1]);
$draw->line(@c[2..$#c]);
}
$draw->stroke;
# draw arrows
for (qw(first last)) {
if ($arrow eq $_ or $arrow eq 'both') {
@c=$_ eq 'first' ? @coords[0..3] : @coords[-2,-1,-4,-3];
my $angle = 180*atan2($c[2]-$c[0],$c[1]-$c[3])/3.14159265;
$draw->save;
$draw->translate(@c[0,1]);
$draw->linedash();
$draw->linecap(0);
$draw->linejoin(0);
$draw->rotate($_ eq 'first' ? -$angle : $angle-90);
$draw->move(0,0);
$draw->line($ars->[1],$ars->[2], $ars->[0],0, $ars->[1],-$ars->[2], 0,0);
$draw->close;
$draw->fillstroke;
$draw->restore;
}
}
} elsif ($type eq 'oval') {
my $width=$canvas->itemcget($item,'-width');
my @dash=_canvas_to_pdf_dash($width,$canvas->itemcget($item,"-${state}dash"));
@dash=() if @dash<2;
my $color=$canvas->itemcget($item,"-${state}fill");
my $outlinecolor=$canvas->itemcget($item,"-${state}outline");
$outlinecolor=$color if !defined($outlinecolor);
if ($opts{-grayscale}) {
$color = color2gray($color);
$outlinecolor = color2gray($outlinecolor);
}
# TODO: dashoffset
$draw->linewidth($width);
$draw->linedash(@dash);
$draw->strokecolor($outlinecolor) if defined $outlinecolor;
$draw->fillcolor($color) if defined $color;
my @c = (($coords[2]+$coords[0])/2,($coords[3]+$coords[1])/2,
($coords[2]-$coords[0])/2,($coords[3]-$coords[1])/2);
__debug "Ellipse: @c";
$draw->ellipse(@c);
if (defined($color)) {
$draw->fillstroke;
} else {
$draw->stroke;
}
} elsif ($type eq 'polygon') {
my $width=$canvas->itemcget($item,'-width');
my $join=$canvas->itemcget($item,'-joinstyle');
my @dash=_canvas_to_pdf_dash($width,$canvas->itemcget($item,"-${state}dash"));
@dash=() if @dash<2;
my $color=$canvas->itemcget($item,"-${state}fill");
my $outlinecolor=$canvas->itemcget($item,"-${state}outline");
$outlinecolor=$color if !defined($outlinecolor);
if ($opts{-grayscale}) {
$color = color2gray($color);
$outlinecolor = color2gray($outlinecolor);
}
my $smooth = $canvas->itemcget($item,"-smooth");
# TODO: dashoffset
$draw->linewidth($width);
$draw->linedash(@dash);
$draw->linejoin($join{$join});
$draw->strokecolor($outlinecolor) if defined($color);
$draw->fillcolor($color) if defined($color);
__debug "Polygon: @coords";
if ($smooth) {
$draw->move(@coords[0,1]);
$draw->curve(@coords);
$draw->close();
} else {
$draw->rect(@coords);
}
if (defined $color) {
$draw->fillstroke;
} else {
$draw->stroke;
}
} elsif ($type eq 'rectangle') {
my $width=$canvas->itemcget($item,'-width');
my @dash=_canvas_to_pdf_dash($width,$canvas->itemcget($item,"-${state}dash"));
@dash=() if @dash<2;
my $color=$canvas->itemcget($item,"-${state}fill");
my $outlinecolor=$canvas->itemcget($item,"-${state}outline");
$outlinecolor=$color if !defined($outlinecolor);
if ($opts{-grayscale}) {
$color = color2gray($color);
$outlinecolor = color2gray($outlinecolor);
}
# TODO: dashoffset
$draw->linewidth($width);
$draw->linedash(@dash);
$draw->linejoin(0);
$draw->linecap(0);
$draw->strokecolor($outlinecolor) if defined($outlinecolor);
$draw->fillcolor($color) if defined($color);
__debug "Rectangle: @coords";
$draw->rectxy(@coords);
if (defined $color) {
$draw->fillstroke;
} else {
$draw->stroke;
}
}
# TODO image, ...
} continue {
$draw->restore;
}
}
sub _canvas_to_pdf_dash {
my ($linewidth,@dash)=@_;
my $dash = join " ",@dash;
my %d=qw(. 40 - 120 , 80 _ 160);
$dash =~ s/(\d+)/$1*$linewidth/ge;
$dash =~ s/[-.,_]( *)/$d{$1}." ".40*(1+length($2))." "/ge;
$dash =~ s/[{}]//;
return split /\s*/,$dash;
}
package Tk::Canvas;
sub pdf {
my $self = shift;
Tk::Canvas::PDF::pdf($self,@_);
}
1;
rgb.pm
(application/x-perl-module, 21.2 KB)
package Tk::rgb;
BEGIN {
%rgb = (
'snow' => [255,250,250],
'ghost white' => [248,248,255],
'GhostWhite' => [248,248,255],
'white smoke' => [245,245,245],
'WhiteSmoke' => [245,245,245],
'gainsboro' => [220,220,220],
'floral white' => [255,250,240],
'FloralWhite' => [255,250,240],
'old lace' => [253,245,230],
'OldLace' => [253,245,230],
'linen' => [250,240,230],
'antique white' => [250,235,215],
'AntiqueWhite' => [250,235,215],
'papaya whip' => [255,239,213],
'PapayaWhip' => [255,239,213],
'blanched almond' => [255,235,205],
'BlanchedAlmond' => [255,235,205],
'bisque' => [255,228,196],
'peach puff' => [255,218,185],
'PeachPuff' => [255,218,185],
'navajo white' => [255,222,173],
'NavajoWhite' => [255,222,173],
'moccasin' => [255,228,181],
'cornsilk' => [255,248,220],
'ivory' => [255,255,240],
'lemon chiffon' => [255,250,205],
'LemonChiffon' => [255,250,205],
'seashell' => [255,245,238],
'honeydew' => [240,255,240],
'mint cream' => [245,255,250],
'MintCream' => [245,255,250],
'azure' => [240,255,255],
'alice blue' => [240,248,255],
'AliceBlue' => [240,248,255],
'lavender' => [230,230,250],
'lavender blush' => [255,240,245],
'LavenderBlush' => [255,240,245],
'misty rose' => [255,228,225],
'MistyRose' => [255,228,225],
'white' => [255,255,255],
'black' => [0,0,0],
'dark slate gray' => [47,79,79],
'DarkSlateGray' => [47,79,79],
'dark slate grey' => [47,79,79],
'DarkSlateGrey' => [47,79,79],
'dim gray' => [105,105,105],
'DimGray' => [105,105,105],
'dim grey' => [105,105,105],
'DimGrey' => [105,105,105],
'slate gray' => [112,128,144],
'SlateGray' => [112,128,144],
'slate grey' => [112,128,144],
'SlateGrey' => [112,128,144],
'light slate gray' => [119,136,153],
'LightSlateGray' => [119,136,153],
'light slate grey' => [119,136,153],
'LightSlateGrey' => [119,136,153],
'gray' => [190,190,190],
'grey' => [190,190,190],
'light grey' => [211,211,211],
'LightGrey' => [211,211,211],
'light gray' => [211,211,211],
'LightGray' => [211,211,211],
'midnight blue' => [25,25,112],
'MidnightBlue' => [25,25,112],
'navy' => [0,0,128],
'navy blue' => [0,0,128],
'NavyBlue' => [0,0,128],
'cornflower blue' => [100,149,237],
'CornflowerBlue' => [100,149,237],
'dark slate blue' => [72,61,139],
'DarkSlateBlue' => [72,61,139],
'slate blue' => [106,90,205],
'SlateBlue' => [106,90,205],
'medium slate blue' => [123,104,238],
'MediumSlateBlue' => [123,104,238],
'light slate blue' => [132,112,255],
'LightSlateBlue' => [132,112,255],
'medium blue' => [0,0,205],
'MediumBlue' => [0,0,205],
'royal blue' => [65,105,225],
'RoyalBlue' => [65,105,225],
'blue' => [0,0,255],
'dodger blue' => [30,144,255],
'DodgerBlue' => [30,144,255],
'deep sky blue' => [0,191,255],
'DeepSkyBlue' => [0,191,255],
'sky blue' => [135,206,235],
'SkyBlue' => [135,206,235],
'light sky blue' => [135,206,250],
'LightSkyBlue' => [135,206,250],
'steel blue' => [70,130,180],
'SteelBlue' => [70,130,180],
'light steel blue' => [176,196,222],
'LightSteelBlue' => [176,196,222],
'light blue' => [173,216,230],
'LightBlue' => [173,216,230],
'powder blue' => [176,224,230],
'PowderBlue' => [176,224,230],
'pale turquoise' => [175,238,238],
'PaleTurquoise' => [175,238,238],
'dark turquoise' => [0,206,209],
'DarkTurquoise' => [0,206,209],
'medium turquoise' => [72,209,204],
'MediumTurquoise' => [72,209,204],
'turquoise' => [64,224,208],
'cyan' => [0,255,255],
'light cyan' => [224,255,255],
'LightCyan' => [224,255,255],
'cadet blue' => [95,158,160],
'CadetBlue' => [95,158,160],
'medium aquamarine' => [102,205,170],
'MediumAquamarine' => [102,205,170],
'aquamarine' => [127,255,212],
'dark green' => [0,100,0],
'DarkGreen' => [0,100,0],
'dark olive green' => [85,107,47],
'DarkOliveGreen' => [85,107,47],
'dark sea green' => [143,188,143],
'DarkSeaGreen' => [143,188,143],
'sea green' => [46,139,87],
'SeaGreen' => [46,139,87],
'medium sea green' => [60,179,113],
'MediumSeaGreen' => [60,179,113],
'light sea green' => [32,178,170],
'LightSeaGreen' => [32,178,170],
'pale green' => [152,251,152],
'PaleGreen' => [152,251,152],
'spring green' => [0,255,127],
'SpringGreen' => [0,255,127],
'lawn green' => [124,252,0],
'LawnGreen' => [124,252,0],
'green' => [0,255,0],
'chartreuse' => [127,255,0],
'medium spring green' => [0,250,154],
'MediumSpringGreen' => [0,250,154],
'green yellow' => [173,255,47],
'GreenYellow' => [173,255,47],
'lime green' => [50,205,50],
'LimeGreen' => [50,205,50],
'yellow green' => [154,205,50],
'YellowGreen' => [154,205,50],
'forest green' => [34,139,34],
'ForestGreen' => [34,139,34],
'olive drab' => [107,142,35],
'OliveDrab' => [107,142,35],
'dark khaki' => [189,183,107],
'DarkKhaki' => [189,183,107],
'khaki' => [240,230,140],
'pale goldenrod' => [238,232,170],
'PaleGoldenrod' => [238,232,170],
'light goldenrod yellow' => [250,250,210],
'LightGoldenrodYellow' => [250,250,210],
'light yellow' => [255,255,224],
'LightYellow' => [255,255,224],
'yellow' => [255,255,0],
'gold' => [255,215,0],
'light goldenrod' => [238,221,130],
'LightGoldenrod' => [238,221,130],
'goldenrod' => [218,165,32],
'dark goldenrod' => [184,134,11],
'DarkGoldenrod' => [184,134,11],
'rosy brown' => [188,143,143],
'RosyBrown' => [188,143,143],
'indian red' => [205,92,92],
'IndianRed' => [205,92,92],
'saddle brown' => [139,69,19],
'SaddleBrown' => [139,69,19],
'sienna' => [160,82,45],
'peru' => [205,133,63],
'burlywood' => [222,184,135],
'beige' => [245,245,220],
'wheat' => [245,222,179],
'sandy brown' => [244,164,96],
'SandyBrown' => [244,164,96],
'tan' => [210,180,140],
'chocolate' => [210,105,30],
'firebrick' => [178,34,34],
'brown' => [165,42,42],
'dark salmon' => [233,150,122],
'DarkSalmon' => [233,150,122],
'salmon' => [250,128,114],
'light salmon' => [255,160,122],
'LightSalmon' => [255,160,122],
'orange' => [255,165,0],
'dark orange' => [255,140,0],
'DarkOrange' => [255,140,0],
'coral' => [255,127,80],
'light coral' => [240,128,128],
'LightCoral' => [240,128,128],
'tomato' => [255,99,71],
'orange red' => [255,69,0],
'OrangeRed' => [255,69,0],
'red' => [255,0,0],
'hot pink' => [255,105,180],
'HotPink' => [255,105,180],
'deep pink' => [255,20,147],
'DeepPink' => [255,20,147],
'pink' => [255,192,203],
'light pink' => [255,182,193],
'LightPink' => [255,182,193],
'pale violet red' => [219,112,147],
'PaleVioletRed' => [219,112,147],
'maroon' => [176,48,96],
'medium violet red' => [199,21,133],
'MediumVioletRed' => [199,21,133],
'violet red' => [208,32,144],
'VioletRed' => [208,32,144],
'magenta' => [255,0,255],
'violet' => [238,130,238],
'plum' => [221,160,221],
'orchid' => [218,112,214],
'medium orchid' => [186,85,211],
'MediumOrchid' => [186,85,211],
'dark orchid' => [153,50,204],
'DarkOrchid' => [153,50,204],
'dark violet' => [148,0,211],
'DarkViolet' => [148,0,211],
'blue violet' => [138,43,226],
'BlueViolet' => [138,43,226],
'purple' => [160,32,240],
'medium purple' => [147,112,219],
'MediumPurple' => [147,112,219],
'thistle' => [216,191,216],
'snow1' => [255,250,250],
'snow2' => [238,233,233],
'snow3' => [205,201,201],
'snow4' => [139,137,137],
'seashell1' => [255,245,238],
'seashell2' => [238,229,222],
'seashell3' => [205,197,191],
'seashell4' => [139,134,130],
'AntiqueWhite1' => [255,239,219],
'AntiqueWhite2' => [238,223,204],
'AntiqueWhite3' => [205,192,176],
'AntiqueWhite4' => [139,131,120],
'bisque1' => [255,228,196],
'bisque2' => [238,213,183],
'bisque3' => [205,183,158],
'bisque4' => [139,125,107],
'PeachPuff1' => [255,218,185],
'PeachPuff2' => [238,203,173],
'PeachPuff3' => [205,175,149],
'PeachPuff4' => [139,119,101],
'NavajoWhite1' => [255,222,173],
'NavajoWhite2' => [238,207,161],
'NavajoWhite3' => [205,179,139],
'NavajoWhite4' => [139,121,94],
'LemonChiffon1' => [255,250,205],
'LemonChiffon2' => [238,233,191],
'LemonChiffon3' => [205,201,165],
'LemonChiffon4' => [139,137,112],
'cornsilk1' => [255,248,220],
'cornsilk2' => [238,232,205],
'cornsilk3' => [205,200,177],
'cornsilk4' => [139,136,120],
'ivory1' => [255,255,240],
'ivory2' => [238,238,224],
'ivory3' => [205,205,193],
'ivory4' => [139,139,131],
'honeydew1' => [240,255,240],
'honeydew2' => [224,238,224],
'honeydew3' => [193,205,193],
'honeydew4' => [131,139,131],
'LavenderBlush1' => [255,240,245],
'LavenderBlush2' => [238,224,229],
'LavenderBlush3' => [205,193,197],
'LavenderBlush4' => [139,131,134],
'MistyRose1' => [255,228,225],
'MistyRose2' => [238,213,210],
'MistyRose3' => [205,183,181],
'MistyRose4' => [139,125,123],
'azure1' => [240,255,255],
'azure2' => [224,238,238],
'azure3' => [193,205,205],
'azure4' => [131,139,139],
'SlateBlue1' => [131,111,255],
'SlateBlue2' => [122,103,238],
'SlateBlue3' => [105,89,205],
'SlateBlue4' => [71,60,139],
'RoyalBlue1' => [72,118,255],
'RoyalBlue2' => [67,110,238],
'RoyalBlue3' => [58,95,205],
'RoyalBlue4' => [39,64,139],
'blue1' => [0,0,255],
'blue2' => [0,0,238],
'blue3' => [0,0,205],
'blue4' => [0,0,139],
'DodgerBlue1' => [30,144,255],
'DodgerBlue2' => [28,134,238],
'DodgerBlue3' => [24,116,205],
'DodgerBlue4' => [16,78,139],
'SteelBlue1' => [99,184,255],
'SteelBlue2' => [92,172,238],
'SteelBlue3' => [79,148,205],
'SteelBlue4' => [54,100,139],
'DeepSkyBlue1' => [0,191,255],
'DeepSkyBlue2' => [0,178,238],
'DeepSkyBlue3' => [0,154,205],
'DeepSkyBlue4' => [0,104,139],
'SkyBlue1' => [135,206,255],
'SkyBlue2' => [126,192,238],
'SkyBlue3' => [108,166,205],
'SkyBlue4' => [74,112,139],
'LightSkyBlue1' => [176,226,255],
'LightSkyBlue2' => [164,211,238],
'LightSkyBlue3' => [141,182,205],
'LightSkyBlue4' => [96,123,139],
'SlateGray1' => [198,226,255],
'SlateGray2' => [185,211,238],
'SlateGray3' => [159,182,205],
'SlateGray4' => [108,123,139],
'LightSteelBlue1' => [202,225,255],
'LightSteelBlue2' => [188,210,238],
'LightSteelBlue3' => [162,181,205],
'LightSteelBlue4' => [110,123,139],
'LightBlue1' => [191,239,255],
'LightBlue2' => [178,223,238],
'LightBlue3' => [154,192,205],
'LightBlue4' => [104,131,139],
'LightCyan1' => [224,255,255],
'LightCyan2' => [209,238,238],
'LightCyan3' => [180,205,205],
'LightCyan4' => [122,139,139],
'PaleTurquoise1' => [187,255,255],
'PaleTurquoise2' => [174,238,238],
'PaleTurquoise3' => [150,205,205],
'PaleTurquoise4' => [102,139,139],
'CadetBlue1' => [152,245,255],
'CadetBlue2' => [142,229,238],
'CadetBlue3' => [122,197,205],
'CadetBlue4' => [83,134,139],
'turquoise1' => [0,245,255],
'turquoise2' => [0,229,238],
'turquoise3' => [0,197,205],
'turquoise4' => [0,134,139],
'cyan1' => [0,255,255],
'cyan2' => [0,238,238],
'cyan3' => [0,205,205],
'cyan4' => [0,139,139],
'DarkSlateGray1' => [151,255,255],
'DarkSlateGray2' => [141,238,238],
'DarkSlateGray3' => [121,205,205],
'DarkSlateGray4' => [82,139,139],
'aquamarine1' => [127,255,212],
'aquamarine2' => [118,238,198],
'aquamarine3' => [102,205,170],
'aquamarine4' => [69,139,116],
'DarkSeaGreen1' => [193,255,193],
'DarkSeaGreen2' => [180,238,180],
'DarkSeaGreen3' => [155,205,155],
'DarkSeaGreen4' => [105,139,105],
'SeaGreen1' => [84,255,159],
'SeaGreen2' => [78,238,148],
'SeaGreen3' => [67,205,128],
'SeaGreen4' => [46,139,87],
'PaleGreen1' => [154,255,154],
'PaleGreen2' => [144,238,144],
'PaleGreen3' => [124,205,124],
'PaleGreen4' => [84,139,84],
'SpringGreen1' => [0,255,127],
'SpringGreen2' => [0,238,118],
'SpringGreen3' => [0,205,102],
'SpringGreen4' => [0,139,69],
'green1' => [0,255,0],
'green2' => [0,238,0],
'green3' => [0,205,0],
'green4' => [0,139,0],
'chartreuse1' => [127,255,0],
'chartreuse2' => [118,238,0],
'chartreuse3' => [102,205,0],
'chartreuse4' => [69,139,0],
'OliveDrab1' => [192,255,62],
'OliveDrab2' => [179,238,58],
'OliveDrab3' => [154,205,50],
'OliveDrab4' => [105,139,34],
'DarkOliveGreen1' => [202,255,112],
'DarkOliveGreen2' => [188,238,104],
'DarkOliveGreen3' => [162,205,90],
'DarkOliveGreen4' => [110,139,61],
'khaki1' => [255,246,143],
'khaki2' => [238,230,133],
'khaki3' => [205,198,115],
'khaki4' => [139,134,78],
'LightGoldenrod1' => [255,236,139],
'LightGoldenrod2' => [238,220,130],
'LightGoldenrod3' => [205,190,112],
'LightGoldenrod4' => [139,129,76],
'LightYellow1' => [255,255,224],
'LightYellow2' => [238,238,209],
'LightYellow3' => [205,205,180],
'LightYellow4' => [139,139,122],
'yellow1' => [255,255,0],
'yellow2' => [238,238,0],
'yellow3' => [205,205,0],
'yellow4' => [139,139,0],
'gold1' => [255,215,0],
'gold2' => [238,201,0],
'gold3' => [205,173,0],
'gold4' => [139,117,0],
'goldenrod1' => [255,193,37],
'goldenrod2' => [238,180,34],
'goldenrod3' => [205,155,29],
'goldenrod4' => [139,105,20],
'DarkGoldenrod1' => [255,185,15],
'DarkGoldenrod2' => [238,173,14],
'DarkGoldenrod3' => [205,149,12],
'DarkGoldenrod4' => [139,101,8],
'RosyBrown1' => [255,193,193],
'RosyBrown2' => [238,180,180],
'RosyBrown3' => [205,155,155],
'RosyBrown4' => [139,105,105],
'IndianRed1' => [255,106,106],
'IndianRed2' => [238,99,99],
'IndianRed3' => [205,85,85],
'IndianRed4' => [139,58,58],
'sienna1' => [255,130,71],
'sienna2' => [238,121,66],
'sienna3' => [205,104,57],
'sienna4' => [139,71,38],
'burlywood1' => [255,211,155],
'burlywood2' => [238,197,145],
'burlywood3' => [205,170,125],
'burlywood4' => [139,115,85],
'wheat1' => [255,231,186],
'wheat2' => [238,216,174],
'wheat3' => [205,186,150],
'wheat4' => [139,126,102],
'tan1' => [255,165,79],
'tan2' => [238,154,73],
'tan3' => [205,133,63],
'tan4' => [139,90,43],
'chocolate1' => [255,127,36],
'chocolate2' => [238,118,33],
'chocolate3' => [205,102,29],
'chocolate4' => [139,69,19],
'firebrick1' => [255,48,48],
'firebrick2' => [238,44,44],
'firebrick3' => [205,38,38],
'firebrick4' => [139,26,26],
'brown1' => [255,64,64],
'brown2' => [238,59,59],
'brown3' => [205,51,51],
'brown4' => [139,35,35],
'salmon1' => [255,140,105],
'salmon2' => [238,130,98],
'salmon3' => [205,112,84],
'salmon4' => [139,76,57],
'LightSalmon1' => [255,160,122],
'LightSalmon2' => [238,149,114],
'LightSalmon3' => [205,129,98],
'LightSalmon4' => [139,87,66],
'orange1' => [255,165,0],
'orange2' => [238,154,0],
'orange3' => [205,133,0],
'orange4' => [139,90,0],
'DarkOrange1' => [255,127,0],
'DarkOrange2' => [238,118,0],
'DarkOrange3' => [205,102,0],
'DarkOrange4' => [139,69,0],
'coral1' => [255,114,86],
'coral2' => [238,106,80],
'coral3' => [205,91,69],
'coral4' => [139,62,47],
'tomato1' => [255,99,71],
'tomato2' => [238,92,66],
'tomato3' => [205,79,57],
'tomato4' => [139,54,38],
'OrangeRed1' => [255,69,0],
'OrangeRed2' => [238,64,0],
'OrangeRed3' => [205,55,0],
'OrangeRed4' => [139,37,0],
'red1' => [255,0,0],
'red2' => [238,0,0],
'red3' => [205,0,0],
'red4' => [139,0,0],
'DeepPink1' => [255,20,147],
'DeepPink2' => [238,18,137],
'DeepPink3' => [205,16,118],
'DeepPink4' => [139,10,80],
'HotPink1' => [255,110,180],
'HotPink2' => [238,106,167],
'HotPink3' => [205,96,144],
'HotPink4' => [139,58,98],
'pink1' => [255,181,197],
'pink2' => [238,169,184],
'pink3' => [205,145,158],
'pink4' => [139,99,108],
'LightPink1' => [255,174,185],
'LightPink2' => [238,162,173],
'LightPink3' => [205,140,149],
'LightPink4' => [139,95,101],
'PaleVioletRed1' => [255,130,171],
'PaleVioletRed2' => [238,121,159],
'PaleVioletRed3' => [205,104,137],
'PaleVioletRed4' => [139,71,93],
'maroon1' => [255,52,179],
'maroon2' => [238,48,167],
'maroon3' => [205,41,144],
'maroon4' => [139,28,98],
'VioletRed1' => [255,62,150],
'VioletRed2' => [238,58,140],
'VioletRed3' => [205,50,120],
'VioletRed4' => [139,34,82],
'magenta1' => [255,0,255],
'magenta2' => [238,0,238],
'magenta3' => [205,0,205],
'magenta4' => [139,0,139],
'orchid1' => [255,131,250],
'orchid2' => [238,122,233],
'orchid3' => [205,105,201],
'orchid4' => [139,71,137],
'plum1' => [255,187,255],
'plum2' => [238,174,238],
'plum3' => [205,150,205],
'plum4' => [139,102,139],
'MediumOrchid1' => [224,102,255],
'MediumOrchid2' => [209,95,238],
'MediumOrchid3' => [180,82,205],
'MediumOrchid4' => [122,55,139],
'DarkOrchid1' => [191,62,255],
'DarkOrchid2' => [178,58,238],
'DarkOrchid3' => [154,50,205],
'DarkOrchid4' => [104,34,139],
'purple1' => [155,48,255],
'purple2' => [145,44,238],
'purple3' => [125,38,205],
'purple4' => [85,26,139],
'MediumPurple1' => [171,130,255],
'MediumPurple2' => [159,121,238],
'MediumPurple3' => [137,104,205],
'MediumPurple4' => [93,71,139],
'thistle1' => [255,225,255],
'thistle2' => [238,210,238],
'thistle3' => [205,181,205],
'thistle4' => [139,123,139],
'gray0' => [0,0,0],
'grey0' => [0,0,0],
'gray1' => [3,3,3],
'grey1' => [3,3,3],
'gray2' => [5,5,5],
'grey2' => [5,5,5],
'gray3' => [8,8,8],
'grey3' => [8,8,8],
'gray4' => [10,10,10],
'grey4' => [10,10,10],
'gray5' => [13,13,13],
'grey5' => [13,13,13],
'gray6' => [15,15,15],
'grey6' => [15,15,15],
'gray7' => [18,18,18],
'grey7' => [18,18,18],
'gray8' => [20,20,20],
'grey8' => [20,20,20],
'gray9' => [23,23,23],
'grey9' => [23,23,23],
'gray10' => [26,26,26],
'grey10' => [26,26,26],
'gray11' => [28,28,28],
'grey11' => [28,28,28],
'gray12' => [31,31,31],
'grey12' => [31,31,31],
'gray13' => [33,33,33],
'grey13' => [33,33,33],
'gray14' => [36,36,36],
'grey14' => [36,36,36],
'gray15' => [38,38,38],
'grey15' => [38,38,38],
'gray16' => [41,41,41],
'grey16' => [41,41,41],
'gray17' => [43,43,43],
'grey17' => [43,43,43],
'gray18' => [46,46,46],
'grey18' => [46,46,46],
'gray19' => [48,48,48],
'grey19' => [48,48,48],
'gray20' => [51,51,51],
'grey20' => [51,51,51],
'gray21' => [54,54,54],
'grey21' => [54,54,54],
'gray22' => [56,56,56],
'grey22' => [56,56,56],
'gray23' => [59,59,59],
'grey23' => [59,59,59],
'gray24' => [61,61,61],
'grey24' => [61,61,61],
'gray25' => [64,64,64],
'grey25' => [64,64,64],
'gray26' => [66,66,66],
'grey26' => [66,66,66],
'gray27' => [69,69,69],
'grey27' => [69,69,69],
'gray28' => [71,71,71],
'grey28' => [71,71,71],
'gray29' => [74,74,74],
'grey29' => [74,74,74],
'gray30' => [77,77,77],
'grey30' => [77,77,77],
'gray31' => [79,79,79],
'grey31' => [79,79,79],
'gray32' => [82,82,82],
'grey32' => [82,82,82],
'gray33' => [84,84,84],
'grey33' => [84,84,84],
'gray34' => [87,87,87],
'grey34' => [87,87,87],
'gray35' => [89,89,89],
'grey35' => [89,89,89],
'gray36' => [92,92,92],
'grey36' => [92,92,92],
'gray37' => [94,94,94],
'grey37' => [94,94,94],
'gray38' => [97,97,97],
'grey38' => [97,97,97],
'gray39' => [99,99,99],
'grey39' => [99,99,99],
'gray40' => [102,102,102],
'grey40' => [102,102,102],
'gray41' => [105,105,105],
'grey41' => [105,105,105],
'gray42' => [107,107,107],
'grey42' => [107,107,107],
'gray43' => [110,110,110],
'grey43' => [110,110,110],
'gray44' => [112,112,112],
'grey44' => [112,112,112],
'gray45' => [115,115,115],
'grey45' => [115,115,115],
'gray46' => [117,117,117],
'grey46' => [117,117,117],
'gray47' => [120,120,120],
'grey47' => [120,120,120],
'gray48' => [122,122,122],
'grey48' => [122,122,122],
'gray49' => [125,125,125],
'grey49' => [125,125,125],
'gray50' => [127,127,127],
'grey50' => [127,127,127],
'gray51' => [130,130,130],
'grey51' => [130,130,130],
'gray52' => [133,133,133],
'grey52' => [133,133,133],
'gray53' => [135,135,135],
'grey53' => [135,135,135],
'gray54' => [138,138,138],
'grey54' => [138,138,138],
'gray55' => [140,140,140],
'grey55' => [140,140,140],
'gray56' => [143,143,143],
'grey56' => [143,143,143],
'gray57' => [145,145,145],
'grey57' => [145,145,145],
'gray58' => [148,148,148],
'grey58' => [148,148,148],
'gray59' => [150,150,150],
'grey59' => [150,150,150],
'gray60' => [153,153,153],
'grey60' => [153,153,153],
'gray61' => [156,156,156],
'grey61' => [156,156,156],
'gray62' => [158,158,158],
'grey62' => [158,158,158],
'gray63' => [161,161,161],
'grey63' => [161,161,161],
'gray64' => [163,163,163],
'grey64' => [163,163,163],
'gray65' => [166,166,166],
'grey65' => [166,166,166],
'gray66' => [168,168,168],
'grey66' => [168,168,168],
'gray67' => [171,171,171],
'grey67' => [171,171,171],
'gray68' => [173,173,173],
'grey68' => [173,173,173],
'gray69' => [176,176,176],
'grey69' => [176,176,176],
'gray70' => [179,179,179],
'grey70' => [179,179,179],
'gray71' => [181,181,181],
'grey71' => [181,181,181],
'gray72' => [184,184,184],
'grey72' => [184,184,184],
'gray73' => [186,186,186],
'grey73' => [186,186,186],
'gray74' => [189,189,189],
'grey74' => [189,189,189],
'gray75' => [191,191,191],
'grey75' => [191,191,191],
'gray76' => [194,194,194],
'grey76' => [194,194,194],
'gray77' => [196,196,196],
'grey77' => [196,196,196],
'gray78' => [199,199,199],
'grey78' => [199,199,199],
'gray79' => [201,201,201],
'grey79' => [201,201,201],
'gray80' => [204,204,204],
'grey80' => [204,204,204],
'gray81' => [207,207,207],
'grey81' => [207,207,207],
'gray82' => [209,209,209],
'grey82' => [209,209,209],
'gray83' => [212,212,212],
'grey83' => [212,212,212],
'gray84' => [214,214,214],
'grey84' => [214,214,214],
'gray85' => [217,217,217],
'grey85' => [217,217,217],
'gray86' => [219,219,219],
'grey86' => [219,219,219],
'gray87' => [222,222,222],
'grey87' => [222,222,222],
'gray88' => [224,224,224],
'grey88' => [224,224,224],
'gray89' => [227,227,227],
'grey89' => [227,227,227],
'gray90' => [229,229,229],
'grey90' => [229,229,229],
'gray91' => [232,232,232],
'grey91' => [232,232,232],
'gray92' => [235,235,235],
'grey92' => [235,235,235],
'gray93' => [237,237,237],
'grey93' => [237,237,237],
'gray94' => [240,240,240],
'grey94' => [240,240,240],
'gray95' => [242,242,242],
'grey95' => [242,242,242],
'gray96' => [245,245,245],
'grey96' => [245,245,245],
'gray97' => [247,247,247],
'grey97' => [247,247,247],
'gray98' => [250,250,250],
'grey98' => [250,250,250],
'gray99' => [252,252,252],
'grey99' => [252,252,252],
'gray100' => [255,255,255],
'grey100' => [255,255,255],
'dark grey' => [169,169,169],
'DarkGrey' => [169,169,169],
'dark gray' => [169,169,169],
'DarkGray' => [169,169,169],
'dark blue' => [0,0,139],
'DarkBlue' => [0,0,139],
'dark cyan' => [0,139,139],
'DarkCyan' => [0,139,139],
'dark magenta' => [139,0,139],
'DarkMagenta' => [139,0,139],
'dark red' => [139,0,0],
'DarkRed' => [139,0,0],
'light green' => [144,238,144],
'LightGreen' => [144,238,144]
);
foreach (keys %rgb) {
$rgb{lc($_)}=$rgb{$_} if (lc($_) ne $_ and !exists($rgb{lc($_)}))
}
}
1;
signature.asc
(application/pgp-signature, 189 B)
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.3 (GNU/Linux) iD8DBQBBrGSxQfxdLDi03+IRAkF3AKCPNCMS08kAG/EXIvI26bm3rMo1wACbBuj0 TOrzf21mHbsX+E1RQCPTQgw= =2b+Y -----END PGP SIGNATURE-----