diff options
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 9 | ||||
-rw-r--r-- | src/gui/painting/qpaintengineex.cpp | 44 | ||||
-rw-r--r-- | src/gui/text/qfont.cpp | 12 | ||||
-rw-r--r-- | src/gui/text/qfontdatabase.cpp | 18 | ||||
-rw-r--r-- | src/gui/text/qtextdocument.cpp | 29 | ||||
-rw-r--r-- | src/gui/text/qtextdocument_p.h | 1 | ||||
-rw-r--r-- | src/gui/text/qtextdocumentwriter.cpp | 6 | ||||
-rw-r--r-- | src/gui/text/qtextengine.cpp | 16 |
8 files changed, 106 insertions, 29 deletions
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index a3e199cec9..71881bbc45 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -2414,15 +2414,20 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe QRectF targetBounds = s->matrix.mapRect(r); bool exceedsPrecision = r.width() > 0x7fff || r.height() > 0x7fff + || targetBounds.left() < -0x7fff + || targetBounds.top() < -0x7fff + || targetBounds.right() > 0x7fff + || targetBounds.bottom() > 0x7fff || targetBounds.width() > 0x7fff || targetBounds.height() > 0x7fff || s->matrix.m11() >= 512 || s->matrix.m22() >= 512; - if (!exceedsPrecision && d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { if (s->matrix.type() > QTransform::TxScale) { SrcOverTransformFunc func = qTransformFunctions[d->rasterBuffer->format][img.format()]; - if (func && (!clip || clip->hasRectClip)) { + // The fast transform methods doesn't really work on small targets, see QTBUG-93475 + // And it can't antialias the edges + if (func && (!clip || clip->hasRectClip) && !s->flags.antialiased && targetBounds.width() >= 16 && targetBounds.height() >= 16) { func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(), img.bits(), img.bytesPerLine(), r, sr, !clip ? d->deviceRect : clip->clipRect, s->matrix, s->intOpacity); diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 5d8f89eadd..5a6a2d84e9 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -385,7 +385,7 @@ QPainterState *QPaintEngineEx::createState(QPainterState *orig) const Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp -void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) +void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &inPen) { #ifdef QT_DEBUG_DRAW qDebug() << "QPaintEngineEx::stroke()" << pen; @@ -403,6 +403,38 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) d->stroker.setCubicToHook(qpaintengineex_cubicTo); } + QRectF clipRect; + QPen pen = inPen; + if (pen.style() > Qt::SolidLine) { + QRectF cpRect = path.controlPointRect(); + const QTransform &xf = state()->matrix; + if (qt_pen_is_cosmetic(pen, state()->renderHints)) { + clipRect = d->exDeviceRect; + cpRect.translate(xf.dx(), xf.dy()); + } else { + clipRect = xf.inverted().mapRect(QRectF(d->exDeviceRect)); + } + // Check to avoid generating unwieldy amount of dashes that will not be visible anyway + QRectF extentRect = cpRect & clipRect; + qreal extent = qMax(extentRect.width(), extentRect.height()); + qreal patternLength = 0; + const QVector<qreal> pattern = pen.dashPattern(); + const int patternSize = qMin(pattern.size(), 32); + for (int i = 0; i < patternSize; i++) + patternLength += qMax(pattern.at(i), qreal(0)); + if (pen.widthF()) + patternLength *= pen.widthF(); + if (qFuzzyIsNull(patternLength)) { + pen.setStyle(Qt::NoPen); + } else if (extent / patternLength > 10000) { + // approximate stream of tiny dashes with semi-transparent solid line + pen.setStyle(Qt::SolidLine); + QColor color(pen.color()); + color.setAlpha(color.alpha() / 2); + pen.setColor(color); + } + } + if (!qpen_fast_equals(pen, d->strokerPen)) { d->strokerPen = pen; d->stroker.setJoinStyle(pen.joinStyle()); @@ -430,14 +462,8 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) return; } - if (pen.style() > Qt::SolidLine) { - if (qt_pen_is_cosmetic(pen, state()->renderHints)){ - d->activeStroker->setClipRect(d->exDeviceRect); - } else { - QRectF clipRect = state()->matrix.inverted().mapRect(QRectF(d->exDeviceRect)); - d->activeStroker->setClipRect(clipRect); - } - } + if (!clipRect.isNull()) + d->activeStroker->setClipRect(clipRect); if (d->activeStroker == &d->stroker) d->stroker.setForceOpen(path.hasExplicitOpen()); diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 5a1fa36e5c..3d044edd5a 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -220,8 +220,10 @@ QFontPrivate::~QFontPrivate() if (engineData && !engineData->ref.deref()) delete engineData; engineData = nullptr; - if (scFont && scFont != this) - scFont->ref.deref(); + if (scFont && scFont != this) { + if (!scFont->ref.deref()) + delete scFont; + } scFont = nullptr; } @@ -630,8 +632,10 @@ void QFont::detach() if (d->engineData && !d->engineData->ref.deref()) delete d->engineData; d->engineData = nullptr; - if (d->scFont && d->scFont != d.data()) - d->scFont->ref.deref(); + if (d->scFont && d->scFont != d.data()) { + if (!d->scFont->ref.deref()) + delete d->scFont; + } d->scFont = nullptr; return; } diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 72dcac6904..bdbfcd7af4 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -1731,13 +1731,19 @@ bool QFontDatabase::isSmoothlyScalable(const QString &family, const QString &sty for (int j = 0; j < f->count; j++) { QtFontFoundry *foundry = f->foundries[j]; if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { - for (int k = 0; k < foundry->count; k++) - if ((style.isEmpty() || - foundry->styles[k]->styleName == style || - foundry->styles[k]->key == styleKey) && foundry->styles[k]->smoothScalable) { - smoothScalable = true; + for (int k = 0; k < foundry->count; k++) { + QtFontStyle *fontStyle = foundry->styles[k]; + smoothScalable = + fontStyle->smoothScalable + && ((style.isEmpty() + || fontStyle->styleName == style + || fontStyle->key == styleKey) + || (fontStyle->styleName.isEmpty() + && style == styleStringHelper(fontStyle->key.weight, + QFont::Style(fontStyle->key.style)))); + if (smoothScalable) goto end; - } + } } } end: diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 7ee9898537..bb4390bca0 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -3032,10 +3032,12 @@ void QTextHtmlExporter::emitBlock(const QTextBlock &block) if (fragmentMarkers && block.position() + block.length() == doc->docHandle()->length()) html += QLatin1String("<!--EndFragment-->"); + QString closeTags; + if (pre) html += QLatin1String("</pre>"); else if (list) - html += QLatin1String("</li>"); + closeTags += QLatin1String("</li>"); else { int headingLevel = blockFormat.headingLevel(); if (headingLevel > 0 && headingLevel <= 6) @@ -3047,9 +3049,30 @@ void QTextHtmlExporter::emitBlock(const QTextBlock &block) if (list) { if (list->itemNumber(block) == list->count() - 1) { // last item? close list if (isOrderedList(list->format().style())) - html += QLatin1String("</ol>"); + closeTags += QLatin1String("</ol>"); else - html += QLatin1String("</ul>"); + closeTags += QLatin1String("</ul>"); + } + const QTextBlock nextBlock = block.next(); + // If the next block is the beginning of a new deeper nested list, then we don't + // want to close the current list item just yet. This should be closed when this + // item is fully finished + if (nextBlock.isValid() && nextBlock.textList() && + nextBlock.textList()->itemNumber(nextBlock) == 0 && + nextBlock.textList()->format().indent() > list->format().indent()) { + QString lastTag; + if (!closingTags.isEmpty() && list->itemNumber(block) == list->count() - 1) + lastTag = closingTags.takeLast(); + lastTag.prepend(closeTags); + closingTags << lastTag; + } else if (list->itemNumber(block) == list->count() - 1) { + // If we are at the end of the list now then we can add in the closing tags for that + // current block + html += closeTags; + if (!closingTags.isEmpty()) + html += closingTags.takeLast(); + } else { + html += closeTags; } } diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h index 7f85d27ba0..9908f14ba3 100644 --- a/src/gui/text/qtextdocument_p.h +++ b/src/gui/text/qtextdocument_p.h @@ -405,6 +405,7 @@ private: QTextCharFormat defaultCharFormat; const QTextDocument *doc; bool fragmentMarkers; + QStringList closingTags; }; QT_END_NAMESPACE diff --git a/src/gui/text/qtextdocumentwriter.cpp b/src/gui/text/qtextdocumentwriter.cpp index 0bafa5d9ff..312396fb29 100644 --- a/src/gui/text/qtextdocumentwriter.cpp +++ b/src/gui/text/qtextdocumentwriter.cpp @@ -249,9 +249,11 @@ QString QTextDocumentWriter::fileName () const */ bool QTextDocumentWriter::write(const QTextDocument *document) { - QByteArray suffix; + if (!d->device) + return false; - if (d->device && d->format.isEmpty()) { + QByteArray suffix; + if (d->format.isEmpty()) { // if there's no format, see if device is a file, and if so, find // the file suffix if (QFile *file = qobject_cast<QFile *>(d->device)) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 8af64f9cf8..3edd8b4cc5 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -258,7 +258,7 @@ struct QBidiAlgorithm { for (int i = 0; i < length; ++i) { int pos = i; uint uc = text[i].unicode(); - if (QChar::isHighSurrogate(uc) && i < length - 1) { + if (QChar::isHighSurrogate(uc) && i < length - 1 && text[i + 1].isLowSurrogate()) { ++i; analysis[i].bidiDirection = QChar::DirNSM; uc = QChar::surrogateToUcs4(ushort(uc), text[i].unicode()); @@ -2173,20 +2173,30 @@ void QTextEngine::itemize() const QTextDocumentPrivate::FragmentIterator end = p->find(block.position() + block.length() - 1); // -1 to omit the block separator char int format = it.value()->format; + int preeditPosition = s ? s->preeditPosition : INT_MAX; int prevPosition = 0; int position = prevPosition; while (1) { const QTextFragmentData * const frag = it.value(); if (it == end || format != frag->format) { - if (s && position >= s->preeditPosition) { + if (s && position >= preeditPosition) { position += s->preeditText.length(); - s = nullptr; + preeditPosition = INT_MAX; } Q_ASSERT(position <= length); QFont::Capitalization capitalization = formatCollection()->charFormat(format).hasProperty(QTextFormat::FontCapitalization) ? formatCollection()->charFormat(format).fontCapitalization() : formatCollection()->defaultFont().capitalization(); + if (s) { + for (const auto &range : qAsConst(s->formats)) { + if (range.start >= prevPosition && range.start < position && range.format.hasProperty(QTextFormat::FontCapitalization)) { + itemizer.generate(prevPosition, range.start - prevPosition, capitalization); + itemizer.generate(range.start, range.length, range.format.fontCapitalization()); + prevPosition = range.start + range.length; + } + } + } itemizer.generate(prevPosition, position - prevPosition, capitalization); if (it == end) { if (position < length) |