Render text in Quick directly.
Uses private QQuickTextNode api.
This commit is contained in:
parent
66543f1588
commit
70a199a2f5
6 changed files with 176 additions and 31 deletions
|
@ -69,5 +69,6 @@ target_include_directories(fgqcanvas PRIVATE ${PROJECT_SOURCE_DIR})
|
||||||
target_include_directories(fgqcanvas PRIVATE ${PROJECT_BINARY_DIR})
|
target_include_directories(fgqcanvas PRIVATE ${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
target_include_directories(fgqcanvas PRIVATE ${Qt5Gui_PRIVATE_INCLUDE_DIRS})
|
target_include_directories(fgqcanvas PRIVATE ${Qt5Gui_PRIVATE_INCLUDE_DIRS})
|
||||||
|
target_include_directories(fgqcanvas PRIVATE ${Qt5Quick_PRIVATE_INCLUDE_DIRS})
|
||||||
|
|
||||||
install(TARGETS fgqcanvas RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
install(TARGETS fgqcanvas RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
QT += core gui gui-private quick websockets
|
QT += core gui gui-private quick websockets quick-private
|
||||||
CONFIG += c++11
|
CONFIG += c++11
|
||||||
|
|
||||||
!ios:!android
|
!ios:!android
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QQmlComponent>
|
#include <QQmlComponent>
|
||||||
#include <QQmlEngine>
|
#include <QQmlEngine>
|
||||||
|
#include <QTextLayout>
|
||||||
|
|
||||||
|
#include <private/qquicktextnode_p.h>
|
||||||
|
|
||||||
#include "fgcanvaspaintcontext.h"
|
#include "fgcanvaspaintcontext.h"
|
||||||
#include "localprop.h"
|
#include "localprop.h"
|
||||||
|
@ -28,7 +31,158 @@
|
||||||
#include "canvasitem.h"
|
#include "canvasitem.h"
|
||||||
#include "canvasconnection.h"
|
#include "canvasconnection.h"
|
||||||
|
|
||||||
static QQmlComponent* static_textComponent = nullptr;
|
class TextCanvasItem : public CanvasItem
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
TextCanvasItem(QQuickItem* parent)
|
||||||
|
: CanvasItem(parent)
|
||||||
|
{
|
||||||
|
setFlag(ItemHasContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setText(QString t)
|
||||||
|
{
|
||||||
|
if (t == m_text) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_text = t;
|
||||||
|
updateTextLayout();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setColor(QColor c)
|
||||||
|
{
|
||||||
|
m_color = c;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAlignment(Qt::Alignment textAlign)
|
||||||
|
{
|
||||||
|
m_alignment = textAlign;
|
||||||
|
updateTextLayout();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFont(QFont font)
|
||||||
|
{
|
||||||
|
m_font = font;
|
||||||
|
updateTextLayout();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QSGNode* updatePaintNode(QSGNode* oldNode, QQuickItem::UpdatePaintNodeData *data)
|
||||||
|
{
|
||||||
|
if (!m_textNode) {
|
||||||
|
m_textNode = new QQuickTextNode(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_textNode->deleteContent();
|
||||||
|
QPointF pos = posForAlignment();
|
||||||
|
|
||||||
|
m_textNode->addTextLayout(pos,
|
||||||
|
&m_layout,
|
||||||
|
m_color,
|
||||||
|
QQuickText::Normal);
|
||||||
|
|
||||||
|
|
||||||
|
return m_textNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QPointF posForAlignment()
|
||||||
|
{
|
||||||
|
float x = 0.0f;
|
||||||
|
float y = 0.0f;
|
||||||
|
const float itemWidth = width();
|
||||||
|
const float itemHeight = height();
|
||||||
|
const float textWidth = m_layout.boundingRect().width();
|
||||||
|
const float textHeight = m_layout.boundingRect().height();
|
||||||
|
|
||||||
|
switch (m_alignment & Qt::AlignHorizontal_Mask) {
|
||||||
|
case Qt::AlignLeft:
|
||||||
|
case Qt::AlignJustify:
|
||||||
|
break;
|
||||||
|
case Qt::AlignRight:
|
||||||
|
x = itemWidth - textWidth;
|
||||||
|
break;
|
||||||
|
case Qt::AlignHCenter:
|
||||||
|
x = (itemWidth - textWidth) / 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (m_alignment & Qt::AlignVertical_Mask) {
|
||||||
|
case Qt::AlignTop:
|
||||||
|
break;
|
||||||
|
case Qt::AlignBottom:
|
||||||
|
y = itemHeight - textHeight;
|
||||||
|
break;
|
||||||
|
case Qt::AlignVCenter:
|
||||||
|
y = (itemHeight - textHeight) / 2;
|
||||||
|
break;
|
||||||
|
case Qt::AlignBaseline:
|
||||||
|
y = -m_baselineOffset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QPointF(x,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
|
||||||
|
{
|
||||||
|
QQuickItem::geometryChanged(newGeometry, oldGeometry);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF boundingRect() const
|
||||||
|
{
|
||||||
|
if ((width() == 0.0) || (height() == 0.0)) {
|
||||||
|
return m_layout.boundingRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QQuickItem::boundingRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateTextLayout()
|
||||||
|
{
|
||||||
|
QFontMetricsF fm(m_font);
|
||||||
|
m_baselineOffset = fm.ascent(); // for aligning to first base line
|
||||||
|
|
||||||
|
m_layout.setText(m_text);
|
||||||
|
QTextOption textOpt(m_alignment);
|
||||||
|
m_layout.setTextOption(textOpt);
|
||||||
|
m_layout.setFont(m_font);
|
||||||
|
|
||||||
|
m_layout.beginLayout();
|
||||||
|
float leading = fm.leading();
|
||||||
|
int lineCount = 0;
|
||||||
|
float y = 0.0;
|
||||||
|
|
||||||
|
QTextLine line = m_layout.createLine();
|
||||||
|
while (line.isValid()) {
|
||||||
|
int nextBreak = m_text.indexOf('\n', line.textStart());
|
||||||
|
int columnsToNextBreak = nextBreak >= 0 ? nextBreak : INT_MAX;
|
||||||
|
line.setNumColumns(columnsToNextBreak);
|
||||||
|
line.setPosition(QPointF(0.0, y));
|
||||||
|
++lineCount;
|
||||||
|
y += leading + line.height();
|
||||||
|
line = m_layout.createLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_layout.endLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QQuickTextNode* m_textNode = nullptr;
|
||||||
|
QColor m_color;
|
||||||
|
QFont m_font;
|
||||||
|
QString m_text;
|
||||||
|
Qt::Alignment m_alignment = Qt::AlignCenter;
|
||||||
|
QTextLayout m_layout;
|
||||||
|
float m_baselineOffset;
|
||||||
|
};
|
||||||
|
|
||||||
FGCanvasText::FGCanvasText(FGCanvasGroup* pr, LocalProp* prop) :
|
FGCanvasText::FGCanvasText(FGCanvasGroup* pr, LocalProp* prop) :
|
||||||
FGCanvasElement(pr, prop),
|
FGCanvasElement(pr, prop),
|
||||||
|
@ -38,9 +192,7 @@ FGCanvasText::FGCanvasText(FGCanvasGroup* pr, LocalProp* prop) :
|
||||||
|
|
||||||
CanvasItem *FGCanvasText::createQuickItem(QQuickItem *parent)
|
CanvasItem *FGCanvasText::createQuickItem(QQuickItem *parent)
|
||||||
{
|
{
|
||||||
Q_ASSERT(static_textComponent);
|
_quickItem = new TextCanvasItem(parent);
|
||||||
_quickItem = qobject_cast<CanvasItem*>(static_textComponent->create());
|
|
||||||
_quickItem->setParentItem(parent);
|
|
||||||
markFontDirty(); // so it gets set on the new item
|
markFontDirty(); // so it gets set on the new item
|
||||||
return _quickItem;
|
return _quickItem;
|
||||||
}
|
}
|
||||||
|
@ -50,12 +202,6 @@ CanvasItem *FGCanvasText::quickItem() const
|
||||||
return _quickItem;
|
return _quickItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGCanvasText::setEngine(QQmlEngine *engine)
|
|
||||||
{
|
|
||||||
static_textComponent = new QQmlComponent(engine, QUrl("qrc:///qml/text.qml"));
|
|
||||||
qDebug() << static_textComponent->errorString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FGCanvasText::doPaint(FGCanvasPaintContext *context) const
|
void FGCanvasText::doPaint(FGCanvasPaintContext *context) const
|
||||||
{
|
{
|
||||||
context->painter()->setFont(_font);
|
context->painter()->setFont(_font);
|
||||||
|
@ -82,6 +228,9 @@ void FGCanvasText::doPaint(FGCanvasPaintContext *context) const
|
||||||
}
|
}
|
||||||
|
|
||||||
context->painter()->drawText(rect, _alignment, _text);
|
context->painter()->drawText(rect, _alignment, _text);
|
||||||
|
|
||||||
|
context->painter()->setPen(Qt::cyan);
|
||||||
|
context->painter()->drawRect(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGCanvasText::doPolish()
|
void FGCanvasText::doPolish()
|
||||||
|
@ -125,7 +274,7 @@ void FGCanvasText::onTextChanged(QVariant var)
|
||||||
{
|
{
|
||||||
_text = var.toString();
|
_text = var.toString();
|
||||||
if (_quickItem) {
|
if (_quickItem) {
|
||||||
_quickItem->setProperty("text", var);
|
_quickItem->setText(var.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,12 +294,12 @@ void FGCanvasText::rebuildAlignment(QVariant var) const
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_quickItem) {
|
|
||||||
_quickItem->setProperty("canvasAlignment", alignString);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (alignString == "center") {
|
if (alignString == "center") {
|
||||||
_alignment = Qt::AlignCenter;
|
_alignment = Qt::AlignCenter;
|
||||||
|
|
||||||
|
if (_quickItem) {
|
||||||
|
_quickItem->setAlignment(_alignment);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +327,9 @@ void FGCanvasText::rebuildAlignment(QVariant var) const
|
||||||
}
|
}
|
||||||
|
|
||||||
_alignment = newAlignment;
|
_alignment = newAlignment;
|
||||||
|
if (_quickItem) {
|
||||||
|
_quickItem->setAlignment(_alignment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGCanvasText::markFontDirty()
|
void FGCanvasText::markFontDirty()
|
||||||
|
@ -216,11 +368,10 @@ void FGCanvasText::rebuildFont() const
|
||||||
rebuildAlignment(getCascadedStyle("alignment"));
|
rebuildAlignment(getCascadedStyle("alignment"));
|
||||||
|
|
||||||
if (_quickItem) {
|
if (_quickItem) {
|
||||||
_quickItem->setProperty("fontFamily", f.family());
|
_quickItem->setFont(f);
|
||||||
_quickItem->setProperty("fontPixelSize", pixelSize);
|
_quickItem->setColor(fillColor());
|
||||||
|
// _quickItem->setProperty("fontPixelSize", pixelSize);
|
||||||
QColor fill = fillColor();
|
|
||||||
_quickItem->setProperty("color", fill.name());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "fgcanvastext.moc"
|
||||||
|
|
|
@ -20,10 +20,11 @@
|
||||||
|
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QFontMetricsF>
|
#include <QFontMetricsF>
|
||||||
#include <QQmlEngine>
|
|
||||||
|
|
||||||
#include "fgcanvaselement.h"
|
#include "fgcanvaselement.h"
|
||||||
|
|
||||||
|
class TextCanvasItem;
|
||||||
|
|
||||||
class FGCanvasText : public FGCanvasElement
|
class FGCanvasText : public FGCanvasElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -32,7 +33,6 @@ public:
|
||||||
CanvasItem* createQuickItem(QQuickItem *parent) override;
|
CanvasItem* createQuickItem(QQuickItem *parent) override;
|
||||||
CanvasItem* quickItem() const override;
|
CanvasItem* quickItem() const override;
|
||||||
|
|
||||||
static void setEngine(QQmlEngine* engine);
|
|
||||||
protected:
|
protected:
|
||||||
virtual void doPaint(FGCanvasPaintContext* context) const override;
|
virtual void doPaint(FGCanvasPaintContext* context) const override;
|
||||||
void doPolish() override;
|
void doPolish() override;
|
||||||
|
@ -59,7 +59,7 @@ private:
|
||||||
mutable QFont _font;
|
mutable QFont _font;
|
||||||
mutable QFontMetricsF _metrics;
|
mutable QFontMetricsF _metrics;
|
||||||
|
|
||||||
CanvasItem* _quickItem = nullptr;
|
TextCanvasItem* _quickItem = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,6 @@
|
||||||
#include <QQuickView>
|
#include <QQuickView>
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
|
|
||||||
#include "fgcanvastext.h"
|
|
||||||
#include "fgqcanvasimage.h"
|
|
||||||
#include "canvasitem.h"
|
#include "canvasitem.h"
|
||||||
#include "applicationcontroller.h"
|
#include "applicationcontroller.h"
|
||||||
#include "canvasdisplay.h"
|
#include "canvasdisplay.h"
|
||||||
|
@ -48,9 +46,6 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
quickView.rootContext()->setContextProperty("_application", &appController);
|
quickView.rootContext()->setContextProperty("_application", &appController);
|
||||||
|
|
||||||
FGCanvasText::setEngine(quickView.engine());
|
|
||||||
FGQCanvasImage::setEngine(quickView.engine());
|
|
||||||
|
|
||||||
quickView.setSource(QUrl("qrc:///qml/mainMenu.qml"));
|
quickView.setSource(QUrl("qrc:///qml/mainMenu.qml"));
|
||||||
quickView.setResizeMode(QQuickView::SizeRootObjectToView);
|
quickView.setResizeMode(QQuickView::SizeRootObjectToView);
|
||||||
quickView.show();
|
quickView.show();
|
||||||
|
|
|
@ -46,8 +46,6 @@ TemporaryWidget::TemporaryWidget(QWidget *parent) :
|
||||||
ui->quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
ui->quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||||
ui->quickWidget->setSource(QUrl("root.qml"));
|
ui->quickWidget->setSource(QUrl("root.qml"));
|
||||||
|
|
||||||
FGCanvasText::setEngine(ui->quickWidget->engine());
|
|
||||||
|
|
||||||
connect(ui->canvasSelectCombo, SIGNAL(activated(int)),
|
connect(ui->canvasSelectCombo, SIGNAL(activated(int)),
|
||||||
this, SLOT(onCanvasSelected(int)));
|
this, SLOT(onCanvasSelected(int)));
|
||||||
ui->canvasSelectCombo->hide();
|
ui->canvasSelectCombo->hide();
|
||||||
|
|
Loading…
Add table
Reference in a new issue