📄 q3paintengine_svg.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the Qt3Support 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://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** 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 <private/qpainter_p.h>#include <private/qpaintengine_p.h>#include "qfile.h"#include "qimage.h"#include "qlist.h"#include "qmap.h"#include "q3paintengine_svg_p.h"#include "qpainter.h"#include "qpixmap.h"#include "qregexp.h"#include "qtextstream.h"#include <math.h>static const double deg2rad = 0.017453292519943295769; // pi/180static const char piData[] = "version=\"1.0\" standalone=\"no\"";static const char publicId[] = "-//W3C//DTD SVG 20001102//EN";static const char systemId[] = "http://www.w3.org/TR/2000/CR-SVG-20001102/DTD/svg-20001102.dtd";static QString qt_svg_compose_path(const QPainterPath &path);struct QImgElement { QDomElement element; QImage image; Q_DUMMY_COMPARISON_OPERATOR(QImgElement)};struct QPixElement { QDomElement element; QPixmap pixmap; Q_DUMMY_COMPARISON_OPERATOR(QPixElement)};struct Q3SVGPaintEngineState { double textx, texty; // current text position int textalign; // text alignment Q_DUMMY_COMPARISON_OPERATOR(Q3SVGPaintEngineState)};typedef QList<QImgElement> ImageList;typedef QList<QPixElement> PixmapList;typedef QList<Q3SVGPaintEngineState> StateList;enum ElementType { InvalidElement = 0, AnchorElement, CircleElement, ClipElement, CommentElement, DescElement, EllipseElement, GroupElement, ImageElement, LineElement, PolylineElement, PolygonElement, PathElement, RectElement, SvgElement, TextElement, TitleElement, TSpanElement};typedef QMap<QString,ElementType> QSvgTypeMap;static QSvgTypeMap *qSvgTypeMap=0; // element typesstatic QMap<QString,QString> *qSvgColMap=0; // recognized color keyword namesclass Q3SVGPaintEnginePrivate : public QPaintEnginePrivate{ Q_DECLARE_PUBLIC(Q3SVGPaintEngine)public: Q3SVGPaintEnginePrivate() : dirtyTransform(false), dirtyStyle(false), currentClip(0), dev(0), wwidth(0), wheight(0) {} void appendChild(QDomElement &e, QPicturePrivate::PaintCommand c); void applyStyle(QDomElement *e, QPicturePrivate::PaintCommand c) const; void applyTransform(QDomElement *e) const; double parseLen(const QString &str, bool *ok=0, bool horiz=true) const; int lenToInt(const QDomNamedNodeMap &map, const QString &attr, int def = 0) const; double lenToDouble(const QDomNamedNodeMap &map, const QString &attr, int def = 0) const; bool play(const QDomNode &node, QPainter *p); void setTransform(const QString &tr, QPainter *p); void restoreAttributes(QPainter *p); void saveAttributes(QPainter *p); void setStyle(const QString &s, QPainter *p); void setStyleProperty(const QString &prop, const QString &val, QPen *pen, QFont *font, int *talign, QPainter *p); void drawPath(const QString &data, QPainter *p); QColor parseColor(const QString &col); void init() { QDomImplementation domImpl; QDomDocumentType docType = domImpl.createDocumentType("svg", publicId, systemId); doc = domImpl.createDocument("http://www.w3.org/2000/svg", "svg", docType); doc.insertBefore(doc.createProcessingInstruction("xml", piData), doc.firstChild()); current = doc.documentElement(); images.clear(); pixmaps.clear(); doc.documentElement().setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink"); } bool dirtyTransform; bool dirtyStyle; QRect brect; // bounding rectangle QDomDocument doc; // document tree QDomNode current; ImageList images; // old private PixmapList pixmaps; StateList stack; int currentClip;// QPoint curPt; Q3SVGPaintEngineState *curr;// QPainter *pt; // only used by recursive play() et al QPen cpen; QBrush cbrush; QFont cfont; QMatrix worldMatrix; const QPaintDevice *dev; int wwidth; int wheight;};Q3SVGPaintEngine::Q3SVGPaintEngine() : QPaintEngine(*(new Q3SVGPaintEnginePrivate), AllFeatures){ Q_D(Q3SVGPaintEngine); d->init();}Q3SVGPaintEngine::Q3SVGPaintEngine(Q3SVGPaintEnginePrivate &dptr) : QPaintEngine(dptr, AllFeatures){ Q_D(Q3SVGPaintEngine); d->init();}Q3SVGPaintEngine::~Q3SVGPaintEngine(){ delete qSvgTypeMap; qSvgTypeMap = 0; // static delete qSvgColMap; qSvgColMap = 0;}bool Q3SVGPaintEngine::begin(QPaintDevice *pdev){ Q_D(Q3SVGPaintEngine); d->dirtyTransform = d->dirtyStyle = false; d->dev = pdev; setActive(true); return true;}bool Q3SVGPaintEngine::end(){ Q_D(Q3SVGPaintEngine); d->dev = 0; setActive(false); return true;}void Q3SVGPaintEngine::updateState(const QPaintEngineState &state){ QPaintEngine::DirtyFlags flags = state.state(); if (flags & DirtyPen) updatePen(state.pen()); if ((flags & DirtyBrush) || (flags & DirtyBrushOrigin)) updateBrush(state.brush(), state.brushOrigin()); if (flags & DirtyBackground) updateBackground(state.backgroundMode(), state.backgroundBrush()); if (flags & DirtyFont) updateFont(state.font()); if (flags & DirtyTransform) updateMatrix(state.matrix()); if (flags & DirtyClipRegion) updateClipRegion(state.clipRegion(), state.clipOperation()); if (flags & DirtyClipPath) updateClipPath(state.clipPath(), state.clipOperation());}void Q3SVGPaintEngine::updatePen(const QPen &pen){ Q_D(Q3SVGPaintEngine); d->cpen = pen; d->dirtyStyle = true;}void Q3SVGPaintEngine::updateBrush(const QBrush &brush, const QPointF &){ Q_D(Q3SVGPaintEngine); d->cbrush = brush; d->dirtyStyle = true;}void Q3SVGPaintEngine::updateFont(const QFont &font){ Q_D(Q3SVGPaintEngine); d->cfont = font; d->dirtyStyle = true;}void Q3SVGPaintEngine::updateBackground(Qt::BGMode, const QBrush &){ Q_D(Q3SVGPaintEngine); d->dirtyStyle = true;}void Q3SVGPaintEngine::updateMatrix(const QMatrix &matrix){ Q_D(Q3SVGPaintEngine); d->dirtyTransform = true; d->worldMatrix = matrix;// d->wwidth = ps->ww;// d->wheight = ps->wh;}void Q3SVGPaintEngine::updateClipPath(const QPainterPath &path, Qt::ClipOperation op){ Q_D(Q3SVGPaintEngine); if (op == Qt::NoClip) return; QDomElement e; d->currentClip++; e = d->doc.createElement("clipPath"); e.setAttribute("id", QString("clip%1").arg(d->currentClip)); QDomElement path_element = d->doc.createElement("path"); path_element.setAttribute("d", qt_svg_compose_path(path)); e.appendChild(path_element); d->appendChild(e, QPicturePrivate::PdcSetClipPath);}void Q3SVGPaintEngine::updateClipRegion(const QRegion &clipRegion, Qt::ClipOperation op){ QPainterPath clipPath; clipPath.addRegion(clipRegion); updateClipPath(clipPath, op);}void Q3SVGPaintEngine::updateRenderHints(QPainter::RenderHints){}void Q3SVGPaintEngine::drawRect(const QRectF &r){ Q_D(Q3SVGPaintEngine); QDomElement e; e = d->doc.createElement("rect"); e.setAttribute("x", r.x()); e.setAttribute("y", r.y()); e.setAttribute("width", r.width()); e.setAttribute("height", r.height()); d->appendChild(e, QPicturePrivate::PdcDrawRect);}void Q3SVGPaintEngine::drawPoint(const QPointF &p){ QLineF l(p, p); drawLines(&l, 1);}void Q3SVGPaintEngine::drawPoints(const QPointF *points, int pointCount){ for (int i = 0; i < pointCount; ++i) { QLineF l(points[i], points[i]); drawLines(&l, 1); }}void Q3SVGPaintEngine::drawEllipse(const QRect &r){ Q_D(Q3SVGPaintEngine); QDomElement e; if (r.width() == r.height()) { e = d->doc.createElement("circle"); double cx = r.x() + (r.width() / 2.0); double cy = r.y() + (r.height() / 2.0); e.setAttribute("cx", cx); e.setAttribute("cy", cy); e.setAttribute("r", cx - r.x()); } else { e = d->doc.createElement("ellipse"); double cx = r.x() + (r.width() / 2.0); double cy = r.y() + (r.height() / 2.0); e.setAttribute("cx", cx); e.setAttribute("cy", cy); e.setAttribute("rx", cx - r.x()); e.setAttribute("ry", cy - r.y()); } d->appendChild(e, QPicturePrivate::PdcDrawEllipse);}void Q3SVGPaintEngine::drawLine(const QLineF &line){ drawLines(&line, 1);}void Q3SVGPaintEngine::drawLines(const QLineF *lines, int lineCount){ Q_D(Q3SVGPaintEngine); QDomElement e; for (int i = 0; i < lineCount; ++i) { e = d->doc.createElement("line"); e.setAttribute("x1", lines[i].x1()); e.setAttribute("y1", lines[i].y1()); e.setAttribute("x2", lines[i].x2()); e.setAttribute("y2", lines[i].y2()); d->appendChild(e, QPicturePrivate::PdcDrawLineSegments); }}void Q3SVGPaintEngine::drawPath(const QPainterPath &path){ Q_D(Q3SVGPaintEngine); QDomElement e = d->doc.createElement("path"); e.setAttribute("d", qt_svg_compose_path(path)); d->appendChild(e, QPicturePrivate::PdcDrawPath);}void Q3SVGPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode){ Q_D(Q3SVGPaintEngine); QString str; if (mode == PolylineMode) { QDomElement e = d->doc.createElement("polyline"); for (int i = 0; i < pointCount; ++i) { QString tmp; tmp.sprintf("%f %f ", points[i].x(), points[i].y()); str += tmp; } e.setAttribute("points", str.trimmed()); d->appendChild(e, QPicturePrivate::PdcDrawPolyline); } else { QDomElement e = d->doc.createElement("polygon"); for (int i = 0; i < pointCount; ++i) { QString tmp; tmp.sprintf("%f %f ", points[i].x(), points[i].y()); str += tmp; } e.setAttribute("points", str.trimmed()); d->appendChild(e, QPicturePrivate::PdcDrawPolygon); }}void Q3SVGPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode){ QPolygonF poly; for (int i = 0; i < pointCount; ++i) poly << points[i]; drawPolygon(poly.constData(), pointCount, mode);}void Q3SVGPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF & /* sr */){ Q_D(Q3SVGPaintEngine);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -