line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Text::UnicodeBox::Utility; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Text::UnicodeBox::Utility |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 DESCRIPTION |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
This module is part of the low level interface to L<Text::UnicodeBox>; you probably don't need to use it directly. |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=cut |
12
|
|
|
|
|
|
|
|
13
|
1
|
|
|
1
|
|
31535
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
41
|
|
14
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
30
|
|
15
|
1
|
|
|
1
|
|
8822
|
use charnames (); |
|
1
|
|
|
|
|
41556
|
|
|
1
|
|
|
|
|
25
|
|
16
|
1
|
|
|
1
|
|
10
|
use Exporter 'import'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
777
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
our @EXPORT_OK = qw(find_box_unicode_name fetch_box_character normalize_box_character_parameters); |
19
|
|
|
|
|
|
|
our $report_on_failure = 0; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 EXPORTED METHODS |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
The following methods are exportable by name. |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=head2 fetch_box_character |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
my $character = fetch_box_character( vertical => 'heavy' ); |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
Same as C<find_box_unicode_name> but returns the actual symbol. |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=cut |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
sub fetch_box_character { |
34
|
0
|
|
|
0
|
1
|
0
|
my $name = find_box_unicode_name(@_); |
35
|
0
|
0
|
|
|
|
0
|
return undef unless $name; |
36
|
|
|
|
|
|
|
|
37
|
0
|
|
|
|
|
0
|
return chr charnames::vianame($name); |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=head2 find_box_unicode_name (%spec) |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
Given a list of directions and styles, find a matching unicode name that can represent the symbol. Returns undefined if no such symbol exists. |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
The spec may contain keys like so: |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=over 4 |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=item up |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=item down |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
=item left |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=item right |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
Provide a style for the named direction |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=item horizontal |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=item vertical |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
These are the same as having provided 'top' & 'bottom' or 'left' and 'right' |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=back |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
For each key, the value may be and empty string or the string '1' to default to the style 'light'. Otherwise, the value is the style you want the line segment to be ('light', 'heavy', 'double', 'single'). |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=cut |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
sub find_box_unicode_name { |
71
|
10
|
|
|
10
|
1
|
39
|
my %directions = normalize_box_character_parameters(@_); |
72
|
10
|
50
|
|
|
|
24
|
return undef unless %directions; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
# Group together styles |
75
|
10
|
|
|
|
|
12
|
my %styles; |
76
|
10
|
|
|
|
|
35
|
while (my ($direction, $style) = each %directions) { |
77
|
16
|
|
|
|
|
14
|
push @{ $styles{$style} }, $direction; |
|
16
|
|
|
|
|
70
|
|
78
|
|
|
|
|
|
|
} |
79
|
10
|
|
|
|
|
23
|
my @styles = keys %styles; |
80
|
|
|
|
|
|
|
|
81
|
10
|
|
|
|
|
14
|
my $base_name = 'box drawings '; |
82
|
10
|
|
|
|
|
9
|
my @variations; |
83
|
|
|
|
|
|
|
|
84
|
10
|
100
|
|
|
|
28
|
if (int @styles == 1) { |
|
|
50
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# Only one style; should be at most only two directions |
86
|
7
|
|
|
|
|
7
|
my @directions = @{ $styles{ $styles[0] } }; |
|
7
|
|
|
|
|
20
|
|
87
|
7
|
50
|
|
|
|
17
|
if (int @directions > 2) { |
88
|
0
|
|
|
|
|
0
|
die "Unexpected scenario; one style but more than 2 directions"; |
89
|
|
|
|
|
|
|
} |
90
|
7
|
|
|
|
|
20
|
foreach my $variation (\@directions, [ reverse @directions ]) { |
91
|
14
|
|
|
|
|
45
|
push @variations, uc $base_name . $styles[0] . ' ' . join (' and ', @$variation); |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
elsif (int @styles == 2) { |
95
|
3
|
|
|
|
|
4
|
my @parts; |
96
|
3
|
|
|
|
|
6
|
foreach my $style (@styles) { |
97
|
6
|
|
|
|
|
7
|
my @directions = @{ $styles{$style} }; |
|
6
|
|
|
|
|
13
|
|
98
|
6
|
50
|
|
|
|
14
|
if (int @directions > 1) { |
99
|
|
|
|
|
|
|
# right/left down/up/vertical, never down/up/vertical left/right |
100
|
|
|
|
|
|
|
# up/down horizontal, never horizontal up/down |
101
|
0
|
0
|
0
|
|
|
0
|
if ( |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
102
|
|
|
|
|
|
|
($directions[0] =~ m/^(down|up|vertical)$/ && $directions[1] =~ m{^(left|right)$}) |
103
|
|
|
|
|
|
|
|| ($directions[0] =~ m/^(horizontal)$/ && $directions[1] =~ m{^(up|down)$}) |
104
|
|
|
|
|
|
|
) { |
105
|
0
|
|
|
|
|
0
|
@directions = reverse @directions; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
} |
108
|
6
|
|
|
|
|
17
|
push @parts, join ' ', @directions, $style; |
109
|
|
|
|
|
|
|
} |
110
|
3
|
|
|
|
|
11
|
foreach my $variation (\@parts, [ reverse @parts ]) { |
111
|
6
|
|
|
|
|
20
|
push @variations, uc $base_name . join(' and ', @$variation); |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
10
|
50
|
|
|
|
32
|
if (! @variations) { |
116
|
0
|
|
|
|
|
0
|
return undef; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
10
|
|
|
|
|
14
|
foreach my $variation (@variations) { |
120
|
14
|
100
|
|
|
|
1456
|
next unless charnames::vianame($variation); |
121
|
9
|
|
|
|
|
14952
|
return $variation; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
1
|
50
|
|
|
|
333
|
if ($report_on_failure) { |
125
|
0
|
|
|
|
|
0
|
print "Unable to find any character like (" . |
126
|
0
|
|
|
|
|
0
|
join (', ', map { "$_: $directions{$_}" } sort keys %directions) . |
127
|
|
|
|
|
|
|
"), tried the following: " . |
128
|
|
|
|
|
|
|
join (', ', @variations) . "\n"; |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
1
|
|
|
|
|
7
|
return undef; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=head2 normalize_box_character_parameters (%spec) |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
Takes the passed argument list to fetch_box_character() and normalizes the arguments in an idempotent fashion, returning the new spec list. |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=cut |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
sub normalize_box_character_parameters { |
141
|
10
|
|
|
10
|
1
|
41
|
my %directions = @_; |
142
|
|
|
|
|
|
|
|
143
|
10
|
50
|
|
|
|
23
|
if (grep { ! defined $_ } values %directions) { |
|
18
|
|
|
|
|
55
|
|
144
|
0
|
0
|
|
|
|
0
|
print "No way to handle undefined values: " . |
145
|
0
|
|
|
|
|
0
|
join (', ', map { "$_: ".(defined $directions{$_} ? $directions{$_} : 'undef') } sort keys %directions) . "\n"; |
146
|
0
|
|
|
|
|
0
|
return (); |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
# Expand shorthand |
150
|
10
|
|
|
|
|
19
|
foreach my $direction (keys %directions) { |
151
|
18
|
100
|
|
|
|
65
|
$directions{$direction} = 'light' if $directions{$direction} . '' eq '1'; |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
# Convert left & right to horizontal, up & down to vertical |
155
|
10
|
100
|
100
|
|
|
66
|
if ($directions{down} && $directions{up} && $directions{down} eq $directions{up}) { |
|
|
|
66
|
|
|
|
|
156
|
1
|
|
|
|
|
3
|
$directions{vertical} = delete $directions{down}; |
157
|
1
|
|
|
|
|
3
|
delete $directions{up}; |
158
|
|
|
|
|
|
|
} |
159
|
10
|
100
|
100
|
|
|
47
|
if ($directions{left} && $directions{right} && $directions{left} eq $directions{right}) { |
|
|
|
66
|
|
|
|
|
160
|
1
|
|
|
|
|
3
|
$directions{horizontal} = delete $directions{left}; |
161
|
1
|
|
|
|
|
2
|
delete $directions{right}; |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
# If any of the styles is a double, make sure all 'light' are 'single' |
165
|
10
|
100
|
|
|
|
18
|
if (grep { $directions{$_} eq 'double' } keys %directions) { |
|
16
|
|
|
|
|
44
|
|
166
|
2
|
|
|
|
|
5
|
foreach my $direction (grep { $directions{$_} eq 'light' } keys %directions) { |
|
4
|
|
|
|
|
10
|
|
167
|
0
|
|
|
|
|
0
|
$directions{$direction} = 'single'; |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
10
|
|
|
|
|
40
|
return %directions; |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=head1 COPYRIGHT |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
Copyright (c) 2012 Eric Waters and Shutterstock Images (http://shutterstock.com). All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
The full text of the license can be found in the LICENSE file included with this module. |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=head1 AUTHOR |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
Eric Waters <ewaters@gmail.com> |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=cut |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
1; |