summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoshua Grauman <jnfo@grauman.com>2011-01-04 10:03:32 (GMT)
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2011-01-04 10:03:32 (GMT)
commit254281dae38b932998eb8014a55177948842b78d (patch)
tree21fe7d7a9758754b6233e426dcc0198e825163c4
parent5d68753927ac6ba1445ceb6831da7e2346d91bf9 (diff)
downloadQt-254281dae38b932998eb8014a55177948842b78d.zip
Qt-254281dae38b932998eb8014a55177948842b78d.tar.gz
Qt-254281dae38b932998eb8014a55177948842b78d.tar.bz2
Add line spacing to QTextBlockFormat, get/set functions, CSS support
The patch adds line spacing options to Qt, as in all modern word processors. I primarily checked OpenOffice as a reference for how to position the lines based on the various types of line spacing as well as where to do the page breaks. The following functions were added: void QTextBlockFormat::setLineHeight(qreal height, int heightType) qreal QTextBlockFormat::lineHeight() int QTextBlockFormat::lineHeightType() qreal QTextBlockFormat::lineHeight(qreal scriptLineHeight, qreal scaling) Here are the HeightTypes available: QTextBlockFormat::SingleHeight QTextBlockFormat::ProportionalHeight QTextBlockFormat::FixedHeight QTextBlockFormat::AtLeastHeight QTextBlockFormat::LineDistanceHeight The following CSS syntax was added: line-height:150% line-height:40px line-height:normal line-height:40al line-height:40ld Merge-request: 2305 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
-rw-r--r--src/gui/text/qcssparser.cpp1
-rw-r--r--src/gui/text/qcssparser_p.h1
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp38
-rw-r--r--src/gui/text/qtextformat.cpp67
-rw-r--r--src/gui/text/qtextformat.h35
-rw-r--r--src/gui/text/qtexthtmlparser.cpp18
6 files changed, 154 insertions, 6 deletions
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index dafc8e7..edb08ae 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -122,6 +122,7 @@ static const QCssKnownValue properties[NumProperties - 1] = {
{ "image", QtImage },
{ "image-position", QtImageAlignment },
{ "left", Left },
+ { "line-height", LineHeight },
{ "list-style", ListStyle },
{ "list-style-type", ListStyleType },
{ "margin" , Margin },
diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h
index ca9688e..6bcbdab 100644
--- a/src/gui/text/qcssparser_p.h
+++ b/src/gui/text/qcssparser_p.h
@@ -180,6 +180,7 @@ enum Property {
TextTransform,
QtListNumberPrefix,
QtListNumberSuffix,
+ LineHeight,
NumProperties
};
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index ff14490..5334ae8 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -2506,6 +2506,23 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout
fd->currentLayoutStruct = 0;
}
+static inline void getLineHeightParams(const QTextBlockFormat &blockFormat, const QTextLine &line, qreal scaling,
+ QFixed *lineAdjustment, QFixed *lineBreakHeight, QFixed *lineHeight)
+{
+ *lineHeight = QFixed::fromReal(blockFormat.lineHeight(line.height(), scaling));
+ if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight || blockFormat.lineHeightType() == QTextBlockFormat::AtLeastHeight) {
+ *lineBreakHeight = *lineHeight;
+ if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight)
+ *lineAdjustment = QFixed::fromReal(line.ascent() + qMax(line.leading(), 0.0)) - ((*lineHeight * 4) / 5);
+ else
+ *lineAdjustment = QFixed::fromReal(line.height()) - *lineHeight;
+ }
+ else {
+ *lineBreakHeight = QFixed::fromReal(line.height());
+ *lineAdjustment = 0;
+ }
+}
+
void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosition, const QTextBlockFormat &blockFormat,
QTextLayoutStruct *layoutStruct, int layoutFrom, int layoutTo, const QTextBlockFormat *previousBlockFormat)
{
@@ -2639,8 +2656,12 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
}
- QFixed lineHeight = QFixed::fromReal(line.height());
- if (layoutStruct->pageHeight > 0 && layoutStruct->absoluteY() + lineHeight > layoutStruct->pageBottom) {
+ QFixed lineBreakHeight, lineHeight, lineAdjustment;
+ qreal scaling = (q->paintDevice() && q->paintDevice()->logicalDpiY() != qt_defaultDpi()) ?
+ qreal(q->paintDevice()->logicalDpiY()) / qreal(qt_defaultDpi()) : 1;
+ getLineHeightParams(blockFormat, line, scaling, &lineAdjustment, &lineBreakHeight, &lineHeight);
+
+ if (layoutStruct->pageHeight > 0 && layoutStruct->absoluteY() + lineBreakHeight > layoutStruct->pageBottom) {
layoutStruct->newPage();
floatMargins(layoutStruct->y, layoutStruct, &left, &right);
@@ -2652,7 +2673,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
right -= text_indent;
}
- line.setPosition(QPointF((left - layoutStruct->x_left).toReal(), (layoutStruct->y - cy).toReal()));
+ line.setPosition(QPointF((left - layoutStruct->x_left).toReal(), (layoutStruct->y - cy - lineAdjustment).toReal()));
layoutStruct->y += lineHeight;
layoutStruct->contentsWidth
= qMax<QFixed>(layoutStruct->contentsWidth, QFixed::fromReal(line.x() + line.naturalTextWidth()) + totalRightMargin);
@@ -2672,11 +2693,16 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
QTextLine line = tl->lineAt(i);
layoutStruct->contentsWidth
= qMax(layoutStruct->contentsWidth, QFixed::fromReal(line.x() + tl->lineAt(i).naturalTextWidth()) + totalRightMargin);
- const QFixed lineHeight = QFixed::fromReal(line.height());
+
+ QFixed lineBreakHeight, lineHeight, lineAdjustment;
+ qreal scaling = (q->paintDevice() && q->paintDevice()->logicalDpiY() != qt_defaultDpi()) ?
+ qreal(q->paintDevice()->logicalDpiY()) / qreal(qt_defaultDpi()) : 1;
+ getLineHeightParams(blockFormat, line, scaling, &lineAdjustment, &lineBreakHeight, &lineHeight);
+
if (layoutStruct->pageHeight != QFIXED_MAX) {
- if (layoutStruct->absoluteY() + lineHeight > layoutStruct->pageBottom)
+ if (layoutStruct->absoluteY() + lineBreakHeight > layoutStruct->pageBottom)
layoutStruct->newPage();
- line.setPosition(QPointF(line.position().x(), layoutStruct->y.toReal() - tl->position().y()));
+ line.setPosition(QPointF(line.position().x(), (layoutStruct->y - lineAdjustment).toReal() - tl->position().y()));
}
layoutStruct->y += lineHeight;
}
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 945b012..719db7a 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -541,6 +541,8 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
\value TabPositions Specifies the tab positions. The tab positions are structs of QTextOption::Tab which are stored in
a QList (internally, in a QList<QVariant>).
\value BlockIndent
+ \value LineHeight
+ \value LineHeightType
\value BlockNonBreakableLines
\value BlockTrailingHorizontalRulerWidth The width of a horizontal ruler element.
@@ -1856,6 +1858,10 @@ QFont QTextCharFormat::font() const
indentation is set with setIndent(), the indentation of the first
line with setTextIndent().
+ Line spacing is set with setLineHeight() and retreived via lineHeight()
+ and lineHeightType(). The types of line spacing available are in the
+ LineHeightTypes enum.
+
Line breaking can be enabled and disabled with setNonBreakableLines().
The brush used to paint the paragraph's background
@@ -1872,6 +1878,22 @@ QFont QTextCharFormat::font() const
*/
/*!
+ \since 4.7
+ \enum QTextBlockFormat::LineHeightTypes
+
+ This enum describes the various types of line spacing support paragraphs can have.
+
+ \value SingleHeight This is the default line height: single spacing.
+ \value ProportionalHeight This sets the spacing proportional to the line (in percentage).
+ For example, set to 200 for double spacing.
+ \value FixedHeight This sets the line height to a fixed line height (in pixels).
+ \value AtLeastHeight This sets the minimum line height (in pixels).
+ \value LineDistanceHeight This adds the specified height between lines (in pixels).
+
+ \sa lineHeight(), lineHeightType(), setLineHeight()
+*/
+
+/*!
\fn QTextBlockFormat::QTextBlockFormat()
Constructs a new QTextBlockFormat.
@@ -2089,6 +2111,51 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
/*!
+ \fn void QTextBlockFormat::setLineHeight(qreal height, int heightType)
+ \since 4.7
+
+ This sets the line height for the paragraph to the value in height
+ which is dependant on heightType, described by the LineHeightTypes enum.
+
+ \sa LineHeightTypes, lineHeight(), lineHeightType()
+*/
+
+
+/*!
+ \fn qreal QTextBlockFormat::lineHeight(qreal scriptLineHeight, qreal scaling) const
+ \since 4.7
+
+ This returns what the height of the lines in the paragraph will be depending
+ on the given height of the script line and the scaling. The value that is returned
+ is also dependant on the given LineHeightType of the paragraph as well as the LineHeight
+ setting that has been set for the paragraph. The scaling is needed for the heights
+ that include a fixed number of pixels, to scale them appropriately for printing.
+
+ \sa LineHeightTypes, setLineHeight(), lineHeightType()
+*/
+
+
+/*!
+ \fn qreal QTextBlockFormat::lineHeight() const
+ \since 4.7
+
+ This returns the LineHeight property for the paragraph.
+
+ \sa LineHeightTypes, setLineHeight(), lineHeightType()
+*/
+
+
+/*!
+ \fn qreal QTextBlockFormat::lineHeightType() const
+ \since 4.7
+
+ This returns the LineHeightType property of the paragraph.
+
+ \sa LineHeightTypes, setLineHeight(), lineHeight()
+*/
+
+
+/*!
\fn void QTextBlockFormat::setNonBreakableLines(bool b)
If \a b is true, the lines in the paragraph are treated as
diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
index bb6e71d..41cc1d9 100644
--- a/src/gui/text/qtextformat.h
+++ b/src/gui/text/qtextformat.h
@@ -164,6 +164,8 @@ public:
TextIndent = 0x1034,
TabPositions = 0x1035,
BlockIndent = 0x1040,
+ LineHeight = 0x1048,
+ LineHeightType = 0x1049,
BlockNonBreakableLines = 0x1050,
BlockTrailingHorizontalRulerWidth = 0x1060,
@@ -531,6 +533,14 @@ inline void QTextCharFormat::setTableCellColumnSpan(int _tableCellColumnSpan)
class Q_GUI_EXPORT QTextBlockFormat : public QTextFormat
{
public:
+ enum LineHeightTypes {
+ SingleHeight = 0,
+ ProportionalHeight = 1,
+ FixedHeight = 2,
+ AtLeastHeight = 3,
+ LineDistanceHeight = 4
+ };
+
QTextBlockFormat();
bool isValid() const { return isBlockFormat(); }
@@ -568,6 +578,14 @@ public:
inline int indent() const
{ return intProperty(BlockIndent); }
+ inline void setLineHeight(qreal height, int heightType)
+ { setProperty(LineHeight, height); setProperty(LineHeightType, heightType); }
+ inline qreal lineHeight(qreal scriptLineHeight, qreal scaling) const;
+ inline qreal lineHeight() const
+ { return doubleProperty(LineHeight); }
+ inline int lineHeightType() const
+ { return intProperty(LineHeightType); }
+
inline void setNonBreakableLines(bool b)
{ setProperty(BlockNonBreakableLines, b); }
inline bool nonBreakableLines() const
@@ -592,6 +610,23 @@ inline void QTextBlockFormat::setAlignment(Qt::Alignment aalignment)
inline void QTextBlockFormat::setIndent(int aindent)
{ setProperty(BlockIndent, aindent); }
+inline qreal QTextBlockFormat::lineHeight(qreal scriptLineHeight, qreal scaling = 1.0) const
+{
+ switch(intProperty(LineHeightType)) {
+ case SingleHeight:
+ return(scriptLineHeight);
+ case ProportionalHeight:
+ return(scriptLineHeight * doubleProperty(LineHeight) / 100.0);
+ case FixedHeight:
+ return(doubleProperty(LineHeight) * scaling);
+ case AtLeastHeight:
+ return(qMax(scriptLineHeight, doubleProperty(LineHeight) * scaling));
+ case LineDistanceHeight:
+ return(scriptLineHeight + doubleProperty(LineHeight) * scaling);
+ }
+ return(0);
+}
+
class Q_GUI_EXPORT QTextListFormat : public QTextFormat
{
public:
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index 5b9ab90..769a509 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -1250,6 +1250,24 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration>
case QCss::QtBlockIndent:
blockFormat.setIndent(decl.d->values.first().variant.toInt());
break;
+ case QCss::LineHeight: {
+ qreal lineHeight;
+ if (decl.realValue(&lineHeight, "px"))
+ blockFormat.setLineHeight(lineHeight, QTextBlockFormat::FixedHeight);
+ else if (decl.realValue(&lineHeight, "al"))
+ blockFormat.setLineHeight(lineHeight, QTextBlockFormat::AtLeastHeight);
+ else if (decl.realValue(&lineHeight, "ld"))
+ blockFormat.setLineHeight(lineHeight, QTextBlockFormat::LineDistanceHeight);
+ else {
+ bool ok;
+ QString value = decl.d->values.first().toString();
+ lineHeight = value.toDouble(&ok);
+ if (ok)
+ blockFormat.setLineHeight(lineHeight, QTextBlockFormat::ProportionalHeight);
+ else
+ blockFormat.setLineHeight(0, QTextBlockFormat::SingleHeight);
+ }
+ break; }
case QCss::TextIndent: {
qreal indent = 0;
if (decl.realValue(&indent, "px"))