|
|
|
from typing import Optional
|
|
|
|
import typing
|
|
|
|
|
|
|
|
import pygame
|
|
|
|
|
|
|
|
|
|
|
|
def draw_cursor(surface, cur_position, high, c, size=4):
|
|
|
|
pygame.draw.line(surface, c,
|
|
|
|
cur_position,
|
|
|
|
(cur_position[0], cur_position[1] + high), size)
|
|
|
|
|
|
|
|
|
|
|
|
def get_word_length(ft, word: str):
|
|
|
|
word_surface = ft.render(word, 0, pygame.Color('black'))
|
|
|
|
return word_surface.get_size()
|
|
|
|
|
|
|
|
|
|
|
|
def render_text(surface, position: typing.Tuple[int, int], font: pygame.font, text: str, c=pygame.Color('black'),
|
|
|
|
cursor_position: Optional[int] = None) -> int:
|
|
|
|
"""Render text with hyphenation"""
|
|
|
|
|
|
|
|
if len(list(filter(bool, text.split()))) == 0:
|
|
|
|
return 0
|
|
|
|
|
|
|
|
need_cursor = cursor_position is not None
|
|
|
|
lines = [word.split() for word in text.splitlines()]
|
|
|
|
space_size = font.size(' ')[0]
|
|
|
|
max_width, max_height = surface.get_size()
|
|
|
|
|
|
|
|
x, y = position
|
|
|
|
symbols_counter = 0
|
|
|
|
for line in lines:
|
|
|
|
for word in line:
|
|
|
|
w, h = get_word_length(font, word)
|
|
|
|
if w > max_width or h > max_height:
|
|
|
|
raise ValueError("Surface is too small")
|
|
|
|
if x + w >= max_width:
|
|
|
|
x = position[0]
|
|
|
|
y += h
|
|
|
|
surface.blit(font.render(word, 0, c), (x, y))
|
|
|
|
if need_cursor and symbols_counter + len(word) >= cursor_position:
|
|
|
|
# It means that cursor is in this word or after this word
|
|
|
|
cur_coord = (x + get_word_length(font,
|
|
|
|
word[:cursor_position - symbols_counter])[0], y)
|
|
|
|
draw_cursor(surface, cur_coord, h, c)
|
|
|
|
need_cursor = False
|
|
|
|
symbols_counter += len(word) + 1
|
|
|
|
x += w + space_size
|
|
|
|
y += h
|
|
|
|
x = position[0]
|
|
|
|
return y
|