typemytype / drawbot

http://www.drawbot.com
Other
408 stars 63 forks source link

Problems when using language tag in FormattedString #399

Open frankrolf opened 4 years ago

frankrolf commented 4 years ago

I am proofing Cyrillic, including Bulgarian alternates. This example makes two pages, one Russian, the other Bulgarian:

import os
import drawBot as db

def make_proof_page(language_tag):

    proof_text = 'вгджзийклнпттттфцчшщъьюѝ'

    font = 'SourceSerifPro-Light.otf'
    margin = 30
    pt_size = 40

    db.newPage(1200, 120)
    y_offset = db.height() - margin - pt_size
    fs = db.FormattedString(
        proof_text,
        font=font,
        language=language_tag,
        fontSize=pt_size,
    )

    db.text(fs, (margin, y_offset))
    print(fs.size().width)

db.newDrawing()
for language_tag in ['ru', 'bg']:
    make_proof_page(language_tag)

output_name = 'ru vs bgr.pdf'
db.saveImage(output_name)
os.system(f'open "{output_name}"')
db.endDrawing()

Issues I observe:

Test case (with font) attached: Formatted String + language tag.zip

frankrolf commented 4 years ago

I used DrawBot 3.126 (both module and packaged) on macOS 10.15.6.

typemytype commented 4 years ago

mm, Im unsure in CoreText when OT features are applied... I assume while doing the layout, so when a size of string is calculated there are no replacements done yet...

probably this is related @LettError variable arrows issue (cannot find it back directly)

if this is the case DrawBot needs to calculate the size based with laid out strings.

LettError commented 4 years ago

Reference for clipping in variable font text issue: https://github.com/typemytype/drawbot/issues/332

typemytype commented 4 years ago

you can check the typesetted bounds of a formattestring with textBoxCharacterBounds

this should probably by used for textSize() and formattedString.size()

import os
import drawBot as db

def make_proof_page(language_tag):

    proof_text = 'вгджзийклнпттттфцчшщъьюѝ'

    font = 'SourceSerifPro-Light.otf'
    margin = 30
    pt_size = 40

    db.newPage(1200, 120)
    y_offset = db.height() - margin - pt_size
    fs = db.FormattedString(
        proof_text,
        font=font,
        language=language_tag,
        fontSize=pt_size,
    )

    db.text(fs, (margin, y_offset))

    dummyHeight = 5000
    boxes = db.textBoxCharacterBounds(fs, (margin, y_offset, 5000, dummyHeight))
    for box in boxes:
        db.fill(1, 0, 0, .5)
        x, y, w, h = box.bounds
        db.rect(x, y-dummyHeight + fs.fontLineHeight() + fs.fontDescender(), w, h)
    print(fs.size().width)

db.newDrawing()
for language_tag in ['ru', 'bg']:
    make_proof_page(language_tag)

output_name = 'ru vs bgr.pdf'
db.saveImage(output_name)
#os.system(f'open "{output_name}"')
db.endDrawing()
justvanrossum commented 4 years ago

Simplified test:

size(600, 120)

proof_text = 'вгджзийклнпттттфцчшщъьюѝ'

font('../fonts/SourceSerifPro-Regular.otf')
fontSize(39)
text(proof_text, (12, 74))
language("bg")
text(proof_text, (12, 33))

The second line wraps, so the box calculation is not using the correct language setting.

image

justvanrossum commented 4 years ago

FWIW, drawbot-skia now supports language()