We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Label Text Clipped Horizontally (Moved)
**Originally reported as a continuation of #576 by esbullington**

I think I'm having trouble with this same issue.  I'm trying to use markup with a Label, and am finding that my Label text is cut-off along the horizontal axis if I have markup set to True.  This probably is only occurring with the latest development version, even after the above path was pulled.  The problem does not occur with Kivy 1.3.0.  If needed, I can re-install the development version and make a screen shot, but for now I'm working with Kivy 1.3.0. 

I've only started working with Kivy in the past few days, so I'm not yet in a place where I feel comfortable sending in a patch.  (awesome framework, by the way, congrats on the great work!).

Oh, and it doesn't look like I can re-open the issue, so someone else may wish to do so, or else tell me to open another issue for the problem.

UPDATE: I coped markup.py from Kivy 1.3 to Kivy1.4-dev and it resolved this issue for me.  I may now have problems with rst, but at least my markdown labels aren't cut in half.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kivy/core/text/markup.py`
Content:
```
1 '''
2 Text Markup
3 ===========
4 
5 .. versionadded:: 1.1.0
6 
7 We provide a simple text-markup for inline text styling. The syntax look the
8 same as the `BBCode <http://en.wikipedia.org/wiki/BBCode>`_.
9 
10 A tag is defined as ``[tag]``, and might have a closed tag associated:
11 ``[/tag]``. Example of a markup text::
12 
13     [b]Hello [color=ff0000]world[/b][/color]
14 
15 The following tags are availables:
16 
17 ``[b][/b]``
18     Activate bold text
19 ``[i][/i]``
20     Activate italic text
21 ``[font=<str>][/font]``
22     Change the font
23 ``[size=<integer>][/size]``
24     Change the font size
25 ``[color=#<color>][/color]``
26     Change the text color
27 ``[ref=<str>][/ref]``
28     Add an interactive zone. The reference + all the word box inside the
29     reference will be available in :data:`MarkupLabel.refs`
30 ``[anchor=<str>]``
31     Put an anchor in the text. You can get the position of your anchor within
32     the text with :data:`MarkupLabel.anchors`
33 
34 If you need to escape the markup from the current text, use
35 :func:`kivy.utils.escape_markup`.
36 '''
37 
38 __all__ = ('MarkupLabel', )
39 
40 from kivy.graphics.texture import Texture
41 from kivy.utils import platform
42 from kivy.parser import parse_color
43 from kivy.logger import Logger
44 import re
45 from kivy.core.text import Label, LabelBase
46 from copy import copy
47 
48 # We need to do this trick when documentation is generated
49 MarkupLabelBase = Label
50 if Label is None:
51     MarkupLabelBase = LabelBase
52 
53 
54 class MarkupLabel(MarkupLabelBase):
55     '''Markup text label.
56 
57     See module documentation for more informations.
58     '''
59 
60     def __init__(self, *largs, **kwargs):
61         self._style_stack = {}
62         self._refs = {}
63         super(MarkupLabel, self).__init__(*largs, **kwargs)
64 
65     @property
66     def refs(self):
67         '''Get the bounding box of all the ``[ref=...]``::
68 
69             { 'refA': ((x1, y1, x2, y2), (x1, y1, x2, y2)), ... }
70         '''
71         return self._refs
72 
73     @property
74     def anchors(self):
75         '''Get the position of all the ``[anchor=...]``::
76 
77             { 'anchorA': (x, y), 'anchorB': (x, y), ... }
78         '''
79         return self._anchors
80 
81     @property
82     def markup(self):
83         '''Return the text with all the markup splitted::
84 
85             >>> MarkupLabel('[b]Hello world[/b]').markup
86             >>> ('[b]', 'Hello world', '[/b]')
87 
88         '''
89         s = re.split('(\[.*?\])', self.label)
90         s = [x for x in s if x != '']
91         return s
92 
93     def _push_style(self, k):
94         if not k in self._style_stack:
95             self._style_stack[k] = []
96         self._style_stack[k].append(self.options[k])
97 
98     def _pop_style(self, k):
99         if k not in self._style_stack or len(self._style_stack[k]) == 0:
100             Logger.warning('Label: pop style stack without push')
101             return
102         v = self._style_stack[k].pop()
103         self.options[k] = v
104 
105     def render(self, real=False):
106         options = copy(self.options)
107         if not real:
108             ret = self._pre_render()
109         else:
110             ret = self._real_render()
111         self.options = options
112         return ret
113 
114     def _pre_render(self):
115         # split markup, words, and lines
116         # result: list of word with position and width/height
117         # during the first pass, we don't care about h/valign
118         self._lines = lines = []
119         self._refs = {}
120         self._anchors = {}
121         spush = self._push_style
122         spop = self._pop_style
123         options = self.options
124         options['_ref'] = None
125         for item in self.markup:
126             if item == '[b]':
127                 spush('bold')
128                 options['bold'] = True
129                 self.resolve_font_name()
130             elif item == '[/b]':
131                 spop('bold')
132                 self.resolve_font_name()
133             elif item == '[i]':
134                 spush('italic')
135                 options['italic'] = True
136                 self.resolve_font_name()
137             elif item == '[/i]':
138                 spop('italic')
139                 self.resolve_font_name()
140             elif item[:6] == '[size=':
141                 try:
142                     size = int(item[6:-1])
143                 except ValueError:
144                     size = options['font_size']
145                 spush('font_size')
146                 options['font_size'] = size
147             elif item == '[/size]':
148                 spop('font_size')
149             elif item[:7] == '[color=':
150                 color = parse_color(item[7:-1])
151                 spush('color')
152                 options['color'] = color
153             elif item == '[/color]':
154                 spop('color')
155             elif item[:6] == '[font=':
156                 fontname = item[6:-1]
157                 spush('font_name')
158                 options['font_name'] = fontname
159                 self.resolve_font_name()
160             elif item == '[/font]':
161                 spop('font_name')
162                 self.resolve_font_name()
163             elif item[:5] == '[ref=':
164                 ref = item[5:-1]
165                 spush('_ref')
166                 options['_ref'] = ref
167             elif item == '[/ref]':
168                 spop('_ref')
169             elif item[:8] == '[anchor=':
170                 ref = item[8:-1]
171                 if len(lines):
172                     x, y = lines[-1][0:2]
173                 else:
174                     x = y = 0
175                 self._anchors[ref] = x, y
176             else:
177                 item = item.replace('&bl;', '[').replace(
178                         '&br;', ']').replace('&amp;', '&')
179                 self._pre_render_label(item, options, lines)
180 
181         # calculate the texture size
182         w, h = self.text_size
183         if h < 0:
184             h = None
185         if w < 0:
186             w = None
187         if w is None:
188             w = max([line[0] for line in lines])
189         if h is None:
190             h = sum([line[1] for line in lines])
191         return w, h
192 
193     def _pre_render_label(self, word, options, lines):
194         # precalculate id/name
195         if not self.fontid in self._cache_glyphs:
196             self._cache_glyphs[self.fontid] = {}
197         cache = self._cache_glyphs[self.fontid]
198 
199         # verify that each glyph have size
200         glyphs = list(set(word))
201         get_extents = self.get_extents
202         for glyph in glyphs:
203             if not glyph in cache:
204                 cache[glyph] = get_extents(glyph)
205 
206         # get last line information
207         if len(lines):
208             line = lines[-1]
209         else:
210             # line-> line width, line height, words
211             # words -> (w, h, word)...
212             line = [0, 0, []]
213             lines.append(line)
214 
215         # extract user limitation
216         uw, uh = self.text_size
217 
218         # split the word
219         for part in re.split(r'( |\n)', word):
220 
221             if part == '':
222                 continue
223 
224             if part == '\n':
225                 # put a new line!
226                 line = [0, 0, []]
227                 lines.append(line)
228                 continue
229 
230             # get current line information
231             lw, lh = line[:2]
232 
233             # calculate the size of the part
234             # (extract all extents of the part,
235             # calculate width through extents due to kerning
236             # and get the maximum height)
237             pg = [cache[g] for g in part]
238             pw = get_extents(part)[0]
239             ph = max([g[1] for g in pg])
240 
241             options = copy(options)
242 
243             # check if the part can be put in the line
244             if uw is None or lw + pw < uw:
245                 # no limitation or part can be contained in the line
246                 # then append the part to the line
247                 line[2].append((pw, ph, part, options))
248                 # and update the line size
249                 line[0] += pw
250                 line[1] = max(line[1], ph)
251             else:
252                 # part can't be put in the line, do a new one...
253                 line = [pw, ph, [(pw, ph, part, options)]]
254                 lines.append(line)
255 
256     def _real_render(self):
257         # use the lines to do the rendering !
258         self._render_begin()
259 
260         r = self._render_text
261 
262         # convert halign/valign to int, faster comparaison
263         av = {'top': 0, 'middle': 1, 'bottom': 2}[self.options['valign']]
264         ah = {'left': 0, 'center': 1, 'right': 2}[self.options['halign']]
265 
266         y = 0
267         w, h = self._size
268         refs = self._refs
269         no_of_lines = len(self._lines)-1
270 
271         for line in self._lines:
272             lh = line[1]
273             lw = line[0]
274 
275             # horizontal alignement
276             if ah == 0:
277                 x = 0
278             elif ah == 1:
279                 x = int((w - lw) / 2)
280             else:
281                 x = w - lw
282 
283             # vertical alignement
284             if y == 0:
285                 if av == 1:
286                     y = int((h - (lh*no_of_lines))/2)
287                 elif av == 2:
288                     y = h - (lh*(no_of_lines))
289 
290 
291             for pw, ph, part, options in line[2]:
292                 self.options = options
293                 r(part, x, y + (lh - ph) / 1.25)
294 
295                 # should we record refs ?
296                 ref = options['_ref']
297                 if ref is not None:
298                     if not ref in refs:
299                         refs[ref] = []
300                     refs[ref].append((x, y, x + pw, y + ph))
301 
302                 #print 'render', repr(part), x, y, (lh, ph), options
303                 x += pw
304             y += line[1]
305 
306         # get data from provider
307         data = self._render_end()
308         assert(data)
309 
310         # create texture is necessary
311         texture = self.texture
312         mipmap = self.options['mipmap']
313         if texture is None:
314             if data is None:
315                 if platform() in ('android', 'ios'):
316                     colorfmt = 'rgba'
317                 else:
318                     colorfmt = 'luminance_alpha'
319                 texture = Texture.create(
320                         size=self.size, colorfmt=colorfmt,
321                         mipmap=mipmap)
322             else:
323                 texture = Texture.create_from_data(data, mipmap=mipmap)
324             texture.flip_vertical()
325         elif self.width != texture.width or self.height != texture.height:
326             if data is None:
327                 texture = Texture.create(size=self.size, mipmap=mipmap)
328             else:
329                 texture = Texture.create_from_data(data, mipmap=mipmap)
330             texture.flip_vertical()
331 
332         # update texture
333         self.texture = texture
334         self.texture.blit_data(data)
335 
336
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/kivy/core/text/markup.py b/kivy/core/text/markup.py
--- a/kivy/core/text/markup.py
+++ b/kivy/core/text/markup.py
@@ -266,7 +266,7 @@
         y = 0
         w, h = self._size
         refs = self._refs
-        no_of_lines = len(self._lines)-1
+        no_of_lines = len(self._lines)
 
         for line in self._lines:
             lh = line[1]

{"golden_diff": "diff --git a/kivy/core/text/markup.py b/kivy/core/text/markup.py\n--- a/kivy/core/text/markup.py\n+++ b/kivy/core/text/markup.py\n@@ -266,7 +266,7 @@\n         y = 0\n         w, h = self._size\n         refs = self._refs\n-        no_of_lines = len(self._lines)-1\n+        no_of_lines = len(self._lines)\n \n         for line in self._lines:\n             lh = line[1]\n", "issue": "Label Text Clipped Horizontally (Moved)\n**Originally reported as a continuation of #576 by esbullington**\n\nI think I'm having trouble with this same issue.  I'm trying to use markup with a Label, and am finding that my Label text is cut-off along the horizontal axis if I have markup set to True.  This probably is only occurring with the latest development version, even after the above path was pulled.  The problem does not occur with Kivy 1.3.0.  If needed, I can re-install the development version and make a screen shot, but for now I'm working with Kivy 1.3.0. \n\nI've only started working with Kivy in the past few days, so I'm not yet in a place where I feel comfortable sending in a patch.  (awesome framework, by the way, congrats on the great work!).\n\nOh, and it doesn't look like I can re-open the issue, so someone else may wish to do so, or else tell me to open another issue for the problem.\n\nUPDATE: I coped markup.py from Kivy 1.3 to Kivy1.4-dev and it resolved this issue for me.  I may now have problems with rst, but at least my markdown labels aren't cut in half.\n\n", "before_files": [{"content": "'''\nText Markup\n===========\n\n.. versionadded:: 1.1.0\n\nWe provide a simple text-markup for inline text styling. The syntax look the\nsame as the `BBCode <http://en.wikipedia.org/wiki/BBCode>`_.\n\nA tag is defined as ``[tag]``, and might have a closed tag associated:\n``[/tag]``. Example of a markup text::\n\n    [b]Hello [color=ff0000]world[/b][/color]\n\nThe following tags are availables:\n\n``[b][/b]``\n    Activate bold text\n``[i][/i]``\n    Activate italic text\n``[font=<str>][/font]``\n    Change the font\n``[size=<integer>][/size]``\n    Change the font size\n``[color=#<color>][/color]``\n    Change the text color\n``[ref=<str>][/ref]``\n    Add an interactive zone. The reference + all the word box inside the\n    reference will be available in :data:`MarkupLabel.refs`\n``[anchor=<str>]``\n    Put an anchor in the text. You can get the position of your anchor within\n    the text with :data:`MarkupLabel.anchors`\n\nIf you need to escape the markup from the current text, use\n:func:`kivy.utils.escape_markup`.\n'''\n\n__all__ = ('MarkupLabel', )\n\nfrom kivy.graphics.texture import Texture\nfrom kivy.utils import platform\nfrom kivy.parser import parse_color\nfrom kivy.logger import Logger\nimport re\nfrom kivy.core.text import Label, LabelBase\nfrom copy import copy\n\n# We need to do this trick when documentation is generated\nMarkupLabelBase = Label\nif Label is None:\n    MarkupLabelBase = LabelBase\n\n\nclass MarkupLabel(MarkupLabelBase):\n    '''Markup text label.\n\n    See module documentation for more informations.\n    '''\n\n    def __init__(self, *largs, **kwargs):\n        self._style_stack = {}\n        self._refs = {}\n        super(MarkupLabel, self).__init__(*largs, **kwargs)\n\n    @property\n    def refs(self):\n        '''Get the bounding box of all the ``[ref=...]``::\n\n            { 'refA': ((x1, y1, x2, y2), (x1, y1, x2, y2)), ... }\n        '''\n        return self._refs\n\n    @property\n    def anchors(self):\n        '''Get the position of all the ``[anchor=...]``::\n\n            { 'anchorA': (x, y), 'anchorB': (x, y), ... }\n        '''\n        return self._anchors\n\n    @property\n    def markup(self):\n        '''Return the text with all the markup splitted::\n\n            >>> MarkupLabel('[b]Hello world[/b]').markup\n            >>> ('[b]', 'Hello world', '[/b]')\n\n        '''\n        s = re.split('(\\[.*?\\])', self.label)\n        s = [x for x in s if x != '']\n        return s\n\n    def _push_style(self, k):\n        if not k in self._style_stack:\n            self._style_stack[k] = []\n        self._style_stack[k].append(self.options[k])\n\n    def _pop_style(self, k):\n        if k not in self._style_stack or len(self._style_stack[k]) == 0:\n            Logger.warning('Label: pop style stack without push')\n            return\n        v = self._style_stack[k].pop()\n        self.options[k] = v\n\n    def render(self, real=False):\n        options = copy(self.options)\n        if not real:\n            ret = self._pre_render()\n        else:\n            ret = self._real_render()\n        self.options = options\n        return ret\n\n    def _pre_render(self):\n        # split markup, words, and lines\n        # result: list of word with position and width/height\n        # during the first pass, we don't care about h/valign\n        self._lines = lines = []\n        self._refs = {}\n        self._anchors = {}\n        spush = self._push_style\n        spop = self._pop_style\n        options = self.options\n        options['_ref'] = None\n        for item in self.markup:\n            if item == '[b]':\n                spush('bold')\n                options['bold'] = True\n                self.resolve_font_name()\n            elif item == '[/b]':\n                spop('bold')\n                self.resolve_font_name()\n            elif item == '[i]':\n                spush('italic')\n                options['italic'] = True\n                self.resolve_font_name()\n            elif item == '[/i]':\n                spop('italic')\n                self.resolve_font_name()\n            elif item[:6] == '[size=':\n                try:\n                    size = int(item[6:-1])\n                except ValueError:\n                    size = options['font_size']\n                spush('font_size')\n                options['font_size'] = size\n            elif item == '[/size]':\n                spop('font_size')\n            elif item[:7] == '[color=':\n                color = parse_color(item[7:-1])\n                spush('color')\n                options['color'] = color\n            elif item == '[/color]':\n                spop('color')\n            elif item[:6] == '[font=':\n                fontname = item[6:-1]\n                spush('font_name')\n                options['font_name'] = fontname\n                self.resolve_font_name()\n            elif item == '[/font]':\n                spop('font_name')\n                self.resolve_font_name()\n            elif item[:5] == '[ref=':\n                ref = item[5:-1]\n                spush('_ref')\n                options['_ref'] = ref\n            elif item == '[/ref]':\n                spop('_ref')\n            elif item[:8] == '[anchor=':\n                ref = item[8:-1]\n                if len(lines):\n                    x, y = lines[-1][0:2]\n                else:\n                    x = y = 0\n                self._anchors[ref] = x, y\n            else:\n                item = item.replace('&bl;', '[').replace(\n                        '&br;', ']').replace('&amp;', '&')\n                self._pre_render_label(item, options, lines)\n\n        # calculate the texture size\n        w, h = self.text_size\n        if h < 0:\n            h = None\n        if w < 0:\n            w = None\n        if w is None:\n            w = max([line[0] for line in lines])\n        if h is None:\n            h = sum([line[1] for line in lines])\n        return w, h\n\n    def _pre_render_label(self, word, options, lines):\n        # precalculate id/name\n        if not self.fontid in self._cache_glyphs:\n            self._cache_glyphs[self.fontid] = {}\n        cache = self._cache_glyphs[self.fontid]\n\n        # verify that each glyph have size\n        glyphs = list(set(word))\n        get_extents = self.get_extents\n        for glyph in glyphs:\n            if not glyph in cache:\n                cache[glyph] = get_extents(glyph)\n\n        # get last line information\n        if len(lines):\n            line = lines[-1]\n        else:\n            # line-> line width, line height, words\n            # words -> (w, h, word)...\n            line = [0, 0, []]\n            lines.append(line)\n\n        # extract user limitation\n        uw, uh = self.text_size\n\n        # split the word\n        for part in re.split(r'( |\\n)', word):\n\n            if part == '':\n                continue\n\n            if part == '\\n':\n                # put a new line!\n                line = [0, 0, []]\n                lines.append(line)\n                continue\n\n            # get current line information\n            lw, lh = line[:2]\n\n            # calculate the size of the part\n            # (extract all extents of the part,\n            # calculate width through extents due to kerning\n            # and get the maximum height)\n            pg = [cache[g] for g in part]\n            pw = get_extents(part)[0]\n            ph = max([g[1] for g in pg])\n\n            options = copy(options)\n\n            # check if the part can be put in the line\n            if uw is None or lw + pw < uw:\n                # no limitation or part can be contained in the line\n                # then append the part to the line\n                line[2].append((pw, ph, part, options))\n                # and update the line size\n                line[0] += pw\n                line[1] = max(line[1], ph)\n            else:\n                # part can't be put in the line, do a new one...\n                line = [pw, ph, [(pw, ph, part, options)]]\n                lines.append(line)\n\n    def _real_render(self):\n        # use the lines to do the rendering !\n        self._render_begin()\n\n        r = self._render_text\n\n        # convert halign/valign to int, faster comparaison\n        av = {'top': 0, 'middle': 1, 'bottom': 2}[self.options['valign']]\n        ah = {'left': 0, 'center': 1, 'right': 2}[self.options['halign']]\n\n        y = 0\n        w, h = self._size\n        refs = self._refs\n        no_of_lines = len(self._lines)-1\n\n        for line in self._lines:\n            lh = line[1]\n            lw = line[0]\n\n            # horizontal alignement\n            if ah == 0:\n                x = 0\n            elif ah == 1:\n                x = int((w - lw) / 2)\n            else:\n                x = w - lw\n\n            # vertical alignement\n            if y == 0:\n                if av == 1:\n                    y = int((h - (lh*no_of_lines))/2)\n                elif av == 2:\n                    y = h - (lh*(no_of_lines))\n\n\n            for pw, ph, part, options in line[2]:\n                self.options = options\n                r(part, x, y + (lh - ph) / 1.25)\n\n                # should we record refs ?\n                ref = options['_ref']\n                if ref is not None:\n                    if not ref in refs:\n                        refs[ref] = []\n                    refs[ref].append((x, y, x + pw, y + ph))\n\n                #print 'render', repr(part), x, y, (lh, ph), options\n                x += pw\n            y += line[1]\n\n        # get data from provider\n        data = self._render_end()\n        assert(data)\n\n        # create texture is necessary\n        texture = self.texture\n        mipmap = self.options['mipmap']\n        if texture is None:\n            if data is None:\n                if platform() in ('android', 'ios'):\n                    colorfmt = 'rgba'\n                else:\n                    colorfmt = 'luminance_alpha'\n                texture = Texture.create(\n                        size=self.size, colorfmt=colorfmt,\n                        mipmap=mipmap)\n            else:\n                texture = Texture.create_from_data(data, mipmap=mipmap)\n            texture.flip_vertical()\n        elif self.width != texture.width or self.height != texture.height:\n            if data is None:\n                texture = Texture.create(size=self.size, mipmap=mipmap)\n            else:\n                texture = Texture.create_from_data(data, mipmap=mipmap)\n            texture.flip_vertical()\n\n        # update texture\n        self.texture = texture\n        self.texture.blit_data(data)\n\n", "path": "kivy/core/text/markup.py"}], "after_files": [{"content": "'''\nText Markup\n===========\n\n.. versionadded:: 1.1.0\n\nWe provide a simple text-markup for inline text styling. The syntax look the\nsame as the `BBCode <http://en.wikipedia.org/wiki/BBCode>`_.\n\nA tag is defined as ``[tag]``, and might have a closed tag associated:\n``[/tag]``. Example of a markup text::\n\n    [b]Hello [color=ff0000]world[/b][/color]\n\nThe following tags are availables:\n\n``[b][/b]``\n    Activate bold text\n``[i][/i]``\n    Activate italic text\n``[font=<str>][/font]``\n    Change the font\n``[size=<integer>][/size]``\n    Change the font size\n``[color=#<color>][/color]``\n    Change the text color\n``[ref=<str>][/ref]``\n    Add an interactive zone. The reference + all the word box inside the\n    reference will be available in :data:`MarkupLabel.refs`\n``[anchor=<str>]``\n    Put an anchor in the text. You can get the position of your anchor within\n    the text with :data:`MarkupLabel.anchors`\n\nIf you need to escape the markup from the current text, use\n:func:`kivy.utils.escape_markup`.\n'''\n\n__all__ = ('MarkupLabel', )\n\nfrom kivy.graphics.texture import Texture\nfrom kivy.utils import platform\nfrom kivy.parser import parse_color\nfrom kivy.logger import Logger\nimport re\nfrom kivy.core.text import Label, LabelBase\nfrom copy import copy\n\n# We need to do this trick when documentation is generated\nMarkupLabelBase = Label\nif Label is None:\n    MarkupLabelBase = LabelBase\n\n\nclass MarkupLabel(MarkupLabelBase):\n    '''Markup text label.\n\n    See module documentation for more informations.\n    '''\n\n    def __init__(self, *largs, **kwargs):\n        self._style_stack = {}\n        self._refs = {}\n        super(MarkupLabel, self).__init__(*largs, **kwargs)\n\n    @property\n    def refs(self):\n        '''Get the bounding box of all the ``[ref=...]``::\n\n            { 'refA': ((x1, y1, x2, y2), (x1, y1, x2, y2)), ... }\n        '''\n        return self._refs\n\n    @property\n    def anchors(self):\n        '''Get the position of all the ``[anchor=...]``::\n\n            { 'anchorA': (x, y), 'anchorB': (x, y), ... }\n        '''\n        return self._anchors\n\n    @property\n    def markup(self):\n        '''Return the text with all the markup splitted::\n\n            >>> MarkupLabel('[b]Hello world[/b]').markup\n            >>> ('[b]', 'Hello world', '[/b]')\n\n        '''\n        s = re.split('(\\[.*?\\])', self.label)\n        s = [x for x in s if x != '']\n        return s\n\n    def _push_style(self, k):\n        if not k in self._style_stack:\n            self._style_stack[k] = []\n        self._style_stack[k].append(self.options[k])\n\n    def _pop_style(self, k):\n        if k not in self._style_stack or len(self._style_stack[k]) == 0:\n            Logger.warning('Label: pop style stack without push')\n            return\n        v = self._style_stack[k].pop()\n        self.options[k] = v\n\n    def render(self, real=False):\n        options = copy(self.options)\n        if not real:\n            ret = self._pre_render()\n        else:\n            ret = self._real_render()\n        self.options = options\n        return ret\n\n    def _pre_render(self):\n        # split markup, words, and lines\n        # result: list of word with position and width/height\n        # during the first pass, we don't care about h/valign\n        self._lines = lines = []\n        self._refs = {}\n        self._anchors = {}\n        spush = self._push_style\n        spop = self._pop_style\n        options = self.options\n        options['_ref'] = None\n        for item in self.markup:\n            if item == '[b]':\n                spush('bold')\n                options['bold'] = True\n                self.resolve_font_name()\n            elif item == '[/b]':\n                spop('bold')\n                self.resolve_font_name()\n            elif item == '[i]':\n                spush('italic')\n                options['italic'] = True\n                self.resolve_font_name()\n            elif item == '[/i]':\n                spop('italic')\n                self.resolve_font_name()\n            elif item[:6] == '[size=':\n                try:\n                    size = int(item[6:-1])\n                except ValueError:\n                    size = options['font_size']\n                spush('font_size')\n                options['font_size'] = size\n            elif item == '[/size]':\n                spop('font_size')\n            elif item[:7] == '[color=':\n                color = parse_color(item[7:-1])\n                spush('color')\n                options['color'] = color\n            elif item == '[/color]':\n                spop('color')\n            elif item[:6] == '[font=':\n                fontname = item[6:-1]\n                spush('font_name')\n                options['font_name'] = fontname\n                self.resolve_font_name()\n            elif item == '[/font]':\n                spop('font_name')\n                self.resolve_font_name()\n            elif item[:5] == '[ref=':\n                ref = item[5:-1]\n                spush('_ref')\n                options['_ref'] = ref\n            elif item == '[/ref]':\n                spop('_ref')\n            elif item[:8] == '[anchor=':\n                ref = item[8:-1]\n                if len(lines):\n                    x, y = lines[-1][0:2]\n                else:\n                    x = y = 0\n                self._anchors[ref] = x, y\n            else:\n                item = item.replace('&bl;', '[').replace(\n                        '&br;', ']').replace('&amp;', '&')\n                self._pre_render_label(item, options, lines)\n\n        # calculate the texture size\n        w, h = self.text_size\n        if h < 0:\n            h = None\n        if w < 0:\n            w = None\n        if w is None:\n            w = max([line[0] for line in lines])\n        if h is None:\n            h = sum([line[1] for line in lines])\n        return w, h\n\n    def _pre_render_label(self, word, options, lines):\n        # precalculate id/name\n        if not self.fontid in self._cache_glyphs:\n            self._cache_glyphs[self.fontid] = {}\n        cache = self._cache_glyphs[self.fontid]\n\n        # verify that each glyph have size\n        glyphs = list(set(word))\n        get_extents = self.get_extents\n        for glyph in glyphs:\n            if not glyph in cache:\n                cache[glyph] = get_extents(glyph)\n\n        # get last line information\n        if len(lines):\n            line = lines[-1]\n        else:\n            # line-> line width, line height, words\n            # words -> (w, h, word)...\n            line = [0, 0, []]\n            lines.append(line)\n\n        # extract user limitation\n        uw, uh = self.text_size\n\n        # split the word\n        for part in re.split(r'( |\\n)', word):\n\n            if part == '':\n                continue\n\n            if part == '\\n':\n                # put a new line!\n                line = [0, 0, []]\n                lines.append(line)\n                continue\n\n            # get current line information\n            lw, lh = line[:2]\n\n            # calculate the size of the part\n            # (extract all extents of the part,\n            # calculate width through extents due to kerning\n            # and get the maximum height)\n            pg = [cache[g] for g in part]\n            pw = get_extents(part)[0]\n            ph = max([g[1] for g in pg])\n\n            options = copy(options)\n\n            # check if the part can be put in the line\n            if uw is None or lw + pw < uw:\n                # no limitation or part can be contained in the line\n                # then append the part to the line\n                line[2].append((pw, ph, part, options))\n                # and update the line size\n                line[0] += pw\n                line[1] = max(line[1], ph)\n            else:\n                # part can't be put in the line, do a new one...\n                line = [pw, ph, [(pw, ph, part, options)]]\n                lines.append(line)\n\n    def _real_render(self):\n        # use the lines to do the rendering !\n        self._render_begin()\n\n        r = self._render_text\n\n        # convert halign/valign to int, faster comparaison\n        av = {'top': 0, 'middle': 1, 'bottom': 2}[self.options['valign']]\n        ah = {'left': 0, 'center': 1, 'right': 2}[self.options['halign']]\n\n        y = 0\n        w, h = self._size\n        refs = self._refs\n        no_of_lines = len(self._lines)\n\n        for line in self._lines:\n            lh = line[1]\n            lw = line[0]\n\n            # horizontal alignement\n            if ah == 0:\n                x = 0\n            elif ah == 1:\n                x = int((w - lw) / 2)\n            else:\n                x = w - lw\n\n            # vertical alignement\n            if y == 0:\n                if av == 1:\n                    y = int((h - (lh*no_of_lines))/2)\n                elif av == 2:\n                    y = h - (lh*(no_of_lines))\n\n\n            for pw, ph, part, options in line[2]:\n                self.options = options\n                r(part, x, y + (lh - ph) / 1.25)\n\n                # should we record refs ?\n                ref = options['_ref']\n                if ref is not None:\n                    if not ref in refs:\n                        refs[ref] = []\n                    refs[ref].append((x, y, x + pw, y + ph))\n\n                #print 'render', repr(part), x, y, (lh, ph), options\n                x += pw\n            y += line[1]\n\n        # get data from provider\n        data = self._render_end()\n        assert(data)\n\n        # create texture is necessary\n        texture = self.texture\n        mipmap = self.options['mipmap']\n        if texture is None:\n            if data is None:\n                if platform() in ('android', 'ios'):\n                    colorfmt = 'rgba'\n                else:\n                    colorfmt = 'luminance_alpha'\n                texture = Texture.create(\n                        size=self.size, colorfmt=colorfmt,\n                        mipmap=mipmap)\n            else:\n                texture = Texture.create_from_data(data, mipmap=mipmap)\n            texture.flip_vertical()\n        elif self.width != texture.width or self.height != texture.height:\n            if data is None:\n                texture = Texture.create(size=self.size, mipmap=mipmap)\n            else:\n                texture = Texture.create_from_data(data, mipmap=mipmap)\n            texture.flip_vertical()\n\n        # update texture\n        self.texture = texture\n        self.texture.blit_data(data)\n\n", "path": "kivy/core/text/markup.py"}]}