/src/svg/qsvgnode.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 345 lines · 257 code · 43 blank · 45 comment · 34 complexity · 6dd075b28afe410f2dd41f4a56818320 MD5 · raw file

  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  4. ** All rights reserved.
  5. ** Contact: Nokia Corporation (qt-info@nokia.com)
  6. **
  7. ** This file is part of the QtSvg module of the Qt Toolkit.
  8. **
  9. ** $QT_BEGIN_LICENSE:LGPL$
  10. ** GNU Lesser General Public License Usage
  11. ** This file may be used under the terms of the GNU Lesser General Public
  12. ** License version 2.1 as published by the Free Software Foundation and
  13. ** appearing in the file LICENSE.LGPL included in the packaging of this
  14. ** file. Please review the following information to ensure the GNU Lesser
  15. ** General Public License version 2.1 requirements will be met:
  16. ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  17. **
  18. ** In addition, as a special exception, Nokia gives you certain additional
  19. ** rights. These rights are described in the Nokia Qt LGPL Exception
  20. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  21. **
  22. ** GNU General Public License Usage
  23. ** Alternatively, this file may be used under the terms of the GNU General
  24. ** Public License version 3.0 as published by the Free Software Foundation
  25. ** and appearing in the file LICENSE.GPL included in the packaging of this
  26. ** file. Please review the following information to ensure the GNU General
  27. ** Public License version 3.0 requirements will be met:
  28. ** http://www.gnu.org/copyleft/gpl.html.
  29. **
  30. ** Other Usage
  31. ** Alternatively, this file may be used in accordance with the terms and
  32. ** conditions contained in a signed written agreement between you and Nokia.
  33. **
  34. **
  35. **
  36. **
  37. **
  38. ** $QT_END_LICENSE$
  39. **
  40. ****************************************************************************/
  41. #include "qsvgnode_p.h"
  42. #include "qsvgtinydocument_p.h"
  43. #ifndef QT_NO_SVG
  44. #include "qdebug.h"
  45. #include "qstack.h"
  46. QT_BEGIN_NAMESPACE
  47. QSvgNode::QSvgNode(QSvgNode *parent)
  48. : m_parent(parent),
  49. m_visible(true),
  50. m_displayMode(BlockMode)
  51. {
  52. }
  53. QSvgNode::~QSvgNode()
  54. {
  55. }
  56. void QSvgNode::appendStyleProperty(QSvgStyleProperty *prop, const QString &id)
  57. {
  58. //qDebug()<<"appending "<<prop->type()<< " ("<< id <<") "<<"to "<<this<<this->type();
  59. QSvgTinyDocument *doc;
  60. switch (prop->type()) {
  61. case QSvgStyleProperty::QUALITY:
  62. m_style.quality = static_cast<QSvgQualityStyle*>(prop);
  63. break;
  64. case QSvgStyleProperty::FILL:
  65. m_style.fill = static_cast<QSvgFillStyle*>(prop);
  66. break;
  67. case QSvgStyleProperty::VIEWPORT_FILL:
  68. m_style.viewportFill = static_cast<QSvgViewportFillStyle*>(prop);
  69. break;
  70. case QSvgStyleProperty::FONT:
  71. m_style.font = static_cast<QSvgFontStyle*>(prop);
  72. break;
  73. case QSvgStyleProperty::STROKE:
  74. m_style.stroke = static_cast<QSvgStrokeStyle*>(prop);
  75. break;
  76. case QSvgStyleProperty::SOLID_COLOR:
  77. m_style.solidColor = static_cast<QSvgSolidColorStyle*>(prop);
  78. doc = document();
  79. if (doc && !id.isEmpty())
  80. doc->addNamedStyle(id, m_style.solidColor);
  81. break;
  82. case QSvgStyleProperty::GRADIENT:
  83. m_style.gradient = static_cast<QSvgGradientStyle*>(prop);
  84. doc = document();
  85. if (doc && !id.isEmpty())
  86. doc->addNamedStyle(id, m_style.gradient);
  87. break;
  88. case QSvgStyleProperty::TRANSFORM:
  89. m_style.transform = static_cast<QSvgTransformStyle*>(prop);
  90. break;
  91. case QSvgStyleProperty::ANIMATE_COLOR:
  92. m_style.animateColor = static_cast<QSvgAnimateColor*>(prop);
  93. break;
  94. case QSvgStyleProperty::ANIMATE_TRANSFORM:
  95. m_style.animateTransforms.append(
  96. static_cast<QSvgAnimateTransform*>(prop));
  97. break;
  98. case QSvgStyleProperty::OPACITY:
  99. m_style.opacity = static_cast<QSvgOpacityStyle*>(prop);
  100. break;
  101. case QSvgStyleProperty::COMP_OP:
  102. m_style.compop = static_cast<QSvgCompOpStyle*>(prop);
  103. break;
  104. default:
  105. qDebug("QSvgNode: Trying to append unknown property!");
  106. break;
  107. }
  108. }
  109. void QSvgNode::applyStyle(QPainter *p, QSvgExtraStates &states) const
  110. {
  111. m_style.apply(p, this, states);
  112. }
  113. void QSvgNode::revertStyle(QPainter *p, QSvgExtraStates &states) const
  114. {
  115. m_style.revert(p, states);
  116. }
  117. QSvgStyleProperty * QSvgNode::styleProperty(QSvgStyleProperty::Type type) const
  118. {
  119. const QSvgNode *node = this;
  120. while (node) {
  121. switch (type) {
  122. case QSvgStyleProperty::QUALITY:
  123. if (node->m_style.quality)
  124. return node->m_style.quality;
  125. break;
  126. case QSvgStyleProperty::FILL:
  127. if (node->m_style.fill)
  128. return node->m_style.fill;
  129. break;
  130. case QSvgStyleProperty::VIEWPORT_FILL:
  131. if (m_style.viewportFill)
  132. return node->m_style.viewportFill;
  133. break;
  134. case QSvgStyleProperty::FONT:
  135. if (node->m_style.font)
  136. return node->m_style.font;
  137. break;
  138. case QSvgStyleProperty::STROKE:
  139. if (node->m_style.stroke)
  140. return node->m_style.stroke;
  141. break;
  142. case QSvgStyleProperty::SOLID_COLOR:
  143. if (node->m_style.solidColor)
  144. return node->m_style.solidColor;
  145. break;
  146. case QSvgStyleProperty::GRADIENT:
  147. if (node->m_style.gradient)
  148. return node->m_style.gradient;
  149. break;
  150. case QSvgStyleProperty::TRANSFORM:
  151. if (node->m_style.transform)
  152. return node->m_style.transform;
  153. break;
  154. case QSvgStyleProperty::ANIMATE_COLOR:
  155. if (node->m_style.animateColor)
  156. return node->m_style.animateColor;
  157. break;
  158. case QSvgStyleProperty::ANIMATE_TRANSFORM:
  159. if (!node->m_style.animateTransforms.isEmpty())
  160. return node->m_style.animateTransforms.first();
  161. break;
  162. case QSvgStyleProperty::OPACITY:
  163. if (node->m_style.opacity)
  164. return node->m_style.opacity;
  165. break;
  166. case QSvgStyleProperty::COMP_OP:
  167. if (node->m_style.compop)
  168. return node->m_style.compop;
  169. break;
  170. default:
  171. break;
  172. }
  173. node = node->parent();
  174. }
  175. return 0;
  176. }
  177. QSvgFillStyleProperty * QSvgNode::styleProperty(const QString &id) const
  178. {
  179. QString rid = id;
  180. if (rid.startsWith(QLatin1Char('#')))
  181. rid.remove(0, 1);
  182. QSvgTinyDocument *doc = document();
  183. return doc ? doc->namedStyle(rid) : 0;
  184. }
  185. QRectF QSvgNode::bounds(QPainter *, QSvgExtraStates &) const
  186. {
  187. return QRectF(0, 0, 0, 0);
  188. }
  189. QRectF QSvgNode::transformedBounds() const
  190. {
  191. if (!m_cachedBounds.isEmpty())
  192. return m_cachedBounds;
  193. QImage dummy(1, 1, QImage::Format_RGB32);
  194. QPainter p(&dummy);
  195. QSvgExtraStates states;
  196. QPen pen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
  197. pen.setMiterLimit(4);
  198. p.setPen(pen);
  199. QStack<QSvgNode*> parentApplyStack;
  200. QSvgNode *parent = m_parent;
  201. while (parent) {
  202. parentApplyStack.push(parent);
  203. parent = parent->parent();
  204. }
  205. for (int i = parentApplyStack.size() - 1; i >= 0; --i)
  206. parentApplyStack[i]->applyStyle(&p, states);
  207. p.setWorldTransform(QTransform());
  208. m_cachedBounds = transformedBounds(&p, states);
  209. return m_cachedBounds;
  210. }
  211. QSvgTinyDocument * QSvgNode::document() const
  212. {
  213. QSvgTinyDocument *doc = 0;
  214. QSvgNode *node = const_cast<QSvgNode*>(this);
  215. while (node && node->type() != QSvgNode::DOC) {
  216. node = node->parent();
  217. }
  218. doc = static_cast<QSvgTinyDocument*>(node);
  219. return doc;
  220. }
  221. void QSvgNode::setRequiredFeatures(const QStringList &lst)
  222. {
  223. m_requiredFeatures = lst;
  224. }
  225. const QStringList & QSvgNode::requiredFeatures() const
  226. {
  227. return m_requiredFeatures;
  228. }
  229. void QSvgNode::setRequiredExtensions(const QStringList &lst)
  230. {
  231. m_requiredExtensions = lst;
  232. }
  233. const QStringList & QSvgNode::requiredExtensions() const
  234. {
  235. return m_requiredExtensions;
  236. }
  237. void QSvgNode::setRequiredLanguages(const QStringList &lst)
  238. {
  239. m_requiredLanguages = lst;
  240. }
  241. const QStringList & QSvgNode::requiredLanguages() const
  242. {
  243. return m_requiredLanguages;
  244. }
  245. void QSvgNode::setRequiredFormats(const QStringList &lst)
  246. {
  247. m_requiredFormats = lst;
  248. }
  249. const QStringList & QSvgNode::requiredFormats() const
  250. {
  251. return m_requiredFormats;
  252. }
  253. void QSvgNode::setRequiredFonts(const QStringList &lst)
  254. {
  255. m_requiredFonts = lst;
  256. }
  257. const QStringList & QSvgNode::requiredFonts() const
  258. {
  259. return m_requiredFonts;
  260. }
  261. void QSvgNode::setVisible(bool visible)
  262. {
  263. //propagate visibility change of true to the parent
  264. //not propagating false is just a small performance
  265. //degradation since we'll iterate over children without
  266. //drawing any of them
  267. if (m_parent && visible && !m_parent->isVisible())
  268. m_parent->setVisible(true);
  269. m_visible = visible;
  270. }
  271. QRectF QSvgNode::transformedBounds(QPainter *p, QSvgExtraStates &states) const
  272. {
  273. applyStyle(p, states);
  274. QRectF rect = bounds(p, states);
  275. revertStyle(p, states);
  276. return rect;
  277. }
  278. void QSvgNode::setNodeId(const QString &i)
  279. {
  280. m_id = i;
  281. }
  282. void QSvgNode::setXmlClass(const QString &str)
  283. {
  284. m_class = str;
  285. }
  286. void QSvgNode::setDisplayMode(DisplayMode mode)
  287. {
  288. m_displayMode = mode;
  289. }
  290. QSvgNode::DisplayMode QSvgNode::displayMode() const
  291. {
  292. return m_displayMode;
  293. }
  294. qreal QSvgNode::strokeWidth(QPainter *p)
  295. {
  296. QPen pen = p->pen();
  297. if (pen.style() == Qt::NoPen || pen.brush().style() == Qt::NoBrush || pen.isCosmetic())
  298. return 0;
  299. return pen.widthF();
  300. }
  301. QT_END_NAMESPACE
  302. #endif // QT_NO_SVG