I tried messing around with the letter spacing parameter, trying to find a relationship between geometrical length of the line feature and the required spacing, but I was getting nowhere fast and it seemed like the results were finnicky at best, so I after some messing around I came up with this solution. It requires a plugin and several steps, so some parts of it may benefit from automation, but I think that the final result is exactly what you are looking for.
Starting with our sample lines:
Make sure your line features have a unique identifier attribute, we will need it later.
Download the QChainage plugin and split your lines into a number of segments equal to the number of letters in their label minus one (I am using "ABCEDFG" as my sample label, so I am using 6):
- Buffer the resultant points using Fixed Distance Buffer, using a distance sufficiently large that it captures the curvature of the line, but sufficiently small that they do not overlap:
- Clip the original lines using the generated buffers:
Using Multipart to singleparts to break the resultant multipart features into individual pieces.
Open the Attribute Table of the singlepart line layer you just created and replace the label attribute of each feature with the individual letters of the label from the original line. You can tell the features apart via the unique identifier attribute mentioned in step 0:
(The order of these line features should stay intact because the points used in the buffers used to clip them should have been generated in linear order by QChainage. If some of them are backwards, consider using Reverse Line Direction on the lines that were backwards) and re-doing the steps.
Works at all scales (provided the final lines are large enough to be labelled):