Scale text to fit rectangle?



  • I am trying to render text (in various languages) within a fixed size rectangle using drawbot. Following the code in this issue: https://github.com/typemytype/drawbot/issues/218, I am able to draw a rectangle around the rendered text (this is the smaller rectangle in the attached image).

    Is there anyway to do this the other way around; given a rectangle (the larger one in the image), fit the text in it? With largest possible width or height, whichever comes first?

    drawbot_KWËTI.png



  • One way of doing this is increasing the font size until it no longer fits the rectangle.

    # Based on the examples on https://www.drawbot.com/content/text/drawingText.html
    
    fs = 1
    txt = "hello"
    box = (100, 300, 800, 400)
    
    fontSize(fs)
    # Increasing the fontsize fs until the text no longer fits.
    # textOverflow returns the overflowed text without drawing the text.
    while textOverflow("hello", box) == "":
        fs += 1
        fontSize(fs)
    
    # The fontsize adds up until the text no longer fits. To make the text fit, fs must be 1 smaller.
    fontSize(fs-1)
    # Draw a red box in the background
    fill(1, 0, 0)
    rect(*box)
    # Draw white text over the box
    fill(1)
    textBox(txt, box, align="center")
    

  • admin

    scale the canvas based on the dimension of your destination rectangle:

    # set a width height
    w, h = 396, 244
    # create a formattedString
    txt = FormattedString()
    # set a font
    txt.font("Times")
    # add some text
    txt += "kweti"
    
    #move it a bit
    translate(100, 100)
    # draw the black stroked rect
    fill(None)
    stroke(0)
    rect(0, 0, w, h)
    
    # create a path object
    path = BezierPath()
    # draw text into the path
    path.text(txt)
    # get the bounds of the path
    minx, miny, maxx, maxy = path.bounds()
    # get a scale value based on the bounding box
    scaleX = w / (maxx - minx)
    scaleY = h / (maxy - miny)
    # pick the smallest one and shift up to the middle in the other direction
    if scaleX < scaleY:
        scale(scaleX)
        shift = (h / scaleX - (maxy - miny)) / 2
        translate(0, shift)
    else:
        scale(scaleY)
        shift = (w / scaleY - (maxx - minx)) / 2
        translate(shift, 0)
    # translate witht the offset
    translate(-minx, -miny)
    # draw as text
    text(txt, (0, 0))
    

Log in to reply