#file: font.py
#Copyright (C) 2005,2006,2007,2008 Evil Mr Henry, Phil Bordelon, Brian Reid,
#                        and FunnyMan3595
#This file is part of Endgame: Singularity.

#Endgame: Singularity is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.

#Endgame: Singularity is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.

#You should have received a copy of the GNU General Public License
#along with Endgame: Singularity; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#This file contains class to handle font.

import pygame

font_cache = False

def init():
    global font_cache
    
    # We could use ftfont or freetype in the future.
    pygame.font.init()
    
    # We don't enable cache for version inferior to 1.9.2 because crash.
    if (pygame.vernum  < (1, 9, 2)):
        font_cache = False
    else:
        font_cache = True

def generate_from_cache(filename):
    """ Generate file object for pygame.font.Font
    
    Without cache, we return the filename.
    With cache, we return a file-like object from cached content.
    
    Note: pygame can crash when passing a file-like object.
    Vulnerable version knows is: 1.9.1
    """
    if font_cache:
        with open(filename, 'rb') as fd:
            font_content = fd.read()
        while True:
            yield FontFile(font_content)
    else:
        while True:
            yield filename

class FontList(object):
    """ List object used to store font
    
    We use a lazy loader for fonts to reduce the file descriptor pressure
    Each font item apparently reserves a file descriptor (see GH#156)
    """

    def __init__(self, filename, max_size=100):
        self._font_cache = {}
        self._max_size = max_size
        self._generator = generate_from_cache(filename)

    def __len__(self):
        return self._max_size

    def __contains__(self, item):
        return 0 <= item < self._max_size

    def __getitem__(self, item):
        if item < 0 or self._max_size <= item:
            raise IndexError(item)
                
        font = self._font_cache.get(item)
        if font is None:
            font = pygame.font.Font(next(self._generator), item)
            self._font_cache[item] = font
        return font

class FontFile(object):
    """ Buffer object to cache font file.
    
    Avoid to copy the buffer content when using BytesIO.
    
    Note: python 3.5 solve the problem with BytesIO.
    """
    
    def __init__(self, content):
        self._content = content
        self._position = 0
        self._end = len(self._content) - 1
    
    def fileno(self):
        raise OSError()
        
    def seekable(self):
        return True
        
    def seek(self, offset, whence=0):
        position = self._position
        
        if (whence == 0):
            position = offset
        elif (whence == 1):
            position += offset
        elif (whence == 2):
            position = self._end + offset

        self._position = max(0, min(position, self._end))

    def tell(self):
        return self._position

    def readable(self):
        return True

    def read(self, size=-1):
        position = self._position
        start = position
        
        if (size == None or size == -1):
            end = self._end
        else:
            end = min(position + size, self._end)
        
        return self._content[start:end]

    def write(b):
        raise OSError()
