pyxora.wrapper.text
1from .functions import vector 2from ..assets import Assets 3from ..utils import engine 4 5from typing import Union,Tuple 6from collections import OrderedDict 7 8import pygame 9 10text_sizes = { 11 1, 2, 4, 8, 10, 12, 12 14, 16, 18, 24, 32, 13 48, 64, 72, 96, 128, 14 144, 192, 256 15} 16"""The available text sizes""" 17 18class Text: 19 """ 20 A class for rendering text 21 22 Supports caching of fonts and rendered surfaces for performance, 23 alignment options, scaling (zoom), and limiting cache size. 24 """ 25 26 surfaces: dict = OrderedDict() 27 """The surfaces cache""" 28 _cache_limit = 10000 # default surface cache limit is 10000 29 30 def __init__( 31 self,text: str,pos: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3,color: str | tuple, 32 font_name: str=pygame.font.get_default_font().split(".")[0],size: int= 24,align: str= "left") -> None: 33 """ 34 Initialize a Text object. 35 36 Args: 37 pos (pos: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3): The position of the text. 38 text (str): The string to render. 39 color (str or tuple): The color of the text. 40 font_name (str): The text font name. 41 size (int): Font size. 42 align (str): Alignment of the text: "left", "center", or "right". 43 """ 44 size = self.__fix_size(size) 45 font = self.__get_font(font_name,size) 46 47 self._text = text 48 self._pos = vector(*pos) 49 self._color = color 50 self._font_name = font_name 51 52 self._font = font 53 self._size = size 54 55 self._zoom = 1 56 self._zoom_surface = None # cache the zoom_surface for performance 57 58 # Initialize the surface cache 59 self._cache_surface() if(font,text) not in self.surfaces else setattr(self,"_surface",self.surfaces[(font,text)]) 60 61 # change the position of the text based on the alignment 62 self._align_pos(align) 63 64 @classmethod 65 def set_cache(cls,new_limit: int) -> None: 66 """ 67 Set the maximum number of cached surfaces. 68 Note: Default is 10000, but can be increased or decreased as needed. 69 70 Args: 71 new_limit (int): New cache size limit. 72 """ 73 cls._cache_limit = new_limit 74 75 @classmethod 76 def get_cache(cls) -> int: 77 """ 78 Get the number of cached surfaces. 79 80 Returns: 81 int: The number of cached surfaces. 82 """ 83 return len(cls.surfaces) 84 85 @classmethod 86 def clear_cache(cls) -> None: 87 """ 88 Clear all cached text surfaces. 89 """ 90 cls.surfaces.clear() 91 92 @classmethod 93 def font_size_for(cls,text: str, size: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3, font_name: str) -> int: 94 """ 95 Calculates the largest font size that fits the text inside a given area. 96 97 Args: 98 text (str): Text to render. 99 size (size: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3): The size of the text. 100 font_name (str): Name of the cache font. 101 102 Returns: 103 int: Maximum font size that fits. 104 """ 105 width,height = size[0],size[1] 106 font_type = "sys" if font_name.lower() in pygame.font.get_fonts() else "local" 107 for font_size in text_sizes: 108 font = cls.__get_font(font_name, font_size) 109 text_surface = font.render(text, True, (0, 0, 0)) 110 text_width, text_height = text_surface.get_size() 111 112 if text_width > width or text_height > height: 113 return font_size - 1 114 115 return font_size 116 117 @property 118 def position(self) -> pygame.math.Vector2 | pygame.math.Vector3: 119 """ 120 Get a copy of the position of the text. 121 122 Returns: 123 pygame.math.Vector2 or pygame.math.Vector3: The position of the text. 124 """ 125 return self._pos.copy() 126 127 @property 128 def value(self) -> str: 129 """ 130 Get the value of the text. 131 132 Returns: 133 str: The value of the text. 134 """ 135 return self._text 136 137 @property 138 def color(self) -> str | tuple: 139 """ 140 Get the color of the text. 141 142 Returns: 143 (str or tuple): The color of the text. 144 """ 145 return self._color 146 147 @property 148 def font(self) -> str: 149 """ 150 Get the color of the text. 151 152 Returns: 153 (str): The font name 154 """ 155 return self._font_name 156 157 @property 158 def font_size(self) -> int: 159 """ 160 Get the size of the text font. 161 162 Returns: 163 int: The size of the text font. 164 """ 165 return self._size 166 167 @property 168 def size(self) -> int: 169 """ 170 Get the surface size of the text font. 171 172 Returns: 173 int: The size of the text font. 174 """ 175 return self._surface.get_size() 176 177 @property 178 def rect(self) -> pygame.Rect: 179 """ 180 Get the rectangle bounds of the text surface. 181 182 Returns: 183 pygame.Rect: The rectangle with position applied. 184 """ 185 _rect = self._surface.get_rect() 186 _rect.x = self._pos[0] 187 _rect.y = self._pos[1] 188 return _rect 189 190 @property 191 def memory(self) -> int: 192 """ 193 Returns the memory size of the text in bytes. 194 195 Returns: 196 int: The memory size of the text surface. 197 """ 198 bytes_per_pixel = self._surface.get_bytesize() 199 width,height = self._surface.get_size() 200 return width * height * bytes_per_pixel 201 202 def move(self,pos: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3) -> None: 203 """ 204 Moves the text by the given offset. 205 206 Args: 207 pos (Tuple[int | float, int | float] | Vector2 | Vector3): 208 The amount to move the text by, relative to its current position. 209 """ 210 self._pos.x += pos[0] 211 self._pos.y += pos[1] 212 213 def move_at(self,pos: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3) -> None: 214 """ 215 Moves the text to a position. 216 217 Args: 218 pos (Tuple[int | float, int | float] | Vector2 | Vector3): 219 The new position for the text. 220 """ 221 self._pos.x = pos[0] 222 self._pos.y = pos[1] 223 224 def draw(self,surf: pygame.Surface,scale: float) -> None: 225 """ 226 Draws the text on the given surface. 227 228 Args: 229 surf (pygame.Surface): 230 The surface to draw the text on. 231 scale (float): 232 The scale factor to apply to the text. 233 """ 234 zoom = scale 235 if zoom == 1: 236 surf.blit(self._surface, self._pos) 237 return 238 if not self._zoom == zoom: 239 self._zoom_surface = pygame.transform.scale_by(self._surface, zoom) 240 self._zoom = zoom 241 surf.blit(self._zoom_surface, self._pos) 242 243 244 def _cache_surface(self) -> None: 245 """ 246 Caches the rendered text surface for future use. 247 248 This method ensures that the text surface is only rendered once and stored in a cache. 249 If the cache limit is reached, the oldest cached surface is removed to make room for the new one. 250 """ 251 self._surface = self._font.render(self._text, False, self._color) 252 253 if len(self.surfaces) >= self._cache_limit: 254 self.surfaces and self.surfaces.popitem(last=True) 255 256 self.surfaces[(self._font,self._text)] = self._surface 257 258 def _align_pos(self,align: str) -> None: 259 """ 260 Adjust the text position based on the specified alignment. 261 262 Args: 263 align (str): "left", "center", or "right". 264 """ 265 # the text is left aligned by default 266 if align == "left": 267 return 268 269 rect = self.rect 270 if align == "center": 271 self._pos.x -= rect.width / 2 272 self._pos.y -= rect.height / 2 273 elif align == "right": 274 self._pos.x += rect.width / 2 275 else: 276 raise ValueError(f"Invalid alignment: {align}") 277 278 @staticmethod 279 def __get_font(font_name: str, size: int) -> pygame.font.Font: 280 """ 281 Retrieves the font from the assets. 282 283 Args: 284 font_name (str): The name of the font. 285 286 Returns: 287 pygame.font.Font: The font object. 288 """ 289 font = Assets.get("data","fonts",font_name) or Assets.get("engine","fonts",font_name) 290 if not font: 291 raise ValueError(f"Font '{font_name}' not found.") 292 return font.get(size) 293 294 @staticmethod 295 def __fix_size(size: int) -> int: 296 """ 297 Returns the closest supported font size from the default set. 298 299 Args: 300 size (int): The requested font size. 301 302 Returns: 303 int: The closest allowed font size. 304 """ 305 closest = min(text_sizes, key=lambda s: abs(s - size)) 306 307 if closest != size: 308 engine.warning(f"Font size {size} not available. Using closest: {closest}") 309 return closest 310 return size
The available text sizes
19class Text: 20 """ 21 A class for rendering text 22 23 Supports caching of fonts and rendered surfaces for performance, 24 alignment options, scaling (zoom), and limiting cache size. 25 """ 26 27 surfaces: dict = OrderedDict() 28 """The surfaces cache""" 29 _cache_limit = 10000 # default surface cache limit is 10000 30 31 def __init__( 32 self,text: str,pos: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3,color: str | tuple, 33 font_name: str=pygame.font.get_default_font().split(".")[0],size: int= 24,align: str= "left") -> None: 34 """ 35 Initialize a Text object. 36 37 Args: 38 pos (pos: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3): The position of the text. 39 text (str): The string to render. 40 color (str or tuple): The color of the text. 41 font_name (str): The text font name. 42 size (int): Font size. 43 align (str): Alignment of the text: "left", "center", or "right". 44 """ 45 size = self.__fix_size(size) 46 font = self.__get_font(font_name,size) 47 48 self._text = text 49 self._pos = vector(*pos) 50 self._color = color 51 self._font_name = font_name 52 53 self._font = font 54 self._size = size 55 56 self._zoom = 1 57 self._zoom_surface = None # cache the zoom_surface for performance 58 59 # Initialize the surface cache 60 self._cache_surface() if(font,text) not in self.surfaces else setattr(self,"_surface",self.surfaces[(font,text)]) 61 62 # change the position of the text based on the alignment 63 self._align_pos(align) 64 65 @classmethod 66 def set_cache(cls,new_limit: int) -> None: 67 """ 68 Set the maximum number of cached surfaces. 69 Note: Default is 10000, but can be increased or decreased as needed. 70 71 Args: 72 new_limit (int): New cache size limit. 73 """ 74 cls._cache_limit = new_limit 75 76 @classmethod 77 def get_cache(cls) -> int: 78 """ 79 Get the number of cached surfaces. 80 81 Returns: 82 int: The number of cached surfaces. 83 """ 84 return len(cls.surfaces) 85 86 @classmethod 87 def clear_cache(cls) -> None: 88 """ 89 Clear all cached text surfaces. 90 """ 91 cls.surfaces.clear() 92 93 @classmethod 94 def font_size_for(cls,text: str, size: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3, font_name: str) -> int: 95 """ 96 Calculates the largest font size that fits the text inside a given area. 97 98 Args: 99 text (str): Text to render. 100 size (size: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3): The size of the text. 101 font_name (str): Name of the cache font. 102 103 Returns: 104 int: Maximum font size that fits. 105 """ 106 width,height = size[0],size[1] 107 font_type = "sys" if font_name.lower() in pygame.font.get_fonts() else "local" 108 for font_size in text_sizes: 109 font = cls.__get_font(font_name, font_size) 110 text_surface = font.render(text, True, (0, 0, 0)) 111 text_width, text_height = text_surface.get_size() 112 113 if text_width > width or text_height > height: 114 return font_size - 1 115 116 return font_size 117 118 @property 119 def position(self) -> pygame.math.Vector2 | pygame.math.Vector3: 120 """ 121 Get a copy of the position of the text. 122 123 Returns: 124 pygame.math.Vector2 or pygame.math.Vector3: The position of the text. 125 """ 126 return self._pos.copy() 127 128 @property 129 def value(self) -> str: 130 """ 131 Get the value of the text. 132 133 Returns: 134 str: The value of the text. 135 """ 136 return self._text 137 138 @property 139 def color(self) -> str | tuple: 140 """ 141 Get the color of the text. 142 143 Returns: 144 (str or tuple): The color of the text. 145 """ 146 return self._color 147 148 @property 149 def font(self) -> str: 150 """ 151 Get the color of the text. 152 153 Returns: 154 (str): The font name 155 """ 156 return self._font_name 157 158 @property 159 def font_size(self) -> int: 160 """ 161 Get the size of the text font. 162 163 Returns: 164 int: The size of the text font. 165 """ 166 return self._size 167 168 @property 169 def size(self) -> int: 170 """ 171 Get the surface size of the text font. 172 173 Returns: 174 int: The size of the text font. 175 """ 176 return self._surface.get_size() 177 178 @property 179 def rect(self) -> pygame.Rect: 180 """ 181 Get the rectangle bounds of the text surface. 182 183 Returns: 184 pygame.Rect: The rectangle with position applied. 185 """ 186 _rect = self._surface.get_rect() 187 _rect.x = self._pos[0] 188 _rect.y = self._pos[1] 189 return _rect 190 191 @property 192 def memory(self) -> int: 193 """ 194 Returns the memory size of the text in bytes. 195 196 Returns: 197 int: The memory size of the text surface. 198 """ 199 bytes_per_pixel = self._surface.get_bytesize() 200 width,height = self._surface.get_size() 201 return width * height * bytes_per_pixel 202 203 def move(self,pos: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3) -> None: 204 """ 205 Moves the text by the given offset. 206 207 Args: 208 pos (Tuple[int | float, int | float] | Vector2 | Vector3): 209 The amount to move the text by, relative to its current position. 210 """ 211 self._pos.x += pos[0] 212 self._pos.y += pos[1] 213 214 def move_at(self,pos: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3) -> None: 215 """ 216 Moves the text to a position. 217 218 Args: 219 pos (Tuple[int | float, int | float] | Vector2 | Vector3): 220 The new position for the text. 221 """ 222 self._pos.x = pos[0] 223 self._pos.y = pos[1] 224 225 def draw(self,surf: pygame.Surface,scale: float) -> None: 226 """ 227 Draws the text on the given surface. 228 229 Args: 230 surf (pygame.Surface): 231 The surface to draw the text on. 232 scale (float): 233 The scale factor to apply to the text. 234 """ 235 zoom = scale 236 if zoom == 1: 237 surf.blit(self._surface, self._pos) 238 return 239 if not self._zoom == zoom: 240 self._zoom_surface = pygame.transform.scale_by(self._surface, zoom) 241 self._zoom = zoom 242 surf.blit(self._zoom_surface, self._pos) 243 244 245 def _cache_surface(self) -> None: 246 """ 247 Caches the rendered text surface for future use. 248 249 This method ensures that the text surface is only rendered once and stored in a cache. 250 If the cache limit is reached, the oldest cached surface is removed to make room for the new one. 251 """ 252 self._surface = self._font.render(self._text, False, self._color) 253 254 if len(self.surfaces) >= self._cache_limit: 255 self.surfaces and self.surfaces.popitem(last=True) 256 257 self.surfaces[(self._font,self._text)] = self._surface 258 259 def _align_pos(self,align: str) -> None: 260 """ 261 Adjust the text position based on the specified alignment. 262 263 Args: 264 align (str): "left", "center", or "right". 265 """ 266 # the text is left aligned by default 267 if align == "left": 268 return 269 270 rect = self.rect 271 if align == "center": 272 self._pos.x -= rect.width / 2 273 self._pos.y -= rect.height / 2 274 elif align == "right": 275 self._pos.x += rect.width / 2 276 else: 277 raise ValueError(f"Invalid alignment: {align}") 278 279 @staticmethod 280 def __get_font(font_name: str, size: int) -> pygame.font.Font: 281 """ 282 Retrieves the font from the assets. 283 284 Args: 285 font_name (str): The name of the font. 286 287 Returns: 288 pygame.font.Font: The font object. 289 """ 290 font = Assets.get("data","fonts",font_name) or Assets.get("engine","fonts",font_name) 291 if not font: 292 raise ValueError(f"Font '{font_name}' not found.") 293 return font.get(size) 294 295 @staticmethod 296 def __fix_size(size: int) -> int: 297 """ 298 Returns the closest supported font size from the default set. 299 300 Args: 301 size (int): The requested font size. 302 303 Returns: 304 int: The closest allowed font size. 305 """ 306 closest = min(text_sizes, key=lambda s: abs(s - size)) 307 308 if closest != size: 309 engine.warning(f"Font size {size} not available. Using closest: {closest}") 310 return closest 311 return size
A class for rendering text
Supports caching of fonts and rendered surfaces for performance, alignment options, scaling (zoom), and limiting cache size.
31 def __init__( 32 self,text: str,pos: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3,color: str | tuple, 33 font_name: str=pygame.font.get_default_font().split(".")[0],size: int= 24,align: str= "left") -> None: 34 """ 35 Initialize a Text object. 36 37 Args: 38 pos (pos: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3): The position of the text. 39 text (str): The string to render. 40 color (str or tuple): The color of the text. 41 font_name (str): The text font name. 42 size (int): Font size. 43 align (str): Alignment of the text: "left", "center", or "right". 44 """ 45 size = self.__fix_size(size) 46 font = self.__get_font(font_name,size) 47 48 self._text = text 49 self._pos = vector(*pos) 50 self._color = color 51 self._font_name = font_name 52 53 self._font = font 54 self._size = size 55 56 self._zoom = 1 57 self._zoom_surface = None # cache the zoom_surface for performance 58 59 # Initialize the surface cache 60 self._cache_surface() if(font,text) not in self.surfaces else setattr(self,"_surface",self.surfaces[(font,text)]) 61 62 # change the position of the text based on the alignment 63 self._align_pos(align)
Initialize a Text object.
Arguments:
- pos (pos: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3): The position of the text.
- text (str): The string to render.
- color (str or tuple): The color of the text.
- font_name (str): The text font name.
- size (int): Font size.
- align (str): Alignment of the text: "left", "center", or "right".
65 @classmethod 66 def set_cache(cls,new_limit: int) -> None: 67 """ 68 Set the maximum number of cached surfaces. 69 Note: Default is 10000, but can be increased or decreased as needed. 70 71 Args: 72 new_limit (int): New cache size limit. 73 """ 74 cls._cache_limit = new_limit
Set the maximum number of cached surfaces. Note: Default is 10000, but can be increased or decreased as needed.
Arguments:
- new_limit (int): New cache size limit.
76 @classmethod 77 def get_cache(cls) -> int: 78 """ 79 Get the number of cached surfaces. 80 81 Returns: 82 int: The number of cached surfaces. 83 """ 84 return len(cls.surfaces)
Get the number of cached surfaces.
Returns:
int: The number of cached surfaces.
86 @classmethod 87 def clear_cache(cls) -> None: 88 """ 89 Clear all cached text surfaces. 90 """ 91 cls.surfaces.clear()
Clear all cached text surfaces.
93 @classmethod 94 def font_size_for(cls,text: str, size: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3, font_name: str) -> int: 95 """ 96 Calculates the largest font size that fits the text inside a given area. 97 98 Args: 99 text (str): Text to render. 100 size (size: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3): The size of the text. 101 font_name (str): Name of the cache font. 102 103 Returns: 104 int: Maximum font size that fits. 105 """ 106 width,height = size[0],size[1] 107 font_type = "sys" if font_name.lower() in pygame.font.get_fonts() else "local" 108 for font_size in text_sizes: 109 font = cls.__get_font(font_name, font_size) 110 text_surface = font.render(text, True, (0, 0, 0)) 111 text_width, text_height = text_surface.get_size() 112 113 if text_width > width or text_height > height: 114 return font_size - 1 115 116 return font_size
Calculates the largest font size that fits the text inside a given area.
Arguments:
- text (str): Text to render.
- size (size: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3): The size of the text.
- font_name (str): Name of the cache font.
Returns:
int: Maximum font size that fits.
118 @property 119 def position(self) -> pygame.math.Vector2 | pygame.math.Vector3: 120 """ 121 Get a copy of the position of the text. 122 123 Returns: 124 pygame.math.Vector2 or pygame.math.Vector3: The position of the text. 125 """ 126 return self._pos.copy()
Get a copy of the position of the text.
Returns:
pygame.math.Vector2 or pygame.math.Vector3: The position of the text.
128 @property 129 def value(self) -> str: 130 """ 131 Get the value of the text. 132 133 Returns: 134 str: The value of the text. 135 """ 136 return self._text
Get the value of the text.
Returns:
str: The value of the text.
138 @property 139 def color(self) -> str | tuple: 140 """ 141 Get the color of the text. 142 143 Returns: 144 (str or tuple): The color of the text. 145 """ 146 return self._color
Get the color of the text.
Returns:
(str or tuple): The color of the text.
148 @property 149 def font(self) -> str: 150 """ 151 Get the color of the text. 152 153 Returns: 154 (str): The font name 155 """ 156 return self._font_name
Get the color of the text.
Returns:
(str): The font name
158 @property 159 def font_size(self) -> int: 160 """ 161 Get the size of the text font. 162 163 Returns: 164 int: The size of the text font. 165 """ 166 return self._size
Get the size of the text font.
Returns:
int: The size of the text font.
168 @property 169 def size(self) -> int: 170 """ 171 Get the surface size of the text font. 172 173 Returns: 174 int: The size of the text font. 175 """ 176 return self._surface.get_size()
Get the surface size of the text font.
Returns:
int: The size of the text font.
178 @property 179 def rect(self) -> pygame.Rect: 180 """ 181 Get the rectangle bounds of the text surface. 182 183 Returns: 184 pygame.Rect: The rectangle with position applied. 185 """ 186 _rect = self._surface.get_rect() 187 _rect.x = self._pos[0] 188 _rect.y = self._pos[1] 189 return _rect
Get the rectangle bounds of the text surface.
Returns:
pygame.Rect: The rectangle with position applied.
191 @property 192 def memory(self) -> int: 193 """ 194 Returns the memory size of the text in bytes. 195 196 Returns: 197 int: The memory size of the text surface. 198 """ 199 bytes_per_pixel = self._surface.get_bytesize() 200 width,height = self._surface.get_size() 201 return width * height * bytes_per_pixel
Returns the memory size of the text in bytes.
Returns:
int: The memory size of the text surface.
203 def move(self,pos: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3) -> None: 204 """ 205 Moves the text by the given offset. 206 207 Args: 208 pos (Tuple[int | float, int | float] | Vector2 | Vector3): 209 The amount to move the text by, relative to its current position. 210 """ 211 self._pos.x += pos[0] 212 self._pos.y += pos[1]
Moves the text by the given offset.
Arguments:
- pos (Tuple[int | float, int | float] | Vector2 | Vector3): The amount to move the text by, relative to its current position.
214 def move_at(self,pos: Tuple[int | float, int | float] | pygame.math.Vector2 | pygame.math.Vector3) -> None: 215 """ 216 Moves the text to a position. 217 218 Args: 219 pos (Tuple[int | float, int | float] | Vector2 | Vector3): 220 The new position for the text. 221 """ 222 self._pos.x = pos[0] 223 self._pos.y = pos[1]
Moves the text to a position.
Arguments:
- pos (Tuple[int | float, int | float] | Vector2 | Vector3): The new position for the text.
225 def draw(self,surf: pygame.Surface,scale: float) -> None: 226 """ 227 Draws the text on the given surface. 228 229 Args: 230 surf (pygame.Surface): 231 The surface to draw the text on. 232 scale (float): 233 The scale factor to apply to the text. 234 """ 235 zoom = scale 236 if zoom == 1: 237 surf.blit(self._surface, self._pos) 238 return 239 if not self._zoom == zoom: 240 self._zoom_surface = pygame.transform.scale_by(self._surface, zoom) 241 self._zoom = zoom 242 surf.blit(self._zoom_surface, self._pos)
Draws the text on the given surface.
Arguments:
- surf (pygame.Surface): The surface to draw the text on.
- scale (float): The scale factor to apply to the text.