Beispiel #1
0
def layout_width(triples, justify=False):
    """
    Returns the width of the given list of triples. 
    """

    rv = 0

    curts = None
    cur = ""

    rtl = renpy.config.rtl

    for type, ts, i in triples:
        if ts is not curts:
            if cur:

                if rtl:
                    cur, dir = log2vis(cur, ON)

                rv += curts.get_width(cur)

            curts = ts
            cur = i

        elif justify and type == "space":
            cur += i

            if rtl:
                cur, dir = log2vis(cur, ON)

            rv += curts.get_width(cur)
            cur = ""

        else:
            cur += i

    if curts:
        if rtl:
            cur, dir = log2vis(cur, ON)

        rv += curts.get_width(cur)

    return rv
def layout_width(triples, justify=False):
    """
    Returns the width of the given list of triples. 
    """

    rv = 0

    curts = None
    cur = ""

    rtl = renpy.config.rtl
    
    for type, ts, i in triples:
        if ts is not curts:
            if cur:

                if rtl:
                    cur, dir = log2vis(cur, ON)

                rv += curts.get_width(cur)
                
            curts = ts
            cur = i

        elif justify and type == "space":
            cur += i

            if rtl:
                cur, dir = log2vis(cur, ON)

            rv += curts.get_width(cur)
            cur = ""

        else:
            cur += i

    if curts:
        if rtl:
            cur, dir = log2vis(cur, ON)

        rv += curts.get_width(cur)

    return rv
Beispiel #3
0
    def rtl_paragraph(self, p):
        """
        Given a paragraph (a list of segment, text tuples) handles
        RTL and ligaturization. This returns the reversed RTL paragraph,
        which differers from the LTR one. It also returns a flag that is
        True if this is an rtl paragraph.
        """

        direction = ON

        l = []

        for ts, s in p:
            s, direction = log2vis(s, direction)
            l.append((ts, s))

        rtl = (direction == RTL or direction == WRTL)

        return l, rtl
Beispiel #4
0
    def rtl_paragraph(self, p):
        """
        Given a paragraph (a list of segment, text tuples) handles
        RTL and ligaturization. This returns the reversed RTL paragraph,
        which differers from the LTR one. It also returns a flag that is
        True if this is an rtl paragraph.
        """

        direction = ON

        l = [ ]

        for ts, s in p:
            s, direction = log2vis(s, direction)
            l.append((ts, s))

        rtl = (direction == RTL or direction == WRTL)

        return l, rtl
