redrawing the font's contours + adding coordinates for manipulating



  • Hello, I'd like to ask for some advice on how to achieve adding coordinates to the letters I'm drawing by reading coordinates of the font's contours (basically what the code below does).

    What I'd like to add is:

    • I’d like to write a function that would take coordinates placed for instance in the left bottom part of the letter. for example something like this
    # for x, y in segment:
    #   if x < glyphWidth/2 && y <glyphHeight/2
    
    • add point with handles in between y0 and glyphHeight/2 and y1 and glyphHeight/2 after that move the y0 and y1 to random position within the left bottom part of the letter
      (as showed on the picture)
      alt text
    newPage(4000,1200)
    fill(255,255,255)
    
    # UI
    Variable([
        dict(name="widthOfTheStroke", ui="Slider",
                args=dict(
                    value=10,
                    minValue=1,
                    maxValue=300)),
        dict(name="ovalSize", ui="Slider",
                args=dict(
                    value=0,
                    minValue=0,
                    maxValue=600)),
        dict(name="closeEach", ui="CheckBox"),
        dict(name="rounded", ui="CheckBox", args=dict(value=True)),
        dict(name="aText", ui="EditText", args=dict(text='P'))
        ], globals())
    
    
    # setting up the font
    letter = BezierPath()
    letter.text(aText, font='source/AkzidenzGrotesk-Regular.otf', fontSize=1200, offset=(100, 100))
    
    fill(0.1)
    stroke(0.1)
    strokeWidth(widthOfTheStroke)
    
    
    
    
    path = BezierPath()
    # function for drawing each letter based on the its coordinates (.otf file)
    # reading coordinates based on the received coordinates of each contour
    for contour in letter.contours:
        
        # move to the position of the starting point of the path
        path.moveTo(contour[0][0])
        
        # loop through each coordinate – they come as an array of either one coordinate (just a point) or three coordinates (point with handlers for curves)
        for segment in contour:
            
            # ––––––––––––––––––––––––––––––––––––––––––– #
            # if the segment is with the handles draw curve
            # ––––––––––––––––––––––––––––––––––––––––––– #
            if len(segment) == 3:
                if rounded == 1:
                    path.curveTo(segment[0], segment[1], segment[2])
                
                if closeEach == 1:
                    path.closePath()
                # decide whether to draw them as curver with three values or just as points
                for x, y in segment:
                    if rounded == 0:
                        path.curveTo((x,y))
                                    
            # ––––––––––––––––––––––––––––––––––––––––––– #
            # if the segment is just a point draw a line to
            # ––––––––––––––––––––––––––––––––––––––––––– #
            if len(segment) == 1:
                for x, y in segment:
                    path.lineTo((x,y))
                    
                    print()
                    
                    # this optional
                    # here im closing path for every new point
                    if closeEach == 1:    
                        path.closePath()
                        
            # in case you want to show each of the coordinate returned from looping through contours                   
            for x, y in segment:
                with savedState():
                    stroke(None)
                    fill(0.3)
                    oval(x-ovalSize/2,y-ovalSize/2, ovalSize,ovalSize)
                    
        print(["contour is closed", "contour is open"][contour.open])
    
    
    
    drawPath(path)
    
    

    Thank you for taking look at this and for any feedback,
    Szymon


  • admin

    he Szymon!

    a bezierPath object is not made to be editable. One way could be jumpt to a glyph object.

    or do a detour by cutting the path in four quarters and draw them seperatly

    # create a bezierPath
    path = BezierPath()
    # add text to the path with a font and fontSize
    path.text("P", font="Helvetica-Bold", fontSize=778)
    # move the page a bit
    translate(100, 100)
    # get the bounds of the path
    minx, miny, maxx, maxy = path.bounds()
    # calculate the width, height of the bounds
    # we only need half the width, height
    w = (maxx-minx) * .5
    h = (maxy-miny) * .5
    # create a bezierPath and add a quarter
    bottomLeft = BezierPath()
    bottomLeft.rect(minx, miny, w, h)
    # create a bezierPath and add a quarter
    bottomRight = BezierPath()
    bottomRight.rect(minx + w, miny, w, h)
    # create a bezierPath and add a quarter
    topLeft = BezierPath()
    topLeft.rect(minx, miny + h, w, h)
    # create a bezierPath and add a quarter
    topRight = BezierPath()
    topRight.rect(minx + w, miny + h, w, h)
    
    # only keep the path when both of the them are filled
    bottomLeft = bottomLeft & path
    bottomRight = bottomRight & path
    topLeft = topLeft & path
    topRight = topRight & path
    # start drawing
    with savedState():
        translate(w, h)
        skew(-30, 0)
        translate(-w, -h)
        fill(1, 0, 0)
        drawPath(bottomLeft)
        fill(1, 1, 0)
        drawPath(bottomRight)
        
    fill(0, 1, 0)
    drawPath(topLeft)
    fill(0, 1, 1)
    drawPath(topRight)
    

    df81aad8-11f9-4fb7-9b12-9f37a3937c21-image.png


Log in to reply