Revision control
Copy as Markdown
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QSGINTERNALTEXTNODE_P_H
#define QSGINTERNALTEXTNODE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qsgtextnode.h"
#include "qquicktext_p.h"
#include <qglyphrun.h>
#include <QtGui/qcolor.h>
#include <QtGui/qtextlayout.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qscopedpointer.h>
QT_BEGIN_NAMESPACE
class QSGGlyphNode;
class QTextBlock;
class QColor;
class QTextDocument;
class QSGContext;
class QRawFont;
class QSGInternalImageNode;
class QSGInternalRectangleNode;
class QSGVisitableNode;
class QSGClipNode;
class QSGTexture;
class QSGRenderContext;
class QQuickTextNodeEngine;
class Q_QUICK_EXPORT QSGInternalTextNode : public QSGTextNode
{
public:
struct RecycleBin {
enum NodeType : quint8 { GlyphNode, RectangleNode, ImageNode };
struct UnusedNode {
QSGVisitableNode *node;
NodeType type;
};
RecycleBin() = default;
~RecycleBin()
{
Q_ASSERT(unusedNodes.isEmpty());
Q_ASSERT(unusedTextures.isEmpty());
}
// Reusing a node leaves it where it already is in the child list, and the child list is
// the draw order, so nodes can only be handed out in the order they were collected and
// only as children of the text node itself. Once the requests diverge from that, the
// rest of the bin has to be discarded instead of reused.
QSGVisitableNode *takeNextReusableNode(NodeType type)
{
const UnusedNode *next = peekNextReusableNode(type);
if (next == nullptr)
return nullptr;
++reusedNodes;
return next->node;
}
QSGGlyphNode *takeNextReusableGlyphNode(QSGTextNode::RenderType renderType);
void stopReusing() { reuseStopped = true; }
QVarLengthArray<UnusedNode, 8> unusedNodes;
qsizetype reusedNodes = 0;
bool reuseStopped = false;
QList<QSGTexture *> unusedTextures;
private:
const UnusedNode *peekNextReusableNode(NodeType type)
{
if (!reuseStopped) {
if (reusedNodes < unusedNodes.size()) {
const UnusedNode &next = unusedNodes.at(reusedNodes);
if (next.type == type)
return &next;
}
stopReusing();
}
return nullptr;
}
Q_DISABLE_COPY(RecycleBin)
};
QSGInternalTextNode(QSGRenderContext *renderContext);
~QSGInternalTextNode();
static bool isComplexRichText(QTextDocument *);
void setColor(QColor color) override
{
m_color = color;
}
QColor color() const override
{
return m_color;
}
void setTextStyle(TextStyle textStyle) override
{
m_textStyle = textStyle;
}
TextStyle textStyle() override
{
return m_textStyle;
}
void setStyleColor(QColor styleColor) override
{
m_styleColor = styleColor;
}
QColor styleColor() const override
{
return m_styleColor;
}
void setLinkColor(QColor linkColor) override
{
m_linkColor = linkColor;
}
QColor linkColor() const override
{
return m_linkColor;
}
void setSelectionColor(QColor selectionColor) override
{
m_selectionColor = selectionColor;
}
QColor selectionColor() const override
{
return m_selectionColor;
}
void setSelectionTextColor(QColor selectionTextColor) override
{
m_selectionTextColor = selectionTextColor;
}
QColor selectionTextColor() const override
{
return m_selectionTextColor;
}
void setRenderTypeQuality(int renderTypeQuality) override
{
m_renderTypeQuality = renderTypeQuality;
}
int renderTypeQuality() const override
{
return m_renderTypeQuality;
}
void setRenderType(RenderType renderType) override
{
m_renderType = renderType;
}
RenderType renderType() const override
{
return m_renderType;
}
bool containsUnscalableGlyphs() const
{
return m_containsUnscalableGlyphs;
}
void setFiltering(QSGTexture::Filtering filtering) override
{
m_filtering = filtering;
}
QSGTexture::Filtering filtering() const override
{
return m_filtering;
}
void setViewport(const QRectF &viewport) override
{
m_viewport = viewport;
}
QRectF viewport() const override
{
return m_viewport;
}
void setDevicePixelRatio(qreal dpr)
{
m_devicePixelRatio = dpr;
}
void setCursor(const QRectF &rect, const QColor &color, RecycleBin *recycleBin);
void clearCursor();
void addRectangleNode(const QRectF &rect, const QColor &color, RecycleBin *recycleBin);
virtual void addDecorationNode(const QRectF &rect,
const QColor &color,
QTextCharFormat::UnderlineStyle style,
RecycleBin *recycleBin);
void addImage(const QRectF &rect, const QImage &image, RecycleBin *recycleBin);
void clear() override;
void recycle(RecycleBin *recycleBin);
QSGGlyphNode *addGlyphs(const QPointF &position,
const QGlyphRun &glyphs,
const QColor &color,
RecycleBin *recycleBin,
QQuickText::TextStyle style = QQuickText::Normal,
const QColor &styleColor = QColor(),
QSGNode *parentNode = 0);
QSGInternalRectangleNode *cursorNode() const { return m_cursorNode; }
std::pair<int, int> renderedLineRange() const { return { m_firstLineInViewport, m_firstLinePastViewport }; }
void discardUnusedNodes(RecycleBin *recycleBin);
void addTextLayout(QPointF position,
QTextLayout *layout,
RecycleBin *recycleBin,
int selectionStart = -1,
int selectionCount = -1,
int lineStart = 0,
int lineCount = -1)
{
doAddTextLayout(position, layout, selectionStart, selectionCount, lineStart, lineCount, recycleBin);
}
void addTextDocument(QPointF position,
QTextDocument *document,
RecycleBin *recycleBin,
int selectionStart = -1,
int selectionCount = -1)
{
doAddTextDocument(position, document, selectionStart, selectionCount, recycleBin);
}
protected:
void doAddTextLayout(QPointF position,
QTextLayout *textLayout,
int selectionStart,
int selectionEnd,
int lineStart,
int lineCount,
RecycleBin *recycleBin);
void doAddTextLayout(QPointF position,
QTextLayout *textLayout,
int selectionStart,
int selectionEnd,
int lineStart,
int lineCount) override
{
doAddTextLayout(position, textLayout, selectionStart, selectionEnd, lineStart, lineCount, nullptr);
}
void doAddTextDocument(QPointF position,
QTextDocument *textDocument,
int selectionStart,
int selectionEnd,
RecycleBin *recycleBin);
void doAddTextDocument(QPointF position,
QTextDocument *textDocument,
int selectionStart,
int selectionEnd) override
{
doAddTextDocument(position, textDocument, selectionStart, selectionEnd, nullptr);
}
private:
QSGInternalImageNode *findOrCreateImageNode(RecycleBin *recycleBin);
QSGGlyphNode *findOrCreateGlyphNode(RenderType renderType,
RecycleBin *recycleBin,
QSGNode *parentNode);
QSGInternalRectangleNode *findOrCreateRectangleNode(RecycleBin *recycleBin);
QSGInternalRectangleNode *m_cursorNode = nullptr;
QList<QSGTexture *> m_textures;
QSGRenderContext *m_renderContext = nullptr;
RenderType m_renderType = QtRendering;
TextStyle m_textStyle = Normal;
QRectF m_viewport;
QColor m_color = QColor(0, 0, 0);
QColor m_styleColor = QColor(0, 0, 0);
QColor m_linkColor = QColor(0, 0, 255);
QColor m_selectionColor = QColor(0, 0, 128);
QColor m_selectionTextColor = QColor(255, 255, 255);
QSGTexture::Filtering m_filtering = QSGTexture::Nearest;
int m_renderTypeQuality = -1;
int m_firstLineInViewport = -1;
int m_firstLinePastViewport = -1;
bool m_containsUnscalableGlyphs = false;
qreal m_devicePixelRatio = 1.0;
friend class QQuickTextEdit;
friend class QQuickTextEditPrivate;
};
QT_END_NAMESPACE
#endif // QSGINTERNALTEXTNODE_P_H