Beispiel #5
0
    def layout(self, width, time):
        """
        This lays out the text of this widget. It sets self.laidout,
        self.laidout_lineheights, self.laidout_width, and
        self.laidout_height.
        """

        if self.laidout and self.width == width:
            return

        if self.tokens is None:
            self.update()

        # Set this, so caching works.
        self.width = width

        # We are building this list of triples, which will be passed
        # to text_layout.
        triples = []

        # text style list - a stack of text styles.
        tsl = [TextStyle()]

        # The default style. (Duplicated in {a}, {st})
        tsl[-1].font = self.style.font
        tsl[-1].size = self.style.size
        tsl[-1].bold = self.style.bold
        tsl[-1].italic = self.style.italic
        tsl[-1].underline = self.style.underline
        tsl[-1].strikethrough = self.style.strikethrough
        tsl[-1].color = None
        tsl[-1].black_color = None
        tsl[-1].hyperlink = None
        tsl[-1].update()

        self.laidout_hyperlinks = []  # W0201

        # if not self.text:
        #     text = " "
        # else:
        #     text = self.text

        # for i in re.split(r'( |\{[^{}]+\}|\{\{|\n)', text):

        tokens = []
        for l in self.tokens:
            tokens.extend(l)

        ti = iter(tokens)

        for kind, i in ti:

            # Newline.
            if kind == "newline":
                triples.append(("newline", tsl[-1], ""))
                continue

            elif kind == "tag":

                # Are we closing a tag?
                if i.startswith("/"):

                    tsl.pop()

                    if not tsl:
                        raise Exception(
                            "Closing tag %s does not match an open tag." % i)

                    continue

                if i == "w":
                    # Automatically closes.
                    continue

                elif i == "nw":
                    # Automatically closes.
                    continue

                elif i.startswith("w="):
                    # Automatically closes.
                    continue

                elif i == "fast":
                    # Automatically closes.
                    triples.append(("start", tsl[-1], ""))
                    continue

                elif i.startswith("a="):
                    m = re.match(r'a=(.*)', i)
                    if not m:
                        raise Exception(
                            'Hyperlink tag %s could not be parsed.' % i)

                    # TODO: check to see if we need to be focused.

                    target = m.group(1)
                    hls = renpy.config.hyperlink_styler(target)

                    old_prefix = hls.prefix

                    link = len(self.laidout_hyperlinks)

                    if renpy.display.focus.argument == link:

                        if self.activated:
                            hls.set_prefix("activate_")
                        else:
                            hls.set_prefix("hover_")
                    else:
                        hls.set_prefix("idle_")

                    tsl.append(TextStyle())
                    tsl[-1].font = hls.font
                    tsl[-1].size = hls.size
                    tsl[-1].bold = hls.bold
                    tsl[-1].italic = hls.italic
                    tsl[-1].underline = hls.underline
                    tsl[-1].strikethrough = hls.strikethrough
                    tsl[-1].color = hls.color
                    tsl[-1].black_color = hls.black_color
                    tsl[-1].hyperlink = link
                    tsl[-1].update()

                    self.laidout_hyperlinks.append(target)

                    hls.set_prefix(old_prefix)

                    continue

                # Otherwise, we're opening a new tag.
                tsl.append(TextStyle(tsl[-1]))

                if i == "b":
                    tsl[-1].bold = True
                    tsl[-1].update()

                elif i == "i":
                    tsl[-1].italic = True
                    tsl[-1].update()

                elif i == "u":
                    tsl[-1].underline = True
                    tsl[-1].update()

                elif i == "s":
                    tsl[-1].strikethrough = True
                    tsl[-1].update()

                elif i == "plain":
                    tsl[-1].bold = False
                    tsl[-1].italic = False
                    tsl[-1].underline = False
                    tsl[-1].update()

                elif i[0] == "=":
                    style = getattr(renpy.store.style, i[1:])

                    tsl[-1].font = style.font
                    tsl[-1].size = style.size
                    tsl[-1].bold = style.bold
                    tsl[-1].italic = style.italic
                    tsl[-1].underline = style.underline
                    tsl[-1].strikethrough = style.strikethrough
                    tsl[-1].color = style.color
                    tsl[-1].black_color = style.black_color
                    tsl[-1].update()

                elif i.startswith("font"):

                    m = re.match(r'font=(.*)', i)

                    if not m:
                        raise Exception('Font tag %s could not be parsed.' % i)

                    tsl[-1].font = m.group(1)
                    tsl[-1].update()

                elif i.startswith("size"):

                    m = re.match(r'size=(\+|-|)(\d+)', i)

                    if not m:
                        raise Exception('Size tag %s could not be parsed.' % i)

                    if m.group(1) == '+':
                        tsl[-1].size += int(m.group(2))
                    elif m.group(1) == '-':
                        tsl[-1].size -= int(m.group(2))
                    else:
                        tsl[-1].size = int(m.group(2))
                    tsl[-1].update()

                elif i.startswith("color"):

                    m = re.match(r'color=(\#?[a-fA-F0-9]+)', i)

                    if not m:
                        raise Exception('Color tag %s could not be parsed.' %
                                        i)

                    tsl[-1].color = color(m.group(1))
                    tsl[-1].update()

                else:
                    raise Exception(
                        "Text tag %s was not recognized. Case and spacing matter here."
                        % i)

                # Since the kind can change.
                if kind == "tag":
                    continue

            elif kind == "space":
                # Spaces always get appended to the end of a line. So they
                # will never show up at the start of a line, unless they're
                # after a newline or at the start of a string.

                triples.append(("space", tsl[-1], i))

                continue

            elif kind == "word":
                triples.append(("word", tsl[-1], i))

            elif kind == "widget":
                pass

            else:
                raise Exception("Unknown text token kind %s." % kind)

            if kind == "widget":
                wstyle = WidgetStyle(tsl[-1], i, width, time)
                triples.append(("word", wstyle, i))

        # We're done matching tags.

        if len(tsl) != 1:
            Exception("A tag was left open at the end of the text.")

        # Give text_layout a list of triples, get back a list of lists of
        # triples, one per line.
        linetriples, lines_last = renpy.config.text_layout(
            triples, width, self.style)

        # Now, we need to go through these lines, to generate the data
        # we need to render text.

        self.laidout = []  # W0201
        self.laidout_lineheights = []  # W0201
        self.laidout_linewidths = []  # W0201
        self.laidout_length = 0  # W0201
        self.laidout_start = 0  # W0201
        self.laidout_width = self.style.min_width  # W0201
        self.laidout_height = 0  # W0201
        self.laidout_lines_last = lines_last  # W0201

        # Add something to empty lines.
        for l in linetriples:
            if not l:
                l.append(('word', tsl[-1], ' '))

        justify = self.style.justify

        for l in linetriples:

            line = []
            oldts = None
            cur = None

            for kind, ts, i in l:

                if kind == "start":
                    self.laidout_start = self.laidout_length
                    continue

                try:
                    self.laidout_length += len(i)
                except:
                    self.laidout_length += ts.length(i)

                if ts is not oldts:
                    if oldts is not None:
                        line.append((oldts, cur))

                    oldts = ts
                    cur = i
                else:
                    cur += i

                if justify and kind == "space":
                    if cur:
                        line.append((oldts, cur))
                        cur = ""
                    line.append((SpacerStyle(), ""))

            if oldts:
                line.append((oldts, cur))

            if renpy.config.rtl:

                rtl_line = []

                # RTL direction.
                line_direction = ON

                for ts, i in line:
                    if isinstance(ts, TextStyle):
                        i, line_direction = log2vis(i, line_direction)

                    rtl_line.append((ts, i))

                if line_direction == RTL or line_direction == WRTL:
                    rtl_line.reverse()

                line = rtl_line

            width = 0
            height = 0

            for ts, i in line:

                # This is a special case to handle mostly-blank lines introduced
                # by newlines.
                if len(line) == 1 and i == "":
                    i = " "

                w, h = ts.sizes(i)

                width += w
                height = max(height, h)

            self.laidout.append(line)
            self.laidout_linewidths.append(width)
            self.laidout_lineheights.append(height)
            self.laidout_width = max(width, self.laidout_width)
            self.laidout_height += height + self.style.line_spacing

            # For the newline.
            self.laidout_length += 1
    def layout(self, width, time):
        """
        This lays out the text of this widget. It sets self.laidout,
        self.laidout_lineheights, self.laidout_width, and
        self.laidout_height.
        """

        self.update()
        
        if self.laidout and self.width == width and self.layout_generation == layout_generation:
            return

        self.layout_generation = layout_generation

        # Set this, so caching works.
        self.width = width

        # We are building this list of triples, which will be passed
        # to text_layout.
        triples = [ ]

        # text style list - a stack of text styles.
        tsl = [ TextStyle() ]

        # The default style. (Duplicated in {a}, {st})
        tsl[-1].font = self.style.font
        tsl[-1].size = self.style.size
        tsl[-1].bold = self.style.bold
        tsl[-1].italic = self.style.italic
        tsl[-1].underline = self.style.underline
        tsl[-1].strikethrough = self.style.strikethrough
        tsl[-1].color = None
        tsl[-1].black_color = None
        tsl[-1].hyperlink = None
        tsl[-1].update()

        self.laidout_hyperlinks = [ ] # W0201
        
        tokens = [ ]
        for l in self.tokens:
            tokens.extend(l)

        ti = iter(tokens)

        for kind, i in ti:

            # Newline.
            if kind == "newline":
                triples.append(("newline", tsl[-1], ""))                
                continue

            elif kind == "tag":

                # Are we closing a tag?
                if i.startswith("/"):

                    tsl.pop()

                    if not tsl:
                        raise Exception("Closing tag %s does not match an open tag." % i)

                    continue

                if i == "w" or i.startswith("w="):
                    # Automatically closes.
                    continue

                elif i == "p" or i.startswith("p="):
                    # Automatically closes.
                    triples.append(("newline", tsl[-1], "\n"))
                    continue
                    
                elif i == "nw":
                    # Automatically closes.
                    continue
                    
                elif i.startswith("w="):
                    # Automatically closes.
                    continue
                    
                elif i == "fast":
                    # Automatically closes.
                    continue

                elif i == "_start":
                    # Automatically closes.
                    triples.append(("start", tsl[-1], ""))
                    continue

                elif i.startswith("a="):
                    # TODO: check to see if we need to be focused.

                    target = i[2:]

                    hyperlink_styler = self.style.hyperlink_functions[0]
                        
                    if hyperlink_styler:                                        
                        hls = hyperlink_styler(target)
                    else:
                        hls = self.style

                    old_prefix = hls.prefix

                    link = len(self.laidout_hyperlinks)

                    if renpy.display.focus.argument == link:

                        if self.activated:
                            hls.set_prefix("activate_")
                        else:
                            hls.set_prefix("hover_")
                    else:
                        hls.set_prefix("idle_")
                    
                    tsl.append(TextStyle())
                    tsl[-1].font = hls.font
                    tsl[-1].size = hls.size
                    tsl[-1].bold = hls.bold
                    tsl[-1].italic = hls.italic
                    tsl[-1].underline = hls.underline
                    tsl[-1].strikethrough = hls.strikethrough
                    tsl[-1].color = hls.color
                    tsl[-1].black_color = hls.black_color
                    tsl[-1].hyperlink = link
                    tsl[-1].update()

                    self.laidout_hyperlinks.append(target)
                    
                    hls.set_prefix(old_prefix)

                    continue
                    
                # Otherwise, we're opening a new tag.
                tsl.append(TextStyle(tsl[-1]))

                if i == "b":
                    tsl[-1].bold = True
                    tsl[-1].update()

                elif i == "i":
                    tsl[-1].italic = True
                    tsl[-1].update()

                elif i == "u":
                    tsl[-1].underline = True
                    tsl[-1].update()

                elif i == "s":
                    tsl[-1].strikethrough = True
                    tsl[-1].update()

                elif i == "plain":
                    tsl[-1].bold = False
                    tsl[-1].italic = False
                    tsl[-1].underline = False
                    tsl[-1].update()

                elif i[0] == "=":
                    style = getattr(renpy.store.style, i[1:])

                    tsl[-1].font = style.font
                    tsl[-1].size = style.size
                    tsl[-1].bold = style.bold
                    tsl[-1].italic = style.italic
                    tsl[-1].underline = style.underline
                    tsl[-1].strikethrough = style.strikethrough
                    tsl[-1].color = style.color
                    tsl[-1].black_color = style.black_color
                    tsl[-1].update()

                elif i.startswith("font="):

                    tsl[-1].font = i[5:]
                    tsl[-1].update()

                elif i.startswith("size="):

                    m = re.match(r'size=(\+|-|)(\d+)', i)

                    if not m:
                        raise Exception('Size tag %s could not be parsed.' % i)

                    if m.group(1) == '+':
                        tsl[-1].size += int(m.group(2))
                    elif m.group(1) == '-':
                        tsl[-1].size -= int(m.group(2))
                    else:
                        tsl[-1].size = int(m.group(2))                    
                    tsl[-1].update()

                elif i.startswith("color="):

                    tsl[-1].color = color(i[6:])
                    tsl[-1].update()
                    
                else:
                    raise Exception("Text tag %s was not recognized. Case and spacing matter here." % i)

                # Since the kind can change.
                if kind == "tag":
                    continue

            elif kind == "space":
                # Spaces always get appended to the end of a line. So they
                # will never show up at the start of a line, unless they're
                # after a newline or at the start of a string.

                triples.append(("space", tsl[-1], i))
                
                continue

            elif kind == "word":
                triples.append(("word", tsl[-1], i))

            elif kind == "widget":
                pass
            
            else:
                raise Exception("Unknown text token kind %s." % kind)

            if kind == "widget":
                wstyle = WidgetStyle(tsl[-1], i, width, time)
                triples.append(("word", wstyle, i))
                            
        # We're done matching tags.

        if len(tsl) != 1:
            Exception("A tag was left open at the end of the text.")


        # Give text_layout a list of triples, get back a list of lists of
        # triples, one per line.
        linetriples, lines_last = renpy.config.text_layout(triples, width, self.style)
        
        # Now, we need to go through these lines, to generate the data
        # we need to render text.

        self.laidout = [ ] # W0201
        self.laidout_lineheights = [ ] # W0201
        self.laidout_linewidths = [ ] # W0201
        self.laidout_length = 0 # W0201
        self.laidout_start = 0 # W0201
        self.laidout_width = self.style.min_width # W0201
        self.laidout_height = 0 # W0201
        self.laidout_lines_last = lines_last # W0201
        
        # Add something to empty lines.
        for l in linetriples:
            if not l:
                l.append(('word', tsl[-1], ' '))

        justify = self.style.justify
                
        for l in linetriples:

            line = [ ]
            oldts = None
            cur = None
            
            for kind, ts, i in l:

                if kind == "start":
                    self.laidout_start = self.laidout_length
                    continue

                try:
                    self.laidout_length += len(i)
                except:
                    self.laidout_length += ts.length(i)
                    
                if ts is not oldts:
                    if oldts is not None:
                        line.append((oldts, cur))

                    oldts = ts
                    cur = i
                else:
                    cur += i

                if justify and kind == "space":
                    if cur:
                        line.append((oldts, cur))
                        cur = ""
                    line.append((SpacerStyle(), ""))
                    
            if oldts:
                line.append((oldts, cur))
                
            if renpy.config.rtl:

                rtl_line = [ ]
                
                # RTL direction.
                line_direction = ON

                for ts, i in line:
                    if isinstance(ts, TextStyle):
                        i, line_direction = log2vis(i, line_direction)

                    rtl_line.append((ts, i))

                if line_direction == RTL or line_direction == WRTL:
                    rtl_line.reverse()

                line = rtl_line
                
            width = 0
            height = 0

            for ts, i in line:

                # This is a special case to handle mostly-blank lines introduced
                # by newlines.
                if len(line) == 1 and i == "":
                    i = " "

                w, h = ts.sizes(i)

                width += w
                height = max(height, h)

            self.laidout.append(line)
            self.laidout_linewidths.append(width)
            self.laidout_lineheights.append(height)
            self.laidout_width = max(width, self.laidout_width)
            self.laidout_height += height + max(self.style.line_spacing, 0)

            # For the newline.
            self.laidout_length += 1