line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
2
|
|
|
|
|
|
|
package PostScript::Calendar; |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# Copyright 2010 Christopher J. Madsen |
5
|
|
|
|
|
|
|
# |
6
|
|
|
|
|
|
|
# Author: Christopher J. Madsen |
7
|
|
|
|
|
|
|
# Created: Sat Nov 25 14:32:55 2006 |
8
|
|
|
|
|
|
|
# |
9
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify |
10
|
|
|
|
|
|
|
# it under the same terms as Perl itself. |
11
|
|
|
|
|
|
|
# |
12
|
|
|
|
|
|
|
# This program is distributed in the hope that it will be useful, |
13
|
|
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
14
|
|
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the |
15
|
|
|
|
|
|
|
# GNU General Public License or the Artistic License for more details. |
16
|
|
|
|
|
|
|
# |
17
|
|
|
|
|
|
|
# ABSTRACT: Generate a monthly calendar in PostScript |
18
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
19
|
|
|
|
|
|
|
|
20
|
3
|
|
|
3
|
|
46565
|
use 5.008; |
|
3
|
|
|
|
|
10
|
|
|
3
|
|
|
|
|
148
|
|
21
|
3
|
|
|
3
|
|
20
|
use warnings; |
|
3
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
109
|
|
22
|
3
|
|
|
3
|
|
73
|
use strict; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
120
|
|
23
|
3
|
|
|
3
|
|
20
|
use Carp; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
614
|
|
24
|
3
|
|
|
|
|
444
|
use Date::Calc 5.0 qw(Add_Delta_YM Day_of_Week Day_of_Week_to_Text |
25
|
3
|
|
|
3
|
|
3867
|
Days_in_Month Localtime Mktime Month_to_Text); |
|
3
|
|
|
|
|
165017
|
|
26
|
3
|
|
|
3
|
|
4791
|
use PostScript::File 2.20 qw(str); # need use_functions |
|
3
|
|
|
|
|
133986
|
|
|
3
|
|
|
|
|
19603
|
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
#===================================================================== |
30
|
|
|
|
|
|
|
# Package Global Variables: |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
our $VERSION = '1.01'; |
33
|
|
|
|
|
|
|
# This file is part of PostScript-Calendar 1.01 (February 12, 2012) |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
our @phaseName = qw(NewMoon FirstQuarter FullMoon LastQuarter); |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
38
|
|
|
|
|
|
|
# Tied hashes for interpolating function calls into strings: |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
{ package PostScript::Calendar::Interpolation; |
41
|
|
|
|
|
|
|
|
42
|
6
|
|
|
6
|
|
24
|
sub TIEHASH { bless $_[1], $_[0] } |
43
|
1687
|
|
|
1687
|
|
3783
|
sub FETCH { $_[0]->($_[1]) } |
44
|
|
|
|
|
|
|
} # end PostScript::Calendar::Interpolation |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
our (%C, %E, %S, $psFile); |
47
|
|
|
|
|
|
|
tie %E, 'PostScript::Calendar::Interpolation', sub { $_[0] }; # eval |
48
|
|
|
|
|
|
|
# quoted string: |
49
|
|
|
|
|
|
|
tie %S, 'PostScript::Calendar::Interpolation', sub { $psFile->pstr(shift) }; |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
52
|
|
|
|
|
|
|
# Return the first defined value: |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub firstdef |
55
|
|
|
|
|
|
|
{ |
56
|
414
|
|
|
414
|
0
|
1149
|
foreach (@_) { |
57
|
987
|
100
|
|
|
|
3709
|
return $_ if defined $_; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
0
|
|
|
|
|
0
|
$_[-1]; |
61
|
|
|
|
|
|
|
} # end firstdef |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
64
|
|
|
|
|
|
|
sub _fmt_color |
65
|
|
|
|
|
|
|
{ |
66
|
61
|
|
|
61
|
|
85
|
my $color = shift; |
67
|
|
|
|
|
|
|
|
68
|
61
|
50
|
66
|
|
|
481
|
if (not ref $color and $color =~ /^#((?:[0-9a-f]{3})+)$/i) { |
69
|
0
|
|
|
|
|
0
|
my $hexcolor = $1; |
70
|
|
|
|
|
|
|
|
71
|
0
|
|
|
|
|
0
|
my $digits = int(length($hexcolor) / 3); # Number of digits per color |
72
|
0
|
|
|
|
|
0
|
my $max = hex('F' x $digits); # Max intensity per color |
73
|
|
|
|
|
|
|
|
74
|
0
|
|
|
|
|
0
|
$color = [ map { |
75
|
0
|
|
|
|
|
0
|
my $n = sprintf('%.3f', |
76
|
|
|
|
|
|
|
hex(substr($hexcolor, $_ * $digits, $digits)) / $max); |
77
|
0
|
|
|
|
|
0
|
$n =~ s/\.?0+$//; |
78
|
0
|
|
|
|
|
0
|
$n |
79
|
|
|
|
|
|
|
} 0 .. 2 ]; |
80
|
|
|
|
|
|
|
} # end if color as hex triplet |
81
|
|
|
|
|
|
|
|
82
|
61
|
|
|
|
|
179
|
str($color); |
83
|
|
|
|
|
|
|
} # end _fmt_color |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
86
|
|
|
|
|
|
|
# Round to an integer, but preserve undef: |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub round |
89
|
|
|
|
|
|
|
{ |
90
|
144
|
100
|
|
144
|
0
|
1539
|
defined $_[0] ? sprintf('%d', $_[0]) : $_[0]; |
91
|
|
|
|
|
|
|
} # end round |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
94
|
|
|
|
|
|
|
# Add delta months: |
95
|
|
|
|
|
|
|
# |
96
|
|
|
|
|
|
|
# ($year, $month) = Add_Delta_M($year, $month, $delta_months); |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub Add_Delta_M |
99
|
|
|
|
|
|
|
{ |
100
|
25
|
|
|
25
|
0
|
179
|
(Add_Delta_YM($_[0], $_[1], 1, 0, $_[2]))[0,1]; |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
#===================================================================== |
104
|
|
|
|
|
|
|
# Constants: |
105
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# This is one time subroutine prototypes are useful: |
108
|
|
|
|
|
|
|
## no critic (ProhibitSubroutinePrototypes) |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub evTxt () { 0 } |
111
|
|
|
|
|
|
|
sub evPS () { 1 } |
112
|
|
|
|
|
|
|
sub evBackground () { 2 } |
113
|
|
|
|
|
|
|
sub evTopMargin () { 3 } |
114
|
|
|
|
|
|
|
sub evDict () { 4 } |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
## use critic |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
#===================================================================== |
119
|
|
|
|
|
|
|
# Package PostScript::Calendar: |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub new |
122
|
|
|
|
|
|
|
{ |
123
|
18
|
|
|
18
|
1
|
92741
|
my ($class, $year, $month, %p) = @_; |
124
|
|
|
|
|
|
|
|
125
|
18
|
|
50
|
|
|
135
|
my $self = bless { |
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
126
|
|
|
|
|
|
|
events => [], |
127
|
|
|
|
|
|
|
psFile => $p{ps_file}, |
128
|
|
|
|
|
|
|
condense => $p{condense}, |
129
|
|
|
|
|
|
|
border => firstdef($p{border}, 1), |
130
|
|
|
|
|
|
|
dayHeight => round($p{day_height}), |
131
|
|
|
|
|
|
|
grid => firstdef($p{grid}, 1), |
132
|
|
|
|
|
|
|
gridWidth => firstdef($p{grid_width}, 0.72), # 3 pixels at 300dpi |
133
|
|
|
|
|
|
|
mini => $p{mini_calendars}, |
134
|
|
|
|
|
|
|
phases => $p{phases}, |
135
|
|
|
|
|
|
|
title => firstdef($p{title}, |
136
|
|
|
|
|
|
|
sprintf '%s %d', Month_to_Text($month), $year), |
137
|
|
|
|
|
|
|
days => ($p{days} || [ 0 .. 6 ]), # Sun .. Sat |
138
|
|
|
|
|
|
|
year => $year, |
139
|
|
|
|
|
|
|
month => $month, |
140
|
|
|
|
|
|
|
sideMar => round(firstdef($p{side_margins}, $p{margin}, 24)), |
141
|
|
|
|
|
|
|
topMar => round(firstdef($p{top_margin}, $p{margin}, 36)), |
142
|
|
|
|
|
|
|
botMar => round(firstdef($p{bottom_margin}, $p{margin}, 24)), |
143
|
|
|
|
|
|
|
titleFont => $p{title_font} || 'Helvetica-iso', |
144
|
|
|
|
|
|
|
titleSize => $p{title_size} || 14, |
145
|
|
|
|
|
|
|
titleSkip => round(firstdef($p{title_skip}, 5)), |
146
|
|
|
|
|
|
|
labelFont => $p{label_font} || $p{title_font} || 'Helvetica-iso', |
147
|
|
|
|
|
|
|
labelSize => $p{label_size} || $p{title_size} || 14, |
148
|
|
|
|
|
|
|
labelSkip => round(firstdef($p{label_skip}, $p{title_skip}, 5)), |
149
|
|
|
|
|
|
|
dateFont => $p{date_font} || 'Helvetica-Oblique-iso', |
150
|
|
|
|
|
|
|
dateSize => $p{date_size} || $p{title_size} || 14, |
151
|
|
|
|
|
|
|
eventFont => $p{event_font} || 'Helvetica-iso', |
152
|
|
|
|
|
|
|
eventSize => $p{event_size} || 8, |
153
|
|
|
|
|
|
|
eventSkip => firstdef($p{event_skip}, 2), |
154
|
|
|
|
|
|
|
miniFont => $p{mini_font} || 'Helvetica-iso', |
155
|
|
|
|
|
|
|
miniSize => $p{mini_size} || 6, |
156
|
|
|
|
|
|
|
miniSkip => firstdef($p{mini_skip}, 3), |
157
|
|
|
|
|
|
|
borderWidth => firstdef($p{border_width}, 0.72), # 3 pixels at 300dpi |
158
|
|
|
|
|
|
|
dateRightMar => firstdef($p{date_right_margin}, 4), |
159
|
|
|
|
|
|
|
dateTopMar => firstdef($p{date_top_margin}, 2), |
160
|
|
|
|
|
|
|
eventTopMar => firstdef($p{event_top_margin}, $p{event_margin}, 2), |
161
|
|
|
|
|
|
|
eventLeftMar => firstdef($p{event_left_margin}, $p{event_margin}, 3), |
162
|
|
|
|
|
|
|
eventRightMar => firstdef($p{event_right_margin}, $p{event_margin}, 2), |
163
|
|
|
|
|
|
|
miniSideMar => firstdef($p{mini_side_margins}, $p{mini_margin}, 4), |
164
|
|
|
|
|
|
|
miniTopMar => firstdef($p{mini_top_margin}, $p{mini_margin}, 4), |
165
|
|
|
|
|
|
|
moonDark => _fmt_color(firstdef($p{moon_dark}, 0)), |
166
|
|
|
|
|
|
|
moonLight => _fmt_color(firstdef($p{moon_light}, 1)), |
167
|
|
|
|
|
|
|
moonMargin => firstdef($p{moon_margin}, 6), |
168
|
|
|
|
|
|
|
shadeColor => _fmt_color(firstdef($p{shade_color}, 0.85)), |
169
|
|
|
|
|
|
|
}, $class; |
170
|
|
|
|
|
|
|
|
171
|
18
|
|
|
|
|
933
|
my $days = $self->{days}; |
172
|
18
|
|
|
|
|
36
|
my $firstDay = $days->[0]; |
173
|
18
|
|
|
|
|
42
|
$self->{dayOffsets} = [ map { $_ - $firstDay } @$days ]; |
|
126
|
|
|
|
|
257
|
|
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
$self->{dayNames} = |
176
|
|
|
|
|
|
|
($p{day_names} or |
177
|
18
|
|
50
|
|
|
98
|
[ map { Day_of_Week_to_Text($_ % 7 || 7) } @$days ]); |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
# If no title, suppress it completely: |
180
|
18
|
50
|
|
|
|
268
|
if (not length $self->{title}) { |
181
|
0
|
|
|
|
|
0
|
$self->{titleSize} = 0; |
182
|
0
|
|
|
|
|
0
|
$self->{titleSkip} = 0; |
183
|
|
|
|
|
|
|
} # end if title is suppressed |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
# Create a PostScript::File object if necessary: |
186
|
18
|
100
|
|
|
|
59
|
unless ($self->{psFile}) { |
187
|
7
|
|
50
|
|
|
85
|
$self->{psFile} = PostScript::File->new( |
188
|
|
|
|
|
|
|
paper => ($p{paper} || 'Letter'), |
189
|
|
|
|
|
|
|
top => $self->{topMar}, |
190
|
|
|
|
|
|
|
left => $self->{sideMar}, |
191
|
|
|
|
|
|
|
right => $self->{sideMar}, |
192
|
|
|
|
|
|
|
title => PostScript::File->quote_text($self->{title}), |
193
|
|
|
|
|
|
|
reencode => 'cp1252', |
194
|
|
|
|
|
|
|
strip => 'all_comments', |
195
|
|
|
|
|
|
|
landscape => $p{landscape}, |
196
|
|
|
|
|
|
|
); |
197
|
|
|
|
|
|
|
|
198
|
7
|
|
|
|
|
39466
|
$self->{psFile}->add_comment( |
199
|
|
|
|
|
|
|
sprintf 'Creator: %s %s', ref($self), $self->VERSION |
200
|
|
|
|
|
|
|
); |
201
|
|
|
|
|
|
|
} # end unless supplied ps_file |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# Compile the list of required fonts: |
204
|
18
|
|
|
|
|
89
|
my %font; |
205
|
18
|
|
|
|
|
110
|
while (my ($k, $v) = each %$self) { |
206
|
792
|
100
|
|
|
|
2968
|
next unless $k =~ /Font$/; |
207
|
90
|
50
|
|
|
|
630
|
$font{ $v =~ /^(.+)-iso$/ ? $1 : $v } = 1; |
208
|
|
|
|
|
|
|
} |
209
|
18
|
|
|
|
|
128
|
$self->{psFile}->need_resource(font => keys %font); |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
# Shade specified days of the week: |
212
|
18
|
100
|
|
|
|
936
|
$self->shade_days_of_week(@{ $p{shade_days_of_week} }) |
|
3
|
|
|
|
|
16
|
|
213
|
|
|
|
|
|
|
if $p{shade_days_of_week}; |
214
|
|
|
|
|
|
|
|
215
|
18
|
|
|
|
|
90
|
$self; |
216
|
|
|
|
|
|
|
} # end new |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
219
|
|
|
|
|
|
|
sub calc_moon_phases |
220
|
|
|
|
|
|
|
{ |
221
|
1
|
|
|
1
|
0
|
4
|
my ($self, $year, $month) = @_; |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
# RECOMMEND PREREQ: Astro::MoonPhase 0.60 |
224
|
1
|
|
|
|
|
11
|
require Astro::MoonPhase; |
225
|
1
|
|
|
|
|
26
|
Astro::MoonPhase->VERSION(0.60); # Need phaselist |
226
|
|
|
|
|
|
|
|
227
|
1
|
|
|
|
|
10
|
my ($phase, @dates) = Astro::MoonPhase::phaselist( |
228
|
|
|
|
|
|
|
Mktime($year, $month, 1, 0,0,0), |
229
|
|
|
|
|
|
|
Mktime(Add_Delta_M($year, $month, 1), 1, 0,0,0) |
230
|
|
|
|
|
|
|
); |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
# Convert Unix times to day-of-month: |
233
|
1
|
|
|
|
|
1122
|
($phase, map { (Localtime $_)[2] } @dates); |
|
4
|
|
|
|
|
102
|
|
234
|
|
|
|
|
|
|
} # end calc_moon_phases |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
237
|
|
|
|
|
|
|
sub compute_grid |
238
|
|
|
|
|
|
|
{ |
239
|
42
|
|
|
42
|
0
|
88
|
my ($self, $year, $month, $condense) = @_; |
240
|
|
|
|
|
|
|
|
241
|
42
|
|
|
|
|
148
|
my ($days, $offsets) = @$self{qw(days dayOffsets)}; |
242
|
|
|
|
|
|
|
|
243
|
42
|
|
|
|
|
212
|
my $numDays = Days_in_Month($year, $month); |
244
|
|
|
|
|
|
|
|
245
|
42
|
|
|
|
|
591
|
my @grid; |
246
|
|
|
|
|
|
|
|
247
|
42
|
|
|
|
|
176
|
my $leftDate = 1 + $days->[0] - Day_of_Week($year, $month, 1); |
248
|
|
|
|
|
|
|
|
249
|
42
|
100
|
|
|
|
1499
|
$leftDate += 7 if $leftDate + $offsets->[-1] < 1; |
250
|
|
|
|
|
|
|
|
251
|
42
|
|
|
|
|
121
|
while ($leftDate <= $numDays) { |
252
|
219
|
|
|
|
|
354
|
push @grid, [ map { my $d = $leftDate + $_; |
|
1533
|
|
|
|
|
1685
|
|
253
|
1533
|
100
|
100
|
|
|
6031
|
($d > 0 and $d <= $numDays) ? $d : undef } @$offsets ]; |
254
|
219
|
|
|
|
|
622
|
$leftDate += 7; |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
|
257
|
42
|
50
|
33
|
|
|
125
|
if ($condense and @grid == 6) { |
258
|
0
|
0
|
|
|
|
0
|
if ($grid[0][-2]) { # merge up the bottom row |
259
|
0
|
|
|
|
|
0
|
$grid[-2][0] = [ split => $grid[-2][0], $grid[-1][0] ]; |
260
|
0
|
|
|
|
|
0
|
pop @grid; |
261
|
|
|
|
|
|
|
} else { # merge down the top row |
262
|
0
|
|
|
|
|
0
|
$grid[1][-1] = [ split => $grid[0][-1], $grid[1][-1] ]; |
263
|
0
|
|
|
|
|
0
|
shift @grid; |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
} # end if grid needs to be condensed |
266
|
|
|
|
|
|
|
|
267
|
42
|
|
|
|
|
113
|
return \@grid; |
268
|
|
|
|
|
|
|
} # end compute_grid |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
271
|
|
|
|
|
|
|
sub get_metrics |
272
|
|
|
|
|
|
|
{ |
273
|
30
|
|
|
30
|
0
|
55
|
my ($self, $font, $size) = @_; |
274
|
|
|
|
|
|
|
|
275
|
30
|
|
66
|
|
|
426
|
$self->{fontCache}{$font}{$size} |
276
|
|
|
|
|
|
|
||= $self->{psFile}->get_metrics($font, $size); |
277
|
|
|
|
|
|
|
} # end get_metrics |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
280
|
|
|
|
|
|
|
sub add_event |
281
|
|
|
|
|
|
|
{ |
282
|
3
|
|
|
3
|
1
|
1310
|
my ($self, $date, $message) = @_; |
283
|
|
|
|
|
|
|
|
284
|
3
|
|
|
|
|
6
|
push @{$self->{events}[$date][evTxt]}, split(/[ \t]*\n/, $message); |
|
3
|
|
|
|
|
34
|
|
285
|
|
|
|
|
|
|
} # end add_event |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
288
|
|
|
|
|
|
|
sub _set_colors |
289
|
|
|
|
|
|
|
{ |
290
|
9
|
|
|
9
|
|
11
|
my $hash = shift; |
291
|
|
|
|
|
|
|
|
292
|
9
|
|
|
|
|
29
|
while (@_) { |
293
|
27
|
|
|
|
|
94
|
my $key = shift; |
294
|
27
|
|
|
|
|
40
|
my $color = shift; |
295
|
|
|
|
|
|
|
|
296
|
27
|
100
|
|
|
|
85
|
$hash->{$key} = _fmt_color($color) if defined $color; |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
} # end _set_colors |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
301
|
|
|
|
|
|
|
sub shade |
302
|
|
|
|
|
|
|
{ |
303
|
9
|
|
|
9
|
1
|
1509
|
my $self = shift @_; |
304
|
|
|
|
|
|
|
|
305
|
9
|
100
|
|
|
|
29
|
my $options = ref($_[0]) ? shift @_ : {}; |
306
|
|
|
|
|
|
|
|
307
|
9
|
|
|
|
|
15
|
my %dict; |
308
|
9
|
|
|
|
|
46
|
_set_colors(\%dict, |
309
|
|
|
|
|
|
|
DayBackground => $options->{shade_color}, |
310
|
|
|
|
|
|
|
MoonDark => $options->{moon_dark}, |
311
|
|
|
|
|
|
|
MoonLight => $options->{moon_light}, |
312
|
|
|
|
|
|
|
); |
313
|
|
|
|
|
|
|
|
314
|
9
|
|
|
|
|
43
|
my $events = $self->{events}; |
315
|
|
|
|
|
|
|
|
316
|
9
|
|
|
|
|
19
|
for my $date (@_) { |
317
|
30
|
|
|
|
|
64
|
$events->[$date][evBackground] = "ShadeDay"; |
318
|
|
|
|
|
|
|
|
319
|
30
|
100
|
|
|
|
92
|
@{ $events->[$date][evDict] }{keys %dict} = values %dict if %dict; |
|
4
|
|
|
|
|
51
|
|
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
} # end shade |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
324
|
|
|
|
|
|
|
sub shade_days_of_week |
325
|
|
|
|
|
|
|
{ |
326
|
3
|
|
|
3
|
1
|
7
|
my $self = shift @_; |
327
|
|
|
|
|
|
|
|
328
|
3
|
|
|
|
|
10
|
my ($year, $month) = @$self{qw(year month)}; |
329
|
|
|
|
|
|
|
|
330
|
3
|
|
|
|
|
5
|
my (@shade, @dates); |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# Copy options over to shade: |
333
|
3
|
50
|
|
|
|
10
|
push @dates, shift @_ if ref $_[0]; |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
# @shade indicates which days of week to shade |
336
|
3
|
|
|
|
|
6
|
foreach (@_) { $shade[$_ % 7] = 1 } |
|
6
|
|
|
|
|
15
|
|
337
|
|
|
|
|
|
|
|
338
|
3
|
|
|
|
|
18
|
my $dow = Day_of_Week($year, $month, 1) % 7; |
339
|
|
|
|
|
|
|
|
340
|
3
|
|
|
|
|
151
|
for my $date (1 .. Days_in_Month($year, $month)) { |
341
|
91
|
100
|
|
|
|
204
|
push @dates, $date if $shade[$dow]; |
342
|
91
|
|
|
|
|
109
|
$dow = ($dow + 1) % 7; |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
3
|
50
|
|
|
|
20
|
$self->shade(@dates) if @dates; |
346
|
|
|
|
|
|
|
} # end shade_days_of_week |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
349
|
|
|
|
|
|
|
sub print_calendar |
350
|
|
|
|
|
|
|
{ |
351
|
42
|
|
|
42
|
0
|
550
|
my ($self, $grid, %p) = @_; |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
# Must set $psFile for interpolation |
354
|
42
|
|
|
|
|
102
|
local $psFile = my $ps = $self->{psFile}; |
355
|
|
|
|
|
|
|
|
356
|
42
|
50
|
|
|
|
426
|
$ps->add_to_page( <<"END_TITLE" ) if length($p{title}); |
357
|
|
|
|
|
|
|
$p{titleFont}$p{midpoint} $p{titleY} $S{$p{title}} showCenter |
358
|
|
|
|
|
|
|
END_TITLE |
359
|
|
|
|
|
|
|
|
360
|
42
|
|
|
|
|
5545
|
$ps->add_to_page("$p{labelFont}\n"); |
361
|
|
|
|
|
|
|
|
362
|
42
|
|
|
|
|
1771
|
my ($dayHeight, $dayWidth, $dateStartX) |
363
|
|
|
|
|
|
|
= @p{qw(dayHeight dayWidth dateStartX)}; |
364
|
|
|
|
|
|
|
|
365
|
42
|
|
|
|
|
61
|
$dateStartX -= $dayWidth; |
366
|
|
|
|
|
|
|
|
367
|
42
|
|
|
|
|
98
|
my $x = $p{leftEdge} + $p{midday}; |
368
|
42
|
|
|
|
|
58
|
foreach (@{ $p{dayNames} }) { |
|
42
|
|
|
|
|
101
|
|
369
|
294
|
|
|
|
|
1836
|
$ps->add_to_page("$x $p{labelY} $S{$_} showCenter\n"); |
370
|
294
|
|
|
|
|
23067
|
$x += $dayWidth; |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
|
373
|
42
|
100
|
|
|
|
205
|
$ps->add_to_page($p{dateFont}) if $p{dateFont}; |
374
|
|
|
|
|
|
|
|
375
|
42
|
|
100
|
|
|
1006
|
my $showdate = $p{dateShow} || 'showRight'; |
376
|
42
|
|
|
|
|
92
|
my $y = $p{dayTop} - $p{dateSize} - $p{dateTopMar}; |
377
|
|
|
|
|
|
|
|
378
|
42
|
|
|
|
|
90
|
foreach my $row (@$grid) { |
379
|
219
|
|
|
|
|
284
|
$x = $dateStartX; |
380
|
|
|
|
|
|
|
|
381
|
219
|
|
|
|
|
361
|
foreach my $day (@$row) { |
382
|
1533
|
|
|
|
|
86710
|
$x += $dayWidth; |
383
|
1533
|
100
|
|
|
|
3009
|
next unless $day; |
384
|
|
|
|
|
|
|
|
385
|
1297
|
100
|
|
|
|
2198
|
if (ref $day) { |
386
|
24
|
50
|
|
|
|
109
|
next unless $day->[0] eq 'split'; |
387
|
0
|
|
|
|
|
0
|
$ps->add_to_page("$x $y $S{$day->[1]} $showdate\n" . |
388
|
|
|
|
|
|
|
"$x $E{$y - $dayHeight/2} $S{$day->[2]} $showdate\n"); |
389
|
|
|
|
|
|
|
} else { |
390
|
1273
|
|
|
|
|
7402
|
$ps->add_to_page("$x $y $S{$day} $showdate\n"); |
391
|
|
|
|
|
|
|
} |
392
|
|
|
|
|
|
|
} # end foreach $day |
393
|
|
|
|
|
|
|
|
394
|
219
|
|
|
|
|
14963
|
$y -= $dayHeight; |
395
|
|
|
|
|
|
|
} # end foreach $row |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
} # end print_calendar |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
400
|
|
|
|
|
|
|
sub print_mini_calendar |
401
|
|
|
|
|
|
|
{ |
402
|
24
|
|
|
24
|
0
|
56
|
my ($self, $year, $month, $x, $y, $width, $height) = @_; |
403
|
|
|
|
|
|
|
|
404
|
24
|
|
|
|
|
60
|
my $yTop = $y + $height - $self->{miniTopMar}; |
405
|
24
|
|
|
|
|
73
|
my $grid = $self->compute_grid($year, $month); |
406
|
24
|
|
|
|
|
45
|
my $cols = @{ $grid->[0] }; |
|
24
|
|
|
|
|
54
|
|
407
|
|
|
|
|
|
|
|
408
|
24
|
|
|
|
|
59
|
my $fontsize = $self->{miniSize}; |
409
|
24
|
|
|
|
|
57
|
my $linespacing = $fontsize + $self->{miniSkip}; |
410
|
24
|
|
|
|
|
38
|
my $sideMar = $self->{miniSideMar}; |
411
|
|
|
|
|
|
|
|
412
|
24
|
|
|
|
|
98
|
my $font = $self->get_metrics($self->{miniFont}, $fontsize); |
413
|
24
|
|
|
|
|
7745
|
my $numWidth = $font->width('22'); |
414
|
|
|
|
|
|
|
|
415
|
24
|
50
|
|
|
|
845
|
my $colSpacing = (($cols > 1) |
416
|
|
|
|
|
|
|
? ($width - 2 * $sideMar - $cols * $numWidth) / ($cols - 1) |
417
|
|
|
|
|
|
|
: 0); |
418
|
|
|
|
|
|
|
|
419
|
24
|
|
|
|
|
62
|
my $dayWidth = int(($numWidth + $colSpacing) * 8) / 8.0; # Round to 1/8 |
420
|
24
|
|
|
|
|
46
|
my $midday = int($numWidth * 4) / 8.0; # Divide by 2 and round to 1/8 |
421
|
|
|
|
|
|
|
|
422
|
168
|
|
|
|
|
527
|
$self->print_calendar($grid, |
423
|
|
|
|
|
|
|
titleFont => "MiniFont setfont\n", |
424
|
|
|
|
|
|
|
labelFont => '', |
425
|
|
|
|
|
|
|
midpoint => $x + $width/2, |
426
|
|
|
|
|
|
|
midday => $midday, |
427
|
|
|
|
|
|
|
titleY => $yTop - $fontsize, |
428
|
|
|
|
|
|
|
title => Month_to_Text($month), |
429
|
|
|
|
|
|
|
dayHeight => $linespacing, |
430
|
|
|
|
|
|
|
dayWidth => $dayWidth, |
431
|
|
|
|
|
|
|
dateStartX => $x + $sideMar + $midday, |
432
|
|
|
|
|
|
|
dateShow => 'showCenter', |
433
|
|
|
|
|
|
|
leftEdge => $x + $sideMar, |
434
|
24
|
|
|
|
|
111
|
dayNames => [ map { substr($_,0,1) } @{$self->{dayNames}} ], |
|
24
|
|
|
|
|
319
|
|
435
|
|
|
|
|
|
|
labelY => $yTop - $fontsize - $linespacing, |
436
|
|
|
|
|
|
|
dayTop => $yTop - 2 * $linespacing, |
437
|
|
|
|
|
|
|
dateSize => $fontsize, |
438
|
|
|
|
|
|
|
dateTopMar => 0, |
439
|
|
|
|
|
|
|
); |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
} # end print_mini_calendar |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
444
|
|
|
|
|
|
|
sub print_events |
445
|
|
|
|
|
|
|
{ |
446
|
34
|
|
|
34
|
0
|
76
|
my ($self, $eventArray, $date, $x, $y, $width, $height, $special) = @_; |
447
|
|
|
|
|
|
|
|
448
|
34
|
|
|
|
|
48
|
my $events = $eventArray->[$date]; |
449
|
34
|
|
|
|
|
52
|
my $ps = $self->{psFile}; |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
# Handle background: |
452
|
34
|
100
|
|
|
|
85
|
unshift @{$events->[evPS]}, $events->[evBackground] |
|
28
|
|
|
|
|
84
|
|
453
|
|
|
|
|
|
|
if $events->[evBackground]; |
454
|
|
|
|
|
|
|
|
455
|
34
|
|
|
|
|
50
|
my $dict = $events->[evDict]; |
456
|
|
|
|
|
|
|
|
457
|
34
|
50
|
33
|
|
|
91
|
if ($special and $events->[evPS]) { |
458
|
0
|
0
|
|
|
|
0
|
$dict = { $dict ? %$dict : () }; |
459
|
0
|
|
|
|
|
0
|
$dict->{DayHeight} = $height; |
460
|
|
|
|
|
|
|
} |
461
|
|
|
|
|
|
|
|
462
|
34
|
100
|
|
|
|
71
|
if ($dict) { |
463
|
4
|
|
|
|
|
18
|
$ps->set_min_langlevel(2); # using dictionary literals |
464
|
7
|
|
|
|
|
52
|
$ps->add_to_page(join("\n", |
465
|
|
|
|
|
|
|
'<<', |
466
|
4
|
|
|
|
|
37
|
( map { "/$_ $dict->{$_}" } sort keys %$dict ), |
467
|
|
|
|
|
|
|
">> begin\n" |
468
|
|
|
|
|
|
|
)); |
469
|
|
|
|
|
|
|
} # end if dictionary |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
# Handle PostScript events: |
472
|
34
|
100
|
|
|
|
663
|
if ($events->[evPS]) { |
473
|
32
|
|
|
|
|
153
|
$ps->add_to_page(join "\n", |
474
|
|
|
|
|
|
|
"gsave\n$x $y translate", |
475
|
32
|
|
|
|
|
73
|
@{ $events->[evPS] }, |
476
|
|
|
|
|
|
|
"grestore\n" |
477
|
|
|
|
|
|
|
); |
478
|
|
|
|
|
|
|
} # end if we have PostScript events |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
# Handle text events: |
481
|
34
|
100
|
|
|
|
2946
|
if ($events->[evTxt]) { |
482
|
3
|
|
|
|
|
11
|
my ($eventSize, $eventTopMar, $eventLeftMar, $eventRightMar) = |
483
|
|
|
|
|
|
|
@$self{qw(eventSize eventTopMar eventLeftMar eventRightMar)}; |
484
|
3
|
|
50
|
|
|
17
|
my $useY = $height - $eventTopMar - ($events->[evTopMargin] || 0); |
485
|
|
|
|
|
|
|
|
486
|
3
|
|
|
|
|
12
|
my $text = $self->wrap_events($useY, $width, $height, $events->[evTxt], |
487
|
|
|
|
|
|
|
$date); |
488
|
3
|
|
|
|
|
65
|
$ps->add_to_page(<<"END_EVENTS"); |
489
|
|
|
|
|
|
|
$E{$x + $eventLeftMar} $E{$y + $useY - $eventSize} [$text] Events |
490
|
|
|
|
|
|
|
END_EVENTS |
491
|
|
|
|
|
|
|
} # end if we have text events |
492
|
|
|
|
|
|
|
|
493
|
34
|
100
|
|
|
|
391
|
$ps->add_to_page("end\n") if $dict; |
494
|
|
|
|
|
|
|
} # end print_events |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
497
|
|
|
|
|
|
|
sub wrap_events |
498
|
|
|
|
|
|
|
{ |
499
|
3
|
|
|
3
|
0
|
9
|
my ($self, $y, $width, $height, $events, $date) = @_; |
500
|
|
|
|
|
|
|
|
501
|
3
|
|
|
|
|
5
|
my $ps = $self->{psFile}; |
502
|
3
|
|
|
|
|
9
|
my $eventSize = $self->{eventSize}; |
503
|
3
|
|
|
|
|
11
|
my $metrics = $self->get_metrics($self->{eventFont}, $eventSize); |
504
|
3
|
|
|
|
|
6010
|
my $eventSpacing = $eventSize + $self->{eventSkip}; |
505
|
|
|
|
|
|
|
|
506
|
3
|
|
|
|
|
6
|
my $dateSize = $self->{dateSize}; |
507
|
3
|
|
|
|
|
10
|
my $dateBottom = $height - $dateSize - $self->{dateTopMar}; |
508
|
|
|
|
|
|
|
|
509
|
3
|
|
|
|
|
9
|
my $fullWidth = ($width -= $self->{eventLeftMar} + $self->{eventRightMar}); |
510
|
|
|
|
|
|
|
|
511
|
3
|
50
|
|
|
|
10
|
if ($y > $dateBottom) { |
512
|
3
|
|
|
|
|
11
|
my $dateMetrics = $self->get_metrics($self->{dateFont}, $dateSize); |
513
|
|
|
|
|
|
|
|
514
|
3
|
|
|
|
|
1561
|
$width -= ($dateMetrics->width($date) + |
515
|
|
|
|
|
|
|
$self->{dateRightMar}); |
516
|
|
|
|
|
|
|
} |
517
|
|
|
|
|
|
|
|
518
|
3
|
|
|
|
|
98
|
my $next; |
519
|
|
|
|
|
|
|
|
520
|
3
|
|
|
|
|
12
|
for (my $i = 0; $i <= $#$events; ++$i, $y -= $eventSpacing) { |
521
|
4
|
50
|
|
|
|
14
|
$width = $fullWidth if $y < $dateBottom; |
522
|
|
|
|
|
|
|
|
523
|
4
|
50
|
|
|
|
10
|
if ($y < $eventSize) { |
524
|
0
|
|
|
|
|
0
|
carp sprintf("WARNING: Event text for %s-%02d-%02d doesn't fit", |
525
|
|
|
|
|
|
|
$self->{year}, $self->{month}, $date); |
526
|
0
|
|
|
|
|
0
|
splice @$events, $i, scalar @$events; |
527
|
0
|
|
|
|
|
0
|
last; |
528
|
|
|
|
|
|
|
} # end if we ran out of space |
529
|
|
|
|
|
|
|
|
530
|
4
|
|
|
|
|
11
|
for ($events->[$i]) { |
531
|
4
|
|
|
|
|
11
|
s/\s+$//; # Remove trailing space, if any |
532
|
|
|
|
|
|
|
|
533
|
4
|
|
|
|
|
7
|
$next = ''; |
534
|
4
|
|
33
|
|
|
15
|
while (($metrics->width($_) > $width) and |
|
|
|
66
|
|
|
|
|
535
|
|
|
|
|
|
|
(s/-([^- \t]+-*)$/-/ or |
536
|
|
|
|
|
|
|
s/([ \t]+[^- \t]*-*)$// or |
537
|
|
|
|
|
|
|
s/(.)$//)) { |
538
|
1
|
|
|
|
|
55
|
$next = $1 . $next; |
539
|
|
|
|
|
|
|
} # end while string too wide |
540
|
|
|
|
|
|
|
|
541
|
4
|
100
|
|
|
|
128
|
if (length $next) { |
542
|
1
|
|
|
|
|
4
|
$next =~ s/^\s+//; |
543
|
1
|
|
|
|
|
7
|
splice @$events, $i+1,0, $next; |
544
|
|
|
|
|
|
|
} # end if string was too wide |
545
|
|
|
|
|
|
|
} # end for this event string |
546
|
|
|
|
|
|
|
} # end for each event |
547
|
|
|
|
|
|
|
|
548
|
3
|
|
|
|
|
7
|
join("\n", map { $ps->pstr($_) } @$events); |
|
4
|
|
|
|
|
33
|
|
549
|
|
|
|
|
|
|
} # end wrap_events |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
552
|
|
|
|
|
|
|
sub generate |
553
|
|
|
|
|
|
|
{ |
554
|
18
|
|
|
18
|
1
|
20720
|
my $self = $_[0]; |
555
|
|
|
|
|
|
|
|
556
|
18
|
|
|
|
|
134
|
my ($ps, $days, $events, $year, $month, $topMar, $botMar, $sideMar, $mini, |
557
|
|
|
|
|
|
|
$titleSize, $dayLabelSize, $labelSkip) |
558
|
|
|
|
|
|
|
= @$self{qw(psFile days events year month topMar botMar sideMar mini |
559
|
|
|
|
|
|
|
titleSize labelSize labelSkip)}; |
560
|
|
|
|
|
|
|
|
561
|
18
|
|
|
|
|
113
|
my ($width, $height, $landscape) = |
562
|
|
|
|
|
|
|
($ps->get_width, $ps->get_height, $ps->get_landscape); |
563
|
|
|
|
|
|
|
|
564
|
18
|
50
|
|
|
|
293
|
($width, $height) = ($height, $width) if $landscape; |
565
|
|
|
|
|
|
|
|
566
|
18
|
|
|
|
|
99
|
my $dayWidth = round(($width - 2 * $sideMar) / @$days); |
567
|
18
|
|
|
|
|
54
|
my $midday = $dayWidth / 2; |
568
|
18
|
|
|
|
|
39
|
my $gridWidth = $dayWidth * @$days; |
569
|
18
|
|
|
|
|
75
|
my $leftEdge = $sideMar; |
570
|
18
|
|
|
|
|
32
|
my $gridRight = $leftEdge + $gridWidth; |
571
|
|
|
|
|
|
|
|
572
|
18
|
|
|
|
|
31
|
my $midpoint = $width / 2; |
573
|
|
|
|
|
|
|
|
574
|
18
|
|
|
|
|
40
|
my $titleY = $height - $titleSize - $topMar; |
575
|
|
|
|
|
|
|
|
576
|
18
|
|
|
|
|
45
|
my $labelY = $titleY - $dayLabelSize - $self->{titleSkip}; |
577
|
|
|
|
|
|
|
|
578
|
18
|
|
|
|
|
33
|
my $dayTop = $labelY - $labelSkip; |
579
|
|
|
|
|
|
|
|
580
|
18
|
|
|
|
|
80
|
my $grid = $self->compute_grid($year, $month, $self->{condense}); |
581
|
|
|
|
|
|
|
|
582
|
18
|
100
|
|
|
|
52
|
if ($mini) { |
583
|
12
|
|
|
|
|
16
|
my (@prev, @next); |
584
|
12
|
50
|
|
|
|
44
|
push @$grid, [ (undef) x @$days ] if @$grid == 4; |
585
|
|
|
|
|
|
|
|
586
|
12
|
100
|
66
|
|
|
195
|
if ($grid->[-1][-1] or |
|
|
50
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
587
|
|
|
|
|
|
|
($mini eq 'before' and not $grid->[0][1]) or |
588
|
|
|
|
|
|
|
($mini eq 'after' and $grid->[-1][-2])) { |
589
|
8
|
|
|
|
|
18
|
@prev = (0,0); @next = (0,1); # Both calendars at beginning |
|
8
|
|
|
|
|
19
|
|
590
|
|
|
|
|
|
|
} elsif ($grid->[0][0] or |
591
|
|
|
|
|
|
|
($mini eq 'after' and not $grid->[-1][-2]) or |
592
|
|
|
|
|
|
|
($mini eq 'before' and $grid->[0][1])) { |
593
|
4
|
|
|
|
|
11
|
@prev = (-1,-2); @next = (-1,-1); # Both calendars at end |
|
4
|
|
|
|
|
10
|
|
594
|
|
|
|
|
|
|
} else { |
595
|
0
|
|
|
|
|
0
|
@prev = (0,0); @next = (-1,-1); # Split between beginning & end |
|
0
|
|
|
|
|
0
|
|
596
|
|
|
|
|
|
|
} |
597
|
|
|
|
|
|
|
|
598
|
12
|
|
|
|
|
50
|
$grid->[$prev[0]][$prev[1]] = [calendar => Add_Delta_M($year, $month, -1)]; |
599
|
12
|
|
|
|
|
638
|
$grid->[$next[0]][$next[1]] = [calendar => Add_Delta_M($year, $month, 1)]; |
600
|
|
|
|
|
|
|
} # end if mini calendars |
601
|
|
|
|
|
|
|
|
602
|
18
|
|
|
|
|
455
|
my $dayHeight = round(($dayTop - $botMar) / @$grid); |
603
|
18
|
100
|
66
|
|
|
229
|
if ($dayHeight > ($self->{dayHeight} || $dayHeight)) { |
604
|
12
|
|
|
|
|
26
|
$dayHeight = $self->{dayHeight}; |
605
|
|
|
|
|
|
|
} |
606
|
|
|
|
|
|
|
|
607
|
18
|
|
|
|
|
45
|
my $gridBottom = $dayTop - $dayHeight * @$grid; |
608
|
18
|
|
|
|
|
33
|
my $gridHeight = $dayTop - $gridBottom + $dayLabelSize + $labelSkip; |
609
|
18
|
|
|
|
|
28
|
my $gridTop = $gridBottom + $gridHeight; |
610
|
|
|
|
|
|
|
|
611
|
18
|
|
|
|
|
404
|
$ps->add_to_page(<<"END_PAGE_INIT"); |
612
|
|
|
|
|
|
|
0 setlinecap |
613
|
|
|
|
|
|
|
0 setlinejoin |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
/DayHeight $dayHeight def |
616
|
|
|
|
|
|
|
/DayWidth $dayWidth def |
617
|
|
|
|
|
|
|
/DayBackground $self->{shadeColor} def |
618
|
|
|
|
|
|
|
/TitleSize $titleSize def |
619
|
|
|
|
|
|
|
/TitleFont /$self->{titleFont} findfont TitleSize scalefont def |
620
|
|
|
|
|
|
|
/LabelSize $dayLabelSize def |
621
|
|
|
|
|
|
|
/LabelFont /$self->{labelFont} findfont LabelSize scalefont def |
622
|
|
|
|
|
|
|
/DateSize $self->{dateSize} def |
623
|
|
|
|
|
|
|
/DateFont /$self->{dateFont} findfont DateSize scalefont def |
624
|
|
|
|
|
|
|
/EventSize $self->{eventSize} def |
625
|
|
|
|
|
|
|
/EventFont /$self->{eventFont} findfont EventSize scalefont def |
626
|
|
|
|
|
|
|
/EventSpacing $E{$self->{eventSize} + $self->{eventSkip}} def |
627
|
|
|
|
|
|
|
/MiniSize $self->{miniSize} def |
628
|
|
|
|
|
|
|
/MiniFont /$self->{miniFont} findfont MiniSize scalefont def |
629
|
|
|
|
|
|
|
END_PAGE_INIT |
630
|
|
|
|
|
|
|
|
631
|
18
|
|
|
|
|
13153
|
$ps->use_functions(qw(hLine vLine setColor showCenter showLeft showLines |
632
|
|
|
|
|
|
|
showRight)); |
633
|
|
|
|
|
|
|
|
634
|
18
|
100
|
|
|
|
16624
|
unless ($ps->has_procset('PostScript_Calendar')) |
635
|
7
|
|
|
|
|
297
|
{ $ps->add_procset('PostScript_Calendar', <<'END_FUNCTIONS') } |
636
|
|
|
|
|
|
|
/pixel {72 mul 300 div} bind def % 300 dpi only |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
%--------------------------------------------------------------------- |
639
|
|
|
|
|
|
|
% Display text events: X Y [STRING ...] Events |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
/Events |
642
|
|
|
|
|
|
|
{ |
643
|
|
|
|
|
|
|
EventFont setfont |
644
|
|
|
|
|
|
|
EventSpacing /showLeft showLines |
645
|
|
|
|
|
|
|
} bind def |
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
%--------------------------------------------------------------------- |
648
|
|
|
|
|
|
|
% Fill a day rect with the current ink: |
649
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
/FillDay |
651
|
|
|
|
|
|
|
{ |
652
|
|
|
|
|
|
|
newpath |
653
|
|
|
|
|
|
|
0 0 moveto |
654
|
|
|
|
|
|
|
DayWidth 0 lineto |
655
|
|
|
|
|
|
|
DayWidth DayHeight lineto |
656
|
|
|
|
|
|
|
0 DayHeight lineto |
657
|
|
|
|
|
|
|
closepath |
658
|
|
|
|
|
|
|
fill |
659
|
|
|
|
|
|
|
} bind def |
660
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
%--------------------------------------------------------------------- |
662
|
|
|
|
|
|
|
% Shade a day: ShadeDay |
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
/ShadeDay |
665
|
|
|
|
|
|
|
{ |
666
|
|
|
|
|
|
|
gsave |
667
|
|
|
|
|
|
|
DayBackground setColor |
668
|
|
|
|
|
|
|
FillDay |
669
|
|
|
|
|
|
|
grestore |
670
|
|
|
|
|
|
|
} bind def |
671
|
|
|
|
|
|
|
END_FUNCTIONS |
672
|
|
|
|
|
|
|
|
673
|
18
|
100
|
|
|
|
10685
|
if ($self->{phases}) { |
674
|
1
|
|
|
|
|
5
|
my ($phase, @dates) = $self->calc_moon_phases($year, $month); |
675
|
1
|
|
|
|
|
34
|
my $margin = $self->{moonMargin} + $self->{dateSize}; |
676
|
1
|
|
|
|
|
5
|
while (@dates) { |
677
|
4
|
50
|
50
|
|
|
29
|
if ($margin > ($events->[$dates[0]][evTopMargin] || 0)) { |
678
|
4
|
|
|
|
|
13
|
$events->[$dates[0]][evTopMargin] = $margin; |
679
|
|
|
|
|
|
|
} |
680
|
4
|
|
|
|
|
6
|
push @{$events->[shift @dates][evPS]}, "/$phaseName[$phase] ShowPhase"; |
|
4
|
|
|
|
|
19
|
|
681
|
4
|
|
|
|
|
14
|
$phase = ($phase + 1) % 4; |
682
|
|
|
|
|
|
|
} # end while @dates |
683
|
|
|
|
|
|
|
|
684
|
1
|
|
|
|
|
12
|
$ps->add_to_page(<<"END_MOON_SETTINGS"); |
685
|
|
|
|
|
|
|
/MoonDark $self->{moonDark} def |
686
|
|
|
|
|
|
|
/MoonLight $self->{moonLight} def |
687
|
|
|
|
|
|
|
/MoonMargin $self->{moonMargin} def |
688
|
|
|
|
|
|
|
END_MOON_SETTINGS |
689
|
|
|
|
|
|
|
|
690
|
1
|
50
|
|
|
|
140
|
unless ($ps->has_procset('PostScript_Calendar_Moon')) |
691
|
1
|
|
|
|
|
75
|
{ $ps->add_procset('PostScript_Calendar_Moon', <<'END_MOON_FUNCTIONS') } |
692
|
|
|
|
|
|
|
%--------------------------------------------------------------------- |
693
|
|
|
|
|
|
|
% Show the phase of the moon: PHASE ShowPhase |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
/ShowPhase |
696
|
|
|
|
|
|
|
{ |
697
|
|
|
|
|
|
|
gsave |
698
|
|
|
|
|
|
|
3 pixel setlinewidth |
699
|
|
|
|
|
|
|
newpath |
700
|
|
|
|
|
|
|
MoonMargin DateSize 2 div add |
701
|
|
|
|
|
|
|
DayHeight MoonMargin sub |
702
|
|
|
|
|
|
|
DateSize 2 div sub |
703
|
|
|
|
|
|
|
DateSize 2 div |
704
|
|
|
|
|
|
|
0 360 arc |
705
|
|
|
|
|
|
|
closepath |
706
|
|
|
|
|
|
|
cvx exec |
707
|
|
|
|
|
|
|
grestore |
708
|
|
|
|
|
|
|
} bind def |
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
/NewMoon { MoonDark setColor fill } bind def |
711
|
|
|
|
|
|
|
/FullMoon { |
712
|
|
|
|
|
|
|
gsave MoonLight setColor fill grestore |
713
|
|
|
|
|
|
|
MoonDark setColor stroke |
714
|
|
|
|
|
|
|
} bind def |
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
/FirstQuarter |
717
|
|
|
|
|
|
|
{ |
718
|
|
|
|
|
|
|
FullMoon |
719
|
|
|
|
|
|
|
newpath |
720
|
|
|
|
|
|
|
MoonMargin DateSize 2 div add |
721
|
|
|
|
|
|
|
DayHeight MoonMargin sub DateSize 2 div sub |
722
|
|
|
|
|
|
|
DateSize 2 div |
723
|
|
|
|
|
|
|
90 270 arc |
724
|
|
|
|
|
|
|
closepath fill |
725
|
|
|
|
|
|
|
} bind def |
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
/LastQuarter |
728
|
|
|
|
|
|
|
{ |
729
|
|
|
|
|
|
|
FullMoon |
730
|
|
|
|
|
|
|
newpath |
731
|
|
|
|
|
|
|
MoonMargin DateSize 2 div add |
732
|
|
|
|
|
|
|
DayHeight MoonMargin sub DateSize 2 div sub |
733
|
|
|
|
|
|
|
DateSize 2 div |
734
|
|
|
|
|
|
|
270 90 arc |
735
|
|
|
|
|
|
|
closepath fill |
736
|
|
|
|
|
|
|
} bind def |
737
|
|
|
|
|
|
|
END_MOON_FUNCTIONS |
738
|
|
|
|
|
|
|
} # end if showing phases of the moon |
739
|
|
|
|
|
|
|
|
740
|
18
|
|
|
|
|
2729
|
my $splitHeight = $dayHeight/2; |
741
|
|
|
|
|
|
|
|
742
|
18
|
|
|
|
|
59
|
my $y = $dayTop; |
743
|
18
|
|
|
|
|
45
|
foreach my $row (@$grid) { |
744
|
93
|
|
|
|
|
208
|
$y -= $dayHeight; |
745
|
93
|
|
|
|
|
132
|
my $x = $leftEdge - $dayWidth; |
746
|
|
|
|
|
|
|
|
747
|
93
|
|
|
|
|
152
|
foreach my $day (@$row) { |
748
|
651
|
|
|
|
|
748
|
$x += $dayWidth; |
749
|
651
|
100
|
|
|
|
1112
|
next unless $day; |
750
|
|
|
|
|
|
|
|
751
|
567
|
100
|
|
|
|
846
|
if (ref $day) { |
752
|
24
|
50
|
|
|
|
108
|
if ($day->[0] eq 'split') { |
|
|
50
|
|
|
|
|
|
753
|
0
|
|
|
|
|
0
|
my $lineY = $y + $splitHeight; |
754
|
0
|
0
|
|
|
|
0
|
$self->print_events($events, $day->[1], $x, $lineY, |
755
|
|
|
|
|
|
|
$dayWidth, $splitHeight, 1) |
756
|
|
|
|
|
|
|
if $events->[$day->[1]]; |
757
|
0
|
0
|
|
|
|
0
|
$self->print_events($events, $day->[2], $x, $y, |
758
|
|
|
|
|
|
|
$dayWidth, $splitHeight, 1) |
759
|
|
|
|
|
|
|
if $events->[$day->[2]]; |
760
|
|
|
|
|
|
|
|
761
|
0
|
|
|
|
|
0
|
$ps->add_to_page(<<"END_SPLIT_LINE"); |
762
|
|
|
|
|
|
|
$dayWidth $x $lineY hLine |
763
|
|
|
|
|
|
|
END_SPLIT_LINE |
764
|
|
|
|
|
|
|
} elsif ($day->[0] eq 'calendar') { |
765
|
24
|
|
|
|
|
123
|
$self->print_mini_calendar(@$day[1,2], $x, $y, $dayWidth, $dayHeight); |
766
|
|
|
|
|
|
|
} |
767
|
|
|
|
|
|
|
} else { |
768
|
543
|
100
|
|
|
|
1316
|
$self->print_events($events, $day, $x, $y, $dayWidth, $dayHeight) |
769
|
|
|
|
|
|
|
if $events->[$day]; |
770
|
|
|
|
|
|
|
} |
771
|
|
|
|
|
|
|
} # end foreach $day |
772
|
|
|
|
|
|
|
} # end foreach $row |
773
|
|
|
|
|
|
|
|
774
|
18
|
|
|
|
|
171
|
$self->print_calendar($grid, |
775
|
|
|
|
|
|
|
titleFont => "TitleFont setfont\n", |
776
|
|
|
|
|
|
|
labelFont => "LabelFont setfont\n", |
777
|
|
|
|
|
|
|
dateFont => "DateFont setfont\n", |
778
|
|
|
|
|
|
|
midpoint => $midpoint, |
779
|
|
|
|
|
|
|
midday => $midday, |
780
|
|
|
|
|
|
|
titleY => $titleY, |
781
|
|
|
|
|
|
|
title => $self->{title}, |
782
|
|
|
|
|
|
|
dayHeight => $dayHeight, |
783
|
|
|
|
|
|
|
dayWidth => $dayWidth, |
784
|
|
|
|
|
|
|
dateStartX => $leftEdge + $dayWidth - $self->{dateRightMar}, |
785
|
|
|
|
|
|
|
leftEdge => $leftEdge, |
786
|
|
|
|
|
|
|
dayNames => $self->{dayNames}, |
787
|
|
|
|
|
|
|
labelY => $labelY, |
788
|
|
|
|
|
|
|
dayTop => $dayTop, |
789
|
|
|
|
|
|
|
dateSize => $self->{dateSize}, |
790
|
|
|
|
|
|
|
dateTopMar => $self->{dateTopMar}, |
791
|
|
|
|
|
|
|
); |
792
|
|
|
|
|
|
|
|
793
|
18
|
50
|
|
|
|
86
|
if ($self->{grid}) { |
794
|
18
|
|
|
|
|
216
|
$ps->add_to_page(<<"END_GRID"); |
795
|
|
|
|
|
|
|
$self->{gridWidth} setlinewidth |
796
|
|
|
|
|
|
|
$E{$gridBottom + $dayHeight} $dayHeight $dayTop\ { |
797
|
|
|
|
|
|
|
$gridWidth $leftEdge 3 -1 roll hLine |
798
|
|
|
|
|
|
|
} for |
799
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
$E{$leftEdge + $dayWidth} $dayWidth $E{$gridRight - $midday}\ { |
801
|
|
|
|
|
|
|
$gridHeight exch $gridBottom vLine |
802
|
|
|
|
|
|
|
} for |
803
|
|
|
|
|
|
|
END_GRID |
804
|
|
|
|
|
|
|
} # end if grid |
805
|
|
|
|
|
|
|
|
806
|
18
|
50
|
|
|
|
5308
|
if ($self->{border}) { |
807
|
18
|
|
|
|
|
193
|
$ps->add_to_page(<<"END_BORDER"); |
808
|
|
|
|
|
|
|
$self->{borderWidth} setlinewidth |
809
|
|
|
|
|
|
|
newpath |
810
|
|
|
|
|
|
|
$leftEdge $gridTop moveto |
811
|
|
|
|
|
|
|
$gridWidth 0 rlineto |
812
|
|
|
|
|
|
|
0 -$gridHeight rlineto |
813
|
|
|
|
|
|
|
-$gridWidth 0 rlineto |
814
|
|
|
|
|
|
|
closepath stroke |
815
|
|
|
|
|
|
|
END_BORDER |
816
|
|
|
|
|
|
|
} else { |
817
|
0
|
|
|
|
|
0
|
$ps->add_to_page("$gridWidth $leftEdge $gridTop hLine\n"); |
818
|
|
|
|
|
|
|
} |
819
|
|
|
|
|
|
|
|
820
|
18
|
|
|
|
|
6887
|
$self->{generated} = 1; |
821
|
|
|
|
|
|
|
} # end generate |
822
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
824
|
|
|
|
|
|
|
sub output |
825
|
|
|
|
|
|
|
{ |
826
|
0
|
|
|
0
|
1
|
0
|
my $self = shift @_; |
827
|
|
|
|
|
|
|
|
828
|
0
|
0
|
|
|
|
0
|
$self->generate unless $self->{generated}; |
829
|
|
|
|
|
|
|
|
830
|
0
|
|
|
|
|
0
|
$self->{psFile}->output(@_); |
831
|
|
|
|
|
|
|
} # end output |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
834
|
7
|
|
|
7
|
1
|
274
|
sub ps_file { $_[0]->{psFile} } |
835
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
837
|
|
|
|
|
|
|
sub get__PostScript_File |
838
|
|
|
|
|
|
|
{ |
839
|
0
|
|
|
0
|
0
|
|
my $self = shift @_; |
840
|
|
|
|
|
|
|
|
841
|
0
|
0
|
|
|
|
|
$self->generate unless $self->{generated}; |
842
|
|
|
|
|
|
|
|
843
|
0
|
|
|
|
|
|
$self->{psFile}; |
844
|
|
|
|
|
|
|
} # end output |
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
#===================================================================== |
847
|
|
|
|
|
|
|
# Package Return Value: |
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
1; |
850
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
__END__ |