File Coverage

blib/lib/Text/UpsideDown.pm
Criterion Covered Total %
statement 18 18 100.0
branch n/a
condition n/a
subroutine 6 6 100.0
pod 1 1 100.0
total 25 25 100.0


line stmt bran cond sub pod time code
1             package Text::UpsideDown;
2 2     2   156706 use 5.008;
  2         9  
  2         116  
3 2     2   12 use strict;
  2         4  
  2         65  
4 2     2   22 use warnings;
  2         6  
  2         69  
5 2     2   2474 use charnames qw(:full);
  2         172232  
  2         96  
6 2     2   869 use Exporter qw(import);
  2         5  
  2         228  
7             our @EXPORT = qw(upside_down);
8             # ABSTRACT: Flip text upside-down using Unicode
9             our $VERSION = '1.22'; # VERSION
10              
11              
12             # Mapping taken from:
13             # - http://www.fileformat.info/convert/text/upside-down-map.htm
14             # - http://en.wikipedia.org/wiki/Transformation_of_text
15             # - http://www.upsidedowntext.com/unicode
16             #
17             # Letters that don't change in upside-down view (like 'H', 'I') aren't given.
18             our %upside_down_map = (
19             'A' => "\N{FOR ALL}",
20             'B' => "\N{GREEK SMALL LETTER XI}",
21             'C' => "\N{ROMAN NUMERAL REVERSED ONE HUNDRED}",
22             'D' => "\N{LEFT HALF BLACK CIRCLE}",
23             'E' => "\N{LATIN CAPITAL LETTER REVERSED E}",
24             'F' => "\N{TURNED CAPITAL F}",
25             'G' => "\N{TURNED SANS-SERIF CAPITAL G}",
26             'J' => "\N{LATIN SMALL LETTER LONG S}",
27             'K' => "\N{RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT}",
28             'L' => "\N{TURNED SANS-SERIF CAPITAL L}",
29             'M' => 'W',
30             'N' => "\N{LATIN LETTER SMALL CAPITAL REVERSED N}",
31             'P' => "\N{CYRILLIC CAPITAL LETTER KOMI DE}",
32             'Q' => "\N{GREEK CAPITAL LETTER OMICRON WITH TONOS}",
33             'R' => "\N{LATIN LETTER SMALL CAPITAL TURNED R}",
34             'T' => "\N{UP TACK}",
35             'U' => "\N{INTERSECTION}",
36             'V' => "\N{GREEK LETTER SMALL CAPITAL LAMDA}",
37             'Y' => "\N{TURNED SANS-SERIF CAPITAL Y}",
38             'a' => "\N{LATIN SMALL LETTER TURNED A}",
39             'b' => 'q',
40             'c' => "\N{LATIN SMALL LETTER OPEN O}",
41             'd' => 'p',
42             'e' => "\N{LATIN SMALL LETTER TURNED E}",
43             'f' => "\N{LATIN SMALL LETTER DOTLESS J WITH STROKE}",
44             'g' => "\N{LATIN SMALL LETTER B WITH TOPBAR}",
45             'h' => "\N{LATIN SMALL LETTER TURNED H}",
46             'i' => "\N{LATIN SMALL LETTER DOTLESS I}",
47             'j' => "\N{LATIN SMALL LETTER R WITH FISHHOOK}",
48             'k' => "\N{LATIN SMALL LETTER TURNED K}",
49             'l' => "\N{LATIN SMALL LETTER ESH}",
50             'm' => "\N{LATIN SMALL LETTER TURNED M}",
51             'n' => 'u',
52             'r' => "\N{LATIN SMALL LETTER TURNED R}",
53             't' => "\N{LATIN SMALL LETTER TURNED T}",
54             'v' => "\N{LATIN SMALL LETTER TURNED V}",
55             'w' => "\N{LATIN SMALL LETTER TURNED W}",
56             'y' => "\N{LATIN SMALL LETTER TURNED Y}",
57              
58             '!' => "\N{INVERTED EXCLAMATION MARK}",
59             '"' => "\N{DOUBLE LOW-9 QUOTATION MARK}",
60             '&' => "\N{TURNED AMPERSAND}",
61             q{'} => ',',
62             '.' => "\N{DOT ABOVE}",
63             '^' => "\N{LOGICAL OR}",
64             '*' => "\N{LOW ASTERISK}",
65             '1' => "\N{DOWNWARDS HARPOON WITH BARB RIGHTWARDS}",
66             '3' => "\N{LATIN CAPITAL LETTER OPEN E}",
67             '6' => '9',
68             '7' => "\N{BOPOMOFO LETTER ENG}",
69             ';' => "\N{ARABIC SEMICOLON}",
70             '?' => "\N{INVERTED QUESTION MARK}",
71             '(' => ')',
72             '[' => ']',
73             '{' => '}',
74             '<' => '>',
75             '_' => "\N{OVERLINE}",
76             "\N{UNDERTIE}" => "\N{CHARACTER TIE}",
77             "\N{LEFT SQUARE BRACKET WITH QUILL}" => "\N{RIGHT SQUARE BRACKET WITH QUILL}",
78             "\N{THEREFORE}" => "\N{BECAUSE}",
79             );
80             %upside_down_map = (%upside_down_map, reverse %upside_down_map);
81              
82              
83             my $tr = eval( ## no critic (BuiltinFunctions::ProhibitStringyEval)
84             sprintf 'sub { tr/%s/%s/ }',
85             map { quotemeta join '', @{ $_ } }
86             [ keys %upside_down_map ], [ values %upside_down_map ]
87             );
88              
89             sub upside_down {
90 2     2 1 465 my $text = shift;
91 2         75 $tr->() for $text;
92 2         17 return scalar reverse $text;
93             }
94              
95             1;
96              
97             __END__