×

Discussion Board

Results 1 to 7 of 7
  1. #1
    Regular Contributor
    Join Date
    Jan 2004
    Location
    Helsinki
    Posts
    376

    Red face TextWrapper example class

    Hi,

    In the case someone needs to render text with wrapping, please use the sample class below:

    Code:
    """ 
        
        Text renderer.
        
    """
    
    __author__ = "Mikko Ohtamaa <mikko@redinnovation.com>"
    __docformat__ = 'epytext'
    
    class TextRenderer:
        """ Simple multi-line text rendering for PyS60 Canvas.
        
        TextRenderer remembers the cursor position, allowing you to
        sequentially add more text.
        
        Basic support for wrapping too long lines exists.
        
        Example::
        
            canvas = appuifw.Canvas()
            renderer = TextRenderer(canvas)
            renderer.set_position(50,50)
            renderer.render_string("Word 1")
            renderer.render_line("Word 2")
            renderer.render("Text split\nby new lines")       
            renderer.render("This is a very long text which is automatically wrapped")
        """
        
        def __init__(self, canvas):
            """ Construct text renderer.
            
            Inital cursor position is (0, 0). 
                 
            @param canvas appuifw.Canvas instance 
            """
            
            # Used canvas
            self.canvas = canvas
            
            # Coordinates of the cursor
            self.coords = [0,0]
            
            self.spacing = 1
            
        def set_line_spacing(self, spacing):
            """ Set Y pixels between text lines.
            
            """
            self.spacing = spacing
                    
        def set_position(self, coords):
            """ Set the position of the cursor.
            
            @param coords [X,Y] sequence
            """
            self.coords = coords
            
        def move_cursor(self, x, y):
            """ Set cursor position relative to the current coordinates.
            
            """
            self.coords[0] += x
            self.coords[1] += y
            
        def render_string(self, text, font, fill):
            """ Render a line and moves cursor right. """
            bounding, to_right, fits = self.canvas.measure_text(text, font=font)
            self.canvas.text([self.coords[0], self.coords[1] - bounding[1]], unicode(text), font=font, fill=fill)
            self.coords = [self.coords[0] + to_rigth, self.coords[1]]
            
        def render_line(self, text, font, fill):
            """ Render one line of text.
            
            Moves cursor below.
            
            @param line string
            """
                
            bounding, to_right, fits = self.canvas.measure_text(text, font=font)
            
            # canvas.text coordinates are the baseline position of the rendered
            # text. It's not top left position.
            self.canvas.text([self.coords[0], self.coords[1] - bounding[1]], unicode(text), font=font, fill=fill)
            
            # Move cursor one line below
            self.coords = [self.coords[0], 
                           self.coords[1] - bounding[1] + bounding[3] + self.spacing                       
                           ]
    
        def chop(self, text, font, width):
            """ Wrap text to lines. 
            
            @param text Row of text to wrap
            @param width pixels we can use for one line
            @param font appuifw font description
                    
            TODO: Smarter breaker char logic.
            """
            
            lines = []
            
            # Paragraph yet to be chopped
            text_left = text
    
            while len(text_left) > 0: 
                bounding, to_right, fits = self.canvas.measure_text(
                        text_left, font=font, 
                        maxwidth=width, maxadvance=width)
                
                if fits <= 0:
                    lines.append(text_left)
                    break
                        
                #print "tor:" + str(to_right) + " fits:" + str(fits)
                slice = text_left[0:fits]
            
                # How many chars we can skip at the end of the row
                # (whitespaces at the end of the row)
                adjust = 0
            
                if len(slice) < len(text_left):
                    # Use the last space as a break point
                    rindex = slice.rfind(" ")            
                    if rindex > 0:
                        adjust = 1
                        slice = slice[0:rindex]
                                    
                lines.append(slice)
                text_left = text_left[len(slice)+adjust:]
            
            return lines
            
        def render(self, text, font=(u"normal", 14), fill=0x000000):
            """ Render a piece of text.
            
            Primitive text wrap support.
            
            Strings are automatically converted to unicode.
            
            @param text: Multiline text
            @param font: appuifw font description (optional)
            @param fill: appuifw fill description (optional)
            
            @type text: unicode or str
            @return None
            """
            text = unicode(text)        
            max_width = self.canvas.size[0] - self.coords[0]
            #print "Max width: " + str(max_width)
            lines = text.split("\n")
            for line in lines:                        
                chopped_lines = self.chop(line, font, max_width)
                for chopped_line in chopped_lines:
                    self.render_line(chopped_line, font, fill)
    Last edited by miohtama; 2008-01-14 at 10:15. Reason: Removed one comment line containing foul language
    Mikko Ohtamaa

    http://mfabrik.com
    http://blog.mfabrik.com

  2. #2
    Regular Contributor
    Join Date
    Sep 2005
    Location
    Finland, Helsinki
    Posts
    323

    Re: TextWrapper example class

    Hi Mikko.

    Quote Originally Posted by miohtama View Post
    In the case someone needs to render text with wrapping, please use the sample class below - -
    Code:
    """  Text renderer. """
    __author__ = "Mikko Ohtamaa <mikko@redinnovation.com>"
    __docformat__ = 'epytext'
    
    class TextRenderer:
    You have posted many useful code snippets here, so thank you for that.

    But under which license you release them? Some Open Source license would be nice (e.g. apache2, MIT-style, GPL...).

  3. #3
    Regular Contributor
    Join Date
    Jan 2004
    Location
    Helsinki
    Posts
    376

    Smile Re: TextWrapper example class

    Quote Originally Posted by aaaaapo View Post
    Hi Mikko.



    You have posted many useful code snippets here, so thank you for that.

    But under which license you release them? Some Open Source license would be nice (e.g. apache2, MIT-style, GPL...).
    Let's say it's BSD

    AFAIK, at least in Finnish copyright law there is a statement for "natural copyright grant". If it's clear from the context that the author is giving permission for the audience to use the copyrighted work, the audience can do it without explictly asking a permission.

    I assume posting small code snippets to public forums is such an act and you can use code snippets found here as you like.

    Just my two study credits of copyright law.

    Of course, the corporate lawyers may go with the stricter interpretation of the law.
    Mikko Ohtamaa

    http://mfabrik.com
    http://blog.mfabrik.com

  4. #4
    Registered User
    Join Date
    Feb 2005
    Location
    Belgium (Europe)
    Posts
    1,352

    Re: TextWrapper example class

    Hello Mikko ,

    Thanks for your useful class but you made a slight error (perhaps you haven't really used this code ?) in the source code of this class.

    You must read to_right instead of to_rigth

    BR
    Cyke64

    Code:
    """ 
        
        Text renderer.
        
    """
    
    __author__ = "Mikko Ohtamaa <mikko@redinnovation.com>"
    __docformat__ = 'epytext'
    
    class TextRenderer:
        """ Simple multi-line text rendering for PyS60 Canvas.
        
        TextRenderer remembers the cursor position, allowing you to
        sequentially add more text.
        
        Basic support for wrapping too long lines exists.
        
        Example::
        
            canvas = appuifw.Canvas()
            renderer = TextRenderer(canvas)
            renderer.set_position(50,50)
            renderer.render_string("Word 1")
            renderer.render_line("Word 2")
            renderer.render("Text split\nby new lines")       
            renderer.render("This is a very long text which is automatically wrapped")
        """
        
        def __init__(self, canvas):
            """ Construct text renderer.
            
            Inital cursor position is (0, 0). 
                 
            @param canvas appuifw.Canvas instance 
            """
            
            # Used canvas
            self.canvas = canvas
            
            # Coordinates of the cursor
            self.coords = [0,0]
            
            self.spacing = 1
            
        def set_line_spacing(self, spacing):
            """ Set Y pixels between text lines.
            
            """
            self.spacing = spacing
                    
        def set_position(self, coords):
            """ Set the position of the cursor.
            
            @param coords [X,Y] sequence
            """
            self.coords = coords
            
        def move_cursor(self, x, y):
            """ Set cursor position relative to the current coordinates.
            
            """
            self.coords[0] += x
            self.coords[1] += y
            
        def render_string(self, text, font, fill):
            """ Render a line and moves cursor right. """
            bounding, to_right, fits = self.canvas.measure_text(text, font=font)
            self.canvas.text([self.coords[0], self.coords[1] - bounding[1]], unicode(text), font=font, fill=fill)
            self.coords = [self.coords[0] + to_right, self.coords[1]]
            
        def render_line(self, text, font, fill):
            """ Render one line of text.
            
            Moves cursor below.
            
            @param line string
            """
                
            bounding, to_right, fits = self.canvas.measure_text(text, font=font)
            
            # canvas.text coordinates are the baseline position of the rendered
            # text. It's not top left position.
            self.canvas.text([self.coords[0], self.coords[1] - bounding[1]], unicode(text), font=font, fill=fill)
            
            # Move cursor one line below
            self.coords = [self.coords[0], 
                           self.coords[1] - bounding[1] + bounding[3] + self.spacing                       
                           ]
    
        def chop(self, text, font, width):
            """ Wrap text to lines. 
            
            @param text Row of text to wrap
            @param width pixels we can use for one line
            @param font appuifw font description
                    
            TODO: Smarter breaker char logic.
            """
            
            lines = []
            
            # Paragraph yet to be chopped
            text_left = text
    
            while len(text_left) > 0: 
                bounding, to_right, fits = self.canvas.measure_text(
                        text_left, font=font, 
                        maxwidth=width, maxadvance=width)
                
                if fits <= 0:
                    lines.append(text_left)
                    break
                        
                #print "tor:" + str(to_right) + " fits:" + str(fits)
                slice = text_left[0:fits]
            
                # How many chars we can skip at the end of the row
                # (whitespaces at the end of the row)
                adjust = 0
            
                if len(slice) < len(text_left):
                    # Use the last space as a break point
                    rindex = slice.rfind(" ")            
                    if rindex > 0:
                        adjust = 1
                        slice = slice[0:rindex]
                                    
                lines.append(slice)
                text_left = text_left[len(slice)+adjust:]
            
            return lines
            
        def render(self, text, font=(u"normal", 14), fill=0x000000):
            """ Render a piece of text.
            
            Primitive text wrap support.
            
            Strings are automatically converted to unicode.
            
            @param text: Multiline text
            @param font: appuifw font description (optional)
            @param fill: appuifw fill description (optional)
            
            @type text: unicode or str
            @return None
            """
            text = unicode(text)        
            max_width = self.canvas.size[0] - self.coords[0]
            #print "Max width: " + str(max_width)
            lines = text.split("\n")
            for line in lines:                        
                chopped_lines = self.chop(line, font, max_width)
                for chopped_line in chopped_lines:
                    self.render_line(chopped_line, font, fill)
    pys60 1.4.5 and 2.0.0, pygame, PyS60 CE on E90 and 5800 !

    Find my pys60 extension modules on cyke64.googlepages.com

  5. #5
    Regular Contributor
    Join Date
    Jan 2004
    Location
    Helsinki
    Posts
    376

    Re: TextWrapper example class

    [QUOTE=cyke64;378027]Hello Mikko ,

    You must read to_right instead of to_rigth

    BR
    Cyke64

    [code]

    Thanks Cyke64. Looks like one bug slipped through my fingers when cleaning up the code
    Mikko Ohtamaa

    http://mfabrik.com
    http://blog.mfabrik.com

  6. #6
    Registered User
    Join Date
    Mar 2008
    Posts
    17

    Re: TextWrapper example class

    Hi,
    I got this error TypeError:set_position[]takes exactly 2 arguments(3 given) when I execute the given code example as shown below.

    canvas = appuifw.Canvas()
    renderer = TextRenderer(canvas)
    renderer.set_position(50,50)
    renderer.render_string("Word 1")
    renderer.render_line("Word 2")
    renderer.render("Text split\nby new lines")
    renderer.render("This is a very long text which is automatically wrapped")


    Pls check what is wrong.
    Thank you.

  7. #7
    Regular Contributor
    Join Date
    Jan 2004
    Location
    Helsinki
    Posts
    376

    Re: TextWrapper example class

    Quote Originally Posted by ComThink View Post
    Hi,
    I got this error TypeError:set_position[]takes exactly 2 arguments(3 given) when I execute the given code example as shown below.

    Pls check what is wrong.
    Thank you.
    renderer.set_position([50,50])

    I later changed set_position to take coordinate tuple instead of x and y arguments and forget to update the example.
    Mikko Ohtamaa

    http://mfabrik.com
    http://blog.mfabrik.com

Similar Threads

  1. Linking Error(Undefined Symbol)
    By nile_mail in forum Carbide.c++ IDE and plug-ins (Closed)
    Replies: 10
    Last Post: 2008-03-26, 23:32
  2. Need one HTTP client example
    By vinayakak in forum Symbian Networking & Messaging (Closed)
    Replies: 15
    Last Post: 2008-01-06, 06:44
  3. need information about j2me polish
    By rathikathangaraj in forum Mobile Java General
    Replies: 4
    Last Post: 2007-12-19, 09:01
  4. send array[0] different class
    By gift_te in forum Symbian
    Replies: 0
    Last Post: 2007-03-28, 13:04
  5. Exceptions while loading application
    By avinash_rs in forum Mobile Java General
    Replies: 0
    Last Post: 2003-06-09, 10:53

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
×