Пример #1
0
 def test_redraw_bg_and_fg_gradient(self, _init_pygame):
     dictionary = UIFontDictionary(BlockingThreadedResourceLoader())
     style = CharStyle()
     gradient = ColourGradient(0, pygame.Color('#FFFF00'), pygame.Color('#FF0000'))
     chunk = StyledChunk(font_size=14, font_name='fira_code',
                         chunk='text', style=style, colour=gradient,
                         bg_colour=gradient,
                         is_link=False, link_href='test', link_style=CharStyle(),
                         position=(0, 0), font_dictionary=dictionary)
     chunk.redraw()
Пример #2
0
 def test_creation(self, _init_pygame, _display_surface_return_none):
     dictionary = UIFontDictionary(BlockingThreadedResourceLoader())
     style = CharStyle()
     StyledChunk(font_size=14, font_name='fira_code',
                 chunk='text', style=style, colour=pygame.Color('#FFFF00'),
                 bg_colour=pygame.Color('#000000'),
                 is_link=False, link_href='test', link_style=CharStyle(),
                 position=(0, 0), font_dictionary=dictionary)
Пример #3
0
 def test_redraw_changed_metrics(self, _init_pygame):
     dictionary = UIFontDictionary()
     style = CharStyle()
     gradient = ColourGradient(0, pygame.Color('#FFFF00'),
                               pygame.Color('#FF0000'))
     chunk = StyledChunk(font_size=14,
                         font_name='fira_code',
                         chunk='text',
                         style=style,
                         color=pygame.Color('#FFFF00'),
                         bg_color=gradient,
                         is_link=False,
                         link_href='test',
                         link_style=CharStyle(),
                         position=(0, 0),
                         font_dictionary=dictionary)
     chunk.chunk = 'testy'
     chunk.redraw()
Пример #4
0
    def test_word_split(self, _init_pygame):
        dictionary = UIFontDictionary()
        dictionary.preload_font(font_size=25, font_name='fira_code')
        style = CharStyle()
        styled_chunk_1 = StyledChunk(font_size=14, font_name='fira_code',
                                     chunk='text_text_text_text ', style=style, color=pygame.Color('#FFFF00'),
                                     bg_color=pygame.Color('#000000'),
                                     is_link=False, link_href='test', link_style=CharStyle(),
                                     position=(0, 0), font_dictionary=dictionary)

        styled_chunk_2 = StyledChunk(font_size=25, font_name='fira_code',
                                     chunk='DAN', style=style, color=pygame.Color('#FFFF00'),
                                     bg_color=pygame.Color('#000000'),
                                     is_link=False, link_href='test', link_style=CharStyle(),
                                     position=(0, 0), font_dictionary=dictionary)

        TextBlock(text='text_text_text_text DAN', rect=pygame.Rect(0, 0, 100, 100),
                  indexed_styles={0: styled_chunk_1, 21: styled_chunk_2}, font_dict=dictionary, link_style=style,
                  bg_colour=pygame.Color('#FF0000'), wrap_to_height=True)
Пример #5
0
    def test_word_split(self, _init_pygame, _display_surface_return_none):
        loader = BlockingThreadedResourceLoader()
        dictionary = UIFontDictionary(loader)
        dictionary.preload_font(font_size=25, font_name='fira_code')
        loader.start()
        loader.update()
        style = CharStyle()
        styled_chunk_1 = StyledChunk(font_size=14,
                                     font_name='fira_code',
                                     chunk='text_text_text_text ',
                                     style=style,
                                     colour=pygame.Color('#FFFF00'),
                                     bg_colour=pygame.Color('#000000'),
                                     is_link=False,
                                     link_href='test',
                                     link_style=CharStyle(),
                                     position=(0, 0),
                                     font_dictionary=dictionary)

        styled_chunk_2 = StyledChunk(font_size=25,
                                     font_name='fira_code',
                                     chunk='DAN',
                                     style=style,
                                     colour=pygame.Color('#FFFF00'),
                                     bg_colour=pygame.Color('#000000'),
                                     is_link=False,
                                     link_href='test',
                                     link_style=CharStyle(),
                                     position=(0, 0),
                                     font_dictionary=dictionary)

        TextBlock(text='text_text_text_text DAN',
                  rect=pygame.Rect(0, 0, 100, 100),
                  indexed_styles={
                      0: styled_chunk_1,
                      21: styled_chunk_2
                  },
                  font_dict=dictionary,
                  link_style=style,
                  bg_colour=pygame.Color('#FF0000'),
                  wrap_to_height=True)
