Improve readability of QTextLine's handling of (negative) right bearing
- Helper functions in LineBreakHelper have been renamed from adjustFoo to calculateFoo, to signal that they do work, and are not adjusting something relative to something else. - The use of QFixed(1) and >= 0 has been replaced with an explicit constant for the case of the bearing not being calculated yet. - A helper function negativeRightBearing() has been added that returns the absolute value of any negative right bearing, making the width computations simpler. - Comments have been added and rewritten to make the logic clearer. Change-Id: I1d3a0214cfa8b4fed4551f3444b43a37d55bd69b Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@theqtcompany.com> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>
This commit is contained in:
parent
d7b847112a
commit
e92c2e119b
@ -1605,8 +1605,8 @@ namespace {
|
|||||||
bool checkFullOtherwiseExtend(QScriptLine &line);
|
bool checkFullOtherwiseExtend(QScriptLine &line);
|
||||||
|
|
||||||
QFixed calculateNewWidth(const QScriptLine &line) const {
|
QFixed calculateNewWidth(const QScriptLine &line) const {
|
||||||
return line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth
|
return line.textWidth + tmpData.textWidth + spaceData.textWidth
|
||||||
- qMin(rightBearing, QFixed());
|
+ softHyphenWidth + negativeRightBearing();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline glyph_t currentGlyph() const
|
inline glyph_t currentGlyph() const
|
||||||
@ -1626,33 +1626,51 @@ namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void adjustRightBearing(glyph_t glyph)
|
inline void calculateRightBearing(glyph_t glyph)
|
||||||
{
|
{
|
||||||
qreal rb;
|
qreal rb;
|
||||||
fontEngine->getGlyphBearings(glyph, 0, &rb);
|
fontEngine->getGlyphBearings(glyph, 0, &rb);
|
||||||
rightBearing = qMin(QFixed(), QFixed::fromReal(rb));
|
|
||||||
|
// We only care about negative right bearings, so we limit the range
|
||||||
|
// of the bearing here so that we can assume it's negative in the rest
|
||||||
|
// of the code, as well ase use QFixed(1) as a sentinel to represent
|
||||||
|
// the state where we have yet to compute the right bearing.
|
||||||
|
rightBearing = qMin(QFixed::fromReal(rb), QFixed(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void adjustRightBearing()
|
inline void calculateRightBearing()
|
||||||
{
|
{
|
||||||
if (currentPosition <= 0)
|
if (currentPosition <= 0)
|
||||||
return;
|
return;
|
||||||
adjustRightBearing(currentGlyph());
|
calculateRightBearing(currentGlyph());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void adjustPreviousRightBearing()
|
inline void calculateRightBearingForPreviousGlyph()
|
||||||
{
|
{
|
||||||
if (previousGlyph > 0)
|
if (previousGlyph > 0)
|
||||||
adjustRightBearing(previousGlyph);
|
calculateRightBearing(previousGlyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const QFixed RightBearingNotCalculated;
|
||||||
|
|
||||||
inline void resetRightBearing()
|
inline void resetRightBearing()
|
||||||
{
|
{
|
||||||
rightBearing = QFixed(1); // Any positive number is defined as invalid since only
|
rightBearing = RightBearingNotCalculated;
|
||||||
// negative right bearings are interesting to us.
|
}
|
||||||
|
|
||||||
|
// We express the negative right bearing as an absolute number
|
||||||
|
// so that it can be applied to the width using addition.
|
||||||
|
inline QFixed negativeRightBearing() const
|
||||||
|
{
|
||||||
|
if (rightBearing == RightBearingNotCalculated)
|
||||||
|
return QFixed(0);
|
||||||
|
|
||||||
|
return qAbs(rightBearing);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const QFixed LineBreakHelper::RightBearingNotCalculated = QFixed(1);
|
||||||
|
|
||||||
inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line)
|
inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line)
|
||||||
{
|
{
|
||||||
LB_DEBUG("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal());
|
LB_DEBUG("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal());
|
||||||
@ -1805,7 +1823,7 @@ void QTextLine::layout_helper(int maxGlyphs)
|
|||||||
current, lbh.logClusters, lbh.glyphs);
|
current, lbh.logClusters, lbh.glyphs);
|
||||||
} else {
|
} else {
|
||||||
lbh.tmpData.length++;
|
lbh.tmpData.length++;
|
||||||
lbh.adjustPreviousRightBearing();
|
lbh.calculateRightBearingForPreviousGlyph();
|
||||||
}
|
}
|
||||||
line += lbh.tmpData;
|
line += lbh.tmpData;
|
||||||
goto found;
|
goto found;
|
||||||
@ -1887,22 +1905,29 @@ void QTextLine::layout_helper(int maxGlyphs)
|
|||||||
lbh.tmpData.textWidth += lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]];
|
lbh.tmpData.textWidth += lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// The actual width of the text needs to take the right bearing into account. The
|
if (sb_or_ws|breakany) {
|
||||||
// right bearing is left-ward, which means that if the rightmost pixel is to the right
|
// To compute the final width of the text we need to take negative right bearing
|
||||||
// of the advance of the glyph, the bearing will be negative. We flip the sign
|
// into account (negative right bearing means the glyph has pixel data past the
|
||||||
// for the code to be more readable. Logic borrowed from qfontmetrics.cpp.
|
// advance length). Note that the negative right bearing is an absolute number,
|
||||||
|
// so that we can apply it to the width using straight forward addition.
|
||||||
|
|
||||||
|
// Store previous right bearing (for the already accepted glyph) in case we
|
||||||
|
// end up breaking due to the current glyph being too wide.
|
||||||
|
QFixed previousRightBearing = lbh.rightBearing;
|
||||||
|
|
||||||
// We ignore the right bearing if the minimum negative bearing is too little to
|
// We ignore the right bearing if the minimum negative bearing is too little to
|
||||||
// expand the text beyond the edge.
|
// expand the text beyond the edge.
|
||||||
if (sb_or_ws|breakany) {
|
|
||||||
QFixed rightBearing = lbh.rightBearing; // store previous right bearing
|
|
||||||
if (lbh.calculateNewWidth(line) - lbh.minimumRightBearing > line.width)
|
if (lbh.calculateNewWidth(line) - lbh.minimumRightBearing > line.width)
|
||||||
lbh.adjustRightBearing();
|
lbh.calculateRightBearing();
|
||||||
|
|
||||||
if (lbh.checkFullOtherwiseExtend(line)) {
|
if (lbh.checkFullOtherwiseExtend(line)) {
|
||||||
// we are too wide, fix right bearing
|
// We are too wide to accept the next glyph with its bearing, so we restore the
|
||||||
if (rightBearing <= 0)
|
// right bearing to that of the previous glyph (the one that was already accepted),
|
||||||
lbh.rightBearing = rightBearing; // take from cache
|
// so that the bearing can be be applied to the final width of the text below.
|
||||||
|
if (previousRightBearing != LineBreakHelper::RightBearingNotCalculated)
|
||||||
|
lbh.rightBearing = previousRightBearing;
|
||||||
else
|
else
|
||||||
lbh.adjustPreviousRightBearing();
|
lbh.calculateRightBearingForPreviousGlyph();
|
||||||
|
|
||||||
if (!breakany) {
|
if (!breakany) {
|
||||||
line.textWidth += lbh.softHyphenWidth;
|
line.textWidth += lbh.softHyphenWidth;
|
||||||
@ -1919,10 +1944,14 @@ void QTextLine::layout_helper(int maxGlyphs)
|
|||||||
LB_DEBUG("reached end of line");
|
LB_DEBUG("reached end of line");
|
||||||
lbh.checkFullOtherwiseExtend(line);
|
lbh.checkFullOtherwiseExtend(line);
|
||||||
found:
|
found:
|
||||||
if (lbh.rightBearing > 0 && !lbh.whiteSpaceOrObject) // If right bearing has not yet been adjusted
|
|
||||||
lbh.adjustRightBearing();
|
|
||||||
line.textAdvance = line.textWidth;
|
line.textAdvance = line.textWidth;
|
||||||
line.textWidth -= qMin(QFixed(), lbh.rightBearing);
|
|
||||||
|
// If right bearing has not been calculated yet, do that now
|
||||||
|
if (lbh.rightBearing == LineBreakHelper::RightBearingNotCalculated && !lbh.whiteSpaceOrObject)
|
||||||
|
lbh.calculateRightBearing();
|
||||||
|
|
||||||
|
// Then apply any negative right bearing
|
||||||
|
line.textWidth += lbh.negativeRightBearing();
|
||||||
|
|
||||||
if (line.length == 0) {
|
if (line.length == 0) {
|
||||||
LB_DEBUG("no break available in line, adding temp: length %d, width %f, space: length %d, width %f",
|
LB_DEBUG("no break available in line, adding temp: length %d, width %f, space: length %d, width %f",
|
||||||
|
Loading…
Reference in New Issue
Block a user