Allow arbitrary baseline shift in QTextCharacterFormat

Added 6 new methods in QTextFormat and QTextDocument to
allow setting/getting specific % positioning for baseline and super/
subscript. Modified QTextLayout to honor those new settings.

[ChangeLog][QtGui][QTextLayout,QTextFormat,QTextDocument] Allow text
layout modification based on baseline offset and super/subscript % height
positioning

Fixes: QTBUG-18260
Change-Id: I0796f18224aac8df6baf8359c35022fd98fe64ef
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
This commit is contained in:
Jordi Pujol Foyo 2020-05-08 15:23:21 +02:00
parent cba2d04434
commit 560117351c
6 changed files with 194 additions and 5 deletions

View File

@ -1732,6 +1732,93 @@ QFont QTextDocument::defaultFont() const
return d->defaultFont();
}
/*!
\fn void QTextDocument::setSuperScriptBaseline(qreal baseline)
\since 6.0
Sets the default superscript's base line as a % of font height to use in the document layout.
The default value is 50% (1/2 of height)
\sa superScriptBaseline(), setSubScriptBaseline(), subScriptBaseline(), setBaselineOffset(), baselineOffset()
*/
void QTextDocument::setSuperScriptBaseline(qreal baseline)
{
Q_D(QTextDocument);
d->formats.setSuperScriptBaseline(baseline);
}
/*!
\fn qreal QTextDocument::superScriptBaseline() const
\since 6.0
Returns the superscript's base line as a % of font height used in the document layout.
\sa setSuperScriptBaseline(), setSubScriptBaseline(), subScriptBaseline(), setBaselineOffset(), baselineOffset()
*/
qreal QTextDocument::superScriptBaseline() const
{
Q_D(const QTextDocument);
return d->formats.defaultTextFormat().superScriptBaseline();
}
/*!
\fn void QTextDocument::setSubScriptBaseline(qreal baseline)
\since 6.0
Sets the default subscript's base line as a % of font height to use in the document layout.
The default value is 16.67% (1/6 of height)
\sa subScriptBaseline(), setSuperScriptBaseline(), superScriptBaseline(), setBaselineOffset(), baselineOffset()
*/
void QTextDocument::setSubScriptBaseline(qreal baseline)
{
Q_D(QTextDocument);
d->formats.setSubScriptBaseline(baseline);
}
/*!
\fn qreal QTextDocument::subScriptBaseline() const
\since 6.0
Returns the superscript's base line as a % of font height used in the document layout.
\sa setSubScriptBaseline(), setSuperScriptBaseline(), superScriptBaseline(), setBaselineOffset(), baselineOffset()
*/
qreal QTextDocument::subScriptBaseline() const
{
Q_D(const QTextDocument);
return d->formats.defaultTextFormat().subScriptBaseline();
}
/*!
\fn void QTextDocument::setBaselineOffset(qreal baseline)
\since 6.0
Sets the baseline (in % of height) to use in the document layout. The default value is 0.
A positive value moves up the text, by the corresponding %; a negative value moves it down.
\sa baselineOffset(), setSubScriptBaseline(), subScriptBaseline(), setSuperScriptBaseline(), superScriptBaseline()
*/
void QTextDocument::setBaselineOffset(qreal baseline)
{
Q_D(QTextDocument);
d->formats.setBaselineOffset(baseline);
}
/*!
\fn qreal QTextDocument::baselineOffset() const
\since 6.0
Returns the the baseline offset in % used in the document layout.
\sa setBaselineOffset(), setSubScriptBaseline(), subScriptBaseline(), setSuperScriptBaseline(), superScriptBaseline()
*/
qreal QTextDocument::baselineOffset() const
{
Q_D(const QTextDocument);
return d->formats.defaultTextFormat().baselineOffset();
}
/*!
\fn void QTextDocument::modificationChanged(bool changed)

View File

@ -208,6 +208,15 @@ public:
void setDefaultFont(const QFont &font);
QFont defaultFont() const;
void setSuperScriptBaseline(qreal baseline);
qreal superScriptBaseline() const;
void setSubScriptBaseline(qreal baseline);
qreal subScriptBaseline() const;
void setBaselineOffset(qreal baseline);
qreal baselineOffset() const;
int pageCount() const;
bool isModified() const;

View File

@ -635,6 +635,10 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
\value TextOutline
\value TextUnderlineStyle
\value TextToolTip Specifies the (optional) tool tip to be displayed for a fragment of text.
\value TextSuperScriptBaseline Specifies the baseline (in % of height) of superscript texts.
\value TextSubScriptBaseline Specifies the baseline (in % of height) of subscript texts.
\value TextBaselineOffset Specifies the baseline (in % of height) of text. A positive value moves up the text,
by the corresponding %; a negative value moves it down.
\value IsAnchor
\value AnchorHref
@ -1795,6 +1799,60 @@ void QTextCharFormat::setUnderlineStyle(UnderlineStyle style)
\sa foreground(), setForeground(), clearBackground()
*/
/*!
\fn void QTextCharFormat::setSuperScriptBaseline(qreal baseline)
\since 6.0
Sets the superscript's base line as a % of font height. The default value is 50% (1/2 of height)
\sa superScriptBaseline(), setSubScriptBaseline(), subScriptBaseline(), setBaselineOffset(), baselineOffset()
*/
/*!
\fn qreal QTextCharFormat::superScriptBaseline() const
\since 6.0
Returns the superscript's base line as a % of font height.
\sa setSuperScriptBaseline(), setSubScriptBaseline(), subScriptBaseline(), setBaselineOffset(), baselineOffset()
*/
/*!
\fn void QTextCharFormat::setSubScriptBaseline(qreal baseline)
\since 6.0
Sets the subscript's base line as a % of font height. The default value is 16.67% (1/6 of height)
\sa subScriptBaseline(), setSuperScriptBaseline(), superScriptBaseline(), setBaselineOffset(), baselineOffset()
*/
/*!
\fn qreal QTextCharFormat::subScriptBaseline() const
\since 6.0
Returns the subscript's base line as a % of font height.
\sa setSubScriptBaseline(), setSuperScriptBaseline(), superScriptBaseline(), setBaselineOffset(), baselineOffset()
*/
/*!
\fn void QTextCharFormat::setBaselineOffset(qreal baseline)
\since 6.0
Sets the baseline (in % of height) of text. A positive value moves up the text, by the corresponding %;
a negative value moves it down. The default value is 0.
\sa baselineOffset(), setSubScriptBaseline(), subScriptBaseline(), setSuperScriptBaseline(), superScriptBaseline()
*/
/*!
\fn qreal QTextCharFormat::baselineOffset() const
\since 6.0
Returns the the baseline offset in %.
\sa setBaselineOffset(), setSubScriptBaseline(), subScriptBaseline(), setSuperScriptBaseline(), superScriptBaseline()
*/
/*!
\fn void QTextCharFormat::setAnchor(bool anchor)

View File

@ -213,6 +213,9 @@ public:
TextOutline = 0x2022,
TextUnderlineStyle = 0x2023,
TextToolTip = 0x2024,
TextSuperScriptBaseline = 0x2025,
TextSubScriptBaseline = 0x2026,
TextBaselineOffset = 0x2027,
IsAnchor = 0x2030,
AnchorHref = 0x2031,
@ -570,6 +573,21 @@ public:
inline QString toolTip() const
{ return stringProperty(TextToolTip); }
inline void setSuperScriptBaseline(qreal baseline)
{ setProperty(TextSuperScriptBaseline, baseline); }
inline qreal superScriptBaseline() const
{ return hasProperty(TextSuperScriptBaseline) ? doubleProperty(TextSuperScriptBaseline) : 50.0; }
inline void setSubScriptBaseline(qreal baseline)
{ setProperty(TextSubScriptBaseline, baseline); }
inline qreal subScriptBaseline() const
{ return hasProperty(TextSubScriptBaseline) ? doubleProperty(TextSubScriptBaseline) : 100.0 / 6.0; }
inline void setBaselineOffset(qreal baseline)
{ setProperty(TextBaselineOffset, baseline); }
inline qreal baselineOffset() const
{ return hasProperty(TextBaselineOffset) ? doubleProperty(TextBaselineOffset) : 0.0; }
inline void setAnchor(bool anchor)
{ setProperty(IsAnchor, anchor); }
inline bool isAnchor() const

View File

@ -101,8 +101,15 @@ public:
inline QFont defaultFont() const { return defaultFnt; }
void setDefaultFont(const QFont &f);
inline void setSuperScriptBaseline(qreal baseline) { defaultFormat.setSuperScriptBaseline(baseline); }
inline void setSubScriptBaseline(qreal baseline) { defaultFormat.setSubScriptBaseline(baseline); }
inline void setBaselineOffset(qreal baseline) { defaultFormat.setBaselineOffset(baseline); }
inline QTextCharFormat defaultTextFormat() const { return defaultFormat; }
private:
QFont defaultFnt;
QTextCharFormat defaultFormat;
Q_DISABLE_COPY_MOVE(QTextFormatCollection)
};

View File

@ -2511,6 +2511,8 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
const QFixed y = QFixed::fromReal(pos.y()) + line.y + lineBase;
const QTextFormatCollection *formatCollection = eng->formatCollection();
bool suppressColors = (eng->option.flags() & QTextOption::SuppressColors);
while (!iterator.atEnd()) {
QScriptItem &si = iterator.next();
@ -2525,10 +2527,12 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
QFixed itemBaseLine = y;
QFont f = eng->font(si);
QTextCharFormat format;
if (formatCollection != nullptr)
format = formatCollection->defaultTextFormat();
if (eng->hasFormats() || selection || formatCollection) {
format.merge(eng->format(&si));
if (eng->hasFormats() || selection) {
format = eng->format(&si);
if (suppressColors) {
format.clearForeground();
format.clearBackground();
@ -2540,14 +2544,20 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
setPenAndDrawBackground(p, pen, format, QRectF(iterator.x.toReal(), (y - lineBase).toReal(),
iterator.itemWidth.toReal(), line.height().toReal()));
const qreal baseLineOffset = format.baselineOffset() / 100.0;
QTextCharFormat::VerticalAlignment valign = format.verticalAlignment();
if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) {
if (valign == QTextCharFormat::AlignSuperScript
|| valign == QTextCharFormat::AlignSubScript
|| !qFuzzyIsNull(baseLineOffset))
{
QFontEngine *fe = f.d->engineForScript(si.analysis.script);
QFixed height = fe->ascent() + fe->descent();
itemBaseLine -= height * QFixed::fromReal(baseLineOffset);
if (valign == QTextCharFormat::AlignSubScript)
itemBaseLine += height / 6;
itemBaseLine += height * QFixed::fromReal(format.subScriptBaseline() / 100.0);
else if (valign == QTextCharFormat::AlignSuperScript)
itemBaseLine -= height / 2;
itemBaseLine -= height * QFixed::fromReal(format.superScriptBaseline() / 100.0);
}
}