book-summaries/bin/busgrap.pl

2685 lines
67 KiB
Perl
Executable File

#!/usr/bin/perl -w
#
# busgraph.pl : Produce Business Graphs in troff format
# Deri James : 5th February 2015
#
# Copyright (C) 2015 Free Software Foundation, Inc.
# Written by Deri James <deri@chuzzlewit.demon.co.uk>
#
# This file is part of groff.
#
# groff is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# groff 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. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
use strict;
my @CMDS=(
['FRAME','c','pi/graph',"6c\t5c"],
['ORIGIN','c','pi/graph',''],
['DARKER','','pi/graph',.8],
['BORDER','p','pi/graph',0],
['BRDCOLOUR','#','pi/graph','black'],
['JUST','','pi/graph','left'],
['FT','p','pi/graph','HR'],
['PS','p','pi/graph','10'],
['VS','p','pi/graph','+10%'],
['TEXTCOLOUR','#','pi/graph','black'],
['BGCOLOUR','#','pi/graph',''],
['WALLCOLOUR','#','graph',''],
['LINECOLOUR','#','pi/graph','black'],
['THICKNESS','p','pi/graph','.2'],
['TYPE','','pi','pi'],
['3D','c','pi','0'],
['COLOURED','bool','pi/graph','no'],
['XRAD','c','pi','2c'],
['YRAD','c','pi','2c'],
['HOLE','','pi','0'],
['OTHERS','','pi',2.05],
['VDECIMALS','','pi',0],
['PDECIMALS','','pi',1],
['PDECIMALS','','graph',''],
['LABEL','','pi','$text ($percent%)'],
['KEYBOX','bool','pi/graph','no'],
['BOXFRAME','c','pi/graph',''], # xoffs, yoffs, width, depth
['BOXHEADS','','pi',"Name\tValue\t%"],
['BOXHEADS','','graph',''],
['BOXLABELS','','pi/graph',"\$text\t\$value\t\$percent"],
['BOXTABS','','pi/graph',"0cL 2.8cR 4cR"],
['FLOW','bool','pi/graph','no'],
['CAPTION','','pi/graph',''],
['SCOLOURS','#','pi/graph',"#bfad94\t#2a586f\t#dbd6ce\t#568da3\t#a17759\t#c1d4de\t#74c9aa\t#dee1b6\t#e1b866\t#bf5434\t#373c42\tgrey80"],
# SCOLOURS:#bfad94 #2a586f #dbd6ce #568da3 #a17759 #c1d4de #74c9aa #dee1b6 #e1b866 #bf5434 #373c42 grey80
# ['SCOLOURS','#','pi/graph',"cyan\tmagenta\tyellow\tpaleturquoise1\tgrey6\tgreen\tpeachpuff\tcornflowerblue\tpink2\tdarkgoldenrod\tdarkolivegreen1\tdarkturquoise"],
['NEGCOLOUR','#','graph',''],
['POSCOLOUR','#','graph',''],
['HGRID','bool','graph','no'],
['VGRID','bool','graph','no'],
['SERIES','undef','pi/graph',''],
['SYMSIZE','p','graph',2],
['FLOOR','undef','graph',''],
['HORIZONTAL','bool','graph','no'],
['SYNC','bool','graph','no'],
['SORT','bool','pi','n'],
['SHADOW','bool','pi','no'],
['SFILE','','pi/graph',''],
['STEPS','undef','graph',''],
['PDFBOOKMARK','','pi/graph',0],
);
my %colours=(
'black' => 'rgb #000000',
'grey' => 'rgb #bebebe',
'dimgrey' => 'rgb #696969',
'lightgray' => 'rgb #d3d3d3',
'lightslategrey' => 'rgb #778899',
'slategray' => 'rgb #708090',
'slategray1' => 'rgb #c6e2ff',
'slategray2' => 'rgb #b9d3ee',
'slategray3' => 'rgb #9fb6cd',
'slategray4' => 'rgb #6c7b8b',
'slategrey' => 'rgb #708090',
'grey0' => 'rgb #000000',
'grey1' => 'rgb #030303',
'grey2' => 'rgb #050505',
'grey3' => 'rgb #080808',
'grey4' => 'rgb #0a0a0a',
'grey5' => 'rgb #0d0d0d',
'grey6' => 'rgb #0f0f0f',
'grey7' => 'rgb #121212',
'grey8' => 'rgb #141414',
'grey9' => 'rgb #171717',
'grey10' => 'rgb #1a1a1a',
'grey11' => 'rgb #1c1c1c',
'grey12' => 'rgb #1f1f1f',
'grey13' => 'rgb #212121',
'grey14' => 'rgb #242424',
'grey15' => 'rgb #262626',
'grey16' => 'rgb #292929',
'grey17' => 'rgb #2b2b2b',
'grey18' => 'rgb #2e2e2e',
'grey19' => 'rgb #303030',
'grey20' => 'rgb #333333',
'grey21' => 'rgb #363636',
'grey22' => 'rgb #383838',
'grey23' => 'rgb #3b3b3b',
'grey24' => 'rgb #3d3d3d',
'grey25' => 'rgb #404040',
'grey26' => 'rgb #424242',
'grey27' => 'rgb #454545',
'grey28' => 'rgb #474747',
'grey29' => 'rgb #4a4a4a',
'grey30' => 'rgb #4d4d4d',
'grey31' => 'rgb #4f4f4f',
'grey32' => 'rgb #525252',
'grey33' => 'rgb #545454',
'grey34' => 'rgb #575757',
'grey35' => 'rgb #595959',
'grey36' => 'rgb #5c5c5c',
'grey37' => 'rgb #5e5e5e',
'grey38' => 'rgb #616161',
'grey39' => 'rgb #636363',
'grey40' => 'rgb #666666',
'grey41' => 'rgb #696969',
'grey42' => 'rgb #6b6b6b',
'grey43' => 'rgb #6e6e6e',
'grey44' => 'rgb #707070',
'grey45' => 'rgb #737373',
'grey46' => 'rgb #757575',
'grey47' => 'rgb #787878',
'grey48' => 'rgb #7a7a7a',
'grey49' => 'rgb #7d7d7d',
'grey50' => 'rgb #7f7f7f',
'grey51' => 'rgb #828282',
'grey52' => 'rgb #858585',
'grey53' => 'rgb #878787',
'grey54' => 'rgb #8a8a8a',
'grey55' => 'rgb #8c8c8c',
'grey56' => 'rgb #8f8f8f',
'grey57' => 'rgb #919191',
'grey58' => 'rgb #949494',
'grey59' => 'rgb #969696',
'grey60' => 'rgb #999999',
'grey61' => 'rgb #9c9c9c',
'grey62' => 'rgb #9e9e9e',
'grey63' => 'rgb #a1a1a1',
'grey64' => 'rgb #a3a3a3',
'grey65' => 'rgb #a6a6a6',
'grey66' => 'rgb #a8a8a8',
'grey67' => 'rgb #ababab',
'grey68' => 'rgb #adadad',
'grey69' => 'rgb #b0b0b0',
'grey70' => 'rgb #b3b3b3',
'grey71' => 'rgb #b5b5b5',
'grey72' => 'rgb #b8b8b8',
'grey73' => 'rgb #bababa',
'grey74' => 'rgb #bdbdbd',
'grey75' => 'rgb #bfbfbf',
'grey76' => 'rgb #c2c2c2',
'grey77' => 'rgb #c4c4c4',
'grey78' => 'rgb #c7c7c7',
'grey79' => 'rgb #c9c9c9',
'grey80' => 'rgb #cccccc',
'grey81' => 'rgb #cfcfcf',
'grey82' => 'rgb #d1d1d1',
'grey83' => 'rgb #d4d4d4',
'grey84' => 'rgb #d6d6d6',
'grey85' => 'rgb #d9d9d9',
'grey86' => 'rgb #dbdbdb',
'grey87' => 'rgb #dedede',
'grey88' => 'rgb #e0e0e0',
'grey89' => 'rgb #e3e3e3',
'grey90' => 'rgb #e5e5e5',
'grey91' => 'rgb #e8e8e8',
'grey92' => 'rgb #ebebeb',
'grey93' => 'rgb #ededed',
'grey94' => 'rgb #f0f0f0',
'grey95' => 'rgb #f2f2f2',
'grey96' => 'rgb #f5f5f5',
'grey97' => 'rgb #f7f7f7',
'grey98' => 'rgb #fafafa',
'grey99' => 'rgb #fcfcfc',
'grey100' => 'rgb #ffffff',
'aliceblue' => 'rgb #f0f8ff',
'blueviolet' => 'rgb #8a2be2',
'cadetblue' => 'rgb #5f9ea0',
'cadetblue1' => 'rgb #98f5ff',
'cadetblue2' => 'rgb #8ee5ee',
'cadetblue3' => 'rgb #7ac5cd',
'cadetblue4' => 'rgb #53868b',
'cornflowerblue' => 'rgb #6495ed',
'darkslateblue' => 'rgb #483d8b',
'darkturquoise' => 'rgb #00ced1',
'deepskyblue' => 'rgb #00bfff',
'deepskyblue1' => 'rgb #00bfff',
'deepskyblue2' => 'rgb #00b2ee',
'deepskyblue3' => 'rgb #009acd',
'deepskyblue4' => 'rgb #00688b',
'dodgerblue' => 'rgb #1e90ff',
'dodgerblue1' => 'rgb #1e90ff',
'dodgerblue2' => 'rgb #1c86ee',
'dodgerblue3' => 'rgb #1874cd',
'dodgerblue4' => 'rgb #104e8b',
'lightblue' => 'rgb #add8e6',
'lightblue1' => 'rgb #bfefff',
'lightblue2' => 'rgb #b2dfee',
'lightblue3' => 'rgb #9ac0cd',
'lightblue4' => 'rgb #68838b',
'lightcyan' => 'rgb #e0ffff',
'lightcyan1' => 'rgb #e0ffff',
'lightcyan2' => 'rgb #d1eeee',
'lightcyan3' => 'rgb #b4cdcd',
'lightcyan4' => 'rgb #7a8b8b',
'lightskyblue' => 'rgb #87cefa',
'lightskyblue1' => 'rgb #b0e2ff',
'lightskyblue2' => 'rgb #a4d3ee',
'lightskyblue3' => 'rgb #8db6cd',
'lightskyblue4' => 'rgb #607b8b',
'lightslateblue' => 'rgb #8470ff',
'lightsteelblue' => 'rgb #b0c4de',
'lightsteelblue1' => 'rgb #cae1ff',
'lightsteelblue2' => 'rgb #bcd2ee',
'lightsteelblue3' => 'rgb #a2b5cd',
'lightsteelblue4' => 'rgb #6e7b8b',
'mediumaquamarine' => 'rgb #66cdaa',
'mediumblue' => 'rgb #0000cd',
'mediumslateblue' => 'rgb #7b68ee',
'mediumturquoise' => 'rgb #48d1cc',
'midnightblue' => 'rgb #191970',
'navyblue' => 'rgb #000080',
'paleturquoise' => 'rgb #afeeee',
'paleturquoise1' => 'rgb #bbffff',
'paleturquoise2' => 'rgb #aeeeee',
'paleturquoise3' => 'rgb #96cdcd',
'paleturquoise4' => 'rgb #668b8b',
'powderblue' => 'rgb #b0e0e6',
'royalblue' => 'rgb #4169e1',
'royalblue1' => 'rgb #4876ff',
'royalblue2' => 'rgb #436eee',
'royalblue3' => 'rgb #3a5fcd',
'royalblue4' => 'rgb #27408b',
'skyblue' => 'rgb #87ceeb',
'skyblue1' => 'rgb #87ceff',
'skyblue2' => 'rgb #7ec0ee',
'skyblue3' => 'rgb #6ca6cd',
'skyblue4' => 'rgb #4a708b',
'slateblue' => 'rgb #6a5acd',
'slateblue1' => 'rgb #836fff',
'slateblue2' => 'rgb #7a67ee',
'slateblue3' => 'rgb #6959cd',
'slateblue4' => 'rgb #473c8b',
'steelblue' => 'rgb #4682b4',
'steelblue1' => 'rgb #63b8ff',
'steelblue2' => 'rgb #5cacee',
'steelblue3' => 'rgb #4f94cd',
'steelblue4' => 'rgb #36648b',
'aquamarine' => 'rgb #7fffd4',
'aquamarine1' => 'rgb #7fffd4',
'aquamarine2' => 'rgb #76eec6',
'aquamarine3' => 'rgb #66cdaa',
'aquamarine4' => 'rgb #458b74',
'azure' => 'rgb #f0ffff',
'azure1' => 'rgb #f0ffff',
'azure2' => 'rgb #e0eeee',
'azure3' => 'rgb #c1cdcd',
'azure4' => 'rgb #838b8b',
'blue' => 'rgb #0000ff',
'blue1' => 'rgb #0000ff',
'blue2' => 'rgb #0000ee',
'blue3' => 'rgb #0000cd',
'blue4' => 'rgb #00008b',
'cyan' => 'rgb #00ffff',
'cyan1' => 'rgb #00ffff',
'cyan2' => 'rgb #00eeee',
'cyan3' => 'rgb #00cdcd',
'cyan4' => 'rgb #008b8b',
'navy' => 'rgb #000080',
'turquoise' => 'rgb #40e0d0',
'turquoise1' => 'rgb #00f5ff',
'turquoise2' => 'rgb #00e5ee',
'turquoise3' => 'rgb #00c5cd',
'turquoise4' => 'rgb #00868b',
'darkslategray' => 'rgb #2f4f4f',
'darkslategray1' => 'rgb #97ffff',
'darkslategray2' => 'rgb #8deeee',
'darkslategray3' => 'rgb #79cdcd',
'darkslategray4' => 'rgb #528b8b',
'rosybrown' => 'rgb #bc8f8f',
'rosybrown1' => 'rgb #ffc1c1',
'rosybrown2' => 'rgb #eeb4b4',
'rosybrown3' => 'rgb #cd9b9b',
'rosybrown4' => 'rgb #8b6969',
'saddlebrown' => 'rgb #8b4513',
'sandybrown' => 'rgb #f4a460',
'beige' => 'rgb #f5f5dc',
'brown' => 'rgb #a52a2a',
'brown1' => 'rgb #ff4040',
'brown2' => 'rgb #ee3b3b',
'brown3' => 'rgb #cd3333',
'brown4' => 'rgb #8b2323',
'burlywood' => 'rgb #deb887',
'burlywood1' => 'rgb #ffd39b',
'burlywood2' => 'rgb #eec591',
'burlywood3' => 'rgb #cdaa7d',
'burlywood4' => 'rgb #8b7355',
'chocolate' => 'rgb #d2691e',
'chocolate1' => 'rgb #ff7f24',
'chocolate2' => 'rgb #ee7621',
'chocolate3' => 'rgb #cd661d',
'chocolate4' => 'rgb #8b4513',
'peru' => 'rgb #cd853f',
'tan' => 'rgb #d2b48c',
'tan1' => 'rgb #ffa54f',
'tan2' => 'rgb #ee9a49',
'tan3' => 'rgb #cd853f',
'tan4' => 'rgb #8b5a2b',
'darkgreen' => 'rgb #006400',
'darkkhaki' => 'rgb #bdb76b',
'darkolivegreen' => 'rgb #556b2f',
'darkolivegreen1' => 'rgb #caff70',
'darkolivegreen2' => 'rgb #bcee68',
'darkolivegreen3' => 'rgb #a2cd5a',
'darkolivegreen4' => 'rgb #6e8b3d',
'darkseagreen' => 'rgb #8fbc8f',
'darkseagreen1' => 'rgb #c1ffc1',
'darkseagreen2' => 'rgb #b4eeb4',
'darkseagreen3' => 'rgb #9bcd9b',
'darkseagreen4' => 'rgb #698b69',
'forestgreen' => 'rgb #228b22',
'greenyellow' => 'rgb #adff2f',
'lawngreen' => 'rgb #7cfc00',
'lightseagreen' => 'rgb #20b2aa',
'limegreen' => 'rgb #32cd32',
'mediumseagreen' => 'rgb #3cb371',
'mediumspringgreen' => 'rgb #00fa9a',
'mintcream' => 'rgb #f5fffa',
'olivedrab' => 'rgb #6b8e23',
'olivedrab1' => 'rgb #c0ff3e',
'olivedrab2' => 'rgb #b3ee3a',
'olivedrab3' => 'rgb #9acd32',
'olivedrab4' => 'rgb #698b22',
'palegreen' => 'rgb #98fb98',
'palegreen1' => 'rgb #9aff9a',
'palegreen2' => 'rgb #90ee90',
'palegreen3' => 'rgb #7ccd7c',
'palegreen4' => 'rgb #548b54',
'seagreen' => 'rgb #2e8b57',
'seagreen1' => 'rgb #54ff9f',
'seagreen2' => 'rgb #4eee94',
'seagreen3' => 'rgb #43cd80',
'seagreen4' => 'rgb #2e8b57',
'springgreen' => 'rgb #00ff7f',
'springgreen1' => 'rgb #00ff7f',
'springgreen2' => 'rgb #00ee76',
'springgreen3' => 'rgb #00cd66',
'springgreen4' => 'rgb #008b45',
'yellowgreen' => 'rgb #9acd32',
'chartreuse' => 'rgb #7fff00',
'chartreuse1' => 'rgb #7fff00',
'chartreuse2' => 'rgb #76ee00',
'chartreuse3' => 'rgb #66cd00',
'chartreuse4' => 'rgb #458b00',
'green' => 'rgb #00ff00',
'green1' => 'rgb #00ff00',
'green2' => 'rgb #00ee00',
'green3' => 'rgb #00cd00',
'green4' => 'rgb #008b00',
'khaki' => 'rgb #f0e68c',
'khaki1' => 'rgb #fff68f',
'khaki2' => 'rgb #eee685',
'khaki3' => 'rgb #cdc673',
'khaki4' => 'rgb #8b864e',
'darkorange' => 'rgb #ff8c00',
'darkorange1' => 'rgb #ff7f00',
'darkorange2' => 'rgb #ee7600',
'darkorange3' => 'rgb #cd6600',
'darkorange4' => 'rgb #8b4500',
'darksalmon' => 'rgb #e9967a',
'lightcoral' => 'rgb #f08080',
'lightsalmon' => 'rgb #ffa07a',
'lightsalmon1' => 'rgb #ffa07a',
'lightsalmon2' => 'rgb #ee9572',
'lightsalmon3' => 'rgb #cd8162',
'lightsalmon4' => 'rgb #8b5742',
'peachpuff' => 'rgb #ffdab9',
'peachpuff1' => 'rgb #ffdab9',
'peachpuff2' => 'rgb #eecbad',
'peachpuff3' => 'rgb #cdaf95',
'peachpuff4' => 'rgb #8b7765',
'bisque' => 'rgb #ffe4c4',
'bisque1' => 'rgb #ffe4c4',
'bisque2' => 'rgb #eed5b7',
'bisque3' => 'rgb #cdb79e',
'bisque4' => 'rgb #8b7d6b',
'coral' => 'rgb #ff7f50',
'coral1' => 'rgb #ff7256',
'coral2' => 'rgb #ee6a50',
'coral3' => 'rgb #cd5b45',
'coral4' => 'rgb #8b3e2f',
'honeydew' => 'rgb #f0fff0',
'honeydew1' => 'rgb #f0fff0',
'honeydew2' => 'rgb #e0eee0',
'honeydew3' => 'rgb #c1cdc1',
'honeydew4' => 'rgb #838b83',
'orange' => 'rgb #ffa500',
'orange1' => 'rgb #ffa500',
'orange2' => 'rgb #ee9a00',
'orange3' => 'rgb #cd8500',
'orange4' => 'rgb #8b5a00',
'salmon' => 'rgb #fa8072',
'salmon1' => 'rgb #ff8c69',
'salmon2' => 'rgb #ee8262',
'salmon3' => 'rgb #cd7054',
'salmon4' => 'rgb #8b4c39',
'sienna' => 'rgb #a0522d',
'sienna1' => 'rgb #ff8247',
'sienna2' => 'rgb #ee7942',
'sienna3' => 'rgb #cd6839',
'sienna4' => 'rgb #8b4726',
'deeppink' => 'rgb #ff1493',
'deeppink1' => 'rgb #ff1493',
'deeppink2' => 'rgb #ee1289',
'deeppink3' => 'rgb #cd1076',
'deeppink4' => 'rgb #8b0a50',
'hotpink' => 'rgb #ff69b4',
'hotpink1' => 'rgb #ff6eb4',
'hotpink2' => 'rgb #ee6aa7',
'hotpink3' => 'rgb #cd6090',
'hotpink4' => 'rgb #8b3a62',
'indianred' => 'rgb #cd5c5c',
'indianred1' => 'rgb #ff6a6a',
'indianred2' => 'rgb #ee6363',
'indianred3' => 'rgb #cd5555',
'indianred4' => 'rgb #8b3a3a',
'lightpink' => 'rgb #ffb6c1',
'lightpink1' => 'rgb #ffaeb9',
'lightpink2' => 'rgb #eea2ad',
'lightpink3' => 'rgb #cd8c95',
'lightpink4' => 'rgb #8b5f65',
'mediumvioletred' => 'rgb #c71585',
'mistyrose' => 'rgb #ffe4e1',
'mistyrose1' => 'rgb #ffe4e1',
'mistyrose2' => 'rgb #eed5d2',
'mistyrose3' => 'rgb #cdb7b5',
'mistyrose4' => 'rgb #8b7d7b',
'orangered' => 'rgb #ff4500',
'orangered1' => 'rgb #ff4500',
'orangered2' => 'rgb #ee4000',
'orangered3' => 'rgb #cd3700',
'orangered4' => 'rgb #8b2500',
'palevioletred' => 'rgb #db7093',
'palevioletred1' => 'rgb #ff82ab',
'palevioletred2' => 'rgb #ee799f',
'palevioletred3' => 'rgb #cd6889',
'palevioletred4' => 'rgb #8b475d',
'violetred' => 'rgb #d02090',
'violetred1' => 'rgb #ff3e96',
'violetred2' => 'rgb #ee3a8c',
'violetred3' => 'rgb #cd3278',
'violetred4' => 'rgb #8b2252',
'firebrick' => 'rgb #b22222',
'firebrick1' => 'rgb #ff3030',
'firebrick2' => 'rgb #ee2c2c',
'firebrick3' => 'rgb #cd2626',
'firebrick4' => 'rgb #8b1a1a',
'pink' => 'rgb #ffc0cb',
'pink1' => 'rgb #ffb5c5',
'pink2' => 'rgb #eea9b8',
'pink3' => 'rgb #cd919e',
'pink4' => 'rgb #8b636c',
'red' => 'rgb #ff0000',
'red1' => 'rgb #ff0000',
'red2' => 'rgb #ee0000',
'red3' => 'rgb #cd0000',
'red4' => 'rgb #8b0000',
'tomato' => 'rgb #ff6347',
'tomato1' => 'rgb #ff6347',
'tomato2' => 'rgb #ee5c42',
'tomato3' => 'rgb #cd4f39',
'tomato4' => 'rgb #8b3626',
'darkorchid' => 'rgb #9932cc',
'darkorchid1' => 'rgb #bf3eff',
'darkorchid2' => 'rgb #b23aee',
'darkorchid3' => 'rgb #9a32cd',
'darkorchid4' => 'rgb #68228b',
'darkviolet' => 'rgb #9400d3',
'lavenderblush' => 'rgb #fff0f5',
'lavenderblush1' => 'rgb #fff0f5',
'lavenderblush2' => 'rgb #eee0e5',
'lavenderblush3' => 'rgb #cdc1c5',
'lavenderblush4' => 'rgb #8b8386',
'mediumorchid' => 'rgb #ba55d3',
'mediumorchid1' => 'rgb #e066ff',
'mediumorchid2' => 'rgb #d15fee',
'mediumorchid3' => 'rgb #b452cd',
'mediumorchid4' => 'rgb #7a378b',
'mediumpurple' => 'rgb #9370db',
'mediumpurple1' => 'rgb #ab82ff',
'mediumpurple2' => 'rgb #9f79ee',
'mediumpurple3' => 'rgb #8968cd',
'mediumpurple4' => 'rgb #5d478b',
'lavender' => 'rgb #e6e6fa',
'magenta' => 'rgb #ff00ff',
'magenta1' => 'rgb #ff00ff',
'magenta2' => 'rgb #ee00ee',
'magenta3' => 'rgb #cd00cd',
'magenta4' => 'rgb #8b008b',
'maroon' => 'rgb #b03060',
'maroon1' => 'rgb #ff34b3',
'maroon2' => 'rgb #ee30a7',
'maroon3' => 'rgb #cd2990',
'maroon4' => 'rgb #8b1c62',
'orchid' => 'rgb #da70d6',
'orchid1' => 'rgb #ff83fa',
'orchid2' => 'rgb #ee7ae9',
'orchid3' => 'rgb #cd69c9',
'orchid4' => 'rgb #8b4789',
'plum' => 'rgb #dda0dd',
'plum1' => 'rgb #ffbbff',
'plum2' => 'rgb #eeaeee',
'plum3' => 'rgb #cd96cd',
'plum4' => 'rgb #8b668b',
'purple' => 'rgb #a020f0',
'purple1' => 'rgb #9b30ff',
'purple2' => 'rgb #912cee',
'purple3' => 'rgb #7d26cd',
'purple4' => 'rgb #551a8b',
'thistle' => 'rgb #d8bfd8',
'thistle1' => 'rgb #ffe1ff',
'thistle2' => 'rgb #eed2ee',
'thistle3' => 'rgb #cdb5cd',
'thistle4' => 'rgb #8b7b8b',
'violet' => 'rgb #ee82ee',
'antiquewhite' => 'rgb #faebd7',
'antiquewhite1' => 'rgb #ffefdb',
'antiquewhite2' => 'rgb #eedfcc',
'antiquewhite3' => 'rgb #cdc0b0',
'antiquewhite4' => 'rgb #8b8378',
'floralwhite' => 'rgb #fffaf0',
'ghostwhite' => 'rgb #f8f8ff',
'navajowhite' => 'rgb #ffdead',
'navajowhite1' => 'rgb #ffdead',
'navajowhite2' => 'rgb #eecfa1',
'navajowhite3' => 'rgb #cdb38b',
'navajowhite4' => 'rgb #8b795e',
'oldlace' => 'rgb #fdf5e6',
'whitesmoke' => 'rgb #f5f5f5',
'gainsboro' => 'rgb #dcdcdc',
'ivory' => 'rgb #fffff0',
'ivory1' => 'rgb #fffff0',
'ivory2' => 'rgb #eeeee0',
'ivory3' => 'rgb #cdcdc1',
'ivory4' => 'rgb #8b8b83',
'linen' => 'rgb #faf0e6',
'seashell' => 'rgb #fff5ee',
'seashell1' => 'rgb #fff5ee',
'seashell2' => 'rgb #eee5de',
'seashell3' => 'rgb #cdc5bf',
'seashell4' => 'rgb #8b8682',
'snow' => 'rgb #fffafa',
'snow1' => 'rgb #fffafa',
'snow2' => 'rgb #eee9e9',
'snow3' => 'rgb #cdc9c9',
'snow4' => 'rgb #8b8989',
'wheat' => 'rgb #f5deb3',
'wheat1' => 'rgb #ffe7ba',
'wheat2' => 'rgb #eed8ae',
'wheat3' => 'rgb #cdba96',
'wheat4' => 'rgb #8b7e66',
'white' => 'rgb #ffffff',
'blanchedalmond' => 'rgb #ffebcd',
'darkgoldenrod' => 'rgb #b8860b',
'darkgoldenrod1' => 'rgb #ffb90f',
'darkgoldenrod2' => 'rgb #eead0e',
'darkgoldenrod3' => 'rgb #cd950c',
'darkgoldenrod4' => 'rgb #8b6508',
'lemonchiffon' => 'rgb #fffacd',
'lemonchiffon1' => 'rgb #fffacd',
'lemonchiffon2' => 'rgb #eee9bf',
'lemonchiffon3' => 'rgb #cdc9a5',
'lemonchiffon4' => 'rgb #8b8970',
'lightgoldenrod' => 'rgb #eedd82',
'lightgoldenrod1' => 'rgb #ffec8b',
'lightgoldenrod2' => 'rgb #eedc82',
'lightgoldenrod3' => 'rgb #cdbe70',
'lightgoldenrod4' => 'rgb #8b814c',
'lightgoldenrodyellow' => 'rgb #fafad2',
'lightyellow' => 'rgb #ffffe0',
'lightyellow1' => 'rgb #ffffe0',
'lightyellow2' => 'rgb #eeeed1',
'lightyellow3' => 'rgb #cdcdb4',
'lightyellow4' => 'rgb #8b8b7a',
'palegoldenrod' => 'rgb #eee8aa',
'papayawhip' => 'rgb #ffefd5',
'cornsilk' => 'rgb #fff8dc',
'cornsilk1' => 'rgb #fff8dc',
'cornsilk2' => 'rgb #eee8cd',
'cornsilk3' => 'rgb #cdc8b1',
'cornsilk4' => 'rgb #8b8878',
'gold' => 'rgb #ffd700',
'gold1' => 'rgb #ffd700',
'gold2' => 'rgb #eec900',
'gold3' => 'rgb #cdad00',
'gold4' => 'rgb #8b7500',
'goldenrod' => 'rgb #daa520',
'goldenrod1' => 'rgb #ffc125',
'goldenrod2' => 'rgb #eeb422',
'goldenrod3' => 'rgb #cd9b1d',
'goldenrod4' => 'rgb #8b6914',
'moccasin' => 'rgb #ffe4b5',
'yellow' => 'rgb #ffff00',
'yellow1' => 'rgb #ffff00',
'yellow2' => 'rgb #eeee00',
'yellow3' => 'rgb #cdcd00',
'yellow4' => 'rgb #8b8b00',
);
my ($ln,%grph,@data,$colno,%sz,$buf,%defcol);
my $InBG=0;
my $piestart;
my $pi=3.1459*2;
my ($fh,$fn);
my @qname=('Jan-Mar','Apr-Jun','Jul-Sep','Oct-Dec');
my @hname=('Jan-Jun','Jul-Dec');
my @mname=('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
my ($stats,$ymarg,$xmarg,%stats);
$stats=\%stats;
while (<>)
{
chomp;
s/\r$//;
if (m'^\.\s*BGS\s*(\w*)')
{
my $type=($1)?$1:'pi';
if ($type ne 'FRAME')
{
$InBG=1;
%grph=();
@data=();
%stats=();
$grph{TYPE}->[0]=lc($type);
$buf="";
next;
}
}
if ($InBG and $_ eq '.BGE')
{
$InBG=0;
$buf.=".fl\n";
BuildGraph();
next;
}
if (!$InBG)
{
print "$_\n";
next;
}
s/^\s+//;
next if substr($_,0,1) eq '#';
$ln++;
if (m/^(.+?):(.*)/)
{
my $cmd=uc($1);
my (@args)=split("\t",$2);
my $cptr;
my $dup=0;
foreach my $c (@CMDS)
{
if ($cmd eq substr($c->[0],0,length($cmd)) and index("/$c->[2]/","/$grph{TYPE}->[0]/") >= 0)
{
$cptr=$c,$c->[4]=$ln if $dup == 0;
$dup++;
}
}
Log(1,"Command '$cmd' not understood") if $dup == 0;
Log(0,"Command '$cmd' is ambiguous - '$cptr->[0]' used") if $cmd ne 'SERIES' and $dup > 1;
$cmd=$cptr->[0];
if ($cmd eq 'SERIES')
{
LoadSeries(\@args);
}
elsif ($cmd eq 'SFILE')
{
if (open(F,"<$args[0]"))
{
while (<F>)
{
chomp;
s/\r$//;
s/^\s+//;
s/^S.*?://;
my (@r)=split("\t");
LoadSeries(\@r);
}
close(F);
}
else
{
Log(1,"Failed to open Series File '$args[0]'");
}
}
else
{
Log(0,$ln,"Redefined command '$cmd'") if exists($grph{$cmd});
$grph{$cmd}=\@args;
}
}
}
exit 0;
sub LoadSeries
{
my $args=shift;
if ($grph{TYPE}->[0] eq 'pi')
{
my ($nm,$val)=(@{$args});
my $valn=$val;
$valn=~s'\\.(\(..|\[.*\])''g;
$valn=~s/[^-0-9.]//g;
$valn=0 if $valn eq '';
$grph{NEGPIE}=1 if $valn < 0;
push(@data,[$valn,$nm,undef,$val]);
}
else
{
my ($sno,$txt,@data);
($sno,$txt,@data)=(@{$args});
$sno=1,$grph{BACKGROUND}=1 if uc($sno) eq 'B';
$sno-- if $sno=~m/^\d+$/ and $sno > 0;
foreach my $d (@data) {$d=~s/\((.+)\)/-$1/}
LoadData($sno,$txt,\@data);
}
}
sub BuildGraph
{
# All Commands now read, assign defaults for any missing
my $type='pi';
$type=lc($grph{TYPE}->[0]) if exists($grph{TYPE});
foreach my $c (@CMDS)
{
# Log(0,"Cmd=$c->[0]");
if (index($c->[2],$type) >= 0)
{
my $cmd=$c->[0];
if (!exists($grph{$cmd}) and $c->[1] ne 'undef')
{
my (@args)=split("\t",$c->[3]);
$args[0]='' if $#args==-1;
$grph{$cmd}=\@args;
}
# Add default scaling factors
my $scale=$c->[1];
if ($scale ne '' and exists($grph{$cmd}))
{
my $ct=-1;
foreach my $v (@{$grph{$cmd}})
{
if ($scale eq '#' and $v ne '')
{
# colours
$v=lc($v);
if (substr($v,0,1) eq '#')
{
$v=defcol("rgb $v");
}
elsif ($v=~m/(rgb|cmyk|cmy|gray|grey)\s+(.*)/)
{
$v=defcol("$1 $2");
}
elsif (exists($colours{$v}))
{
$v=defcol($colours{$v});
}
else
{
Log(0,"Colour names ($v) not found");
}
if ($cmd eq 'SCOLOURS')
{
$grph{CONTRAST}->[++$ct]=contrast($v);
}
}
elsif ($scale eq 'bool')
{
$v=lc($v);
if (substr($v,0,1) eq 'y')
{
$v=1;
}
elsif (substr($v,0,1) eq 'n')
{
$v=0;
}
}
else
{
if ($v=~m/^\s*([-0-9.+]+)\s*$/)
{
$v="$1$scale" if $scale ne 'undef';
}
}
}
}
# Now convert all values to points
if (exists($grph{$cmd}))
{
foreach my $v (@{$grph{$cmd}})
{
if ($scale ne '#' and $scale ne '' and $scale ne 'undef')
{
if ($v=~m/([\d.]+)([cimp])/i)
{
my $num=$1;
my $mul=$2;
$v=ToPoints($num,$mul,$c->[4]);
}
}
}
}
}
}
# If no ORIGIN or relative - centre it
if ($grph{TYPE}->[0] eq 'pi')
{
foreach my $i (0..1)
{
$grph{ORIGIN}->[$i]=0 if !$grph{ORIGIN}->[$i];
if ($grph{ORIGIN}->[$i]=~m/^[+-]/ or $grph{ORIGIN}->[$i] == 0)
{
$grph{ORIGIN}->[$i]+=int($grph{FRAME}->[$i]/2);
}
}
}
# VS may be a percentage of PS
if ($grph{VS}->[0]=~m/(\+|\-)?(\d+)%/)
{
my $p=$grph{PS}->[0];
my $d=$p*$2/100;
$d*=-1 if $1 and $1 eq '-';
$grph{VS}->[0]=$p+$d;
}
# Drop Shadow?
$grph{SHADE}=[];
if ($grph{SHADOW}->[0])
{
my $bg=$grph{BGCOLOUR}->[0] || 'rgb_#ffffff';
my ($coltype,$arg)=split('_',$bg,2);
my (@c)=GetComponents($arg);
my @add;
my $start;
if ($coltype eq 'cmyk')
{
$start=0xffff;
}
elsif ($coltype eq 'cmy')
{
$start=0xffff;
}
elsif ($coltype eq 'grey')
{
$start=0;
}
elsif ($coltype eq 'rgb')
{
$start=0;
}
foreach my $c (@c)
{
push(@add,($c-$start)/10);
}
foreach my $j (1..10)
{
foreach my $i (0..$#c)
{
$c[$i]-=$add[$i];
$c[$i]=0xffff if $c[$i] > 0xffff;
$c[$i]=0 if $c[$i] < 0;
}
push(@{$grph{SHADE}},defcol("$coltype #".join('',map(sprintf("%02x",$_>>8),@c))));
}
}
# Graph floor
if (exists($grph{FLOOR}) and $grph{FLOOR}->[0]=~/^C/)
{
substr($grph{FLOOR}->[0],0,1)='';
$grph{FLOORFLAG}->[0]='C';
}
else
{
$grph{FLOORFLAG}->[0]='';
}
# Frigging with horizontal bar graphs
if ($grph{HORIZONTAL}->[0])
{
# First make all series bar type
foreach my $s (@{$stats->{BAR}}) {$s=1;}
# Now alter data to $label~col1^col2...
foreach my $s (0..$#{$stats->{DATA}})
{
my $d=$stats->{DATA}->[$s];
my $v=shift(@{$d});
my $t=join('^',@{$d});
$stats->{NAME}->[$s].="~$t";
$stats->{DATA}->[$s]=[$v];
}
}
# Now find out width of any text
# my $tmpnm="busgraph-$$";
# my $tmpdir='/tmp';
#
# if (exists($ENV{GROFF_TMPDIR}))
# {
# $tmpdir=$ENV{GROFF_TMPDIR};
# }
# else
# {
# $tmpdir=$ENV{TMPDIR} if exists($ENV{TMPDIR});
# }
#
# my $seq='0000';
#
# do
# {
# $fn="$tmpdir/$tmpnm";
# $fn.="-$seq" if $seq ne '0000';
# $seq++;
# } until (! -e "$fn.dat");
#
# open($fh,">$fn.dat") or die "Failed to open '$fn.dat'";
#
# print $fh ".ps $grph{PS}->[0]\n";
# print $fh ".vs $grph{VS}->[0]\n";
# print $fh ".ft $grph{FT}->[0]\n";
#
# FindLen('I::','I');
# FindLen('II::','II');
# my $ser=0;
#
# foreach my $s (@data)
# {
# my $txt=$s->[1];
# my (@wds)=split(' ',$txt);
# $ser++;
# FindLen("S:$ser:TOT",$s->[1]);
#
# my $wd=0;
#
# foreach my $w (@wds)
# {
# $wd++;
#
# FindLen("S:${ser}:${wd}",$w);
# }
# }
#
# close($fh);
#
# LoadLengths("$fn.dat");
$buf.=".nr GRP:ll \\n[.ll]\n.ev GRP\n.ad l\n.ft $grph{FT}->[0]\n.fam ".substr($grph{FT}->[0],0,-1)."\n.ps $grph{PS}->[0]\n.vs 0\n\\M[$grph{TEXTCOLOUR}->[0]]\\c\n";
if ($grph{PDFBOOKMARK}->[0] and $grph{CAPTION}->[0])
{
$buf.=".pdfbookmark $grph{PDFBOOKMARK}->[0] ".($type eq 'pi'?'Pie':'Chart').": $grph{CAPTION}->[0]\n";
}
if ($grph{JUST}->[0] eq 'left')
{
$buf.=".nr GRP:lefx 0\n";
}
elsif ($grph{JUST}->[0] eq 'centre')
{
$buf.=".nr GRP:lefx \\n[GRP:ll]u/2-($grph{FRAME}->[0]p/2)\n";
}
else
{
$buf.=".nr GRP:lefx \\n[GRP:ll]u-$grph{FRAME}->[0]p\n";
}
if ($grph{TYPE}->[0] eq 'pi')
{
Do_Pie();
}
else
{
Do_Graph();
}
if ($grph{FLOW}->[0] and $grph{JUST}->[0] ne 'centre')
{
$buf.=".de GRP:skip\n.if \\\\n[.d]<\\\\n[GRP:mk]u+$grph{FRAME}->[1]p .sp |\\\\n[GRP:mk]u+$grph{FRAME}->[1]p\n..\n";
if ($grph{JUST}->[0] eq 'left')
{
$buf.=".sp |\\n[GRP:mk]u\n.nr GRP:JPos \\n[GRP:mk]u+$grph{FRAME}->[1]p-.9v\n.de GRP:Just\n'in -($grph{FRAME}->[0]p+8p)\n'sp \\\\n[.trunc]u\n.wh \\n[GRP:JPos]u\n..\n.wh \\n[GRP:JPos]u GRP:Just\n.in $grph{FRAME}->[0]p+8p\n";
}
elsif ($grph{JUST}->[0] eq 'right')
{
$buf.=".sp |\\n[GRP:mk]u\n.nr GRP:JPos \\n[GRP:mk]u+$grph{FRAME}->[1]p-.9v\n.de GRP:Just\n.ll +($grph{FRAME}->[0]p+8p)\n'sp \\\\n[.trunc]u\n.wh \\n[GRP:JPos]u\n..\n.wh \\n[GRP:JPos]u GRP:Just\n.ll -($grph{FRAME}->[0]p+8p)\n";
}
}
else
{
$buf.=".sp |\\n[GRP:mk]u+$grph{FRAME}->[1]p\n";
}
print ".BGS FRAME $grph{FRAME}->[0]p $grph{FRAME}->[1]p\n";
print $buf;
print ".BGE\n";
}
sub Log
{
my $crit=shift;
my $msg=shift;
print STDERR "busgrap: $msg\n";
exit 1 if $crit;
}
sub defcol
{
my $col=shift;
return('') if $col eq '';
my $colnm=$col;
$colnm=~tr[ ][_];
# return($colnm) if exists($defcol{$colnm});
my ($coltype,$arg)=split(' ',$col,2);
my (@c)=GetComponents($arg);
$buf.=".defcolor $colnm $coltype #".join('',map(sprintf("%02x",$_>>8),@c))."\n";
if ($coltype eq 'cmyk')
{
$c[3]+=0x10000*$grph{DARKER}->[0];
}
elsif ($coltype eq 'cmy')
{
foreach my $c (@c) {$c/=$grph{DARKER}->[0];}
}
elsif ($coltype eq 'gray')
{
$c[0]-=0x10000*$grph{DARKER}->[0];
}
elsif ($coltype eq 'rgb')
{
foreach my $c (@c) {$c*=$grph{DARKER}->[0];}
}
foreach my $c (@c)
{
$c=0xffff if ($c > 0xffff);
$c=0 if ($c<0);
}
$buf.=".defcolor ${colnm}DK $coltype #".join('',map(sprintf("%02x",$_>>8),@c))."\n";
$defcol{$colnm}=1;
return($colnm);
}
sub contrast
{
my $col=shift;
my ($coltype,$arg)=split('_',$col,2);
my (@c)=GetComponents($arg);
# (299*R + 587*G + 114*B) / 1000
if ($coltype eq "rgb")
{
return(((($c[0]>>8)*299 + ($c[1]>>8)*587 + ($c[2]>>8)*114)/1000)>128?'black':'white');
}
elsif ($coltype eq "grey")
{
return(($c[0]>128)?'black':'white');
}
return(undef);
}
sub GetComponents
{
my $arg=shift;
if ($arg=~m/([0-9.]+)f?\s+([0-9.]+)f?\s+([0-9.]+)f?/)
{
return($1*65535,$2*65535,$3*65535)
}
elsif ($arg=~m/(\d+)\s+(\d+)\s+(\d+)/)
{
return($1,$2,$3)
}
elsif (substr($arg,0,2) eq '##')
{
return(map(hex($_),$arg=~m/[0-9a-fA-F]{4}/g));
}
elsif (substr($arg,0,1) eq '#')
{
return((map(hex($_) << 8,$arg=~m/[0-9a-fA-F]{2}/g)));
}
Log(0,"Failed to convert colour component '$arg'");
return(());
}
sub FindLen
{
my $key=shift;
my $val=shift;
print $fh ".nr tm \\w'$val'\n.tm $key:\\n[tm]:\\n[rst]:\\n[rsb]\n";
}
sub LoadLengths
{
my $fn=shift;
open(F,"groff $fn -Z 2>&1 |") or die "Can't run groff!\n";
while (<F>)
{
chomp;
my (@r)=split(':');
$sz{$r[0]}->{$r[1]}->{$r[2]}=[@r[3..5]];
}
close(F) or die "Spawning groff failed!\n";
}
sub ToPoints
{
my $num=shift;
my $unit=shift;
my $ln=shift;
if ($unit eq 'i')
{
return($num*72);
}
elsif ($unit eq 'c')
{
return int($num*72/2.54);
}
elsif ($unit eq 'm') # millimetres
{
return int($num*72/25.4);
}
elsif ($unit eq 'p')
{
return($num);
}
elsif ($unit eq 'P')
{
return($num*6);
}
else
{
Log(1,$ln,"Unknown scaling factor '$unit'");
}
}
sub Do_Pie
{
my $tot=0;
my $totval='';
my $srt;
$piestart=$pi/8;
my $pieradx=$grph{XRAD}->[0]*1000;
my $pierady=$grph{YRAD}->[0]*1000;
my $pct=$grph{PDECIMALS}->[0];
my $residual=$grph{OTHERS}->[0];
my $key=$grph{KEYBOX}->[0];
my $hole=$grph{HOLE}->[0];
my $shadv=int((($pieradx+$pierady)/2)*.12);
my $shadh=int($shadv/2);
my $usey=$grph{FRAME}->[1];
my $usex=$grph{FRAME}->[0];
Log(1,0,"No Series data found") if $#data == -1;
my (@wdgs)=(@data);
if ($grph{SORT}->[0])
{
foreach my $wdg (sort {$b->[0] <=> $a->[0]} @wdgs)
{
$tot+=$wdg->[0];
push(@{$srt},$wdg);
}
}
else
{
foreach my $wdg (@wdgs)
{
$tot+=$wdg->[0];
push(@{$srt},$wdg);
}
}
my $totpctval=0;
my $bot=scalar(@wdgs)-1;
my $label=$grph{LABEL}->[0];
$label='' if $key;
return if $tot == 0;
return if $bot+1 < 1;
foreach my $wdg (@{$srt})
{
my $pctval=sprintf("%0.*f",abs(${pct}),$wdg->[0]*100/$tot);
$wdg->[2]=$pctval;
$totpctval+=$pctval;
}
$srt->[0]->[2]+=(100-$totpctval); # "correction" to make percentages = 100
my $srt2;
my $bot2=$bot;
# for (my $j=0; $j <= $bot2; $j++)
# {
# push(@{$srt2},$srt->[$j]);
#
# if ($j < $bot2)
# {
# push(@{$srt2},$srt->[$bot2--]);
# }
# }
#
# $srt=$srt2;
my $residtxt='';
for (my $j=$bot; $j > 0; $j--)
{
next if !defined($srt->[$j]) or $key;
if ($srt->[$j]->[2] < $residual)
{
my $i=$j;
my $t=$srt->[$j]->[2];
my $tc=1;
while ($i > 0 and (($t+$srt->[$i-1]->[2]) < ($residual*2)) or (($t+$srt->[$i-1]->[2])>=($residual*2) and ($srt->[$i-1]->[2] < $residual)))
{
$i--;
$t+=$srt->[$i]->[2];
$tc++;
}
if ($i < $j)
{
$residtxt.=', ' if $residtxt ne '';
$residtxt.=FillTplt($grph{LABEL}->[0],$srt->[$i]->[1],$srt->[$i]->[3],$srt->[$i]->[2],$pct);
$srt->[$i]->[1]="Others";
my $rt='';
foreach my $k ($i+1..$j)
{
$srt->[$i]->[2]+=$srt->[$k]->[2];
$srt->[$i]->[0]+=$srt->[$k]->[0];
$residtxt.=', ' if $residtxt ne '';
$rt=FillTplt($grph{LABEL}->[0],$srt->[$k]->[1],$srt->[$k]->[3],$srt->[$k]->[2],$pct);
$rt=~s/ /\\ /g;
$residtxt.=$rt;
$srt->[$k]=undef;
}
$srt->[$i]->[3]=$srt->[$i]->[0];
}
}
}
if (!$grph{NEGPIE})
{
$buf.=".ne ${usey}p\n.nf\n.vs 0\n.mk GRP:mk\n";
$buf.=".in \\n[GRP:lefx]u\n\\Z'\\D't $grph{THICKNESS}->[0]p'\\m[$grph{TEXTCOLOUR}->[0]]\\M[$grph{LINECOLOUR}->[0]]'\\c\n";
if ($grph{BGCOLOUR}->[0] ne '')
{
$buf.="\\Z@\\M[$grph{BGCOLOUR}->[0]]\\D'P ${usex}p 0 0 ${usey}p -${usex}p 0 0 -${usey}p'\\M[]@\\c\n";
}
if ($grph{BORDER}->[0])
{
$buf.="\\Z@\\D't $grph{BORDER}->[0]p'@\\Z@\\m[$grph{BRDCOLOUR}->[0]]\\D'p ${usex}p 0 0 ${usey}p -${usex}p 0 0 -${usey}p'\\D't $grph{THICKNESS}->[0]p'\\m[]@\\c\n";
}
$buf.=".fl\n.vs $grph{VS}->[0]p\n";
if ($grph{CAPTION}->[0] ne '')
{
$buf.=".fi\n.ad c\n.ll ${usex}p+\\n[GRP:lefx]u\n\\s'+2p'$grph{CAPTION}->[0]\\s'-2p'\n.sp -1\n.ad\n.nf\n";
}
$buf.="\\v'$grph{ORIGIN}->[1]p'\\h'$grph{ORIGIN}->[0]p'\\c\n";
my $lastfill=scalar(@{$grph{SHADE}})-1;
my $pie3d=$grph{'3D'}->[0];
if ($lastfill >= 1)
{
$buf.="\\v'${pie3d}p'";
$buf.="\\Z@\\v'${shadv}u'\\h'${shadh}u-${pieradx}u'";
foreach my $j (0..$lastfill-1) # must have at least 2 colours
{
$buf.="\\Z^\\M[".$grph{SHADE}->[$j]."]\\D'E ".(${pieradx}*2)."u ".(${pierady}*2)."u'^\\v'-".($shadv/$lastfill)."u'\\h'-".($shadh/$lastfill)."u'\\M[]";
}
$buf.="\\Z^\\h'-".($shadh/$lastfill)."u'\\M[".$grph{SHADE}->[$lastfill]."]\\D'E ".(${pieradx}*2)."u ".(${pierady}*2)."u'^\\M[]";
$buf.="@\\c\n";
$buf.="\\v'-${pie3d}p'\\c\n";
}
my $nooutline=($bot==0)?1:0;
$nooutline=1 if $grph{COLOURED}->[0];
if ($pie3d)
{
for (my $j=0; $j <= $bot; $j++)
{
next if !defined($srt->[$j]);
my ($val,$txt,$pctval)=(@{$srt->[$j]});
DoWedge3d(($val/$tot)*360,$grph{SCOLOURS}->[$j]."DK",$txt,$pieradx,$pierady,$nooutline,$grph{'3D'}->[0]) if $pct < 0 or $pctval > 0;
}
}
for (my $j=0; $j <= $bot; $j++)
{
next if !defined($srt->[$j]);
my ($val,$txt,$pctval,$valtxt)=(@{$srt->[$j]});
$pctval=($pct>=0)?sprintf("%0.*f",abs(${pct}),$pctval):'';
my $tmplt=FillTplt($grph{LABEL}->[0],$txt,$valtxt,$pctval,$pct);
$txt=$tmplt if $pct >= 0;
$txt='' if $label eq '';
DoWedge(($val/$tot)*360,$grph{SCOLOURS}->[$j],$txt,$pieradx,$pierady,$nooutline,$grph{'3D'}->[0]) if $pct < 0 or $pctval > 0;
}
if ($hole)
{
$piestart=$pi/8;
DoWedge(360,$grph{BGCOLOUR}->[0],'',$pieradx*$hole,$pierady*$hole,1,0);
}
if ($residtxt ne '')
{
my $ry=int($grph{ORIGIN}->[1]+$grph{YRAD}->[0]+$grph{'3D'}->[0]+2);
# setupfield($fldp,0,1,0);
$buf.=".ll ".($grph{FRAME}->[0])."p\n";
$buf.=".fi\n.ad c\n.sp ${ry}p+1.5v\nOthers includes: $residtxt\n.nf\n.ad l\n";
}
}
if ($key and !$grph{NEGPIE})
{
my $boxlabels=join("\t",@{$grph{BOXLABELS}});
my $boxheads=join("\t",@{$grph{BOXHEADS}});
my $boxtabs=join(' ',@{$grph{BOXTABS}});
$buf.=".vs 0\n.sp |\\n[GRP:mk]u+$grph{BOXFRAME}->[1]p\n.in +$grph{BOXFRAME}->[0]p\n.ta $boxtabs\n.vs\n.in +(1m+4p)\n\\fB$boxheads\\fP\n.sp -.2\n.in -(1m+4p)\n";
for (my $j=0; $j <= $bot; $j++)
{
next if !defined($srt->[$j]);
my ($val,$txt,$pctval,$valtxt)=(@{$srt->[$j]});
my $textcol=$grph{TEXTCOLOUR}->[0];
my $linecol=$grph{LINECOLOUR}->[0];
$linecol=$grph{SCOLOURS}->[$j] if $grph{COLOURED}->[0];
$valtxt=FillTplt($boxlabels,$txt,$valtxt,$pctval,$pct);
$buf.="\\M[$grph{SCOLOURS}->[$j]]\\m[$linecol]";
$buf.="\\Z!\\D'P 0 1 1 0 0 -1'!" if $val > 0;
$buf.="\\D'p 0 1 1 0 0 -1'\\M[]\n.in +1m\n.in +4p\n.sp -.2v\n";
$buf.="\\m[$textcol]$valtxt\\m[]\n.sp -.5\n.in -(1m+4p)\n";
}
# if ($totval and $bot > 0)
# {
# my $pctval=($pct>=0)?sprintf("%0.*f%%",abs(${pct}),100):'';
# $buf.=".in +1m\n'in +$fldk->{INDENT}->{LEFT}p\n'sp +.8v\nTotal\\c\n.in -1m\n.in -$fldk->{INDENT}->{LEFT}p\n'sp -1\n\t$totval\t$pctval\n";
# }
}
$buf.=".fl\n.ev\n";
# print $buf;
}
sub FillTplt
{
my $tmplt=shift;
my $txt=shift;
my $valtxt=shift;
my $pctval=shift;
my $pct=shift;
$tmplt=~s/\$text/$txt/ge;
$tmplt=~s/\$value/$valtxt/ge;
$tmplt=~s/\$percent/sprintf("%0.*f",abs($pct),$pctval)/ge;
return($tmplt);
}
sub PtoR
{
my $theta=shift;
my $radx=shift;
my $rady=shift;
my $y=-int(sin($theta)*$rady);
my $x=int(cos($theta)*$radx);
return ($x,$y);
}
sub rad
{
my $deg=shift;
return((($deg)/360)*$pi);
}
sub deg
{
my $rad=shift;
return(($rad*360)/$pi);
}
sub DoWedge
{
my ($ox,$oy)=(0,0);
my $end=rad($_[0])+$piestart;
my $col=$_[1];
my $txt=$_[2];
my $pieradx=$_[3];
my $pierady=$_[4];
my $nooutline=$_[5];
my $depth3d=$_[6]*1000;
my $step=.05;
my $points='';
my $j;
for ($j=$piestart; $j<=$end; $j+=$step)
{
# $j=$end if $end-$j < $step;
my ($x,$y)=PtoR($j,$pieradx,$pierady);
$x-=$ox;
$y-=$oy;
$points.="${x}u ${y}u ";
$ox+=$x;
$oy+=$y;
}
if ($j < $end+$step)
{
$j=$end;
my ($x,$y)=PtoR($j,$pieradx,$pierady);
$x-=$ox;
$y-=$oy;
$points.="${x}u ${y}u ";
$ox+=$x;
$oy+=$y;
}
$points.="-${ox}u -${oy}u'";
$buf.="\\M[$col]\\D'P 0 0 $points\\M[]\\c\n";
$buf.="\\m[$grph{LINECOLOUR}->[0]]\\D'p 0 0 $points\\m[]\\c\n" if !$nooutline;
$j=$piestart+(($end-$piestart)/2);
while ($j-$pi >= 0) {$j-=$pi;}
$piestart=$end;
return if $txt eq '';
my ($x,$y)=PtoR($j,$pieradx*1.05,$pierady*1.15);
$depth3d=0 if !($j>=$pi/2 and $j < $pi);
$buf.=".nr wi \\w'$txt'\n";
$buf.="\\Z@\\h'${x}u'\\v'${y}u+${depth3d}u'";
$buf.="\\v'\\n[rsb]u'" if $y < -1000;
$buf.="\\v'\\n[rst]u'" if $y > 1000;
rjust($txt) if $x < -1000;
ljust($txt) if $x > 1000;
cjust($txt) if abs($x) <= 1000;
$buf.="@\\c\n";
my($x1,$y1)=PtoR($j,$pieradx,$pierady);
$x-=$x1;
$y-=$y1;
$y1+=$depth3d;
$buf.="\\Z@\\h'${x1}u'\\v'${y1}u'\\D'l ${x}u ${y}u'@\\c\n";
}
sub DoWedge3d
{
my ($ox,$oy)=(0,0);
my $end=rad($_[0])+$piestart;
my $col=$_[1];
my $txt=$_[2];
my $pieradx=$_[3];
my $pierady=$_[4];
my $nooutline=$_[5];
my $depth3d=$_[6]*1000;
my $step=.05;
my $points='';
my $j;
my $doing3d=0;
my $predark='';
my $offs;
my $sx;
for ($j=$piestart; $j<=$end; $j+=$step)
{
# $j=$end if $end-$j < $step;
my ($x,$y)=PtoR($j,$pieradx,$pierady);
if ($doing3d==0 and $j>=$pi/2 and $j < $pi)
{
$doing3d=1;
$offs=$y+$depth3d;
$ox=$x;
$oy=$y;
$sx=$x;
$predark="0u ${offs}u";
}
elsif ($doing3d==1 and $j>=$pi)
{
$doing3d=2;
last;
}
elsif ($doing3d==1)
{
$x-=$ox;
$y-=$oy;
$points.="${x}u ${y}u ";
$ox+=$x;
$oy+=$y;
}
}
if ($doing3d==1 and $j < $end+$step)
{
$j=$end;
my ($x,$y)=PtoR($j,$pieradx,$pierady);
$x-=$ox;
$y-=$oy;
$points.="${x}u ${y}u ";
$ox+=$x;
$oy+=$y;
}
if ($doing3d)
{
$offs=$depth3d+$oy;
my $ex=$sx-$ox;
$points.="0 -${offs}u ${ex}u 0'\\h'-${sx}u";
$buf.="\\M[$col]\\h'${sx}u'\\D'P $predark $points'\\M[]\\c\n";
$buf.="\\h'${sx}u'\\m[$grph{LINECOLOUR}->[0]]\\D'p $predark $points'\\m[]\\c\n" if !$nooutline;
}
$j=$piestart+(($end-$piestart)/2);
$piestart=$end;
}
sub rjust
{
my $txt=shift;
$buf.="\\h'-\\n[wi]u'$txt";
}
sub ljust
{
my $txt=shift;
$buf.="$txt";
}
sub cjust
{
my $txt=shift;
$buf.="\\h'-\\n[wi]u/2u'$txt";
}
sub Do_Graph
{
CalcData();
PlotData();
}
sub LoadData
{
my $s=shift;
my $nm=shift;
my $d=shift;
if (uc($s) eq 'X')
{
push(@{$stats->{LABELS}},@{$d});
}
elsif (uc($s) eq 'A')
{
push(@{$stats->{ANCHOR}},undef,@{$d});
}
else
{
if (uc(substr($nm,0,4)) eq "BAR:")
{
$nm=substr($nm,4);
$stats->{BAR}->[$s]=1;
}
else
{
$stats->{BAR}->[$s]=0;
}
push(@{$stats->{DATA}->[$s]},@{$d});
$stats->{NAME}->[$s]=$nm;
}
}
sub CalcData
{
my $pointsz=$grph{PS}->[0];
my ($min,$max,$factor,$range,$diff,$steps,$step,$bars);
my $floorflag=$grph{FLOORFLAG}->[0];
my $horizontal=$grph{HORIZONTAL}->[0];
$factor=0;
foreach my $set (@{$stats->{DATA}})
{
next if !defined($set);
$#{$set}=$#{$stats->{LABELS}};
my @tset=@{$set};
while (@tset)
{
my $y=shift(@tset);
last if !defined($y);
next if $y eq '.';
if ($y =~ m/\.(\d+)$/)
{
$factor=length($1) if length($1) > $factor;
}
}
}
$stats->{YFACTOR}=$factor;
my $floor=(exists($grph{FLOOR}))?$grph{FLOOR}->[0]*10**$factor:undef;
$min=$max=$floor if defined($floor);
foreach my $set (@{$stats->{DATA}})
{
next if !defined($set);
my @tset=@{$set};
while (@tset)
{
my $y=shift(@tset);
last if !defined($y);
next if $y eq '.';
$y*=10**$factor;
$min=$max=$y if !defined($min);
$min=$y if $y < $min;
$max=$y if $y > $max;
}
}
if (exists($stats->{ANCHOR}))
{
foreach my $y (@{$stats->{ANCHOR}})
{
next if !defined($y);
next if $y eq '.';
my $y2=$y*10**$factor;
$min=$y2 if !defined($min) or $y2 < $min;
$max=$y2 if !defined($max) or $y2 > $max;
}
}
if ($floorflag eq 'C' and $floor >= $min and $floor <= $max)
{
my $diffmax=$max-$floor;
my $diffmin=$floor-$min;
$max=$floor+$diffmin if $diffmax < $diffmin;
$min=$floor-$diffmax if $diffmax > $diffmin;
}
$bars=0;
foreach my $bar (@{$stats->{BAR}})
{
next if !defined($bar);
$bar=1 if $horizontal; # Only bars can be horizontal
$bars++ if $bar;
}
$bars++ if $bars;
foreach my $xlab (@{$stats->{LABELS}})
{
next if !defined($xlab);
if ($xlab=~m/^([A-Z]{3,3})\-(\d+)/i)
{
$xlab=ucfirst(lc($1)).'~'.(($2<30)?$2+2000:($2>100)?$2:$2+1900);
}
elsif ($xlab=~m/^(\d+)Q(\d+)/)
{
$xlab=$qname[$1-1].'~'.(($2<30)?$2+2000:($2>100)?$2:$2+1900);
}
elsif ($xlab=~m/^(\d+)H(\d+)/)
{
$xlab=$hname[$1-1].'~'.(($2<30)?$2+2000:($2>100)?$2:$2+1900);
}
elsif ($xlab=~m/^(\d+)\/(\d+)/)
{
$xlab=$mname[$1-1].'~'.(($2<30)?$2+2000:($2>100)?$2:$2+1900);
}
}
my @lbnd=(-1,-1,-1,-1);
my @lbvl=('','','','');
my $lbrows=-1;
# X labels can be split over multiple rows (1-4)
foreach my $j (0..scalar(@{$stats->{LABELS}})-1)
{
my @vals=split('~',$stats->{LABELS}->[$j]);
foreach my $i (0..3)
{
if (!defined($vals[$i]))
{
$stats->{LABND}->[$j]->[$i]=-1;
next;
}
$lbrows=$i if $i > $lbrows;
if ($vals[$i] ne $lbvl[$i])
{
# Differs
$lbvl[$i]=$vals[$i];
$lbnd[$i]=$j;
$stats->{LABND}->[$j]->[$i]=$j;
}
else
{
$stats->{LABND}->[$lbnd[$i]]->[$i]=$j if $lbnd[$i] > -1;
}
}
$stats->{LABELS}->[$j]=\@vals;
}
$min=$max=0 if !defined($min);
$range=$max-$min;
$range=10*10**$factor,$min--,$max++ if $range/10**$factor < .01;
$min/=10**$factor;
$max/=10**$factor;
$stats->{YRANGE}=$range;
$stats->{XLABS}=$lbrows+1;
$steps=10;
$steps=$grph{STEPS}->[0] if exists($grph{STEPS});
my $ticksz=$range/($steps-1);
my $x=ceil(log10($ticksz)-1);
my $pow10x=10**$x;
$ticksz=ceil($ticksz/$pow10x)*$pow10x/10**$factor;
my $lo2=$ticksz*round($min/$ticksz);
my $hi2=$ticksz*round($max/$ticksz);
$lo2-=$ticksz if $min < $lo2;
$hi2+=$ticksz if $max >= $hi2;
$steps=sprintf("%0f",($hi2-$lo2)/$ticksz);
$stats->{YMIN}=$lo2;
$stats->{YMAX}=$hi2;
$stats->{YSTEP}=$ticksz;
$stats->{YSTEPS}=$steps;
# print STDERR "Min=$min, Max=$max, Lo=$lo2, Hi=$hi2, Sz=",$ticksz,", Ticks=$steps\n";
# for (my $j=$lo2; $j<=$hi2; $j+=$ticksz) {print STDERR "$j\n";}
# print STDERR "\n";
# # $range=10*10**$factor,$min--,$max++ if $range==0;
# $stats->{YRANGE}=$range;
# $stats->{XLABS}=$lbrows+1;
#
# $steps=10;
# my $maxstep=11;
# $maxstep=$grph{STEPS} if exists($grph{STEPS});
# $step=-1;
#
# while ($steps > 9)
# {
# $step++;
# $steps=int($range/(10**$step)+1);
# }
#
# $step=10**$step;
# $step/=10, $steps*=10 if $steps < 2;
# $step/=5, $steps*=5 if $steps < 5 and $steps < $maxstep;
# $step/=2, $steps*=2 if $steps < 7 and $steps < $maxstep;
# $step*=2, $steps=int($steps/2) if $steps > $maxstep;
#
# $stats->{YMIN}=int($min/$step)*$step/10**$factor;
# $stats->{YMAX}=(int($max/$step)+1)*$step/10**$factor;
# $stats->{YSTEP}=$step/10**$factor;
# $stats->{YMIN}-=$stats->{YSTEP}, $steps++ if $min < $stats->{YMIN};
# $stats->{YMAX}+=$stats->{YSTEP}, $steps++ if $max > $stats->{YMAX};
# $stats->{YSTEPS}=$steps;
$factor=0;
if ($grph{PDECIMALS}->[0] ne '')
{
$factor=$grph{PDECIMALS}->[0];
}
else
{
$factor=length($1) if ($stats->{YSTEP}=~m/\.(\d+)$/);
}
$stats->{YMAX}=sprintf("%.*f",$factor,$stats->{YMAX});
$stats->{XSTEPS}=scalar(@{$stats->{LABELS}});
$stats->{XSTEPS}=1 if $horizontal;
$stats->{BARS}=$bars;
my $ylab=length($stats->{YMAX})+1;
# $ylab+=2 if $grph{PDECIMALS} >= 0;
$xmarg=$ylab/2*1.2*$pointsz+($pointsz*.4);
$ymarg=0;
foreach my $j (0..$lbrows)
{
$ymarg+=$pointsz+$j+($pointsz*.1);
}
}
sub sgn
{
return 1 if $_[0]>=0;
return -1;
}
sub log10
{
my $n = shift;
return 0 if !$n;
return log($n)/log(10);
}
sub ceil
{
my $n=shift;
my $i=int($n);
return ($n==$i)?$n:$i+1;
}
sub round
{
my $n=shift;
return(sprintf("%.0f",$n));
}
sub PlotData
{
my $width=$grph{FRAME}->[0];
my $height=$grph{FRAME}->[1];
my $pointsz=$grph{PS}->[0];
my $gthickness=$grph{THICKNESS}->[0];
my $thickness=$grph{BORDER}->[0];
my $symsize=$grph{SYMSIZE}->[0];
my $background=$grph{BACKGROUND};
my $key=$grph{KEYBOX}->[0];
my $bars=$stats->{BARS};
my $floor=(exists($grph{FLOOR}))?$grph{FLOOR}->[0]:$stats->{YMIN};
my $horizontal=$grph{HORIZONTAL}->[0];
my $topmarg=$pointsz+2;
$topmarg+=$pointsz if $key;# and !$horizontal;
my ($xgrph,$ygrph,@sync);
my ($xof,$yof,$tm,$lm)=(0,0,0,0);
if ($grph{ORIGIN}->[0] ne '')
{
$xof=$lm=$grph{ORIGIN}->[0];
$yof=$tm=$grph{ORIGIN}->[1];
if ($#{$grph{ORIGIN}} == 3)
{
$xof=$width-$grph{ORIGIN}->[2];
$yof=$height-$grph{ORIGIN}->[3];
}
}
if ($horizontal)
{
my $t=$width;
$width=$height;
$height=$t;
# $t=$xmarg;
# $xmarg=$ymarg;
# $ymarg=$t;
$ymarg=0;
$xmarg=$pointsz;
$ygrph=($height-$xmarg*2-$xof);
$xgrph=($width-$pointsz*2.8-$yof);
$xmarg+=$lm;
$ymarg+=$tm;
}
else
{
$ygrph=($height-$ymarg-$topmarg-$yof);
$xgrph=($width-$xmarg-$xof);
}
return if $stats->{YSTEPS} == 0 or $stats->{XSTEPS} == 0 or ($bars==0 and $horizontal);
my $ydiv=sprintf("%.2f",$ygrph/$stats->{YSTEPS});
my $xdiv=sprintf("%.2f",$xgrph/$stats->{XSTEPS});
my $barwidth=($bars)?($xdiv*.8)/$bars:0;
my $lbrows=$stats->{XLABS}-1;
my $span=sprintf("%.2f",$stats->{YSTEP}*$stats->{YSTEPS});
# print STDERR "ydiv=$ydiv, xdiv=$xdiv, span=$span, YSTEP=$stats->{YSTEP}, YSTEPS=$stats->{YSTEPS}\n";
if ($span == 0)
{
Log(1,"WARN: span is zero");
return;
};
# Move to origin
my $thick=$symsize;
my $thick2=$thick*2;
my $y60=1*$thick;
my $x60=.866*$thick;
my $x60_2=$x60*2;
my $y60_2=$y60*2;
no warnings;
$buf.=<< "EOF";
.ds series2 \\M[$grph{SCOLOURS}->[1]]\\h'-${thick}p'\\D'C ${thick2}p'\\h'-${thick}p'\\M[]
.ds series3 \\Z'\\M[$grph{SCOLOURS}->[2]]\\h'${thick}p'\\D'P -${thick}p ${thick}p -${thick}p -${thick}p ${thick}p -${thick}p'\\M[]'
.ds series4 \\Z'\\M[$grph{SCOLOURS}->[3]]\\h'${thick}p'\\v'-${thick}p'\\D'P 0p ${thick2}p -${thick2}p 0p 0p -${thick2}p'\\M[]'
.ds series1 \\Z'\\M[$grph{SCOLOURS}->[0]]\\v'-${thick}p'\\D'P ${thick}p ${thick2}p -${thick2}p 0p'\\M[]'
.ds series6 \\M[$grph{SCOLOURS}->[5]]\\h'-${thick}p'\\D'C ${thick2}p'\\h'-${thick}p'\\M[]
.ds series5 \\Z'\\M[$grph{SCOLOURS}->[4]]\\h'${x60}p'\\v'-${y60}p'\\D'P -${x60_2}p 0p ${x60}p ${y60_2}p'\\M[]'
EOF
use warnings;
$buf.=".ne ${height}p\n.nf\n.mk GRP:mk\n";
$buf.=".in \\n[GRP:lefx]u\n\\Z'\\D't $grph{THICKNESS}->[0]p'\\m[$grph{TEXTCOLOUR}->[0]]\\M[$grph{LINECOLOUR}->[0]]'\\c\n";
Swap(\$width,\$height) if $horizontal;
if ($grph{BGCOLOUR}->[0] ne '')
{
$buf.="\\Z@\\M[$grph{BGCOLOUR}->[0]]\\D'P ${width}p 0 0 ${height}p -${width}p 0 0 -${height}p'\\M[]@\\c\n";
}
if ($grph{BORDER}->[0])
{
$buf.="\\Z@\\D't $grph{BORDER}->[0]p'@\\Z@\\m[$grph{BRDCOLOUR}->[0]]\\D'p ${width}p 0 0 ${height}p -${width}p 0 0 -${height}p'\\D't $grph{THICKNESS}->[0]p'\\m[]@\\c\n";
}
Swap(\$width,\$height) if $horizontal;
$buf.=".fl\n";
$buf.=".sp +".($grph{BORDER}->[0])."p\n";
$buf.=".in +".($grph{BORDER}->[0])."p\n";
$buf.=".ll +".($grph{FRAME}->[0]-$grph{BORDER}->[0]*2)."p\n";
# $buf.=".nf\n";
if ($horizontal)
{
# Move to origin (lower left corner)
$buf.=".mk grph\n\\Z'\\D't ${thickness}p''\\v'${xgrph}p+${topmarg}p'\\h'${xmarg}p'\\c\n";
# Background
$buf.="\\Z'\\M[$grph{WALLCOLOUR}->[0]]\\D'P 0p -${xgrph}p ${ygrph}p 0 0 ${xgrph}p'\\M[]'\\c\n" if $grph{WALLCOLOUR}->[0];
# Base Line
$buf.="\\Z'\\D'l ${ygrph}p 0''\\c\n";
# Floor Line
$buf.="\\Z'";
if ($stats->{YMIN} < $floor and $stats->{YMAX} >= $floor)
{
# zero is between min/max so draw axis on zero
$buf.="\\h'".abs($stats->{YMIN}-$floor)/$span*$ygrph."p'"
}
$buf.="\\D'l 0 -${xgrph}p''\\c\n";
# Ticks on X-axis
$buf.="\\Z'";
for my $j (0..$stats->{YSTEPS})
{
$buf.="\\h'${ydiv}p'" if $j;
$buf.="\\v'".($pointsz*.1+$thickness/2)."p'\\D'l 0 -".($pointsz*.1)."p'\\v'-".($thickness/2)."p'";
$buf.="\\Z!\\D'l 0 -".(${xgrph}-$thickness)."p'!" if $grph{VGRID};
}
$buf.="'\\c\n";
my $barno=0;
my $bardiv=d2($xgrph/($bars));
$barwidth=d2($pointsz*2);
$barwidth=$bardiv*.8 if $barwidth > $bardiv*.8;
foreach (my $i=scalar(@{$stats->{DATA}})-1; $i>=0; $i--) # For each series
{
my $set=$stats->{DATA}->[$i];
next if !defined($set);
next if !$stats->{BAR}->[$i];
my @tset=@{$set};
my ($oy,$ay,$cx,$ox);
my ($lbl,$txt)=split('~',$stats->{NAME}->[$i]);
$cx=$bardiv/2;
$buf.=".nr wi \\w'$lbl'\n";
my $baseline=($stats->{YMIN}<$floor)?((($stats->{YMIN}-$floor)/$span)*$ygrph):0;
# $oy=((($tset[$ox]-$stats->{YMIN})/$span)+$stats->{YMIN} )*$ygrph;
$oy=(($tset[0]-$stats->{YMIN})/$span)*$ygrph;
# $oy=((($tset[$ox]-$stats->{YMIN})/$span)-$stats->{YMIN})*$ygrph;
my $s=($i % 6) + 1;
my $cx2=sprintf("%.2f",($barno*$bardiv)+($bardiv/2)-($barwidth/2));
my $dep;
my $colo;
$sync[$i]=$topmarg+$xgrph-$cx-$cx2-$barwidth/2-$pointsz*.4;
$barno++;
my $j=0; # Horizontal bars have multiple series with one value in each
next if !defined($tset[$j]);
next if $tset[$j] eq '.';
my $y=(($tset[$j]-$stats->{YMIN})/$span)*$ygrph;
$dep=d2($oy+$baseline);
$dep=sgn($dep)*.5 if abs($dep) < 1;
if ($grph{NEGCOLOUR}->[0])
{
$colo=($dep < 0)?$grph{NEGCOLOUR}->[$i]:$grph{SCOLOURS}->[$i];
}
else
{
$colo=$grph{SCOLOURS}->[$i];
}
# my $y=((($tset[$j]-$stats->{YMIN})/$span)+$stats->{YMIN} )*$ygrph;
# my $y=((($tset[$j]-$stats->{YMIN})/$span)-$stats->{YMIN})*$ygrph;
my ($contrast,$contrastnd);
$contrast=$grph{CONTRAST}->[$i];
if (defined($contrast))
{
$contrast="\\m[$contrast]";
$contrastnd="\\m[]";
}
else
{
$contrast=$contrastnd='';
}
if ($dep < 0)
{
if ($pointsz < $barwidth)
{
$buf.=".ie \\n[wi]u+2p<".abs(${dep})."p .ds lb $contrast\\h'1p'$lbl$contrastnd\n";
$buf.=".el .ds lb \\h'-\\n[wi]u-2p'$lbl\n";
}
else
{
$buf.=".ds lb \\h'-\\n[wi]u-1p'$lbl\n";
}
}
else
{
if ($pointsz < $barwidth)
{
$buf.=".ie \\n[wi]u+2p>".abs(${dep})."p .ds lb \\h'1p'$lbl\n";
$buf.=".el .ds lb $contrast\\h'-\\n[wi]u-2p'$lbl$contrastnd\n";
}
else
{
$buf.=".ds lb \\h'1p'$lbl\n";
}
}
$buf.="\\Z'";
$buf.="\\h'${oy}p'\\v'-${cx}p'";
$buf.="\\m[$colo]" if $grph{COLOURED}->[0];
$buf.="\\Z~\\D't 0p'\\M[$colo]\\v'-${cx2}p'\\D'P 0 -${barwidth}p -${dep}p 0 0 ${barwidth}p ${dep}p 0'\\M[]\\D't ${thickness}p'~";
$buf.="\\Z~\\v'-".($cx2+$barwidth/2-($pointsz*.4))."p'\\h'".(sgn($dep ))."p'";
$buf.="\\*[lb]";
$buf.="~";
# $buf.="\\Z~\\D't 0p'\\M[$colo]\\v'-${cx2}p'\\D'P ${barwidth}p 0p 0p ${dep}p -${barwidth}p 0p 0p -${dep}p'\\M[]\\D't ${thickness}p'~";
# $buf.="\\v'-${cx}p'\\h'".sprintf("%.3f",$y-$oy)."p'";
# $buf.="\\D'l ${cx}p ".sprintf("%.3f",$oy-$y)."p'";
$buf.="\\m[]" if $grph{COLOURED}->[0];
$oy=$y;
$dep=$oy+$baseline;
# if (exists($grph{POSCOLOUR}))
# {
# $colo=($dep < 0)?$grph{NEGCOLOUR}->{NAME}:$grph{POSCOLOUR}->{NAME}
# }
# else
# {
# $colo=$grph{COLOURS}->[$i]->{NAME};
# }
# $buf.="\\Z~\\D't 0p'\\M[$colo]\\v'-${cx2}p'\\D'P 0 -${barwidth}p -${dep}p 0 0 ${barwidth}p ${dep}p 0'\\M[]\\D't ${thickness}p'~";
$buf.="'\\c\n";
}
# Now bottom labels
my $y=$stats->{YMIN};
my $factor=0;
my $pattern="%.*f";
if ($grph{PDECIMALS}->[0] ne '')
{
# $pattern.='%%';
$factor=$grph{PDECIMALS}->[0];
}
else
{
$factor=length($1) if ($stats->{YSTEP}=~m/\.(\d+)$/);
$factor=1 if ($stats->{YMAX}-$stats->{YMIN}) < $stats->{YSTEPS};
}
$buf.="\\v'".($pointsz*1.2)."p'\\c\n";
foreach my $j (0..$stats->{YSTEPS})
{
my $dy=sprintf($pattern,$factor,$y);
$buf.=".nr wi \\w'$dy'\n";
$buf.="\\h'-\\n[wi]u/2u'$dy\\h'${ydiv}p-(\\n[wi]u/2u)'\\c\n";
$y+=$stats->{YSTEP};
}
if ($grph{KEYBOX}->[0])
{
my $marg=$symsize*4;
my $ps=$grph{PS}->[0];
my $boxlabels=join("\t",@{$grph{BOXLABELS}});
my $boxheads=join("\t",@{$grph{BOXHEADS}});
my $boxtabs=join(' ',@{$grph{BOXTABS}});
$buf.=".sp |\\n[GRP:mk]u+$grph{BOXFRAME}->[1]p\n.in +$grph{BOXFRAME}->[0]p\n.ta $boxtabs\n.vs\n.in +(4p)\n\\fB$boxheads\\fP\n.sp .2\n.in -(4p)\n";
my $y2=0;
# $buf.=".sp ${pointsz}p\n" if $grph{SYNC};
foreach my $i (0..scalar(@{$stats->{NAME}})-1)
{
next if !defined($stats->{NAME}->[$i]);
my ($lbl,$txt)=split('~',$stats->{NAME}->[$i]);
$txt=~tr[^][\t];
if ($grph{SYNC}->[0])
{
$buf.=".sp |\\n[GRP:mk]u+$sync[$i]p-2p\n";
}
# else
# {
$buf.="\\v'-".($pointsz*.4)."p'\\h'-${thick}p'\\Z!\\M[$grph{SCOLOURS}->[$i]]\\v'-${thick}p'\\D'P ${thick2}p 0 0 ${thick2}p -${thick2}p 0'!\\h'${thick2}p'\\v'".($pointsz*.4)."p'\\~\\c\n" if !$grph{POSCOLOUR}->[0];
$buf.="$txt\n";
$buf.="\\M[]\\c\n" if !$grph{POSCOLOUR}->[0];
# }
# print STDERR "$sync[$i] "
# $buf.="\\v'-".($pointsz*.4)."p'\\D'l ".(${symsize}*4)."p 0p'\\Z'\\h'-".(${symsize}*2)."p'\\*[series$s]'\\v'".($pointsz*.4)."p'\\~\\c\n";
# $buf.=".in +${marg}p\n.sp -1\n$txt\\h'".(${symsize}*2)."p'\n.sp $fldk->{SKIPAFTER}p\n.in -${marg}p\n";
}
}
# print STDERR "\n";
}
else
{
# Move to origin (lower left corner)
$buf.=".mk grph\n\\Z'\\D't ${thickness}p''\\v'${ygrph}p+${topmarg}p+${tm}p'\\h'${xmarg}p+${lm}p'\\c\n";
# Background
$buf.="\\Z'\\M[$grph{WALLCOLOUR}->[0]]\\D'P 0p -${ygrph}p ${xgrph}p 0 0 ${ygrph}p'\\M[]'\\c\n" if $grph{WALLCOLOUR}->[0];
# Left line
$buf.="\\Z'\\L'-${ygrph}p''\\c\n";
# Bottom line
$buf.="\\Z'";
if ($stats->{YMIN} < $floor and $stats->{YMAX} >= $floor)
{
# zero is between min/max so draw axis on zero
$buf.="\\v'-".abs($stats->{YMIN}-$floor)/$span*$ygrph."p'"
}
$buf.="\\l'${xgrph}p''\\c\n";
# Label Y axis
# ticks
$buf.="\\Z'";
for my $j (0..$stats->{YSTEPS})
{
$buf.="\\v'-${ydiv}p'" if $j;
$buf.="\\h'-".($pointsz*.1+$thickness/2)."p'\\l'".($pointsz*.1)."p'\\h'".($thickness/2)."p'";
$buf.="\\Z!\\D'l ".(${xgrph}-$thickness)."p 0'!" if $grph{HGRID}->[0];
}
$buf.="'\\c\n";
# Label X axis
# ticks
foreach my $j (0..$lbrows)
{
my $sofar=0;
my $fi=0;
my $targ=0;
my $nd;
my $i;
for ($i=0; $i<scalar(@{$stats->{LABELS}}); $i=$nd+1)
{
$nd=$stats->{LABND}->[$i]->[$j];
$nd=$i if $nd < 0;
$sofar+=($nd-$i)*$xdiv;
my $mi=($i!=$nd)?$nd:int(($i-$fi)/2)+$fi;
my $lblsz=length($stats->{LABELS}->[$mi]->[$j] || '')*$pointsz*.6;
if ($lblsz==0 or ($lblsz) > $xdiv+$sofar)
{
$fi=$nd+1 if $lblsz==0;
$sofar+=$xdiv;
$stats->{LABELS}->[$nd]->[$j]='.' if $nd > $i;
next;
}
else
{
# print STDERR "$stats->{LABELS}->[$mi]->[$j]: sofar $sofar: lblsz $lblsz: xdiv $xdiv\n";
$sofar=0;
foreach my $t ($fi..$nd)
{
$stats->{LABELS}->[$t]->[$j]='' if $stats->{LABELS}->[$t]->[$j] ne '.' and $t != $mi;
}
$fi=$nd+1;
}
}
foreach my $i ($fi..$#{$stats->{LABELS}})
{
$stats->{LABELS}->[$i]->[$j]='';
}
}
$buf.="\\Z'";
for my $j (0..$stats->{XSTEPS}-1)
{
$buf.="\\h'${xdiv}p'" if $j;
$buf.="\\h'".(${xdiv}/2)."p'" if $j==0;
next if $stats->{LABELS}->[$j]->[0] eq '';
$buf.="\\D'l 0 ".($pointsz*.3)."p'\\v'-".($pointsz*.3)."p'";
$buf.="\\Z!\\D'l 0 -".(${ygrph}-$thickness)."p'!" if $grph{VGRID}->[0];
}
$buf.="'\\c\n";
# $buf.=series
# First any bars?
my $barno=0;
foreach my $i (0..scalar(@{$stats->{DATA}})-1)
{
my $set=$stats->{DATA}->[$i];
next if !defined($set);
next if !$stats->{BAR}->[$i];
my @tset=@{$set};
my ($oy,$ay,$cx,$ox);
$cx=$xdiv/2+$barwidth/2;
for ($ox=0; $ox<=$#tset; $ox++)
{
last if $tset[$ox] ne '.';
$cx+=$xdiv;
}
if (!defined($tset[$ox]) or $tset[$ox] eq '.')
{
$stats->{NAME}->[$i]=undef;
next;
}
$buf.="\\Z'";
my $baseline=($stats->{YMIN}<$floor)?((($stats->{YMIN}-$floor)/$span)*$ygrph):0;
# $oy=((($tset[$ox]-$stats->{YMIN})/$span)+$stats->{YMIN} )*$ygrph;
$oy=(($tset[$ox]-$stats->{YMIN})/$span)*$ygrph;
# $oy=((($tset[$ox]-$stats->{YMIN})/$span)-$stats->{YMIN})*$ygrph;
my $s=($i % 6) + 1;
$buf.="\\v'-${oy}p'\\h'${cx}p'";
$cx=0;
my $cx2=sprintf("%.3f",($barno*$barwidth)-($bars*$barwidth/2));
my $dep;
my $colo;
foreach my $j ($ox+1..$stats->{XSTEPS})
{
$cx+=$xdiv;
next if !defined($tset[$j]);
next if $tset[$j] eq '.';
my $y=(($tset[$j]-$stats->{YMIN})/$span)*$ygrph;
$dep=$oy+$baseline;
$dep=sgn($dep)*.5 if abs($dep) < 1;
if ($grph{POSCOLOUR}->[0])
{
$colo=($dep < 0)?$grph{NEGCOLOUR}->[0]:$grph{POSCOLOUR}->[0];
}
else
{
$colo=$grph{SCOLOURS}->[$i];
}
# my $y=((($tset[$j]-$stats->{YMIN})/$span)+$stats->{YMIN} )*$ygrph;
# my $y=((($tset[$j]-$stats->{YMIN})/$span)-$stats->{YMIN})*$ygrph;
$buf.="\\m[$colo]" if $grph{COLOURED}->[0];
$buf.="\\Z~\\D't 0p'\\M[$colo]\\h'${cx2}p'\\D'P ${barwidth}p 0p 0p ${dep}p -${barwidth}p 0p 0p -${dep}p'\\M[]\\D't ${thickness}p'~";
$buf.="\\h'${cx}p'\\v'".sprintf("%.3f",$oy-$y)."p'";
# $buf.="\\D'l ${cx}p ".sprintf("%.3f",$oy-$y)."p'";
$buf.="\\m[]" if $grph{COLOURED}->[0];
$oy=$y;
$cx=0;
}
$dep=$oy+$baseline;
if ($grph{POSCOLOUR}->[0])
{
$colo=($dep < 0)?$grph{NEGCOLOUR}->[0]:$grph{POSCOLOUR}->[0];
}
else
{
$colo=$grph{SCOLOURS}->[$i];
}
$buf.="\\Z~\\D't 0p'\\M[$colo]\\h'${cx2}p'\\D'P ${barwidth}p 0p 0p ${dep}p -${barwidth}p 0p 0p -${dep}p'\\M[]\\D't ${thickness}p'~";
$buf.="'\\c\n";
$barno++;
}
# Now the graph lines
foreach my $i (0..scalar(@{$stats->{DATA}})-1)
{
my $set=$stats->{DATA}->[$i];
next if !defined($set);
next if $stats->{BAR}->[$i];
my @tset=@{$set};
my ($oy,$ay,$cx,$ox);
$cx=$xdiv/2;
for ($ox=0; $ox<=$#tset; $ox++)
{
last if $tset[$ox] ne '.';
$cx+=$xdiv;
}
if (!defined($tset[$ox]) or $tset[$ox] eq '.')
{
$stats->{NAME}->[$i]=undef;
next;
}
$buf.="\\Z'";
$buf.="\\m[$grph{SCOLOURS}->[$i]DK]" if $grph{COLOURED}->[0];
$buf.="\\Z!\\D't ${gthickness}p'!";
$oy=(($tset[$ox]-$stats->{YMIN})/$span)*$ygrph;
my $s=($i % 6) + 1;
if (exists($stats->{ANCHOR}) and $stats->{ANCHOR}->[$i] ne '.')
{
$ay=(($stats->{ANCHOR}->[$i]-$stats->{YMIN})/$span)*$ygrph;
$buf.="\\v'-${ay}p'";
if ($background and $i == 0)
{
$buf.="\\Z'\\D't 0p'\\M[$grph{SCOLOURS}->[$i]DK]\\D'P ${cx}p ".sprintf("%.3f",$ay-$oy)."p 0p ${oy}p -${cx}p 0p 0p -${ay}p'\\M[]\\D't ${gthickness}p''";
}
$buf.="\\D'l ${cx}p ".sprintf("%.3f",$ay-$oy)."p'";
$cx=0;
}
else
{
$buf.="\\v'-${oy}p'\\h'${cx}p'";
$cx=0;
}
foreach my $j ($ox+1..$stats->{XSTEPS}-1)
{
$cx+=$xdiv;
next if !defined($tset[$j]);
next if $tset[$j] eq '.';
my $y=(($tset[$j]-$stats->{YMIN})/$span)*$ygrph;
if ($background and $i == 0)
{
$buf.="\\Z'\\D't 0p'\\M[$grph{SCOLOURS}->[$i]DK]\\D'P ${cx}p ".sprintf("%.3f",$oy-$y)."p 0p ${y}p -${cx}p 0p 0p -${oy}p'\\M[]\\D't ${gthickness}p''";
}
$buf.="\\D'l ${cx}p ".sprintf("%.3f",$oy-$y)."p'";
$oy=$y;
$cx=0;
}
$buf.="\\m[]" if $grph{COLOURED}->[0];
$buf.="'\\c\n";
# Draw points
if ($symsize)
{
$cx=$xdiv/2;
for ($ox=0; $ox<=$#tset; $ox++)
{
last if $tset[$ox] ne '.';
$cx+=$xdiv;
}
if (!defined($tset[$ox]) or $tset[$ox] eq '.')
{
$stats->{NAME}->[$i]=undef;
next;
}
$buf.="\\Z'";
$buf.="\\m[$grph{SCOLOURS}->[$i]]" if $grph{COLOURED}->[0];
$oy=(($tset[$ox]-$stats->{YMIN})/$span)*$ygrph;
if (exists($stats->{ANCHOR}) and $stats->{ANCHOR}->[$i] ne '.')
{
$ay=(($stats->{ANCHOR}->[$i]-$stats->{YMIN})/$span)*$ygrph;
$buf.="\\v'-${ay}p'";
$buf.="\\h'${cx}p'\\v'".sprintf("%.3f",$ay-$oy)."p'";
$cx=0;
}
else
{
$buf.="\\v'-${oy}p'\\h'${cx}p'";
$cx=0;
}
my $sym='';
$sym="\\*[series$s]" if !$background or $i != 0;
$buf.=$sym;
foreach my $j ($ox+1..$stats->{XSTEPS}-1)
{
$cx+=$xdiv;
next if !defined($tset[$j]);
next if $tset[$j] eq '.';
my $y=(($tset[$j]-$stats->{YMIN})/$span)*$ygrph;
$buf.="\\h'${cx}p'\\v'".sprintf("%.3f",$oy-$y)."p'$sym";
$oy=$y;
$cx=0;
}
$buf.="\\m[]" if $grph{COLOURED};
$buf.="'\\c\n";
}
}
# $buf.=X Labels
$buf.=".nf\n.sp |\\n[grph]u+${ygrph}p+${topmarg}p+${tm}p\n.vs $grph{VS}->[0]p\n";
foreach my $j (0..$lbrows)
{
$buf.="\\m[$grph{TEXTCOLOUR}->[0]]\\c\n";
$buf.=".ta ";
my $tab=$xmarg;
my $tabln='';
my $divs=1;
my $nd=0;
for (my $i=0; $i<scalar(@{$stats->{LABELS}}); $tab+=$divs*$xdiv, $i=$nd+1)
{
# next if $xskip != 1 and ($i+1) % $xskip != 1;
$nd=$stats->{LABND}->[$i]->[$j];
$nd=$i if $nd < 0;
$divs=$nd-$i+1;
$i=$nd;
my $vals=$stats->{LABELS}->[$i];
next if !defined($vals->[$j]) or $vals->[$j] eq '' or $vals->[$j] eq '.';
$buf.="".($tab+($divs*$xdiv)/2)."pC ";
$tabln.="\t$vals->[$j]";
}
$buf.="\n\\s'+${j}'$tabln\\s'-${j}'\n";
}
$buf.=".vs\n.fi\n.ta ".($xmarg+$lm-$pointsz*.2-$thickness/2)."pR\n";
my $y=$stats->{YMIN};
my $factor=0;
my $pattern="%.*f";
if ($grph{PDECIMALS}->[0] ne '')
{
# $pattern.='%%';
$factor=$grph{PDECIMALS}->[0];
}
else
{
$factor=length($1) if ($stats->{YSTEP}=~m/\.(\d+)$/);
}
foreach my $j (0..$stats->{YSTEPS})
{
$buf.=".sp |\\n[grph]u+".(${ygrph}-$ydiv*$j+$pointsz/4+$topmarg+${tm})."p\n\t".sprintf($pattern,$factor,$y)."\n";
$y+=$stats->{YSTEP};
}
$buf.="\\m[]\\D't ${thickness}p'\n";
if (!$grph{KEYBOX}->[0])
{
$buf.=".sp |\\n[grph]u+${pointsz}p+${tm}p\n.in +${xmarg}p+${lm}p+6p\n";
foreach my $i (0..scalar(@{$stats->{NAME}})-1)
{
next if !defined($stats->{NAME}->[$i]);
my $s=($i % 6)+1;
if ($stats->{BAR}->[$i])
{
$buf.="\\v'-".($pointsz*.4)."p'\\h'-${thick}p'\\Z!\\M[$grph{SCOLOURS}->[$i]]\\v'-${thick}p'\\D'P ${thick2}p 0 0 ${thick2}p -${thick2}p 0'!\\h'${thick2}p'\\v'".($pointsz*.4)."p'\\~$stats->{NAME}->[$i]\\0\\M[]\n";
}
else
{
my $symsize=2;
$buf.="\\Z'\\D't 2p'\\m[$grph{SCOLOURS}->[$i]DK]'";
$buf.="\\v'-".($pointsz*.4)."p'\\D'l ".(${symsize}*4)."p 0p'\\Z'\\h'-".(${symsize}*2)."p'\\m[]\\*[series$s]'\\v'".($pointsz*.4)."p'\\~$stats->{NAME}->[$i]\\h'".(${symsize}*2)."p'\n";
}
}
}
else
{
my $marg=$symsize*4;
my $boxlabels=join("\t",@{$grph{BOXLABELS}});
my $boxheads=join("\t",@{$grph{BOXHEADS}});
my $boxtabs=join(' ',@{$grph{BOXTABS}});
$buf.=".fl\n.vs 0\n.sp |\\n[GRP:mk]u+$grph{BOXFRAME}->[1]p\n.in +$grph{BOXFRAME}->[0]p\n.ta $boxtabs\n.vs $grph{VS}->[0]p\n.in +(1m+4p)\n\\fB$boxheads\\fP\n.sp -.2\n.in -(1m+4p)\n";
# $buf.=".in +".($fldk->{THICKNESS}->{LEFT}*.5)."p\n.sp -1v\n.sp $fldk->{INDENT}->{TOP}p\n.ll +$fldk->{POSITION}->{WIDTH}p\n";
foreach my $i (0..scalar(@{$stats->{NAME}})-1)
{
next if !defined($stats->{NAME}->[$i]);
my $s=($i % 6)+1;
$buf.="\\v'-".($pointsz*.4)."p'\\D'l ".(${symsize}*4)."p 0p'\\Z'\\h'-".(${symsize}*2)."p'\\*[series$s]'\\v'".($pointsz*.4)."p'\\~\\c\n";
$buf.=".in +${marg}p\n.sp -1\n$stats->{NAME}->[$i]\\h'".(${symsize}*2)."p'\n.in -${marg}p\n";
}
}
}
$buf.=".fl\n.ev\n";
### $srcur=undef;
# outbuf($buf);
}
sub d2
{
return sprintf("%.2f",$_[0]);
}
sub Swap
{
my $v1=shift;
my $v2=shift;
my $t=$$v1;
$$v1=$$v2;
$$v2=$t;
}