Пример #6
0
    def test_creation_scale_vert_to_text(self, _init_pygame):
        dictionary = UIFontDictionary()
        style = CharStyle()
        styled_chunk = StyledChunk(font_size=14, font_name='fira_code',
                                   chunk='text', style=style, colour=pygame.Color('#FFFF00'),
                                   bg_colour=pygame.Color('#000000'),
                                   is_link=False, link_href='test', link_style=CharStyle(),
                                   position=(0, 0), font_dictionary=dictionary)

        TextBlock(text='test', rect=pygame.Rect(0, 0, -1, 100),
                  indexed_styles={0: styled_chunk}, font_dict=dictionary, link_style=style,
                  bg_colour=pygame.Color('#FF0000'), wrap_to_height=True)
Пример #7
0
 def test_creation(self, _init_pygame):
     dictionary = UIFontDictionary()
     style = CharStyle()
     StyledChunk(font_size=14,
                 font_name='fira_code',
                 chunk='text',
                 style=style,
                 color=pygame.Color('#FFFF00'),
                 bg_color=pygame.Color('#000000'),
                 is_link=False,
                 link_href='test',
                 link_style=CharStyle(),
                 position=(0, 0),
                 font_dictionary=dictionary)
Пример #8
0
    def test_creation(self, _init_pygame, _display_surface_return_none):
        dictionary = UIFontDictionary(BlockingThreadedResourceLoader())
        style = CharStyle()
        styled_chunk = StyledChunk(font_size=14,
                                   font_name='fira_code',
                                   chunk='text',
                                   style=style,
                                   colour=pygame.Color('#FFFF00'),
                                   bg_colour=pygame.Color('#000000'),
                                   is_link=False,
                                   link_href='test',
                                   link_style=CharStyle(),
                                   position=(0, 0),
                                   font_dictionary=dictionary)

        TextBlock(text='test',
                  rect=pygame.Rect(0, 0, 100, 100),
                  indexed_styles={0: styled_chunk},
                  font_dict=dictionary,
                  link_style=style,
                  bg_colour=pygame.Color('#FF0000'),
                  wrap_to_height=True)
Пример #9
0
    def _draw_chunks_to_surface(
            self, lines_of_chunks: List[Dict[str, Union[List[Dict[str, Any]],
                                                        int]]]):
        """
        Takes a list of lines of chunks and draws it to a surface using the styles and positions
        attached to the chunks.

        :param lines_of_chunks:
        :return:
        """
        self.block_sprite = None
        if self.height != -1 and self.width != -1:
            self.block_sprite = pygame.surface.Surface(
                (self.width, self.height), pygame.SRCALPHA, depth=32)
            self.block_sprite.fill(pygame.Color('#00000000'))
        position = [0, 0]
        line_height_acc = 0
        max_line_length = 0
        for line in lines_of_chunks:
            line_chunks = []
            max_line_char_height = 0
            for chunk in line['chunks']:
                if len(chunk['text']) > 0:
                    new_chunk = StyledChunk(
                        chunk['style'].font_size, chunk['style'].font_name,
                        chunk['text'], chunk['style'].style,
                        chunk['style'].colour, chunk['style'].bg_colour,
                        chunk['style'].is_link, chunk['style'].link_href,
                        self.link_style, (position[0], position[1]),
                        self.font_dict)
                    position[0] += new_chunk.advance
                    if new_chunk.height > max_line_char_height:
                        max_line_char_height = new_chunk.height
                    line_chunks.append(new_chunk)

                    if self.block_sprite is not None:
                        # need to adjust y start pos based on ascents
                        new_chunk.rect.y += (line['line_ascent'] -
                                             new_chunk.ascent)
                        basic_blit(self.block_sprite, new_chunk.rendered_chunk,
                                   new_chunk.rect)

            text_line = TextBlock.TextLine()
            text_line.chunks = line_chunks
            text_line.max_line_ascent = line['line_ascent']
            self.lines.append(text_line)

            if position[0] > max_line_length:
                max_line_length = position[0]
            position[0] = 0
            position[1] += max_line_char_height
            line_height_acc += max_line_char_height
        if self.block_sprite is None:
            self.width = max_line_length if self.width == -1 else self.width
            self.height = line_height_acc if self.height == -1 else self.height
            self.block_sprite = pygame.surface.Surface(
                (self.width, self.height), pygame.SRCALPHA, depth=32)
            self.block_sprite.fill(pygame.Color('#00000000'))

            for line in self.lines:
                for chunk in line.chunks:
                    # need to adjust y start pos based on ascents
                    chunk.rect.y += line.max_line_ascent - chunk.ascent
                    basic_blit(self.block_sprite, chunk.rendered_chunk,
                               chunk.rect)

        self.final_dimensions = (self.width, self.height)
