#!/usr/bin/perl -w use utf8; use feature 'unicode_strings'; use open ':std', ':encoding(UTF-8)'; $version = "0.1"; $DEBUG = 0; # Ideas for future features: work as a filter (text on stdin)? support # for ANSI colors from command line? detect terminal width and do # word-wrap? use unicode 13.0 semigraphics (2x3 pixel blocks)? these # aren't well supported by fonts yet... but it would allow our font to # be higher resolution None of this stuff may ever happen... =pod =encoding utf8 =head1 NAME bitmaptext.pl - print giant characters =head1 SYNOPSIS =head2 From the shell: bitmaptext.pl [--help | --man | --version] | [-g] [-i] [ [--test] | [--] [text] ] =head2 From within irssi: /script load bitmaptext.pl /big [-i] [text] /giant [-i] [text] =head1 DESCRIPTION bitmaptext.pl prints text strings rendered as Unicode block characters, using either the 'quadrant' characters from the 25xx block to treat each terminal character cell as a block of 2x2 'semigraphics' pixels, or (with B<-g> option or B in irssi) the full-block and space characters for I large characters. The font used for rendering is proportional, and uses a B by 8 character cell (where 2 < B < 9; most glyphs are 5x7). Only printable ASCII (I to I) and Latin-1 (I to I) is supported, plus a few emoji: =over 4 =item ☮ the peace symbol (I) =item ☯ the yin-yang (I) =item ☺ the smiley face (I) =item ☹ the frowny face (I) =back Other characters will render as spaces. When run from the command line, each argument is printed on its own line. To print a message with a space in it, quote the argument. When run from irssi, the entire string is printed as one line. Standard IRC color codes are supported anywhere in the string (e.g. B<^C3,4> for green text on red background). Other formatting (e.g. bold or italic) is not supported. Note that the text argument(s) must be Unicode (UTF-8), whether running standalone or within irssi. =head1 OPTIONS =head2 Irssi Options =over 4 =item B<-i> Print text in inverse video. Applies to both B and B commands. =back =head2 Command-line Options =over 4 =item B<-g> Print giant text. Same as B in irssi. =item B<-i> Print text in inverse video. =item B<--> Stop processing options; anything after B<--> is taken as the text to print. Use this if your text begins with I<->. =item B<--test> Print the entire printable character set (ASCII and Latin-1). Can be combined with B<-i> and/or B<-g>. Without B<-g>, the table is 43x48 characters. With B<-g>, it's 90x96. If the table is too big for your terminal, resize your terminal or try piping it though B. =item B<--help> Print built-in help. =item B<--man> Print built-in help in man page format. =item B<--version> Print bitmaptext.pl version number and exit. =back =head1 EXAMPLES These examples may not format properly on your terminal. If they don't, your terminal probably won't be able to display the large text from bitmaptext.pl, either. $ bitmaptext.pl 'Big Text' ▄▄ ▗ ▄▄▖ ▖ ▙▄▘▄ ▞▀▌ ▌ ▞▀▖▌▐▝▛ ▌ ▌▐ ▚▄▌ ▌ ▛▀▘▞▚ ▌ ▀▀ ▀▘▗▄▘ ▘ ▝▀ ▘▝ ▝ $ bitmaptext.pl -g HEY █ █ █████ █ █ █ █ █ █ █ █████ ████ █ █ █ █ █ █ █ █ █ █ █ █ █████ █ $ bitmaptext.pl -i ' Foobar.' ███▀▀▜██████▜█████████ ███▝▀█▚▄▜▚▄▜▝▀█▙▄▜▗▄▜█ ███▐██▐█▐▐█▐▐█▐▚▄▐▐███ ███▟██▙▄█▙▄█▄▄█▙▄▟▟██▟ =head1 TROUBLESHOOTING =head2 Command-line If the display in your teminal looks like gibberish, make sure your terminal supports Unicode and UTF-8 (and has the support enabled). If you're sure it's enabled but the display is still wrong, make sure you're using a font that has the Unicode box-drawing characters. Terminus is a good choice. Terminals known to work include B, B (with e.g. B<-u8> option or UTF-8 enabled in B<~/.Xdefaults>), B, B, B (KDE), B (XFCE). The original B is known I to work. The Linux console may work, but a lot of the available fonts lack some or all of the quadrant characters (-g should still work). If all else fails, try it in B, which has built-in box-drawing characters. =head2 Irssi Make sure irssi is running in a Unicode/UTF-8 capable terminal (see above). Also run I from within irssi. If you can see your big text just fine, but another user can't, the problem is at the other user's end. He has to enable UTF-8 in his client (and if the client runs in a terminal, he has to use a UTF-8 capable terminal). =head1 NOTES There's no way to load the font from an external file; it's built into the script, although it's at least easy to edit (look at the bottom of the script file). Without B<-g> (or with B in irssi), each character will be rendered as a B / 2 by 4 block of 2x2 pixel cells, meaning you can easily exceed the width of your terminal (or your audience's terminal(s)). Best to stick with messages of 20 characters or less. Even if you use a really wide terminal window, the people you're talking to might not. With B<-g> (or with B in irssi), each character will be rendered as a B by 8 block of single-pixel cells. It's very easy to exceed the terminal width; best to stick with 10 characters or less. Also, in irssi, you're sending 8 lines to the server at once: you may trigger the server's (or the channel's) flood protection and be temporarily silenced, banned, or even disconnected from the server. A future version of this script may someday include a delay between lines to avoid this... On IRC, you have no control over how other peoples' clients display your text. Anyone whose client doesn't support Unicode and UTF-8 won't be able to see your big and giant messages. Also, with clients that use a proportional (variable-width) font, the spacing may not come out right. The font was "drawn freehand" in a text editor, not directly based on any existing font. All glyphs have a blank column on the right, and most have a blank row at the bottom and top (so the glyphs are mostly 5x6). Lowercase I, I, I

