8#include <private/qsvgvisitor_p.h>
12#include <QTextDocument>
17#include <private/qquickshape_p.h>
18#include <private/qquicktext_p.h>
19#include <private/qquicktranslate_p.h>
20#include <private/qquickitem_p.h>
22#include <private/qquickimagebase_p_p.h>
23#include <private/qquickimage_p.h>
24#include <private/qsgcurveprocessor_p.h>
26#include <private/qquadpath_p.h>
28#include <QtCore/private/qstringiterator_p.h>
31#include <QtCore/qloggingcategory.h>
33#include <QtSvg/private/qsvgstyle_p.h>
85 return brush.gradient();
120 for (
auto &stop : grad.
stops()) {
121 stop.second.setAlphaF(stop.second.alphaF() * opacity);
133 return penWidth ? penWidth : 1;
152 bool foundPath =
false;
154 switch (
child->type()) {
181 if (!
child->style().transform.isDefault()) {
188 qCDebug(lcQuickVectorImage) <<
"Unhandled type in switch" <<
child->type();
256 return dashArrayString;
261 : m_svgFileName(svgFileName)
269 qCDebug(lcQuickVectorImage) <<
"No valid QQuickGenerator is set. Genration will stop";
275 qCDebug(lcQuickVectorImage) <<
"Not a valid Svg File : " << m_svgFileName;
285 handleBaseNodeSetup(node);
288 fillCommonNodeInfo(node,
info);
292 handleBaseNodeEnd(node);
298 handleBaseNodeSetup(node);
301 fillCommonNodeInfo(node,
info);
308 handleBaseNodeEnd(node);
335 p.arcTo(
x1,
y2 -
ry * 2,
rx * 2,
ry * 2, 270, -90);
338 p.arcTo(
x1,
y1,
rx * 2,
ry * 2, 180, -90);
340 handlePathNode(node,
p);
350 handlePathNode(node,
p);
355 handlePathNode(node, node->
path());
363 handlePathNode(node,
p);
369 handlePathNode(node,
p);
375 handlePathNode(node,
p);
384 cssDescription +=
" -qt-foreground: qlineargradient("_L1;
385 cssDescription +=
"x1:"_L1 +
QString::number(linearGradient->start().x()) + u
',';
386 cssDescription +=
"y1:"_L1 +
QString::number(linearGradient->start().y()) + u
',';
387 cssDescription +=
"x2:"_L1 +
QString::number(linearGradient->finalStop().x()) + u
',';
388 cssDescription +=
"y2:"_L1 +
QString::number(linearGradient->finalStop().y()) + u
',';
392 cssDescription +=
" -qt-foreground: qradialgradient("_L1;
393 cssDescription +=
"cx:"_L1 +
QString::number(radialGradient->center().x()) + u
',';
394 cssDescription +=
"cy:"_L1 +
QString::number(radialGradient->center().y()) + u
',';
395 cssDescription +=
"fx:"_L1 +
QString::number(radialGradient->focalPoint().x()) + u
',';
396 cssDescription +=
"fy:"_L1 +
QString::number(radialGradient->focalPoint().y()) + u
',';
397 cssDescription +=
"radius:"_L1 +
QString::number(radialGradient->radius()) + u
',';
401 cssDescription +=
" -qt-foreground: qconicalgradient("_L1;
402 cssDescription +=
"cx:"_L1 +
QString::number(conicalGradient->center().x()) + u
',';
403 cssDescription +=
"cy:"_L1 +
QString::number(conicalGradient->center().y()) + u
',';
404 cssDescription +=
"angle:"_L1 +
QString::number(conicalGradient->angle()) + u
',';
407 const QStringList coordinateModes = {
"logical"_L1,
"stretchtodevice"_L1,
"objectbounding"_L1,
"object"_L1 };
408 cssDescription +=
"coordinatemode:"_L1;
409 cssDescription += coordinateModes.at(
int(gradient->
coordinateMode()));
410 cssDescription += u
',';
412 const QStringList spreads = {
"pad"_L1,
"reflect"_L1,
"repeat"_L1 };
413 cssDescription +=
"spread:"_L1;
414 cssDescription += spreads.at(
int(gradient->
spread()));
417 cssDescription +=
",stop:"_L1;
419 cssDescription += u
' ';
423 cssDescription +=
");"_L1;
425 return cssDescription;
437 return cssDescription;
458 ShaperFlags
flags)
const override;
460 void addGlyphsToPath(
glyph_t *glyphs,
464 QTextItem::RenderFlags
flags)
override;
468 void recalcAdvances(
QGlyphLayout *, ShaperFlags)
const override;
469 QFixed ascent()
const override;
470 QFixed capHeight()
const override;
471 QFixed descent()
const override;
472 QFixed leading()
const override;
473 qreal maxCharWidth()
const override;
474 qreal minLeftBearing()
const override;
475 qreal minRightBearing()
const override;
477 QFixed emSquareSize()
const override;
487 fontDef.pixelSize =
size;
488 fontDef.families =
QStringList(m_font->m_familyName);
491 QFixed QSvgFontEngine::emSquareSize()
const
496 glyph_t QSvgFontEngine::glyphIndex(
uint ucs4)
const
498 if (ucs4 < USHRT_MAX && m_font->m_glyphs.contains(
QChar(
ushort(ucs4))))
504 int QSvgFontEngine::stringToCMap(
const QChar *
str,
508 ShaperFlags
flags)
const
511 if (*nglyphs <
len) {
518 while (
it.hasNext()) {
519 char32_t ucs4 =
it.next();
524 *nglyphs = ucs4Length;
527 if (!(
flags & GlyphIndicesOnly))
528 recalcAdvances(glyphs,
flags);
533 void QSvgFontEngine::addGlyphsToPath(
glyph_t *glyphs,
537 QTextItem::RenderFlags
flags)
541 for (
int i = 0;
i < nGlyphs; ++
i) {
551 path->addPath(glyphPath);
564 ret.height = ascent() + descent();
570 QSvgFontEngine *otherEngine =
new QSvgFontEngine(m_font,
size);
574 void QSvgFontEngine::recalcAdvances(
QGlyphLayout *glyphLayout, ShaperFlags)
const
584 QFixed QSvgFontEngine::ascent()
const
589 QFixed QSvgFontEngine::capHeight()
const
593 QFixed QSvgFontEngine::descent()
const
598 QFixed QSvgFontEngine::leading()
const
603 qreal QSvgFontEngine::maxCharWidth()
const
609 qreal QSvgFontEngine::minLeftBearing()
const
614 qreal QSvgFontEngine::minRightBearing()
const
622 handleBaseNodeSetup(node);
626 const QSvgFont *svgFont = styleResolver->states().svgFont;
627 bool needsRichText =
false;
629 const QGradient *mainGradient = styleResolver->currentFillGradient();
632 if (svgFont !=
nullptr) {
633 fontEngine =
new QSvgFontEngine(svgFont, styleResolver->painter().font().pointSize());
637#if QT_CONFIG(texthtmlparser)
638 bool needsPathNode = mainGradient !=
nullptr
639 || svgFont !=
nullptr
640 || styleResolver->currentStrokeGradient() !=
nullptr;
642 for (
const auto *tspan : node->
tspans()) {
650 handleBaseNodeSetup(tspan);
651 QFont font = styleResolver->painter().font();
676 if (styleResolver->currentFillGradient() !=
nullptr
677 && styleResolver->currentFillGradient() != mainGradient) {
678 const QGradient grad = styleResolver->applyOpacityToGradient(*styleResolver->currentFillGradient(), styleResolver->currentFillOpacity());
679 styleTagContent += gradientCssDescription(&grad) + u
';';
680#if QT_CONFIG(texthtmlparser)
681 needsPathNode =
true;
685 const QColor currentStrokeColor = styleResolver->currentStrokeColor();
686 if (currentStrokeColor.
alpha() > 0) {
687 QString strokeColor = colorCssDescription(currentStrokeColor);
688 styleTagContent +=
QStringLiteral(
"-qt-stroke-color:%1;").arg(strokeColor);
689 styleTagContent +=
QStringLiteral(
"-qt-stroke-width:%1px;").arg(styleResolver->currentStrokeWidth());
690 styleTagContent +=
QStringLiteral(
"-qt-stroke-dasharray:%1;").arg(dashArrayString(styleResolver->currentStroke().dashPattern()));
691 styleTagContent +=
QStringLiteral(
"-qt-stroke-dashoffset:%1;").arg(styleResolver->currentStroke().dashOffset());
692 styleTagContent +=
QStringLiteral(
"-qt-stroke-lineCap:%1;").arg(capStyleName(styleResolver->currentStroke().capStyle()));
693 styleTagContent +=
QStringLiteral(
"-qt-stroke-lineJoin:%1;").arg(joinStyleName(styleResolver->currentStroke().joinStyle()));
695 styleTagContent +=
QStringLiteral(
"-qt-stroke-miterlimit:%1;").arg(styleResolver->currentStroke().miterLimit());
696#if QT_CONFIG(texthtmlparser)
697 needsPathNode =
true;
708 bool fontTag =
false;
709 if (!tspan->style().fill.isDefault()) {
710 auto &
b = tspan->style().
fill->qbrush();
711 qCDebug(lcQuickVectorImage) <<
"tspan FILL:" <<
b;
716 QString spanColor =
b.color().name();
717 fontTag = !spanColor.
isEmpty();
721 QString spanColor = colorCssDescription(
b.color());
727 needsRichText = needsRichText || !styleTagContent.isEmpty();
728 if (!styleTagContent.isEmpty())
748 qCWarning(lcQuickVectorImage) <<
"Title case not implemented for tspan";
764 if (!styleTagContent.isEmpty())
767 handleBaseNodeEnd(tspan);
770 if (preserveWhiteSpace && (needsRichText || styleResolver->currentFillGradient() !=
nullptr))
773 QFont font = styleResolver->painter().font();
777#if QT_CONFIG(texthtmlparser)
780 document.setHtml(
text);
781 if (isTextArea && node->
size().
width() > 0)
782 document.setTextWidth(node->
size().
width());
783 document.setDefaultFont(
font);
784 document.pageCount();
790 if (lout !=
nullptr) {
796 if (svgFont !=
nullptr
800 rawFontD->setFontEngine(fontEngine->
cloneWithSize(blockFont.pixelSize()));
807 fillCommonNodeInfo(node,
info);
810 info.fillRule = fillStyle->fillRule();
813 info.fillColor =
fmt.foreground().color();
815 info.grad = *
fmt.foreground().gradient();
817 info.fillColor = styleResolver->currentFillColor();
820 info.painterPath =
p;
822 const QGradient *strokeGradient = styleResolver->currentStrokeGradient();
825 pen =
fmt.textOutline();
826 if (strokeGradient ==
nullptr) {
831 pen = styleResolver->currentStroke();
832 if (strokeGradient ==
nullptr) {
834 info.strokeStyle.color = styleResolver->currentStrokeColor();
839 info.grad = styleResolver->applyOpacityToGradient(*styleResolver->currentFillGradient(), styleResolver->currentFillOpacity());
841 info.fillTransform = styleResolver->currentFillTransform();
843 m_generator->generatePath(
info);
845 if (strokeGradient !=
nullptr) {
847 fillCommonNodeInfo(node, strokeInfo);
849 strokeInfo.grad = *strokeGradient;
853 m_generator->generatePath(strokeInfo);
861 const QPointF baselineTranslation(0.0, baselineOffset);
862 auto glyphsToPath = [&](QList<QGlyphRun> glyphRuns,
qreal width) {
863 QList<QPainterPath>
paths;
864 for (
const QGlyphRun &glyphRun : glyphRuns) {
866 QList<quint32> glyphIndexes = glyphRun.glyphIndexes();
867 QList<QPointF>
positions = glyphRun.positions();
870 quint32 glyphIndex = glyphIndexes.at(
j);
874 p.translate(
pos + node->
position() + baselineTranslation);
897 block = block.
next();
903 fillCommonNodeInfo(node,
info);
909 info.isTextArea = isTextArea;
910 info.needsRichText = needsRichText;
911 info.fillColor = styleResolver->currentFillColor();
912 info.alignment = styleResolver->states().textAnchor;
913 info.strokeColor = styleResolver->currentStrokeColor();
915 m_generator->generateTextNode(
info);
918 handleBaseNodeEnd(node);
920 if (fontEngine !=
nullptr) {
933 handleBaseNodeSetup(node);
935 fillCommonNodeInfo(node,
info);
940 m_generator->generateUseNode(
info);
945 m_generator->generateUseNode(
info);
946 handleBaseNodeEnd(node);
953 return m_generator->generateDefsNode(
NodeInfo{});
958 constexpr bool forceSeparatePaths =
false;
959 handleBaseNodeSetup(node);
963 fillCommonNodeInfo(node,
info);
964 info.forceSeparatePaths = forceSeparatePaths;
965 info.isPathContainer = isPathContainer(node);
968 return m_generator->generateStructureNode(
info);
973 handleBaseNodeEnd(node);
978 fillCommonNodeInfo(node,
info);
981 m_generator->generateStructureNode(
info);
986 handleBaseNodeSetup(node);
989 fillCommonNodeInfo(node,
info);
994 info.isPathContainer = isPathContainer(node);
997 return m_generator->generateRootNode(
info);
1002 handleBaseNodeEnd(node);
1003 qCDebug(lcQuickVectorImage) <<
"REVERT" << node->
nodeId() << node->
type() << (styleResolver->painter().pen().style() !=
Qt::NoPen)
1004 << styleResolver->painter().pen().color().
name() << (styleResolver->painter().pen().brush().style() !=
Qt::NoBrush)
1005 << styleResolver->painter().pen().brush().color().name();
1008 fillCommonNodeInfo(node,
info);
1011 m_generator->generateRootNode(
info);
1026void QSvgVisitorImpl::handleBaseNodeSetup(
const QSvgNode *node)
1028 qCDebug(lcQuickVectorImage) <<
"Before SETUP" << node <<
"fill" << styleResolver->currentFillColor()
1029 <<
"stroke" << styleResolver->currentStrokeColor() << styleResolver->currentStrokeWidth()
1032 node->
applyStyle(&styleResolver->painter(), styleResolver->states());
1034 qCDebug(lcQuickVectorImage) <<
"After SETUP" << node <<
"fill" << styleResolver->currentFillColor()
1035 <<
"stroke" << styleResolver->currentStrokeColor()
1036 << styleResolver->currentStrokeWidth() << node->
nodeId();
1039void QSvgVisitorImpl::handleBaseNode(
const QSvgNode *node)
1042 fillCommonNodeInfo(node,
info);
1044 m_generator->generateNodeBase(
info);
1047void QSvgVisitorImpl::handleBaseNodeEnd(
const QSvgNode *node)
1049 node->
revertStyle(&styleResolver->painter(), styleResolver->states());
1051 qCDebug(lcQuickVectorImage) <<
"After END" << node <<
"fill" << styleResolver->currentFillColor()
1052 <<
"stroke" << styleResolver->currentStrokeColor() << styleResolver->currentStrokeWidth()
1058 handleBaseNodeSetup(node);
1061 fillCommonNodeInfo(node,
info);
1064 info.fillRule = fillStyle->fillRule();
1066 const QGradient *strokeGradient = styleResolver->currentStrokeGradient();
1069 info.fillColor = styleResolver->currentFillColor();
1070 if (strokeGradient ==
nullptr) {
1072 info.strokeStyle.color = styleResolver->currentStrokeColor();
1074 if (styleResolver->currentFillGradient() !=
nullptr)
1075 info.grad = styleResolver->applyOpacityToGradient(*styleResolver->currentFillGradient(), styleResolver->currentFillOpacity());
1076 info.fillTransform = styleResolver->currentFillTransform();
1078 m_generator->generatePath(
info);
1080 if (strokeGradient !=
nullptr) {
1082 fillCommonNodeInfo(node, strokeInfo);
1084 strokeInfo.grad = *strokeGradient;
1087 strokeInfo.painterPath = stroker.createStroke(
path);
1088 m_generator->generatePath(strokeInfo);
1091 handleBaseNodeEnd(node);
T loadRelaxed() const noexcept
const QGradient * gradient() const
Returns the gradient describing this brush.
const QColor & color() const
Returns the brush color.
Qt::BrushStyle style() const
Returns the brush style.
QTransform transform() const
The QColor class provides colors based on RGB, HSV or CMYK values.
void setAlphaF(float alpha)
Sets the alpha of this color to alpha.
int alpha() const noexcept
Returns the alpha color component of this color.
virtual QFontEngine * cloneWithSize(qreal) const
\reentrant \inmodule QtGui
qreal ascent() const
Returns the ascent of the font.
QString family() const
Returns the requested font family name.
int pixelSize() const
Returns the pixel size of the font if it was set with setPixelSize().
bool italic() const
Returns true if the style() of the font is not QFont::StyleNormal.
Capitalization capitalization() const
Weight weight() const
Returns the weight of the font, using the same scale as the \l{QFont::Weight} enumeration.
int pointSize() const
Returns the point size of the font.
void setPixelSize(int)
Sets the font size to pixelSize pixels, with a maxiumum size of an unsigned 16-bit integer.
bool bold() const
Returns true if weight() is a value greater than \l{Weight}{QFont::Medium}; otherwise returns false.
qreal pointSizeF() const
Returns the point size of the font.
The QGlyphRun class provides direct access to the internal glyphs in a font.
Spread spread() const
Returns the spread method use by this gradient.
CoordinateMode coordinateMode() const
void setStops(const QGradientStops &stops)
Replaces the current set of stop points with the given stopPoints.
Type type() const
Returns the type of gradient.
QGradientStops stops() const
Returns the stop points for this gradient.
T value(const Key &key) const noexcept
constexpr QPointF p1() const
Returns the line's start point.
constexpr QPointF p2() const
Returns the line's end point.
void append(parameter_type t)
The QPainterPathStroker class is used to generate fillable outlines for a given painter path.
QPainterPath createStroke(const QPainterPath &path) const
Generates a new path that is a fillable area representing the outline of the given path.
void moveTo(const QPointF &p)
Moves the current point to the given point, implicitly starting a new subpath and closing the previou...
void addEllipse(const QRectF &rect)
Creates an ellipse within the specified boundingRectangle and adds it to the painter path as a closed...
The QPainter class performs low-level painting on widgets and other paint devices.
const QPen & pen() const
Returns the painter's current pen.
void setPen(const QColor &color)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool begin(QPaintDevice *)
Begins painting the paint device and returns true if successful; otherwise returns false.
const QBrush & brush() const
Returns the painter's current brush.
void setBrush(const QBrush &brush)
Sets the painter's brush to the given brush.
qreal widthF() const
Returns the pen width with floating point precision.
QColor color() const
Returns the color of this pen's brush.
void setMiterLimit(qreal limit)
Sets the miter limit of this pen to the given limit.
QBrush brush() const
Returns the brush used to fill strokes generated with this pen.
\inmodule QtCore\reentrant
virtual void generateNode(const NodeInfo &info)=0
virtual void generateImageNode(const ImageNodeInfo &info)=0
static QRawFontPrivate * get(const QRawFont &font)
The QRawFont class provides access to a single physical instance of a font.
\inmodule QtCore\reentrant
constexpr qreal width() const noexcept
Returns the width.
\macro QT_RESTRICTED_CAST_FROM_ASCII
QString & fill(QChar c, qsizetype size=-1)
Sets every character in the string to character ch.
QString & replace(qsizetype i, qsizetype len, QChar after)
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
QString toLower() const &
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString toUpper() const &
QString toHtmlEscaped() const
QHash< QChar, QSvgGlyph > m_glyphs
const QImage & image() const
void revertStyle(QPainter *p, QSvgExtraStates &states) const
void applyStyle(QPainter *p, QSvgExtraStates &states) const
DisplayMode displayMode() const
const QSvgStyle & style() const
virtual Type type() const =0
const QPainterPath & path() const
const QPolygonF & polygon() const
const QPolygonF & polygon() const
QList< QSvgNode * > renderers() const
const QGradient * currentFillGradient() const
const QGradient * currentStrokeGradient() const
QColor currentFillColor() const
QSvgExtraStates & states()
static QGradient applyOpacityToGradient(const QGradient &gradient, float opacity)
QTransform currentFillTransform() const
QPen currentStroke() const
qreal currentFillOpacity() const
float currentStrokeWidth() const
QSvgExtraStates m_svgState
QColor currentStrokeColor() const
QSvgRefCounter< QSvgOpacityStyle > opacity
QSvgRefCounter< QSvgTransformStyle > transform
QSvgRefCounter< QSvgFillStyle > fill
const QList< QSvgTspan * > tspans() const
WhitespaceMode whitespaceMode() const
Type type() const override
Type type() const override
static QSvgTinyDocument * load(const QString &file, QtSvg::Options options={})
void visitPolygonNode(const QSvgPolygon *node) override
void visitEllipseNode(const QSvgEllipse *node) override
void visitPathNode(const QSvgPath *node) override
bool visitDefsNodeStart(const QSvgDefs *node) override
QSvgVisitorImpl(const QString svgFileName, QQuickGenerator *generator)
void visitDocumentNodeEnd(const QSvgTinyDocument *node) override
void visitStructureNodeEnd(const QSvgStructureNode *node) override
void visitRectNode(const QSvgRect *node) override
void visitLineNode(const QSvgLine *node) override
void visitNode(const QSvgNode *node) override
void visitPolylineNode(const QSvgPolyline *node) override
void visitUseNode(const QSvgUse *node) override
bool visitDocumentNodeStart(const QSvgTinyDocument *node) override
void visitImageNode(const QSvgImage *node) override
void visitTextNode(const QSvgText *node) override
bool visitStructureNodeStart(const QSvgStructureNode *node) override
void traverse(const QSvgStructureNode *node)
bool isValid() const
Returns true if this text block is valid; otherwise returns false.
QList< QTextLayout::FormatRange > textFormats() const
QTextBlock next() const
Returns the text block in the document after this block, or an empty text block if this is the last o...
QTextLayout * layout() const
Returns the QTextLayout that is used to lay out and display the block's contents.
QTextCharFormat charFormat() const
Returns the QTextCharFormat that describes the block's character format.
QFont font() const
Returns the font for this character format.
\reentrant \inmodule QtGui
qreal minimumWidth() const
The minimum width the layout needs.
QList< QGlyphRun > glyphRuns(int from=-1, int length=-1, GlyphRunRetrievalFlags flags=DefaultRetrievalFlags) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
void setRawFont(const QRawFont &rawFont)
int lineCount() const
Returns the number of lines in this text layout.
QTextLine lineAt(int i) const
Returns the {i}-th line of text in this text layout.
bool isValid() const
Returns true if this text line is valid; otherwise returns false.
qreal ascent() const
Returns the line's ascent.
QSet< QString >::iterator it
constexpr QColor Transparent
QPainterPath polygonToPath(const QPolygonF &poly, bool closed)
Combined button and popup list for selecting options.
QPair< qreal, QColor > QGradientStop
QList< QString > QStringList
Constructs a string list that contains the given string, str.
static const QCssKnownValue positions[NumKnownPositionModes - 1]
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
GLboolean GLboolean GLboolean b
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLfloat GLfloat GLfloat x1
GLsizei const GLuint * paths
GLsizei const GLfloat * dashArray
GLfixed GLfixed GLfixed y2
GLsizei const GLchar *const * path
GLenum GLenum GLenum GLenum GLenum scale
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define QStringLiteral(str)
QVideoFrameFormat::PixelFormat fmt
QRandomGenerator generator(sseq)
static constexpr QFixed fromReal(qreal r)
\inmodule QtCore \reentrant
static StrokeStyle fromPen(const QPen &p)