Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

text function limitations?

in Bugs Posts: 194

Hi all,

Just wondering if anyone has seen what I’m currently seeing? I’m trying to draw a fairly hefty chunk of text using the text function (~ 3000 characters) but as soon as the length of the string I pass goes above 2010 characters nothing is drawn. The text I’m passing is just some lorum ipsum placeholder for the moment.

This is the code that works:

local txt = string.sub(text_to_draw, 1, 2010)
text(txt, 0, 0)

and this doesn’t:

local txt = string.sub(text_to_draw, 1, 2011)
text(txt, 0, 0)

Anyone have any ideas?

Tagged:

Comments

  • Posts: 2,356
    @Steppers - you need a routine to split the text you wish to present into widths that will fit the screen width at the text size you have specified and with the font you have chosen.

    I think I found a routine which I used in the Final Frontier demo in that post if you want to look it up. Found it, and others, with an internet search.
  • dave1707dave1707 Mod
    Posts: 9,423

    @Steppers What other code do you have. A straight text line doesn’t go much past the width of the screen let alone 2010 characters. Are you wrapping the text or something like that.

  • edited May 23 Posts: 194

    @Bri_G @dave1707 Yep, it’s wrapping the text at the correct width and it renders just fine exactly where I expect it to at 2010 characters but it just seems like an odd limitation beyond that.

    I can’t really split it easily and render the parts nicely as it’s currently failing in the middle of a word. I could but it’ll be a pain.

  • Posts: 194

    For context, it’s part of a project info panel I’m adding to WebRepo for longer descriptions so it’s unlikely we’ll actually hit this limit but it seems odd nonetheless.

    This should be a little more of the actual code I’m using (which doesn’t render the text when over 2010 characters)

    -- Draw long description
    textWrapWidth(PANEL_W - PADDING*2)
    if self.metadata.long_desc then
        textMode(CORNER)
        local txt = self.metadata.long_desc
        _, th = textSize(txt)
        text(txt, PADDING, button_y - 36 - PADDING - th)
    end
    
  • dave1707dave1707 Mod
    Posts: 9,423

    @Steppers I can show a chunk of code that’s 4,105 characters. I’m using a textWrapWidth of 1026 in landscape. A textWrapWidth of 1027 or 4106 characters and nothing displays.

  • Posts: 194

    @dave1707 Oh that’s pretty strange then. That definitely sounds broken to me.

    I can get it to render just fine if I set the wrap width to 1024 so something to do with that I guess.

  • dave1707dave1707 Mod
    Posts: 9,423

    @Steppers I don’t know if it’s broken or not. I’m sure there’s limitations to everything. They probably thought 4,000+ characters was more than enough.

  • dave1707dave1707 Mod
    Posts: 9,423

    @Steppers Anytime I want to show a lot of text, I do something like this. You can scroll the text up/down. Change the variable “wide” value to fill the screen.

    viewer.mode=FULLSCREEN
    
    function setup()
        font("Courier")
        textMode(CORNER)
        str=""
        for z=1,8000 do
            str=str..string.format("%04d",z)      
        end
        fill(255)
        wide=80
        dy=0
    end
    
    function draw()
        background(0)   
        line=0 
        for y=0,#str//wide do
            line=line+1
            text(string.sub(str,y*wide+1,y*wide+wide),1,HEIGHT-line*20+dy)
        end
    end
    
    function touched(t)
        if t.state==CHANGED then
            dy=dy+t.deltaY
            if dy<0 then
                dy=0
            end
        end
    end
    
  • Posts: 194

    @dave1707 Perfect, thank you. I’m going to stick with unscrollable text for the time being but will come back and use something like that later :smile:

    I think I’d like it to split between words too but I hadn’t thought about actually doing it manually.

  • dave1707dave1707 Mod
    Posts: 9,423

    @Steppers Splitting between words at the end of each line should be easy enough. The code I show above I just did off the top of my head. I probably have or had code that splits words on spaces at the end of each line.

  • edited May 24 Posts: 2,356
    @Steppers - here is the function I found on the net.

    Pardon the android phone formatting. See amended post below.
  • Posts: 1,278

    @Steppers @Simeon @dave1707 imho there’s definitely something wrong with the text function bc even with just three words it won’t print to screen at seemingly-random sizes. IIRC you could sometimes get the text in my text-resizing box to disappear and reappear at least twice before it reached any of the screen borders.

  • edited May 24 Posts: 2,356

    @Stepper - here is the function I found on the net.

    function split(str, max_line_length)
        local lines = {}
        local line
        str:gsub('(%s*)(%S+)',
        function(spc, word)
            if not line or #line + #spc + #word > max_line_length then
                table.insert(lines, line)
                line = word
            else
                line = line..spc..word
            end
        end
        )
        table.insert(lines, line)
        return lines
    end
    
    

    Grrrrh - I hate posting from Android phones into this forum but when you're away from your iPad and Mac what can you do? Pasting here much better.

  • Posts: 194

    @Bri_G Amazing. Thank you! I’ll check it out when I come to adding scrolling text on the project panels.

  • dave1707dave1707 Mod
    Posts: 9,423

    Here’s a version that I have. The function split does all the work and creates a table of lines so the line splitting only needs to be done once. Then use the tabLine table to display the lines. Input is the string to split and the pixel width of the line. It uses pixel size and font size to determine the line size. I created a string of 27,456 characters so you can scroll the text up or down. Try changing the sizePixel and sizeFont parameters. It also works for different fonts types. All the other code is just to setup the demo so split() is all that’s needed.

    viewer.mode=STANDARD
    
    function setup()
        parameter.integer("sizePixel",50,800,400,split1)
        parameter.integer("sizeFont",5,60,17,split1)
        fontSize(12)
        textMode(CORNER)
        fill(255)
        tabLine={}
        str="Five little monkeys jumping on the bed. One fell off and bumped his head. Mama called the doctor and the doctor said: No more monkeys jumping on the bed! Four little monkeys jumping on the bed. One fell off and bumped his head. Mama called the doctor and the doctor said: No more monkeys jumping on the bed! Three little monkeys jumping on the bed. One fell off and bumped his head. Mama called the doctor and the doctor said: No more monkeys jumping on the bed! Two little monkeys jumping on the bed. One fell off and bumped his head. Mama called the doctor and the doctor said: No more monkeys jumping on the bed! One little monkey jumping on the bed. He fell off and bumped his head. Mama called the doctor and the doctor said: No more monkeys jumping on the bed! Now there's no little monkeys jumping on the bed. They`re all jumping on the sofa instead! "
    
        for z=1,5 do        -- create a large string
            str=str..str
        end
        print("string size  ",#str)
    
        stroke(255)
        strokeWidth(2)
        dy=0   
        w,h=textSize("A")
        split(str,400)
    end
    
    function split1()
        fontSize(sizeFont)
        w,h=textSize("A")
        dy=0
        tabLine={}
        split(str,sizePixel)
    end
    
    function split(str,pixelSize)
        local temp,line={},"" 
        for word in str:gmatch("%S+") do 
            table.insert(temp,word) 
        end    
        for a,b in pairs(temp) do
            if textSize(line)+textSize(b)<pixelSize then
                line=line..b.." "
            else
                table.insert(tabLine,line)
                line=b.." "
            end            
        end
        if #line>0 then
            table.insert(tabLine,line)
        end
    end
    
    function draw()
        background()
        for a,b in pairs(tabLine) do
            text(b,20,HEIGHT-a*h+dy)
        end
        line(19,0,19,HEIGHT)
        line(sizePixel+20,0,sizePixel+20,HEIGHT)
    end
    
    function touched(t)
        if t.state==CHANGED then
            dy=dy+t.deltaY
        end
    end
    
  • dave1707dave1707 Mod
    edited May 29 Posts: 9,423

    Here’s an updated version of the above code. It splits a string on space boundaries to fit within scrolling box area. Pass the class the string and the x,y,w,h of the scroll area. Also, the font size, font color, and font name can be different for each scroll area. I could have added a lot more options, but this is good enough for now.

    viewer.mode=FULLSCREEN
    
    function setup()
        textMode(CORNER)
        str="Five little monkeys jumping on the bed. One fell off and bumped his head. Mama called the doctor and the doctor said: No more monkeys jumping on the bed! Four little monkeys jumping on the bed. One fell off and bumped his head. Mama called the doctor and the doctor said: No more monkeys jumping on the bed! Three little monkeys jumping on the bed. One fell off and bumped his head. Mama called the doctor and the doctor said: No more monkeys jumping on the bed! Two little monkeys jumping on the bed. One fell off and bumped his head. Mama called the doctor and the doctor said: No more monkeys jumping on the bed! One little monkey jumping on the bed. He fell off and bumped his head. Mama called the doctor and the doctor said: No more monkeys jumping on the bed! Now there's no little monkeys jumping on the bed. They`re all jumping on the sofa instead! "    
        for z=1,5 do        -- create a larger string
            str=str..str
        end
    
        -- string,  x,  y,  w,  h,  font size, font color, font name
        s1=splitString(str,  20,300,300,400, 10,color(0,255,255),"MarkerFelt-Thin")
        s2=splitString(str, 350,400,450,400, 30,color(0,255,0),"SnellRoundhand")
        s3=splitString(str, 450,100,300,200, 15,color(255,255,0),"CourierNewPS-ItalicMT")
    end
    
    function draw()
        background(32, 72, 104)
        s1:draw()
        s2:draw()
        s3:draw()
    end
    
    function touched(t)
        s1:touched(t)
        s2:touched(t)
        s3:touched(t)
    end
    
    splitString=class()
    
    function splitString:init(str,x,y,width,height,sizeFont,colr,fontName)
        self.x=math.max(5,x)
        self.y=math.max(5,y)  
        self.width=math.min(width,WIDTH-self.x-5)
        self.height=math.min(height,HEIGHT-self.y-5) 
        self.sizeFont=sizeFont
        self.colr=colr
        self.fontName=fontName
        self.lineHeight=0
        self.line="" 
        self.dy=0 
        self.tab={}
        self:split(self)
    end
    
    function splitString:split()
        font(self.fontName)
        fontSize(self.sizeFont)
        _,self.lineHeight=textSize("A")
        local temp={}
        for word in str:gmatch("%S+") do 
            table.insert(temp,word) 
        end    
        for a,b in pairs(temp) do
            if textSize(self.line)+textSize(b)<self.width then
                self.line=self.line..b.." "
            else
                table.insert(self.tab,self.line)
                self.line=b.." "
            end            
        end
        if #self.line>0 then
            table.insert(self.tab,self.line)
        end
    end
    
    function splitString:draw()
        clip(self.x-5,self.y-5,self.width+10,self.height+10)
        stroke(255)
        strokeWidth(2)
        fill(40)
        rect(self.x-5,self.y-5,self.width+10,self.height+10)
        fill(self.colr)
        font(self.fontName)
        fontSize(self.sizeFont)
        for a,b in pairs(self.tab) do
            text(b,self.x,self.y-a*self.lineHeight+self.dy+self.height)
        end
    end
    
    function splitString:touched(t)
        if t.x>self.x and t.x<self.x+self.width and 
                    t.y>self.y and t.y<self.y+self.height then
            if t.state==CHANGED then
                self.dy=self.dy+t.deltaY
                if self.dy<0 then
                    self.dy=0
                end
            end
        end
    end
    
  • Posts: 1,089

    If I draw a rectangle at the side of the screen, I get half a rectangle. I suggest that text should clip at the screen edge, not just vanish altogether.

    This comment in no way relates to the apparent bug I had in my class/method printer due to extremely long method names. Not at all.

    But really, shouldn't it display what it can, like other display stuff?

  • Posts: 1,278
    @RonJeffries i believe it used to.
  • Posts: 1,089

    that, i do not know

  • Posts: 1,278
    @RonJeffries it seems to me one of those low-priority bugs that just hangs around forever. I’m idly curious if rendering to an image context and then drawing that as a sprite would solve the problem in, like, 4 easy steps.
  • Posts: 1,089

    might. try it?

  • dave1707dave1707 Mod
    Posts: 9,423

    @RonJeffries Were you referring to my code above about the rectangle at the side of the screen. If so, I added the following changes to the above code. It now use the edges as limits.

        self.x=math.max(5,x)
        self.y=math.max(5,y)  
        self.width=math.min(width,WIDTH-self.x-5)
        self.height=math.min(height,HEIGHT-self.y-5) 
    

    If anyone is looking for other print/text issues, the following code prints the string of zeroes to the print window. 390768 works, but 390769 doesn’t show anything.
    It prints 13,956 lines.

    function setup()
        str=string.rep("0",390768)
        print(str)
    end
    
  • edited May 29 Posts: 1,278
    @RonJeffries try this project.

    If you tap the Boolean for rendering text to a buffer first, it’ll do that.

    Right now for me there’s no visible difference, because at least on my iPhone this project isn’t currently causing the vanishing-text problem, which I know for a fact it used to because @dave1707 pointed that out the first time I posted it.
  • dave1707dave1707 Mod
    Posts: 9,423

    @UberGoober If I slide the rectH parameter, the text disappears if I do the Boolean switch or not.

  • Posts: 1,278
    @dave1707 huh you’re right.

    I didn’t catch that because it’s not just about the text extending past the screen, which is what I tested for, and which works fine at most sizes.

    For some reason this is about certain specific heights. I don’t get it.
  • dave1707dave1707 Mod
    Posts: 9,423

    As far as I’m concerned, there’s limitations to Codea. It can’t do everything the way everyone wants. If Codea doesn’t do something, I write code to compensate, that’s life. Sure, @Simeon can adjust things, but there will always be something else.

  • Posts: 1,089

    I'm here to request what I think would be of value. If I wanted to put up with bad stuff, I'd code in C# :smiley:. Simeon gets to decide, but I believe it is part of our job as experienced users to suggest ideas of potential value.

  • Posts: 1,278
    @dave1707 your pragmatic attitude makes sense to me a lot of time, but I think there are edge cases where you might possibly be going overboard, such as questioning the necessity of keeping Codea from violating the universal standard for where the cursor goes after you paste something, for one, and this, for another.

    Consistency in rendering text at any size and any location no matter what the coordinates is imho also a universal standard—it’s table stakes for any graphics renderer really.

    Codea flubbing it obviously isn’t a death blow, mainly because it doesn’t come up very often, but it does come up now and then, and when it does, it’s a bad look.
  • dave1707dave1707 Mod
    Posts: 9,423

    @RonJeffries @UberGoober I’m not saying that Codea shouldn’t be fixed. I’m just saying that it has its limitations and we’re going to run into them as we write code. So someone can either stop writing code and wait until the problems are fixed, or they're going to have to modify their code to work around it. Once the fixes are made, they can always go back and modify the original code or leave it. Right now there are limitations as to how text is displayed on the screen. So someone can either wait or code around it until, if or when it’s fixed. The text limitation has been around for a very long time. Will it be changed soon, I don’t know. But I’ll write code to avoid it. Will my code work, yes. Will it still work when the fix is made, probably.

  • Posts: 1,089

    I'm not sure I am understanding the point here. I'm sure we all write code including whatever workarounds we need to get things to work. But it seems you were objecting to my request that text not fail at screen edge but instead display as much as fits. Were you not objecting? If not ... then I don't understand.

    Thanks!

  • dave1707dave1707 Mod
    Posts: 9,423

    @RonJeffries We must not be talking about the same thing. You posted this right after my post of a program above.

    If I draw a rectangle at the side of the screen, I get half a rectangle. I suggest that text should clip at the screen edge, not just vanish altogether.

    So I made changes to my code to clip the text if the rectangle exceeded the edge of the screen. So we’re you referring to my program or something else.

  • Posts: 1,089

    i'm referring to the same thing. i can of course work around it. what i don't understand is that you seem to be taking issue with the idea that it would be more consistent and better, if it clipped.

  • edited May 29 Posts: 194

    I’m can’t quite follow the entire discussion but I’ll throw in my two cents.
    In my opinion the text should absolutely just clip by default. From my own experience with it, the current behaviour just seems like a bug. A limitation yes, but one imposed by the presence of the bug itself.

    I can understand it’s unlikely to be fixed and I can work around it but it’s still a bug and the limitation should not realistically exist. There’s not even a clear cut point as far as I can tell as to when the bug manifests.

  • dave1707dave1707 Mod
    edited May 29 Posts: 9,423

    @RonJeffries In the case of my code, I didn't see the text clipping as a problem. The user chooses the x,y,w,h values for splitString to create the text/rect area. If the edge of the text box ended up passed the edge of the screen and got clipped, they would alter the values to keep it on the screen. I figured that was just a user problem. But anyways I fixed it so the edge limits the size unless they’re too close to an edge. I normally don’t code for everything that can go wrong, not even for myself. If I write it and it breaks for something, I usually fix it.

    PS. My other posts were about the text disappearing if it was too long to display on the screen. That’s been a problem for a long time and the only fix is to code for it.

  • Posts: 1,089

    as you were, or at least as i was. i think there may be an easy way to do this. will report back.

  • edited May 30 Posts: 1,278
    [original post deleted] I think I got on a bit of a high horse that I’d prefer to climb down from. Carry on!
  • dave1707dave1707 Mod
    edited May 30 Posts: 9,423

    Here’s the explanation for the disappearing text on the screen. I thought it was based on the screen width or height, but it’s not. I knew about this a long time ago, but I just remembered how it works now. I’ll see if I can find my original post from long ago. But here’s the explanation in the meantime.

    There’s a command textSize() that returns the 2 values width and height of a string. So w,h=textSize(string) will give the w,h values of a string that’s being displayed using the text command. Different fonts and fontSize will change the values of w and h. The only constant for the text command no matter what the font or fontSize is, is 1024. If the width of the text being displayed is 1024 or less, it will show on the screen. If the width is greater than 1024, it will disappear. So you can determine if a text command will or won’t show on the screen. It doesn’t matter if you’re in portrait or landscape orientation, 1024 is the limit.

    PS. Here’s one link where I explain this and refer to an earlier post. Scroll to the bottom.

    https://codea.io/talk/discussion/8682/scrolling-text-box
    
  • Posts: 1,278
    @dave nice detective work, it seems like. That explains why this bug crops up on my iPad when the text is nowhere near the size of the screen.
  • dave1707dave1707 Mod
    Posts: 9,423

    Here’s an example that I probably posted the first time I wrote about the text disappearing. Change the sliders for tww (textWrapWidth) and fs (fontSize) to vary the text on the screen. In the upper right corner I display the text width and text height. Anytime the width or height exceeds 1024, the text disappears.

    viewer.mode=STANDARD
    
    function setup()
        parameter.integer("tww",100,1100,500)
        parameter.integer("fs",10,100,20)
        fill(255)
        textMode(CORNER)
        str=string.rep("0",500)
    end
    
    function draw()
        background(0)
        fontSize(fs)
        textWrapWidth(tww)
        w,h=textSize(str)
        text(str,0,0)
        pushStyle()
        textWrapWidth(1000)
        fontSize(17)
        fill(224, 199, 174)
        rect(WIDTH-220,HEIGHT-80,200,50)
        fill(0)
        text("string width   "..w,WIDTH-200,HEIGHT-50)
        text("string height  "..h,WIDTH-200,HEIGHT-80)
        popStyle()
    end
    
  • edited May 31 Posts: 1,089

    fascinating! that's totally not what i thought was happening! well done.

    however, with a screen that's much wider than 1024 pixels i wonder why?

Sign In or Register to comment.