openfl / lime

A foundational Haxe framework for cross-platform development
https://lime.openfl.org/
MIT License
749 stars 362 forks source link

Ligatures mess up text selection on native targets #1741

Closed player-03 closed 6 months ago

player-03 commented 6 months ago

A ligature is a special glyph that renders two characters as one. It's font-dependent, but given the right font it isn't uncommon in English text.

So we have cases where two characters are rendered as one glyph, causing Lime to miscount the number of characters in the line. When this happens, Lime is still able to display the black highlight box correctly, but it turns the wrong characters gray. Near the end of the line, it attempts to turn a nonexistent character gray, crashing the app.

Here's a quick demo so you can see this for yourself... assuming your default font has ligatures.

class Main extends Sprite {
    public function new() {
        super();

        var textField = new TextField();
        textField.width = stage.stageWidth;
        textField.type = INPUT;

        //The square brackets point out which words have ligatures, but don't do anything else.
        textField.text = "Note the [effects] of selecting the period at the end of this line.\n"
            + "This line is ok unless you delete the space in [f f].\n"
            + "We should also [fix] the highlighting issue that makes the wrong characters appear light.\n"
            + "[ffffffffffff] <- It can get quite bad if there's a lot of ligatures early in the line.";

        addChild(textField);
    }
}

The crash can be fixed in Cairo.showGlyphs() simply by removing null values from the end of the array, but that doesn't fix the highlight offset problem.

Highlighting

tobil4sk commented 6 months ago

Also relevant: https://github.com/openfl/openfl/issues/2602. This lime issue can cause crashes in openfl.

Dimensionscape commented 6 months ago

Sorry! This is somewhat my fault 🤔.

So, a very long while ago, I replaced the text selection compositing to Cairo.ShowGylphs() instead of Cairo.ShowText() in order to improve text behavior quality when highlighted. https://github.com/openfl/openfl/commit/30f99cbb9b61782e907060cb8c15c2c02f043c8d I overlooked that the simple approach omits handling for ligatures, but the fix should be pretty straight forward.

https://github.com/openfl/openfl/blob/332cb95f2531b0a0a8f92e537e8057edc84298a6/src/openfl/display/_internal/CairoTextField.hx#L378C9-L378C9 This line here defines our rectangle for the highlight, but the measurements need to account for ligatures.

In order to prevent a crash, we also need to factor in ligatures here https://github.com/openfl/openfl/blob/332cb95f2531b0a0a8f92e537e8057edc84298a6/src/openfl/display/_internal/CairoTextField.hx#L388

player-03 commented 6 months ago

Also relevant: openfl/openfl#2602. This lime issue can cause crashes in openfl.

You know, maybe it is just an OpenFL issue. I'll head over there.