📄 qsvghandler.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtSVG module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qsvghandler_p.h"#include "qsvgtinydocument_p.h"#include "qsvgstructure_p.h"#include "qsvggraphics_p.h"#include "qsvgnode_p.h"#include "qsvgfont_p.h"#include "qapplication.h"#include "qwidget.h"#include "qpen.h"#include "qpainterpath.h"#include "qbrush.h"#include "qcolor.h"#include "qtextformat.h"#include "qvector.h"#include "qfileinfo.h"#include "qfile.h"#include "qdebug.h"#include "private/qmath_p.h"#include <math.h>double qstrtod(const char *s00, char const **se, bool *ok);static bool parsePathDataFast(const QStringRef &data, QPainterPath &path);static QPen defaultPen(Qt::black, 1, Qt::NoPen, Qt::FlatCap, Qt::SvgMiterJoin);static QString xmlSimplify(const QString &str){ QString dummy = str; dummy.remove(QLatin1Char('\n')); if (dummy.trimmed().isEmpty()) return QString(); QString temp; QString::const_iterator itr = dummy.constBegin(); bool wasSpace = false; for (;itr != dummy.constEnd(); ++itr) { if ((*itr).isSpace()) { if (wasSpace || !(*itr).isPrint()) { continue; } temp += *itr; wasSpace = true; } else { temp += *itr; wasSpace = false; } } return temp;}struct QSvgAttributes{ QSvgAttributes(const QXmlStreamAttributes &xmlAttributes, QSvgHandler *handler); QStringRef value(const QLatin1String &name) const; QStringRef value(const QString &namespaceUri, const QLatin1String &name) const; QXmlStreamAttributes m_xmlAttributes; QVector<QSvgCssAttribute> m_cssAttributes;};QSvgAttributes::QSvgAttributes(const QXmlStreamAttributes &xmlAttributes, QSvgHandler *handler) : m_xmlAttributes(xmlAttributes){ QStringRef style = xmlAttributes.value(QLatin1String("style")); if (!style.isEmpty()) handler->parseCSStoXMLAttrs(style.toString(), &m_cssAttributes);}QStringRef QSvgAttributes::value(const QLatin1String &name) const{ QStringRef v = m_xmlAttributes.value(name); if (v.isEmpty()) { for (int i = 0; i < m_cssAttributes.count(); ++i) { if (m_cssAttributes.at(i).name == name) { v = m_cssAttributes.at(i).value; break; } } } return v;}QStringRef QSvgAttributes::value(const QString &namespaceUri, const QLatin1String &name) const{ QStringRef v = m_xmlAttributes.value(namespaceUri, name); if (v.isEmpty()) { for (int i = 0; i < m_cssAttributes.count(); ++i) { if (m_cssAttributes.at(i).name == name) { v = m_cssAttributes.at(i).value; break; } } } return v;}static inline QString someId(const QXmlStreamAttributes &attributes){ QString id = attributes.value(QLatin1String("id")).toString(); if (id.isEmpty()) id = attributes.value(QLatin1String("xml:id")).toString(); return id;}static inline QString someId(const QSvgAttributes &attributes){ return someId(attributes.m_xmlAttributes); }static const char * QSvgStyleSelector_nodeString[] = { "svg", "g", "defs", "switch", "animation", "arc", "circle", "ellipse", "image", "line", "path", "polygon", "polyline", "rect", "text", "textarea", "use", "video"};class QSvgStyleSelector : public QCss::StyleSelector{public: virtual ~QSvgStyleSelector() { } inline QString nodeToName(QSvgNode *node) const { return QLatin1String(QSvgStyleSelector_nodeString[node->type()]); } inline QSvgNode *svgNode(NodePtr node) const { return (QSvgNode*)node.ptr; } inline QSvgStructureNode *nodeToStructure(QSvgNode *n) const { if (n && (n->type() == QSvgNode::DOC || n->type() == QSvgNode::G || n->type() == QSvgNode::DEFS || n->type() == QSvgNode::SWITCH)) { return (QSvgStructureNode*)n; } return 0; } inline QSvgStructureNode *svgStructure(NodePtr node) const { QSvgNode *n = svgNode(node); QSvgStructureNode *st = nodeToStructure(n); return st; } virtual bool nodeNameEquals(NodePtr node, const QString& nodeName) const { QSvgNode *n = svgNode(node); if (!n) return false; QString name = nodeToName(n); return QString::compare(name, nodeName, Qt::CaseInsensitive) == 0; } virtual QString attribute(NodePtr node, const QString &name) const { QSvgNode *n = svgNode(node); if ((!n->nodeId().isEmpty() && (name == QLatin1String("id") || name == QLatin1String("xml:id")))) return n->nodeId(); if (!n->xmlClass().isEmpty() && name == QLatin1String("class")) return n->xmlClass(); return QString(); } virtual bool hasAttribute(NodePtr node, const QString &name) const { QSvgNode *n = svgNode(node); if ((!n->nodeId().isEmpty() && (name == QLatin1String("id") || name == QLatin1String("xml:id")))) return true; if (!n->xmlClass().isEmpty() && name == QLatin1String("class")) return true; return false; } virtual bool hasAttributes(NodePtr node) const { QSvgNode *n = svgNode(node); return (n && (!n->nodeId().isEmpty() || !n->xmlClass().isEmpty())); } virtual QStringList nodeIds(NodePtr node) const { QSvgNode *n = svgNode(node); QString nid; if (n) nid = n->nodeId(); QStringList lst; lst.append(nid); return lst; } virtual bool isNullNode(NodePtr node) const { return !node.ptr; } virtual NodePtr parentNode(NodePtr node) const { QSvgNode *n = svgNode(node); NodePtr newNode; newNode.ptr = 0; newNode.id = 0; if (n) { QSvgNode *svgParent = n->parent(); if (svgParent) { newNode.ptr = svgParent; } } return newNode; } virtual NodePtr previousSiblingNode(NodePtr node) const { NodePtr newNode; newNode.ptr = 0; newNode.id = 0; QSvgNode *n = svgNode(node); if (!n) return newNode; QSvgStructureNode *svgParent = nodeToStructure(n->parent()); if (svgParent) { newNode.ptr = svgParent->previousSiblingNode(n); } return newNode; } virtual NodePtr duplicateNode(NodePtr node) const { NodePtr n; n.ptr = node.ptr; n.id = node.id; return n; } virtual void freeNode(NodePtr node) const { Q_UNUSED(node); }};static qreal toDouble(const QChar *&str){ const int maxLen = 255;//technically doubles can go til 308+ but whatever char temp[maxLen+1]; int pos = 0; if (*str == QLatin1Char('-')) { temp[pos++] = '-'; ++str; } else if (*str == QLatin1Char('+')) { ++str; } while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) { temp[pos++] = str->toLatin1(); ++str; } if (*str == QLatin1Char('.') && pos < maxLen) { temp[pos++] = '.'; ++str; } while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) { temp[pos++] = str->toLatin1(); ++str; } bool exponent = false; if (*str == QLatin1Char('e') && pos < maxLen) { exponent = true; temp[pos++] = 'e'; ++str; if ((*str == QLatin1Char('-') || *str == QLatin1Char('+')) && pos < maxLen) { temp[pos++] = str->toLatin1(); ++str; } while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) { temp[pos++] = str->toLatin1(); ++str; } } temp[pos] = '\0'; qreal val; if (!exponent && pos < 10) { int ival = 0; const char *t = temp; bool neg = false; if(*t == '-') { neg = true; ++t; } while(*t && *t != '.') { ival *= 10; ival += (*t) - '0'; ++t; } if(*t == '.') { ++t; int div = 1; while(*t) { ival *= 10; ival += (*t) - '0'; div *= 10; ++t; } val = ((qreal)ival)/((qreal)div); } else { val = ival; } if (neg) val = -val; } else {#ifdef Q_WS_QWS if(sizeof(qreal) == sizeof(float)) val = strtof(temp, 0); else#endif { bool ok = false; val = qstrtod(temp, 0, &ok); } } return val;}static qreal toDouble(const QString &str){ const QChar *c = str.constData();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -