| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #! /usr/bin/perl -w | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | package PostScript::Simple; | 
| 4 |  |  |  |  |  |  |  | 
| 5 | 7 |  |  | 7 |  | 78923 | use strict; | 
|  | 7 |  |  |  |  | 9 |  | 
|  | 7 |  |  |  |  | 206 |  | 
| 6 | 7 |  |  | 7 |  | 21 | use vars qw($VERSION @ISA @EXPORT); | 
|  | 7 |  |  |  |  | 7 |  | 
|  | 7 |  |  |  |  | 399 |  | 
| 7 | 7 |  |  | 7 |  | 25 | use Carp; | 
|  | 7 |  |  |  |  | 14 |  | 
|  | 7 |  |  |  |  | 429 |  | 
| 8 | 7 |  |  | 7 |  | 23 | use Exporter; | 
|  | 7 |  |  |  |  | 15 |  | 
|  | 7 |  |  |  |  | 188 |  | 
| 9 | 7 |  |  | 7 |  | 1982 | use PostScript::Simple::EPS; | 
|  | 7 |  |  |  |  | 11 |  | 
|  | 7 |  |  |  |  | 33423 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | @ISA = qw(Exporter); | 
| 12 |  |  |  |  |  |  | @EXPORT = qw(); | 
| 13 |  |  |  |  |  |  | $VERSION = '0.09'; | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | =head1 NAME | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | PostScript::Simple - Produce PostScript files from Perl | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | use PostScript::Simple; | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | # create a new PostScript object | 
| 27 |  |  |  |  |  |  | $p = new PostScript::Simple(papersize => "A4", | 
| 28 |  |  |  |  |  |  | colour => 1, | 
| 29 |  |  |  |  |  |  | eps => 0, | 
| 30 |  |  |  |  |  |  | units => "in"); | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | # create a new page | 
| 33 |  |  |  |  |  |  | $p->newpage; | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | # draw some lines and other shapes | 
| 36 |  |  |  |  |  |  | $p->line(1,1, 1,4); | 
| 37 |  |  |  |  |  |  | $p->linextend(2,4); | 
| 38 |  |  |  |  |  |  | $p->box(1.5,1, 2,3.5); | 
| 39 |  |  |  |  |  |  | $p->circle(2,2, 1); | 
| 40 |  |  |  |  |  |  | $p->setlinewidth( 0.01 ); | 
| 41 |  |  |  |  |  |  | $p->curve(1,5, 1,7, 3,7, 3,5); | 
| 42 |  |  |  |  |  |  | $p->curvextend(3,3, 5,3, 5,5); | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | # draw a rotated polygon in a different colour | 
| 45 |  |  |  |  |  |  | $p->setcolour(0,100,200); | 
| 46 |  |  |  |  |  |  | $p->polygon({rotate=>45}, 1,1, 1,2, 2,2, 2,1, 1,1); | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | # add some text in red | 
| 49 |  |  |  |  |  |  | $p->setcolour("red"); | 
| 50 |  |  |  |  |  |  | $p->setfont("Times-Roman", 20); | 
| 51 |  |  |  |  |  |  | $p->text(1,1, "Hello"); | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | # write the output to a file | 
| 54 |  |  |  |  |  |  | $p->output("file.ps"); | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | PostScript::Simple allows you to have a simple method of writing PostScript | 
| 60 |  |  |  |  |  |  | files from Perl. It has graphics primitives that allow lines, curves, circles, | 
| 61 |  |  |  |  |  |  | polygons and boxes to be drawn. Text can be added to the page using standard | 
| 62 |  |  |  |  |  |  | PostScript fonts. | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | The images can be single page EPS files, or multipage PostScript files. The | 
| 65 |  |  |  |  |  |  | image size can be set by using a recognised paper size ("C", for example) or | 
| 66 |  |  |  |  |  |  | by giving dimensions. The units used can be specified ("C" or "C", etc) | 
| 67 |  |  |  |  |  |  | and are the same as those used in TeX. The default unit is a bp, or a PostScript | 
| 68 |  |  |  |  |  |  | point, unlike TeX. | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | =head1 PREREQUISITES | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | This module requires C and C. | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | =head2 EXPORT | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | None. | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | =cut | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  |  | 
| 81 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  | # Define some colour names | 
| 84 |  |  |  |  |  |  | my %pscolours = ( | 
| 85 |  |  |  |  |  |  | # Original colours from PostScript::Simple | 
| 86 |  |  |  |  |  |  | brightred         => [255, 0,   0],   brightgreen          => [0,   255, 0],   brightblue      => [0,   0,   1], | 
| 87 |  |  |  |  |  |  | red               => [204, 0,   0],   green                => [0,   204, 0],   blue            => [0,   0,   204], | 
| 88 |  |  |  |  |  |  | darkred           => [127, 0,   0],   darkgreen            => [0,   127, 0],   darkblue        => [0,   0,   127], | 
| 89 |  |  |  |  |  |  | grey10            => [25,  25,  25],  grey20               => [51,  51,  51],  grey30          => [76,  76,  76], | 
| 90 |  |  |  |  |  |  | grey40            => [102, 102, 102], grey50               => [127, 127, 127], grey60          => [153, 153, 153], | 
| 91 |  |  |  |  |  |  | grey70            => [178, 178, 178], grey80               => [204, 204, 204], grey90          => [229, 229, 229], | 
| 92 |  |  |  |  |  |  | black             => [0,   0,   0],   white                => [255, 255, 255], | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  | # X-Windows colours, unless they clash with the above (only /(dark)?(red|green|blue)/ ) | 
| 95 |  |  |  |  |  |  | aliceblue         => [240, 248, 255], antiquewhite         => [250, 235, 215], aqua            => [0,   255, 255], | 
| 96 |  |  |  |  |  |  | aquamarine        => [127, 255, 212], azure                => [240, 255, 255], beige           => [245, 245, 220], | 
| 97 |  |  |  |  |  |  | bisque            => [255, 228, 196], blanchedalmond       => [255, 255, 205], blueviolet      => [138, 43,  226], | 
| 98 |  |  |  |  |  |  | brown             => [165, 42,  42],  burlywood            => [222, 184, 135], cadetblue       => [95,  158, 160], | 
| 99 |  |  |  |  |  |  | chartreuse        => [127, 255, 0],   chocolate            => [210, 105, 30],  coral           => [255, 127, 80], | 
| 100 |  |  |  |  |  |  | cornflowerblue    => [100, 149, 237], cornsilk             => [255, 248, 220], crimson         => [220, 20,  60], | 
| 101 |  |  |  |  |  |  | cyan              => [0,   255, 255], darkcyan             => [0,   139, 139], darkgoldenrod   => [184, 134, 11], | 
| 102 |  |  |  |  |  |  | darkgray          => [169, 169, 169], darkgrey             => [169, 169, 169], darkkhaki       => [189, 183, 107], | 
| 103 |  |  |  |  |  |  | darkmagenta       => [139, 0,   139], darkolivegreen       => [85,  107, 47],  darkorange      => [255, 140, 0], | 
| 104 |  |  |  |  |  |  | darkorchid        => [153, 50,  204], darksalmon           => [233, 150, 122], darkseagreen    => [143, 188, 143], | 
| 105 |  |  |  |  |  |  | darkslateblue     => [72,  61,  139], darkslategray        => [47,  79,  79],  darkslategrey   => [47,  79,  79], | 
| 106 |  |  |  |  |  |  | darkturquoise     => [0,   206, 209], darkviolet           => [148, 0,   211], deeppink        => [255, 20,  147], | 
| 107 |  |  |  |  |  |  | deepskyblue       => [0,   191, 255], dimgray              => [105, 105, 105], dimgrey         => [105, 105, 105], | 
| 108 |  |  |  |  |  |  | dodgerblue        => [30,  144, 255], firebrick            => [178, 34,  34],  floralwhite     => [255, 250, 240], | 
| 109 |  |  |  |  |  |  | forestgreen       => [34,  139, 34],  fuchsia              => [255, 0,   255], gainsboro       => [220, 220, 220], | 
| 110 |  |  |  |  |  |  | ghostwhite        => [248, 248, 255], gold                 => [255, 215, 0],   goldenrod       => [218, 165, 32], | 
| 111 |  |  |  |  |  |  | gray              => [128, 128, 128], grey                 => [128, 128, 128], greenyellow     => [173, 255, 47], | 
| 112 |  |  |  |  |  |  | honeydew          => [240, 255, 240], hotpink              => [255, 105, 180], indianred       => [205, 92,  92], | 
| 113 |  |  |  |  |  |  | indigo            => [75,  0,   130], ivory                => [255, 240, 240], khaki           => [240, 230, 140], | 
| 114 |  |  |  |  |  |  | lavender          => [230, 230, 250], lavenderblush        => [255, 240, 245], lawngreen       => [124, 252, 0], | 
| 115 |  |  |  |  |  |  | lemonchiffon      => [255, 250, 205], lightblue            => [173, 216, 230], lightcoral      => [240, 128, 128], | 
| 116 |  |  |  |  |  |  | lightcyan         => [224, 255, 255], lightgoldenrodyellow => [250, 250, 210], lightgray       => [211, 211, 211], | 
| 117 |  |  |  |  |  |  | lightgreen        => [144, 238, 144], lightgrey            => [211, 211, 211], lightpink       => [255, 182, 193], | 
| 118 |  |  |  |  |  |  | lightsalmon       => [255, 160, 122], lightseagreen        => [32,  178, 170], lightskyblue    => [135, 206, 250], | 
| 119 |  |  |  |  |  |  | lightslategray    => [119, 136, 153], lightslategrey       => [119, 136, 153], lightsteelblue  => [176, 196, 222], | 
| 120 |  |  |  |  |  |  | lightyellow       => [255, 255, 224], lime                 => [0,   255, 0],   limegreen       => [50,  205, 50], | 
| 121 |  |  |  |  |  |  | linen             => [250, 240, 230], magenta              => [255, 0,   255], maroon          => [128, 0,   0], | 
| 122 |  |  |  |  |  |  | mediumaquamarine  => [102, 205, 170], mediumblue           => [0,   0,   205], mediumorchid    => [186, 85,  211], | 
| 123 |  |  |  |  |  |  | mediumpurple      => [147, 112, 219], mediumseagreen       => [60,  179, 113], mediumslateblue => [123, 104, 238], | 
| 124 |  |  |  |  |  |  | mediumspringgreen => [0,   250, 154], mediumturquoise      => [72,  209, 204], mediumvioletred => [199, 21,  133], | 
| 125 |  |  |  |  |  |  | midnightblue      => [25,  25,  112], mintcream            => [245, 255, 250], mistyrose       => [255, 228, 225], | 
| 126 |  |  |  |  |  |  | moccasin          => [255, 228, 181], navajowhite          => [255, 222, 173], navy            => [0,   0,   128], | 
| 127 |  |  |  |  |  |  | oldlace           => [253, 245, 230], olive                => [128, 128, 0],   olivedrab       => [107, 142, 35], | 
| 128 |  |  |  |  |  |  | orange            => [255, 165, 0],   orangered            => [255, 69,  0],   orchid          => [218, 112, 214], | 
| 129 |  |  |  |  |  |  | palegoldenrod     => [238, 232, 170], palegreen            => [152, 251, 152], paleturquoise   => [175, 238, 238], | 
| 130 |  |  |  |  |  |  | palevioletred     => [219, 112, 147], papayawhip           => [255, 239, 213], peachpuff       => [255, 218, 185], | 
| 131 |  |  |  |  |  |  | peru              => [205, 133, 63],  pink                 => [255, 192, 203], plum            => [221, 160, 221], | 
| 132 |  |  |  |  |  |  | powderblue        => [176, 224, 230], purple               => [128, 0,   128], rosybrown       => [188, 143, 143], | 
| 133 |  |  |  |  |  |  | royalblue         => [65,  105, 225], saddlebrown          => [139, 69,  19],  salmon          => [250, 128, 114], | 
| 134 |  |  |  |  |  |  | sandybrown        => [244, 164, 96],  seagreen             => [46,  139, 87],  seashell        => [255, 245, 238], | 
| 135 |  |  |  |  |  |  | sienna            => [160, 82,  45],  silver               => [192, 192, 192], skyblue         => [135, 206, 235], | 
| 136 |  |  |  |  |  |  | slateblue         => [106, 90,  205], slategray            => [112, 128, 144], slategrey       => [112, 128, 144], | 
| 137 |  |  |  |  |  |  | snow              => [255, 250, 250], springgreen          => [0,   255, 127], steelblue       => [70,  130, 180], | 
| 138 |  |  |  |  |  |  | tan               => [210, 180, 140], teal                 => [0,   128, 128], thistle         => [216, 191, 216], | 
| 139 |  |  |  |  |  |  | tomato            => [253, 99,  71],  turquoise            => [64,  224, 208], violet          => [238, 130, 238], | 
| 140 |  |  |  |  |  |  | wheat             => [245, 222, 179], whitesmoke           => [245, 245, 245], yellow          => [255, 255, 0], | 
| 141 |  |  |  |  |  |  | yellowgreen       => [154, 205, 50], | 
| 142 |  |  |  |  |  |  | ); | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  |  | 
| 145 |  |  |  |  |  |  | # define page sizes here (a4, letter, etc) | 
| 146 |  |  |  |  |  |  | # should be Properly Cased | 
| 147 |  |  |  |  |  |  | my %pspaper = ( | 
| 148 |  |  |  |  |  |  | A0                    => [2384, 3370], | 
| 149 |  |  |  |  |  |  | A1                    => [1684, 2384], | 
| 150 |  |  |  |  |  |  | A2                    => [1191, 1684], | 
| 151 |  |  |  |  |  |  | A3                    => [841.88976, 1190.5512], | 
| 152 |  |  |  |  |  |  | A4                    => [595.27559, 841.88976], | 
| 153 |  |  |  |  |  |  | A5                    => [420.94488, 595.27559], | 
| 154 |  |  |  |  |  |  | A6                    => [297, 420], | 
| 155 |  |  |  |  |  |  | A7                    => [210, 297], | 
| 156 |  |  |  |  |  |  | A8                    => [148, 210], | 
| 157 |  |  |  |  |  |  | A9                    => [105, 148], | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | B0                    => [2920, 4127], | 
| 160 |  |  |  |  |  |  | B1                    => [2064, 2920], | 
| 161 |  |  |  |  |  |  | B2                    => [1460, 2064], | 
| 162 |  |  |  |  |  |  | B3                    => [1032, 1460], | 
| 163 |  |  |  |  |  |  | B4                    => [729, 1032], | 
| 164 |  |  |  |  |  |  | B5                    => [516, 729], | 
| 165 |  |  |  |  |  |  | B6                    => [363, 516], | 
| 166 |  |  |  |  |  |  | B7                    => [258, 363], | 
| 167 |  |  |  |  |  |  | B8                    => [181, 258], | 
| 168 |  |  |  |  |  |  | B9                    => [127, 181 ], | 
| 169 |  |  |  |  |  |  | B10                   => [91, 127], | 
| 170 |  |  |  |  |  |  |  | 
| 171 |  |  |  |  |  |  | Executive             => [522, 756], | 
| 172 |  |  |  |  |  |  | Folio                 => [595, 935], | 
| 173 |  |  |  |  |  |  | 'Half-Letter'         => [612, 397], | 
| 174 |  |  |  |  |  |  | Letter                => [612, 792], | 
| 175 |  |  |  |  |  |  | 'US-Letter'           => [612, 792], | 
| 176 |  |  |  |  |  |  | Legal                 => [612, 1008], | 
| 177 |  |  |  |  |  |  | 'US-Legal'            => [612, 1008], | 
| 178 |  |  |  |  |  |  | Tabloid               => [792, 1224], | 
| 179 |  |  |  |  |  |  | 'SuperB'              => [843, 1227], | 
| 180 |  |  |  |  |  |  | Ledger                => [1224, 792], | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | 'Comm #10 Envelope'   => [297, 684], | 
| 183 |  |  |  |  |  |  | 'Envelope-Monarch'    => [280, 542], | 
| 184 |  |  |  |  |  |  | 'Envelope-DL'         => [312, 624], | 
| 185 |  |  |  |  |  |  | 'Envelope-C5'         => [461, 648], | 
| 186 |  |  |  |  |  |  |  | 
| 187 |  |  |  |  |  |  | 'EuroPostcard'        => [298, 420], | 
| 188 |  |  |  |  |  |  | ); | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  |  | 
| 191 |  |  |  |  |  |  | # The 13 standard fonts that are available on all PS 1 implementations: | 
| 192 |  |  |  |  |  |  | my @fonts = ( | 
| 193 |  |  |  |  |  |  | 'Courier', 'Courier-Bold', 'Courier-BoldOblique', 'Courier-Oblique', | 
| 194 |  |  |  |  |  |  | 'Helvetica', 'Helvetica-Bold', 'Helvetica-BoldOblique', 'Helvetica-Oblique', | 
| 195 |  |  |  |  |  |  | 'Times-Roman', 'Times-Bold', 'Times-BoldItalic', 'Times-Italic', | 
| 196 |  |  |  |  |  |  | 'Symbol'); | 
| 197 |  |  |  |  |  |  |  | 
| 198 |  |  |  |  |  |  | # define the origins for the page a document can have | 
| 199 |  |  |  |  |  |  | # (default is "LeftBottom") | 
| 200 |  |  |  |  |  |  | my %psorigin = ( | 
| 201 |  |  |  |  |  |  | 'LeftBottom'  => [ 0,  0], | 
| 202 |  |  |  |  |  |  | 'LeftTop'     => [ 0, -1], | 
| 203 |  |  |  |  |  |  | 'RightBottom' => [-1,  0], | 
| 204 |  |  |  |  |  |  | 'RightTop'    => [-1, -1], | 
| 205 |  |  |  |  |  |  | ); | 
| 206 |  |  |  |  |  |  |  | 
| 207 |  |  |  |  |  |  | # define the co-ordinate direction (default is 'RightUp') | 
| 208 |  |  |  |  |  |  | my %psdirs = ( | 
| 209 |  |  |  |  |  |  | 'RightUp'     => [ 1,  1], | 
| 210 |  |  |  |  |  |  | 'RightDown'   => [ 1, -1], | 
| 211 |  |  |  |  |  |  | 'LeftUp'      => [-1,  1], | 
| 212 |  |  |  |  |  |  | 'LeftDown'    => [-1, -1], | 
| 213 |  |  |  |  |  |  | ); | 
| 214 |  |  |  |  |  |  |  | 
| 215 |  |  |  |  |  |  |  | 
| 216 |  |  |  |  |  |  | # measuring units are two-letter acronyms as used in TeX: | 
| 217 |  |  |  |  |  |  | #  bp: postscript point (72 per inch) | 
| 218 |  |  |  |  |  |  | #  in: inch (72 postscript points) | 
| 219 |  |  |  |  |  |  | #  pt: printer's point (72.27 per inch) | 
| 220 |  |  |  |  |  |  | #  mm: millimetre (25.4 per inch) | 
| 221 |  |  |  |  |  |  | #  cm: centimetre (2.54 per inch) | 
| 222 |  |  |  |  |  |  | #  pi: pica (12 printer's points) | 
| 223 |  |  |  |  |  |  | #  dd: didot point (67.567. per inch) | 
| 224 |  |  |  |  |  |  | #  cc: cicero (12 didot points) | 
| 225 |  |  |  |  |  |  |  | 
| 226 |  |  |  |  |  |  | #  set up the others here (sp) XXXXX | 
| 227 |  |  |  |  |  |  |  | 
| 228 |  |  |  |  |  |  | my %psunits = ( | 
| 229 |  |  |  |  |  |  | pt   => [72, 72.27], | 
| 230 |  |  |  |  |  |  | pc   => [72, 6.0225], | 
| 231 |  |  |  |  |  |  | in   => [72, 1], | 
| 232 |  |  |  |  |  |  | bp   => [1, 1], | 
| 233 |  |  |  |  |  |  | cm   => [72, 2.54], | 
| 234 |  |  |  |  |  |  | mm   => [72, 25.4], | 
| 235 |  |  |  |  |  |  | dd   => [72, 67.567], | 
| 236 |  |  |  |  |  |  | cc   => [72, 810.804], | 
| 237 |  |  |  |  |  |  | ); | 
| 238 |  |  |  |  |  |  |  | 
| 239 |  |  |  |  |  |  |  | 
| 240 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 241 |  |  |  |  |  |  |  | 
| 242 |  |  |  |  |  |  | =head1 CONSTRUCTOR | 
| 243 |  |  |  |  |  |  |  | 
| 244 |  |  |  |  |  |  | =over 4 | 
| 245 |  |  |  |  |  |  |  | 
| 246 |  |  |  |  |  |  | =item C | 
| 247 |  |  |  |  |  |  |  | 
| 248 |  |  |  |  |  |  | Create a new PostScript::Simple object. The different options that can be set are: | 
| 249 |  |  |  |  |  |  |  | 
| 250 |  |  |  |  |  |  | =over 4 | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  | =item units | 
| 253 |  |  |  |  |  |  |  | 
| 254 |  |  |  |  |  |  | Units that are to be used in the file. Common units would be C, C, | 
| 255 |  |  |  |  |  |  | C, C, and C. Others are as used in TeX. (Default: C) | 
| 256 |  |  |  |  |  |  |  | 
| 257 |  |  |  |  |  |  | =item xsize | 
| 258 |  |  |  |  |  |  |  | 
| 259 |  |  |  |  |  |  | Specifies the width of the drawing area in units. | 
| 260 |  |  |  |  |  |  |  | 
| 261 |  |  |  |  |  |  | =item ysize | 
| 262 |  |  |  |  |  |  |  | 
| 263 |  |  |  |  |  |  | Specifies the height of the drawing area in units. | 
| 264 |  |  |  |  |  |  |  | 
| 265 |  |  |  |  |  |  | =item papersize | 
| 266 |  |  |  |  |  |  |  | 
| 267 |  |  |  |  |  |  | The size of paper to use, if C or C are not defined. This allows | 
| 268 |  |  |  |  |  |  | a document to easily be created using a standard paper size without having to | 
| 269 |  |  |  |  |  |  | remember the size of paper using PostScript points. Valid choices are currently | 
| 270 |  |  |  |  |  |  | "C", "C", "C", and "C". | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  | =item landscape | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  | Use the landscape option to rotate the page by 90 degrees. The paper dimensions | 
| 275 |  |  |  |  |  |  | are also rotated, so that clipping will still work. (Note that the printer will | 
| 276 |  |  |  |  |  |  | still think that the paper is portrait.) (Default: 0) | 
| 277 |  |  |  |  |  |  |  | 
| 278 |  |  |  |  |  |  | =item copies | 
| 279 |  |  |  |  |  |  |  | 
| 280 |  |  |  |  |  |  | Set the number of copies that should be printed. (Default: 1) | 
| 281 |  |  |  |  |  |  |  | 
| 282 |  |  |  |  |  |  | =item clip | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | If set to 1, the image will be clipped to the xsize and ysize. This is most | 
| 285 |  |  |  |  |  |  | useful for an EPS image. (Default: 0) | 
| 286 |  |  |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | =item colour | 
| 288 |  |  |  |  |  |  |  | 
| 289 |  |  |  |  |  |  | Specifies whether the image should be rendered in colour or not. If set to 0 | 
| 290 |  |  |  |  |  |  | (default) all requests for a colour are mapped to a greyscale. Otherwise the | 
| 291 |  |  |  |  |  |  | colour requested with C or C is used. This option is present | 
| 292 |  |  |  |  |  |  | because most modern laser printers are only black and white. (Default: 0) | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  | =item eps | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  | Generate an EPS file, rather than a standard PostScript file. If set to 1, no | 
| 297 |  |  |  |  |  |  | newpage methods will actually create a new page. This option is probably the | 
| 298 |  |  |  |  |  |  | most useful for generating images to be imported into other applications, such | 
| 299 |  |  |  |  |  |  | as TeX. (Default: 1) | 
| 300 |  |  |  |  |  |  |  | 
| 301 |  |  |  |  |  |  | =item page | 
| 302 |  |  |  |  |  |  |  | 
| 303 |  |  |  |  |  |  | Specifies the initial page number of the (multi page) document. The page number | 
| 304 |  |  |  |  |  |  | is set with the Adobe DSC comments, and is used nowhere else. It only makes | 
| 305 |  |  |  |  |  |  | finding your pages easier. See also the C method. (Default: 1) | 
| 306 |  |  |  |  |  |  |  | 
| 307 |  |  |  |  |  |  | =item coordorigin | 
| 308 |  |  |  |  |  |  |  | 
| 309 |  |  |  |  |  |  | Defines the co-ordinate origin for each page produced. Valid arguments are | 
| 310 |  |  |  |  |  |  | C, C, C and C. The default is | 
| 311 |  |  |  |  |  |  | C. | 
| 312 |  |  |  |  |  |  |  | 
| 313 |  |  |  |  |  |  | =item direction | 
| 314 |  |  |  |  |  |  |  | 
| 315 |  |  |  |  |  |  | The direction the co-ordinates go from the origin. Values can be C, | 
| 316 |  |  |  |  |  |  | C, C and C. The default value is C. | 
| 317 |  |  |  |  |  |  |  | 
| 318 |  |  |  |  |  |  | =item reencode | 
| 319 |  |  |  |  |  |  |  | 
| 320 |  |  |  |  |  |  | Requests that a font re-encode function be added and that the 13 standard | 
| 321 |  |  |  |  |  |  | PostScript fonts get re-encoded in the specified encoding. The most popular | 
| 322 |  |  |  |  |  |  | choice (other than undef) is 'ISOLatin1Encoding' which selects the iso8859-1 | 
| 323 |  |  |  |  |  |  | encoding and fits most of western Europe, including the Scandinavia. Refer to | 
| 324 |  |  |  |  |  |  | Adobes Postscript documentation for other encodings. | 
| 325 |  |  |  |  |  |  |  | 
| 326 |  |  |  |  |  |  | The output file is, by default, re-encoded to ISOLatin1Encoding. To stop this | 
| 327 |  |  |  |  |  |  | happening, use 'reencode => undef'. To use the re-encoded font, '-iso' must be | 
| 328 |  |  |  |  |  |  | appended to the names of the fonts used, e.g. 'Helvetica-iso'. | 
| 329 |  |  |  |  |  |  |  | 
| 330 |  |  |  |  |  |  | =back | 
| 331 |  |  |  |  |  |  |  | 
| 332 |  |  |  |  |  |  | Example: | 
| 333 |  |  |  |  |  |  |  | 
| 334 |  |  |  |  |  |  | $ref = new PostScript::Simple(landscape => 1, | 
| 335 |  |  |  |  |  |  | eps => 0, | 
| 336 |  |  |  |  |  |  | xsize => 4, | 
| 337 |  |  |  |  |  |  | ysize => 3, | 
| 338 |  |  |  |  |  |  | units => "in"); | 
| 339 |  |  |  |  |  |  |  | 
| 340 |  |  |  |  |  |  | Create a document that is 4 by 3 inches and prints landscape on a page. It is | 
| 341 |  |  |  |  |  |  | not an EPS file, and must therefore use the C method. | 
| 342 |  |  |  |  |  |  |  | 
| 343 |  |  |  |  |  |  | $ref = new PostScript::Simple(eps => 1, | 
| 344 |  |  |  |  |  |  | colour => 1, | 
| 345 |  |  |  |  |  |  | xsize => 12, | 
| 346 |  |  |  |  |  |  | ysize => 12, | 
| 347 |  |  |  |  |  |  | units => "cm", | 
| 348 |  |  |  |  |  |  | reencode => "ISOLatin1Encoding"); | 
| 349 |  |  |  |  |  |  |  | 
| 350 |  |  |  |  |  |  | Create a 12 by 12 cm EPS image that is in colour. Note that "C 1>" | 
| 351 |  |  |  |  |  |  | did not have to be specified because this is the default. Re-encode the | 
| 352 |  |  |  |  |  |  | standard fonts into the iso8859-1 encoding, providing all the special characters | 
| 353 |  |  |  |  |  |  | used in Western Europe. The C method should not be used. | 
| 354 |  |  |  |  |  |  |  | 
| 355 |  |  |  |  |  |  | =back | 
| 356 |  |  |  |  |  |  |  | 
| 357 |  |  |  |  |  |  | =cut | 
| 358 |  |  |  |  |  |  |  | 
| 359 |  |  |  |  |  |  | sub new | 
| 360 |  |  |  |  |  |  | { | 
| 361 | 9 |  |  | 9 | 1 | 467 | my ($class, %data) = @_; | 
| 362 | 9 |  |  |  |  | 159 | my $self = { | 
| 363 |  |  |  |  |  |  | xsize          => undef, | 
| 364 |  |  |  |  |  |  | ysize          => undef, | 
| 365 |  |  |  |  |  |  | papersize      => undef, | 
| 366 |  |  |  |  |  |  | units          => "bp",     # measuring units (see below) | 
| 367 |  |  |  |  |  |  | landscape      => 0,        # rotate the page 90 degrees | 
| 368 |  |  |  |  |  |  | copies         => 1,        # number of copies | 
| 369 |  |  |  |  |  |  | colour         => 0,        # use colour | 
| 370 |  |  |  |  |  |  | clip           => 0,        # clip to the bounding box | 
| 371 |  |  |  |  |  |  | eps            => 1,        # create eps file | 
| 372 |  |  |  |  |  |  | page           => 1,        # page number to start at | 
| 373 |  |  |  |  |  |  | reencode       => "ISOLatin1Encoding", # Re-encode the 13 standard | 
| 374 |  |  |  |  |  |  | # fonts in this encoding | 
| 375 |  |  |  |  |  |  |  | 
| 376 |  |  |  |  |  |  | bbx1           => 0,        # Bounding Box definitions | 
| 377 |  |  |  |  |  |  | bby1           => 0, | 
| 378 |  |  |  |  |  |  | bbx2           => 0, | 
| 379 |  |  |  |  |  |  | bby2           => 0, | 
| 380 |  |  |  |  |  |  |  | 
| 381 |  |  |  |  |  |  | pscomments     => "",       # the following entries store data | 
| 382 |  |  |  |  |  |  | psprolog       => "",       # for the same DSC areas of the | 
| 383 |  |  |  |  |  |  | psresources    => {},       # postscript file. | 
| 384 |  |  |  |  |  |  | pssetup        => "", | 
| 385 |  |  |  |  |  |  | pspages        => [], | 
| 386 |  |  |  |  |  |  | pstrailer      => "", | 
| 387 |  |  |  |  |  |  | usedunits      => {},       # units that have been used | 
| 388 |  |  |  |  |  |  |  | 
| 389 |  |  |  |  |  |  | lastfontsize   => 0, | 
| 390 |  |  |  |  |  |  | pspagecount    => 0, | 
| 391 |  |  |  |  |  |  |  | 
| 392 |  |  |  |  |  |  | coordorigin    => 'LeftBottom', | 
| 393 |  |  |  |  |  |  | direction      => 'RightUp', | 
| 394 |  |  |  |  |  |  |  | 
| 395 |  |  |  |  |  |  | lasterror      => undef, | 
| 396 |  |  |  |  |  |  | }; | 
| 397 |  |  |  |  |  |  |  | 
| 398 | 9 |  |  |  |  | 38 | foreach (keys %data) { | 
| 399 | 26 |  |  |  |  | 29 | $self->{$_} = $data{$_}; | 
| 400 |  |  |  |  |  |  | } | 
| 401 |  |  |  |  |  |  |  | 
| 402 | 9 |  |  |  |  | 36 | bless $self, $class; | 
| 403 | 9 |  |  |  |  | 38 | $self->init(); | 
| 404 |  |  |  |  |  |  |  | 
| 405 | 9 |  |  |  |  | 28 | return $self; | 
| 406 |  |  |  |  |  |  | } | 
| 407 |  |  |  |  |  |  |  | 
| 408 |  |  |  |  |  |  |  | 
| 409 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 410 |  |  |  |  |  |  |  | 
| 411 |  |  |  |  |  |  | sub _u | 
| 412 |  |  |  |  |  |  | { | 
| 413 | 519 |  |  | 519 |  | 1927 | my ($self, $u, $rev) = @_; | 
| 414 |  |  |  |  |  |  |  | 
| 415 | 519 |  |  |  |  | 282 | my $val; | 
| 416 |  |  |  |  |  |  | my $unit; | 
| 417 |  |  |  |  |  |  |  | 
| 418 |  |  |  |  |  |  | # $u may be... | 
| 419 |  |  |  |  |  |  | #  a simple number, in which case the current units are used | 
| 420 |  |  |  |  |  |  | #  a listref of [number, "unit"], to force the unit | 
| 421 |  |  |  |  |  |  | #  a string "number unit", e.g. "4 mm" or "2.4in" | 
| 422 |  |  |  |  |  |  |  | 
| 423 | 519 | 100 |  |  |  | 529 | if (ref($u) eq "ARRAY") { | 
| 424 | 5 |  |  |  |  | 7 | $val = $$u[0]; | 
| 425 | 5 |  |  |  |  | 6 | $unit = $$u[1]; | 
| 426 | 5 | 100 |  |  |  | 263 | confess "Invalid array" if @$u != 2; | 
| 427 |  |  |  |  |  |  | } else { | 
| 428 | 514 | 100 |  |  |  | 1656 | if ($u =~ /^\s*(-?\d+(?:\.\d+)?)\s*([a-z][a-z])?\s*$/) { | 
| 429 | 512 |  |  |  |  | 556 | $val = $1; | 
| 430 | 512 |  | 66 |  |  | 917 | $unit = $2 || $self->{units}; | 
| 431 |  |  |  |  |  |  | } | 
| 432 |  |  |  |  |  |  | } | 
| 433 |  |  |  |  |  |  |  | 
| 434 | 517 | 100 |  |  |  | 727 | confess "Cannot determine length" unless defined $val; | 
| 435 | 515 | 50 |  |  |  | 592 | confess "Cannot determine unit (invalid array?)" unless defined $unit; | 
| 436 |  |  |  |  |  |  |  | 
| 437 | 515 | 100 |  |  |  | 690 | croak "Invalid unit '$unit'" unless defined $psunits{$unit}; | 
| 438 |  |  |  |  |  |  |  | 
| 439 | 514 | 100 |  |  |  | 590 | unless (defined $self->{usedunits}{$unit}) { | 
| 440 | 15 |  |  |  |  | 18 | my ($m, $d) = @{$psunits{$unit}}; | 
|  | 15 |  |  |  |  | 26 |  | 
| 441 |  |  |  |  |  |  |  | 
| 442 | 15 |  |  |  |  | 20 | my $c = "{"; | 
| 443 | 15 | 100 |  |  |  | 38 | $c .= "$m mul " unless $m == 1; | 
| 444 | 15 | 100 |  |  |  | 75 | $c .= "$d div " unless $d == 1; | 
| 445 | 15 |  |  |  |  | 34 | $c =~ s/ $//; | 
| 446 | 15 |  |  |  |  | 18 | $c .="}"; | 
| 447 | 15 |  |  |  |  | 40 | $self->{usedunits}{$unit} = "/u$unit $c def"; | 
| 448 |  |  |  |  |  |  | } | 
| 449 |  |  |  |  |  |  |  | 
| 450 | 514 | 100 |  |  |  | 823 | $val = $rev * $val if defined $rev; | 
| 451 |  |  |  |  |  |  |  | 
| 452 | 514 |  |  |  |  | 1231 | return "$val u$unit "; | 
| 453 |  |  |  |  |  |  | } | 
| 454 |  |  |  |  |  |  |  | 
| 455 |  |  |  |  |  |  | sub _ux | 
| 456 |  |  |  |  |  |  | { | 
| 457 | 251 |  |  | 251 |  | 352 | my ($self, $d) = @_; | 
| 458 |  |  |  |  |  |  |  | 
| 459 | 251 |  |  |  |  | 340 | return $self->_u($d, $psdirs{$self->{direction}}[0]); | 
| 460 |  |  |  |  |  |  | } | 
| 461 |  |  |  |  |  |  |  | 
| 462 |  |  |  |  |  |  | sub _uy | 
| 463 |  |  |  |  |  |  | { | 
| 464 | 250 |  |  | 250 |  | 203 | my ($self, $d) = @_; | 
| 465 |  |  |  |  |  |  |  | 
| 466 | 250 |  |  |  |  | 302 | return $self->_u($d, $psdirs{$self->{direction}}[1]); | 
| 467 |  |  |  |  |  |  | } | 
| 468 |  |  |  |  |  |  |  | 
| 469 |  |  |  |  |  |  | sub _uxy | 
| 470 |  |  |  |  |  |  | { | 
| 471 | 249 |  |  | 249 |  | 225 | my ($self, $x, $y) = @_; | 
| 472 |  |  |  |  |  |  |  | 
| 473 | 249 |  |  |  |  | 271 | return $self->_ux($x) . $self->_uy($y); | 
| 474 |  |  |  |  |  |  | } | 
| 475 |  |  |  |  |  |  |  | 
| 476 |  |  |  |  |  |  |  | 
| 477 |  |  |  |  |  |  | sub init | 
| 478 |  |  |  |  |  |  | { | 
| 479 | 9 |  |  | 9 | 0 | 18 | my $self = shift; | 
| 480 |  |  |  |  |  |  |  | 
| 481 | 9 |  |  |  |  | 22 | my ($m, $d) = (1, 1); | 
| 482 | 9 |  |  |  |  | 11 | my ($u, $mm); | 
| 483 |  |  |  |  |  |  |  | 
| 484 |  |  |  |  |  |  | # Create a blank "page" for EPS | 
| 485 | 9 | 100 |  |  |  | 53 | if ($self->{eps}) { | 
| 486 | 7 |  |  |  |  | 12 | $self->{currentpage} = []; | 
| 487 | 7 |  |  |  |  | 18 | $self->{pspages} = [$self->{currentpage}]; | 
| 488 |  |  |  |  |  |  | } | 
| 489 |  |  |  |  |  |  |  | 
| 490 |  |  |  |  |  |  |  | 
| 491 |  |  |  |  |  |  | # Units | 
| 492 | 9 |  |  |  |  | 23 | $self->{units} = lc $self->{units}; | 
| 493 |  |  |  |  |  |  |  | 
| 494 | 9 | 50 |  |  |  | 33 | if (defined($psunits{$self->{units}})) { | 
| 495 | 9 |  |  |  |  | 64 | ($m, $d) = @{$psunits{$self->{units}}}; | 
|  | 9 |  |  |  |  | 39 |  | 
| 496 |  |  |  |  |  |  | } else { | 
| 497 | 0 |  |  |  |  | 0 | $self->_error( "unit '$self->{units}' undefined" ); | 
| 498 |  |  |  |  |  |  | } | 
| 499 |  |  |  |  |  |  |  | 
| 500 |  |  |  |  |  |  |  | 
| 501 |  |  |  |  |  |  | # Paper size | 
| 502 | 9 | 100 |  |  |  | 62 | if (defined $self->{papersize}) { | 
| 503 | 3 |  |  |  |  | 12 | $self->{papersize} = ucfirst lc $self->{papersize}; | 
| 504 |  |  |  |  |  |  | } | 
| 505 |  |  |  |  |  |  |  | 
| 506 | 9 | 100 | 66 |  |  | 75 | if (!defined $self->{xsize} || !defined $self->{ysize}) { | 
| 507 | 6 | 100 | 66 |  |  | 31 | if (defined $self->{papersize} && defined $pspaper{$self->{papersize}}) { | 
| 508 | 3 |  |  |  |  | 6 | ($self->{xsize}, $self->{ysize}) = @{$pspaper{$self->{papersize}}}; | 
|  | 3 |  |  |  |  | 12 |  | 
| 509 | 3 |  |  |  |  | 11 | $self->{bbx2} = int($self->{xsize}); | 
| 510 | 3 |  |  |  |  | 4 | $self->{bby2} = int($self->{ysize}); | 
| 511 | 3 |  |  |  |  | 48 | $self->{pscomments} .= "\%\%DocumentMedia: $self->{papersize} $self->{xsize} "; | 
| 512 | 3 |  |  |  |  | 12 | $self->{pscomments} .= "$self->{ysize} 0 ( ) ( )\n"; | 
| 513 |  |  |  |  |  |  | } else { | 
| 514 | 3 |  |  |  |  | 4 | ($self->{xsize}, $self->{ysize}) = (100,100); | 
| 515 | 3 |  |  |  |  | 6 | $self->_error( "page size undefined" ); | 
| 516 |  |  |  |  |  |  | } | 
| 517 |  |  |  |  |  |  | } else { | 
| 518 | 3 |  |  |  |  | 14 | $self->{bbx2} = int(($self->{xsize} * $m) / $d); | 
| 519 | 3 |  |  |  |  | 7 | $self->{bby2} = int(($self->{ysize} * $m) / $d); | 
| 520 |  |  |  |  |  |  | } | 
| 521 |  |  |  |  |  |  |  | 
| 522 | 9 | 100 |  |  |  | 42 | if (!$self->{eps}) { | 
| 523 | 2 |  |  |  |  | 17 | $self->{pssetup} .= "ll 2 ge { << /PageSize [ $self->{xsize} " . | 
| 524 |  |  |  |  |  |  | "$self->{ysize} ] /ImagingBBox null >>" . | 
| 525 |  |  |  |  |  |  | " setpagedevice } if\n"; | 
| 526 |  |  |  |  |  |  | } | 
| 527 |  |  |  |  |  |  |  | 
| 528 |  |  |  |  |  |  | # Landscape | 
| 529 | 9 | 50 |  |  |  | 19 | if ($self->{landscape}) { | 
| 530 | 0 |  |  |  |  | 0 | my $swap; | 
| 531 |  |  |  |  |  |  |  | 
| 532 | 0 |  |  |  |  | 0 | $self->{psresources}{landscape} = <<"EOP"; | 
| 533 |  |  |  |  |  |  | /landscape { | 
| 534 |  |  |  |  |  |  | $self->{bbx2} 0 translate 90 rotate | 
| 535 |  |  |  |  |  |  | } bind def | 
| 536 |  |  |  |  |  |  | EOP | 
| 537 |  |  |  |  |  |  |  | 
| 538 |  |  |  |  |  |  | # I now think that Portrait is the correct thing here, as the page is | 
| 539 |  |  |  |  |  |  | # rotated. | 
| 540 | 0 |  |  |  |  | 0 | $self->{pscomments} .= "\%\%Orientation: Portrait\n"; | 
| 541 |  |  |  |  |  |  | #    $self->{pscomments} .= "\%\%Orientation: Landscape\n"; | 
| 542 | 0 |  |  |  |  | 0 | $swap = $self->{bbx2}; | 
| 543 | 0 |  |  |  |  | 0 | $self->{bbx2} = $self->{bby2}; | 
| 544 | 0 |  |  |  |  | 0 | $self->{bby2} = $swap; | 
| 545 |  |  |  |  |  |  |  | 
| 546 |  |  |  |  |  |  | # for EPS files, change to landscape here, as there are no pages | 
| 547 | 0 | 0 |  |  |  | 0 | if ($self->{eps}) { $self->{pssetup} .= "landscape\n" } | 
|  | 0 |  |  |  |  | 0 |  | 
| 548 |  |  |  |  |  |  | } else { | 
| 549 | 9 |  |  |  |  | 15 | $self->{pscomments} .= "\%\%Orientation: Portrait\n"; | 
| 550 |  |  |  |  |  |  | } | 
| 551 |  |  |  |  |  |  |  | 
| 552 |  |  |  |  |  |  | # Clipping | 
| 553 | 9 | 50 |  |  |  | 22 | if ($self->{clip}) { | 
| 554 | 0 |  |  |  |  | 0 | $self->{psresources}{pageclip} = <<"EOP"; | 
| 555 |  |  |  |  |  |  | /pageclip { | 
| 556 |  |  |  |  |  |  | newpath | 
| 557 |  |  |  |  |  |  | $self->{bbx1} $self->{bby1} moveto | 
| 558 |  |  |  |  |  |  | $self->{bbx1} $self->{bby2} lineto | 
| 559 |  |  |  |  |  |  | $self->{bbx2} $self->{bby2} lineto | 
| 560 |  |  |  |  |  |  | $self->{bbx2} $self->{bby1} lineto | 
| 561 |  |  |  |  |  |  | $self->{bbx1} $self->{bby1} lineto | 
| 562 |  |  |  |  |  |  | closepath clip | 
| 563 |  |  |  |  |  |  | } bind def | 
| 564 |  |  |  |  |  |  | EOP | 
| 565 | 0 | 0 |  |  |  | 0 | if ($self->{eps}) { $self->{pssetup} .= "pageclip\n" } | 
|  | 0 |  |  |  |  | 0 |  | 
| 566 |  |  |  |  |  |  | } | 
| 567 |  |  |  |  |  |  |  | 
| 568 |  |  |  |  |  |  | # Font reencoding | 
| 569 | 9 | 100 |  |  |  | 22 | if ($self->{reencode}) { | 
| 570 | 8 |  |  |  |  | 8 | my $encoding; # The name of the encoding | 
| 571 |  |  |  |  |  |  | my $ext;      # The extention to tack onto the std fontnames | 
| 572 |  |  |  |  |  |  |  | 
| 573 | 8 | 50 |  |  |  | 18 | if (ref $self->{reencode} eq 'ARRAY') { | 
| 574 | 0 |  |  |  |  | 0 | die "Custom reencoding of fonts not really implemented yet, sorry..."; | 
| 575 | 0 |  |  |  |  | 0 | $encoding = shift @{$self->{reencode}}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 576 | 0 |  |  |  |  | 0 | $ext = shift @{$self->{reencode}}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 577 |  |  |  |  |  |  | # TODO: Do something to add the actual encoding to the postscript code. | 
| 578 |  |  |  |  |  |  | } else { | 
| 579 | 8 |  |  |  |  | 11 | $encoding = $self->{reencode}; | 
| 580 | 8 |  |  |  |  | 15 | $ext = '-iso'; | 
| 581 |  |  |  |  |  |  | } | 
| 582 |  |  |  |  |  |  |  | 
| 583 | 8 |  |  |  |  | 47 | $self->{psresources}{REENCODEFONT} = <<'EOP'; | 
| 584 |  |  |  |  |  |  | /STARTDIFFENC { mark } bind def | 
| 585 |  |  |  |  |  |  | /ENDDIFFENC { | 
| 586 |  |  |  |  |  |  |  | 
| 587 |  |  |  |  |  |  | % /NewEnc BaseEnc STARTDIFFENC number or glyphname ... ENDDIFFENC - | 
| 588 |  |  |  |  |  |  | counttomark 2 add -1 roll 256 array copy | 
| 589 |  |  |  |  |  |  | /TempEncode exch def | 
| 590 |  |  |  |  |  |  |  | 
| 591 |  |  |  |  |  |  | % pointer for sequential encodings | 
| 592 |  |  |  |  |  |  | /EncodePointer 0 def | 
| 593 |  |  |  |  |  |  | { | 
| 594 |  |  |  |  |  |  | % Get the bottom object | 
| 595 |  |  |  |  |  |  | counttomark -1 roll | 
| 596 |  |  |  |  |  |  | % Is it a mark? | 
| 597 |  |  |  |  |  |  | dup type dup /marktype eq { | 
| 598 |  |  |  |  |  |  | % End of encoding | 
| 599 |  |  |  |  |  |  | pop pop exit | 
| 600 |  |  |  |  |  |  | } { | 
| 601 |  |  |  |  |  |  | /nametype eq { | 
| 602 |  |  |  |  |  |  | % Insert the name at EncodePointer | 
| 603 |  |  |  |  |  |  |  | 
| 604 |  |  |  |  |  |  | % and increment the pointer. | 
| 605 |  |  |  |  |  |  | TempEncode EncodePointer 3 -1 roll put | 
| 606 |  |  |  |  |  |  | /EncodePointer EncodePointer 1 add def | 
| 607 |  |  |  |  |  |  | } { | 
| 608 |  |  |  |  |  |  | % Set the EncodePointer to the number | 
| 609 |  |  |  |  |  |  | /EncodePointer exch def | 
| 610 |  |  |  |  |  |  | } ifelse | 
| 611 |  |  |  |  |  |  | } ifelse | 
| 612 |  |  |  |  |  |  | } loop | 
| 613 |  |  |  |  |  |  |  | 
| 614 |  |  |  |  |  |  | TempEncode def | 
| 615 |  |  |  |  |  |  | } bind def | 
| 616 |  |  |  |  |  |  |  | 
| 617 |  |  |  |  |  |  | % Define ISO Latin1 encoding if it doesnt exist | 
| 618 |  |  |  |  |  |  | /ISOLatin1Encoding where { | 
| 619 |  |  |  |  |  |  | %	(ISOLatin1 exists!) = | 
| 620 |  |  |  |  |  |  | pop | 
| 621 |  |  |  |  |  |  | } { | 
| 622 |  |  |  |  |  |  | (ISOLatin1 does not exist, creating...) = | 
| 623 |  |  |  |  |  |  | /ISOLatin1Encoding StandardEncoding STARTDIFFENC | 
| 624 |  |  |  |  |  |  | 144 /dotlessi /grave /acute /circumflex /tilde | 
| 625 |  |  |  |  |  |  | /macron /breve /dotaccent /dieresis /.notdef /ring | 
| 626 |  |  |  |  |  |  | /cedilla /.notdef /hungarumlaut /ogonek /caron /space | 
| 627 |  |  |  |  |  |  | /exclamdown /cent /sterling /currency /yen /brokenbar | 
| 628 |  |  |  |  |  |  | /section /dieresis /copyright /ordfeminine | 
| 629 |  |  |  |  |  |  | /guillemotleft /logicalnot /hyphen /registered | 
| 630 |  |  |  |  |  |  | /macron /degree /plusminus /twosuperior | 
| 631 |  |  |  |  |  |  | /threesuperior /acute /mu /paragraph /periodcentered | 
| 632 |  |  |  |  |  |  | /cedilla /onesuperior /ordmasculine /guillemotright | 
| 633 |  |  |  |  |  |  | /onequarter /onehalf /threequarters /questiondown | 
| 634 |  |  |  |  |  |  | /Agrave /Aacute /Acircumflex /Atilde /Adieresis | 
| 635 |  |  |  |  |  |  | /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex | 
| 636 |  |  |  |  |  |  | /Edieresis /Igrave /Iacute /Icircumflex /Idieresis | 
| 637 |  |  |  |  |  |  | /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde | 
| 638 |  |  |  |  |  |  | /Odieresis /multiply /Oslash /Ugrave /Uacute | 
| 639 |  |  |  |  |  |  | /Ucircumflex /Udieresis /Yacute /Thorn /germandbls | 
| 640 |  |  |  |  |  |  | /agrave /aacute /acircumflex /atilde /adieresis | 
| 641 |  |  |  |  |  |  | /aring /ae /ccedilla /egrave /eacute /ecircumflex | 
| 642 |  |  |  |  |  |  | /edieresis /igrave /iacute /icircumflex /idieresis | 
| 643 |  |  |  |  |  |  | /eth /ntilde /ograve /oacute /ocircumflex /otilde | 
| 644 |  |  |  |  |  |  | /odieresis /divide /oslash /ugrave /uacute | 
| 645 |  |  |  |  |  |  | /ucircumflex /udieresis /yacute /thorn /ydieresis | 
| 646 |  |  |  |  |  |  | ENDDIFFENC | 
| 647 |  |  |  |  |  |  | } ifelse | 
| 648 |  |  |  |  |  |  |  | 
| 649 |  |  |  |  |  |  | % Name: Re-encode Font | 
| 650 |  |  |  |  |  |  | % Description: Creates a new font using the named encoding. | 
| 651 |  |  |  |  |  |  |  | 
| 652 |  |  |  |  |  |  | /REENCODEFONT { % /Newfont NewEncoding /Oldfont | 
| 653 |  |  |  |  |  |  | findfont dup length 4 add dict | 
| 654 |  |  |  |  |  |  | begin | 
| 655 |  |  |  |  |  |  | { % forall | 
| 656 |  |  |  |  |  |  | 1 index /FID ne | 
| 657 |  |  |  |  |  |  | 2 index /UniqueID ne and | 
| 658 |  |  |  |  |  |  | 2 index /XUID ne and | 
| 659 |  |  |  |  |  |  | { def } { pop pop } ifelse | 
| 660 |  |  |  |  |  |  | } forall | 
| 661 |  |  |  |  |  |  | /Encoding exch def | 
| 662 |  |  |  |  |  |  | % defs for DPS | 
| 663 |  |  |  |  |  |  | /BitmapWidths false def | 
| 664 |  |  |  |  |  |  | /ExactSize 0 def | 
| 665 |  |  |  |  |  |  | /InBetweenSize 0 def | 
| 666 |  |  |  |  |  |  | /TransformedChar 0 def | 
| 667 |  |  |  |  |  |  | currentdict | 
| 668 |  |  |  |  |  |  | end | 
| 669 |  |  |  |  |  |  | definefont pop | 
| 670 |  |  |  |  |  |  | } bind def | 
| 671 |  |  |  |  |  |  |  | 
| 672 |  |  |  |  |  |  | % Reencode the std fonts: | 
| 673 |  |  |  |  |  |  | EOP | 
| 674 |  |  |  |  |  |  |  | 
| 675 | 8 |  |  |  |  | 19 | for my $font (@fonts) { | 
| 676 | 104 |  |  |  |  | 180 | $self->{psresources}{REENCODEFONT} .= "/${font}$ext $encoding /$font REENCODEFONT\n"; | 
| 677 |  |  |  |  |  |  | } | 
| 678 |  |  |  |  |  |  | } | 
| 679 |  |  |  |  |  |  | } | 
| 680 |  |  |  |  |  |  |  | 
| 681 |  |  |  |  |  |  |  | 
| 682 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 683 |  |  |  |  |  |  |  | 
| 684 |  |  |  |  |  |  | =head1 OBJECT METHODS | 
| 685 |  |  |  |  |  |  |  | 
| 686 |  |  |  |  |  |  | Unless otherwise specified, object methods return 1 for success or 0 in some | 
| 687 |  |  |  |  |  |  | error condition (e.g. insufficient arguments). Error message text is also | 
| 688 |  |  |  |  |  |  | drawn on the page. | 
| 689 |  |  |  |  |  |  |  | 
| 690 |  |  |  |  |  |  | =over 4 | 
| 691 |  |  |  |  |  |  |  | 
| 692 |  |  |  |  |  |  | =item C | 
| 693 |  |  |  |  |  |  |  | 
| 694 |  |  |  |  |  |  | Generates a new page on a PostScript file. If specified, C gives the | 
| 695 |  |  |  |  |  |  | number (or name) of the page. This method should not be used for EPS files. | 
| 696 |  |  |  |  |  |  |  | 
| 697 |  |  |  |  |  |  | The page number is automatically incremented each time this is called without | 
| 698 |  |  |  |  |  |  | a new page number, or decremented if the current page number is negative. | 
| 699 |  |  |  |  |  |  |  | 
| 700 |  |  |  |  |  |  | Example: | 
| 701 |  |  |  |  |  |  |  | 
| 702 |  |  |  |  |  |  | $p->newpage(1); | 
| 703 |  |  |  |  |  |  | $p->newpage; | 
| 704 |  |  |  |  |  |  | $p->newpage("hello"); | 
| 705 |  |  |  |  |  |  | $p->newpage(-6); | 
| 706 |  |  |  |  |  |  | $p->newpage; | 
| 707 |  |  |  |  |  |  |  | 
| 708 |  |  |  |  |  |  | will generate five pages, numbered: 1, 2, "hello", -6, -7. | 
| 709 |  |  |  |  |  |  |  | 
| 710 |  |  |  |  |  |  | =cut | 
| 711 |  |  |  |  |  |  |  | 
| 712 |  |  |  |  |  |  | sub newpage | 
| 713 |  |  |  |  |  |  | { | 
| 714 | 5 |  |  | 5 | 1 | 947 | my $self = shift; | 
| 715 | 5 |  |  |  |  | 8 | my $nextpage = shift; | 
| 716 |  |  |  |  |  |  |  | 
| 717 | 5 | 100 |  |  |  | 11 | if (defined($nextpage)) { $self->{page} = $nextpage; } | 
|  | 2 |  |  |  |  | 3 |  | 
| 718 |  |  |  |  |  |  |  | 
| 719 | 5 | 100 |  |  |  | 12 | if ($self->{eps}) { | 
| 720 |  |  |  |  |  |  | # Cannot have multiple pages in an EPS file | 
| 721 | 1 |  |  |  |  | 5 | $self->_error("Do not use newpage for eps files!"); | 
| 722 | 1 |  |  |  |  | 3 | return 0; | 
| 723 |  |  |  |  |  |  | } | 
| 724 |  |  |  |  |  |  |  | 
| 725 |  |  |  |  |  |  | # close old page if required | 
| 726 | 4 | 100 |  |  |  | 9 | if ($self->{pspagecount} != 0) { | 
| 727 | 2 |  |  |  |  | 4 | $self->_closepage(); | 
| 728 |  |  |  |  |  |  | } | 
| 729 |  |  |  |  |  |  |  | 
| 730 |  |  |  |  |  |  | # start new page | 
| 731 | 4 |  |  |  |  | 9 | $self->_openpage(); | 
| 732 |  |  |  |  |  |  |  | 
| 733 | 4 |  |  |  |  | 8 | return 1; | 
| 734 |  |  |  |  |  |  | } | 
| 735 |  |  |  |  |  |  |  | 
| 736 |  |  |  |  |  |  |  | 
| 737 |  |  |  |  |  |  | sub _openpage | 
| 738 |  |  |  |  |  |  | { | 
| 739 | 4 |  |  | 4 |  | 4 | my $self = shift; | 
| 740 | 4 |  |  |  |  | 3 | my ($x, $y); | 
| 741 |  |  |  |  |  |  |  | 
| 742 | 4 |  |  |  |  | 6 | $self->{pspagecount}++; | 
| 743 |  |  |  |  |  |  |  | 
| 744 | 4 |  |  |  |  | 6 | $self->{currentpage} = []; | 
| 745 | 4 |  |  |  |  | 3 | push @{$self->{pspages}}, $self->{currentpage}; | 
|  | 4 |  |  |  |  | 8 |  | 
| 746 |  |  |  |  |  |  |  | 
| 747 | 4 |  |  |  |  | 17 | $self->_addtopage("\%\%Page: $self->{page} $self->{pspagecount}\n"); | 
| 748 |  |  |  |  |  |  |  | 
| 749 | 4 | 100 |  |  |  | 8 | if ($self->{page} >= 0) { | 
| 750 | 2 |  |  |  |  | 4 | $self->{page} ++; | 
| 751 |  |  |  |  |  |  | } else { | 
| 752 | 2 |  |  |  |  | 3 | $self->{page} --; | 
| 753 |  |  |  |  |  |  | } | 
| 754 |  |  |  |  |  |  |  | 
| 755 | 4 |  |  |  |  | 6 | $self->_addtopage("\%\%BeginPageSetup\n"); | 
| 756 | 4 |  |  |  |  | 6 | $self->_addtopage("/pagelevel save def\n"); | 
| 757 |  |  |  |  |  |  |  | 
| 758 | 4 | 50 |  |  |  | 10 | if ($self->{landscape}) { $self->_addtopage("landscape\n"); } | 
|  | 0 |  |  |  |  | 0 |  | 
| 759 | 4 | 50 |  |  |  | 8 | if ($self->{clip}) { $self->_addtopage("pageclip\n"); } | 
|  | 0 |  |  |  |  | 0 |  | 
| 760 |  |  |  |  |  |  |  | 
| 761 | 4 |  |  |  |  | 9 | ($x, $y) = @{$psorigin{$self->{coordorigin}}}; | 
|  | 4 |  |  |  |  | 8 |  | 
| 762 | 4 | 50 |  |  |  | 9 | $x = $self->{xsize} if ($x < 0); | 
| 763 | 4 | 50 |  |  |  | 7 | $y = $self->{ysize} if ($y < 0); | 
| 764 | 4 | 50 | 33 |  |  | 20 | $self->_addtopage("$x $y translate\n") if (($x != 0) || ($y != 0)); | 
| 765 | 4 |  |  |  |  | 6 | $self->_addtopage("\%\%EndPageSetup\n"); | 
| 766 |  |  |  |  |  |  | } | 
| 767 |  |  |  |  |  |  |  | 
| 768 |  |  |  |  |  |  | sub _closepage | 
| 769 |  |  |  |  |  |  | { | 
| 770 | 4 |  |  | 4 |  | 6 | my $self = shift; | 
| 771 |  |  |  |  |  |  |  | 
| 772 | 4 |  |  |  |  | 11 | $self->_addtopage("\%\%PageTrailer\npagelevel restore\nshowpage\n"); | 
| 773 |  |  |  |  |  |  | } | 
| 774 |  |  |  |  |  |  |  | 
| 775 |  |  |  |  |  |  |  | 
| 776 |  |  |  |  |  |  |  | 
| 777 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 778 |  |  |  |  |  |  |  | 
| 779 |  |  |  |  |  |  | =item C | 
| 780 |  |  |  |  |  |  |  | 
| 781 |  |  |  |  |  |  | Writes the current PostScript out to the file named C. Will destroy | 
| 782 |  |  |  |  |  |  | any existing file of the same name. | 
| 783 |  |  |  |  |  |  |  | 
| 784 |  |  |  |  |  |  | Use this method whenever output is required to disk. The current PostScript | 
| 785 |  |  |  |  |  |  | document in memory is not cleared, and can still be extended. | 
| 786 |  |  |  |  |  |  |  | 
| 787 |  |  |  |  |  |  | =cut | 
| 788 |  |  |  |  |  |  |  | 
| 789 |  |  |  |  |  |  | sub _builddocument | 
| 790 |  |  |  |  |  |  | { | 
| 791 | 4 |  |  | 4 |  | 8 | my $self = shift; | 
| 792 | 4 |  |  |  |  | 17 | my $title = shift; | 
| 793 |  |  |  |  |  |  |  | 
| 794 | 4 |  |  |  |  | 5 | my $doc; | 
| 795 | 4 |  |  |  |  | 649 | my $date = scalar localtime; | 
| 796 | 4 |  |  |  |  | 8 | my $user; | 
| 797 |  |  |  |  |  |  |  | 
| 798 | 4 | 50 |  |  |  | 12 | $title = 'undefined' unless $title; | 
| 799 |  |  |  |  |  |  |  | 
| 800 | 4 |  |  |  |  | 9 | $doc = []; | 
| 801 |  |  |  |  |  |  |  | 
| 802 |  |  |  |  |  |  | # getlogin is unimplemented on some systems | 
| 803 | 4 |  |  |  |  | 7 | eval { $user = getlogin; }; | 
|  | 4 |  |  |  |  | 2206 |  | 
| 804 | 4 | 50 |  |  |  | 27 | $user = 'Console' unless $user; | 
| 805 |  |  |  |  |  |  |  | 
| 806 |  |  |  |  |  |  | # Comments Section | 
| 807 | 4 |  |  |  |  | 9 | push @$doc, "%!PS-Adobe-3.0"; | 
| 808 | 4 | 100 |  |  |  | 16 | push @$doc, " EPSF-1.2" if ($self->{eps}); | 
| 809 | 4 |  |  |  |  | 9 | push @$doc, "\n"; | 
| 810 | 4 |  |  |  |  | 12 | push @$doc, "\%\%Title: ($title)\n"; | 
| 811 | 4 |  |  |  |  | 12 | push @$doc, "\%\%LanguageLevel: 1\n"; | 
| 812 | 4 |  |  |  |  | 12 | push @$doc, "\%\%Creator: PostScript::Simple perl module version $VERSION\n"; | 
| 813 | 4 |  |  |  |  | 12 | push @$doc, "\%\%CreationDate: $date\n"; | 
| 814 | 4 |  |  |  |  | 8 | push @$doc, "\%\%For: $user\n"; | 
| 815 | 4 |  |  |  |  | 16 | push @$doc, \$self->{pscomments}; | 
| 816 |  |  |  |  |  |  | #  push @$doc, "\%\%DocumentFonts: \n"; | 
| 817 | 4 | 100 |  |  |  | 18 | if ($self->{eps}) { | 
| 818 | 2 |  |  |  |  | 12 | push @$doc, "\%\%BoundingBox: $self->{bbx1} $self->{bby1} $self->{bbx2} $self->{bby2}\n"; | 
| 819 |  |  |  |  |  |  | } else { | 
| 820 | 2 |  |  |  |  | 7 | push @$doc, "\%\%Pages: $self->{pspagecount}\n"; | 
| 821 |  |  |  |  |  |  | } | 
| 822 | 4 |  |  |  |  | 10 | push @$doc, "\%\%EndComments\n"; | 
| 823 |  |  |  |  |  |  |  | 
| 824 |  |  |  |  |  |  | # Prolog Section | 
| 825 | 4 |  |  |  |  | 8 | push @$doc, "\%\%BeginProlog\n"; | 
| 826 | 4 |  |  |  |  | 5 | push @$doc, "/ll 1 def systemdict /languagelevel known {\n"; | 
| 827 | 4 |  |  |  |  | 7 | push @$doc, "/ll languagelevel def } if\n"; | 
| 828 | 4 |  |  |  |  | 8 | push @$doc, \$self->{psprolog}; | 
| 829 | 4 |  |  |  |  | 5 | foreach my $fn (sort keys %{$self->{psresources}}) { | 
|  | 4 |  |  |  |  | 33 |  | 
| 830 | 13 |  |  |  |  | 23 | push @$doc, "\%\%BeginResource: PostScript::Simple-$fn\n"; | 
| 831 | 13 |  |  |  |  | 24 | push @$doc, $self->{psresources}{$fn}; | 
| 832 | 13 |  |  |  |  | 18 | push @$doc, "\%\%EndResource\n"; | 
| 833 |  |  |  |  |  |  | } | 
| 834 | 4 |  |  |  |  | 12 | push @$doc, "\%\%EndProlog\n"; | 
| 835 |  |  |  |  |  |  |  | 
| 836 |  |  |  |  |  |  | # Setup Section | 
| 837 | 4 |  |  |  |  | 10 | push @$doc, "\%\%BeginSetup\n"; | 
| 838 | 4 |  |  |  |  | 7 | foreach my $un (sort keys %{$self->{usedunits}}) { | 
|  | 4 |  |  |  |  | 12 |  | 
| 839 | 5 |  |  |  |  | 11 | push @$doc, $self->{usedunits}{$un} . "\n"; | 
| 840 |  |  |  |  |  |  | } | 
| 841 | 4 | 50 |  |  |  | 16 | if ($self->{copies} > 1) { | 
| 842 | 0 |  |  |  |  | 0 | push @$doc, "/#copies " . $self->{copies} . " def\n"; | 
| 843 |  |  |  |  |  |  | } | 
| 844 | 4 |  |  |  |  | 8 | push @$doc, \$self->{pssetup}; | 
| 845 | 4 |  |  |  |  | 12 | push @$doc, "\%\%EndSetup\n"; | 
| 846 |  |  |  |  |  |  |  | 
| 847 |  |  |  |  |  |  | # Pages | 
| 848 | 4 | 100 | 66 |  |  | 23 | if ((!$self->{eps}) && ($self->{pspagecount} > 0)) { | 
| 849 | 2 |  |  |  |  | 6 | $self->_closepage(); | 
| 850 |  |  |  |  |  |  | } | 
| 851 |  |  |  |  |  |  |  | 
| 852 | 4 |  |  |  |  | 5 | foreach my $page (@{$self->{pspages}}) { | 
|  | 4 |  |  |  |  | 10 |  | 
| 853 | 6 |  |  |  |  | 21 | push @$doc, $self->_buildpage($page); | 
| 854 |  |  |  |  |  |  | } | 
| 855 |  |  |  |  |  |  |  | 
| 856 |  |  |  |  |  |  | # Trailer Section | 
| 857 | 4 | 50 |  |  |  | 12 | if (length($self->{pstrailer})) { | 
| 858 | 0 |  |  |  |  | 0 | push @$doc, "\%\%Trailer\n"; | 
| 859 | 0 |  |  |  |  | 0 | push @$doc, \$self->{pstrailer}; | 
| 860 |  |  |  |  |  |  | } | 
| 861 | 4 |  |  |  |  | 10 | push @$doc, "\%\%EOF\n"; | 
| 862 |  |  |  |  |  |  |  | 
| 863 | 4 |  |  |  |  | 7 | return $doc; | 
| 864 |  |  |  |  |  |  | } | 
| 865 |  |  |  |  |  |  |  | 
| 866 |  |  |  |  |  |  | sub _buildpage | 
| 867 |  |  |  |  |  |  | { | 
| 868 | 9 |  |  | 9 |  | 342 | my ($self, $page) = @_; | 
| 869 |  |  |  |  |  |  |  | 
| 870 | 9 |  |  |  |  | 12 | my $data = ""; | 
| 871 |  |  |  |  |  |  |  | 
| 872 | 9 |  |  |  |  | 16 | foreach my $statement (@$page) { | 
| 873 | 618 |  |  |  |  | 511 | $data .= $$statement[1]; | 
| 874 |  |  |  |  |  |  | } | 
| 875 |  |  |  |  |  |  |  | 
| 876 | 9 |  |  |  |  | 29 | return $data; | 
| 877 |  |  |  |  |  |  | } | 
| 878 |  |  |  |  |  |  |  | 
| 879 |  |  |  |  |  |  | #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | 
| 880 |  |  |  |  |  |  |  | 
| 881 |  |  |  |  |  |  | sub output | 
| 882 |  |  |  |  |  |  | { | 
| 883 | 5 |  |  | 5 | 1 | 1578 | my $self = shift; | 
| 884 | 5 |  | 100 |  |  | 25 | my $file = shift || die("Must supply a filename for output"); | 
| 885 | 4 |  |  |  |  | 7 | my $page; | 
| 886 |  |  |  |  |  |  | my $i; | 
| 887 |  |  |  |  |  |  |  | 
| 888 | 4 |  |  |  |  | 19 | $page = _builddocument($self, $file); | 
| 889 |  |  |  |  |  |  |  | 
| 890 | 4 |  |  |  |  | 14 | local *OUT; | 
| 891 | 4 | 50 |  |  |  | 409 | open(OUT, '>', $file) or die("Cannot write to file $file: $!"); | 
| 892 |  |  |  |  |  |  |  | 
| 893 | 4 |  |  |  |  | 9 | foreach $i (@$page) { | 
| 894 | 128 | 100 |  |  |  | 114 | if (ref($i) eq "SCALAR") { | 
| 895 | 12 |  |  |  |  | 16 | print OUT $$i; | 
| 896 |  |  |  |  |  |  | } else { | 
| 897 | 116 |  |  |  |  | 182 | print OUT $i; | 
| 898 |  |  |  |  |  |  | } | 
| 899 |  |  |  |  |  |  | } | 
| 900 |  |  |  |  |  |  |  | 
| 901 | 4 |  |  |  |  | 225 | close OUT; | 
| 902 |  |  |  |  |  |  |  | 
| 903 | 4 |  |  |  |  | 29 | return 1; | 
| 904 |  |  |  |  |  |  | } | 
| 905 |  |  |  |  |  |  |  | 
| 906 |  |  |  |  |  |  |  | 
| 907 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 908 |  |  |  |  |  |  |  | 
| 909 |  |  |  |  |  |  | =item C | 
| 910 |  |  |  |  |  |  |  | 
| 911 |  |  |  |  |  |  | Returns the current document. | 
| 912 |  |  |  |  |  |  |  | 
| 913 |  |  |  |  |  |  | Use this method whenever output is required as a scalar. The current PostScript | 
| 914 |  |  |  |  |  |  | document in memory is not cleared, and can still be extended. | 
| 915 |  |  |  |  |  |  |  | 
| 916 |  |  |  |  |  |  | =cut | 
| 917 |  |  |  |  |  |  |  | 
| 918 |  |  |  |  |  |  | sub get | 
| 919 |  |  |  |  |  |  | { | 
| 920 | 0 |  |  | 0 | 1 | 0 | my $self = shift; | 
| 921 | 0 |  |  |  |  | 0 | my $page; | 
| 922 |  |  |  |  |  |  | my $i; | 
| 923 | 0 |  |  |  |  | 0 | my $doc; | 
| 924 |  |  |  |  |  |  |  | 
| 925 | 0 |  |  |  |  | 0 | $page = _builddocument($self, "PostScript::Simple generated page"); | 
| 926 | 0 |  |  |  |  | 0 | $doc = ""; | 
| 927 | 0 |  |  |  |  | 0 | foreach $i (@$page) { | 
| 928 | 0 | 0 |  |  |  | 0 | if (ref($i) eq "SCALAR") { | 
| 929 | 0 |  |  |  |  | 0 | $doc .= $$i; | 
| 930 |  |  |  |  |  |  | } else { | 
| 931 | 0 |  |  |  |  | 0 | $doc .= $i; | 
| 932 |  |  |  |  |  |  | } | 
| 933 |  |  |  |  |  |  | } | 
| 934 | 0 |  |  |  |  | 0 | return $doc; | 
| 935 |  |  |  |  |  |  | } | 
| 936 |  |  |  |  |  |  |  | 
| 937 |  |  |  |  |  |  |  | 
| 938 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 939 |  |  |  |  |  |  |  | 
| 940 |  |  |  |  |  |  | =item C | 
| 941 |  |  |  |  |  |  |  | 
| 942 |  |  |  |  |  |  | Returns the current document as a PostScript::Simple::EPS object. Only works if | 
| 943 |  |  |  |  |  |  | the current document is EPS. | 
| 944 |  |  |  |  |  |  |  | 
| 945 |  |  |  |  |  |  | This method calls new PostScript::Simple::EPS with all the default options. To | 
| 946 |  |  |  |  |  |  | change these, call it yourself as below, rather than using this method. | 
| 947 |  |  |  |  |  |  |  | 
| 948 |  |  |  |  |  |  | $eps = new PostScript::Simple::EPS(source => $ps->get); | 
| 949 |  |  |  |  |  |  |  | 
| 950 |  |  |  |  |  |  | =cut | 
| 951 |  |  |  |  |  |  |  | 
| 952 |  |  |  |  |  |  | sub geteps | 
| 953 |  |  |  |  |  |  | { | 
| 954 | 0 |  |  | 0 | 1 | 0 | my $self = shift; | 
| 955 | 0 |  |  |  |  | 0 | my $page; | 
| 956 |  |  |  |  |  |  | my $i; | 
| 957 | 0 |  |  |  |  | 0 | my $doc; | 
| 958 | 0 |  |  |  |  | 0 | my $eps; | 
| 959 |  |  |  |  |  |  |  | 
| 960 | 0 | 0 |  |  |  | 0 | croak "document is not EPS" unless ($$self{eps} == 1); | 
| 961 |  |  |  |  |  |  |  | 
| 962 | 0 |  |  |  |  | 0 | $eps = new PostScript::Simple::EPS(source => $self->get); | 
| 963 | 0 |  |  |  |  | 0 | return $eps; | 
| 964 |  |  |  |  |  |  | } | 
| 965 |  |  |  |  |  |  |  | 
| 966 |  |  |  |  |  |  |  | 
| 967 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 968 |  |  |  |  |  |  |  | 
| 969 |  |  |  |  |  |  | =item C | 
| 970 |  |  |  |  |  |  |  | 
| 971 |  |  |  |  |  |  | Sets the new drawing colour to the RGB values specified in C, C and | 
| 972 |  |  |  |  |  |  | C. The values range from 0 to 255. | 
| 973 |  |  |  |  |  |  |  | 
| 974 |  |  |  |  |  |  | Alternatively, a colour name may be specified. Those currently defined are | 
| 975 |  |  |  |  |  |  | listed at the top of the PostScript::Simple module in the C<%pscolours> hash | 
| 976 |  |  |  |  |  |  | and include the standard X-Windows colour names. | 
| 977 |  |  |  |  |  |  |  | 
| 978 |  |  |  |  |  |  | Example: | 
| 979 |  |  |  |  |  |  |  | 
| 980 |  |  |  |  |  |  | # set new colour to brown | 
| 981 |  |  |  |  |  |  | $p->setcolour(200,100,0); | 
| 982 |  |  |  |  |  |  | # set new colour to black | 
| 983 |  |  |  |  |  |  | $p->setcolour("black"); | 
| 984 |  |  |  |  |  |  |  | 
| 985 |  |  |  |  |  |  | =cut | 
| 986 |  |  |  |  |  |  |  | 
| 987 |  |  |  |  |  |  | sub setcolour | 
| 988 |  |  |  |  |  |  | { | 
| 989 | 53 |  |  | 53 | 1 | 317 | my $self = shift; | 
| 990 | 53 |  |  |  |  | 46 | my ($r, $g, $b) = @_; | 
| 991 |  |  |  |  |  |  |  | 
| 992 | 53 | 100 |  |  |  | 81 | if ( @_ == 1 ) { | 
| 993 | 10 |  |  |  |  | 9 | $r = lc $r; | 
| 994 | 10 | 100 |  |  |  | 23 | if (defined $pscolours{$r}) { | 
| 995 | 9 |  |  |  |  | 8 | ($r, $g, $b) = @{$pscolours{$r}}; | 
|  | 9 |  |  |  |  | 16 |  | 
| 996 |  |  |  |  |  |  | } else { | 
| 997 | 1 |  |  |  |  | 4 | $self->_error( "bad colour name '$r'" ); | 
| 998 | 1 |  |  |  |  | 3 | return 0; | 
| 999 |  |  |  |  |  |  | } | 
| 1000 |  |  |  |  |  |  | } | 
| 1001 |  |  |  |  |  |  |  | 
| 1002 | 52 |  |  |  |  | 43 | my $bad = 0; | 
| 1003 | 52 | 50 |  |  |  | 75 | if (not defined $r) { $r = 'undef'; $bad = 1; } | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 1004 | 52 | 50 |  |  |  | 78 | if (not defined $g) { $g = 'undef'; $bad = 1; } | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 1005 | 52 | 100 |  |  |  | 68 | if (not defined $b) { $b = 'undef'; $bad = 1; } | 
|  | 2 |  |  |  |  | 2 |  | 
|  | 2 |  |  |  |  | 3 |  | 
| 1006 |  |  |  |  |  |  |  | 
| 1007 | 52 | 100 |  |  |  | 60 | if ($bad) { | 
| 1008 | 2 |  |  |  |  | 14 | $self->_error( "setcolour given invalid arguments: $r, $g, $b" ); | 
| 1009 | 2 |  |  |  |  | 13 | return 0; | 
| 1010 |  |  |  |  |  |  | } | 
| 1011 |  |  |  |  |  |  |  | 
| 1012 |  |  |  |  |  |  | # make sure floats aren't too long, and means the tests pass when | 
| 1013 |  |  |  |  |  |  | # using a system with long doubles enabled by default | 
| 1014 | 50 |  |  |  |  | 259 | $r = 0 + sprintf("%0.5f", $r / 255); | 
| 1015 | 50 |  |  |  |  | 100 | $g = 0 + sprintf("%0.5f", $g / 255); | 
| 1016 | 50 |  |  |  |  | 90 | $b = 0 + sprintf("%0.5f", $b / 255); | 
| 1017 |  |  |  |  |  |  |  | 
| 1018 | 50 | 50 |  |  |  | 69 | if ($self->{colour}) { | 
| 1019 | 50 |  |  |  |  | 188 | $self->_addtopage("$r $g $b setrgbcolor\n"); | 
| 1020 |  |  |  |  |  |  | } else { | 
| 1021 |  |  |  |  |  |  | # Better colour->grey conversion than just 0.33 of each: | 
| 1022 | 0 |  |  |  |  | 0 | $r = 0.3*$r + 0.59*$g + 0.11*$b; | 
| 1023 | 0 |  |  |  |  | 0 | $r = 0 + sprintf("%0.5f", $r / 255); | 
| 1024 | 0 |  |  |  |  | 0 | $self->_addtopage("$r setgray\n"); | 
| 1025 |  |  |  |  |  |  | } | 
| 1026 |  |  |  |  |  |  |  | 
| 1027 | 50 |  |  |  |  | 78 | return 1; | 
| 1028 |  |  |  |  |  |  | } | 
| 1029 |  |  |  |  |  |  |  | 
| 1030 |  |  |  |  |  |  |  | 
| 1031 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1032 |  |  |  |  |  |  |  | 
| 1033 |  |  |  |  |  |  | =item C | 
| 1034 |  |  |  |  |  |  |  | 
| 1035 |  |  |  |  |  |  | Sets the new drawing colour to the CMYK values specified in C, | 
| 1036 |  |  |  |  |  |  | C, C. The values range from 0 to 1. Note that | 
| 1037 |  |  |  |  |  |  | PostScript::Simple does not do any colour management, so the output colour (as | 
| 1038 |  |  |  |  |  |  | also with C) may vary according to output device. | 
| 1039 |  |  |  |  |  |  |  | 
| 1040 |  |  |  |  |  |  | Example: | 
| 1041 |  |  |  |  |  |  |  | 
| 1042 |  |  |  |  |  |  | # set new colour to a shade of blue | 
| 1043 |  |  |  |  |  |  | $p->setcmykcolour(0.1, 0.5, 0, 0.2); | 
| 1044 |  |  |  |  |  |  | # set new colour to black | 
| 1045 |  |  |  |  |  |  | $p->setcmykcolour(0, 0, 0, 1); | 
| 1046 |  |  |  |  |  |  | # set new colour to a rich black | 
| 1047 |  |  |  |  |  |  | $p->setcmykcolour(0.5, 0.5, 0.5, 1); | 
| 1048 |  |  |  |  |  |  |  | 
| 1049 |  |  |  |  |  |  | =cut | 
| 1050 |  |  |  |  |  |  |  | 
| 1051 |  |  |  |  |  |  | sub setcmykcolour | 
| 1052 |  |  |  |  |  |  | { | 
| 1053 | 3 |  |  | 3 | 1 | 4 | my $self = shift; | 
| 1054 | 3 |  |  |  |  | 5 | my ($c, $m, $y, $k) = @_; | 
| 1055 |  |  |  |  |  |  |  | 
| 1056 | 3 | 100 |  |  |  | 7 | if ( @_ != 4 ) { | 
| 1057 | 2 |  |  |  |  | 5 | $self->_error( "setcmykcolour given incorrect number of arguments" ); | 
| 1058 | 2 |  |  |  |  | 6 | return 0; | 
| 1059 |  |  |  |  |  |  | } | 
| 1060 |  |  |  |  |  |  |  | 
| 1061 |  |  |  |  |  |  | # Don't currently convert to grey if colour is not set. Patches welcome for | 
| 1062 |  |  |  |  |  |  | # something that gives a reasonable approximation... | 
| 1063 |  |  |  |  |  |  |  | 
| 1064 | 1 |  |  |  |  | 14 | $self->_addtopage("$c $m $y $k setcmykcolor\n"); | 
| 1065 |  |  |  |  |  |  |  | 
| 1066 | 1 |  |  |  |  | 5 | return 1; | 
| 1067 |  |  |  |  |  |  | } | 
| 1068 |  |  |  |  |  |  |  | 
| 1069 |  |  |  |  |  |  |  | 
| 1070 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1071 |  |  |  |  |  |  |  | 
| 1072 |  |  |  |  |  |  | =item C | 
| 1073 |  |  |  |  |  |  |  | 
| 1074 |  |  |  |  |  |  | Sets the new line width to C units. | 
| 1075 |  |  |  |  |  |  |  | 
| 1076 |  |  |  |  |  |  | Example: | 
| 1077 |  |  |  |  |  |  |  | 
| 1078 |  |  |  |  |  |  | # draw a line 10mm long and 4mm wide | 
| 1079 |  |  |  |  |  |  | $p = new PostScript::Simple(units => "mm"); | 
| 1080 |  |  |  |  |  |  | $p->setlinewidth(4); | 
| 1081 |  |  |  |  |  |  | $p->line(10,10, 20,10); | 
| 1082 |  |  |  |  |  |  |  | 
| 1083 |  |  |  |  |  |  | =cut | 
| 1084 |  |  |  |  |  |  |  | 
| 1085 |  |  |  |  |  |  | sub setlinewidth | 
| 1086 |  |  |  |  |  |  | { | 
| 1087 | 5 |  |  | 5 | 1 | 10 | my $self = shift; | 
| 1088 | 5 |  | 66 |  |  | 13 | my $width = shift || do { | 
| 1089 |  |  |  |  |  |  | $self->_error( "setlinewidth not given a width" ); return 0; | 
| 1090 |  |  |  |  |  |  | }; | 
| 1091 |  |  |  |  |  |  |  | 
| 1092 | 4 | 100 |  |  |  | 9 | $width = "0.4 bp" if $width eq "thin"; | 
| 1093 |  |  |  |  |  |  |  | 
| 1094 | 4 |  |  |  |  | 9 | $self->_addtopage($self->_u($width) . "setlinewidth\n"); | 
| 1095 |  |  |  |  |  |  |  | 
| 1096 | 4 |  |  |  |  | 8 | return 1; | 
| 1097 |  |  |  |  |  |  | } | 
| 1098 |  |  |  |  |  |  |  | 
| 1099 |  |  |  |  |  |  |  | 
| 1100 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1101 |  |  |  |  |  |  |  | 
| 1102 |  |  |  |  |  |  | =item C | 
| 1103 |  |  |  |  |  |  |  | 
| 1104 |  |  |  |  |  |  | Draws a line from the co-ordinates (x1,x2) to (x2,y2). If values are specified | 
| 1105 |  |  |  |  |  |  | for C, C and C, then the colour is set before the line is drawn. | 
| 1106 |  |  |  |  |  |  |  | 
| 1107 |  |  |  |  |  |  | Example: | 
| 1108 |  |  |  |  |  |  |  | 
| 1109 |  |  |  |  |  |  | # set the colour to black | 
| 1110 |  |  |  |  |  |  | $p->setcolour("black"); | 
| 1111 |  |  |  |  |  |  |  | 
| 1112 |  |  |  |  |  |  | # draw a line in the current colour (black) | 
| 1113 |  |  |  |  |  |  | $p->line(10,10, 10,20); | 
| 1114 |  |  |  |  |  |  |  | 
| 1115 |  |  |  |  |  |  | # draw a line in red | 
| 1116 |  |  |  |  |  |  | $p->line(20,10, 20,20, 255,0,0); | 
| 1117 |  |  |  |  |  |  |  | 
| 1118 |  |  |  |  |  |  | # draw another line in red | 
| 1119 |  |  |  |  |  |  | $p->line(30,10, 30,20); | 
| 1120 |  |  |  |  |  |  |  | 
| 1121 |  |  |  |  |  |  | =cut | 
| 1122 |  |  |  |  |  |  |  | 
| 1123 |  |  |  |  |  |  | sub line | 
| 1124 |  |  |  |  |  |  | { | 
| 1125 | 13 |  |  | 13 | 1 | 33 | my $self = shift; | 
| 1126 | 13 |  |  |  |  | 16 | my ($x1, $y1, $x2, $y2, $r, $g, $b) = @_; | 
| 1127 |  |  |  |  |  |  |  | 
| 1128 | 13 | 50 | 66 |  |  | 32 | if ((!$self->{pspagecount}) and (!$self->{eps})) { | 
| 1129 |  |  |  |  |  |  | # Cannot draw on to non-page when not an eps file | 
| 1130 | 0 |  |  |  |  | 0 | return 0; | 
| 1131 |  |  |  |  |  |  | } | 
| 1132 |  |  |  |  |  |  |  | 
| 1133 | 13 | 100 |  |  |  | 36 | if ( @_ == 7 ) { | 
|  |  | 100 |  |  |  |  |  | 
| 1134 | 4 |  |  |  |  | 8 | $self->setcolour($r, $g, $b); | 
| 1135 |  |  |  |  |  |  | } elsif ( @_ != 4 ) { | 
| 1136 | 2 |  |  |  |  | 3 | $self->_error( "wrong number of args for line" ); | 
| 1137 | 2 |  |  |  |  | 28 | return 0; | 
| 1138 |  |  |  |  |  |  | } | 
| 1139 |  |  |  |  |  |  |  | 
| 1140 | 11 |  |  |  |  | 22 | $self->newpath; | 
| 1141 | 11 |  |  |  |  | 22 | $self->moveto($x1, $y1); | 
| 1142 | 11 |  |  |  |  | 16 | $self->_addtopage($self->_uxy($x2, $y2) . "lineto stroke\n"); | 
| 1143 |  |  |  |  |  |  |  | 
| 1144 | 11 |  |  |  |  | 23 | return 1; | 
| 1145 |  |  |  |  |  |  | } | 
| 1146 |  |  |  |  |  |  |  | 
| 1147 |  |  |  |  |  |  |  | 
| 1148 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1149 |  |  |  |  |  |  |  | 
| 1150 |  |  |  |  |  |  | =item C | 
| 1151 |  |  |  |  |  |  |  | 
| 1152 |  |  |  |  |  |  | Assuming the previous command was C, C, C or | 
| 1153 |  |  |  |  |  |  | C, extend that line to include another segment to the co-ordinates | 
| 1154 |  |  |  |  |  |  | (x,y). Behaviour after any other method is unspecified. | 
| 1155 |  |  |  |  |  |  |  | 
| 1156 |  |  |  |  |  |  | Example: | 
| 1157 |  |  |  |  |  |  |  | 
| 1158 |  |  |  |  |  |  | $p->line(10,10, 10,20); | 
| 1159 |  |  |  |  |  |  | $p->linextend(20,20); | 
| 1160 |  |  |  |  |  |  | $p->linextend(20,10); | 
| 1161 |  |  |  |  |  |  | $p->linextend(10,10); | 
| 1162 |  |  |  |  |  |  |  | 
| 1163 |  |  |  |  |  |  | Notes | 
| 1164 |  |  |  |  |  |  |  | 
| 1165 |  |  |  |  |  |  | The C method may be more appropriate. | 
| 1166 |  |  |  |  |  |  |  | 
| 1167 |  |  |  |  |  |  | =cut | 
| 1168 |  |  |  |  |  |  |  | 
| 1169 |  |  |  |  |  |  | sub linextend | 
| 1170 |  |  |  |  |  |  | { | 
| 1171 | 6 |  |  | 6 | 1 | 14 | my $self = shift; | 
| 1172 | 6 |  |  |  |  | 7 | my ($x, $y) = @_; | 
| 1173 |  |  |  |  |  |  |  | 
| 1174 | 6 | 100 |  |  |  | 15 | unless ( @_ == 2 ) { | 
| 1175 | 1 |  |  |  |  | 3 | $self->_error( "wrong number of args for linextend" ); | 
| 1176 | 1 |  |  |  |  | 3 | return 0; | 
| 1177 |  |  |  |  |  |  | } | 
| 1178 |  |  |  |  |  |  |  | 
| 1179 | 5 |  |  |  |  | 8 | my $out = $self->_uxy($x, $y) . "lineto stroke\n"; | 
| 1180 |  |  |  |  |  |  |  | 
| 1181 | 5 |  |  |  |  | 8 | my $p = $self->{currentpage}; | 
| 1182 | 5 |  |  |  |  | 6 | my $last = pop @$p; | 
| 1183 | 5 |  |  |  |  | 7 | $last = $$last[1]; | 
| 1184 | 5 |  |  |  |  | 29 | $last =~ s/eto stroke\n$/eto\n$out/; | 
| 1185 | 5 |  |  |  |  | 9 | $self->_addtopage($last); | 
| 1186 |  |  |  |  |  |  |  | 
| 1187 |  |  |  |  |  |  | # FIXMEFIXMEFIXME | 
| 1188 |  |  |  |  |  |  | # perhaps we need something like $self->{_lastcommand} to know if operations | 
| 1189 |  |  |  |  |  |  | # are valid, rather than using a regexp? | 
| 1190 |  |  |  |  |  |  |  | 
| 1191 | 5 |  |  |  |  | 10 | return 1; | 
| 1192 |  |  |  |  |  |  | } | 
| 1193 |  |  |  |  |  |  |  | 
| 1194 |  |  |  |  |  |  |  | 
| 1195 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1196 |  |  |  |  |  |  |  | 
| 1197 |  |  |  |  |  |  | =item C | 
| 1198 |  |  |  |  |  |  |  | 
| 1199 |  |  |  |  |  |  | Draws an arc on the circle of radius C with centre (C,C). The arc | 
| 1200 |  |  |  |  |  |  | starts at angle C and finishes at C. Angles are specified | 
| 1201 |  |  |  |  |  |  | in degrees, where 0 is at 3 o'clock, and the direction of travel is anti-clockwise. | 
| 1202 |  |  |  |  |  |  |  | 
| 1203 |  |  |  |  |  |  | Any options are passed in a hash reference as the first parameter. The available | 
| 1204 |  |  |  |  |  |  | option is: | 
| 1205 |  |  |  |  |  |  |  | 
| 1206 |  |  |  |  |  |  | =over 4 | 
| 1207 |  |  |  |  |  |  |  | 
| 1208 |  |  |  |  |  |  | =item filled => 1 | 
| 1209 |  |  |  |  |  |  |  | 
| 1210 |  |  |  |  |  |  | If C is 1 then the arc will be filled in. | 
| 1211 |  |  |  |  |  |  |  | 
| 1212 |  |  |  |  |  |  | =back | 
| 1213 |  |  |  |  |  |  |  | 
| 1214 |  |  |  |  |  |  | Example: | 
| 1215 |  |  |  |  |  |  |  | 
| 1216 |  |  |  |  |  |  | # semi-circle | 
| 1217 |  |  |  |  |  |  | $p->arc(10, 10, 5, 0, 180); | 
| 1218 |  |  |  |  |  |  |  | 
| 1219 |  |  |  |  |  |  | # complete filled circle | 
| 1220 |  |  |  |  |  |  | $p->arc({filled=>1}, 30, 30, 10, 0, 360); | 
| 1221 |  |  |  |  |  |  |  | 
| 1222 |  |  |  |  |  |  | =cut | 
| 1223 |  |  |  |  |  |  |  | 
| 1224 |  |  |  |  |  |  | sub arc | 
| 1225 |  |  |  |  |  |  | { | 
| 1226 | 0 |  |  | 0 | 1 | 0 | my $self = shift; | 
| 1227 | 0 |  |  |  |  | 0 | my %opt = (); | 
| 1228 |  |  |  |  |  |  |  | 
| 1229 | 0 | 0 |  |  |  | 0 | if (ref($_[0])) { | 
| 1230 | 0 |  |  |  |  | 0 | %opt = %{; shift}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1231 |  |  |  |  |  |  | } | 
| 1232 |  |  |  |  |  |  |  | 
| 1233 | 0 | 0 | 0 |  |  | 0 | if ((!$self->{pspagecount}) and (!$self->{eps})) { | 
| 1234 |  |  |  |  |  |  | # Cannot draw on to non-page when not an eps file | 
| 1235 | 0 |  |  |  |  | 0 | return 0; | 
| 1236 |  |  |  |  |  |  | } | 
| 1237 |  |  |  |  |  |  |  | 
| 1238 | 0 |  |  |  |  | 0 | my ($x, $y, $r, $sa, $ea) = @_; | 
| 1239 |  |  |  |  |  |  |  | 
| 1240 | 0 | 0 |  |  |  | 0 | unless (@_ == 5) { | 
| 1241 | 0 |  |  |  |  | 0 | $self->_error("arc: wrong number of arguments"); | 
| 1242 | 0 |  |  |  |  | 0 | return 0; | 
| 1243 |  |  |  |  |  |  | } | 
| 1244 |  |  |  |  |  |  |  | 
| 1245 | 0 |  |  |  |  | 0 | $self->newpath; | 
| 1246 | 0 |  |  |  |  | 0 | $self->_addtopage($self->_uxy($x, $y) . $self->_u($r) . "$sa $ea arc "); | 
| 1247 | 0 | 0 |  |  |  | 0 | if ($opt{'filled'}) { | 
| 1248 | 0 |  |  |  |  | 0 | $self->_addtopage("fill\n"); | 
| 1249 |  |  |  |  |  |  | } else { | 
| 1250 | 0 |  |  |  |  | 0 | $self->_addtopage("stroke\n"); | 
| 1251 |  |  |  |  |  |  | } | 
| 1252 |  |  |  |  |  |  |  | 
| 1253 | 0 |  |  |  |  | 0 | return 1; | 
| 1254 |  |  |  |  |  |  | } | 
| 1255 |  |  |  |  |  |  |  | 
| 1256 |  |  |  |  |  |  |  | 
| 1257 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1258 |  |  |  |  |  |  |  | 
| 1259 |  |  |  |  |  |  | =item C | 
| 1260 |  |  |  |  |  |  |  | 
| 1261 |  |  |  |  |  |  | The C method is multi-function, allowing many shapes to be created and | 
| 1262 |  |  |  |  |  |  | manipulated. Polygon draws lines from (x1,y1) to (x2,y2) and then from (x2,y2) to | 
| 1263 |  |  |  |  |  |  | (x3,y3) up to (xn-1,yn-1) to (xn,yn). | 
| 1264 |  |  |  |  |  |  |  | 
| 1265 |  |  |  |  |  |  | Any options are passed in a hash reference as the first parameter. The available | 
| 1266 |  |  |  |  |  |  | options are as follows: | 
| 1267 |  |  |  |  |  |  |  | 
| 1268 |  |  |  |  |  |  | =over 4 | 
| 1269 |  |  |  |  |  |  |  | 
| 1270 |  |  |  |  |  |  | =item rotate => angle | 
| 1271 |  |  |  |  |  |  | =item rotate => [angle,x,y] | 
| 1272 |  |  |  |  |  |  |  | 
| 1273 |  |  |  |  |  |  | Rotate the polygon by C degrees anti-clockwise. If x and y are specified | 
| 1274 |  |  |  |  |  |  | then use the co-ordinate (x,y) as the centre of rotation, otherwise use the | 
| 1275 |  |  |  |  |  |  | co-ordinate (x1,y1) from the main polygon. | 
| 1276 |  |  |  |  |  |  |  | 
| 1277 |  |  |  |  |  |  | =item filled => 1 | 
| 1278 |  |  |  |  |  |  |  | 
| 1279 |  |  |  |  |  |  | If C is 1 then the PostScript output is set to fill the object rather | 
| 1280 |  |  |  |  |  |  | than just draw the lines. | 
| 1281 |  |  |  |  |  |  |  | 
| 1282 |  |  |  |  |  |  | =item offset => [x,y] | 
| 1283 |  |  |  |  |  |  |  | 
| 1284 |  |  |  |  |  |  | Displace the object by the vector (x,y). | 
| 1285 |  |  |  |  |  |  |  | 
| 1286 |  |  |  |  |  |  | =back | 
| 1287 |  |  |  |  |  |  |  | 
| 1288 |  |  |  |  |  |  | Example: | 
| 1289 |  |  |  |  |  |  |  | 
| 1290 |  |  |  |  |  |  | # draw a square with lower left point at (10,10) | 
| 1291 |  |  |  |  |  |  | $p->polygon(10,10, 10,20, 20,20, 20,10, 10,10); | 
| 1292 |  |  |  |  |  |  |  | 
| 1293 |  |  |  |  |  |  | # draw a filled square with lower left point at (20,20) | 
| 1294 |  |  |  |  |  |  | $p->polygon( {offset => [10,10], filled => 1}, | 
| 1295 |  |  |  |  |  |  | 10,10, 10,20, 20,20, 20,10, 10,10); | 
| 1296 |  |  |  |  |  |  |  | 
| 1297 |  |  |  |  |  |  | # draw a filled square with lower left point at (10,10) | 
| 1298 |  |  |  |  |  |  | # rotated 45 degrees (about the point (10,10)) | 
| 1299 |  |  |  |  |  |  | $p->polygon( {rotate => 45, filled => 1}, | 
| 1300 |  |  |  |  |  |  | 10,10, 10,20, 20,20, 20,10, 10,10); | 
| 1301 |  |  |  |  |  |  |  | 
| 1302 |  |  |  |  |  |  | =cut | 
| 1303 |  |  |  |  |  |  |  | 
| 1304 |  |  |  |  |  |  | sub polygon | 
| 1305 |  |  |  |  |  |  | { | 
| 1306 | 27 |  |  | 27 | 1 | 94 | my $self = shift; | 
| 1307 |  |  |  |  |  |  |  | 
| 1308 | 27 |  |  |  |  | 26 | my %opt = (); | 
| 1309 | 27 |  |  |  |  | 23 | my ($xoffset, $yoffset) = (0,0); | 
| 1310 | 27 |  |  |  |  | 20 | my ($rotate, $rotatex, $rotatey) = (0,0,0); | 
| 1311 |  |  |  |  |  |  |  | 
| 1312 | 27 | 100 |  |  |  | 46 | if ($#_ < 3) { | 
| 1313 |  |  |  |  |  |  | # cannot have polygon with just one point... | 
| 1314 | 1 |  |  |  |  | 2 | $self->_error( "bad polygon - not enough points" ); | 
| 1315 | 1 |  |  |  |  | 4 | return 0; | 
| 1316 |  |  |  |  |  |  | } | 
| 1317 |  |  |  |  |  |  |  | 
| 1318 | 26 | 100 |  |  |  | 43 | if (ref($_[0])) { | 
| 1319 | 24 |  |  |  |  | 16 | %opt = %{; shift}; | 
|  | 24 |  |  |  |  | 53 |  | 
| 1320 |  |  |  |  |  |  | } | 
| 1321 |  |  |  |  |  |  |  | 
| 1322 | 26 |  |  |  |  | 22 | my $x = shift; | 
| 1323 | 26 |  |  |  |  | 18 | my $y = shift; | 
| 1324 |  |  |  |  |  |  |  | 
| 1325 | 26 | 100 |  |  |  | 45 | if (defined $opt{'rotate'}) { | 
| 1326 | 22 | 100 |  |  |  | 29 | if (ref($opt{'rotate'})) { | 
| 1327 | 20 |  |  |  |  | 15 | ($rotate, $rotatex, $rotatey) = @{$opt{'rotate'}}; | 
|  | 20 |  |  |  |  | 26 |  | 
| 1328 |  |  |  |  |  |  | } else { | 
| 1329 | 2 |  |  |  |  | 4 | ($rotate, $rotatex, $rotatey) = ($opt{'rotate'}, $x, $y); | 
| 1330 |  |  |  |  |  |  | } | 
| 1331 |  |  |  |  |  |  | } | 
| 1332 |  |  |  |  |  |  |  | 
| 1333 | 26 | 100 |  |  |  | 44 | if (defined $opt{'offset'}) { | 
| 1334 | 21 | 50 |  |  |  | 21 | if (ref($opt{'offset'})) { | 
| 1335 | 21 |  |  |  |  | 14 | ($xoffset, $yoffset) = @{$opt{'offset'}}; | 
|  | 21 |  |  |  |  | 19 |  | 
| 1336 |  |  |  |  |  |  | } else { | 
| 1337 | 0 |  |  |  |  | 0 | $self->_error("polygon: bad offset option" ); | 
| 1338 | 0 |  |  |  |  | 0 | return 0; | 
| 1339 |  |  |  |  |  |  | } | 
| 1340 |  |  |  |  |  |  | } | 
| 1341 |  |  |  |  |  |  |  | 
| 1342 | 26 | 100 |  |  |  | 47 | if (!defined $opt{'filled'}) { | 
| 1343 | 6 |  |  |  |  | 8 | $opt{'filled'} = 0; | 
| 1344 |  |  |  |  |  |  | } | 
| 1345 |  |  |  |  |  |  |  | 
| 1346 | 26 | 50 | 33 |  |  | 81 | unless (defined($x) && defined($y)) { | 
| 1347 | 0 |  |  |  |  | 0 | $self->_error("polygon: no start point"); | 
| 1348 | 0 |  |  |  |  | 0 | return 0; | 
| 1349 |  |  |  |  |  |  | } | 
| 1350 |  |  |  |  |  |  |  | 
| 1351 | 26 | 100 | 100 |  |  | 103 | my $savestate = ($xoffset || $yoffset || $rotate) ? 1 : 0 ; | 
| 1352 |  |  |  |  |  |  |  | 
| 1353 | 26 | 100 |  |  |  | 33 | if ( $savestate ) { | 
| 1354 | 23 |  |  |  |  | 27 | $self->_addtopage("gsave "); | 
| 1355 |  |  |  |  |  |  | } | 
| 1356 |  |  |  |  |  |  |  | 
| 1357 | 26 | 100 | 66 |  |  | 76 | if ($xoffset || $yoffset) { | 
| 1358 | 3 |  |  |  |  | 5 | $self->_addtopage($self->_uxy($xoffset, $yoffset) . "translate\n"); | 
| 1359 |  |  |  |  |  |  | } | 
| 1360 |  |  |  |  |  |  |  | 
| 1361 | 26 | 100 |  |  |  | 34 | if ($rotate) { | 
| 1362 | 21 | 100 |  |  |  | 35 | unless (defined $self->{psresources}{rotabout}) { | 
| 1363 | 3 |  |  |  |  | 6 | $self->{psresources}{rotabout} = <<'EOP'; | 
| 1364 |  |  |  |  |  |  | /rotabout { | 
| 1365 |  |  |  |  |  |  | 3 copy pop translate rotate exch | 
| 1366 |  |  |  |  |  |  | 0 exch sub exch 0 exch sub translate | 
| 1367 |  |  |  |  |  |  | } def | 
| 1368 |  |  |  |  |  |  | EOP | 
| 1369 |  |  |  |  |  |  | } | 
| 1370 |  |  |  |  |  |  |  | 
| 1371 | 21 |  |  |  |  | 27 | $self->_addtopage($self->_uxy($rotatex, $rotatey) . "$rotate rotabout\n"); | 
| 1372 |  |  |  |  |  |  | } | 
| 1373 |  |  |  |  |  |  |  | 
| 1374 | 26 |  |  |  |  | 37 | $self->newpath; | 
| 1375 | 26 |  |  |  |  | 29 | $self->moveto($x, $y); | 
| 1376 |  |  |  |  |  |  |  | 
| 1377 | 26 |  |  |  |  | 45 | while ($#_ > 0) { | 
| 1378 | 63 |  |  |  |  | 43 | my $x = shift; | 
| 1379 | 63 |  |  |  |  | 81 | my $y = shift; | 
| 1380 |  |  |  |  |  |  |  | 
| 1381 | 63 |  |  |  |  | 69 | $self->_addtopage($self->_uxy($x, $y) . "lineto "); | 
| 1382 |  |  |  |  |  |  | } | 
| 1383 |  |  |  |  |  |  |  | 
| 1384 | 26 | 100 |  |  |  | 45 | if ($opt{'filled'}) { | 
| 1385 | 2 |  |  |  |  | 4 | $self->_addtopage("fill\n"); | 
| 1386 |  |  |  |  |  |  | } else { | 
| 1387 | 24 |  |  |  |  | 27 | $self->_addtopage("stroke\n"); | 
| 1388 |  |  |  |  |  |  | } | 
| 1389 |  |  |  |  |  |  |  | 
| 1390 | 26 | 100 |  |  |  | 44 | if ( $savestate ) { | 
| 1391 | 23 |  |  |  |  | 33 | $self->_addtopage("grestore\n"); | 
| 1392 |  |  |  |  |  |  | } | 
| 1393 |  |  |  |  |  |  |  | 
| 1394 | 26 |  |  |  |  | 71 | return 1; | 
| 1395 |  |  |  |  |  |  | } | 
| 1396 |  |  |  |  |  |  |  | 
| 1397 |  |  |  |  |  |  |  | 
| 1398 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1399 |  |  |  |  |  |  |  | 
| 1400 |  |  |  |  |  |  | =item C | 
| 1401 |  |  |  |  |  |  |  | 
| 1402 |  |  |  |  |  |  | Plot a circle with centre at (x,y) and radius of r. | 
| 1403 |  |  |  |  |  |  |  | 
| 1404 |  |  |  |  |  |  | There is only one option. | 
| 1405 |  |  |  |  |  |  |  | 
| 1406 |  |  |  |  |  |  | =over 4 | 
| 1407 |  |  |  |  |  |  |  | 
| 1408 |  |  |  |  |  |  | =item filled => 1 | 
| 1409 |  |  |  |  |  |  |  | 
| 1410 |  |  |  |  |  |  | If C is 1 then the PostScript output is set to fill the object rather | 
| 1411 |  |  |  |  |  |  | than just draw the lines. | 
| 1412 |  |  |  |  |  |  |  | 
| 1413 |  |  |  |  |  |  | =back | 
| 1414 |  |  |  |  |  |  |  | 
| 1415 |  |  |  |  |  |  | Example: | 
| 1416 |  |  |  |  |  |  |  | 
| 1417 |  |  |  |  |  |  | $p->circle(40,40, 20); | 
| 1418 |  |  |  |  |  |  | $p->circle( {filled => 1}, 62,31, 15); | 
| 1419 |  |  |  |  |  |  |  | 
| 1420 |  |  |  |  |  |  | =cut | 
| 1421 |  |  |  |  |  |  |  | 
| 1422 |  |  |  |  |  |  | sub circle | 
| 1423 |  |  |  |  |  |  | { | 
| 1424 | 6 |  |  | 6 | 1 | 17 | my $self = shift; | 
| 1425 | 6 |  |  |  |  | 9 | my %opt = (); | 
| 1426 |  |  |  |  |  |  |  | 
| 1427 | 6 | 100 |  |  |  | 15 | if (ref($_[0])) { | 
| 1428 | 2 |  |  |  |  | 2 | %opt = %{; shift}; | 
|  | 2 |  |  |  |  | 6 |  | 
| 1429 |  |  |  |  |  |  | } | 
| 1430 |  |  |  |  |  |  |  | 
| 1431 | 6 |  |  |  |  | 11 | my ($x, $y, $r) = @_; | 
| 1432 |  |  |  |  |  |  |  | 
| 1433 | 6 | 100 |  |  |  | 15 | unless (@_ == 3) { | 
| 1434 | 2 |  |  |  |  | 5 | $self->_error("circle: wrong number of arguments"); | 
| 1435 | 2 |  |  |  |  | 7 | return 0; | 
| 1436 |  |  |  |  |  |  | } | 
| 1437 |  |  |  |  |  |  |  | 
| 1438 | 4 | 100 |  |  |  | 11 | unless (defined $self->{psresources}{circle}) { | 
| 1439 | 3 |  |  |  |  | 10 | $self->{psresources}{circle} = "/circle {newpath 0 360 arc closepath} bind def\n"; | 
| 1440 |  |  |  |  |  |  | } | 
| 1441 |  |  |  |  |  |  |  | 
| 1442 | 4 |  |  |  |  | 11 | $self->_addtopage($self->_uxy($x, $y) . $self->_u($r) . "circle "); | 
| 1443 | 4 | 100 |  |  |  | 11 | if ($opt{'filled'}) { | 
| 1444 | 2 |  |  |  |  | 3 | $self->_addtopage("fill\n"); | 
| 1445 |  |  |  |  |  |  | } else { | 
| 1446 | 2 |  |  |  |  | 4 | $self->_addtopage("stroke\n"); | 
| 1447 |  |  |  |  |  |  | } | 
| 1448 |  |  |  |  |  |  |  | 
| 1449 | 4 |  |  |  |  | 10 | return 1; | 
| 1450 |  |  |  |  |  |  | } | 
| 1451 |  |  |  |  |  |  |  | 
| 1452 |  |  |  |  |  |  |  | 
| 1453 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1454 |  |  |  |  |  |  |  | 
| 1455 |  |  |  |  |  |  | =item C | 
| 1456 |  |  |  |  |  |  |  | 
| 1457 |  |  |  |  |  |  | Draw text in an arc centered about angle C with circle midpoint (C,C) | 
| 1458 |  |  |  |  |  |  | and radius C. | 
| 1459 |  |  |  |  |  |  |  | 
| 1460 |  |  |  |  |  |  | There is only one option. | 
| 1461 |  |  |  |  |  |  |  | 
| 1462 |  |  |  |  |  |  | =over 4 | 
| 1463 |  |  |  |  |  |  |  | 
| 1464 |  |  |  |  |  |  | =item align => "alignment" | 
| 1465 |  |  |  |  |  |  |  | 
| 1466 |  |  |  |  |  |  | C can be 'inside' or 'outside'. The default is 'inside'. | 
| 1467 |  |  |  |  |  |  |  | 
| 1468 |  |  |  |  |  |  | =back | 
| 1469 |  |  |  |  |  |  |  | 
| 1470 |  |  |  |  |  |  | Example: | 
| 1471 |  |  |  |  |  |  |  | 
| 1472 |  |  |  |  |  |  | # outside the radius, centered at 90 degrees from the origin | 
| 1473 |  |  |  |  |  |  | $p->circletext(40, 40, 20, 90, "Hello, Outside World!"); | 
| 1474 |  |  |  |  |  |  | # inside the radius centered at 270 degrees from the origin | 
| 1475 |  |  |  |  |  |  | $p->circletext( {align => "inside"}, 40, 40, 20, 270, "Hello, Inside World!"); | 
| 1476 |  |  |  |  |  |  |  | 
| 1477 |  |  |  |  |  |  | =cut | 
| 1478 |  |  |  |  |  |  |  | 
| 1479 |  |  |  |  |  |  | sub circletext | 
| 1480 |  |  |  |  |  |  | { | 
| 1481 | 0 |  |  | 0 | 1 | 0 | my $self = shift; | 
| 1482 | 0 |  |  |  |  | 0 | my %opt = (); | 
| 1483 |  |  |  |  |  |  |  | 
| 1484 | 0 | 0 |  |  |  | 0 | if (ref($_[0])) { | 
| 1485 | 0 |  |  |  |  | 0 | %opt = %{; shift}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1486 |  |  |  |  |  |  | } | 
| 1487 |  |  |  |  |  |  |  | 
| 1488 | 0 |  |  |  |  | 0 | my ($x, $y, $r, $a, $text) = @_; | 
| 1489 |  |  |  |  |  |  |  | 
| 1490 | 0 | 0 |  |  |  | 0 | unless (@_ == 5) { | 
| 1491 | 0 |  |  |  |  | 0 | $self->_error("circletext: wrong number of arguments"); | 
| 1492 | 0 |  |  |  |  | 0 | return 0; | 
| 1493 |  |  |  |  |  |  | } | 
| 1494 |  |  |  |  |  |  |  | 
| 1495 | 0 | 0 |  |  |  | 0 | unless (defined $self->{lastfontsize}) { | 
| 1496 | 0 |  |  |  |  | 0 | $self->_error("circletext: must set font first"); | 
| 1497 | 0 |  |  |  |  | 0 | return 0; | 
| 1498 |  |  |  |  |  |  | } | 
| 1499 |  |  |  |  |  |  |  | 
| 1500 | 0 | 0 |  |  |  | 0 | unless (defined $self->{psresources}{circletext}) { | 
| 1501 | 0 |  |  |  |  | 0 | $self->{psresources}{circletext} = <<'EOP'; | 
| 1502 |  |  |  |  |  |  | /outsidecircletext | 
| 1503 |  |  |  |  |  |  | { $circtextdict begin | 
| 1504 |  |  |  |  |  |  | /radius exch def | 
| 1505 |  |  |  |  |  |  | /centerangle exch def | 
| 1506 |  |  |  |  |  |  | /ptsize exch def | 
| 1507 |  |  |  |  |  |  | /str exch def | 
| 1508 |  |  |  |  |  |  | /xradius radius ptsize 4 div add def | 
| 1509 |  |  |  |  |  |  | gsave | 
| 1510 |  |  |  |  |  |  | centerangle str findhalfangle add rotate | 
| 1511 |  |  |  |  |  |  | str { /charcode exch def ( ) dup 0 charcode put outsideshowcharandrotate } forall | 
| 1512 |  |  |  |  |  |  | grestore | 
| 1513 |  |  |  |  |  |  | end | 
| 1514 |  |  |  |  |  |  | } def | 
| 1515 |  |  |  |  |  |  |  | 
| 1516 |  |  |  |  |  |  | /insidecircletext | 
| 1517 |  |  |  |  |  |  | { $circtextdict begin | 
| 1518 |  |  |  |  |  |  | /radius exch def | 
| 1519 |  |  |  |  |  |  | /centerangle exch def | 
| 1520 |  |  |  |  |  |  | /ptsize exch def | 
| 1521 |  |  |  |  |  |  | /str exch def | 
| 1522 |  |  |  |  |  |  | /xradius radius ptsize 3 div sub def | 
| 1523 |  |  |  |  |  |  | gsave | 
| 1524 |  |  |  |  |  |  | centerangle str findhalfangle sub rotate | 
| 1525 |  |  |  |  |  |  | str { /charcode exch def ( ) dup 0 charcode put insideshowcharandrotate } forall | 
| 1526 |  |  |  |  |  |  | grestore | 
| 1527 |  |  |  |  |  |  | end | 
| 1528 |  |  |  |  |  |  | } def | 
| 1529 |  |  |  |  |  |  | /$circtextdict 16 dict def | 
| 1530 |  |  |  |  |  |  | $circtextdict begin | 
| 1531 |  |  |  |  |  |  | /findhalfangle | 
| 1532 |  |  |  |  |  |  | { stringwidth pop 2 div 2 xradius mul pi mul div 360 mul | 
| 1533 |  |  |  |  |  |  | } def | 
| 1534 |  |  |  |  |  |  | /outsideshowcharandrotate | 
| 1535 |  |  |  |  |  |  | { /char exch def | 
| 1536 |  |  |  |  |  |  | /halfangle char findhalfangle def | 
| 1537 |  |  |  |  |  |  | gsave | 
| 1538 |  |  |  |  |  |  | halfangle neg rotate radius 0 translate -90 rotate | 
| 1539 |  |  |  |  |  |  | char stringwidth pop 2 div neg 0 moveto char show | 
| 1540 |  |  |  |  |  |  | grestore | 
| 1541 |  |  |  |  |  |  | halfangle 2 mul neg rotate | 
| 1542 |  |  |  |  |  |  | } def | 
| 1543 |  |  |  |  |  |  | /insideshowcharandrotate | 
| 1544 |  |  |  |  |  |  | { /char exch def | 
| 1545 |  |  |  |  |  |  | /halfangle char findhalfangle def | 
| 1546 |  |  |  |  |  |  | gsave | 
| 1547 |  |  |  |  |  |  | halfangle rotate radius 0 translate 90 rotate | 
| 1548 |  |  |  |  |  |  | char stringwidth pop 2 div neg 0 moveto char show | 
| 1549 |  |  |  |  |  |  | grestore | 
| 1550 |  |  |  |  |  |  | halfangle 2 mul rotate | 
| 1551 |  |  |  |  |  |  | } def | 
| 1552 |  |  |  |  |  |  | /pi 3.1415926 def | 
| 1553 |  |  |  |  |  |  | end | 
| 1554 |  |  |  |  |  |  | EOP | 
| 1555 |  |  |  |  |  |  | } | 
| 1556 |  |  |  |  |  |  |  | 
| 1557 | 0 |  |  |  |  | 0 | $self->_addtopage("gsave\n"); | 
| 1558 | 0 |  |  |  |  | 0 | $self->_addtopage("  " . $self->_uxy($x, $y) . "translate\n"); | 
| 1559 | 0 |  |  |  |  | 0 | $self->_addtopage("  ($text) $self->{lastfontsize} $a " . $self->_u($r)); | 
| 1560 | 0 | 0 | 0 |  |  | 0 | if ($opt{'align'} && ($opt{'align'} eq "outside")) { | 
| 1561 | 0 |  |  |  |  | 0 | $self->_addtopage("outsidecircletext\n"); | 
| 1562 |  |  |  |  |  |  | } else { | 
| 1563 | 0 |  |  |  |  | 0 | $self->_addtopage("insidecircletext\n"); | 
| 1564 |  |  |  |  |  |  | } | 
| 1565 | 0 |  |  |  |  | 0 | $self->_addtopage("grestore\n"); | 
| 1566 |  |  |  |  |  |  |  | 
| 1567 | 0 |  |  |  |  | 0 | return 1; | 
| 1568 |  |  |  |  |  |  | } | 
| 1569 |  |  |  |  |  |  |  | 
| 1570 |  |  |  |  |  |  |  | 
| 1571 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1572 |  |  |  |  |  |  |  | 
| 1573 |  |  |  |  |  |  | =item C | 
| 1574 |  |  |  |  |  |  |  | 
| 1575 |  |  |  |  |  |  | Draw a rectangle from lower left co-ordinates (x1,y1) to upper right | 
| 1576 |  |  |  |  |  |  | co-ordinates (y1,y2). | 
| 1577 |  |  |  |  |  |  |  | 
| 1578 |  |  |  |  |  |  | Options are: | 
| 1579 |  |  |  |  |  |  |  | 
| 1580 |  |  |  |  |  |  | =over 4 | 
| 1581 |  |  |  |  |  |  |  | 
| 1582 |  |  |  |  |  |  | =item filled => 1 | 
| 1583 |  |  |  |  |  |  |  | 
| 1584 |  |  |  |  |  |  | If C is 1 then fill the rectangle. | 
| 1585 |  |  |  |  |  |  |  | 
| 1586 |  |  |  |  |  |  | =back | 
| 1587 |  |  |  |  |  |  |  | 
| 1588 |  |  |  |  |  |  | Example: | 
| 1589 |  |  |  |  |  |  |  | 
| 1590 |  |  |  |  |  |  | $p->box(10,10, 20,30); | 
| 1591 |  |  |  |  |  |  | $p->box( {filled => 1}, 10,10, 20,30); | 
| 1592 |  |  |  |  |  |  |  | 
| 1593 |  |  |  |  |  |  | Notes | 
| 1594 |  |  |  |  |  |  |  | 
| 1595 |  |  |  |  |  |  | The C method is far more flexible, but this method is quicker! | 
| 1596 |  |  |  |  |  |  |  | 
| 1597 |  |  |  |  |  |  | =cut | 
| 1598 |  |  |  |  |  |  |  | 
| 1599 |  |  |  |  |  |  | sub box | 
| 1600 |  |  |  |  |  |  | { | 
| 1601 | 41 |  |  | 41 | 1 | 113 | my $self = shift; | 
| 1602 |  |  |  |  |  |  |  | 
| 1603 | 41 |  |  |  |  | 39 | my %opt = (); | 
| 1604 |  |  |  |  |  |  |  | 
| 1605 | 41 | 100 |  |  |  | 64 | if (ref($_[0])) { | 
| 1606 | 36 |  |  |  |  | 20 | %opt = %{; shift}; | 
|  | 36 |  |  |  |  | 59 |  | 
| 1607 |  |  |  |  |  |  | } | 
| 1608 |  |  |  |  |  |  |  | 
| 1609 | 41 |  |  |  |  | 41 | my ($x1, $y1, $x2, $y2) = @_; | 
| 1610 |  |  |  |  |  |  |  | 
| 1611 | 41 | 100 |  |  |  | 61 | unless (@_ == 4) { | 
| 1612 | 1 |  |  |  |  | 3 | $self->_error("box: wrong number of arguments"); | 
| 1613 | 1 |  |  |  |  | 5 | return 0; | 
| 1614 |  |  |  |  |  |  | } | 
| 1615 |  |  |  |  |  |  |  | 
| 1616 | 40 | 100 |  |  |  | 61 | if (!defined($opt{'filled'})) { | 
| 1617 | 4 |  |  |  |  | 8 | $opt{'filled'} = 0; | 
| 1618 |  |  |  |  |  |  | } | 
| 1619 |  |  |  |  |  |  |  | 
| 1620 | 40 | 100 |  |  |  | 56 | unless (defined $self->{psresources}{box}) { | 
| 1621 | 4 |  |  |  |  | 9 | $self->{psresources}{box} = <<'EOP'; | 
| 1622 |  |  |  |  |  |  | /box { | 
| 1623 |  |  |  |  |  |  | newpath 3 copy pop exch 4 copy pop pop | 
| 1624 |  |  |  |  |  |  | 8 copy pop pop pop pop exch pop exch | 
| 1625 |  |  |  |  |  |  | 3 copy pop pop exch moveto lineto | 
| 1626 |  |  |  |  |  |  | lineto lineto pop pop pop pop closepath | 
| 1627 |  |  |  |  |  |  | } bind def | 
| 1628 |  |  |  |  |  |  | EOP | 
| 1629 |  |  |  |  |  |  | } | 
| 1630 |  |  |  |  |  |  |  | 
| 1631 | 40 |  |  |  |  | 48 | $self->_addtopage($self->_uxy($x1, $y1)); | 
| 1632 | 40 |  |  |  |  | 57 | $self->_addtopage($self->_uxy($x2, $y2) . "box "); | 
| 1633 | 40 | 100 |  |  |  | 62 | if ($opt{'filled'}) { | 
| 1634 | 36 |  |  |  |  | 40 | $self->_addtopage("fill\n"); | 
| 1635 |  |  |  |  |  |  | } else { | 
| 1636 | 4 |  |  |  |  | 21 | $self->_addtopage("stroke\n"); | 
| 1637 |  |  |  |  |  |  | } | 
| 1638 |  |  |  |  |  |  |  | 
| 1639 | 40 |  |  |  |  | 84 | return 1; | 
| 1640 |  |  |  |  |  |  | } | 
| 1641 |  |  |  |  |  |  |  | 
| 1642 |  |  |  |  |  |  |  | 
| 1643 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1644 |  |  |  |  |  |  |  | 
| 1645 |  |  |  |  |  |  | =item C | 
| 1646 |  |  |  |  |  |  |  | 
| 1647 |  |  |  |  |  |  | Set the current font to the PostScript font C. Set the size in PostScript | 
| 1648 |  |  |  |  |  |  | points to C. | 
| 1649 |  |  |  |  |  |  |  | 
| 1650 |  |  |  |  |  |  | Notes | 
| 1651 |  |  |  |  |  |  |  | 
| 1652 |  |  |  |  |  |  | This method must be called on every page before the C method is used. | 
| 1653 |  |  |  |  |  |  |  | 
| 1654 |  |  |  |  |  |  | =cut | 
| 1655 |  |  |  |  |  |  |  | 
| 1656 |  |  |  |  |  |  | sub setfont | 
| 1657 |  |  |  |  |  |  | { | 
| 1658 | 4 |  |  | 4 | 1 | 14 | my $self = shift; | 
| 1659 | 4 |  |  |  |  | 7 | my ($name, $size, $ysize) = @_; | 
| 1660 |  |  |  |  |  |  |  | 
| 1661 | 4 | 100 |  |  |  | 15 | unless (@_ == 2) { | 
| 1662 | 1 |  |  |  |  | 3 | $self->_error( "wrong number of arguments for setfont" ); | 
| 1663 | 1 |  |  |  |  | 5 | return 0; | 
| 1664 |  |  |  |  |  |  | } | 
| 1665 |  |  |  |  |  |  |  | 
| 1666 |  |  |  |  |  |  | # set font y size XXXXX | 
| 1667 | 3 |  |  |  |  | 17 | $self->_addtopage("/$name findfont $size scalefont setfont\n"); | 
| 1668 |  |  |  |  |  |  |  | 
| 1669 | 3 |  |  |  |  | 7 | $self->{lastfontsize} = $size; | 
| 1670 |  |  |  |  |  |  |  | 
| 1671 | 3 |  |  |  |  | 7 | return 1; | 
| 1672 |  |  |  |  |  |  | } | 
| 1673 |  |  |  |  |  |  |  | 
| 1674 |  |  |  |  |  |  |  | 
| 1675 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1676 |  |  |  |  |  |  |  | 
| 1677 |  |  |  |  |  |  | =item C | 
| 1678 |  |  |  |  |  |  |  | 
| 1679 |  |  |  |  |  |  | Plot text on the current page with the lower left co-ordinates at (x,y) and | 
| 1680 |  |  |  |  |  |  | using the current font. The text is specified in C. | 
| 1681 |  |  |  |  |  |  |  | 
| 1682 |  |  |  |  |  |  | Options are: | 
| 1683 |  |  |  |  |  |  |  | 
| 1684 |  |  |  |  |  |  | =over 4 | 
| 1685 |  |  |  |  |  |  |  | 
| 1686 |  |  |  |  |  |  | =item align => "alignment" | 
| 1687 |  |  |  |  |  |  |  | 
| 1688 |  |  |  |  |  |  | alignment can be 'left', 'centre' or 'right'. The default is 'left'. | 
| 1689 |  |  |  |  |  |  |  | 
| 1690 |  |  |  |  |  |  | =item rotate => angle | 
| 1691 |  |  |  |  |  |  |  | 
| 1692 |  |  |  |  |  |  | "rotate" degrees of rotation, defaults to 0 (i.e. no rotation). | 
| 1693 |  |  |  |  |  |  | The angle to rotate the text, in degrees. Centres about (x,y) and rotates | 
| 1694 |  |  |  |  |  |  | clockwise. (?). Default 0 degrees. | 
| 1695 |  |  |  |  |  |  |  | 
| 1696 |  |  |  |  |  |  | =back | 
| 1697 |  |  |  |  |  |  |  | 
| 1698 |  |  |  |  |  |  | Example: | 
| 1699 |  |  |  |  |  |  |  | 
| 1700 |  |  |  |  |  |  | $p->setfont("Times-Roman", 12); | 
| 1701 |  |  |  |  |  |  | $p->text(40,40, "The frog sat on the leaf in the pond."); | 
| 1702 |  |  |  |  |  |  | $p->text( {align => 'centre'}, 140,40, "This is centered."); | 
| 1703 |  |  |  |  |  |  | $p->text( {rotate => 90}, 140,40, "This is rotated."); | 
| 1704 |  |  |  |  |  |  | $p->text( {rotate => 90, align => 'centre'}, 140,40, "This is both."); | 
| 1705 |  |  |  |  |  |  |  | 
| 1706 |  |  |  |  |  |  | =cut | 
| 1707 |  |  |  |  |  |  |  | 
| 1708 |  |  |  |  |  |  | sub text | 
| 1709 |  |  |  |  |  |  | { | 
| 1710 | 19 |  |  | 19 | 1 | 124 | my $self = shift; | 
| 1711 |  |  |  |  |  |  |  | 
| 1712 | 19 |  |  |  |  | 19 | my $rot = ""; | 
| 1713 | 19 |  |  |  |  | 16 | my $rot_m = ""; | 
| 1714 | 19 |  |  |  |  | 19 | my $align = ""; | 
| 1715 | 19 |  |  |  |  | 28 | my %opt = (); | 
| 1716 |  |  |  |  |  |  |  | 
| 1717 | 19 | 100 |  |  |  | 34 | if (ref($_[0])) { | 
| 1718 | 5 |  |  |  |  | 6 | %opt = %{; shift}; | 
|  | 5 |  |  |  |  | 20 |  | 
| 1719 |  |  |  |  |  |  | } | 
| 1720 |  |  |  |  |  |  |  | 
| 1721 | 19 | 100 |  |  |  | 37 | unless ( @_ == 3 ) | 
| 1722 |  |  |  |  |  |  | { # check required params first | 
| 1723 | 2 |  |  |  |  | 3 | $self->_error("text: wrong number of arguments"); | 
| 1724 | 2 |  |  |  |  | 7 | return 0; | 
| 1725 |  |  |  |  |  |  | } | 
| 1726 |  |  |  |  |  |  |  | 
| 1727 | 17 |  |  |  |  | 17 | my ($x, $y, $text) = @_; | 
| 1728 |  |  |  |  |  |  |  | 
| 1729 | 17 | 100 | 33 |  |  | 97 | unless (defined($x) && defined($y) && defined($text)) { | 
|  |  |  | 66 |  |  |  |  | 
| 1730 | 1 |  |  |  |  | 4 | $self->_error("text: wrong number of arguments"); | 
| 1731 | 1 |  |  |  |  | 2 | return 0; | 
| 1732 |  |  |  |  |  |  | } | 
| 1733 |  |  |  |  |  |  |  | 
| 1734 |  |  |  |  |  |  | # Escape text to allow parentheses | 
| 1735 | 16 |  |  |  |  | 38 | $text =~ s|([\\\(\)])|\\$1|g; | 
| 1736 | 16 |  |  |  |  | 24 | $text =~ s/([\x00-\x1f\x7f-\xff])/sprintf('\\%03o',ord($1))/ge; | 
|  | 66 |  |  |  |  | 95 |  | 
| 1737 |  |  |  |  |  |  |  | 
| 1738 | 16 |  |  |  |  | 27 | $self->newpath; | 
| 1739 | 16 |  |  |  |  | 21 | $self->moveto($x, $y); | 
| 1740 |  |  |  |  |  |  |  | 
| 1741 |  |  |  |  |  |  | # rotation | 
| 1742 |  |  |  |  |  |  |  | 
| 1743 | 16 | 100 |  |  |  | 32 | if (defined $opt{'rotate'}) { | 
| 1744 | 3 |  |  |  |  | 6 | my $rot_a = $opt{ 'rotate' }; | 
| 1745 | 3 | 50 |  |  |  | 13 | if( $rot_a != 0 ) { | 
| 1746 | 3 |  |  |  |  | 10 | $rot   = " $rot_a rotate "; | 
| 1747 | 3 |  |  |  |  | 4 | $rot_a = -$rot_a; | 
| 1748 | 3 |  |  |  |  | 9 | $rot_m = " $rot_a rotate "; | 
| 1749 |  |  |  |  |  |  | }; | 
| 1750 |  |  |  |  |  |  | } | 
| 1751 |  |  |  |  |  |  |  | 
| 1752 |  |  |  |  |  |  | # alignment | 
| 1753 |  |  |  |  |  |  |  | 
| 1754 | 16 |  |  |  |  | 14 | $align = " show stroke"; | 
| 1755 | 16 | 100 |  |  |  | 28 | if (defined $opt{'align'}) { | 
| 1756 |  |  |  |  |  |  | $align = " dup stringwidth pop neg 0 rmoveto show" | 
| 1757 | 3 | 100 |  |  |  | 6 | if $opt{ 'align' } eq 'right'; | 
| 1758 |  |  |  |  |  |  | $align = " dup stringwidth pop 2 div neg 0 rmoveto show" | 
| 1759 | 3 | 100 | 66 |  |  | 19 | if $opt{ 'align' } eq 'center' or $opt{ 'align' } eq 'centre'; | 
| 1760 |  |  |  |  |  |  | } | 
| 1761 |  |  |  |  |  |  |  | 
| 1762 | 16 |  |  |  |  | 48 | $self->_addtopage("($text) $rot $align $rot_m\n"); | 
| 1763 |  |  |  |  |  |  |  | 
| 1764 | 16 |  |  |  |  | 34 | return 1; | 
| 1765 |  |  |  |  |  |  | } | 
| 1766 |  |  |  |  |  |  |  | 
| 1767 |  |  |  |  |  |  |  | 
| 1768 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1769 |  |  |  |  |  |  |  | 
| 1770 |  |  |  |  |  |  | =item curve( x1, y1, x2, y2, x3, y3, x4, y4 ) | 
| 1771 |  |  |  |  |  |  |  | 
| 1772 |  |  |  |  |  |  | Create a curve from (x1, y1) to (x4, y4). (x2, y2) and (x3, y3) are the | 
| 1773 |  |  |  |  |  |  | control points for the start- and end-points respectively. | 
| 1774 |  |  |  |  |  |  |  | 
| 1775 |  |  |  |  |  |  | =cut | 
| 1776 |  |  |  |  |  |  |  | 
| 1777 |  |  |  |  |  |  | sub curve | 
| 1778 |  |  |  |  |  |  | { | 
| 1779 | 2 |  |  | 2 | 1 | 3 | my $self = shift; | 
| 1780 | 2 |  |  |  |  | 4 | my ($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4) = @_; | 
| 1781 |  |  |  |  |  |  |  | 
| 1782 | 2 | 100 |  |  |  | 9 | unless ( @_ == 8 ) { | 
| 1783 | 1 |  |  |  |  | 8 | $self->_error( "bad curve definition, wrong number of args" ); | 
| 1784 | 1 |  |  |  |  | 3 | return 0; | 
| 1785 |  |  |  |  |  |  | } | 
| 1786 |  |  |  |  |  |  |  | 
| 1787 | 1 | 50 | 33 |  |  | 9 | if ((!$self->{pspagecount}) and (!$self->{eps})) { | 
| 1788 |  |  |  |  |  |  | # Cannot draw on to non-page when not an eps file | 
| 1789 | 0 |  |  |  |  | 0 | return 0; | 
| 1790 |  |  |  |  |  |  | } | 
| 1791 |  |  |  |  |  |  |  | 
| 1792 | 1 |  |  |  |  | 4 | $self->newpath; | 
| 1793 | 1 |  |  |  |  | 3 | $self->moveto($x1, $y1); | 
| 1794 | 1 |  |  |  |  | 3 | $self->_addtopage($self->_uxy($x2, $y2)); | 
| 1795 | 1 |  |  |  |  | 3 | $self->_addtopage($self->_uxy($x3, $y3)); | 
| 1796 | 1 |  |  |  |  | 1 | $self->_addtopage($self->_uxy($x4, $y4) . "curveto stroke\n"); | 
| 1797 |  |  |  |  |  |  |  | 
| 1798 | 1 |  |  |  |  | 4 | return 1; | 
| 1799 |  |  |  |  |  |  | } | 
| 1800 |  |  |  |  |  |  |  | 
| 1801 |  |  |  |  |  |  |  | 
| 1802 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1803 |  |  |  |  |  |  |  | 
| 1804 |  |  |  |  |  |  | =item curvextend( x1, y1, x2, y2, x3, y3 ) | 
| 1805 |  |  |  |  |  |  |  | 
| 1806 |  |  |  |  |  |  | Assuming the previous command was C, C, C or | 
| 1807 |  |  |  |  |  |  | C, extend that path with another curve segment to the co-ordinates | 
| 1808 |  |  |  |  |  |  | (x3, y3). (x1, y1) and (x2, y2) are the control points.  Behaviour after any | 
| 1809 |  |  |  |  |  |  | other method is unspecified. | 
| 1810 |  |  |  |  |  |  |  | 
| 1811 |  |  |  |  |  |  | =cut | 
| 1812 |  |  |  |  |  |  |  | 
| 1813 |  |  |  |  |  |  | sub curvextend | 
| 1814 |  |  |  |  |  |  | { | 
| 1815 | 2 |  |  | 2 | 1 | 3 | my $self = shift; | 
| 1816 | 2 |  |  |  |  | 5 | my ($x1, $y1, $x2, $y2, $x3, $y3) = @_; | 
| 1817 |  |  |  |  |  |  |  | 
| 1818 | 2 | 100 |  |  |  | 8 | unless ( @_ == 6 ) { | 
| 1819 | 1 |  |  |  |  | 4 | $self->_error( "bad curvextend definition, wrong number of args" ); | 
| 1820 | 1 |  |  |  |  | 5 | return 0; | 
| 1821 |  |  |  |  |  |  | } | 
| 1822 |  |  |  |  |  |  |  | 
| 1823 | 1 |  |  |  |  | 3 | my $out = $self->_uxy($x1, $y1); | 
| 1824 | 1 |  |  |  |  | 4 | $out .= $self->_uxy($x2, $y2); | 
| 1825 | 1 |  |  |  |  | 4 | $out .= $self->_uxy($x3, $y3) . "curveto stroke\n"; | 
| 1826 |  |  |  |  |  |  |  | 
| 1827 |  |  |  |  |  |  | # FIXMEFIXMEFIXME | 
| 1828 |  |  |  |  |  |  | # curveto may follow a lineto etc... | 
| 1829 | 1 |  |  |  |  | 3 | my $p = $self->{currentpage}; | 
| 1830 | 1 |  |  |  |  | 2 | my $last = pop @$p; | 
| 1831 | 1 |  |  |  |  | 4 | $last = $$last[1]; | 
| 1832 | 1 |  |  |  |  | 16 | $last =~ s/eto stroke\n$/eto\n$out/; | 
| 1833 | 1 |  |  |  |  | 5 | $self->_addtopage($last); | 
| 1834 |  |  |  |  |  |  |  | 
| 1835 | 1 |  |  |  |  | 5 | return 1; | 
| 1836 |  |  |  |  |  |  | } | 
| 1837 |  |  |  |  |  |  |  | 
| 1838 |  |  |  |  |  |  |  | 
| 1839 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1840 |  |  |  |  |  |  |  | 
| 1841 |  |  |  |  |  |  | =item newpath | 
| 1842 |  |  |  |  |  |  |  | 
| 1843 |  |  |  |  |  |  | This method is used internally to begin a new drawing path - you should | 
| 1844 |  |  |  |  |  |  | generally NEVER use it. | 
| 1845 |  |  |  |  |  |  |  | 
| 1846 |  |  |  |  |  |  | =cut | 
| 1847 |  |  |  |  |  |  |  | 
| 1848 |  |  |  |  |  |  | sub newpath | 
| 1849 |  |  |  |  |  |  | { | 
| 1850 | 54 |  |  | 54 | 1 | 50 | my $self = shift; | 
| 1851 |  |  |  |  |  |  |  | 
| 1852 | 54 |  |  |  |  | 69 | $self->_addtopage("newpath\n"); | 
| 1853 |  |  |  |  |  |  |  | 
| 1854 | 54 |  |  |  |  | 49 | return 1; | 
| 1855 |  |  |  |  |  |  | } | 
| 1856 |  |  |  |  |  |  |  | 
| 1857 |  |  |  |  |  |  |  | 
| 1858 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1859 |  |  |  |  |  |  |  | 
| 1860 |  |  |  |  |  |  | =item moveto( x, y ) | 
| 1861 |  |  |  |  |  |  |  | 
| 1862 |  |  |  |  |  |  | This method is used internally to move the cursor to a new point at (x, y) - | 
| 1863 |  |  |  |  |  |  | you will generally NEVER use this method. | 
| 1864 |  |  |  |  |  |  |  | 
| 1865 |  |  |  |  |  |  | =cut | 
| 1866 |  |  |  |  |  |  |  | 
| 1867 |  |  |  |  |  |  | sub moveto | 
| 1868 |  |  |  |  |  |  | { | 
| 1869 | 54 |  |  | 54 | 1 | 38 | my $self = shift; | 
| 1870 | 54 |  |  |  |  | 55 | my ($x, $y) = @_; | 
| 1871 |  |  |  |  |  |  |  | 
| 1872 | 54 |  |  |  |  | 70 | $self->_addtopage($self->_uxy($x, $y) . "moveto\n"); | 
| 1873 |  |  |  |  |  |  |  | 
| 1874 | 54 |  |  |  |  | 57 | return 1; | 
| 1875 |  |  |  |  |  |  | } | 
| 1876 |  |  |  |  |  |  |  | 
| 1877 |  |  |  |  |  |  |  | 
| 1878 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1879 |  |  |  |  |  |  |  | 
| 1880 |  |  |  |  |  |  | =item C | 
| 1881 |  |  |  |  |  |  |  | 
| 1882 |  |  |  |  |  |  | Imports an EPS file and scales/translates its bounding box to fill | 
| 1883 |  |  |  |  |  |  | the area defined by lower left co-ordinates (x1,y1) and upper right | 
| 1884 |  |  |  |  |  |  | co-ordinates (x2,y2). By default, if the co-ordinates have a different | 
| 1885 |  |  |  |  |  |  | aspect ratio from the bounding box, the scaling is constrained on the | 
| 1886 |  |  |  |  |  |  | greater dimension to keep the EPS fully inside the area. | 
| 1887 |  |  |  |  |  |  |  | 
| 1888 |  |  |  |  |  |  | Options are: | 
| 1889 |  |  |  |  |  |  |  | 
| 1890 |  |  |  |  |  |  | =over 4 | 
| 1891 |  |  |  |  |  |  |  | 
| 1892 |  |  |  |  |  |  | =item overlap => 1 | 
| 1893 |  |  |  |  |  |  |  | 
| 1894 |  |  |  |  |  |  | If C is 1 then the scaling is calculated on the lesser dimension | 
| 1895 |  |  |  |  |  |  | and the EPS can overlap the area. | 
| 1896 |  |  |  |  |  |  |  | 
| 1897 |  |  |  |  |  |  | =item stretch => 1 | 
| 1898 |  |  |  |  |  |  |  | 
| 1899 |  |  |  |  |  |  | If C is 1 then fill the entire area, ignoring the aspect ratio. | 
| 1900 |  |  |  |  |  |  | This option overrides C if both are given. | 
| 1901 |  |  |  |  |  |  |  | 
| 1902 |  |  |  |  |  |  | =back | 
| 1903 |  |  |  |  |  |  |  | 
| 1904 |  |  |  |  |  |  | Example: | 
| 1905 |  |  |  |  |  |  |  | 
| 1906 |  |  |  |  |  |  | # Assume smiley.eps is a round smiley face in a square bounding box | 
| 1907 |  |  |  |  |  |  |  | 
| 1908 |  |  |  |  |  |  | # Scale it to a (10,10)(20,20) box | 
| 1909 |  |  |  |  |  |  | $p->importepsfile("smiley.eps", 10,10, 20,20); | 
| 1910 |  |  |  |  |  |  |  | 
| 1911 |  |  |  |  |  |  | # Keeps aspect ratio, constrained to smallest fit | 
| 1912 |  |  |  |  |  |  | $p->importepsfile("smiley.eps", 10,10, 30,20); | 
| 1913 |  |  |  |  |  |  |  | 
| 1914 |  |  |  |  |  |  | # Keeps aspect ratio, allowed to overlap for largest fit | 
| 1915 |  |  |  |  |  |  | $p->importepsfile( {overlap => 1}, "smiley.eps", 10,10, 30,20); | 
| 1916 |  |  |  |  |  |  |  | 
| 1917 |  |  |  |  |  |  | # Aspect ratio is changed to give exact fit | 
| 1918 |  |  |  |  |  |  | $p->importepsfile( {stretch => 1}, "smiley.eps", 10,10, 30,20); | 
| 1919 |  |  |  |  |  |  |  | 
| 1920 |  |  |  |  |  |  | =cut | 
| 1921 |  |  |  |  |  |  |  | 
| 1922 |  |  |  |  |  |  | sub importepsfile | 
| 1923 |  |  |  |  |  |  | { | 
| 1924 | 0 |  |  | 0 | 1 | 0 | my $self = shift; | 
| 1925 |  |  |  |  |  |  |  | 
| 1926 | 0 |  |  |  |  | 0 | my $bbllx; | 
| 1927 |  |  |  |  |  |  | my $bblly; | 
| 1928 | 0 |  |  |  |  | 0 | my $bburx; | 
| 1929 | 0 |  |  |  |  | 0 | my $bbury; | 
| 1930 | 0 |  |  |  |  | 0 | my $bbw; | 
| 1931 | 0 |  |  |  |  | 0 | my $bbh; | 
| 1932 | 0 |  |  |  |  | 0 | my $pagew; | 
| 1933 | 0 |  |  |  |  | 0 | my $pageh; | 
| 1934 | 0 |  |  |  |  | 0 | my $scalex; | 
| 1935 | 0 |  |  |  |  | 0 | my $scaley; | 
| 1936 | 0 |  |  |  |  | 0 | my $line; | 
| 1937 | 0 |  |  |  |  | 0 | my $eps; | 
| 1938 |  |  |  |  |  |  |  | 
| 1939 | 0 |  |  |  |  | 0 | my %opt = (); | 
| 1940 |  |  |  |  |  |  |  | 
| 1941 | 0 | 0 |  |  |  | 0 | if (ref($_[0])) { | 
| 1942 | 0 |  |  |  |  | 0 | %opt = %{; shift}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1943 |  |  |  |  |  |  | } | 
| 1944 |  |  |  |  |  |  |  | 
| 1945 | 0 |  |  |  |  | 0 | my ($file, $x1, $y1, $x2, $y2) = @_; | 
| 1946 |  |  |  |  |  |  |  | 
| 1947 | 0 | 0 |  |  |  | 0 | unless (@_ == 5) { | 
| 1948 | 0 |  |  |  |  | 0 | $self->_error("importepsfile: wrong number of arguments"); | 
| 1949 | 0 |  |  |  |  | 0 | return 0; | 
| 1950 |  |  |  |  |  |  | } | 
| 1951 |  |  |  |  |  |  |  | 
| 1952 | 0 | 0 |  |  |  | 0 | $opt{'overlap'} = 0 if (!defined($opt{'overlap'})); | 
| 1953 | 0 | 0 |  |  |  | 0 | $opt{'stretch'} = 0 if (!defined($opt{'stretch'})); | 
| 1954 |  |  |  |  |  |  |  | 
| 1955 | 0 |  |  |  |  | 0 | $eps = new PostScript::Simple::EPS(file => $file); | 
| 1956 | 0 |  |  |  |  | 0 | ($bbllx, $bblly, $bburx, $bbury) = $eps->get_bbox(); | 
| 1957 |  |  |  |  |  |  |  | 
| 1958 | 0 |  |  |  |  | 0 | $pagew = $x2 - $x1; | 
| 1959 | 0 |  |  |  |  | 0 | $pageh = $y2 - $y1; | 
| 1960 |  |  |  |  |  |  |  | 
| 1961 | 0 |  |  |  |  | 0 | $bbw = $bburx - $bbllx; | 
| 1962 | 0 |  |  |  |  | 0 | $bbh = $bbury - $bblly; | 
| 1963 |  |  |  |  |  |  |  | 
| 1964 | 0 | 0 | 0 |  |  | 0 | if (($bbw == 0) || ($bbh == 0)) { | 
| 1965 | 0 |  |  |  |  | 0 | $self->_error("importeps: Bounding Box has zero dimension"); | 
| 1966 | 0 |  |  |  |  | 0 | return 0; | 
| 1967 |  |  |  |  |  |  | } | 
| 1968 |  |  |  |  |  |  |  | 
| 1969 | 0 |  |  |  |  | 0 | $scalex = $pagew / $bbw; | 
| 1970 | 0 |  |  |  |  | 0 | $scaley = $pageh / $bbh; | 
| 1971 |  |  |  |  |  |  |  | 
| 1972 | 0 | 0 |  |  |  | 0 | if ($opt{'stretch'} == 0) { | 
| 1973 | 0 | 0 |  |  |  | 0 | if ($opt{'overlap'} == 0) { | 
| 1974 | 0 | 0 |  |  |  | 0 | if ($scalex > $scaley) { | 
| 1975 | 0 |  |  |  |  | 0 | $scalex = $scaley; | 
| 1976 |  |  |  |  |  |  | } else { | 
| 1977 | 0 |  |  |  |  | 0 | $scaley = $scalex; | 
| 1978 |  |  |  |  |  |  | } | 
| 1979 |  |  |  |  |  |  | } else { | 
| 1980 | 0 | 0 |  |  |  | 0 | if ($scalex > $scaley) { | 
| 1981 | 0 |  |  |  |  | 0 | $scaley = $scalex; | 
| 1982 |  |  |  |  |  |  | } else { | 
| 1983 | 0 |  |  |  |  | 0 | $scalex = $scaley; | 
| 1984 |  |  |  |  |  |  | } | 
| 1985 |  |  |  |  |  |  | } | 
| 1986 |  |  |  |  |  |  | } | 
| 1987 |  |  |  |  |  |  |  | 
| 1988 | 0 |  |  |  |  | 0 | $eps->scale($scalex, $scaley); | 
| 1989 | 0 |  |  |  |  | 0 | $eps->translate(-$bbllx, -$bblly); | 
| 1990 | 0 |  |  |  |  | 0 | $self->_add_eps($eps, $x1, $y1); | 
| 1991 |  |  |  |  |  |  |  | 
| 1992 | 0 |  |  |  |  | 0 | return 1; | 
| 1993 |  |  |  |  |  |  | } | 
| 1994 |  |  |  |  |  |  |  | 
| 1995 |  |  |  |  |  |  |  | 
| 1996 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 1997 |  |  |  |  |  |  |  | 
| 1998 |  |  |  |  |  |  | =item C | 
| 1999 |  |  |  |  |  |  |  | 
| 2000 |  |  |  |  |  |  | Imports a PostScript::Simple::EPS object into the current document at position | 
| 2001 |  |  |  |  |  |  | C<(x,y)>. | 
| 2002 |  |  |  |  |  |  |  | 
| 2003 |  |  |  |  |  |  | Example: | 
| 2004 |  |  |  |  |  |  |  | 
| 2005 |  |  |  |  |  |  | use PostScript::Simple; | 
| 2006 |  |  |  |  |  |  |  | 
| 2007 |  |  |  |  |  |  | # create a new PostScript object | 
| 2008 |  |  |  |  |  |  | $p = new PostScript::Simple(papersize => "A4", | 
| 2009 |  |  |  |  |  |  | colour => 1, | 
| 2010 |  |  |  |  |  |  | units => "in"); | 
| 2011 |  |  |  |  |  |  |  | 
| 2012 |  |  |  |  |  |  | # create a new page | 
| 2013 |  |  |  |  |  |  | $p->newpage; | 
| 2014 |  |  |  |  |  |  |  | 
| 2015 |  |  |  |  |  |  | # create an eps object | 
| 2016 |  |  |  |  |  |  | $e = new PostScript::Simple::EPS(file => "test.eps"); | 
| 2017 |  |  |  |  |  |  | $e->rotate(90); | 
| 2018 |  |  |  |  |  |  | $e->scale(0.5); | 
| 2019 |  |  |  |  |  |  |  | 
| 2020 |  |  |  |  |  |  | # add eps to the current page | 
| 2021 |  |  |  |  |  |  | $p->importeps($e, 10,50); | 
| 2022 |  |  |  |  |  |  |  | 
| 2023 |  |  |  |  |  |  | =cut | 
| 2024 |  |  |  |  |  |  |  | 
| 2025 |  |  |  |  |  |  | sub importeps | 
| 2026 |  |  |  |  |  |  | { | 
| 2027 | 0 |  |  | 0 | 1 | 0 | my $self = shift; | 
| 2028 | 0 |  |  |  |  | 0 | my ($epsobj, $xpos, $ypos) = @_; | 
| 2029 |  |  |  |  |  |  |  | 
| 2030 | 0 | 0 |  |  |  | 0 | unless (@_ == 3) { | 
| 2031 | 0 |  |  |  |  | 0 | $self->_error("importeps: wrong number of arguments"); | 
| 2032 | 0 |  |  |  |  | 0 | return 0; | 
| 2033 |  |  |  |  |  |  | } | 
| 2034 |  |  |  |  |  |  |  | 
| 2035 | 0 |  |  |  |  | 0 | $self->_add_eps($epsobj, $xpos, $ypos); | 
| 2036 |  |  |  |  |  |  |  | 
| 2037 | 0 |  |  |  |  | 0 | return 1; | 
| 2038 |  |  |  |  |  |  | } | 
| 2039 |  |  |  |  |  |  |  | 
| 2040 |  |  |  |  |  |  |  | 
| 2041 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 2042 |  |  |  |  |  |  |  | 
| 2043 |  |  |  |  |  |  | =item C | 
| 2044 |  |  |  |  |  |  |  | 
| 2045 |  |  |  |  |  |  | Returns the last error generated. | 
| 2046 |  |  |  |  |  |  |  | 
| 2047 |  |  |  |  |  |  | Example: | 
| 2048 |  |  |  |  |  |  |  | 
| 2049 |  |  |  |  |  |  | unless ($ps->setcolour("purplewithyellowspots")) { | 
| 2050 |  |  |  |  |  |  | print $ps->err(); | 
| 2051 |  |  |  |  |  |  | } | 
| 2052 |  |  |  |  |  |  |  | 
| 2053 |  |  |  |  |  |  | # prints "bad colour name 'purplewithyellowspots'"; | 
| 2054 |  |  |  |  |  |  |  | 
| 2055 |  |  |  |  |  |  | =cut | 
| 2056 |  |  |  |  |  |  |  | 
| 2057 |  |  |  |  |  |  | sub err { | 
| 2058 | 0 |  |  | 0 | 1 | 0 | my $self = shift; | 
| 2059 |  |  |  |  |  |  |  | 
| 2060 | 0 |  |  |  |  | 0 | return $self->{lasterror}; | 
| 2061 |  |  |  |  |  |  | } | 
| 2062 |  |  |  |  |  |  |  | 
| 2063 |  |  |  |  |  |  |  | 
| 2064 |  |  |  |  |  |  | ################################################################################ | 
| 2065 |  |  |  |  |  |  | # PRIVATE methods | 
| 2066 |  |  |  |  |  |  |  | 
| 2067 |  |  |  |  |  |  | sub _addtopage | 
| 2068 |  |  |  |  |  |  | { | 
| 2069 | 532 |  |  | 532 |  | 414 | my ($self, $data) = @_; | 
| 2070 |  |  |  |  |  |  |  | 
| 2071 | 532 | 50 |  |  |  | 567 | if (defined $self->{currentpage}) { | 
| 2072 | 532 |  |  |  |  | 332 | push @{$self->{currentpage}}, ["ps", $data]; | 
|  | 532 |  |  |  |  | 1124 |  | 
| 2073 |  |  |  |  |  |  | } else { | 
| 2074 | 0 |  |  |  |  | 0 | confess "internal page error"; | 
| 2075 |  |  |  |  |  |  | } | 
| 2076 |  |  |  |  |  |  | } | 
| 2077 |  |  |  |  |  |  |  | 
| 2078 |  |  |  |  |  |  |  | 
| 2079 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 2080 |  |  |  |  |  |  |  | 
| 2081 |  |  |  |  |  |  | sub _add_eps | 
| 2082 |  |  |  |  |  |  | { | 
| 2083 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 2084 | 0 |  |  |  |  | 0 | my $epsobj; | 
| 2085 |  |  |  |  |  |  | my $xpos; | 
| 2086 | 0 |  |  |  |  | 0 | my $ypos; | 
| 2087 |  |  |  |  |  |  |  | 
| 2088 | 0 | 0 |  |  |  | 0 | if (ref($_[0]) ne "PostScript::Simple::EPS") { | 
| 2089 | 0 |  |  |  |  | 0 | croak "internal error: _add_eps[0] must be eps object"; | 
| 2090 |  |  |  |  |  |  | } | 
| 2091 |  |  |  |  |  |  |  | 
| 2092 | 0 | 0 | 0 |  |  | 0 | if ((!$self->{pspagecount}) and (!$self->{eps})) { | 
| 2093 |  |  |  |  |  |  | # Cannot draw on to non-page when not an eps file | 
| 2094 | 0 |  |  |  |  | 0 | $self->_error("importeps: no current page"); | 
| 2095 | 0 |  |  |  |  | 0 | return 0; | 
| 2096 |  |  |  |  |  |  | } | 
| 2097 |  |  |  |  |  |  |  | 
| 2098 | 0 | 0 |  |  |  | 0 | if ( @_ != 3 ) { | 
| 2099 | 0 |  |  |  |  | 0 | croak "internal error: wrong number of arguments for _add_eps"; | 
| 2100 | 0 |  |  |  |  | 0 | return 0; | 
| 2101 |  |  |  |  |  |  | } | 
| 2102 |  |  |  |  |  |  |  | 
| 2103 | 0 | 0 |  |  |  | 0 | unless (defined $self->{psresources}{importeps}) { | 
| 2104 | 0 |  |  |  |  | 0 | $self->{psresources}{importeps} = <<'EOP'; | 
| 2105 |  |  |  |  |  |  | /BeginEPSF { /b4_Inc_state save def /dict_count countdictstack def | 
| 2106 |  |  |  |  |  |  | /op_count count 1 sub def userdict begin /showpage { } def 0 setgray | 
| 2107 |  |  |  |  |  |  | 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit [ ] | 
| 2108 |  |  |  |  |  |  | 0 setdash newpath /languagelevel where { pop languagelevel 1 ne { | 
| 2109 |  |  |  |  |  |  | false setstrokeadjust false setoverprint } if } if } bind def | 
| 2110 |  |  |  |  |  |  | /EndEPSF { count op_count sub {pop} repeat countdictstack dict_count | 
| 2111 |  |  |  |  |  |  | sub {end} repeat b4_Inc_state restore } bind def | 
| 2112 |  |  |  |  |  |  | EOP | 
| 2113 |  |  |  |  |  |  | } | 
| 2114 |  |  |  |  |  |  |  | 
| 2115 | 0 |  |  |  |  | 0 | ($epsobj, $xpos, $ypos) = @_; | 
| 2116 |  |  |  |  |  |  |  | 
| 2117 | 0 |  |  |  |  | 0 | my $eps = "BeginEPSF\n"; | 
| 2118 | 0 |  |  |  |  | 0 | $eps .= $self->_uxy($xpos, $ypos) . "translate\n"; | 
| 2119 | 0 |  |  |  |  | 0 | $eps .= $self->_uxy(1, 1) . "scale\n"; | 
| 2120 | 0 |  |  |  |  | 0 | $eps .= $epsobj->_get_include_data($xpos, $ypos); | 
| 2121 | 0 |  |  |  |  | 0 | $eps .= "EndEPSF\n"; | 
| 2122 |  |  |  |  |  |  |  | 
| 2123 | 0 |  |  |  |  | 0 | $self->_addtopage($eps); | 
| 2124 |  |  |  |  |  |  |  | 
| 2125 | 0 |  |  |  |  | 0 | return 1; | 
| 2126 |  |  |  |  |  |  | } | 
| 2127 |  |  |  |  |  |  |  | 
| 2128 |  |  |  |  |  |  |  | 
| 2129 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 2130 |  |  |  |  |  |  |  | 
| 2131 |  |  |  |  |  |  | sub _error { | 
| 2132 | 23 |  |  | 23 |  | 20 | my $self = shift; | 
| 2133 | 23 |  |  |  |  | 21 | my $msg = shift; | 
| 2134 |  |  |  |  |  |  |  | 
| 2135 | 23 |  |  |  |  | 28 | $self->{lasterror} = $msg; | 
| 2136 | 23 |  |  |  |  | 64 | $self->_addtopage("(error: $msg\n) print flush\n"); | 
| 2137 |  |  |  |  |  |  | } | 
| 2138 |  |  |  |  |  |  |  | 
| 2139 |  |  |  |  |  |  |  | 
| 2140 |  |  |  |  |  |  | #------------------------------------------------------------------------------- | 
| 2141 |  |  |  |  |  |  |  | 
| 2142 |  |  |  |  |  |  | # Display method for debugging internal variables | 
| 2143 |  |  |  |  |  |  | # | 
| 2144 |  |  |  |  |  |  | #sub display { | 
| 2145 |  |  |  |  |  |  | #  my $self = shift; | 
| 2146 |  |  |  |  |  |  | #  my $i; | 
| 2147 |  |  |  |  |  |  | # | 
| 2148 |  |  |  |  |  |  | #  foreach $i (keys(%{$self})) | 
| 2149 |  |  |  |  |  |  | #  { | 
| 2150 |  |  |  |  |  |  | #    print "$i = $self->{$i}\n"; | 
| 2151 |  |  |  |  |  |  | #  } | 
| 2152 |  |  |  |  |  |  | #} | 
| 2153 |  |  |  |  |  |  |  | 
| 2154 |  |  |  |  |  |  | =back | 
| 2155 |  |  |  |  |  |  |  | 
| 2156 |  |  |  |  |  |  | =head1 BUGS | 
| 2157 |  |  |  |  |  |  |  | 
| 2158 |  |  |  |  |  |  | Some current functionality may not be as expected, and/or may not work correctly. | 
| 2159 |  |  |  |  |  |  | That's the fun with using code in development! | 
| 2160 |  |  |  |  |  |  |  | 
| 2161 |  |  |  |  |  |  | =head1 AUTHOR | 
| 2162 |  |  |  |  |  |  |  | 
| 2163 |  |  |  |  |  |  | The PostScript::Simple module was created by Matthew Newton, with ideas | 
| 2164 |  |  |  |  |  |  | and suggestions from Mark Withall and many other people from around the world. | 
| 2165 |  |  |  |  |  |  | Thanks! | 
| 2166 |  |  |  |  |  |  |  | 
| 2167 |  |  |  |  |  |  | Please see the README file in the distribution for more information about | 
| 2168 |  |  |  |  |  |  | contributors. | 
| 2169 |  |  |  |  |  |  |  | 
| 2170 |  |  |  |  |  |  | Copyright (C) 2002-2014 Matthew C. Newton | 
| 2171 |  |  |  |  |  |  |  | 
| 2172 |  |  |  |  |  |  | This program is free software; you can redistribute it and/or modify it under | 
| 2173 |  |  |  |  |  |  | the terms of the GNU General Public License as published by the Free Software | 
| 2174 |  |  |  |  |  |  | Foundation, version 2. | 
| 2175 |  |  |  |  |  |  |  | 
| 2176 |  |  |  |  |  |  | This program is distributed in the hope that it will be useful, but WITHOUT ANY | 
| 2177 |  |  |  |  |  |  | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | 
| 2178 |  |  |  |  |  |  | PARTICULAR PURPOSE. See the GNU General Public License for more details, | 
| 2179 |  |  |  |  |  |  | available at http://www.gnu.org/licenses/gpl.html. | 
| 2180 |  |  |  |  |  |  |  | 
| 2181 |  |  |  |  |  |  | =head1 SEE ALSO | 
| 2182 |  |  |  |  |  |  |  | 
| 2183 |  |  |  |  |  |  | L | 
| 2184 |  |  |  |  |  |  |  | 
| 2185 |  |  |  |  |  |  | =cut | 
| 2186 |  |  |  |  |  |  |  | 
| 2187 |  |  |  |  |  |  | 1; | 
| 2188 |  |  |  |  |  |  |  | 
| 2189 |  |  |  |  |  |  | # vim:foldmethod=marker: |