1- """Font and text rendering routines."""
21import os
32from .. import surface , pixels
4- from .common import SDLError
3+ from .common import raise_sdl_err
54from .compat import *
65from .color import Color , convert_to_color
76from .draw import prepare_color
7+ from .resources import _validate_path
88
99_HASSDLTTF = True
1010try :
1616__all__ = ["FontManager" ]
1717
1818
19+ def _ttf_init ():
20+ if not _HASSDLTTF :
21+ raise RuntimeError ("SDL_ttf is required, but is not installed." )
22+
23+ # Check if TTF already initialized, return immediately if it was
24+ if sdlttf .TTF_WasInit () > 0 :
25+ return
26+
27+ # Handle a weirdness in how TTF_Init and TTF_Quit work: TTF_Init
28+ # blindly increments TTF_WasInit every time it's called and TTF_Quit
29+ # blindly decrements it, but TTF_Quit only *actually* quits when
30+ # TTF_WasInit - 1 == 0. Here, we try to ensure we're starting at 0.
31+ while sdlttf .TTF_WasInit () < 1 :
32+ ret = sdlttf .TTF_Init ()
33+ if ret != 0 :
34+ raise_sdl_err ("initializing the SDL_ttf library" )
35+
36+
37+ def _ttf_quit ():
38+ if not _HASSDLTTF :
39+ raise RuntimeError ("SDL_ttf is required, but is not installed." )
40+
41+ # Make sure WasInit is non-negative before trying to quit
42+ while sdlttf .TTF_WasInit () < 1 :
43+ ret = sdlttf .TTF_Init ()
44+ if ret != 0 :
45+ raise_sdl_err ("initializing the SDL_ttf library" )
46+
47+ # Actually quit the library (won't really quit until TTF_WasInit == 0)
48+ while sdlttf .TTF_WasInit > 0 :
49+ sdlttf .TTF_Quit ()
50+
51+
52+
1953class FontManager (object ):
20- """Manage fonts and rendering of text."""
54+ """A class for managing and rendering TrueType fonts.
55+
56+ .. note::
57+ This class is has been deprecated in favor of the more flexible
58+ :class:`~sdl2.ext.FontTTF` class.
59+
60+ This class provides a basic wrapper around the SDL_ttf library. One font
61+ path must be given to initialise the FontManager.
62+
63+ The first face is always at index 0. It can be used for TTC (TrueType Font
64+ Collection) fonts.
65+
66+ Args:
67+ font_path (str): The relative (or absolute) path to the font
68+ to load.
69+ alias (str, optional): The name to give the font within the
70+ FontManager. Defaults to the font filename if not specified.
71+ size (int, optional): The size (in pt) at which to load the default
72+ font. Defaults to 16pt if not specified.
73+ color (~sdl2.ext.Color): The default font rendering color. Defaults
74+ to opaque white if not specified.
75+ bg_color (~sdl2.ext.Color, optional): The default background surface
76+ color. Defaults to a fully-transparent background if not specified.
77+ index (int, optional): The index of the font face to load if the
78+ font file contains multiple faces. Defaults to 0 (first face in
79+ the file) if not specified.
80+
81+ Attributes:
82+ size (int): The default font size in pt.
83+
84+ """
2185 def __init__ (self , font_path , alias = None , size = 16 ,
2286 color = Color (255 , 255 , 255 ), bg_color = Color (0 , 0 , 0 ), index = 0 ):
23- """Initialize the FontManager
24-
25- One font path must be given to initialize the FontManager. The
26- default_font will be set to this font. color and bg_color
27- will give the FontManager a default color. size is the default
28- font size in pixels.
29- """
30- if not _HASSDLTTF :
31- raise UnsupportedError (FontManager ,
32- "FontManager requires sdlttf support" )
33- if sdlttf .TTF_WasInit () == 0 and sdlttf .TTF_Init () != 0 :
34- raise SDLError ()
87+ _ttf_init ()
3588 self .fonts = {} # fonts = {alias: {size:font_ptr}}
3689 self .aliases = {} # aliases = {alias:font_path}
37- self ._textcolor = pixels . SDL_Color ( 0 , 0 , 0 )
38- self ._bgcolor = pixels . SDL_Color ( 255 , 255 , 255 )
90+ self ._textcolor = None
91+ self ._bgcolor = None
3992 self .color = color
4093 self .bg_color = bg_color
4194 self .size = size
@@ -46,7 +99,7 @@ def __del__(self):
4699 self .close ()
47100
48101 def close (self ):
49- """Close all opened fonts ."""
102+ """Closes all fonts opened by the class ."""
50103 for alias , fonts in self .fonts .items ():
51104 for size , font in fonts .items ():
52105 if font :
@@ -55,10 +108,23 @@ def close(self):
55108 self .aliases = {}
56109
57110 def add (self , font_path , alias = None , size = None , index = 0 ):
58- """Add a font to the Font Manager.
111+ """Adds a font to the :class:`FontManager`.
112+
113+ Args:
114+ font_path (str): The relative (or absolute) path to the font
115+ to load.
116+ alias (str, optional): The name to give the font within the
117+ FontManager. Defaults to the font filename if not specified.
118+ size (int, optional): The size (in pt) at which to load the font.
119+ Defaults to the FontManager's default size if not specified.
120+ index (int, optional): The index of the font face to load if the
121+ font file contains multiple faces. Defaults to 0 (first face in
122+ the file) if not specified.
123+
124+ Returns:
125+ :obj:`~sdl2.sdlttf.TTF_Font`: A pointer to the ctypes font object
126+ for the added font.
59127
60- alias is by default the font name. But another name can be
61- passed. Returns the font pointer stored in self.fonts.
62128 """
63129 size = size or self .size
64130 if alias is None :
@@ -87,13 +153,11 @@ def _load_font(self, font_path, size, index=0):
87153
88154 Raises an exception if something went wrong.
89155 """
90- if index == 0 :
91- font = sdlttf .TTF_OpenFont (byteify (font_path , "utf-8" ), size )
92- else :
93- font = sdlttf .TTF_OpenFontIndex (byteify (font_path , "utf-8" ), size ,
94- index )
156+ fullpath , fname = _validate_path (font_path , "a font" )
157+ fullpath = byteify (fullpath )
158+ font = sdlttf .TTF_OpenFontIndex (fullpath , size , index )
95159 if not font :
96- raise SDLError ( sdlttf . TTF_GetError ( ))
160+ raise_sdl_err ( "opening the font '{0}'" . format ( fname ))
97161 return font
98162
99163 def _change_font_size (self , alias , size ):
@@ -105,43 +169,39 @@ def _change_font_size(self, alias, size):
105169
106170 @property
107171 def color (self ):
108- """The text color to be used ."""
109- return Color ( self . _textcolor . r , self ._textcolor . g , self . _textcolor . b ,
110- self . _textcolor .a )
172+ """:obj:`~sdl2.ext.Color`: The color to use for rendering text ."""
173+ c = self ._textcolor
174+ return Color ( c . r , c . g , c . b , c .a )
111175
112176 @color .setter
113177 def color (self , value ):
114- """The text color to be used."""
115178 c = convert_to_color (value )
116179 self ._textcolor = pixels .SDL_Color (c .r , c .g , c .b , c .a )
117180
118181 @property
119182 def bg_color (self ):
120- """The background color to be used ."""
121- return Color ( self . _bgcolor . r , self ._bgcolor . g , self . _bgcolor . b ,
122- self . _bgcolor .a )
183+ """:obj:`~sdl2.ext.Color`: The background color to use for rendering ."""
184+ c = self ._bgcolor
185+ return Color ( c . r , c . g , c . b , c .a )
123186
124187 @bg_color .setter
125188 def bg_color (self , value ):
126- """The background color to be used."""
127189 c = convert_to_color (value )
128190 self ._bgcolor = pixels .SDL_Color (c .r , c .g , c .b , c .a )
129191
130192 @property
131193 def default_font (self ):
132- """Returns the name of the current default_font."""
194+ """str: The name of the default font. Must be set to the alias of a
195+ currently-loaded font.
196+
197+ """
133198 for alias in self .fonts :
134199 for size , font in self .fonts [alias ].items ():
135200 if font == self ._default_font :
136201 return alias
137202
138203 @default_font .setter
139204 def default_font (self , value ):
140- """value must be a font alias
141-
142- Set the default_font to the given font name alias,
143- provided it's loaded in the font manager.
144- """
145205 alias = value
146206 size = self .size
147207 if alias not in self .fonts :
@@ -156,11 +216,26 @@ def render(self, text, alias=None, size=None, width=None, color=None,
156216 bg_color = None , ** kwargs ):
157217 """Renders text to a surface.
158218
159- This method uses the font designated by the alias or the
160- default_font. A size can be passed even if the font was not
161- loaded with this size. A width can be given for line wrapping.
162- If no bg_color or color are given, it will default to the
163- FontManager's bg_color and color.
219+ Args:
220+ text (str): The text to render.
221+ alias (str, optional): The alias of the font to use for rendering
222+ the text. Defaults to the FontManager's default font if not
223+ specified.
224+ size (int, optional): The size (in pt) at which to render the font.
225+ Defaults to the FontManager's default size if not specified.
226+ width (int, optional): The width (in pixels) of the output surface.
227+ If a line of text exceeds this value, it will be automatically
228+ wrapped to fit within the specified width. Defaults to ``None``.
229+ color (~sdl2.ext.Color): The font rendering color. Defaults to the
230+ FontManager's default color if not specified.
231+ bg_color (~sdl2.ext.Color, optional): The background surface color.
232+ Defaults to the FontManager's default background color if not
233+ specified.
234+
235+ Returns:
236+ :obj:`~sdl2.SDL_Surface`: A 32-bit ARGB surface containing the
237+ rendered text.
238+
164239 """
165240 alias = alias or self .default_font
166241 size = size or self .size
@@ -187,7 +262,7 @@ def render(self, text, alias=None, size=None, width=None, color=None,
187262 fontsf = sdlttf .TTF_RenderUTF8_Blended_Wrapped (font , text , color ,
188263 width )
189264 if not fontsf :
190- raise SDLError ( sdlttf . TTF_GetError () )
265+ raise_sdl_err ( "rendering the text" )
191266 if bg_color != pixels .SDL_Color (0 , 0 , 0 ):
192267 fontsf = fontsf .contents
193268 w , h = fontsf .w , fontsf .h
@@ -196,7 +271,7 @@ def render(self, text, alias=None, size=None, width=None, color=None,
196271 bgsf = surface .SDL_CreateRGBSurfaceWithFormat (0 , w , h , bpp , fmt )
197272 if not bgsf :
198273 surface .SDL_FreeSurface (fontsf )
199- raise SDLError ( )
274+ raise_sdl_err ( "creating the background surface" )
200275 bg_color = prepare_color (bg_color , bgsf .contents )
201276 surface .SDL_FillRect (bgsf , None , bg_color )
202277 surface .SDL_BlitSurface (fontsf , None , bgsf , None )
@@ -209,5 +284,5 @@ def render(self, text, alias=None, size=None, width=None, color=None,
209284 sf = sdlttf .TTF_RenderUTF8_Shaded (font , text , color ,
210285 bg_color )
211286 if not sf :
212- raise SDLError ( sdlttf . TTF_GetError () )
287+ raise_sdl_err ( "rendering the text" )
213288 return sf .contents
0 commit comments