text cursor before first character of a text element or before a special character of text aren't initialized to text element's default

• Jan 15, 2019 - 07:01
Reported version
S2 - Critical

If I put a dynamic text, then double click prior to the first character, the text toolbar calls the font as "Arimo":


However if instead double-click after the second character, it is called "Bitstream vera Sans":


Surely they should be the same font? This seems to be indicative of an underlying bug. And if user does start typing text at either of those positions, the added text will be different font depending on whether the cursor was placed before or after the first special character.

Even after the final character of dynamic text with only special chars, it is still called "Bitstream vera Sans":


Similarly before the notehead of a tempo text, it is called "Arimo":


Although it seems when the next characters are normal text, it properly realizes that subsequent chars are normal unformated "FreeSerif":


Note for single-character dynamics p or f, if you double-click near the end of the character, it will put the cursor after the text and call the font "Bitstream vera Sans":


(I bring that last part up because if I double click at a sweet spot just to the right of the last character of any text - normal text or special formatted text like dynamics - then it places the cursor at the start of the text, with font the same as the font face in inspector...which I think makes sense because it seems double clicking the border of the text elements always puts the cursor at the very start of the text with font the same as the font face. That seems to make sense, but I bring it up incase whoever is reading isn't aware of this slight difference when double-clicking at end of text elements.)


Basically same issue as #279702: Make text in dynamics default to italic and #279703: Using ctrl+a then delete to edit tempo text keeps custom formatting - our handling of the font substitution for the special characters in tempo and dynamics text is not sufficiently transparent. It works but isn't reflected well in the toolbar (my vote is that the toolbar "lie" and just pretend the font hasn't changed) and new characters inserted take the hit for it.

ok. Thanks for clarification.

I'm starting to dig through the code...upon double-clicking before the first p of a pp dynamic and hitting a breakpoint I set in TextBase::startEdit(), I see that the _text of that TextBase element is: open itali, close italic, font face = "ScoreText", and then the unicode for p (0xe520) twice.

Why and when it seems to think that is Arimo...still investigating...

ok, thanks.

At the point in TextBase::startEdit() when it calls TextBlock::formatAt() for either column 0 (before the first p) or column 1 (after the first p), it correclty reports the font as being "ScoreText". Investiating further...

yes marc..."Guessing it's because the actual substituted font isn't available in the usual way (certainly not under the placeholder name "ScoreText") and the drop-down doesn't get initialized correctly." is the conclusion I've come to as well.

I've discovered the the "Arimo" font phenomeon occurs for any text, not just special text such as dynamics, whenever double-clicking at the start of the font. And I've also descovered that this produces a seg-fault during auto-save if auto-save is triggered while cursor is at the start of the text element with this bogus "Arimo" font: https://gist.github.com/ericfont/26add5c0f6af1791719a6d199071fc67. Presumably "Arimo" is chosen as default because it is cloest to the start of the alphabet. I'm noticing that TextTools::updateTools when calls CharFormat* format = cursor->format(); gets a format looking like

        format  @0x555559bb4168 Ms::CharFormat
            _fontFamily ""  QString
            _fontSize   12  qreal
            _preedit    false   bool
            _style  Ms::FontStyle::Normal (0)   Ms::FontStyle
            _valign Ms::VerticalAlignment::AlignNormal (0)  Ms::VerticalAlignment

The _fontFamily being empty string seems problematic...the next line QFont f(format->fontFamily()); results in a QFont varible that has QFontPrivate* scFont equal to NULL, which seems to be a problem for the next line typefaceFamily->setCurrentFont(f); as that NULL font wouldn't be found...

So I think need to do a proper translation from MuseScore's madeup "ScoreText" into the text element's default font, I believe...

maybe if format->fontFamilty() is either empty or "ScoreText", then in either case set the font to the text element's default? I don't know... I'm also wondering if somehow this should be cursor's responsibility to figure out the default font, not TextTools's responsibility.

I'm noticing TextCursor::set has a test

if (oldRow != _row || oldColumn != _column) {

which calls updateCursorFormat()

But that test isn't triggered for the very first time double-click to set cursor before first charcter, because the oldRow was set to 0 because _row and _column are initialized to 0 in TextCursor's constructor.

~~Maybe _row and _column should be initialized to -1? That way this test would be triggered??~~

Edit: no...that was a bad idea...

So the test if (oldRow != _row || oldColumn != _column) { does seem problematic when first set cursor to first element, because updateCursorFormat doesn't set the format family to the default "ScoreText", but rather keeps it as empty string. I'm commenting out that if statement...I'm guessing it is an optimization to avoid doing an updateall...but it does seem problematic...at least I'd think the updateCursorFormat() should be moved out after the if block.

I think I've fixed the problem with dynamics by modifying TextCursor::updateCursorFormat() to be like:

      if (!format || format->fontFamily() == "ScoreText")

That way when cursor is placed before a dynamic, the cursor and Text Toolbar won't be set the problematic "ScoreText" but rather to the text element's default via init().

Title text cursor before first special character of dynamic text registers font as "Arimo" but after as "Bitstream Vera Sans" text cursor before first character of a text element or before a special character of text aren't initialized to text element's default

I'm updating the title to reflect the underlying issue.

Status PR created fixed

Fixed in branch master, commit 560f58f0b8

_fix #281831 text cursor init w/special symbols

Previously, double-clicking text cursor next to a special text such as piano or forte dynamics or the notehead of tempo text would cause MuseScore to set the cursor to use a special font family string claled 'ScoreText'. This caused problems when typing more text because this special ScoreText font doesn't actually exist in the list of fonts, and so musescore would default to an undesired one (on my arch linux computer would be Bitstream Vera Sans) instead of the text element style's default. This is fixed by having TextCursor::updateCursorFormat() initialize the cursor (to use the text element style's default) if the fontFamily was the special 'ScoreText'.

Another problem occured where setting the cursor to be before the initial character would result in the fontFamily string being an empty string (again causing confusion from not being able to find an actual font corresponding to empty string). This was because TextCursor::set() wouldn't call updateCursorFormat() if the cursor was first placed at row and column 0, due to what looks like a problematic attempt at an optimization. Seems like the optimization was to avoid performing updates if the text cursor and row indexes didn't change position...but this optimization failed to consider the case that double-clicking before the first character corresponds to row 0 and column 0, which is the same values as what TextCursor's constructor ititializes row and column to...that resulted in the updateCursorFormat() line not being executed. This problem is fixed by moving updateCursorFormat() line to be after the if (oldRow != row || oldColumn != _column) block, so that it always gets called even when first double-clicking the initial character of a text element.

Fix version