Пример #10
0
    def redraw(self, text_effect):
        """
        Takes our parsed text and the styles generated from that parsing and builds rendered 'chunks' out of them
        that are then blitted onto a final surface containing all our drawn text.
        """
        self.lines = []
        if text_effect:
            end_text_position = text_effect.get_end_text_pos()
        else:
            end_text_position = len(self.characters)

        lines_of_chunks = []
        chunk_line = []
        start_style_key = 0
        keys = [key for key in list(self.indexed_styles.keys()) if key <= end_text_position]
        keys.sort()
        keys.append(end_text_position)
        max_line_ascent = 0
        for end_style_key in keys:
            if end_style_key != 0:
                text = self.characters[start_style_key:end_style_key]
                chunk = [text, self.indexed_styles[start_style_key]]
                chunk_font = self.font_dict.find_font(chunk[1].font_size,
                                                      chunk[1].font_name,
                                                      chunk[1].style.bold,
                                                      chunk[1].style.italic)
                chunk_ascent = chunk_font.get_ascent()
                if chunk_ascent > max_line_ascent:
                    max_line_ascent = chunk_ascent
                if chunk[0] == '\n':
                    if len(chunk_line) == 0:
                        lines_of_chunks.append([max_line_ascent, [['', chunk[1]]]])
                    else:
                        lines_of_chunks.append([max_line_ascent, chunk_line])
                    chunk_line = []
                    max_line_ascent = 0
                else:
                    chunk_line.append(chunk)

            start_style_key = end_style_key

        if len(chunk_line) > 0:
            lines_of_chunks.append([max_line_ascent, chunk_line])

        if self.width != -1:
            line_index = 0
            while line_index < len(lines_of_chunks):
                line = lines_of_chunks[line_index][1]
                line_render_length = 0
                split_point = -1
                chunk_index = 0
                chunk_to_split_index = 0
                chunk_length = 0
                for chunk in line:
                    font = self.font_dict.find_font(chunk[1].font_size,
                                                    chunk[1].font_name,
                                                    chunk[1].style.bold,
                                                    chunk[1].style.italic)

                    metrics = font.metrics(chunk[0])
                    chunk_length = font.size(chunk[0])[0]
                    line_render_length += chunk_length
                    if line_render_length > self.width:
                        char_line_length = line_render_length - chunk_length
                        for i in range(0, len(metrics)):
                            advance = metrics[i][4]
                            char_line_length += advance
                            if char_line_length > self.width:
                                # splitting time
                                chunk_to_split_index = chunk_index
                                split_point = i
                                break
                    if split_point != -1:
                        break
                    chunk_index += 1

                if split_point != -1:
                    word_split_point = 0
                    chunk_to_split = line[chunk_to_split_index]
                    for i in range(split_point, 0, -1):
                        if chunk_to_split[0][i] == ' ':
                            word_split_point = i
                            break
                    if word_split_point == 0 and chunk_to_split_index == 0 and chunk_length > self.width:
                        # our chunk is one word, at the start of the line, and the split point is in it, so split the
                        # word instead of hunting for a word split point
                        if split_point > 1:
                            chunk_1 = [chunk_to_split[0][:split_point - 1] + '-', chunk_to_split[1]]
                            chunk_2 = ["-" + chunk_to_split[0][split_point - 1:].lstrip(' '), chunk_to_split[1]]

                            chunk_2_font = self.font_dict.find_font(chunk_2[1].font_size,
                                                                    chunk_2[1].font_name,
                                                                    chunk_2[1].style.bold,
                                                                    chunk_2[1].style.italic)
                            chunk_2_ascent = chunk_2_font.get_ascent()

                            lines_of_chunks[line_index][1][chunk_to_split_index] = chunk_1
                            new_line = [chunk_2_ascent, [chunk_2]]

                            chunk_length_of_line = len(lines_of_chunks[line_index][1])
                            for remaining_chunk_index in range(chunk_to_split_index + 1, chunk_length_of_line):
                                remaining_chunk = lines_of_chunks[line_index][1][remaining_chunk_index]
                                new_line[1].append(remaining_chunk)

                                remaining_chunk_font = self.font_dict.find_font(remaining_chunk[1].font_size,
                                                                                remaining_chunk[1].font_name,
                                                                                remaining_chunk[1].style.bold,
                                                                                remaining_chunk[1].style.italic)
                                remaining_chunk_ascent = remaining_chunk_font.get_ascent()
                                if remaining_chunk_ascent > new_line[0]:
                                    new_line[0] = remaining_chunk_ascent

                            for remaining_chunk_index in range(chunk_to_split_index + 1, chunk_length_of_line):
                                lines_of_chunks[line_index][1].pop()

                            lines_of_chunks.insert(line_index + 1, new_line)

                        else:
                            warnings.warn('Unable to split word into chunks because text box is too narrow')

                    else:
                        chunk_1 = [chunk_to_split[0][:word_split_point], chunk_to_split[1]]
                        chunk_2 = [chunk_to_split[0][word_split_point:].lstrip(' '), chunk_to_split[1]]

                        chunk_2_font = self.font_dict.find_font(chunk_2[1].font_size,
                                                                chunk_2[1].font_name,
                                                                chunk_2[1].style.bold,
                                                                chunk_2[1].style.italic)
                        chunk_2_ascent = chunk_2_font.get_ascent()

                        lines_of_chunks[line_index][1][chunk_to_split_index] = chunk_1
                        new_line = [chunk_2_ascent, [chunk_2]]

                        chunk_length_of_line = len(lines_of_chunks[line_index][1])
                        for remaining_chunk_index in range(chunk_to_split_index + 1, chunk_length_of_line):
                            remaining_chunk = lines_of_chunks[line_index][1][remaining_chunk_index]
                            new_line[1].append(remaining_chunk)

                            remaining_chunk_font = self.font_dict.find_font(remaining_chunk[1].font_size,
                                                                            remaining_chunk[1].font_name,
                                                                            remaining_chunk[1].style.bold,
                                                                            remaining_chunk[1].style.italic)
                            remaining_chunk_ascent = remaining_chunk_font.get_ascent()
                            if remaining_chunk_ascent > new_line[0]:
                                new_line[0] = remaining_chunk_ascent

                        for remaining_chunk_index in range(chunk_to_split_index + 1, chunk_length_of_line):
                            lines_of_chunks[line_index][1].pop()

                        lines_of_chunks.insert(line_index + 1, new_line)
                line_index += 1

        surface = None
        surface_width = self.width
        surface_height = self.height
        if self.height != -1 and self.width != -1:
            surface = pygame.Surface((self.width, self.height), pygame.SRCALPHA, depth=32)

        position = [0, 0]
        line_height_acc = 0
        max_line_length = 0
        for line in lines_of_chunks:
            line_chunks = []
            max_line_char_height = 0
            max_line_ascent = 0
            for chunk in line[1]:
                new_chunk = StyledChunk(chunk[1].font_size,
                                        chunk[1].font_name,
                                        chunk[0],
                                        chunk[1].style,
                                        chunk[1].color,
                                        chunk[1].bg_color,
                                        chunk[1].is_link,
                                        chunk[1].link_href,
                                        self.link_style,
                                        (position[0], position[1]),
                                        self.font_dict)
                position[0] += new_chunk.advance
                if new_chunk.height > max_line_char_height:
                    max_line_char_height = new_chunk.height
                if new_chunk.ascent > max_line_ascent:
                    max_line_ascent = new_chunk.ascent
                line_chunks.append(new_chunk)

                if surface is not None:
                    # need to adjust y start pos based on ascents
                    chunk_rect = new_chunk.rect
                    adjust = line[0] - new_chunk.ascent
                    chunk_rect.y += adjust
                    surface.blit(new_chunk.rendered_chunk, chunk_rect)

            text_line = TextBlock.TextLine()
            text_line.chunks = line_chunks
            text_line.max_line_ascent = max_line_ascent
            self.lines.append(text_line)

            position[0] = 0
            position[1] += max_line_char_height
            line_height_acc += max_line_char_height

        if surface is None:
            if self.width == -1:
                surface_width = max_line_length
            else:
                surface_width = self.width
            if self.height == -1:
                surface_height = line_height_acc
            else:
                surface_height = self.height

            surface = pygame.Surface((surface_width, surface_height), pygame.SRCALPHA, depth=32)

            for line in self.lines:
                for chunk in line.chunks:
                    # need to adjust y start pos based on ascents
                    chunk_rect = chunk.rect
                    adjust = line.max_line_ascent - chunk.ascent
                    chunk_rect.y += adjust
                    surface.blit(chunk.rendered_chunk, chunk_rect)

        self.block_sprite = surface
        self.final_dimensions = [surface_width, surface_height]
        self.width = surface_width
        self.height = surface_height