1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2016 The Qt Company Ltd. 4 ** Contact: https://www.qt.io/licensing/ 5 ** 6 ** This file is part of the QtGui module of the Qt Toolkit. 7 ** 8 ** $QT_BEGIN_LICENSE:LGPL$ 9 ** Commercial License Usage 10 ** Licensees holding valid commercial Qt licenses may use this file in 11 ** accordance with the commercial license agreement provided with the 12 ** Software or, alternatively, in accordance with the terms contained in 13 ** a written agreement between you and The Qt Company. For licensing terms 14 ** and conditions see https://www.qt.io/terms-conditions. For further 15 ** information use the contact form at https://www.qt.io/contact-us. 16 ** 17 ** GNU Lesser General Public License Usage 18 ** Alternatively, this file may be used under the terms of the GNU Lesser 19 ** General Public License version 3 as published by the Free Software 20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the 21 ** packaging of this file. Please review the following information to 22 ** ensure the GNU Lesser General Public License version 3 requirements 23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 24 ** 25 ** GNU General Public License Usage 26 ** Alternatively, this file may be used under the terms of the GNU 27 ** General Public License version 2.0 or (at your option) the GNU General 28 ** Public license version 3 or any later version approved by the KDE Free 29 ** Qt Foundation. The licenses are as published by the Free Software 30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 31 ** included in the packaging of this file. Please review the following 32 ** information to ensure the GNU General Public License requirements will 33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and 34 ** https://www.gnu.org/licenses/gpl-3.0.html. 35 ** 36 ** $QT_END_LICENSE$ 37 ** 38 ****************************************************************************/ 39 40 #ifndef QTEXTHTMLPARSER_P_H 41 #define QTEXTHTMLPARSER_P_H 42 43 // 44 // W A R N I N G 45 // ------------- 46 // 47 // This file is not part of the Qt API. It exists purely as an 48 // implementation detail. This header file may change from version to 49 // version without notice, or even be removed. 50 // 51 // We mean it. 52 // 53 54 #include <QtGui/private/qtguiglobal_p.h> 55 #include "QtCore/qvector.h" 56 #include "QtGui/qbrush.h" 57 #include "QtGui/qcolor.h" 58 #include "QtGui/qfont.h" 59 #include "QtGui/qtextdocument.h" 60 #include "QtGui/qtextcursor.h" 61 #include "private/qtextformat_p.h" 62 #include "private/qtextdocument_p.h" 63 #include "private/qcssparser_p.h" 64 65 #ifndef QT_NO_TEXTHTMLPARSER 66 67 QT_BEGIN_NAMESPACE 68 69 enum QTextHTMLElements { 70 Html_unknown = -1, 71 Html_qt = 0, 72 Html_body, 73 74 Html_a, 75 Html_em, 76 Html_i, 77 Html_big, 78 Html_small, 79 Html_strong, 80 Html_b, 81 Html_cite, 82 Html_address, 83 Html_var, 84 Html_dfn, 85 86 Html_h1, 87 Html_h2, 88 Html_h3, 89 Html_h4, 90 Html_h5, 91 Html_h6, 92 Html_p, 93 Html_center, 94 95 Html_font, 96 97 Html_ul, 98 Html_ol, 99 Html_li, 100 101 Html_code, 102 Html_tt, 103 Html_kbd, 104 Html_samp, 105 106 Html_img, 107 Html_br, 108 Html_hr, 109 110 Html_sub, 111 Html_sup, 112 113 Html_pre, 114 Html_blockquote, 115 Html_head, 116 Html_div, 117 Html_span, 118 Html_dl, 119 Html_dt, 120 Html_dd, 121 Html_u, 122 Html_s, 123 Html_nobr, 124 125 // tables 126 Html_table, 127 Html_tr, 128 Html_td, 129 Html_th, 130 Html_thead, 131 Html_tbody, 132 Html_tfoot, 133 Html_caption, 134 135 // misc... 136 Html_html, 137 Html_style, 138 Html_title, 139 Html_meta, 140 Html_link, 141 Html_script, 142 143 Html_NumElements 144 }; 145 146 struct QTextHtmlElement 147 { 148 const char name[11]; 149 QTextHTMLElements id; 150 enum DisplayMode { DisplayBlock, DisplayInline, DisplayTable, DisplayNone } displayMode; 151 }; 152 153 class QTextHtmlParser; 154 155 struct QTextHtmlParserNode { 156 enum WhiteSpaceMode { 157 WhiteSpaceNormal, 158 WhiteSpacePre, 159 WhiteSpaceNoWrap, 160 WhiteSpacePreWrap, 161 WhiteSpacePreLine, 162 WhiteSpaceModeUndefined = -1 163 }; 164 165 QTextHtmlParserNode(); 166 QString tag; 167 QString text; 168 QStringList attributes; 169 int parent; 170 QVector<int> children; 171 QTextHTMLElements id; 172 QTextCharFormat charFormat; 173 QTextBlockFormat blockFormat; 174 uint cssFloat : 2; 175 uint hasOwnListStyle : 1; 176 uint hasOwnLineHeightType : 1; 177 uint hasLineHeightMultiplier : 1; 178 uint hasCssListIndent : 1; 179 uint isEmptyParagraph : 1; 180 uint isTextFrame : 1; 181 uint isRootFrame : 1; 182 uint displayMode : 3; // QTextHtmlElement::DisplayMode 183 uint hasHref : 1; 184 QTextListFormat::Style listStyle; 185 QString textListNumberPrefix; 186 QString textListNumberSuffix; 187 QString imageName; 188 QString imageAlt; 189 qreal imageWidth; 190 qreal imageHeight; 191 QTextLength width; 192 QTextLength height; 193 qreal tableBorder; 194 int tableCellRowSpan; 195 int tableCellColSpan; 196 qreal tableCellSpacing; 197 qreal tableCellPadding; 198 qreal tableCellBorder[4]; 199 QBrush tableCellBorderBrush[4]; 200 QTextFrameFormat::BorderStyle tableCellBorderStyle[4]; 201 QBrush borderBrush; 202 QTextFrameFormat::BorderStyle borderStyle; 203 bool borderCollapse; 204 int userState; 205 206 int cssListIndent; 207 208 WhiteSpaceMode wsm; 209 isListStartQTextHtmlParserNode210 inline bool isListStart() const 211 { return id == Html_ol || id == Html_ul; } isTableCellQTextHtmlParserNode212 inline bool isTableCell() const 213 { return id == Html_td || id == Html_th; } isBlockQTextHtmlParserNode214 inline bool isBlock() const 215 { return displayMode == QTextHtmlElement::DisplayBlock; } 216 isNotSelfNestingQTextHtmlParserNode217 inline bool isNotSelfNesting() const 218 { return id == Html_p || id == Html_li; } 219 allowedInContextQTextHtmlParserNode220 inline bool allowedInContext(int parentId) const 221 { 222 switch (id) { 223 case Html_dd: 224 case Html_dt: return (parentId == Html_dl); 225 case Html_tr: return (parentId == Html_table 226 || parentId == Html_thead 227 || parentId == Html_tbody 228 || parentId == Html_tfoot 229 ); 230 case Html_th: 231 case Html_td: return (parentId == Html_tr); 232 case Html_thead: 233 case Html_tbody: 234 case Html_tfoot: return (parentId == Html_table); 235 case Html_caption: return (parentId == Html_table); 236 case Html_body: return parentId != Html_head; 237 default: break; 238 } 239 return true; 240 } 241 mayNotHaveChildrenQTextHtmlParserNode242 inline bool mayNotHaveChildren() const 243 { return id == Html_img || id == Html_hr || id == Html_br || id == Html_meta; } 244 245 void initializeProperties(const QTextHtmlParserNode *parent, const QTextHtmlParser *parser); 246 uncollapsedMarginQTextHtmlParserNode247 inline int uncollapsedMargin(int mar) const { return margin[mar]; } 248 249 bool isNestedList(const QTextHtmlParser *parser) const; 250 251 void parseStyleAttribute(const QString &value, const QTextDocument *resourceProvider); 252 253 #if QT_CONFIG(cssparser) 254 void applyCssDeclarations(const QVector<QCss::Declaration> &declarations, const QTextDocument *resourceProvider); 255 256 void setListStyle(const QVector<QCss::Value> &cssValues); 257 #endif 258 259 void applyForegroundImage(qint64 cacheKey, const QTextDocument *resourceProvider); 260 void applyBackgroundImage(const QString &url, const QTextDocument *resourceProvider); 261 262 bool hasOnlyWhitespace() const; 263 264 int margin[4]; 265 int padding[4]; 266 267 friend class QTextHtmlParser; 268 }; 269 Q_DECLARE_TYPEINFO(QTextHtmlParserNode, Q_MOVABLE_TYPE); 270 271 272 class QTextHtmlParser 273 { 274 public: 275 enum Margin { 276 MarginTop, 277 MarginRight, 278 MarginBottom, 279 MarginLeft 280 }; 281 at(int i)282 inline const QTextHtmlParserNode &at(int i) const { return nodes.at(i); } 283 inline QTextHtmlParserNode &operator[](int i) { return nodes[i]; } count()284 inline int count() const { return nodes.count(); } last()285 inline int last() const { return nodes.count()-1; } 286 int depth(int i) const; 287 int topMargin(int i) const; 288 int bottomMargin(int i) const; leftMargin(int i)289 inline int leftMargin(int i) const { return margin(i, MarginLeft); } rightMargin(int i)290 inline int rightMargin(int i) const { return margin(i, MarginRight); } 291 topPadding(int i)292 inline int topPadding(int i) const { return at(i).padding[MarginTop]; } bottomPadding(int i)293 inline int bottomPadding(int i) const { return at(i).padding[MarginBottom]; } leftPadding(int i)294 inline int leftPadding(int i) const { return at(i).padding[MarginLeft]; } rightPadding(int i)295 inline int rightPadding(int i) const { return at(i).padding[MarginRight]; } 296 tableCellBorder(int i,int edge)297 inline qreal tableCellBorder(int i, int edge) const { return at(i).tableCellBorder[edge]; } tableCellBorderStyle(int i,int edge)298 inline QTextFrameFormat::BorderStyle tableCellBorderStyle(int i, int edge) const { return at(i).tableCellBorderStyle[edge]; } tableCellBorderBrush(int i,int edge)299 inline QBrush tableCellBorderBrush(int i, int edge) const { return at(i).tableCellBorderBrush[edge]; } 300 301 void dumpHtml(); 302 303 void parse(const QString &text, const QTextDocument *resourceProvider); 304 305 static int lookupElement(const QString &element); 306 protected: 307 QTextHtmlParserNode *newNode(int parent); 308 QVector<QTextHtmlParserNode> nodes; 309 QString txt; 310 int pos, len; 311 312 bool textEditMode; 313 314 void parse(); 315 void parseTag(); 316 void parseCloseTag(); 317 void parseExclamationTag(); 318 QString parseEntity(); 319 QString parseWord(); 320 QTextHtmlParserNode *resolveParent(); 321 void resolveNode(); 322 QStringList parseAttributes(); 323 void applyAttributes(const QStringList &attributes); 324 void eatSpace(); 325 inline bool hasPrefix(QChar c, int lookahead = 0) const 326 {return pos + lookahead < len && txt.at(pos) == c; } 327 int margin(int i, int mar) const; 328 329 bool nodeIsChildOf(int i, QTextHTMLElements id) const; 330 331 332 #if QT_CONFIG(cssparser) 333 QVector<QCss::Declaration> declarationsForNode(int node) const; 334 void resolveStyleSheetImports(const QCss::StyleSheet &sheet); 335 void importStyleSheet(const QString &href); 336 337 struct ExternalStyleSheet 338 { ExternalStyleSheetExternalStyleSheet339 inline ExternalStyleSheet() {} ExternalStyleSheetExternalStyleSheet340 inline ExternalStyleSheet(const QString &_url, const QCss::StyleSheet &_sheet) 341 : url(_url), sheet(_sheet) {} 342 QString url; 343 QCss::StyleSheet sheet; 344 }; 345 friend class QTypeInfo<ExternalStyleSheet>; 346 QVector<ExternalStyleSheet> externalStyleSheets; 347 QVector<QCss::StyleSheet> inlineStyleSheets; 348 #endif 349 350 const QTextDocument *resourceProvider; 351 }; 352 #if QT_CONFIG(cssparser) 353 Q_DECLARE_TYPEINFO(QTextHtmlParser::ExternalStyleSheet, Q_MOVABLE_TYPE); 354 #endif 355 356 QT_END_NAMESPACE 357 358 #endif // QT_NO_TEXTHTMLPARSER 359 360 #endif // QTEXTHTMLPARSER_P_H 361