#!/usr/bin/env python

"""
usage:
    font_browser
    font_browser x.ttf y.ttf
    font_browser *
    font_browser fontdir/*
    font_browser "*"

Usage 1 loads all TTF fonts in the current directory and subdirectories one
level deep.

Usage 2 loads all named files.

Usage 3 loads all TTF files (that match *.ttf, case insensitive).

Usage 4 loads all TTF files in fontdir (that match *.ttf, case insensitive).

Usage 5 is the same as usage 3, except Python's glob is used to match files.

Controls:
    MOUSESCROLL DOWN/UP     Next, previous font
    MOUSECLICK RIGHT/LEFT   Increase, decrease font size
    RIGHT, LEFT             Next, previous font
    UP, DOWN                Increase, decrease size
    a                       Antialias rendering
"""


import glob
import os
import sys
import pygame
from pygame.locals import *


# Starting position in the font list if you don't want to start at zero. Convenient
# if you're in the process of weeding out bad fonts.
start_pos = 0


# This program will avoid the fonts in this list.
bad_font_list = (
    'aharoni',
    'aparajitaitali',
    'cambria',
    'kokilaitali',
    'lucidahandwriting',
    'maiandragddemi',
    'meiryomeiryoboldmeiryouiboldmeiryouibolditalic',
    'meiryomeiryomeiryouimeiryouiitalic',
    'msreferencesansserif',
    'rockwellextra',
    'utsaahitali',
    'vivaldi',
)


##                         ##
##                         ##
##  No more configurables  ##
##                         ##
##                         ##


def is_bad_font(name):
    return name not in bad_font_list


def do_key(key):
    global n, name, size, antialias, font
    dirty = 1
    if key == K_a:
        antialias = antialias == False
    elif key == K_LEFT:
        if n > 0:
            n -= 1
        else:
            n = len(font_list) - 1
        name = font_list[n]
    elif key == K_RIGHT:
        if n < len(font_list) - 1:
            n += 1
        else:
            n = 0
        name = font_list[n]
    elif key == K_UP:
        size += 1
    elif key == K_DOWN:
        if size > 5:
            size -= 1
    else:
        dirty = 0

    return dirty


def do_mouse_down(button):
    global n, name, mouse1, mouse3
    dirty = 1
    if button == 4:
        if n > 0:
            n -= 1
        else:
            n = len(font_list) - 1
        name = font_list[n]
    elif button == 5:
        if n < len(font_list) - 1:
            n += 1
        else:
            n = 0
        name = font_list[n]
    elif button == 1:
        mouse1 -= 1
    elif button == 3:
        mouse3 += 1
    else:
        dirty = 0

    return dirty


def do_mouse_up(button):
    global n, name, mouse1, mouse3
    dirty = 1
    if button == 1:
        mouse1 += 1
    elif button == 3:
        mouse3 -= 1
    else:
        dirty = 0

    return dirty


def make_font(name, size):
    # if this hangs, manually add the name to bad_font_list
    print('loading font {}: {}'.format(n, name))
    return pygame.font.Font(name, size)


def draw(lines):
    screen.fill((0, 0, 0))
    y = 5
    yspace = 3
    for i, line in enumerate(lines):
        im = font.render(line, antialias, Color('white'))
        screen.blit(im, (5, y))
        y += font.get_height() + yspace
    pygame.display.flip()


def set_caption():
    pygame.display.set_caption('{}/{}: {} {} {}'.format(
        n + 1, nr_fonts, size,
        aa_display[antialias],
        name))


##                ##
##                ##
##  Main program  ##
##                ##
##                ##

os.environ['SDL_VIDEO_CENTERED'] = '1'
pygame.init()
screen = pygame.display.set_mode((800,600))

texts = (
    'ABCDEFGHIJKLMNOPQRTUVWXYZ',
    'abcdefghijklmnopqrtuvwxyz',
    '1234567890`~!@#$%^&*()-_=+[]{}\\|;:\'",.<>/?',
)

style_display = {
    (False,False) : 'Normal',
    (True,False) : 'Bold',
    (False,True) : 'Italic',
    (True,True) : 'Bold Italic',
}

aa_display = {
    True : 'AA',
    False : 'No_AA',
}

if len(sys.argv) > 1:
    font_list = []
    for g in sys.argv:
        font_list.extend(
            [f for f in glob.glob(g)
                if f not in bad_font_list and f.lower().endswith('.ttf')])
else:
    font_list = list([f for f in glob.glob('*') + glob.glob('*/*')
                  if f not in bad_font_list and f.lower().endswith('.ttf')])
font_list.sort()
n = start_pos
nr_fonts = len(font_list)
name = font_list[n]
size = 13
antialias = True
font = None
dirty = 0
mouse1 = 0
mouse3 = 0

set_caption()
font = make_font(name, size)
draw(texts)

while 1:
    for e in pygame.event.get():
        if e.type == QUIT:
            quit()
        elif e.type == KEYDOWN:
            dirty += do_key(e.key)
        elif e.type == MOUSEBUTTONDOWN:
            dirty += do_mouse_down(e.button)
        elif e.type == MOUSEBUTTONUP:
            dirty += do_mouse_up(e.button)
    if mouse1 + mouse3:
        size += mouse1 + mouse3
        if size < 5:
            size = 5
        else:
            dirty = 1
    if dirty:
        set_caption()
        font = make_font(name, size)
        draw(texts)
        dirty = 0
    pygame.time.wait(100)
