''' Created on Mar 18, 2018 @author: Brett Paufler Copyright Brett Paufler Archived: 2021-02-21 A semi-reimplementation of pyfiglet For use in/on BrettGames webpages as a header A is for ASCII (another abandoned work of mine) As of 3-18-18, all files in ./fig_fonts (on my computer) are from the pyfiglet distribution. And hence, All my .flf fonts are GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Indivisual Results May Vary # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 2021-02-21 I could not get pyfiglet to work as I desired. So, I made a passable replacement that fit my needs. The sole purpose was to create ASCII ART HEADERS. It works. But it turns out, I don't care about those Headers. I have not used very many. Please see if __name__ == "__main__" at bottom for simple use cases IrfanView is needed to save txt as png But that portion is easy to comment out ''' from os import listdir, system from os.path import join as path_join #I rename this alot from os.path import basename, splitext, abspath class All_Fonts(object): '''A holding class for all fonts in font_dir.''' def __init__(self): '''Processes all font files at once.''' self.fig = [] font_dir = './/fig_fonts//' #HARDWIRED #Where are the fonts located? self.font_paths = [ path_join(font_dir, f) for f in listdir(font_dir) if splitext(f)[1] == '.flf' ] #List of the actual .flf fonts #Font() pulls the font text from an .flf file self.font_list = [ Font(f) for f in self.font_paths if Font(f) is not None] def phrase_to_all(self, phrase, only_these_fonts=[]): '''saves text file of passed "phrase" for all fonts But if a list of font names passed is passed to only_these_fonts, then only those are used ''' if only_these_fonts: these_fonts = [f for f in self.font_list if f.name in only_these_fonts] else: these_fonts = self.font_list for font in these_fonts: font.create_fig(phrase) font.save_text() class Font(object): """.flf files are converted to Strings, which can be used as fonts.""" def __init__(self, file_path): #For simplicity #Only figlet fonts allowed in directory if not file_path.endswith('.flf'): error = 'Non Figlet File In Directory:\n\t%s' % file_path raise ValueError(error) #Name without Directory or Extension self.name = splitext(basename(file_path))[0] #print self.name #Extracts text from file with open(file_path) as f: self.text_raw = f.read() #Processes Header Information self.process_figlet_header() #Parses the font file into a dictionary self.create_font_mapping() def process_figlet_header(self): """I did not comment this back when originally coded So hopefully, I chose good names.""" header = self.text_raw.split('\n')[0] h_info = header.split(' ') self.signature = h_info[0][:-1] self.hardblank = h_info[0][-1] self.height = int(h_info[1]) self.baseline = int(h_info[2]) self.max_length = int(h_info[3]) self.old_layout = int(h_info[4]) self.comment_lines = int(h_info[5]) #A Mapping is a Dictionary #It's a lot of munging, making the code quite brittle. def create_font_mapping(self): #Deletes Header and Comment Lines skip = 1 + self.comment_lines text = '\n'.join( self.text_raw.split('\n')[skip:]) #Typically, this is '@' #Less commonly, '#' #But sometimes, it names the letter 'A', 'B', etc delimiter = text.split('\n')[0][-1] text = text.replace('\n', '') text = text.replace('\r', '') #The important part #{A:'xxx',B:'xxx', I would guess #Meaning, I expect Caplital Letters as Keys self.map = {} #I only care about the Base Letters (A-Z) #As Special Characters are often skipped in the .flf letters = text.split(2* delimiter)[:94] for num, letter in enumerate(letters): #starting with space num += 32 #32 is ASCII code point for space lines = letter.split(delimiter) max_len = max([len(line) for line in lines]) #print num #Insure Width of each line is equal lines = [ line + ' '*(max_len - len(line)) for line in lines] #Replaces hardblanks with spaces lines = [ line.replace(self.hardblank, ' ') for line in lines] #Replaces Blank Lines with space lines = [ line.replace('', ' ') for line in lines] self.map[chr(num)] = lines if num >= 126: break #Outputs ASCII ART String def create_fig(self, phrase): """Converts String "Phrase" to String Art""" print self.name, phrase phrase_map = [self.map[letter] for letter in phrase] #All letter same height #So, add extra lines to bottom max_height = max([ len(letter) for letter in phrase_map]) phrase_map = [ letter + [' '] * (max_height - len(letter)) for letter in phrase_map] #All lines in letter same length #So, add padding spaces (' ') to end of lines for letter in phrase_map: max_chars = max([ len(line) for line in letter]) letter = [ line + ' ' * (max_chars - len(line)) for line in letter] fig = [''] * max_height for letter in phrase_map: for i, line in enumerate(letter): fig[i] = fig[i] + line self.fig = '\n'.join(fig) #For blank top line self.fig = '\n' + self.fig def save_text(self): """Outputs our work (THE ASCII ART) to file.""" #Saves The Raw Text File save_name_txt = '.\output\%s.txt' % self.name save_name_txt = abspath(save_name_txt) with open(save_name_txt, 'w') as f: f.write(self.fig) #Saves Text as an Image #Images Auto Resize, so often better for webpages #Uses IrfanView save_name_png = '.\output\%s.png' % self.name save_name_png = abspath(save_name_png) path_irfanview = '"C:\Program Files\IrfanView\i_view64.exe" ' command = '%s %s /convert=%s' % ( path_irfanview, save_name_txt, save_name_png) print command #Let's have some feedback system(command) #Saves with   for blanks #Thus, the resultant text is HTML ready save_name_nbsp = '.\output\%s_nbsp.txt' % self.name save_name_nbsp = abspath(save_name_nbsp) nbsp_text = self.fig.replace(' ', ' ') nbsp_text = nbsp_text.replace('\n', '
\n') with open(save_name_nbsp, 'w') as f: f.write(nbsp_text) if __name__ == '__main__': #phrase is the string to be converted to ASCII ART #phrase = 'MEGALOPOLIS' #phrase = "Whatever" phrase = "ABCD EFGH IGKL MNOP QRST UVW XYZ" select_fonts = [] #select_fonts = ['tomahawk'] #A blanket initialization works all_fonts = All_Fonts() #Optional #select_fonts = ['this font', 'that font'] #select_fonts = ["base file name 1", "next"] #select_fonts =[] #Do It! all_fonts.phrase_to_all(phrase, select_fonts)