[Qt-interest] My first Qt patch
Joshua Grauman
jnfo-c at grauman.com
Wed Feb 10 01:13:25 CET 2010
Hello all,
I had requested a new feature (line spacing options) that I'd really like
to see in Qt a bit ago, and then I thought, "Hey, this is open source, why
don't I just add it myself." So while I've helped find bugs, etc., in the
past this is my first attempt at adding a new feature to Qt and would like
some input. First I'd like to know what is the preferred way of sending in
a patch for Qt? I've included everything here but if there is a better
place to send it, let me know. Otherwise, besides how to try to get the
patch included, other comments are appreciated as well.
I googled and found a recent doc about sending a patch in for Qt Creator,
I'm assuming the same basic rules apply. I read about style, etc., and
think I've done everything the Qt way, as far as I can tell. I'd prefer to
send in a diff, as I'd rather not have to learn git at this point.
It turned out to be a bit bigger and more complex than I was originally
intending. 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.
I tried to be careful not to add extra cycles to the default code path
(single spacing) which is the default.
The interface is via QTextBlockFormat. The following options are
available:
QTextBlockFormat::SingleHeight
QTextBlockFormat::ProportionalHeight
QTextBlockFormat::FixedHeight
QTextBlockFormat::AtLeastHeight
QTextBlockFormat::LineDistanceHeight
They are set via:
void QTextBlockFormat::setLineHeight(qreal height, int heightType)
All the height values are in pixels (except proportional, which is a
percentage). The fixed pixel distances are scaled for use during printing.
and can be read back via:
qreal QTextBlockFormat::lineHeight()
int QTextBlockFormat::lineHeightType()
There is also a function which returns back what the line height will be
based upon the given script line height and scaling (during printing):
qreal QTextBlockFormat::lineHeight(qreal scriptLineHeight, qreal scaling)
I also added support for the standard css property 'line-height' with the
following variants supported:
line-height:150%
line-height:40px
line-height:normal
I also added support for the following two non-standard css properties to
support the AtLeastHeight and LineDistanceHeight options which aren't
supported in standard css. I thought there is probably a better way to
support these though... so I'm open to better syntax here. I've included
them as an easy way to test these features.
line-height:40al
line-height:40ld
The change touches 5 files in src/gui/text.
Here is the diff. I haven't added documentation yet, but can help do that
too. I'm happy to sign off copyright on the patch. It's a diff off of
4.6.1. Input is appreciated. Hopefully this is pretty close as I ended up
putting more time than I was originally thinking of doing as I'd love to
see this get into Qt ;) Thanks. Let me know if explanation/comments for
anything is needed. I've tested it quite a bit and everything looks good
so far, but I could definitely use another set of eyes or two looking over
the patch...
Josh
-------------- next part --------------
--- qcssparser.cpp.org 2010-02-05 22:25:52.380701205 -0800
+++ qcssparser.cpp 2010-02-06 13:19:38.121957202 -0800
@@ -120,6 +120,7 @@ static const QCssKnownValue properties[N
{ "image", QtImage },
{ "image-position", QtImageAlignment },
{ "left", Left },
+ { "line-height", LineHeight },
{ "list-style", ListStyle },
{ "list-style-type", ListStyleType },
{ "margin" , Margin },
--- qcssparser_p.h.org 2010-02-05 22:25:56.500709921 -0800
+++ qcssparser_p.h 2010-02-06 13:19:38.121957202 -0800
@@ -178,6 +178,7 @@ enum Property {
OutlineBottomRightRadius,
FontVariant,
TextTransform,
+ LineHeight,
NumProperties
};
--- qtextdocumentlayout.cpp.org 2010-02-05 22:25:52.401950025 -0800
+++ qtextdocumentlayout.cpp 2010-02-09 16:11:03.700449047 -0800
@@ -2508,6 +2508,23 @@ void QTextDocumentLayoutPrivate::layoutF
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,
QLayoutStruct *layoutStruct, int layoutFrom, int layoutTo, const QTextBlockFormat *previousBlockFormat)
{
@@ -2643,8 +2660,11 @@ void QTextDocumentLayoutPrivate::layoutB
}
- 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);
@@ -2656,8 +2676,9 @@ void QTextDocumentLayoutPrivate::layoutB
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);
@@ -2676,11 +2697,15 @@ void QTextDocumentLayoutPrivate::layoutB
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;
}
--- qtextformat.h.org 2010-02-05 22:25:56.510704501 -0800
+++ qtextformat.h 2010-02-09 16:07:46.550449039 -0800
@@ -164,6 +164,8 @@ public:
TextIndent = 0x1034,
TabPositions = 0x1035,
BlockIndent = 0x1040,
+ LineHeight = 0x1048,
+ LineHeightType = 0x1049,
BlockNonBreakableLines = 0x1050,
BlockTrailingHorizontalRulerWidth = 0x1060,
@@ -529,6 +531,14 @@ inline void QTextCharFormat::setTableCel
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(); }
@@ -566,6 +576,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
@@ -590,6 +608,23 @@ inline void QTextBlockFormat::setAlignme
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:
--- qtexthtmlparser.cpp.org 2010-02-05 22:25:52.401950025 -0800
+++ qtexthtmlparser.cpp 2010-02-07 17:32:51.090449028 -0800
@@ -1256,6 +1256,24 @@ void QTextHtmlParserNode::applyCssDeclar
if (decl.realValue(&indent, "px"))
blockFormat.setTextIndent(indent);
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::QtListIndent:
if (decl.intValue(&cssListIndent))
hasCssListIndent = true;
More information about the Qt-interest-old
mailing list