, I, and I have true descenders, meaning they use the bottom row. As with any low-res bitmap fonts, some compromises have to be made. The lowercase I and I are too tall, and the centerlines on the I, I, and I are one pixel lower than they should be. The B and B are too short. Some of the Latin-1 glyphs are even worse: the diacritics require the letters to be squashed, and even so, they don't have a blank line on top, so they'll touch true-descender characters on the line above. =head1 AUTHOR Urchlay on Libera IRC, =head1 LICENSE WTFPL. =head1 SEE ALSO B(1), B(1), B(1), B(1) =cut # (0,0) (1,0) (0,1) (1,0) order. %pixel_map = ( '____' => ' ', '___X' => '▗', '__X_' => '▖', '__XX' => '▄', '_X__' => '▝', '_X_X' => '▐', '_XX_' => '▞', '_XXX' => '▟', 'X___' => '▘', 'X__X' => '▚', 'X_X_' => '▌', 'X_XX' => '▙', 'XX__' => '▀', 'XX_X' => '▜', 'XXX_' => '▛', 'XXXX' => '█', ); # add a glyph to the pixels array, on the right. sub add_glyph_to_pixels { my $chr = shift; # character my $pixels = shift; # array ref $chr = " " unless $glyphs{$chr}; my @g = @{$glyphs{$chr}}; for(my $i = 0; $i < @g; $i++) { $pixels->[$i] .= $g[$i]; } } # does the 2x2 quadrant-block rendering. arg is the array of # pixels (which are X and _, not unicode blocks/spaces!) # return value is an array of 3 ready-to-print lines of unicode. # when called with no args, returns the height of the output, in # screen lines (font size divided by two). sub render_big_pixels { return 4 unless @_; my @output; my $input_width = length($_[0]); # if width is odd, add an extra column of 0 pixels to make it even. # have to do this because we use 2x2 blocks (can't have 1x2 blocks # left at the end). if($input_width % 2) { s/$/_/ for @_; } for(my $y = 0; $y < @_; $y += 2) { my $line; for(my $x = 0; $x < $input_width; $x += 2) { # (0,0) (1,0) (0,1) (1,0) order. # e.g. the key for ▚ is X__X. my $key = substr($_[$y], $x, 2) . substr($_[$y + 1], $x, 2); $line .= $pixel_map{$key}; } push @output, $line; } return @output; } # block/space (giant, -g) rendering. very simple: show a solid block # for a 1 pixel, or a space for 0. sub render_giant_pixels { return 8 unless @_; my @output = @_; for(@output) { s/X/█/g; s/_/ /g; } return @output; } # support for -i option: swap the 1's and 0's in the pixels array. sub invert { for(@{$_[0]}) { s/X/#/g; s/_/X/g; s/#/_/g; } } # called when running from command line, not irssi. sub print_string { my $renderer = shift; # either \&render_big_pixels or \&render_giant_pixels my $inverse = shift; # boolean my @pixels; utf8::decode($_[0]); for my $c (split "", $_[0]) { add_glyph_to_pixels($c, \@pixels); } invert(\@pixels) if $inverse; my @output = $renderer->(@pixels); print join("\n", @output), "\n"; } # --test mode, prints whole charset sub print_font { my($renderer, $inverse) = @_; my $termheight = 25; my $col = 0; my(@ascii, @latin); for(my $i = 32; $i < 128; $i += 16) { my $a; $a .= chr($_) for($i .. ($i + 15)); push @ascii, $a; $a = ""; $a .= chr($_) for(($i + 128) .. (($i + 128) + 15)); push @latin, $a; } print_string($renderer, $inverse, $_) for @ascii, @latin; } # main() if we're not running under irssi if(__PACKAGE__ eq 'main') { exec "perldoc $0" if @ARGV && $ARGV[0] =~ /--?h(elp)?/; exec "pod2man --stderr --utf8 -s1 -r$version -c\"Urchlay's Misc Stuff\" $0" if @ARGV && $ARGV[0] =~ /--?m(an)?/; if(@ARGV && $ARGV[0] eq '--version') { print "bitmaptext.pl $version\n"; exit 0; } init_font(); my $renderer = \&render_big_pixels; my $inverse = 0; my $testmode = 0; while(@ARGV) { if($ARGV[0] eq '-g') { $renderer = \&render_giant_pixels; shift; } elsif($ARGV[0] eq '-i') { $inverse++; shift; } elsif($ARGV[0] eq '--test') { shift; $testmode++; } elsif($ARGV[0] eq '--') { shift; last; } elsif($ARGV[0] =~ /^-/) { die "bitmaptext.pl: unknown option '$ARGV[0]'. Try running with --help.\n"; } else { last; } } if($testmode) { print_font($renderer, $inverse); } else { die "bitmaptext.pl: no text. Try running with --help.\n" unless @ARGV; print_string($renderer, $inverse, $_) for @ARGV; } exit 0; } # irssi stuff here init_font(); require Irssi; Irssi->import(qw/command command_bind/); our $VERSION = $version; our %IRSSI = ( authors => 'Urchlay', contact => 'Urchlay on Libera', name => 'bitmaptext', description => 'print giant characters made of UTF-8 boxes', license => 'WTFPL', url => 'none', ); sub irssi_print_string { my ($text, $srv, $chan, $renderer) = @_; return unless $text; return unless $srv; return unless $chan; my $inverse = 0; if($text =~ s/^-i\s//) { $inverse++; } my $height = $renderer->(); my @lines; for(my $i = 0; $i < $height; $i++) { $lines[$i] = ""; } # irssi's written in C, it passes us strings of utf-8 bytes, but in perl # there's a difference between e.g. "\xc2\xa2" (2 bytes, utf8-encoded) and # the string representation of the utf-8 character "¢" (written "\x{a2}"). # utf8::decode turns the former into the latter, so when we split the # string to get the characters, we get unicode characters. utf8::decode($text); # Color spec: # https://modern.ircdocs.horse/formatting.html # we don't have to interpret the color codes, just recognize and # append to output lines. for my $i (split /(\x03[0-9]+(?:,[0-9]+)?|\x03)/, $text) { if($i =~ /^\x03/) { if($DEBUG) { if($i eq "\x03") { print "color off"; } else { print "color " . substr($i, 1); } } map { $_ .= $i } @lines; } else { print "word: $i" if $DEBUG; my @pixels; for my $ch (split "", $i) { print "glyph: $ch" if $DEBUG; add_glyph_to_pixels($ch, \@pixels); } invert(\@pixels) if $inverse; my @r = $renderer->(@pixels); for(my $l = 0; $l < @r; $l++) { $lines[$l] .= $r[$l]; } } } for(@lines) { $chan->command('MSG ' . $chan->{name} . ' ' . $_); } } sub cmd_big { irssi_print_string(@_, \&render_big_pixels); } sub cmd_giant { irssi_print_string(@_, \&render_giant_pixels); } # the help for our 2 options is very similar, use this as a template to # create them both. $helptext = < See also: _OTHERCMD_ EOF sub mkhelp { my $text = $helptext; my $cmd = $_[0]; for(qw/_CMD_ _DESC_ _OTHERCMD_/) { $text =~ s/$_/$_[0]/gm; shift; } # \x02 is ^B, IRC bold toggle. use it for e.g. Syntax:, Parameters:... $text =~ s/^.*:/\x02$&\x02/gm; $help{$cmd} = $text; } mkhelp("big", "using Unicode quadrant blocks as pixels.", "giant"); mkhelp("giant", "using Unicode full blocks and spaces as pixels.", "big"); # write the generated help to files, so irssi's /help command will # find them. this relies on the user's help_path setting, can't remember # what the default is... my $dir = Irssi::get_irssi_dir() . "/help"; if(! -e $dir) { mkdir $dir; } if(-e $dir) { for(keys %help) { if(open my $f, ">", "$dir/$_") { print $f $help{$_}; close $f; } } } command_bind("big", \&cmd_big); command_bind("giant", \&cmd_giant); # call init_font once at startup. it's a function instead of mainline code so # we can avoid calling it when we're run with --help. # # if you're editing the font, the rules are: # # 1. glyphs are variable width Nx8 monochrome bitmaps. there's no limit on N, # but most of the glyphs are 6x8 (5px wide plus a blank column), so you # don't want to make your new glyphs too much wider than that. # 2. all rows in the same glyph must be the same width. # 3. use an X for a set pixel, use _ for an unset pixel. # 4. the rightmost column must be all _, so the characters don't # touch each other. # # There's a bit of error-checking that make the script die if you # break the rules, but it may not be infallible. # Also, not a hard-and-fast-rule, but the bottom row will normally # be blank, except for glyphs with true descenders (lowercase g j q y). # You can assign a glyph to any Unicode character. There's no requirement # for it to be ASCII or Latin-1. sub init_font { # ASCII printable range (32 to 126). @{$glyphs{" "}} = qw/ ______ ______ ______ ______ ______ ______ ______ ______ /; @{$glyphs{"!"}} = qw/ __ X_ X_ X_ X_ __ X_ __ /; @{$glyphs{"\""}} = qw/ ____ X_X_ X_X_ ____ ____ ____ ____ ____ /; @{$glyphs{"#"}} = qw/ ______ ______ _X_X__ XXXXX_ _X_X__ XXXXX_ _X_X__ ______ /; @{$glyphs{"\$"}} = qw/ ______ __X___ _XXXX_ X_X___ _XXX__ __X_X_ XXXX__ __X___ /; @{$glyphs{"%"}} = qw/ ______ ______ XX__X_ ___X__ __X___ _X____ X__XX_ ______ /; @{$glyphs{"&"}} = qw/ _____ __X__ _XXX_ X____ _XX__ X____ _XXX_ __X__ /; ## @{$glyphs{"&"}} = qw/ ## _______ ## _XXX___ ## X___X__ ## _XXX___ ## X__XXX_ ## X___X__ ## _XXX_X_ ## _______ ## /; ## @{$glyphs{"'"}} = qw/ __ X_ X_ __ __ __ __ __ /; @{$glyphs{"("}} = qw/ ___ _X_ X__ X__ X__ X__ _X_ ___ /; @{$glyphs{")"}} = qw/ ___ X__ _X_ _X_ _X_ _X_ X__ ___ /; @{$glyphs{"*"}} = qw/ ______ ______ ______ X_X_X_ _XXX__ X_X_X_ ______ ______ /; @{$glyphs{"+"}} = qw/ ____ ____ ____ _X__ XXX_ _X__ ____ ____ /; @{$glyphs{","}} = qw/ ___ ___ ___ ___ ___ _X_ X__ ___ /; @{$glyphs{"-"}} = qw/ ____ ____ ____ ____ XXX_ ____ ____ ____ /; @{$glyphs{"."}} = qw/ __ __ __ __ __ __ X_ __ /; @{$glyphs{"/"}} = qw/ ______ ______ ____X_ ___X__ __X___ _X____ X_____ ______ /; @{$glyphs{"0"}} = qw/ ______ _XXX__ X__XX_ X_X_X_ XX__X_ X___X_ _XXX__ ______ /; @{$glyphs{"1"}} = qw/ ____ _X__ XX__ _X__ _X__ _X__ XXX_ ____ /; @{$glyphs{"2"}} = qw/ ______ XXXX__ ____X_ _XXX__ X_____ X_____ XXXXX_ ______ /; @{$glyphs{"3"}} = qw/ ______ XXXX__ ____X_ _XXX__ ____X_ ____X_ XXXX__ ______ /; @{$glyphs{"4"}} = qw/ ______ __X_X_ _X__X_ X___X_ XXXXX_ ____X_ ____X_ ______ /; @{$glyphs{"5"}} = qw/ ______ XXXXX_ X_____ XXXX__ ____X_ ____X_ XXXX__ ______ /; @{$glyphs{"6"}} = qw/ ______ _XXX__ X_____ XXXX__ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"7"}} = qw/ ______ XXXXX_ ____X_ ___X__ __X___ __X___ __X___ ______ /; @{$glyphs{"8"}} = qw/ ______ _XXX__ X___X_ _XXX__ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"9"}} = qw/ ______ _XXX__ X___X_ X___X_ _XXXX_ ____X_ _XXX__ ______ /; @{$glyphs{":"}} = qw/ __ __ __ X_ __ X_ __ __ /; @{$glyphs{";"}} = qw/ ___ ___ ___ _X_ ___ _X_ X__ ___ /; @{$glyphs{"<"}} = qw/ ______ ______ ____X_ __XX__ XX____ __XX__ ____X_ ______ /; @{$glyphs{"="}} = qw/ ____ ____ ____ XXX_ ____ XXX_ ____ ____ /; @{$glyphs{">"}} = qw/ ______ ______ X_____ _XX___ ___XX_ _XX___ X_____ ______ /; @{$glyphs{"?"}} = qw/ _XXX__ X___X_ ____X_ ___X__ __X___ ______ __X___ ______ /; @{$glyphs{"@"}} = qw/ ______ ______ _XXX__ X_X_X_ X_XXX_ X_____ _XXXX_ ______ /; @{$glyphs{"A"}} = qw/ ______ __X___ _X_X__ X___X_ XXXXX_ X___X_ X___X_ ______ /; @{$glyphs{"B"}} = qw/ ______ XXXX__ X___X_ XXXX__ X___X_ X___X_ XXXX__ ______ /; @{$glyphs{"C"}} = qw/ ______ _XXX__ X___X_ X_____ X_____ X___X_ _XXX__ ______ /; @{$glyphs{"D"}} = qw/ ______ XXXX__ X___X_ X___X_ X___X_ X___X_ XXXX__ ______ /; @{$glyphs{"E"}} = qw/ ______ XXXXX_ X_____ XXXX__ X_____ X_____ XXXXX_ ______ /; @{$glyphs{"F"}} = qw/ ______ XXXXX_ X_____ XXXX__ X_____ X_____ X_____ ______ /; @{$glyphs{"G"}} = qw/ ______ _XXXX_ X_____ X_____ X__XX_ X___X_ _XXX__ ______ /; @{$glyphs{"H"}} = qw/ ______ X___X_ X___X_ XXXXX_ X___X_ X___X_ X___X_ ______ /; @{$glyphs{"I"}} = qw/ ____ XXX_ _X__ _X__ _X__ _X__ XXX_ ____ /; @{$glyphs{"J"}} = qw/ ______ ___XX_ ____X_ ____X_ ____X_ X___X_ _XXX__ ______ /; @{$glyphs{"K"}} = qw/ ______ X___X_ X__X__ XXX___ X__X__ X___X_ X___X_ ______ /; @{$glyphs{"L"}} = qw/ ______ X_____ X_____ X_____ X_____ X_____ XXXXX_ ______ /; @{$glyphs{"M"}} = qw/ ______ X___X_ XX_XX_ X_X_X_ X_X_X_ X___X_ X___X_ ______ /; @{$glyphs{"N"}} = qw/ ______ X___X_ XX__X_ X_X_X_ X_X_X_ X__XX_ X___X_ ______ /; @{$glyphs{"O"}} = qw/ ______ _XXX__ X___X_ X___X_ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"P"}} = qw/ ______ XXXX__ X___X_ X___X_ XXXX__ X_____ X_____ ______ /; @{$glyphs{"Q"}} = qw/ ______ _XXX__ X___X_ X___X_ X___X_ X__X__ _XX_X_ ______ /; @{$glyphs{"R"}} = qw/ ______ XXXX__ X___X_ X___X_ XXXX__ X___X_ X___X_ ______ /; @{$glyphs{"S"}} = qw/ ______ _XXXX_ X_____ _XXX__ ____X_ ____X_ XXXX__ ______ /; @{$glyphs{"T"}} = qw/ ______ XXXXX_ __X___ __X___ __X___ __X___ __X___ ______ /; @{$glyphs{"U"}} = qw/ ______ X___X_ X___X_ X___X_ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"V"}} = qw/ ______ X___X_ X___X_ X___X_ X___X_ _X_X__ __X___ ______ /; @{$glyphs{"W"}} = qw/ ______ X___X_ X___X_ X_X_X_ X_X_X_ XX_XX_ _X_X__ ______ /; @{$glyphs{"X"}} = qw/ ______ X___X_ _X_X__ __X___ _X_X__ X___X_ X___X_ ______ /; @{$glyphs{"Y"}} = qw/ ______ X___X_ X___X_ _X_X__ __X___ __X___ __X___ ______ /; @{$glyphs{"Z"}} = qw/ ______ XXXXX_ ___X__ __X___ _X____ X_____ XXXXX_ ______ /; @{$glyphs{"["}} = qw/ ____ XXX_ X___ X___ X___ X___ XXX_ ____ /; @{$glyphs{"\\"}} = qw/ ______ ______ X_____ _X____ __X___ ___X__ ____X_ ______ /; @{$glyphs{"]"}} = qw/ ____ XXX_ __X_ __X_ __X_ __X_ XXX_ ____ /; @{$glyphs{"^"}} = qw/ ____ _X__ X_X_ ____ ____ ____ ____ ____ /; @{$glyphs{"_"}} = qw/ ______ ______ ______ ______ ______ ______ XXXXX_ ______ /; @{$glyphs{"`"}} = qw/ ___ X__ _X_ ___ ___ ___ ___ ___ /; @{$glyphs{"a"}} = qw/ ______ ______ _XXX__ ____X_ _XXXX_ X___X_ _XXXX_ ______ /; @{$glyphs{"b"}} = qw/ ______ X_____ X_____ XXXX__ X___X_ X___X_ XXXX__ ______ /; @{$glyphs{"c"}} = qw/ _____ _____ _XXX_ X____ X____ X____ _XXX_ _____ /; @{$glyphs{"d"}} = qw/ ______ ____X_ ____X_ _XXXX_ X___X_ X___X_ _XXXX_ ______ /; @{$glyphs{"e"}} = qw/ ______ ______ _XXX__ X___X_ XXXXX_ X_____ _XXX__ ______ /; @{$glyphs{"f"}} = qw/ _____ __XX_ _X___ XXX__ _X___ _X___ _X___ _____ /; @{$glyphs{"g"}} = qw/ ______ ______ _XXXX_ X___X_ X___X_ _XXXX_ ____X_ _XXX__ /; @{$glyphs{"h"}} = qw/ ______ X_____ X_____ XXXX__ X___X_ X___X_ X___X_ ______ /; @{$glyphs{"i"}} = qw/ ____ _X__ ____ XX__ _X__ _X__ XXX_ ____ /; @{$glyphs{"j"}} = qw/ ____ __X_ ____ _XX_ __X_ __X_ __X_ XX__ /; @{$glyphs{"k"}} = qw/ _____ X____ X__X_ X_X__ XX___ X_X__ X__X_ _____ /; @{$glyphs{"l"}} = qw/ ____ XX__ _X__ _X__ _X__ _X__ _XX_ ____ /; @{$glyphs{"m"}} = qw/ ______ ______ XX_X__ X_X_X_ X_X_X_ X_X_X_ X___X_ ______ /; @{$glyphs{"n"}} = qw/ ______ ______ XXXX__ X___X_ X___X_ X___X_ X___X_ ______ /; @{$glyphs{"o"}} = qw/ ______ ______ _XXX__ X___X_ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"p"}} = qw/ ______ ______ XXXX__ X___X_ X___X_ XXXX__ X_____ X_____ /; @{$glyphs{"q"}} = qw/ _______ _______ _XXXX__ X___X__ X___X__ _XXXX__ ____X__ _____X_ /; @{$glyphs{"r"}} = qw/ ______ ______ XXXX__ X___X_ X_____ X_____ X_____ ______ /; @{$glyphs{"s"}} = qw/ ______ ______ _XXXX_ X_____ _XXX__ ____X_ XXXX__ ______ /; @{$glyphs{"t"}} = qw/ ____ _X__ XXX_ _X__ _X__ _X__ __X_ ____ /; @{$glyphs{"u"}} = qw/ ______ ______ X___X_ X___X_ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"v"}} = qw/ ______ ______ X___X_ X___X_ X___X_ _X_X__ __X___ ______ /; @{$glyphs{"w"}} = qw/ ______ ______ X___X_ X_X_X_ X_X_X_ X_X_X_ _X_X__ ______ /; @{$glyphs{"x"}} = qw/ _____ _____ X__X_ X__X_ _XX__ X__X_ X__X_ _____ /; @{$glyphs{"y"}} = qw/ ______ ______ X___X_ X___X_ X___X_ _X_X__ __X___ _X____ /; @{$glyphs{"z"}} = qw/ ______ ______ XXXXX_ ___X__ __X___ _X____ XXXXX_ ______ /; @{$glyphs{"{"}} = qw/ ____ __X_ _X__ _X__ X___ _X__ _X__ __X_ /; @{$glyphs{"|"}} = qw/ __ X_ X_ X_ X_ X_ X_ __ /; @{$glyphs{"}"}} = qw/ ____ X___ _X__ _X__ __X_ _X__ _X__ X___ /; @{$glyphs{"~"}} = qw/ ______ ______ ______ _XX_X_ X__X__ ______ ______ ______ /; # end of ASCII, start of Latin-1. first char is a non-breaking space. @{$glyphs{" "}} = qw/ ______ ______ ______ ______ ______ ______ ______ ______ /; @{$glyphs{"¡"}} = qw/ __ X_ __ X_ X_ X_ X_ __ /; @{$glyphs{"¢"}} = qw/ _____ __X__ _XXX_ X_X__ X_X__ _XXX_ __X__ _____ /; @{$glyphs{"£"}} = qw/ ______ __XX__ _X__X_ X_____ _XX___ X_____ XXXXX_ ______ /; @{$glyphs{"¤"}} = qw/ ______ ______ X___X_ _XXX__ _X_X__ _XXX__ X___X_ ______ /; @{$glyphs{"¥"}} = qw/ ______ X___X_ _X_X__ XXXXX_ __X___ XXXXX_ __X___ ______ /; @{$glyphs{"¦"}} = qw/ __ X_ X_ X_ __ X_ X_ X_ /; @{$glyphs{"§"}} = qw/ ______ __XX__ _X____ __X___ _X_X__ __X___ ___X__ _XX___ /; @{$glyphs{"¨"}} = qw/ _____ X__X_ _____ _____ _____ _____ _____ _____ /; @{$glyphs{"©"}} = qw/ ________ _XXXXX__ X_____X_ X__XX_X_ X_X___X_ X__XX_X_ X_____X_ _XXXXX__ /; @{$glyphs{"ª"}} = qw/ _______ _XXX___ ___XX__ _XX_X__ __XXX__ _______ XXXXXX_ _______ /; @{$glyphs{"«"}} = qw/ ______ ______ ______ ______ _X__X_ X__X__ _X__X_ ______ /; @{$glyphs{"¬"}} = qw/ ______ ______ ______ ______ ______ XXXXX_ ____X_ ______ /; @{$glyphs{"­"}} = qw/ ____ ____ ____ ____ XXX_ ____ ____ ____ /; @{$glyphs{"®"}} = qw/ _XXXXX__ X_____X_ X_XX__X_ X_X_X_X_ X_XX__X_ X_X_X_X_ X_____X_ _XXXXX__ /; @{$glyphs{"¯"}} = qw/ _____ XXXX_ _____ _____ _____ _____ _____ _____ /; @{$glyphs{"°"}} = qw/ ______ _XXX__ X___X_ _XXX__ ______ ______ ______ ______ /; @{$glyphs{"±"}} = qw/ ______ ______ __X___ XXXXX_ __X___ ______ XXXXX_ ______ /; @{$glyphs{"²"}} = qw/ ____ XX__ __X_ _X__ XXX_ ____ ____ ____ /; @{$glyphs{"³"}} = qw/ ____ XXX_ _XX_ XXX_ ____ ____ ____ ____ /; @{$glyphs{"´"}} = qw/ ___ _X_ X__ ___ ___ ___ ___ ___ /; @{$glyphs{"µ"}} = qw/ ______ ______ X___X_ X___X_ X___X_ XX__X_ X_XX__ X_____ /; @{$glyphs{"¶"}} = qw/ ______ _XX_X_ XXX_X_ _XX_X_ __X_X_ __X_X_ __X_X_ ______ /; @{$glyphs{"·"}} = qw/ __ __ __ __ X_ __ __ __ /; @{$glyphs{"¸"}} = qw/ ____ ____ ____ ____ ____ _X__ __X_ _X__ /; @{$glyphs{"¹"}} = qw/ ____ XX__ _X__ XXX_ ____ ____ ____ ____ /; @{$glyphs{"º"}} = qw/ ______ ______ ______ _XXX__ X___X_ _XXX__ ______ ______ /; @{$glyphs{"»"}} = qw/ ______ ______ ______ ______ X__X__ _X__X_ X__X__ ______ /; @{$glyphs{"¼"}} = qw/ _______ XX_____ _X_____ XXX____ _______ ___X_X_ ___XXX_ _____X_ /; @{$glyphs{"½"}} = qw/ _______ XX_____ _X_____ XXX____ ____XX_ _____X_ ____X__ ____XX_ /; @{$glyphs{"¾"}} = qw/ ________ XXX_____ _XX_____ XXX_____ ________ ____X_X_ ____XXX_ ______X_ /; @{$glyphs{"¿"}} = qw/ __X___ ______ __X___ _X____ X_____ X___X_ _XXX__ ______ /; @{$glyphs{"À"}} = qw/ _X____ __X___ ______ _XXX__ X___X_ XXXXX_ X___X_ ______ /; @{$glyphs{"Á"}} = qw/ ___X__ __X___ ______ _XXX__ X___X_ XXXXX_ X___X_ ______ /; @{$glyphs{"Â"}} = qw/ __X___ _X_X__ ______ _XXX__ X___X_ XXXXX_ X___X_ ______ /; @{$glyphs{"Ã"}} = qw/ __XX_X_ _X__X__ _______ _XXX___ X___X__ XXXXX__ X___X__ _______ /; @{$glyphs{"Ä"}} = qw/ _X_X__ ______ __X___ _X_X__ X___X_ XXXXX_ X___X_ ______ /; @{$glyphs{"Å"}} = qw/ __X____ _X_X___ __X____ _X_X___ X___X__ XXXXX__ X___X__ _______ /; @{$glyphs{"Æ"}} = qw/ ______ __XXX_ _X_X__ X__X__ XXXXX_ X__X__ X__XX_ ______ /; @{$glyphs{"Ç"}} = qw/ ______ _XXXX_ X_____ X_____ X_____ _XXXX_ ___X__ __X___ /; @{$glyphs{"È"}} = qw/ _X____ __X___ XXXXX_ X_____ XXXX__ X_____ XXXXX_ ______ /; @{$glyphs{"É"}} = qw/ ___X__ __X___ XXXXX_ X_____ XXXX__ X_____ XXXXX_ ______ /; @{$glyphs{"Ê"}} = qw/ __X___ _X_X__ XXXXX_ X_____ XXXX__ X_____ XXXXX_ ______ /; @{$glyphs{"Ë"}} = qw/ _X_X__ ______ XXXXX_ X_____ XXXX__ X_____ XXXXX_ ______ /; @{$glyphs{"Ì"}} = qw/ X___ _X__ ____ XXX_ _X__ _X__ XXX_ ____ /; @{$glyphs{"Í"}} = qw/ __X_ _X__ ____ XXX_ _X__ _X__ XXX_ ____ /; @{$glyphs{"Î"}} = qw/ _X__ X_X_ ____ XXX_ _X__ _X__ XXX_ ____ /; @{$glyphs{"Ï"}} = qw/ ____ X_X_ ____ XXX_ _X__ _X__ XXX_ ____ /; @{$glyphs{"Ð"}} = qw/ ______ XXXX__ X___X_ X___X_ XXX_X_ X___X_ XXXX__ ______ /; @{$glyphs{"Ñ"}} = qw/ __X_X_ _X_X__ X___X_ XX__X_ X_X_X_ X__XX_ X___X_ ______ /; @{$glyphs{"Ò"}} = qw/ _X____ __X___ _XXX__ X___X_ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"Ó"}} = qw/ ___X__ __X___ _XXX__ X___X_ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"Ô"}} = qw/ __X___ _X_X__ _XXX__ X___X_ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"Õ"}} = qw/ __XX_X_ _X__X__ _XXX___ X___X__ X___X__ X___X__ _XXX___ _______ /; @{$glyphs{"Ö"}} = qw/ _X_X__ ______ _XXX__ X___X_ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"×"}} = qw/ _____ _____ _____ X__X_ _XX__ X__X_ _____ _____ /; @{$glyphs{"Ø"}} = qw/ ________ __XXX_X_ _X___X__ _X__XX__ _X_X_X__ _XX__X__ X_XXX___ ________ /; @{$glyphs{"Ù"}} = qw/ _X____ __X___ X___X_ X___X_ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"Ú"}} = qw/ ___X__ __X___ X___X_ X___X_ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"Û"}} = qw/ ___X____ __X_X___ X_____X_ X_____X_ X_____X_ X_____X_ _XXXXX__ ________ /; @{$glyphs{"Ü"}} = qw/ _X_X__ ______ X___X_ X___X_ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"Ý"}} = qw/ ___X__ __X___ X___X_ _X_X__ __X___ __X___ __X___ ______ /; @{$glyphs{"Þ"}} = qw/ ______ ______ X_____ XXXX__ X___X_ XXXX__ X_____ ______ /; @{$glyphs{"ß"}} = qw/ ______ _XXX__ X___X_ XXXX__ X___X_ X___X_ X_XX__ ______ /; @{$glyphs{"à"}} = qw/ _X____ __X___ _XXX__ ____X_ _XXXX_ X___X_ _XXXX_ ______ /; @{$glyphs{"á"}} = qw/ ___X__ __X___ _XXX__ ____X_ _XXXX_ X___X_ _XXXX_ ______ /; @{$glyphs{"â"}} = qw/ __X___ _X_X__ _XXX__ ____X_ _XXXX_ X___X_ _XXXX_ ______ /; @{$glyphs{"ã"}} = qw/ __XX_X_ _X__X__ _______ _XXX___ ___XX__ _XX_X__ __XXX__ _______ /; @{$glyphs{"ä"}} = qw/ _X_X__ ______ _XXX__ ____X_ _XXXX_ X___X_ _XXXX_ ______ /; @{$glyphs{"å"}} = qw/ __XX___ _X__X__ __XX___ _XXX___ ___XX__ _XX_X__ __XXX__ _______ /; @{$glyphs{"æ"}} = qw/ ________ ________ _XX_XX__ ___X__X_ _XXXXXX_ X__X____ _XX_XXX_ ________ /; @{$glyphs{"ç"}} = qw/ _____ _____ _XXX_ X____ X____ _XXX_ __X__ _X___ /; @{$glyphs{"è"}} = qw/ _X____ __X___ _XXX__ X___X_ XXXXX_ X_____ _XXX__ ______ /; @{$glyphs{"é"}} = qw/ ___X__ __X___ _XXX__ X___X_ XXXXX_ X_____ _XXX__ ______ /; @{$glyphs{"ê"}} = qw/ __X___ _X_X__ _XXX__ X___X_ XXXXX_ X_____ _XXX__ ______ /; @{$glyphs{"ë"}} = qw/ _X_X__ ______ _XXX__ X___X_ XXXXX_ X_____ _XXX__ ______ /; @{$glyphs{"ì"}} = qw/ X___ _X__ ____ XX__ _X__ _X__ XXX_ ____ /; @{$glyphs{"í"}} = qw/ __X_ _X__ ____ XX__ _X__ _X__ XXX_ ____ /; @{$glyphs{"î"}} = qw/ _X__ X_X_ ____ XX__ _X__ _X__ XXX_ ____ /; @{$glyphs{"ï"}} = qw/ ____ X_X_ ____ XX__ _X__ _X__ XXX_ ____ /; @{$glyphs{"ð"}} = qw/ X_X___ _XX___ X__X__ ____X_ _XXXX_ X___X_ _XXXX_ ______ /; @{$glyphs{"ñ"}} = qw/ _XX_X_ X__X__ ______ XXXX__ X___X_ X___X_ X___X_ ______ /; @{$glyphs{"ò"}} = qw/ _X____ __X___ ______ _XXX__ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"ó"}} = qw/ ___X__ __X___ ______ _XXX__ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"ô"}} = qw/ __X___ _X_X__ ______ _XXX__ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"õ"}} = qw/ __XX_X_ _X__X__ _______ _XXX___ X___X__ X___X__ _XXX___ _______ /; @{$glyphs{"ö"}} = qw/ ______ _X_X__ ______ _XXX__ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"÷"}} = qw/ ____ ____ _X__ ____ XXX_ ____ _X__ ____ /; @{$glyphs{"ø"}} = qw/ ________ ________ __XXX_X_ _X__XX__ _X_X_X__ _XX__X__ X_XXX___ ________ /; @{$glyphs{"ù"}} = qw/ _X____ __X___ ______ X___X_ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"ú"}} = qw/ ___X__ __X___ ______ X___X_ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"û"}} = qw/ __X___ _X_X__ ______ X___X_ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"ü"}} = qw/ ______ _X__X_ ______ X___X_ X___X_ X___X_ _XXX__ ______ /; @{$glyphs{"ý"}} = qw/ ______ ___X__ __X___ X___X_ X___X_ _X_X__ __X___ _X____ /; @{$glyphs{"þ"}} = qw/ _____ X____ XXX__ X__X_ X__X_ XXX__ X____ _____ /; @{$glyphs{"ÿ"}} = qw/ ______ _X_X__ ______ X___X_ X___X_ _X_X__ __X___ _X____ /; # end of Latin-1. a few misc emoji glyphs here. @{$glyphs{"☺"}} = qw/ _XXXXXXX__ X_______X_ X_XX_XX_X_ X_______X_ X_X___X_X_ X__XXX__X_ X_______X_ _XXXXXXX__ /; @{$glyphs{"☹"}} = qw/ _XXXXXXX__ X_______X_ X_XX_XX_X_ X_______X_ X__XXX__X_ X_X___X_X_ X_______X_ _XXXXXXX__ /; ## @{$glyphs{"☺"}} = qw/ ## ________ ## _XXXXX__ ## X__X__X_ ## XXXXXXX_ ## X_XXX_X_ ## XX___XX_ ## _XXXXX__ ## ________ ## /; ## @{$glyphs{"☮"}} = qw/ _XXXXXXX__ X___X___X_ X___X___X_ X__XXX__X_ X_X_X_X_X_ XX__X__XX_ X___X___X_ _XXXXXXX__ /; ## @{$glyphs{"☮"}} = qw/ ## ________ ## _XXXXX__ ## X__X__X_ ## X_XXX_X_ ## XX_X_XX_ ## X__X__X_ ## _XXXXX__ ## ________ ## /; @{$glyphs{"☯"}} = qw/ _XXXXXXXX__ XXXXXX___X_ XX_XX____X_ XXXX_____X_ XXXXX____X_ XXXX___X_X_ XXX______X_ _XXXXXXXX__ /; for my $k (sort keys %glyphs) { my @g = @{$glyphs{$k}}; # this is needed to print $k correctly in irssi. if(__PACKAGE__ ne 'main') { utf8::encode($k); } my $width = length($g[0]); for(@g) { if(/([^X_])/) { die "glyph for $k has invalid definition char '$1' (not X or _)!"; } die "glyph for $k has inconsistent width!" unless length == $width; die "glyph for $k doesn't have blank rightmost column" if /X$/; } if(@g != 8) { die "glyph for $k not 8 lines tall!"; } } }