11#include <qguiapplication.h>
21#ifndef QT_NO_TEXTHTMLPARSER
25using namespace Qt::StringLiterals;
48 {
"Epsilon", 0x0395 },
69 {
"Omicron", 0x039f },
87 {
"Upsilon", 0x03a5 },
98 {
"alefsym", 0x2135 },
106 {
"atilde", 0x00e3 },
110 {
"brvbar", 0x00a6 },
113 {
"ccedil", 0x00e7 },
123 {
"curren", 0x00a4 },
125 {
"dagger", 0x2020 },
130 {
"divide", 0x00f7 },
131 {
"eacute", 0x00e9 },
133 {
"egrave", 0x00e8 },
137 {
"epsilon", 0x03b5 },
145 {
"forall", 0x2200 },
146 {
"frac12", 0x00bd },
147 {
"frac14", 0x00bc },
148 {
"frac34", 0x00be },
155 {
"hearts", 0x2665 },
156 {
"hellip", 0x2026 },
157 {
"iacute", 0x00ed },
160 {
"igrave", 0x00ec },
165 {
"iquest", 0x00bf },
170 {
"lambda", 0x03bb },
177 {
"lfloor", 0x230a },
178 {
"lowast", 0x2217 },
181 {
"lsaquo", 0x2039 },
187 {
"middot", 0x00b7 },
198 {
"ntilde", 0x00f1 },
200 {
"oacute", 0x00f3 },
203 {
"ograve", 0x00f2 },
206 {
"omicron", 0x03bf },
211 {
"oslash", 0x00f8 },
212 {
"otilde", 0x00f5 },
213 {
"otimes", 0x2297 },
217 {
"percnt", 0x0025 },
218 {
"permil", 0x2030 },
223 {
"plusmn", 0x00b1 },
239 {
"rfloor", 0x230b },
242 {
"rsaquo", 0x203a },
245 {
"scaron", 0x0161 },
250 {
"sigmaf", 0x03c2 },
252 {
"spades", 0x2660 },
263 {
"there4", 0x2234 },
265 {
"thetasym", 0x03d1 },
266 {
"thinsp", 0x2009 },
272 {
"uacute", 0x00fa },
275 {
"ugrave", 0x00f9 },
278 {
"upsilon", 0x03c5 },
280 {
"weierp", 0x2118 },
282 {
"yacute", 0x00fd },
289static_assert(
MAX_ENTITY ==
sizeof entities /
sizeof *entities);
291#if defined(Q_CC_MSVC_ONLY) && _MSC_VER < 1600
292bool operator<(
const QTextHtmlEntity &entity1,
const QTextHtmlEntity &entity2)
294 return QLatin1StringView(entity1.name) < QLatin1StringView(entity2.name);
300 return entityStr < QLatin1StringView(entity
.name);
305 return QLatin1StringView(entity
.name) < entityStr;
313 if (e == end || (entity < *e))
419 return str < QLatin1StringView(e
.name);
424 return QLatin1StringView(e
.name) < str;
432 if ((e == end) || (element < *e))
449 n.replace(u'\n',
"\\n"_L1);
469 for (
int i = 0; i < 4; ++i) {
470 tableCellBorderStyle[i] = QTextFrameFormat::BorderStyle_None;
471 tableCellBorder[i] = 0;
472 tableCellBorderBrush[i] = Qt::NoBrush;
478 for (
int i = 0; i <
count(); ++i) {
479 qDebug().nospace() << qPrintable(QString(depth(i) * 4, u' '))
480 << qPrintable(at(i).tag) <<
':'
481 << quoteNewline(at(i).text);
490 bool reuseLastNode =
true;
492 if (nodes.size() == 1) {
493 reuseLastNode =
false;
494 }
else if (lastNode->tag.isEmpty()) {
496 if (lastNode->text.isEmpty()) {
497 reuseLastNode =
true;
500 if (lastNode->text.size() == 1 && lastNode->text.at(0).isSpace()) {
510 reuseLastNode =
false;
512 reuseLastNode =
true;
516 reuseLastNode =
false;
523 reuseLastNode =
false;
528 newNode->tag.clear();
529 newNode->text.clear();
532 nodes.append(
new QTextHtmlParserNode);
533 newNode = nodes.last();
540void QTextHtmlParser::parse(
const QString &text,
const QTextDocument *_resourceProvider)
544 nodes.append(
new QTextHtmlParserNode);
549 resourceProvider = _resourceProvider;
598 while (pos < len && txt.at(pos).isSpace() && txt.at(pos) != QChar::ParagraphSeparator)
605 QChar c = txt.at(pos++);
608 }
else if (c == u'&') {
609 nodes.last()->text += parseEntity();
611 nodes.last()->text += c;
622 if (hasPrefix(u'!')) {
624 if (nodes.last()->wsm != QTextHtmlParserNode::WhiteSpacePre
625 && nodes.last()->wsm != QTextHtmlParserNode::WhiteSpacePreWrap
632 if (hasPrefix(u'/')) {
633 if (nodes.last()->id == Html_style) {
634#ifndef QT_NO_CSSPARSER
635 QCss::Parser parser(nodes.constLast()->text);
636 QCss::StyleSheet sheet;
637 sheet.origin = QCss::StyleSheetOrigin_Author;
638 parser.parse(&sheet, Qt::CaseInsensitive);
639 inlineStyleSheets.append(sheet);
640 resolveStyleSheetImports(sheet);
648 while (p &&
at(p
).tag.size() == 0)
654 node->tag = parseWord().toLower();
659 node->displayMode = elem->displayMode;
664 node->attributes.clear();
666 if (pos < len && txt.at(pos).isSpace())
667 node->attributes = parseAttributes();
675#ifndef QT_NO_CSSPARSER
676 const int nodeIndex = nodes.size() - 1;
677 node->applyCssDeclarations(declarationsForNode(nodeIndex), resourceProvider);
679 applyAttributes(node->attributes);
682 bool tagClosed =
false;
683 while (pos < len && txt.at(pos) != u'>') {
684 if (txt.at(pos) == u'/')
697 if (pos < len - 1 && txt.at(pos) == u'\n')
711 QString tag = parseWord().toLower().trimmed();
713 QChar c = txt.at(pos++);
721 &&
at(p - 1
).tag == tag
725 while (p &&
at(p
).tag != tag)
742 if (at(last()).text.endsWith(u'\n'))
743 nodes[last()]->text.chop(1);
754 if (hasPrefix(u'-') && hasPrefix(u'-', 1)) {
757 int end = txt.indexOf(
"-->"_L1, pos);
758 pos = (end >= 0 ? end + 3 :
len);
762 QChar c = txt.at(pos++);
771 QChar resolved = resolveEntity(entity);
772 if (!resolved.isNull())
773 return QString(resolved);
775 if (entity.size() > 1 && entity.at(0) == u'#') {
776 entity = entity.mid(1);
781 if (entity.at(0).toLower() == u'x') {
782 entity = entity.mid(1);
786 uint uc = entity.toUInt(&ok, base);
790 return QStringView{QChar::fromUcs4(uc)}.toString();
799 const int recover =
pos;
802 QChar c = txt.at(pos++);
803 if (c.isSpace() ||
pos - recover > 9) {
811 const QStringView entity = QStringView(txt).mid(recover, entityLen);
812 QString parsedEntity = parseEntity(entity);
813 if (!parsedEntity.isNull()) {
826 if (hasPrefix(u'\"')) {
829 QChar c = txt.at(pos++);
833 word += parseEntity();
837 }
else if (hasPrefix(u'\'')) {
840 QChar c = txt.at(pos++);
842 if (c == u'\'' && (txt.size() > 1 && txt.at(pos - 2) != u'\\'))
849 QChar c = txt.at(pos++);
850 if (c == u'>' || (c == u'/' && hasPrefix(u'>'))
851 || c == u'<' || c == u'=' || c.isSpace()) {
856 word += parseEntity();
880 nodes.insert(nodes.size() - 1,
new QTextHtmlParserNode);
881 nodes.insert(nodes.size() - 1,
new QTextHtmlParserNode);
886 table->tag =
"table"_L1;
887 table->children.append(nodes.size() - 2);
890 row->parent = nodes.size() - 3;
894 p = nodes.size() - 2;
905 nodes.insert(nodes.size() - 1,
new QTextHtmlParserNode);
909 table->tag =
"table"_L1;
910 p = nodes.size() - 2;
958 nodes[p]->children.append(nodes.size() - 1);
987 charFormat = parent->charFormat;
990 blockFormat.setLayoutDirection(Qt::LeftToRight);
991 else if (parent->blockFormat.hasProperty(QTextFormat::LayoutDirection))
992 blockFormat.setLayoutDirection(parent->blockFormat.layoutDirection());
994 if (parent->displayMode == QTextHtmlElement::DisplayNone)
995 displayMode = QTextHtmlElement::DisplayNone;
998 if (parent->blockFormat.hasProperty(QTextFormat::BlockAlignment))
999 blockFormat.setAlignment(parent->blockFormat.alignment());
1001 blockFormat.clearProperty(QTextFormat::BlockAlignment);
1007 if ((parent->id != Html_tr || !isTableCell())
1008 && (displayMode != QTextHtmlElement::DisplayInline || parent->displayMode != QTextHtmlElement::DisplayInline)
1009 && (parent->id == Html_body || displayMode != QTextHtmlElement::DisplayBlock || parent->displayMode != QTextHtmlElement::DisplayBlock)
1011 charFormat.clearProperty(QTextFormat::BackgroundBrush);
1014 listStyle = parent->listStyle;
1017 charFormat.clearProperty(QTextFormat::AnchorName);
1025 cssFloat = QTextFrameFormat::InFlow;
1027 for (
int i = 0; i < 4; ++i)
1033 for (
int i = 0; i < attributes.size(); i += 2) {
1034 const QString key = attributes.at(i);
1035 if (key.compare(
"href"_L1, Qt::CaseInsensitive) == 0
1036 && !attributes.at(i + 1).isEmpty()) {
1040 charFormat.setAnchor(
true);
1043 charFormat.setProperty(QTextFormat::FontSizeAdjustment,
int(1));
1046 charFormat.setProperty(QTextFormat::FontSizeAdjustment,
int(-1));
1049 charFormat.setProperty(QTextFormat::FontSizeAdjustment,
int(3));
1054 charFormat.setProperty(QTextFormat::FontSizeAdjustment,
int(2));
1059 charFormat.setProperty(QTextFormat::FontSizeAdjustment,
int(1));
1064 charFormat.setProperty(QTextFormat::FontSizeAdjustment,
int(0));
1069 charFormat.setProperty(QTextFormat::FontSizeAdjustment,
int(-1));
1094 text = QChar(QChar::LineSeparator);
1105 blockFormat.setProperty(QTextFormat::BlockQuoteLevel, 1);
1118#ifndef QT_NO_CSSPARSER
1121 for (
int i = 0; i < cssValues.size(); ++i) {
1122 if (cssValues.at(i).type == QCss::Value::KnownIdentifier) {
1123 switch (
static_cast<QCss::KnownValue>(cssValues.at(i).variant.toInt())) {
1124 case QCss::Value_None: hasOwnListStyle =
true; listStyle = QTextListFormat::ListStyleUndefined;
break;
1125 case QCss::Value_Disc: hasOwnListStyle =
true; listStyle = QTextListFormat::ListDisc;
break;
1126 case QCss::Value_Square: hasOwnListStyle =
true; listStyle = QTextListFormat::ListSquare;
break;
1127 case QCss::Value_Circle: hasOwnListStyle =
true; listStyle = QTextListFormat::ListCircle;
break;
1128 case QCss::Value_Decimal: hasOwnListStyle =
true; listStyle = QTextListFormat::ListDecimal;
break;
1129 case QCss::Value_LowerAlpha: hasOwnListStyle =
true; listStyle = QTextListFormat::ListLowerAlpha;
break;
1130 case QCss::Value_UpperAlpha: hasOwnListStyle =
true; listStyle = QTextListFormat::ListUpperAlpha;
break;
1131 case QCss::Value_LowerRoman: hasOwnListStyle =
true; listStyle = QTextListFormat::ListLowerRoman;
break;
1132 case QCss::Value_UpperRoman: hasOwnListStyle =
true; listStyle = QTextListFormat::ListUpperRoman;
break;
1138 if (id == Html_li && hasOwnListStyle)
1139 blockFormat.setProperty(QTextFormat::ListStyle, listStyle);
1145 case QCss::BorderStyle::BorderStyle_Dotted:
1146 return QTextFrameFormat::BorderStyle::BorderStyle_Dotted;
1147 case QCss::BorderStyle::BorderStyle_Dashed:
1148 return QTextFrameFormat::BorderStyle::BorderStyle_Dashed;
1149 case QCss::BorderStyle::BorderStyle_Solid:
1150 return QTextFrameFormat::BorderStyle::BorderStyle_Solid;
1151 case QCss::BorderStyle::BorderStyle_Double:
1152 return QTextFrameFormat::BorderStyle::BorderStyle_Double;
1153 case QCss::BorderStyle::BorderStyle_DotDash:
1154 return QTextFrameFormat::BorderStyle::BorderStyle_DotDash;
1155 case QCss::BorderStyle::BorderStyle_DotDotDash:
1156 return QTextFrameFormat::BorderStyle::BorderStyle_DotDotDash;
1157 case QCss::BorderStyle::BorderStyle_Groove:
1158 return QTextFrameFormat::BorderStyle::BorderStyle_Groove;
1159 case QCss::BorderStyle::BorderStyle_Ridge:
1160 return QTextFrameFormat::BorderStyle::BorderStyle_Ridge;
1161 case QCss::BorderStyle::BorderStyle_Inset:
1162 return QTextFrameFormat::BorderStyle::BorderStyle_Inset;
1163 case QCss::BorderStyle::BorderStyle_Outset:
1164 return QTextFrameFormat::BorderStyle::BorderStyle_Outset;
1165 case QCss::BorderStyle::BorderStyle_Unknown:
1166 case QCss::BorderStyle::BorderStyle_None:
1167 case QCss::BorderStyle::BorderStyle_Native:
1168 return QTextFrameFormat::BorderStyle::BorderStyle_None;
1169 case QCss::BorderStyle::NumKnownBorderStyles:
1177 return static_cast<QTextFrameFormat::BorderStyle>(-1);
1180void QTextHtmlParserNode::applyCssDeclarations(
const QList<QCss::Declaration> &declarations,
const QTextDocument *resourceProvider)
1182 QCss::ValueExtractor extractor(declarations);
1183 extractor.extractBox(margin, padding);
1185 auto getBorderValues = [&extractor](qreal *borderWidth, QBrush *borderBrush, QTextFrameFormat::BorderStyle *borderStyles) {
1186 QCss::BorderStyle cssStyles[4];
1189 for (
int i = 0; i < 4; ++i) {
1190 cssStyles[i] = QCss::BorderStyle_None;
1197 bool hit = extractor.extractBorder(cssBorder, borderBrush, cssStyles, cssRadii);
1198 for (
int i = 0; i < 4; ++i) {
1199 borderStyles[i] = toQTextFrameFormat(cssStyles[i]);
1200 borderWidth[i] =
static_cast<qreal>(cssBorder[i]);
1205 if (id == Html_td || id == Html_th)
1206 getBorderValues(tableCellBorder, tableCellBorderBrush, tableCellBorderStyle);
1208 for (
int i = 0; i < declarations.size(); ++i) {
1209 const QCss::Declaration &decl = declarations.at(i);
1210 if (decl.d->values.isEmpty())
continue;
1212 QCss::KnownValue identifier = QCss::UnknownValue;
1213 if (decl.d->values.constFirst().type == QCss::Value::KnownIdentifier)
1214 identifier =
static_cast<QCss::KnownValue>(decl.d->values.constFirst().variant.toInt());
1216 switch (decl.d->propertyId) {
1217 case QCss::BorderColor: {
1218 QBrush bordersBrush[4];
1219 decl.brushValues(bordersBrush);
1220 if (bordersBrush[0].color().isValid())
1221 borderBrush = bordersBrush[0];
1224 case QCss::BorderStyles:
1225 if (decl.styleValue() != QCss::BorderStyle_Unknown && decl.styleValue() != QCss::BorderStyle_Native)
1226 borderStyle =
static_cast<QTextFrameFormat::BorderStyle>(decl.styleValue() - 1);
1228 case QCss::BorderWidth: {
1230 extractor.lengthValues(decl, borders);
1231 tableBorder = borders[0];
1234 case QCss::Border: {
1236 QBrush tblBorderBrush[4];
1237 QTextFrameFormat::BorderStyle tblBorderStyle[4];
1238 if (getBorderValues(tblBorder, tblBorderBrush, tblBorderStyle)) {
1239 tableBorder = tblBorder[0];
1240 if (tblBorderBrush[0].color().isValid())
1241 borderBrush = tblBorderBrush[0];
1242 if (tblBorderStyle[0] !=
static_cast<QTextFrameFormat::BorderStyle>(-1))
1243 borderStyle = tblBorderStyle[0];
1247 case QCss::BorderCollapse:
1250 case QCss::Color: charFormat.setForeground(decl.colorValue());
break;
1252 cssFloat = QTextFrameFormat::InFlow;
1253 switch (identifier) {
1254 case QCss::Value_Left: cssFloat = QTextFrameFormat::FloatLeft;
break;
1255 case QCss::Value_Right: cssFloat = QTextFrameFormat::FloatRight;
break;
1259 case QCss::QtBlockIndent:
1260 blockFormat.setIndent(decl.d->values.constFirst().variant.toInt());
1262 case QCss::QtLineHeightType: {
1263 QString lineHeightTypeName = decl.d->values.constFirst().variant.toString();
1264 QTextBlockFormat::LineHeightTypes lineHeightType;
1265 if (lineHeightTypeName.compare(
"proportional"_L1, Qt::CaseInsensitive) == 0)
1266 lineHeightType = QTextBlockFormat::ProportionalHeight;
1267 else if (lineHeightTypeName.compare(
"fixed"_L1, Qt::CaseInsensitive) == 0)
1268 lineHeightType = QTextBlockFormat::FixedHeight;
1269 else if (lineHeightTypeName.compare(
"minimum"_L1, Qt::CaseInsensitive) == 0)
1270 lineHeightType = QTextBlockFormat::MinimumHeight;
1271 else if (lineHeightTypeName.compare(
"line-distance"_L1, Qt::CaseInsensitive) == 0)
1272 lineHeightType = QTextBlockFormat::LineDistanceHeight;
1274 lineHeightType = QTextBlockFormat::SingleHeight;
1276 if (hasLineHeightMultiplier) {
1277 qreal lineHeight = blockFormat.lineHeight() / 100.0;
1278 blockFormat.setProperty(QTextBlockFormat::LineHeight, lineHeight);
1281 blockFormat.setProperty(QTextBlockFormat::LineHeightType, lineHeightType);
1282 hasOwnLineHeightType =
true;
1285 case QCss::LineHeight: {
1287 QTextBlockFormat::LineHeightTypes lineHeightType;
1288 if (decl.realValue(&lineHeight,
"px")) {
1289 lineHeightType = QTextBlockFormat::MinimumHeight;
1292 QCss::Value cssValue = decl.d->values.constFirst();
1293 QString value = cssValue.toString();
1294 lineHeight = value.toDouble(&ok);
1296 if (!hasOwnLineHeightType && cssValue.type == QCss::Value::Number) {
1297 lineHeight *= 100.0;
1298 hasLineHeightMultiplier =
true;
1300 lineHeightType = QTextBlockFormat::ProportionalHeight;
1303 lineHeightType = QTextBlockFormat::SingleHeight;
1308 if (hasOwnLineHeightType)
1309 lineHeightType = QTextBlockFormat::LineHeightTypes(blockFormat.lineHeightType());
1311 blockFormat.setLineHeight(lineHeight, lineHeightType);
1314 case QCss::TextIndent: {
1316 if (decl.realValue(&indent,
"px"))
1317 blockFormat.setTextIndent(indent);
1319 case QCss::QtListIndent:
1320 if (decl.intValue(&cssListIndent))
1321 hasCssListIndent =
true;
1323 case QCss::QtParagraphType:
1324 if (decl.d->values.constFirst().variant.toString().compare(
"empty"_L1, Qt::CaseInsensitive) == 0)
1325 isEmptyParagraph =
true;
1327 case QCss::QtTableType:
1328 if (decl.d->values.constFirst().variant.toString().compare(
"frame"_L1, Qt::CaseInsensitive) == 0)
1330 else if (decl.d->values.constFirst().variant.toString().compare(
"root"_L1, Qt::CaseInsensitive) == 0) {
1335 case QCss::QtUserState:
1336 userState = decl.d->values.constFirst().variant.toInt();
1338 case QCss::Whitespace:
1339 switch (identifier) {
1348 case QCss::VerticalAlignment:
1349 switch (identifier) {
1350 case QCss::Value_Sub: charFormat.setVerticalAlignment(QTextCharFormat::AlignSubScript);
break;
1351 case QCss::Value_Super: charFormat.setVerticalAlignment(QTextCharFormat::AlignSuperScript);
break;
1352 case QCss::Value_Middle: charFormat.setVerticalAlignment(QTextCharFormat::AlignMiddle);
break;
1353 case QCss::Value_Top: charFormat.setVerticalAlignment(QTextCharFormat::AlignTop);
break;
1354 case QCss::Value_Bottom: charFormat.setVerticalAlignment(QTextCharFormat::AlignBottom);
break;
1355 default: charFormat.setVerticalAlignment(QTextCharFormat::AlignNormal);
break;
1358 case QCss::PageBreakBefore:
1359 switch (identifier) {
1360 case QCss::Value_Always: blockFormat.setPageBreakPolicy(blockFormat.pageBreakPolicy() | QTextFormat::PageBreak_AlwaysBefore);
break;
1361 case QCss::Value_Auto: blockFormat.setPageBreakPolicy(blockFormat.pageBreakPolicy() & ~QTextFormat::PageBreak_AlwaysBefore);
break;
1365 case QCss::PageBreakAfter:
1366 switch (identifier) {
1367 case QCss::Value_Always: blockFormat.setPageBreakPolicy(blockFormat.pageBreakPolicy() | QTextFormat::PageBreak_AlwaysAfter);
break;
1368 case QCss::Value_Auto: blockFormat.setPageBreakPolicy(blockFormat.pageBreakPolicy() & ~QTextFormat::PageBreak_AlwaysAfter);
break;
1372 case QCss::TextUnderlineStyle:
1373 switch (identifier) {
1374 case QCss::Value_None: charFormat.setUnderlineStyle(QTextCharFormat::NoUnderline);
break;
1375 case QCss::Value_Solid: charFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
break;
1376 case QCss::Value_Dashed: charFormat.setUnderlineStyle(QTextCharFormat::DashUnderline);
break;
1377 case QCss::Value_Dotted: charFormat.setUnderlineStyle(QTextCharFormat::DotLine);
break;
1378 case QCss::Value_DotDash: charFormat.setUnderlineStyle(QTextCharFormat::DashDotLine);
break;
1379 case QCss::Value_DotDotDash: charFormat.setUnderlineStyle(QTextCharFormat::DashDotDotLine);
break;
1380 case QCss::Value_Wave: charFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
break;
1384 case QCss::TextDecorationColor: charFormat.setUnderlineColor(decl.colorValue());
break;
1385 case QCss::ListStyleType:
1386 case QCss::ListStyle:
1387 setListStyle(decl.d->values);
1389 case QCss::QtListNumberPrefix:
1390 textListNumberPrefix = decl.d->values.constFirst().variant.toString();
1392 case QCss::QtListNumberSuffix:
1393 textListNumberSuffix = decl.d->values.constFirst().variant.toString();
1395 case QCss::TextAlignment:
1396 switch (identifier) {
1397 case QCss::Value_Left: blockFormat.setAlignment(Qt::AlignLeft);
break;
1398 case QCss::Value_Center: blockFormat.setAlignment(Qt::AlignCenter);
break;
1399 case QCss::Value_Right: blockFormat.setAlignment(Qt::AlignRight);
break;
1404 case QCss::QtForegroundTextureCacheKey:
1406 if (resourceProvider !=
nullptr && QTextDocumentPrivate::get(resourceProvider) !=
nullptr) {
1408 qint64 searchKey = decl.d->values.constFirst().variant.toLongLong(&ok);
1410 applyForegroundImage(searchKey, resourceProvider);
1414 case QCss::QtStrokeColor:
1416 QPen pen = charFormat.textOutline();
1417 pen.setStyle(Qt::SolidLine);
1418 pen.setColor(decl.colorValue());
1419 charFormat.setTextOutline(pen);
1422 case QCss::QtStrokeWidth:
1425 if (decl.realValue(&width,
"px")) {
1426 QPen pen = charFormat.textOutline();
1427 pen.setWidthF(width);
1428 charFormat.setTextOutline(pen);
1432 case QCss::QtStrokeLineCap:
1434 QPen pen = charFormat.textOutline();
1435 switch (identifier) {
1436 case QCss::Value_SquareCap: pen.setCapStyle(Qt::SquareCap);
break;
1437 case QCss::Value_FlatCap: pen.setCapStyle(Qt::FlatCap);
break;
1438 case QCss::Value_RoundCap: pen.setCapStyle(Qt::RoundCap);
break;
1441 charFormat.setTextOutline(pen);
1444 case QCss::QtStrokeLineJoin:
1446 QPen pen = charFormat.textOutline();
1447 switch (identifier) {
1448 case QCss::Value_MiterJoin: pen.setJoinStyle(Qt::MiterJoin);
break;
1449 case QCss::Value_BevelJoin: pen.setJoinStyle(Qt::BevelJoin);
break;
1450 case QCss::Value_RoundJoin: pen.setJoinStyle(Qt::RoundJoin);
break;
1451 case QCss::Value_SvgMiterJoin: pen.setJoinStyle(Qt::SvgMiterJoin);
break;
1454 charFormat.setTextOutline(pen);
1457 case QCss::QtStrokeMiterLimit:
1460 if (decl.realValue(&miterLimit)) {
1461 QPen pen = charFormat.textOutline();
1462 pen.setMiterLimit(miterLimit);
1463 charFormat.setTextOutline(pen);
1467 case QCss::QtStrokeDashArray:
1469 QList<qreal> dashes = decl.dashArray();
1470 if (!dashes.empty()) {
1471 QPen pen = charFormat.textOutline();
1472 pen.setDashPattern(dashes);
1473 charFormat.setTextOutline(pen);
1477 case QCss::QtStrokeDashOffset:
1480 if (decl.realValue(&dashOffset)) {
1481 QPen pen = charFormat.textOutline();
1482 pen.setDashOffset(dashOffset);
1483 charFormat.setTextOutline(pen);
1487 case QCss::QtForeground:
1489 QBrush brush = decl.brushValue();
1490 charFormat.setForeground(brush);
1493 case QCss::MaximumWidth:
1495 auto imageFormat = charFormat.toImageFormat();
1496 imageFormat.setMaximumWidth(extractor.textLength(decl));
1497 charFormat = imageFormat;
1505 int adjustment = -255;
1506 extractor.extractFont(&f, &adjustment);
1507 if (f.pixelSize() > INT32_MAX / 2)
1508 f.setPixelSize(INT32_MAX / 2);
1509 charFormat.setFont(f, QTextCharFormat::FontPropertiesSpecifiedOnly);
1511 if (adjustment >= -1)
1512 charFormat.setProperty(QTextFormat::FontSizeAdjustment, adjustment);
1515 Qt::Alignment ignoredAlignment;
1516 QCss::Repeat ignoredRepeat;
1519 QCss::Origin ignoredOrigin, ignoredClip;
1520 QCss::Attachment ignoredAttachment;
1521 extractor.extractBackground(&bgBrush, &bgImage, &ignoredRepeat, &ignoredAlignment,
1522 &ignoredOrigin, &ignoredAttachment, &ignoredClip);
1524 if (!bgImage.isEmpty() && resourceProvider) {
1525 applyBackgroundImage(bgImage, resourceProvider);
1526 }
else if (bgBrush.style() != Qt::NoBrush) {
1527 charFormat.setBackground(bgBrush);
1529 blockFormat.setProperty(QTextFormat::BackgroundBrush, bgBrush);
1538 const QTextDocumentPrivate *priv = QTextDocumentPrivate::get(resourceProvider);
1539 for (
int i = 0; i < priv->formats.numFormats(); ++i) {
1540 QTextCharFormat format = priv->formats.charFormat(i);
1541 if (format.isValid()) {
1542 QBrush brush = format.foreground();
1543 if (brush.style() == Qt::TexturePattern) {
1544 const bool isPixmap = qHasPixmapTexture(brush);
1546 if (isPixmap && QCoreApplication::instance()->thread() != QThread::currentThread()) {
1547 qWarning(
"Can't apply QPixmap outside of GUI thread");
1551 const qint64 cacheKey = isPixmap ? brush.texture().cacheKey() : brush.textureImage().cacheKey();
1552 if (cacheKey == searchKey) {
1555 b.setTexture(brush.texture());
1557 b.setTextureImage(brush.textureImage());
1558 b.setStyle(Qt::TexturePattern);
1559 charFormat.setForeground(b);
1569 if (!url.isEmpty() && resourceProvider) {
1570 QVariant val = resourceProvider->resource(QTextDocument::ImageResource, url);
1572 if (QCoreApplication::instance()->thread() != QThread::currentThread()) {
1574 if (val.userType() == QMetaType::QImage) {
1575 QImage image = qvariant_cast<QImage>(val);
1576 charFormat.setBackground(image);
1577 }
else if (val.userType() == QMetaType::QByteArray) {
1579 if (image.loadFromData(val.toByteArray())) {
1580 charFormat.setBackground(image);
1584 if (val.userType() == QMetaType::QImage || val.userType() == QMetaType::QPixmap) {
1585 charFormat.setBackground(qvariant_cast<QPixmap>(val));
1586 }
else if (val.userType() == QMetaType::QByteArray) {
1588 if (pm.loadFromData(val.toByteArray())) {
1589 charFormat.setBackground(pm);
1595 charFormat.setProperty(QTextFormat::BackgroundImageUrl, url);
1600 for (
int i = 0; i < text.size(); ++i)
1601 if (!text.at(i).isSpace() || text.at(i) == QChar::LineSeparator)
1609 int val = value.toInt(&ok);
1619 qreal val = value.toDouble(&ok);
1629 qreal realVal = valueStr.toDouble(&ok);
1631 *width = QTextLength(QTextLength::FixedLength, realVal);
1633 auto value = QStringView(valueStr).trimmed();
1634 if (!value.isEmpty() && value.endsWith(u'%')) {
1635 value.truncate(value.size() - 1);
1636 realVal = value.toDouble(&ok);
1638 *width = QTextLength(QTextLength::PercentageLength, realVal);
1643#ifndef QT_NO_CSSPARSER
1646 const QString css =
"* {"_L1 + value + u'}';
1647 QCss::Parser parser(css);
1648 QCss::StyleSheet sheet;
1649 parser.parse(&sheet, Qt::CaseInsensitive);
1650 if (sheet.styleRules.size() != 1)
return;
1651 applyCssDeclarations(sheet.styleRules.at(0).declarations, resourceProvider);
1661 if (hasPrefix(u'>') || hasPrefix(u'/'))
1663 QString key = parseWord().toLower();
1664 QString value =
"1"_L1;
1665 if (key.size() == 0)
1668 if (hasPrefix(u'=')){
1671 value = parseWord();
1673 if (value.size() == 0)
1675 attrs << key << value;
1684 bool seenQt3Richtext =
false;
1688 if (attributes.size() % 2 == 1)
1693 for (
int i = 0; i < attributes.size(); i += 2) {
1694 QString key = attributes.at(i);
1695 QString value = attributes.at(i + 1);
1700 if (key ==
"size"_L1 && value.size()) {
1701 int n = value.toInt();
1702 if (value.at(0) != u'+' && value.at(0) != u'-')
1704 node->charFormat.setProperty(QTextFormat::FontSizeAdjustment, n);
1705 }
else if (key ==
"face"_L1) {
1706 if (value.contains(u',')) {
1707 QStringList families;
1708 for (
auto family : value.tokenize(u','))
1709 families << family.trimmed().toString();
1710 node->charFormat.setFontFamilies(families);
1712 node->charFormat.setFontFamilies(QStringList(value));
1714 }
else if (key ==
"color"_L1) {
1715 QColor c = QColor::fromString(value);
1717 qWarning(
"QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
1718 node->charFormat.setForeground(c);
1723 if (key ==
"type"_L1) {
1724 node->hasOwnListStyle =
true;
1725 if (value ==
"1"_L1) {
1726 node->listStyle = QTextListFormat::ListDecimal;
1727 }
else if (value ==
"a"_L1) {
1728 node->listStyle = QTextListFormat::ListLowerAlpha;
1729 }
else if (value ==
"A"_L1) {
1730 node->listStyle = QTextListFormat::ListUpperAlpha;
1731 }
else if (value ==
"i"_L1) {
1732 node->listStyle = QTextListFormat::ListLowerRoman;
1733 }
else if (value ==
"I"_L1) {
1734 node->listStyle = QTextListFormat::ListUpperRoman;
1736 value =
std::move(value).toLower();
1737 if (value ==
"square"_L1)
1738 node->listStyle = QTextListFormat::ListSquare;
1739 else if (value ==
"disc"_L1)
1740 node->listStyle = QTextListFormat::ListDisc;
1741 else if (value ==
"circle"_L1)
1742 node->listStyle = QTextListFormat::ListCircle;
1743 else if (value ==
"none"_L1)
1744 node->listStyle = QTextListFormat::ListStyleUndefined;
1746 }
else if (key ==
"start"_L1) {
1751 if (key ==
"class"_L1) {
1752 if (value ==
"unchecked"_L1)
1753 node->blockFormat.setMarker(QTextBlockFormat::MarkerType::Unchecked);
1754 else if (value ==
"checked"_L1)
1755 node->blockFormat.setMarker(QTextBlockFormat::MarkerType::Checked);
1759 if (key ==
"href"_L1)
1760 node->charFormat.setAnchorHref(value);
1761 else if (key ==
"name"_L1)
1762 node->charFormat.setAnchorNames({value});
1765 if (key ==
"src"_L1 || key ==
"source"_L1) {
1766 node->imageName = value;
1767 }
else if (key ==
"width"_L1) {
1768 node->imageWidth = -2;
1769 setFloatAttribute(&node->imageWidth, value);
1770 }
else if (key ==
"height"_L1) {
1771 node->imageHeight = -2;
1772 setFloatAttribute(&node->imageHeight, value);
1773 }
else if (key ==
"alt"_L1) {
1774 node->imageAlt = value;
1775 }
else if (key ==
"title"_L1) {
1781 if (key ==
"bgcolor"_L1) {
1782 QColor c = QColor::fromString(value);
1784 qWarning(
"QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
1785 node->charFormat.setBackground(c);
1786 }
else if (key ==
"background"_L1) {
1787 node->applyBackgroundImage(value, resourceProvider);
1792 if (key ==
"width"_L1) {
1793 setWidthAttribute(&node->width, value);
1794 }
else if (key ==
"bgcolor"_L1) {
1795 QColor c = QColor::fromString(value);
1797 qWarning(
"QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
1798 node->charFormat.setBackground(c);
1799 }
else if (key ==
"background"_L1) {
1800 node->applyBackgroundImage(value, resourceProvider);
1801 }
else if (key ==
"rowspan"_L1) {
1804 }
else if (key ==
"colspan"_L1) {
1811 if (key ==
"border"_L1 && !node->tableBorder) {
1812 setFloatAttribute(&node->tableBorder, value);
1813 }
else if (key ==
"bgcolor"_L1) {
1814 QColor c = QColor::fromString(value);
1816 qWarning(
"QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
1817 node->charFormat.setBackground(c);
1818 }
else if (key ==
"bordercolor"_L1) {
1819 QColor c = QColor::fromString(value);
1821 qWarning(
"QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
1822 node->borderBrush = c;
1823 }
else if (key ==
"background"_L1) {
1824 node->applyBackgroundImage(value, resourceProvider);
1825 }
else if (key ==
"cellspacing"_L1) {
1826 setFloatAttribute(&node->tableCellSpacing, value);
1827 }
else if (key ==
"cellpadding"_L1) {
1828 setFloatAttribute(&node->tableCellPadding, value);
1829 }
else if (key ==
"width"_L1) {
1830 setWidthAttribute(&node->width, value);
1831 }
else if (key ==
"height"_L1) {
1832 setWidthAttribute(&node->height, value);
1836 if (key ==
"name"_L1 && value ==
"qrichtext"_L1)
1837 seenQt3Richtext =
true;
1839 if (key ==
"content"_L1 && value ==
"1"_L1 && seenQt3Richtext)
1843 if (key ==
"width"_L1)
1844 setWidthAttribute(&node->width, value);
1847 if (key ==
"href"_L1)
1849 else if (key ==
"type"_L1)
1853 if (key ==
"class"_L1 && value.startsWith(
"language-"_L1))
1854 node->blockFormat.setProperty(QTextFormat::BlockCodeLanguage, value.mid(9));
1860 if (key ==
"style"_L1) {
1861#ifndef QT_NO_CSSPARSER
1862 node->parseStyleAttribute(value, resourceProvider);
1864 }
else if (key ==
"align"_L1) {
1865 value =
std::move(value).toLower();
1866 bool alignmentSet =
true;
1868 if (value ==
"left"_L1)
1869 node->blockFormat.setAlignment(Qt::AlignLeft|Qt::AlignAbsolute);
1870 else if (value ==
"right"_L1)
1871 node->blockFormat.setAlignment(Qt::AlignRight|Qt::AlignAbsolute);
1872 else if (value ==
"center"_L1)
1873 node->blockFormat.setAlignment(Qt::AlignHCenter);
1874 else if (value ==
"justify"_L1)
1875 node->blockFormat.setAlignment(Qt::AlignJustify);
1877 alignmentSet =
false;
1882 if (node->blockFormat.alignment() & Qt::AlignLeft)
1883 node->cssFloat = QTextFrameFormat::FloatLeft;
1884 else if (node->blockFormat.alignment() & Qt::AlignRight)
1885 node->cssFloat = QTextFrameFormat::FloatRight;
1886 }
else if (value ==
"middle"_L1) {
1887 node->charFormat.setVerticalAlignment(QTextCharFormat::AlignMiddle);
1888 }
else if (value ==
"top"_L1) {
1889 node->charFormat.setVerticalAlignment(QTextCharFormat::AlignTop);
1892 }
else if (key ==
"valign"_L1) {
1893 value =
std::move(value).toLower();
1894 if (value ==
"top"_L1)
1895 node->charFormat.setVerticalAlignment(QTextCharFormat::AlignTop);
1896 else if (value ==
"middle"_L1)
1897 node->charFormat.setVerticalAlignment(QTextCharFormat::AlignMiddle);
1898 else if (value ==
"bottom"_L1)
1899 node->charFormat.setVerticalAlignment(QTextCharFormat::AlignBottom);
1900 }
else if (key ==
"dir"_L1) {
1901 value =
std::move(value).toLower();
1902 if (value ==
"ltr"_L1)
1903 node->blockFormat.setLayoutDirection(Qt::LeftToRight);
1904 else if (value ==
"rtl"_L1)
1905 node->blockFormat.setLayoutDirection(Qt::RightToLeft);
1906 }
else if (key ==
"title"_L1) {
1907 node->charFormat.setToolTip(value);
1908 }
else if (key ==
"id"_L1) {
1909 node->charFormat.setAnchor(
true);
1910 node->charFormat.setAnchorNames({value});
1914#ifndef QT_NO_CSSPARSER
1915 if (resourceProvider && !linkHref.isEmpty() && linkType ==
"text/css"_L1)
1916 importStyleSheet(linkHref);
1920#ifndef QT_NO_CSSPARSER
1925 : parser(parser) { nameCaseSensitivity = Qt::CaseInsensitive; }
1928 QString
attributeValue(NodePtr node,
const QCss::AttributeSelector &aSelector)
const override;
1942 return QStringList(parser
->at(node.id
).tag.toLower());
1947#ifndef QT_NO_CSSPARSER
1949static inline int findAttribute(
const QStringList &attributes,
const QString &name)
1953 idx = attributes.indexOf(name, idx + 1);
1954 }
while (idx != -1 && (idx % 2 == 1));
1960 const QStringList &attributes = parser
->at(node.id
).attributes;
1961 const int idx = findAttribute(attributes, aSelector.name);
1964 return attributes.at(idx + 1);
1969 const QStringList &attributes = parser
->at(node.id
).attributes;
1970 return !attributes.isEmpty();
1975 return node.id == 0;
1983 parent.id = parser
->at(node.id
).parent;
1999 int parent = parser
->at(node.id
).parent;
2002 const int childIdx = parser
->at(parent
).children.indexOf(node.id);
2005 sibling.id = parser
->at(parent
).children.at(childIdx - 1);
2013void QTextHtmlParser::resolveStyleSheetImports(
const QCss::StyleSheet &sheet)
2015 for (
int i = 0; i < sheet.importRules.size(); ++i) {
2016 const QCss::ImportRule &rule = sheet.importRules.at(i);
2017 if (rule.media.isEmpty() || rule.media.contains(
"screen"_L1, Qt::CaseInsensitive))
2018 importStyleSheet(rule.href);
2024 if (!resourceProvider)
2026 for (
int i = 0; i < externalStyleSheets.size(); ++i)
2027 if (externalStyleSheets.at(i).url == href)
2030 QVariant res = resourceProvider->resource(QTextDocument::StyleSheetResource, href);
2032 if (res.userType() == QMetaType::QString) {
2033 css = res.toString();
2034 }
else if (res.userType() == QMetaType::QByteArray) {
2036 css = QString::fromUtf8(res.toByteArray());
2038 if (!css.isEmpty()) {
2039 QCss::Parser parser(css);
2040 QCss::StyleSheet sheet;
2041 parser.parse(&sheet, Qt::CaseInsensitive);
2042 externalStyleSheets.append(ExternalStyleSheet(href, sheet));
2043 resolveStyleSheetImports(sheet);
2049 QList<QCss::Declaration> decls;
2050 QCss::Declaration decl;
2055 bool needsUnderline = (node
.id ==
Html_u) ?
true :
false;
2057 for (
int i = 0; i < node.attributes.size(); i += 2) {
2058 const QString key = node.attributes.at(i);
2059 if (key.compare(
"href"_L1, Qt::CaseInsensitive) == 0
2060 && !node.attributes.at(i + 1).isEmpty()) {
2061 needsUnderline =
true;
2062 decl.d->property =
"color"_L1;
2063 decl.d->propertyId = QCss::Color;
2064 val.type = QCss::Value::Function;
2065 val.variant = QStringList() <<
"palette"_L1 <<
"link"_L1;
2066 decl.d->values = QList<QCss::Value> { val };
2067 decl.d->inheritable =
true;
2073 if (needsUnderline) {
2074 decl = QCss::Declaration();
2075 decl.d->property =
"text-decoration"_L1;
2076 decl.d->propertyId = QCss::TextDecoration;
2077 val.type = QCss::Value::KnownIdentifier;
2078 val.variant = QVariant(QCss::Value_Underline);
2079 decl.d->values = QList<QCss::Value> { val };
2080 decl.d->inheritable =
true;
2093 decl = QCss::Declaration();
2094 decl.d->property =
"font-weight"_L1;
2095 decl.d->propertyId = QCss::FontWeight;
2096 val.type = QCss::Value::KnownIdentifier;
2097 val.variant = QVariant(QCss::Value_Bold);
2098 decl.d->values = QList<QCss::Value> { val };
2099 decl.d->inheritable =
true;
2107 decl = QCss::Declaration();
2108 decl.d->property =
"font-size"_L1;
2109 decl.d->propertyId = QCss::FontSize;
2110 decl.d->inheritable =
false;
2111 val.type = QCss::Value::KnownIdentifier;
2113 case Html_h1: val.variant = QVariant(QCss::Value_XXLarge);
break;
2114 case Html_h2: val.variant = QVariant(QCss::Value_XLarge);
break;
2115 case Html_h3:
case Html_big: val.variant = QVariant(QCss::Value_Large);
break;
2116 case Html_h4: val.variant = QVariant(QCss::Value_Medium);
break;
2117 case Html_h5:
case Html_small: val.variant = QVariant(QCss::Value_Small);
break;
2120 decl.d->values = QList<QCss::Value> { val };
2127 decl = QCss::Declaration();
2128 decl.d->property =
"text-align"_L1;
2129 decl.d->propertyId = QCss::TextAlignment;
2130 val.type = QCss::Value::KnownIdentifier;
2131 val.variant = (node.id == Html_td) ? QVariant(QCss::Value_Left) : QVariant(QCss::Value_Center);
2132 decl.d->values = QList<QCss::Value> { val };
2133 decl.d->inheritable =
true;
2137 decl = QCss::Declaration();
2138 decl.d->property =
"text-decoration"_L1;
2139 decl.d->propertyId = QCss::TextDecoration;
2140 val.type = QCss::Value::KnownIdentifier;
2141 val.variant = QVariant(QCss::Value_LineThrough);
2142 decl.d->values = QList<QCss::Value> { val };
2143 decl.d->inheritable =
true;
2152 decl = QCss::Declaration();
2153 decl.d->property =
"font-style"_L1;
2154 decl.d->propertyId = QCss::FontStyle;
2155 val.type = QCss::Value::KnownIdentifier;
2156 val.variant = QVariant(QCss::Value_Italic);
2157 decl.d->values = QList<QCss::Value> { val };
2158 decl.d->inheritable =
true;
2163 decl = QCss::Declaration();
2164 decl.d->property =
"vertical-align"_L1;
2165 decl.d->propertyId = QCss::VerticalAlignment;
2166 val.type = QCss::Value::KnownIdentifier;
2167 val.variant = (node.id == Html_sub) ? QVariant(QCss::Value_Sub) : QVariant(QCss::Value_Super);
2168 decl.d->values = QList<QCss::Value> { val };
2169 decl.d->inheritable =
true;
2174 decl = QCss::Declaration();
2175 decl.d->property =
"list-style"_L1;
2176 decl.d->propertyId = QCss::ListStyle;
2177 val.type = QCss::Value::KnownIdentifier;
2178 val.variant = (node.id == Html_ul) ? QVariant(QCss::Value_Disc) : QVariant(QCss::Value_Decimal);
2179 decl.d->values = QList<QCss::Value> { val };
2180 decl.d->inheritable =
true;
2188 decl = QCss::Declaration();
2189 decl.d->property =
"font-family"_L1;
2190 decl.d->propertyId = QCss::FontFamily;
2191 QList<QCss::Value> values;
2192 val.type = QCss::Value::String;
2193 val.variant = QFontDatabase::systemFont(QFontDatabase::FixedFont).families().constFirst();
2195 decl.d->values = values;
2196 decl.d->inheritable =
true;
2204 decl = QCss::Declaration();
2205 decl.d->property =
"whitespace"_L1;
2206 decl.d->propertyId = QCss::Whitespace;
2207 val.type = QCss::Value::KnownIdentifier;
2209 case Html_br: val.variant = QVariant(QCss::Value_PreWrap);
break;
2210 case Html_nobr: val.variant = QVariant(QCss::Value_NoWrap);
break;
2211 case Html_pre: val.variant = QVariant(QCss::Value_Pre);
break;
2214 decl.d->values = QList<QCss::Value> { val };
2215 decl.d->inheritable =
true;
2224QList<QCss::Declaration>
QTextHtmlParser::declarationsForNode(
int node)
const
2226 QList<QCss::Declaration> decls;
2231 selector.styleSheets.resize((resourceProvider ? 1 : 0)
2232 + externalStyleSheets.size()
2233 + inlineStyleSheets.size());
2234 if (resourceProvider)
2235 selector.styleSheets[idx++] = QTextDocumentPrivate::get(resourceProvider)->parsedDefaultStyleSheet;
2237 for (
int i = 0; i < externalStyleSheets.size(); ++i, ++idx)
2238 selector.styleSheets[idx] = externalStyleSheets.at(i).sheet;
2240 for (
int i = 0; i < inlineStyleSheets.size(); ++i, ++idx)
2241 selector.styleSheets[idx] = inlineStyleSheets.at(i);
2243 selector.medium = resourceProvider ? resourceProvider->metaInformation(QTextDocument::CssMedia) :
"screen"_L1;
2245 QCss::StyleSelector::NodePtr n;
2248 const char *extraPseudo =
nullptr;
2249 if (nodes.at(node)->id == Html_a && nodes.at(node)->hasHref)
2250 extraPseudo =
"link";
2252 decls = standardDeclarationForNode(*nodes.at(node));
2253 decls += selector.declarationsForNode(n, extraPseudo);
2254 n = selector.parentNode(n);
2255 while (!selector.isNullNode(n)) {
2256 QList<QCss::Declaration> inheritedDecls;
2257 inheritedDecls = selector.declarationsForNode(n, extraPseudo);
2258 for (
int i = 0; i < inheritedDecls.size(); ++i) {
2259 const QCss::Declaration &decl = inheritedDecls.at(i);
2260 if (decl.d->inheritable)
2261 decls.prepend(decl);
2263 n = selector.parentNode(n);
void parseExclamationTag()
bool nodeIsChildOf(int i, QTextHTMLElements id) const
QTextHtmlParserNode * resolveParent()
void applyAttributes(const QStringList &attributes)
int margin(int i, int mar) const
int topMargin(int i) const
const QTextHtmlParserNode & at(int i) const
QStringList parseAttributes()
int bottomMargin(int i) const
QTextHtmlParserNode * newNode(int parent)
NodePtr previousSiblingNode(NodePtr node) const override
bool isNullNode(NodePtr node) const override
QString attributeValue(NodePtr node, const QCss::AttributeSelector &aSelector) const override
bool hasAttributes(NodePtr node) const override
NodePtr duplicateNode(NodePtr node) const override
QTextHtmlStyleSelector(const QTextHtmlParser *parser)
void freeNode(NodePtr node) const override
NodePtr parentNode(NodePtr node) const override
QStringList nodeNames(NodePtr node) const override
static int findAttribute(const QStringList &attributes, const QString &name)
static bool operator<(QStringView entityStr, const QTextHtmlEntity &entity)
static bool operator<(const QTextHtmlEntity &entity, QStringView entityStr)
QList< QCss::Declaration > standardDeclarationForNode(const QTextHtmlParserNode &node)
static const QTextHtmlElement elements[Html_NumElements]
static bool operator<(QStringView str, const QTextHtmlElement &e)
static bool setFloatAttribute(qreal *destination, const QString &value)
static const QTextHtmlElement * lookupElementHelper(QStringView element)
static QTextFrameFormat::BorderStyle toQTextFrameFormat(QCss::BorderStyle cssStyle)
static void setWidthAttribute(QTextLength *width, const QString &valueStr)
static const ushort windowsLatin1ExtendedCharacters[0xA0 - 0x80]
static bool operator<(const QTextHtmlElement &e, QStringView str)
static bool setIntAttribute(int *destination, const QString &value)
static QChar resolveEntity(QStringView entity)
static QString quoteNewline(const QString &s)
bool isNotSelfNesting() const
void initializeProperties(const QTextHtmlParserNode *parent, const QTextHtmlParser *parser)
bool hasOnlyWhitespace() const
bool isNestedList(const QTextHtmlParser *parser) const
bool allowedInContext(int parentId) const
@ WhiteSpaceModeUndefined
void applyForegroundImage(qint64 cacheKey, const QTextDocument *resourceProvider)
bool mayNotHaveChildren() const