Correct use of QFontMetrics.leftBearing for drawing Hindi characters using QRawFont
-
@SGaist Hello
I tried something else.
In the same example, instead of trying to paint individual characters, i tried painting the complete text and lo.., i got perfect result.
Which means the Qt font engine has all the text shaper rules to draw the text properly.basepath.addText(x,y,font(),text); painter.drawPath(basepath);
OR
painter.drawText(x,y,text);
Both give perfect result as seen here.
This will work for all straight line text applications.. However, my application is simillar to the wiggly example where i need align the text along a curve. In that case, i am unable to understand how to get the glyphs of individual characters so that i can align them along a path.
-
Then that might be a font specific issue.
Can you try with a different one that provides the char set you need ? -
@SGaist
No. It does not seem to be a font specific issue. I have tried this will all the indic fonts i have and still have same results.I feel, this is a lot to do with the kerning of fonts. Since the results are proper with Path.addText and painter.drawText, i think Qt has the necessary tools to make this happen.
Now, because I am interested in aligning text on a path just the way it is seen in Inkscape.. as seen here,
In order to do this, I have 2 options.
Option 1: use the QFontMetrics and other classes available in Qt that give the right distances to combine 2 characters. Along with that get the combined character glyph paths which can be worked upon to align characters on the path.Option 2: I can get the combined paths using painterpath.addtext. I need to find out the right way to get the individual glyphs to align them on the path.
Option 3: any other method that i dont know....
Is this possible in Qt?
-
Good question. I recommend that you bring it to the interest mailing where you will find Qt's developers/maintainers.
You might also want to check the bug report system. There are likely related tickets.
-
QRawFont only does basic kerning, it doesn't do HarfBuzz shaping, so you can't really use QRawFont for any complex scripts (It assumes a 1 letter to 1 glyph mapping).
-
@Allan-Jensen Thanks for this response.
Yes, I am getting that. However, unable to understand what function will give the resultant metrics and even more important the combined glyph indexes after the shaping result.
-
@Allan-Jensen @SGaist I have managed to get a few things done... now just a small thing remains.
As mentioned in my earlier post, I got a solution to the Option2: Get individual glyph paths for the combined paths in the Hindi fonts. SO now that i have the individual glyph paths, i can align them as I want.
This is how I could achieve this result. Here is the changed paintEvent.void WigglyWidget::paintEvent(QPaintEvent * /* event */) //! [1] //! [2] { QRawFont *myFont = new QRawFont; *myFont = QRawFont::fromFont(font()); QFontMetrics metrics(font()); int x = (width() - metrics.horizontalAdvance(text)) / 2; int y = (height() + metrics.ascent() - metrics.descent()) / 2; QColor color; //! [2] //! [3] QPainter painter(this); QPainterPath basepath; QTextLayout curlay(text,font()); curlay.beginLayout(); curlay.createLine(); curlay.endLayout(); QList<QGlyphRun> curglyrunlist = curlay.glyphRuns(); QGlyphRun curglyrun = curglyrunlist[0]; QList<quint32> chindices = curglyrun.glyphIndexes(); *myFont =curglyrun.rawFont(); QList<QPointF> curglyadvlist = myFont->advancesForGlyphIndexes(chindices,QRawFont::KernedAdvances); // qreal prevx; for (int i = 0; i < chindices.count(); ++i) { color.setRgb(255,0,0); painter.setPen(color); QPainterPath charpath = myFont->pathForGlyph(chindices[i]); // get the glyph path for character. qreal widt = curglyadvlist[i].x(); // if(widt==0) // charpath = charpath.translated(prevx,y); // else charpath = charpath.translated(x,y); basepath.addPath(charpath); // basepath.addEllipse(x,y,5,5); // qDebug()<<widt<<x<<y; // prevx = x; x += (widt); } painter.drawPath(basepath); painter.drawText((width() - metrics.horizontalAdvance(text)) / 2,y-50,text); }
And this is the result.
Here you can see that the one drawn below is as per the painter.drawPath which is the result of individual glyphs drawn as painterpaths.
While the top one is drawn with painter.drawText.
Now the problem remains that the bottom addition to the main character is not drawn at the right location. The advancesForGlyphIndexes function is not returning the right advance for this character. Whereas when the painter.drawText is drawing it perfectly well.Now, am I missing something... some leftBearing or RightBearing that needs to be added or subtracted from the characters... ?
-
@Allan-Jensen @SGaist I have finally solved it.
I substituted myFont->advancesForGlyphIndexes(chindices,QRawFont::KernedAdvances); with curglyrun.positions(); and that gave me the right positions for all glyphs.
-
Great !
Thanks for sharing your solution :-)